From ec169583ffc56cc7f1efb59448950ee11ca1e90c Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Fri, 16 Oct 2026 11:01:53 -0700 Subject: [PATCH] Add Workflow tab and run-progress API for workflow runs --- TODO.md | 3 - api/openapi.yaml | 91 +++++- docs/operations.md | 5 +- internal/agents/leadtools.go | 6 +- internal/agents/workflows.go | 145 +++++++++ internal/api/api.gen.go | 561 +++++++++++++++++++++++------------ internal/server/workflows.go | 9 + internal/store/workflow.go | 12 + web/dist/panes.js | 6 +- web/dist/panes.js.map | 2 +- web/dist/state.js | 2 +- web/dist/state.js.map | 2 +- web/dist/workflow.js | 182 ++++++++++++ web/dist/workflow.js.map | 1 + web/src/api.gen.ts | 94 +++++- web/src/panes.ts | 6 +- web/src/state.ts | 2 +- web/src/workflow.ts | 232 +++++++++++++++ web/style.css | 133 ++++++++- 19 files changed, 1285 insertions(+), 209 deletions(-) create mode 100644 web/dist/workflow.js create mode 100644 web/dist/workflow.js.map create mode 100644 web/src/workflow.ts diff --git a/TODO.md b/TODO.md index e247e5f..c7aed87 100644 --- a/TODO.md +++ b/TODO.md @@ -10,9 +10,6 @@ # M5 — Workflows -- Workflow tab - A read-only right-pane tab on tasks with a `workflow_run`, showing the frozen graph (lazy-loaded Mermaid) and a textual stage list linking to each stage's task attempts and their finish_stage output. Each stage shows waiting on named dependencies, running, idle but not finished, finished, discarded before finishing, or discarded by normal cleanup after finishing, and which fork attempt fed the next stage. Backed by a typed run-progress API carrying the frozen definition, attempts, completion and dependency provenance, updated from sibling-task events. - # M6 — Fan-out # M7 — Inbox triage diff --git a/api/openapi.yaml b/api/openapi.yaml index 186acae..3ea372e 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -277,6 +277,22 @@ paths: schema: { $ref: "#/components/schemas/TaskWorkflow" } "404": { $ref: "#/components/responses/Error" } + /api/tasks/{taskId}/workflow/run: + parameters: + - { name: taskId, in: path, required: true, schema: { type: string } } + get: + operationId: getWorkflowRun + description: > + The progress of the workflow run the task belongs to: the definition the task froze, and for each stage its + state and every task that attempted it, with the attempts whose outputs each one started from. + responses: + "200": + description: The run's progress. + content: + application/json: + schema: { $ref: "#/components/schemas/WorkflowRun" } + "404": { $ref: "#/components/responses/Error" } + /api/tasks/{taskId}/unmerged: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } @@ -1107,6 +1123,77 @@ components: name: { type: string } definition: { type: string, description: The WorkflowDefinition as YAML. } + WorkflowRun: + type: object + required: [name, run, title, brief, definition, finished, stages] + properties: + name: { type: string } + run: { type: string } + title: { type: string } + brief: { type: string } + definition: { $ref: "#/components/schemas/WorkflowDefinition" } + finished: { type: boolean, description: "Whether the final stage finished, which ends the run." } + stages: + type: array + description: In the definition's order. + items: { $ref: "#/components/schemas/WorkflowRunStage" } + + WorkflowRunStage: + type: object + required: [name, after, state, waiting_on, attempts] + properties: + name: { type: string } + after: + type: array + description: The stages it comes after, with the definition's defaults applied. + items: { type: string } + state: + type: string + enum: [waiting, running, idle, finished, merged, discarded, cleaned_up] + x-enum-varnames: [StageStateWaiting, StageStateRunning, StageStateIdle, StageStateFinished, StageStateMerged, StageStateDiscarded, StageStateCleanedUp] + description: > + waiting: no task yet. Otherwise the state of its latest finished attempt, or of its latest attempt when + none has finished. + waiting_on: + type: array + description: The after stages with no finished attempt yet. + items: { type: string } + attempts: + type: array + description: The tasks that ran the stage (the first, and forks of it), oldest first. + items: { $ref: "#/components/schemas/StageAttempt" } + + StageAttempt: + type: object + required: [task_id, title, state, discarding, inputs] + properties: + task_id: { type: string } + title: { type: string } + state: + type: string + enum: [running, idle, finished, merged, discarded, cleaned_up] + x-enum-varnames: [AttemptStateRunning, AttemptStateIdle, AttemptStateFinished, AttemptStateMerged, AttemptStateDiscarded, AttemptStateCleanedUp] + description: > + running: its agent is mid-turn. idle: active, and finish_stage hasn't taken. finished: active, its output + recorded. merged. discarded: discarded before finishing. cleaned_up: discarded after finishing, as byre + does to the run's other tasks when the final stage finishes. + discarding: { type: boolean, description: "Whether a Discard was started and the task isn't closed yet." } + forked_from: { type: string, description: "The task this attempt was forked from; absent for the stage's first attempt." } + output: { type: string, description: "The finish_stage output the stages after it get; absent until it finishes." } + commit: { type: string, description: "With output: the commit the stage finished at." } + discarded_by: { type: string, description: "discarded and cleaned_up: who discarded it; byre for the cleanup." } + inputs: + type: array + description: "The attempts whose outputs it started from, one per after stage; a fork has its source's." + items: { $ref: "#/components/schemas/StageInput" } + + StageInput: + type: object + required: [stage, task_id] + properties: + stage: { type: string } + task_id: { type: string } + TaskChanges: type: object required: [base, tree, files] @@ -1424,8 +1511,8 @@ components: TaskTab: type: string - enum: [transcript, changes, files, terminal, inbox, reviews, project] - x-enum-varnames: [TabTranscript, TabChanges, TabFiles, TabTerminal, TabInbox, TabReviews, TabProject] + enum: [transcript, changes, files, terminal, inbox, reviews, workflow, project] + x-enum-varnames: [TabTranscript, TabChanges, TabFiles, TabTerminal, TabInbox, TabReviews, TabWorkflow, TabProject] TerminalSize: type: object diff --git a/docs/operations.md b/docs/operations.md index 79d3c27..84f83c6 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -192,7 +192,7 @@ Each user has one long-running lead agent, shown in the left pane. It is not tie - **Notes.** The lead keeps notes on how its user works (priorities, preferences, the reasoning behind choices) in `lead_notes`, one row per note keyed by `owner`, through its `remember` (add, or replace the text of an `id`), `forget` and `list_notes` tools (`internal/agents/leadnotes.go`). Each change records a `lead.note_saved` or `lead.note_deleted` event owned by the user. When a lead's agent process starts, `notesText` lists every note with its id after `leadGuidance` in the session's instructions (`--append-system-prompt` for Claude, which keeps what the session's first request carried; `developerInstructions` for Codex), but not in the per-turn guidance reminder, so a new or compacted lead session starts from the current notes and notes written mid-session are already in its context. The guidance tells the lead when to write a note (an answer that departs from a recommendation, a correction, a stated preference), to cite a note's id when it shapes a recommendation, and that it may answer a task agent's question itself when a note settles it outright. `GET /api/me/lead/notes` lists the caller's notes and `DELETE /api/me/lead/notes/{noteId}` deletes one (`Manager.DeleteLeadNote`), and, when the user has a live lead session, holds a message for it from `byre` naming the note's id and text and telling it to stop applying it, since the running session still has the note in its instructions. It is held as a message, not a signal, so it keeps its place in line with the human's own messages: it goes out ahead of any message they send after the delete, as its own turn (drawn like a signal batch's, and folded away on `NO_REPLY`) or mid-turn after the lead's next tool call; the Settings tab lists them with a delete link each, refetching on either event. `sqlite3 byre.db "SELECT owner, id, text FROM lead_notes ORDER BY created_at"` shows them. - **Restarts.** On shutdown, byre marks each running lead session idle with "byre stopped mid-turn" and holds a restart notice for it, so a lead is never left `running` for a build without lead support to find. After a crash, startup resumes a running lead like a task session. Startup then delivers any held input. -The UI is two panes filling the window, with no navbar. The left has three tabs: Lead, the lead's transcript and composer (the same view as a task transcript, with only the Compact button in its header), Status and Settings, and at the end of its tab strip the connection dot and the user's name. Which left tab is selected is kept only in the page; the Lead view stays mounted while another tab shows, and Status or Settings mounts each time its tab is selected. The right shows the focused task, or project with no task: a top row holding the task picker, centred, and the task's preview links at its right end (see "Previews"), then the tab strip, then the selected tab's view with its own header. The tabs are Transcript, Changes, Files, Terminal, Inbox, Reviews and Project, the lead's `tabs` first. Reviews shows only once it has a `review.*` event, and Inbox only while the task has open items; the selected tab always shows. Tabs that don't fit in the strip move, from the end, into a **More ▾** menu (`web/src/panes.ts`); the selected tab never moves there, and More carries the Inbox highlight and count when Inbox is in it. ⌘P (Ctrl+P elsewhere) selects the Project tab, keeping the right pane's task, and replaces the browser's print shortcut. ⌘L (Ctrl+L elsewhere) selects the Lead tab and puts the cursor in the lead's composer, and replaces the browser's address bar shortcut. ⌘S (Ctrl+S elsewhere) opens the right pane's task's Merge confirmation, from any tab, when the Merge button would be enabled, and replaces the browser's save shortcut. ⌘/ (Ctrl+/ elsewhere) opens a dialog listing every keyboard shortcut; the list is `shortcuts` in `web/src/switcher.ts`, kept in step with the handlers by hand. The ⌘ shortcuts do nothing while a dialog is open. +The UI is two panes filling the window, with no navbar. The left has three tabs: Lead, the lead's transcript and composer (the same view as a task transcript, with only the Compact button in its header), Status and Settings, and at the end of its tab strip the connection dot and the user's name. Which left tab is selected is kept only in the page; the Lead view stays mounted while another tab shows, and Status or Settings mounts each time its tab is selected. The right shows the focused task, or project with no task: a top row holding the task picker, centred, and the task's preview links at its right end (see "Previews"), then the tab strip, then the selected tab's view with its own header. The tabs are Transcript, Changes, Files, Terminal, Inbox, Reviews, Workflow and Project, the lead's `tabs` first. Reviews shows only once it has a `review.*` event, Inbox only while the task has open items, and Workflow only on a task with a `workflow_run` (see "Workflows"); the selected tab always shows. Tabs that don't fit in the strip move, from the end, into a **More ▾** menu (`web/src/panes.ts`); the selected tab never moves there, and More carries the Inbox highlight and count when Inbox is in it. ⌘P (Ctrl+P elsewhere) selects the Project tab, keeping the right pane's task, and replaces the browser's print shortcut. ⌘L (Ctrl+L elsewhere) selects the Lead tab and puts the cursor in the lead's composer, and replaces the browser's address bar shortcut. ⌘S (Ctrl+S elsewhere) opens the right pane's task's Merge confirmation, from any tab, when the Merge button would be enabled, and replaces the browser's save shortcut. ⌘/ (Ctrl+/ elsewhere) opens a dialog listing every keyboard shortcut; the list is `shortcuts` in `web/src/switcher.ts`, kept in step with the handlers by hand. The ⌘ shortcuts do nothing while a dialog is open. ## TODO @@ -293,7 +293,7 @@ Every new snapshot of a task gets a review: a separate agent session on the vend ## Workflows -A workflow is a named graph of stages, each a stage name, the stages it comes after, where its branch starts, a model and the stage agent's prompt written out in full. Every stage runs as its own task, once all the stages it comes after have finished, so one stage's output can go to several stages (fan-out) and one stage can wait for several (fan-in). Workflows live in byre's database, in the `workflows` table (`name`, and the definition's JSON as `definition`), shared by every project and never in a repo. byre stores, validates, exports, imports and freezes them, and runs each run's frozen copy stage by stage (`internal/agents/workflows.go`; the graph helpers `After`, `Next`, `Starts` and `FromMain` are in `internal/workflow/workflow.go`). The human starts one from the task switcher (see "Starting"); there is no UI for managing them: the lead does that with its tools, and draws a workflow for the human as a Mermaid flowchart of its stage names, which its chat renders (see "Inbox"). +A workflow is a named graph of stages, each a stage name, the stages it comes after, where its branch starts, a model and the stage agent's prompt written out in full. Every stage runs as its own task, once all the stages it comes after have finished, so one stage's output can go to several stages (fan-out) and one stage can wait for several (fan-in). Workflows live in byre's database, in the `workflows` table (`name`, and the definition's JSON as `definition`), shared by every project and never in a repo. byre stores, validates, exports, imports and freezes them, and runs each run's frozen copy stage by stage (`internal/agents/workflows.go`; the graph helpers `After`, `Next`, `Starts` and `FromMain` are in `internal/workflow/workflow.go`). The human starts one from the task switcher (see "Starting"); there is no UI for managing them: the lead does that with its tools, and draws a workflow for the human as a Mermaid flowchart of its stage names, which its chat renders (see "Inbox"). A run's progress is shown read-only in the stage tasks' Workflow tab (see "Progress" below). - **Names.** The name is the workflow's key and is shown to the human on buttons and pickers, so it is free text: one line of 1 to 100 characters, trimmed (`workflow.CleanName`). It isn't part of the definition, so the file doesn't carry it. In URLs it is a path-escaped segment. - **File.** One workflow per file: the `WorkflowDefinition` (`api/openapi.yaml`) as YAML, an optional `description` and its `stages`. A stage's `after` lists the stages whose outputs it gets; absent, it means the previous stage in the list (none for the first), so a file without `after` is a chain; `[]` means the stage starts from the brief. Its `base` is `parent` (the default: the commit its one `after` stage finished at, or for a stage with none, where the run was started from) or `main` (the project's default branch); a stage with more than one `after` stage always starts from the default branch. `workflow.Format` writes it with multi-line prompts as literal blocks; `workflow.Parse` reads YAML or JSON and refuses unknown fields. The download is named after the workflow with `/\:*?"<>|` replaced by `_` (`workflow.Filename`). @@ -303,6 +303,7 @@ A workflow is a named graph of stages, each a stage name, the stages it comes af - **Starting.** The lead's `create_task` and `start_todo` take an optional `workflow` (404 when there is none of that name) and then start a run of it instead of an agent on the prompt (`Manager.StartWorkflow`); `model` together with `workflow` is refused, since each stage names its own. `POST /api/projects/{id}/tasks` takes the same optional `workflow`, with the title as the run's brief, and returns the run's first stage task. The task switcher (`web/src/switcher.ts`) offers it as a "Start workflow…" row after each "New task in …" row: picking that lists `GET /api/workflows`, filtered by what is typed next (Esc goes back to the task list), and picking a workflow starts the run with the typed title and opens its first stage task. A run gets a new id and creates a task for every stage with no `after` stages, branched from the default branch, or for a stage with `base: parent`, from the lead's `from_task_id` HEAD when given. Each stage task copies the workflow's name and definition as they are when the run starts into `tasks.workflow_name` and `tasks.workflow_definition`, so later saves or deletes don't change it; its brief into `tasks.workflow_brief` (the lead's `create_task` `prompt`, optional with a workflow and may be empty, or for `start_todo` the TODO item as `todoPrompt` words it); the run's title into `tasks.workflow_title`; the run id into `tasks.workflow_run`; and its stage's name into `tasks.workflow_stage`. Stage tasks are titled `: <stage>`, with the run's title as their merge title, and carry the run's TODO item. The Task's `workflow`, `workflow_run` and `workflow_stage` are those; `GET /api/tasks/{id}/workflow` returns the copy as `{name, definition}` with the definition as YAML (404 for a task without one). A task agent's `create_subtask`, `POST /api/projects/{id}/tasks` without `workflow` and the Project tab's Start create tasks without one. A fork of a stage task copies its frozen workflow, brief, title, run and stage, so it is another attempt at the same stage of the same run. `sqlite3 byre.db "SELECT id, status, workflow_stage, stage_output != '' FROM tasks WHERE workflow_run = '<run>'"` lists a run's tasks and which have finished. - **Stages.** A stage task's agent is an implementer session on the stage's model, created by the user who started the run; any later session of the task (a Compact handoff's, one started by a message) runs the same stage, since the stage belongs to the task. Starting a stage records a `task.workflow_stage` event on its task (`workflow`, `run`, `stage` the name, `after` the ids of the tasks whose outputs it gets; actor the lead for the stages a run starts with, `byre` after) and sends the session its first message, actor `byre`, so the transcript shows it collapsed under its first line: `Workflow "<name>", stage "<stage>"`, then the stage's prompt, a `## Brief` section when the brief isn't empty, a `## From stage "<stage>" (task <id>, branch <branch>)` section with each `after` stage's output, and a line saying where the task starts: from the default branch, with the branches above to `git merge` or read as it needs, or from the commit its one `after` stage finished at. Nothing else of earlier stages is passed on; their branches carry their work. - **Advancing.** A stage session gets the `finish_stage` tool (`output`, required) and a guidance line naming the workflow, its stage and the stages after it. The call stores the output in `agent_sessions.stage_output`, replacing any earlier one; it is refused once the task's stage has finished. When a turn of that session ends normally (not an error or interrupt, not a handoff, not a Merge turn that squashes) with an output stored, byre sets `agent_sessions.stage_finished` before marking the session idle, and then advances (`nextStage`): it records the output and the worktree's HEAD in `tasks.stage_output` and `tasks.stage_commit`, then, holding `workflowMu` so two stages finishing at once can't both start the one after them, goes through each stage after this one. A stage starts once every stage it comes after has a finished task in the run (the latest one, when a fork made several); its task branches from that task's `stage_commit` for `base: parent` with one `after` stage, else from the default branch. Once every stage after it has been dealt with, byre clears `stage_output` and `stage_finished` on the session. The session stays idle in its task for more messages, and queued messages and held answers are delivered to it once advancing is done. When the final stage finishes, byre starts discarding every other active task of the run (as `byre`, through the same `Discard` as the button, so each gets its summary turn first and closes when that turn ends; one already merging or being discarded is skipped and logged as `stage task not discarded`), then records `task.workflow_finished` (`workflow`, `output`) on the final task and clears the flags in the same transaction, leaving the final task for the human to merge. A turn that ends without the call leaves the task in its stage. The output belongs to the turn that stored it: when that turn ends any other way (an error, an interrupt, a handoff, a Merge turn that squashes, an agent process that exits mid-turn, or a session that can't be resumed after a restart), byre clears `stage_output` before marking the session idle, so a later turn can't hand off a stale output; the agent calls `finish_stage` again. A turn cut off by a byre restart and resumed keeps it. If a stage can't start, byre logs `advance workflow stage` and files the error in the finishing task's inbox, and the flag stays set. On startup, before resuming running sessions, `recoverStages` advances every session with `stage_finished` set, skipping the steps already done: the recorded output isn't overwritten; a stage that already has a task in the run isn't created again, but when that task is active and has no session, its session is started, and when its session never got a message (`SessionStarted`), it is sent the stage's first message, and the restart notice isn't sent to it. `sqlite3 byre.db 'SELECT id, task_id FROM agent_sessions WHERE stage_finished = 1'` lists stages waiting to advance. `list_tasks` shows each stage task's workflow and `stage "<name>"`, with `(finished)` once its stage has finished and `workflow finished` once any task of the run has a `task.workflow_finished` event. Nothing reads or writes `agent_sessions.workflow_stage`; it stays in the schema so builds from older branches keep working against the same database. +- **Progress.** `GET /api/tasks/{id}/workflow/run` (`Manager.WorkflowRun`) returns the run of a stage task (404 for a task without one): the definition that task froze (typed, not YAML), name, title, brief, `finished` (any task of the run has `task.workflow_finished`), and per stage in definition order its resolved `after`, `waiting_on` (the `after` stages with no finished attempt), its `attempts` and a `state`. An attempt is every task of the run at that stage, closed ones included, oldest first (the first and its forks), with its `output` and `commit` once `tasks.stage_output` is set, `forked_from`, `discarded_by` (the `task.discarded` actor) and `inputs`: the tasks named in the `after` of its latest `task.workflow_stage` event, each with its stage, so it says which attempt fed it; a fork has no such event and takes its source's. An attempt's state is `merged`, `cleaned_up` (discarded after finishing; `byre` as `discarded_by` is the final stage's cleanup), `discarded` (before finishing), `finished`, `running` (a session is running) or `idle`. A stage is `waiting` with no attempts, else it takes the state of its latest finished attempt, or its latest attempt when none finished. The Workflow tab (`web/src/workflow.ts`) draws the graph once per run with the lazy-loaded Mermaid, then a card per stage with its state, its attempts linking to their tasks, each attempt's inputs ("started from") and the attempts it fed, and its output collapsed as Markdown. It refetches on any stored `task.*` or `session.*` event of a task in the run, and on a `task.created` whose payload carries the run, so a new stage or fork shows up. ## Events diff --git a/internal/agents/leadtools.go b/internal/agents/leadtools.go index 40216c4..80492b6 100644 --- a/internal/agents/leadtools.go +++ b/internal/agents/leadtools.go @@ -359,7 +359,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool { tool("show", "Point the human's right pane at a task, or at a project with no task: tabs are the tabs to put first, in order (the rest follow), and tab is the one to select. "+ - "Tabs: transcript, changes, files, terminal (a shell in the task's worktree), inbox (the task's open items), reviews (the task's reviews by reviewer agents), project (the project's dashboard: its active tasks and its TODO.md items); with only project_id, only project shows anything. "+ + "Tabs: transcript, changes, files, terminal (a shell in the task's worktree), inbox (the task's open items), reviews (the task's reviews by reviewer agents), workflow (a workflow stage task's run: its graph and each stage's state, attempts and outputs), project (the project's dashboard: its active tasks and its TODO.md items); with only project_id, only project shows anything. "+ "Omit both task_id and project_id to clear the pane. "+ "If the pane already shows that task (or project) on that tab, only the tab order changes and you are told so, even while the human is working in the pane. "+ "Otherwise refused while the human is working in the right pane, unless it is on the project tab, or what it shows is finished (a merged or discarded task, or an inbox tab with nothing left), "+ @@ -368,8 +368,8 @@ func (m *Manager) leadTools(l *live) []mcp.Tool { `{"type": "object", "properties": { "task_id": {"type": "string"}, "project_id": {"type": "string", "description": "Ignored when task_id is given."}, - "tabs": {"type": "array", "items": {"type": "string", "enum": ["transcript", "changes", "files", "terminal", "inbox", "reviews", "project"]}}, - "tab": {"type": "string", "enum": ["transcript", "changes", "files", "terminal", "inbox", "reviews", "project"]} + "tabs": {"type": "array", "items": {"type": "string", "enum": ["transcript", "changes", "files", "terminal", "inbox", "reviews", "workflow", "project"]}}, + "tab": {"type": "string", "enum": ["transcript", "changes", "files", "terminal", "inbox", "reviews", "workflow", "project"]} }, "required": ["tabs", "tab"]}`, func(ctx context.Context, user api.User, raw json.RawMessage) (string, error) { f := api.Focus{} diff --git a/internal/agents/workflows.go b/internal/agents/workflows.go index c002adc..6f9f730 100644 --- a/internal/agents/workflows.go +++ b/internal/agents/workflows.go @@ -51,6 +51,151 @@ func (m *Manager) TaskWorkflow(ctx context.Context, taskID string) (api.TaskWork return api.TaskWorkflow{Name: frozen.Name, Definition: string(file)}, nil } +func (m *Manager) WorkflowRun(ctx context.Context, taskID string) (api.WorkflowRun, error) { + frozen, err := m.store.TaskWorkflow(ctx, taskID) + if err != nil { + return api.WorkflowRun{}, err + } + task, err := m.store.GetTask(ctx, taskID) + if err != nil { + return api.WorkflowRun{}, err + } + tasks, err := m.store.RunTasks(ctx, *task.WorkflowRun) + if err != nil { + return api.WorkflowRun{}, err + } + events, err := m.store.RunEvents(ctx, *task.WorkflowRun) + if err != nil { + return api.WorkflowRun{}, err + } + + run := api.WorkflowRun{Name: frozen.Name, Run: *task.WorkflowRun, Title: frozen.Title, Brief: frozen.Brief, Definition: frozen.Definition, Stages: []api.WorkflowRunStage{}} + after := map[string][]string{} + discardedBy := map[string]string{} + for _, ev := range events { + switch ev.Kind { + case "task.workflow_stage": + ids := []string{} + list, _ := ev.Payload["after"].([]any) + for _, v := range list { + id, _ := v.(string) + ids = append(ids, id) + } + after[*ev.TaskId] = ids + case "task.discarded": + discardedBy[*ev.TaskId] = ev.Actor + case "task.workflow_finished": + run.Finished = true + } + } + + byID := map[string]api.Task{} + for _, t := range tasks { + byID[t.Id] = t + } + var inputs func(id string) []api.StageInput + inputs = func(id string) []api.StageInput { + ids, found := after[id] + if !found { + t := byID[id] + if t.ForkedFrom == nil { + return []api.StageInput{} + } + return inputs(*t.ForkedFrom) + } + in := []api.StageInput{} + for _, a := range ids { + stage := "" + if t, found := byID[a]; found { + stage = *t.WorkflowStage + } + in = append(in, api.StageInput{Stage: stage, TaskId: a}) + } + return in + } + + attempts := map[string][]api.StageAttempt{} + done := map[string]bool{} + for _, t := range tasks { + output, commit, err := m.store.StageResult(ctx, t.Id) + if err != nil { + return api.WorkflowRun{}, err + } + running := false + if t.Status == api.TaskStatusActive { + sessions, err := m.store.ListSessions(ctx, t.Id) + if err != nil { + return api.WorkflowRun{}, err + } + for _, s := range sessions { + running = running || s.State == api.AgentSessionStateRunning + } + } + a := api.StageAttempt{ + TaskId: t.Id, + Title: t.Title, + State: attemptState(t, output != "", running), + Discarding: t.Discarding, + ForkedFrom: t.ForkedFrom, + Inputs: inputs(t.Id), + } + if output != "" { + a.Output = &output + a.Commit = &commit + done[*t.WorkflowStage] = true + } + if by, found := discardedBy[t.Id]; found && t.Status == api.TaskStatusDiscarded { + a.DiscardedBy = &by + } + attempts[*t.WorkflowStage] = append(attempts[*t.WorkflowStage], a) + } + + for _, s := range frozen.Definition.Stages { + stage := api.WorkflowRunStage{ + Name: s.Name, + After: workflow.After(frozen.Definition, s.Name), + State: api.StageStateWaiting, + WaitingOn: []string{}, + Attempts: attempts[s.Name], + } + if stage.Attempts == nil { + stage.Attempts = []api.StageAttempt{} + } + for _, a := range stage.After { + if !done[a] { + stage.WaitingOn = append(stage.WaitingOn, a) + } + } + if len(stage.Attempts) > 0 { + deciding := stage.Attempts[len(stage.Attempts)-1] + for _, a := range stage.Attempts { + if a.Output != nil { + deciding = a + } + } + stage.State = api.WorkflowRunStageState(deciding.State) + } + run.Stages = append(run.Stages, stage) + } + return run, nil +} + +func attemptState(t api.Task, finished, running bool) api.StageAttemptState { + switch { + case t.Status == api.TaskStatusMerged: + return api.AttemptStateMerged + case t.Status == api.TaskStatusDiscarded && finished: + return api.AttemptStateCleanedUp + case t.Status == api.TaskStatusDiscarded: + return api.AttemptStateDiscarded + case finished: + return api.AttemptStateFinished + case running: + return api.AttemptStateRunning + } + return api.AttemptStateIdle +} + var errModelWithWorkflow = fmt.Errorf("%w: model can't be combined with workflow: each stage names its own model", ErrInvalid) type parentStage struct { diff --git a/internal/api/api.gen.go b/internal/api/api.gen.go index 1398cee..11d34b6 100644 --- a/internal/api/api.gen.go +++ b/internal/api/api.gen.go @@ -336,6 +336,36 @@ func (e StageBase) Valid() bool { } } +// Defines values for StageAttemptState. +const ( + AttemptStateCleanedUp StageAttemptState = "cleaned_up" + AttemptStateDiscarded StageAttemptState = "discarded" + AttemptStateFinished StageAttemptState = "finished" + AttemptStateIdle StageAttemptState = "idle" + AttemptStateMerged StageAttemptState = "merged" + AttemptStateRunning StageAttemptState = "running" +) + +// Valid indicates whether the value is a known member of the StageAttemptState enum. +func (e StageAttemptState) Valid() bool { + switch e { + case AttemptStateCleanedUp: + return true + case AttemptStateDiscarded: + return true + case AttemptStateFinished: + return true + case AttemptStateIdle: + return true + case AttemptStateMerged: + return true + case AttemptStateRunning: + return true + default: + return false + } +} + // Defines values for TaskStatus. const ( TaskStatusActive TaskStatus = "active" @@ -366,6 +396,7 @@ const ( TabReviews TaskTab = "reviews" TabTerminal TaskTab = "terminal" TabTranscript TaskTab = "transcript" + TabWorkflow TaskTab = "workflow" ) // Valid indicates whether the value is a known member of the TaskTab enum. @@ -385,6 +416,41 @@ func (e TaskTab) Valid() bool { return true case TabTranscript: return true + case TabWorkflow: + return true + default: + return false + } +} + +// Defines values for WorkflowRunStageState. +const ( + StageStateCleanedUp WorkflowRunStageState = "cleaned_up" + StageStateDiscarded WorkflowRunStageState = "discarded" + StageStateFinished WorkflowRunStageState = "finished" + StageStateIdle WorkflowRunStageState = "idle" + StageStateMerged WorkflowRunStageState = "merged" + StageStateRunning WorkflowRunStageState = "running" + StageStateWaiting WorkflowRunStageState = "waiting" +) + +// Valid indicates whether the value is a known member of the WorkflowRunStageState enum. +func (e WorkflowRunStageState) Valid() bool { + switch e { + case StageStateCleanedUp: + return true + case StageStateDiscarded: + return true + case StageStateFinished: + return true + case StageStateIdle: + return true + case StageStateMerged: + return true + case StageStateRunning: + return true + case StageStateWaiting: + return true default: return false } @@ -873,6 +939,41 @@ type Stage struct { // StageBase Where the stage's task branches from. parent (the default): the commit its one after stage finished at, or for a stage with none, where the workflow was started from. main: the project's default branch. Refused on a stage with more than one after stage, which always branches from the default branch. type StageBase string +// StageAttempt defines model for StageAttempt. +type StageAttempt struct { + // Commit With output: the commit the stage finished at. + Commit *string `json:"commit,omitempty"` + + // DiscardedBy discarded and cleaned_up: who discarded it; byre for the cleanup. + DiscardedBy *string `json:"discarded_by,omitempty"` + + // Discarding Whether a Discard was started and the task isn't closed yet. + Discarding bool `json:"discarding"` + + // ForkedFrom The task this attempt was forked from; absent for the stage's first attempt. + ForkedFrom *string `json:"forked_from,omitempty"` + + // Inputs The attempts whose outputs it started from, one per after stage; a fork has its source's. + Inputs []StageInput `json:"inputs"` + + // Output The finish_stage output the stages after it get; absent until it finishes. + Output *string `json:"output,omitempty"` + + // State running: its agent is mid-turn. idle: active, and finish_stage hasn't taken. finished: active, its output recorded. merged. discarded: discarded before finishing. cleaned_up: discarded after finishing, as byre does to the run's other tasks when the final stage finishes. + State StageAttemptState `json:"state"` + TaskId string `json:"task_id"` + Title string `json:"title"` +} + +// StageAttemptState running: its agent is mid-turn. idle: active, and finish_stage hasn't taken. finished: active, its output recorded. merged. discarded: discarded before finishing. cleaned_up: discarded after finishing, as byre does to the run's other tasks when the final stage finishes. +type StageAttemptState string + +// StageInput defines model for StageInput. +type StageInput struct { + Stage string `json:"stage"` + TaskId string `json:"task_id"` +} + // Status defines model for Status. type Status struct { ActiveTasks int `json:"active_tasks"` @@ -1076,6 +1177,42 @@ type WorkflowDefinition struct { Stages []Stage `json:"stages"` } +// WorkflowRun defines model for WorkflowRun. +type WorkflowRun struct { + Brief string `json:"brief"` + + // Definition A workflow's file, which holds everything but its name: its stages, each run as its own task once the stages it comes after have finished. Sent and returned as YAML. + Definition WorkflowDefinition `json:"definition"` + + // Finished Whether the final stage finished, which ends the run. + Finished bool `json:"finished"` + Name string `json:"name"` + Run string `json:"run"` + + // Stages In the definition's order. + Stages []WorkflowRunStage `json:"stages"` + Title string `json:"title"` +} + +// WorkflowRunStage defines model for WorkflowRunStage. +type WorkflowRunStage struct { + // After The stages it comes after, with the definition's defaults applied. + After []string `json:"after"` + + // Attempts The tasks that ran the stage (the first, and forks of it), oldest first. + Attempts []StageAttempt `json:"attempts"` + Name string `json:"name"` + + // State waiting: no task yet. Otherwise the state of its latest finished attempt, or of its latest attempt when none has finished. + State WorkflowRunStageState `json:"state"` + + // WaitingOn The after stages with no finished attempt yet. + WaitingOn []string `json:"waiting_on"` +} + +// WorkflowRunStageState waiting: no task yet. Otherwise the state of its latest finished attempt, or of its latest attempt when none has finished. +type WorkflowRunStageState string + // WorkflowSummary defines model for WorkflowSummary. type WorkflowSummary struct { Description string `json:"description"` @@ -1359,6 +1496,9 @@ type ServerInterface interface { // (GET /api/tasks/{taskId}/workflow) GetTaskWorkflow(w http.ResponseWriter, r *http.Request, taskId string) + // (GET /api/tasks/{taskId}/workflow/run) + GetWorkflowRun(w http.ResponseWriter, r *http.Request, taskId string) + // (GET /api/workflows) ListWorkflows(w http.ResponseWriter, r *http.Request) @@ -2795,6 +2935,32 @@ func (siw *ServerInterfaceWrapper) GetTaskWorkflow(w http.ResponseWriter, r *htt handler.ServeHTTP(w, r) } +// GetWorkflowRun operation middleware +func (siw *ServerInterfaceWrapper) GetWorkflowRun(w http.ResponseWriter, r *http.Request) { + + var err error + _ = err + + // ------------- Path parameter "taskId" ------------- + var taskId string + + err = runtime.BindStyledParameterWithOptions("simple", "taskId", r.PathValue("taskId"), &taskId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "", ValueIsUnescaped: true}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "taskId", Err: err}) + return + } + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.GetWorkflowRun(w, r, taskId) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + // ListWorkflows operation middleware func (siw *ServerInterfaceWrapper) ListWorkflows(w http.ResponseWriter, r *http.Request) { @@ -3026,6 +3192,7 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/projects/{projectId}/todo/tasks", wrapper.StartTodoItem) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}", wrapper.GetTask) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/workflow", wrapper.GetTaskWorkflow) + m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/workflow/run", wrapper.GetWorkflowRun) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/unmerged", wrapper.GetUnmerged) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/co-authors", wrapper.GetCoAuthors) m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/tasks/{taskId}/merge", wrapper.MergeTask) @@ -3069,197 +3236,209 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "HkO+U13kjx//fwAAAP//", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/server/workflows.go b/internal/server/workflows.go index 561b76d..04da247 100644 --- a/internal/server/workflows.go +++ b/internal/server/workflows.go @@ -63,3 +63,12 @@ func (s *Server) GetTaskWorkflow(w http.ResponseWriter, r *http.Request, taskID } writeJSON(w, http.StatusOK, tw) } + +func (s *Server) GetWorkflowRun(w http.ResponseWriter, r *http.Request, taskID string) { + run, err := s.agents.WorkflowRun(r.Context(), taskID) + if err != nil { + writeAgentError(w, err) + return + } + writeJSON(w, http.StatusOK, run) +} diff --git a/internal/store/workflow.go b/internal/store/workflow.go index d9afbf2..2a85d8e 100644 --- a/internal/store/workflow.go +++ b/internal/store/workflow.go @@ -111,6 +111,18 @@ func (s *Store) RunTasks(ctx context.Context, run string) ([]api.Task, error) { return s.queryTasks(ctx, `SELECT `+taskColumns+` FROM tasks WHERE workflow_run = ? ORDER BY created_at`, run) } +func (s *Store) RunEvents(ctx context.Context, run string) ([]api.Event, error) { + rows, err := s.db.QueryContext(ctx, ` + SELECT `+eventColumns+` FROM events + WHERE task_id IN (SELECT id FROM tasks WHERE workflow_run = ?) AND kind IN ('task.workflow_stage', 'task.discarded', 'task.workflow_finished') + ORDER BY seq + `, run) + if err != nil { + return nil, err + } + return scanEvents(rows) +} + func (s *Store) RecordStage(ctx context.Context, taskID, output, commit string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { _, err := tx.ExecContext(ctx, `UPDATE tasks SET stage_output = ?, stage_commit = ? WHERE id = ?`, output, commit, taskID) diff --git a/web/dist/panes.js b/web/dist/panes.js index a62d938..8060765 100644 --- a/web/dist/panes.js +++ b/web/dist/panes.js @@ -13,6 +13,7 @@ import { mountStatus } from "./status.js"; import { openSwitcher } from "./switcher.js"; import { mountTranscript } from "./task.js"; import { mountTerminal } from "./terminal.js"; +import { mountWorkflow } from "./workflow.js"; const views = { transcript: { label: "Transcript", mount: mountTranscript }, changes: { label: "Changes", mount: (root) => mountChanges(root) }, @@ -20,6 +21,7 @@ const views = { terminal: { label: "Terminal", mount: mountTerminal }, inbox: { label: "Inbox", mount: mountInbox }, reviews: { label: "Reviews", mount: mountReviews }, + workflow: { label: "Workflow", mount: mountWorkflow }, project: { label: "Project", mount: mountProject }, }; const leftViews = { @@ -166,6 +168,8 @@ export function taskPane() { return waiting > 0; case "reviews": return state.transcript.some(isReviewEvent); + case "workflow": + return state.selectedTaskId !== undefined && findTask(state.selectedTaskId)?.workflow_run !== undefined; default: return true; } @@ -209,7 +213,7 @@ export function taskPane() { } }; on("inbox", openAsked); - onEach(["focus", "inbox", "selection", "transcript"], render); + onEach(["focus", "inbox", "selection", "transcript", "tasks"], render); onEach(["projects", "tasks", "selection"], renderPicker); new ResizeObserver(layout).observe(strip); render(); diff --git a/web/dist/panes.js.map b/web/dist/panes.js.map index a53968b..64df757 100644 --- a/web/dist/panes.js.map +++ b/web/dist/panes.js.map @@ -1 +1 @@ -{"version":3,"file":"panes.js","sourceRoot":"","sources":["../src/panes.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"panes.js","sourceRoot":"","sources":["../src/panes.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/dist/state.js b/web/dist/state.js index d626d13..81b6069 100644 --- a/web/dist/state.js +++ b/web/dist/state.js @@ -1,6 +1,6 @@ import { get, put, subscribe } from "./api.js"; import { notifyInbox, notifyTurn } from "./notifications.js"; -export const tabs = ["transcript", "changes", "files", "terminal", "inbox", "reviews", "project"]; +export const tabs = ["transcript", "changes", "files", "terminal", "inbox", "reviews", "workflow", "project"]; export const state = { me: undefined, projects: [], diff --git a/web/dist/state.js.map b/web/dist/state.js.map index 0f40ac2..8516bf0 100644 --- a/web/dist/state.js.map +++ b/web/dist/state.js.map @@ -1 +1 @@ -{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAkI,MAAM,UAAU,CAAC;AAC/K,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAsB7D,MAAM,CAAC,MAAM,IAAI,GAAc,CAAC,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAE7G,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,EAAE,EAAE,SAA6B;IACjC,QAAQ,EAAE,EAAe;IACzB,KAAK,EAAE,IAAI,GAAG,EAAkB;IAChC,QAAQ,EAAE,IAAI,GAAG,EAA0B;IAC3C,KAAK,EAAE,EAAiB;IACxB,cAAc,EAAE,SAA+B;IAC/C,UAAU,EAAE,EAAiB;IAC7B,MAAM,EAAE,SAA+B;IACvC,QAAQ,EAAE,SAA+B;IACzC,SAAS,EAAE,KAAK;IAChB,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,YAAY,EAAW;IAC3D,YAAY,EAAE,EAAoB;IAClC,cAAc,EAAE,EAAiB;CAClC,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0C,CAAC;AAEpE,MAAM,UAAU,EAAE,CAAC,KAAY,EAAE,EAA8B;IAC7D,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;QAChB,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,MAAe,EAAE,EAA8B;IACpE,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1C,OAAO,GAAG,EAAE;QACV,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,GAAG,EAAE,CAAC;QACR,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1J,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAY,EAAE,MAAgB;IACnD,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5C,EAAE,CAAC,MAAM,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,EAAU;IACjC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5C,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,WAAW,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACpH,CAAC;AAID,MAAM,UAAU,SAAS,CAAC,IAAU;IAClC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;IACpE,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,EAAE,CAAC;QAClD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAC;IAC1G,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC;IACnF,CAAC;IACD,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,iDAAiD,EAAE,CAAC;IACzG,CAAC;IACD,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QACvC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,6DAA6D,EAAE,CAAC;IACrH,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,+DAA+D,EAAE,CAAC;IACnH,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,SAAS,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;QACtF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,uBAAuB,EAAE,CAAC;IACzJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,WAAW,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAClG,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAA8B,CAAC,CAAC;AACpH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,CAAqB;IAC/C,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACjB,MAAM,CAAC,KAAK,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;IACnB,MAAM,CAAC,QAAQ,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,UAAU,CAAC,CAAC,CAAC,CAAC;IACd,QAAQ,CAAC,SAAS,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,KAAK,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,KAAK,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,CAAC;IAC5C,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9D,MAAM,CAAC,UAAU,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,SAAiB;IAC/C,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,iCAAiC,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IACpF,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1B,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IACD,eAAe,EAAE,CAAC;IAClB,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7F,MAAM,CAAC,OAAO,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc;IAC/C,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,8BAA8B,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5F,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,KAAK,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,CAAC;IACtC,MAAM,CAAC,OAAO,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,KAAK,CAAC,YAAY,GAAG,MAAM,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACxD,MAAM,CAAC,eAAe,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,UAAU,CAAC,MAAM,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAQ;IACjC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IAChB,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACnG,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,CAAC;QACvE,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;IACvB,CAAC;IACD,MAAM,CAAC,OAAO,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAA8E;IAC3G,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC;IAClG,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC;IACtJ,MAAM,IAAI,GAAU,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACnF,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IACD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IACD,UAAU,CAAC,IAAI,CAAC,CAAC;IACjB,UAAU,CAAC,MAAM,GAAG,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,MAAe,YAAY;IACnE,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;AAC9H,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAY;IACnC,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,IAAI;IAQW;IACA;IACA;IACA;IAVV,MAAM,GAAgB,EAAE,CAAC;IAClC,KAAK,GAAG,KAAK,CAAC;IACN,IAAI,GAAG,CAAC,CAAC;IACT,MAAM,GAAgB,EAAE,CAAC;IACzB,KAAK,GAAG,CAAC,CAAC;IAElB,YACmB,eAAsB,EACtB,WAAkB,EAClB,UAAiB,EACjB,KAAoB;QAHpB,oBAAe,GAAf,eAAe,CAAO;QACtB,gBAAW,GAAX,WAAW,CAAO;QAClB,eAAU,GAAV,UAAU,CAAO;QACjB,UAAK,GAAL,KAAK,CAAe;IACpC,CAAC;IAEK,IAAI,GAAG,CAAC,EAAa,EAAQ,EAAE;QACtC,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;YACnD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrB,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CAAC;IAEO,IAAI,GAAG,CAAC,OAAoB,EAAQ,EAAE;QAC7C,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC;IAEM,KAAK;QACX,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,MAAM,GAAgB,EAAE,CAAC;QAC7B,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;YACxB,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAChB,SAAS;YACX,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACpB,MAAM,GAAG,EAAE,CAAC;YACZ,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAEO,MAAM,CAAC,MAAmB;QAChC,MAAM,KAAK,GAAgB,EAAE,CAAC;QAC9B,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;YACxB,IAAI,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACf,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,CAAC;YACrB,CAAC;QACH,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;CACF;AAED,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAgB,CAAC;AAC1C,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACtF,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC;AAEvC,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,IAAU;IACnD,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;QAC1I,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACrB,IAAI,IAAI,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;YAC9B,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,GAAG,EAAQ,CAAC;AAErC,SAAS,QAAQ,CAAC,MAAc;IAC9B,IAAI,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC;QACxF,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC;IACrB,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC1B,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC;SACzB,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;SACxE,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,eAAe;IACtB,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,MAAM,KAAK,KAAK,CAAC,cAAc,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,KAAK,CAAC,cAAc,KAAK,SAAS,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;AACnG,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;AACzB,CAAC;AAED,MAAM,SAAS,GAAG,aAAa,CAAC;AAEhC,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,IAAI,CAA2B,CAAC;AACvF,CAAC;AAED,SAAS,WAAW,CAAC,MAA0B;IAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IACD,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAA0B;IACnD,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAClC,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,KAAK,CAAC,cAAc,GAAG,MAAM,CAAC;IAC9B,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;IACzB,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC;IAC3B,eAAe,EAAE,CAAC;IAClB,MAAM,CAAC,WAAW,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,SAAS,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAa;IACvC,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;QACf,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IAED,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QAChB,KAAK,cAAc;YACjB,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;gBAC5C,KAAK,MAAM,EAAE,CAAC;YAChB,CAAC;YACD,MAAM;QACR,KAAK,iBAAiB;YACpB,KAAK,YAAY,EAAE,CAAC;YACpB,MAAM;QACR,KAAK,cAAc,CAAC;QACpB,KAAK,kBAAkB,CAAC;QACxB,KAAK,mBAAmB,CAAC;QACzB,KAAK,qBAAqB,CAAC;QAC3B,KAAK,2BAA2B,CAAC;QACjC,KAAK,2BAA2B,CAAC;QACjC,KAAK,oBAAoB,CAAC;QAC1B,KAAK,kBAAkB,CAAC;QACxB,KAAK,sBAAsB,CAAC;QAC5B,KAAK,aAAa,CAAC;QACnB,KAAK,gBAAgB;YACnB,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC;gBAClB,KAAK,SAAS,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;YAChC,CAAC;YACD,MAAM;QACR,KAAK,iBAAiB,CAAC;QACvB,KAAK,eAAe,CAAC;QACrB,KAAK,eAAe;YAClB,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;gBACb,KAAK,gBAAgB,EAAE,CAAC;YAC1B,CAAC;iBAAM,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;gBACtB,KAAK,YAAY,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;YACD,MAAM;QACR,KAAK,eAAe;YAClB,WAAW,CAAC,EAAE,CAAC,OAA+B,CAAC,CAAC;YAChD,KAAK,SAAS,EAAE,CAAC;YACjB,MAAM;QACR,KAAK,eAAe;YAClB,KAAK,SAAS,EAAE,CAAC;YACjB,MAAM;QACR,KAAK,YAAY;YACf,UAAU,CAAC,EAAE,CAAC,CAAC;YACf,MAAM;QACR,KAAK,gBAAgB,CAAC;QACtB,KAAK,iBAAiB;YACpB,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC;gBAClB,KAAK,SAAS,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;YAChC,CAAC;YACD,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,EAAE,CAAC;gBAC/E,KAAK,SAAS,EAAE,CAAC;YACnB,CAAC;YACD,MAAM;QACR,KAAK,gBAAgB;YACnB,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,EAAE,CAAC;gBAC/E,KAAK,SAAS,EAAE,CAAC;YACnB,CAAC;YACD,MAAM;QACR,KAAK,eAAe;YAClB,IAAI,EAAE,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;gBACjC,UAAU,CAAC,EAAE,CAAC,OAA2B,CAAC,CAAC;YAC7C,CAAC;YACD,MAAM;IACV,CAAC;IAED,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACtB,CAAC"} \ No newline at end of file +{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/dist/workflow.js b/web/dist/workflow.js new file mode 100644 index 0000000..18fbf9d --- /dev/null +++ b/web/dist/workflow.js @@ -0,0 +1,182 @@ +import { get } from "./api.js"; +import { errorText, h, replace } from "./dom.js"; +import { markdown } from "./markdown.js"; +import { diagram } from "./mermaid.js"; +import { findTask, focusTask, onEach, state } from "./state.js"; +function graph(run) { + const id = new Map(run.stages.map((s, i) => [s.name, `s${i}`])); + const lines = ["flowchart TD"]; + for (const s of run.stages) { + lines.push(` ${id.get(s.name)}["${s.name.replaceAll('"', "#quot;")}"]`); + } + for (const s of run.stages) { + for (const a of s.after) { + lines.push(` ${id.get(a)} --> ${id.get(s.name)}`); + } + } + return lines.join("\n"); +} +function attemptLabel(a) { + switch (a.state) { + case "running": + return "running"; + case "idle": + return "idle, not finished"; + case "finished": + return "finished"; + case "merged": + return "merged"; + case "discarded": + return `discarded before finishing${a.discarded_by ? ` by ${a.discarded_by}` : ""}`; + case "cleaned_up": + return a.discarded_by === "byre" ? "finished, then discarded by the run's cleanup" : `finished, then discarded${a.discarded_by ? ` by ${a.discarded_by}` : ""}`; + } +} +function stageLabel(s) { + if (s.state !== "waiting") { + return attemptLabel(s.attempts.findLast((a) => a.output !== undefined) ?? s.attempts.at(-1)); + } + if (s.waiting_on.length > 0) { + return `waiting on ${s.waiting_on.map((n) => `“${n}”`).join(", ")}`; + } + return "waiting to start"; +} +function taskLink(taskId, label) { + const a = h("a", { href: `#/task/${taskId}`, class: "workflow-task" }, label); + a.onclick = (e) => { + e.preventDefault(); + focusTask(taskId); + }; + return a; +} +function attemptName(run, taskId) { + for (const s of run.stages) { + const i = s.attempts.findIndex((a) => a.task_id === taskId); + if (i >= 0) { + return s.attempts.length > 1 ? `“${s.name}” attempt ${i + 1}` : `“${s.name}”`; + } + } + return findTask(taskId)?.title ?? taskId; +} +function attemptRow(run, stage, a, index) { + const fed = run.stages.flatMap((s) => s.attempts.filter((d) => d.inputs.some((i) => i.task_id === a.task_id)).map((d) => d.task_id)); + return h("li", { class: `workflow-attempt ${a.state}${a.task_id === state.selectedTaskId ? " current" : ""}` }, h("div", { class: "workflow-attempt-head" }, stage.attempts.length > 1 ? h("span", { class: "workflow-attempt-n" }, `#${index + 1}`) : null, taskLink(a.task_id, a.title), h("span", { class: `workflow-state ${a.state}` }, attemptLabel(a)), a.discarding ? h("span", { class: "workflow-state discarding" }, "discarding…") : null), a.forked_from ? h("div", { class: "workflow-line" }, "fork of ", taskLink(a.forked_from, attemptName(run, a.forked_from))) : null, a.inputs.length > 0 + ? h("div", { class: "workflow-line" }, "started from ", ...a.inputs.flatMap((i, n) => [n > 0 ? ", " : null, taskLink(i.task_id, attemptName(run, i.task_id))])) + : null, fed.length > 0 ? h("div", { class: "workflow-line fed" }, "fed ", ...fed.flatMap((id, n) => [n > 0 ? ", " : null, taskLink(id, attemptName(run, id))])) : null, a.output !== undefined + ? h("details", { class: "workflow-output" }, h("summary", {}, "finish_stage output", a.commit ? h("code", {}, ` ${a.commit.slice(0, 10)}`) : null), markdown(a.output, "md", { taskId: a.task_id })) + : null); +} +function stageCard(run, s) { + return h("li", { class: `workflow-stage ${s.state}` }, h("header", {}, h("span", { class: "workflow-stage-name" }, s.name), h("span", { class: `workflow-state ${s.state}` }, stageLabel(s))), s.after.length > 0 ? h("div", { class: "workflow-line" }, `after ${s.after.map((n) => `“${n}”`).join(", ")}`) : h("div", { class: "workflow-line" }, "starts from the brief"), s.attempts.length > 0 ? h("ol", { class: "workflow-attempts" }, ...s.attempts.map((a, i) => attemptRow(run, s, a, i))) : null); +} +export function mountWorkflow(root) { + const head = h("header", { class: "workflow-header" }); + const graphBox = h("div", { class: "workflow-graph" }); + const list = h("div", { class: "workflow-body" }); + let run; + let drawnRun = ""; + let error = ""; + let target = 0; + let loading = false; + let again = false; + let disposed = false; + const load = async () => { + const taskId = state.selectedTaskId; + if (!taskId || !findTask(taskId)?.workflow_run) { + render(); + return; + } + if (loading) { + again = true; + return; + } + loading = true; + const started = ++target; + try { + const fresh = await get("/api/tasks/{taskId}/workflow/run", { path: { taskId } }); + if (started === target) { + run = fresh; + error = ""; + } + } + catch (err) { + if (started === target) { + error = errorText(err); + } + } + loading = false; + if (disposed) { + return; + } + if (started === target) { + render(); + } + if (again) { + again = false; + void load(); + } + }; + const render = () => { + const task = state.selectedTaskId ? findTask(state.selectedTaskId) : undefined; + if (!task?.workflow_run) { + replace(head); + replace(graphBox); + drawnRun = ""; + replace(list, h("div", { class: "empty" }, task ? "This task isn't part of a workflow run." : "No task selected.")); + return; + } + if (error) { + replace(list, h("div", { class: "empty error-text" }, error)); + return; + } + if (!run || run.run !== task.workflow_run) { + replace(list, h("div", { class: "empty" }, "Loading…")); + return; + } + replace(head, h("span", { class: "workflow-name" }, run.name), h("span", { class: "workflow-title" }, run.title), h("span", { class: `workflow-state ${run.finished ? "finished" : "running"}` }, run.finished ? "workflow finished" : "in progress")); + if (drawnRun !== run.run) { + drawnRun = run.run; + replace(graphBox, diagram(graph(run))); + } + replace(list, run.brief.trim() ? h("details", { class: "workflow-brief" }, h("summary", {}, "Brief"), markdown(run.brief, "md", { taskId: task.id })) : null, h("ol", { class: "workflow-stages" }, ...run.stages.map((s) => stageCard(run, s)))); + }; + const relevant = (ev) => { + if (ev.seq === 0 || !run) { + return false; + } + if (ev.kind === "task.created") { + return ev.payload["workflow_run"] === run.run; + } + const ids = new Set(run.stages.flatMap((s) => s.attempts.map((a) => a.task_id))); + return ev.task_id !== undefined && ids.has(ev.task_id) && (ev.kind.startsWith("task.") || ev.kind.startsWith("session.")); + }; + const offs = [ + onEach(["selection"], () => { + target++; + run = undefined; + error = ""; + render(); + void load(); + }), + onEach(["tasks"], () => { + if (!run && !loading && !error) { + void load(); + } + }), + onEach(["event"], (ev) => { + if (relevant(ev)) { + void load(); + } + }), + ]; + replace(root, h("div", { class: "workflow-view" }, head, h("div", { class: "workflow-scroll" }, graphBox, list))); + render(); + void load(); + return () => { + disposed = true; + for (const off of offs) { + off(); + } + }; +} +//# sourceMappingURL=workflow.js.map \ No newline at end of file diff --git a/web/dist/workflow.js.map b/web/dist/workflow.js.map new file mode 100644 index 0000000..6726da2 --- /dev/null +++ b/web/dist/workflow.js.map @@ -0,0 +1 @@ +{"version":3,"file":"workflow.js","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/src/api.gen.ts b/web/src/api.gen.ts index 2c1f745..599831d 100644 --- a/web/src/api.gen.ts +++ b/web/src/api.gen.ts @@ -268,6 +268,25 @@ export interface paths { patch?: never; trace?: never; }; + "/api/tasks/{taskId}/workflow/run": { + parameters: { + query?: never; + header?: never; + path: { + taskId: string; + }; + cookie?: never; + }; + /** @description The progress of the workflow run the task belongs to: the definition the task froze, and for each stage its state and every task that attempted it, with the attempts whose outputs each one started from. */ + get: operations["getWorkflowRun"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/tasks/{taskId}/unmerged": { parameters: { query?: never; @@ -1011,6 +1030,56 @@ export interface components { /** @description The WorkflowDefinition as YAML. */ definition: string; }; + WorkflowRun: { + name: string; + run: string; + title: string; + brief: string; + definition: components["schemas"]["WorkflowDefinition"]; + /** @description Whether the final stage finished, which ends the run. */ + finished: boolean; + /** @description In the definition's order. */ + stages: components["schemas"]["WorkflowRunStage"][]; + }; + WorkflowRunStage: { + name: string; + /** @description The stages it comes after, with the definition's defaults applied. */ + after: string[]; + /** + * @description waiting: no task yet. Otherwise the state of its latest finished attempt, or of its latest attempt when none has finished. + * @enum {string} + */ + state: "waiting" | "running" | "idle" | "finished" | "merged" | "discarded" | "cleaned_up"; + /** @description The after stages with no finished attempt yet. */ + waiting_on: string[]; + /** @description The tasks that ran the stage (the first, and forks of it), oldest first. */ + attempts: components["schemas"]["StageAttempt"][]; + }; + StageAttempt: { + task_id: string; + title: string; + /** + * @description running: its agent is mid-turn. idle: active, and finish_stage hasn't taken. finished: active, its output recorded. merged. discarded: discarded before finishing. cleaned_up: discarded after finishing, as byre does to the run's other tasks when the final stage finishes. + * @enum {string} + */ + state: "running" | "idle" | "finished" | "merged" | "discarded" | "cleaned_up"; + /** @description Whether a Discard was started and the task isn't closed yet. */ + discarding: boolean; + /** @description The task this attempt was forked from; absent for the stage's first attempt. */ + forked_from?: string; + /** @description The finish_stage output the stages after it get; absent until it finishes. */ + output?: string; + /** @description With output: the commit the stage finished at. */ + commit?: string; + /** @description discarded and cleaned_up: who discarded it; byre for the cleanup. */ + discarded_by?: string; + /** @description The attempts whose outputs it started from, one per after stage; a fork has its source's. */ + inputs: components["schemas"]["StageInput"][]; + }; + StageInput: { + stage: string; + task_id: string; + }; TaskChanges: { /** @description The commit or tree compared with: the merge-base of the task branch and the default branch, since, or the previous snapshot's tree. */ base: string; @@ -1288,7 +1357,7 @@ export interface components { drafting: boolean; }; /** @enum {string} */ - TaskTab: "transcript" | "changes" | "files" | "terminal" | "inbox" | "reviews" | "project"; + TaskTab: "transcript" | "changes" | "files" | "terminal" | "inbox" | "reviews" | "workflow" | "project"; TerminalSize: { cols: number; rows: number; @@ -1830,6 +1899,29 @@ export interface operations { 404: components["responses"]["Error"]; }; }; + getWorkflowRun: { + parameters: { + query?: never; + header?: never; + path: { + taskId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The run's progress. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WorkflowRun"]; + }; + }; + 404: components["responses"]["Error"]; + }; + }; getUnmerged: { parameters: { query?: never; diff --git a/web/src/panes.ts b/web/src/panes.ts index 3bbd1c1..866bef4 100644 --- a/web/src/panes.ts +++ b/web/src/panes.ts @@ -13,6 +13,7 @@ import { mountStatus } from "./status.js"; import { openSwitcher } from "./switcher.js"; import { mountTranscript } from "./task.js"; import { mountTerminal } from "./terminal.js"; +import { mountWorkflow } from "./workflow.js"; const views: Record<TaskTab, { label: string; mount: (root: HTMLElement) => () => void }> = { transcript: { label: "Transcript", mount: mountTranscript }, @@ -21,6 +22,7 @@ const views: Record<TaskTab, { label: string; mount: (root: HTMLElement) => () = terminal: { label: "Terminal", mount: mountTerminal }, inbox: { label: "Inbox", mount: mountInbox }, reviews: { label: "Reviews", mount: mountReviews }, + workflow: { label: "Workflow", mount: mountWorkflow }, project: { label: "Project", mount: mountProject }, }; @@ -189,6 +191,8 @@ export function taskPane(): HTMLElement { return waiting > 0; case "reviews": return state.transcript.some(isReviewEvent); + case "workflow": + return state.selectedTaskId !== undefined && findTask(state.selectedTaskId)?.workflow_run !== undefined; default: return true; } @@ -235,7 +239,7 @@ export function taskPane(): HTMLElement { }; on("inbox", openAsked); - onEach(["focus", "inbox", "selection", "transcript"], render); + onEach(["focus", "inbox", "selection", "transcript", "tasks"], render); onEach(["projects", "tasks", "selection"], renderPicker); new ResizeObserver(layout).observe(strip); render(); diff --git a/web/src/state.ts b/web/src/state.ts index ccb48d8..0f87689 100644 --- a/web/src/state.ts +++ b/web/src/state.ts @@ -21,7 +21,7 @@ export type Topic = | "ready" | "lead.ready"; -export const tabs: TaskTab[] = ["transcript", "changes", "files", "terminal", "inbox", "reviews", "project"]; +export const tabs: TaskTab[] = ["transcript", "changes", "files", "terminal", "inbox", "reviews", "workflow", "project"]; export const state = { me: undefined as User | undefined, diff --git a/web/src/workflow.ts b/web/src/workflow.ts new file mode 100644 index 0000000..e743927 --- /dev/null +++ b/web/src/workflow.ts @@ -0,0 +1,232 @@ +import { get, type ByreEvent, type Schemas } from "./api.js"; +import { errorText, h, replace } from "./dom.js"; +import { markdown } from "./markdown.js"; +import { diagram } from "./mermaid.js"; +import { findTask, focusTask, onEach, state } from "./state.js"; + +type WorkflowRun = Schemas["WorkflowRun"]; +type RunStage = Schemas["WorkflowRunStage"]; +type Attempt = Schemas["StageAttempt"]; + +function graph(run: WorkflowRun): string { + const id = new Map(run.stages.map((s, i) => [s.name, `s${i}`])); + const lines = ["flowchart TD"]; + for (const s of run.stages) { + lines.push(` ${id.get(s.name)}["${s.name.replaceAll('"', "#quot;")}"]`); + } + for (const s of run.stages) { + for (const a of s.after) { + lines.push(` ${id.get(a)} --> ${id.get(s.name)}`); + } + } + return lines.join("\n"); +} + +function attemptLabel(a: Attempt): string { + switch (a.state) { + case "running": + return "running"; + case "idle": + return "idle, not finished"; + case "finished": + return "finished"; + case "merged": + return "merged"; + case "discarded": + return `discarded before finishing${a.discarded_by ? ` by ${a.discarded_by}` : ""}`; + case "cleaned_up": + return a.discarded_by === "byre" ? "finished, then discarded by the run's cleanup" : `finished, then discarded${a.discarded_by ? ` by ${a.discarded_by}` : ""}`; + } +} + +function stageLabel(s: RunStage): string { + if (s.state !== "waiting") { + return attemptLabel(s.attempts.findLast((a) => a.output !== undefined) ?? s.attempts.at(-1)!); + } + if (s.waiting_on.length > 0) { + return `waiting on ${s.waiting_on.map((n) => `“${n}”`).join(", ")}`; + } + return "waiting to start"; +} + +function taskLink(taskId: string, label: string): HTMLElement { + const a = h("a", { href: `#/task/${taskId}`, class: "workflow-task" }, label); + a.onclick = (e) => { + e.preventDefault(); + focusTask(taskId); + }; + return a; +} + +function attemptName(run: WorkflowRun, taskId: string): string { + for (const s of run.stages) { + const i = s.attempts.findIndex((a) => a.task_id === taskId); + if (i >= 0) { + return s.attempts.length > 1 ? `“${s.name}” attempt ${i + 1}` : `“${s.name}”`; + } + } + return findTask(taskId)?.title ?? taskId; +} + +function attemptRow(run: WorkflowRun, stage: RunStage, a: Attempt, index: number): HTMLElement { + const fed = run.stages.flatMap((s) => s.attempts.filter((d) => d.inputs.some((i) => i.task_id === a.task_id)).map((d) => d.task_id)); + return h( + "li", + { class: `workflow-attempt ${a.state}${a.task_id === state.selectedTaskId ? " current" : ""}` }, + h( + "div", + { class: "workflow-attempt-head" }, + stage.attempts.length > 1 ? h("span", { class: "workflow-attempt-n" }, `#${index + 1}`) : null, + taskLink(a.task_id, a.title), + h("span", { class: `workflow-state ${a.state}` }, attemptLabel(a)), + a.discarding ? h("span", { class: "workflow-state discarding" }, "discarding…") : null, + ), + a.forked_from ? h("div", { class: "workflow-line" }, "fork of ", taskLink(a.forked_from, attemptName(run, a.forked_from))) : null, + a.inputs.length > 0 + ? h("div", { class: "workflow-line" }, "started from ", ...a.inputs.flatMap((i, n) => [n > 0 ? ", " : null, taskLink(i.task_id, attemptName(run, i.task_id))])) + : null, + fed.length > 0 ? h("div", { class: "workflow-line fed" }, "fed ", ...fed.flatMap((id, n) => [n > 0 ? ", " : null, taskLink(id, attemptName(run, id))])) : null, + a.output !== undefined + ? h( + "details", + { class: "workflow-output" }, + h("summary", {}, "finish_stage output", a.commit ? h("code", {}, ` ${a.commit.slice(0, 10)}`) : null), + markdown(a.output, "md", { taskId: a.task_id }), + ) + : null, + ); +} + +function stageCard(run: WorkflowRun, s: RunStage): HTMLElement { + return h( + "li", + { class: `workflow-stage ${s.state}` }, + h("header", {}, h("span", { class: "workflow-stage-name" }, s.name), h("span", { class: `workflow-state ${s.state}` }, stageLabel(s))), + s.after.length > 0 ? h("div", { class: "workflow-line" }, `after ${s.after.map((n) => `“${n}”`).join(", ")}`) : h("div", { class: "workflow-line" }, "starts from the brief"), + s.attempts.length > 0 ? h("ol", { class: "workflow-attempts" }, ...s.attempts.map((a, i) => attemptRow(run, s, a, i))) : null, + ); +} + +export function mountWorkflow(root: HTMLElement): () => void { + const head = h("header", { class: "workflow-header" }); + const graphBox = h("div", { class: "workflow-graph" }); + const list = h("div", { class: "workflow-body" }); + let run: WorkflowRun | undefined; + let drawnRun = ""; + let error = ""; + let target = 0; + let loading = false; + let again = false; + let disposed = false; + + const load = async () => { + const taskId = state.selectedTaskId; + if (!taskId || !findTask(taskId)?.workflow_run) { + render(); + return; + } + if (loading) { + again = true; + return; + } + loading = true; + const started = ++target; + try { + const fresh = await get("/api/tasks/{taskId}/workflow/run", { path: { taskId } }); + if (started === target) { + run = fresh; + error = ""; + } + } catch (err) { + if (started === target) { + error = errorText(err); + } + } + loading = false; + if (disposed) { + return; + } + if (started === target) { + render(); + } + if (again) { + again = false; + void load(); + } + }; + + const render = () => { + const task = state.selectedTaskId ? findTask(state.selectedTaskId) : undefined; + if (!task?.workflow_run) { + replace(head); + replace(graphBox); + drawnRun = ""; + replace(list, h("div", { class: "empty" }, task ? "This task isn't part of a workflow run." : "No task selected.")); + return; + } + if (error) { + replace(list, h("div", { class: "empty error-text" }, error)); + return; + } + if (!run || run.run !== task.workflow_run) { + replace(list, h("div", { class: "empty" }, "Loading…")); + return; + } + replace( + head, + h("span", { class: "workflow-name" }, run.name), + h("span", { class: "workflow-title" }, run.title), + h("span", { class: `workflow-state ${run.finished ? "finished" : "running"}` }, run.finished ? "workflow finished" : "in progress"), + ); + if (drawnRun !== run.run) { + drawnRun = run.run; + replace(graphBox, diagram(graph(run))); + } + replace( + list, + run.brief.trim() ? h("details", { class: "workflow-brief" }, h("summary", {}, "Brief"), markdown(run.brief, "md", { taskId: task.id })) : null, + h("ol", { class: "workflow-stages" }, ...run.stages.map((s) => stageCard(run!, s))), + ); + }; + + const relevant = (ev: ByreEvent): boolean => { + if (ev.seq === 0 || !run) { + return false; + } + if (ev.kind === "task.created") { + return ev.payload["workflow_run"] === run.run; + } + const ids = new Set(run.stages.flatMap((s) => s.attempts.map((a) => a.task_id))); + return ev.task_id !== undefined && ids.has(ev.task_id) && (ev.kind.startsWith("task.") || ev.kind.startsWith("session.")); + }; + + const offs = [ + onEach(["selection"], () => { + target++; + run = undefined; + error = ""; + render(); + void load(); + }), + onEach(["tasks"], () => { + if (!run && !loading && !error) { + void load(); + } + }), + onEach(["event"], (ev) => { + if (relevant(ev as ByreEvent)) { + void load(); + } + }), + ]; + + replace(root, h("div", { class: "workflow-view" }, head, h("div", { class: "workflow-scroll" }, graphBox, list))); + render(); + void load(); + return () => { + disposed = true; + for (const off of offs) { + off(); + } + }; +} diff --git a/web/style.css b/web/style.css index 89bf219..952462a 100644 --- a/web/style.css +++ b/web/style.css @@ -405,7 +405,8 @@ a.task-link { .files-view, .terminal-view, .inbox-view, -.reviews-view { +.reviews-view, +.workflow-view { flex: 1; min-height: 0; display: flex; @@ -1858,6 +1859,136 @@ pre.file-text .line::before { color: var(--warn); } +.workflow-header { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 10px; + padding: 8px 16px; + border-bottom: 1px solid var(--border); +} + +.workflow-header:empty { + display: none; +} + +.workflow-name { + font-weight: 700; +} + +.workflow-title { + color: var(--muted); +} + +.workflow-scroll { + flex: 1; + overflow-y: auto; + padding: 8px 16px 16px; +} + +.workflow-graph .mermaid-diagram { + margin: 0 0 12px; +} + +.workflow-brief { + margin: 0 0 12px; +} + +.workflow-brief > summary, +.workflow-output > summary { + cursor: pointer; + color: var(--muted); +} + +.workflow-stages, +.workflow-attempts { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; +} + +.workflow-stages { + gap: 12px; +} + +.workflow-stage { + border: 1px solid var(--border); + border-radius: 10px; + padding: 10px 14px; + background: var(--raised); +} + +.workflow-stage > header, +.workflow-attempt-head { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 10px; +} + +.workflow-stage-name { + font-weight: 700; +} + +.workflow-line { + font-size: 11px; + color: var(--muted); + margin-top: 2px; +} + +.workflow-attempts { + gap: 8px; + margin-top: 8px; +} + +.workflow-attempt { + border-top: 1px solid var(--border); + padding-top: 8px; +} + +.workflow-attempt.current .workflow-task { + font-weight: 700; +} + +.workflow-attempt-n { + color: var(--muted); +} + +.workflow-task { + color: var(--accent); +} + +.workflow-state { + font-size: 11px; + color: var(--muted); +} + +.workflow-state.running { + color: var(--accent); +} + +.workflow-state.idle, +.workflow-state.discarding { + color: var(--warn); +} + +.workflow-state.finished, +.workflow-state.merged { + color: var(--ok); +} + +.workflow-output { + margin-top: 6px; +} + +.workflow-output > .md { + margin-top: 6px; + padding-left: 10px; + border-left: 1px solid var(--border); +} + .findings { list-style: none; padding: 0;