diff --git a/api/openapi.yaml b/api/openapi.yaml index f238c1c..3392932 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -959,6 +959,7 @@ components: properties: title: { type: string, description: The title of the item to start. } model: { type: string } + discuss: { type: boolean, description: "Tell the agent the human wants to talk the item through, so it asks before changing anything." } Unmerged: type: object diff --git a/docs/operations.md b/docs/operations.md index c32def7..8ff2a21 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -150,7 +150,7 @@ Each user has one long-running lead agent, shown in the left pane. It is not tie - **Signals.** Every published event goes through `Manager.Observe`. These become signals in `lead_inputs` for every user who has a lead session: `inbox.created` (a question with its choices and recommendation, an error or rate limit), `inbox.updated` when a human answered a question or error, `task.created` (naming the TODO item it was started from, if any), `task.merge_started` (" is merging, started by ."), `task.merged`, `task.discarded`, `turn.ended` with `summary: true` (" finished a turn:" with its `result` cut to 1500 characters), `task.workflow_stage` (" started stage "" of workflow "".") and `task.workflow_finished` (" finished workflow "":" with its output cut to 1500 characters). The human switching the right pane is not a signal. A signal caused by the lead itself (actor ` (lead)`) is skipped, as is the update from an answer it gave. A task's `task.created` event carries the actor that created it, separately from its `created_by` login: tasks the lead creates with `create_task` or `start_todo` keep the human's login as `created_by` but have actor ` (lead)`. Whenever the lead is idle, byre sends the oldest held message from the human as its own turn, or else every held signal as one `byre` message headed "Signals since your last turn (n)", followed by "Tasks now:" with the `list_tasks` text and a line saying what the lead's right pane shows (task or project, and selected tab) and whether the human is working in it (`leadStateText` in `internal/agents/lead.go`). If collecting that fails, for example because a project's repository is gone, the batch is still sent, ending instead with "The task list and right pane state are unavailable:" and the error, which is also logged as `lead state`. Its guidance tells it not to respond to the human's own actions, and to make its final message exactly `NO_REPLY` when a batch needs nothing from it. A transcript (`quietReply` in `web/src/task.ts`) never draws an `agent.message` whose last line is `NO_REPLY` (the model sometimes writes a sentence before it), and hides the live partial message while its text is still a prefix of it; the partial message starts hidden and is first shown by its 100ms render, so an empty one never takes up space. A lead turn that byre starts without a handoff (a signal batch or a handoff continuation) is held (`ctx.held`): its `byre` message is never drawn, and the turn isn't opened, so the scanner stays off, and its partial message stays hidden, until the lead draws something else, such as a tool call, thinking or a real message. When such a turn ends in `NO_REPLY`, everything it drew is removed with it (tool calls, thinking), so the transcript keeps nothing of it; a turn that ends in a real message keeps all of it. - **Tools.** `list_tasks` (each project's active tasks, then a line listing the titles of its `TODO.md` items on the default branch that no active task was started from), `read_transcript` (a task's events in brief, the last `limit` or those after `after_seq`), `read_inbox`, `answer_question` (an `option`, `other` or `dismiss` response recorded as the user, through the same checks as `POST /api/inbox/responses`), `send_message` (starts the task's agent if it has none; refused while it is mid-turn), `create_task` and `start_todo` (each with an optional `workflow` to freeze and run), `interrupt`, `compact_task`, `merge_task`, `discard_task`, `show`, `compact_self`, and the workflow tools (see "Workflows"). The lead also has Claude Code's own tools and reads worktrees by path. Messages it sends task agents have actor ` (lead)`, so they don't make the user a participant; tasks, merges, discards and answers are done as the user. Its guidance says to answer a question only when the answer is clear or the human gave it, and to merge or discard only when the human asks. - **Focus.** `users.focus` holds what the user's right pane shows: `project_id`, `task_id`, `tabs` (the tabs put first, in order) and `tab` (the selected one). With a `task_id`, `project_id` is always that task's project, filled in by the server; with only a `project_id`, the pane shows that project with no task, which only the Project tab has anything for. `GET /api/me/focus` reads it; `PUT /api/me/focus` and the lead's `show` set it, refusing an unknown tab, a task that isn't active or an unknown project, and record a `focus.updated` event owned by the user. The page applies the focus on load and on every `focus.updated` it didn't cause itself; the human's own changes (⌘K, the right pane's task picker, clicking a tab, a task link, a notification) are sent with `PUT /api/me/focus`. The URL follows the focus: `#/task/`, `#/project/`, or `#/` for neither. -- **Pane lock.** A `show` of what the pane already shows (the same task, or the same project with no task, on the same selected tab; `sameView`) tells the lead so and applies only its `tabs` order, whether or not the human is in the pane, so the human's selected tab stays selected. Otherwise, while the human is working in the right pane, the lead's `show` is refused with an error telling it to say in chat what it would have shown, unless its selected tab is `project` (the fallback the lead shows when nothing needs the human, so the human being there doesn't hold it) or the pane is finished (`Manager.paneFinished`): its task is merged, discarded or merging (`merging_by` set), or its selected tab is `inbox` and the task has no open items. When an `inbox.updated`, `task.merge_started`, `task.merged` or `task.discarded` event leaves a user's focused task finished that way, that user's signal for it gets a line "Your right pane is free: has nothing left in its inbox." (or "is merging."/"is merged."/"is discarded."), even when the event itself makes no signal, such as a dismissed error; `inbox.updated` on a task that is no longer active adds none. The lead's guidance tells it to show the next thing that needs the human on that line, or, when nothing does, the project's Project tab with a short status in chat: one line per active task, then up to three TODO items it would start next, each with a reason, starting one only when the human picks it. It writes each item as a link to `#/todo//`; Markdown views draw that (`web/src/todolink.ts`) as the title with a **Start** button that calls `POST /api/projects/{id}/todo/tasks` with the first model, as the Project tab's does, or, once an active task was started from that item, the task's colour, dot and state, linking to it. A chat view refills them whenever its transcript grows or tasks or sessions change. When that status says nothing new since its last one, it replies `NO_REPLY` instead. The page sends `PUT /api/me/pane-focus` with `focused` whenever that changes: true while the browser window has focus and the focused element is inside the right pane. The pane itself is focusable (`tabIndex` -1), so a click anywhere in it counts, not only on inputs and buttons; a re-render that removes the focused element hands focus back to the pane rather than counting as leaving. The page sends false on `pagehide` (with `keepalive`) and resends true when its event stream reconnects. byre keeps the flag in memory per user (`Manager.paneFocused`), so it starts false after a restart until the page resends it. +- **Pane lock.** A `show` of what the pane already shows (the same task, or the same project with no task, on the same selected tab; `sameView`) tells the lead so and applies only its `tabs` order, whether or not the human is in the pane, so the human's selected tab stays selected. Otherwise, while the human is working in the right pane, the lead's `show` is refused with an error telling it to say in chat what it would have shown, unless its selected tab is `project` (the fallback the lead shows when nothing needs the human, so the human being there doesn't hold it) or the pane is finished (`Manager.paneFinished`): its task is merged, discarded or merging (`merging_by` set), or its selected tab is `inbox` and the task has no open items. When an `inbox.updated`, `task.merge_started`, `task.merged` or `task.discarded` event leaves a user's focused task finished that way, that user's signal for it gets a line "Your right pane is free: has nothing left in its inbox." (or "is merging."/"is merged."/"is discarded."), even when the event itself makes no signal, such as a dismissed error; `inbox.updated` on a task that is no longer active adds none. The lead's guidance tells it to show the next thing that needs the human on that line, or, when nothing does, the project's Project tab with a short status in chat: one line per active task, then up to three TODO items it would start next, each with a reason, starting one only when the human picks it. It writes each item as a link to `#/todo//`; Markdown views draw that (`web/src/todolink.ts`) as the title with **Start** and **Discuss** buttons that call `POST /api/projects/{id}/todo/tasks` with the first model, as the Project tab's do, or, once an active task was started from that item, the task's colour, dot and state, linking to it. A chat view refills them whenever its transcript grows or tasks or sessions change. When that status says nothing new since its last one, it replies `NO_REPLY` instead. The page sends `PUT /api/me/pane-focus` with `focused` whenever that changes: true while the browser window has focus and the focused element is inside the right pane. The pane itself is focusable (`tabIndex` -1), so a click anywhere in it counts, not only on inputs and buttons; a re-render that removes the focused element hands focus back to the pane rather than counting as leaving. The page sends false on `pagehide` (with `keepalive`) and resends true when its event stream reconnects. byre keeps the flag in memory per user (`Manager.paneFocused`), so it starts false after a restart until the page resends it. - **Start hold.** Start on a TODO item in the Project tab leaves the pane where it is. When the user starts one themselves (`StartTodo` with the user as actor, not the lead's `start_todo`), byre records the time in `Manager.startedTodo` for them, and for 10 seconds after it (`startHold`), while the pane's selected tab is `project`, every `show` that would change the view is refused, focused or not, with an error telling the lead the human is likely to start more. The user's own `PUT /api/me/focus` (switching task or tab) or a message to the lead clears it. The refusal and the `show` tool's description both tell the lead the hold lasts 10 seconds. When the 10 seconds pass without it being cleared or restarted by another Start (`endStartHold`, on a timer), byre clears it and, if the pane's selected tab is still `project`, sends the lead the signal "The start hold is over: …" so it can show what it held back; its guidance tells it to reply `NO_REPLY` when nothing was. It is in memory, so a restart clears it. - **Compaction.** The pane's **Compact** button asks the lead for a handoff (`leadHandoffPrompt`). The lead can't see its own context size, so the first time one of its turns ends (other than a handoff or a `compact_self` turn) with the latest `session.context` `used` at half its `window` or more, byre holds a signal for it giving the percentage and asking it to call `compact_self` at the next logical point (`warnLeadContext` in `internal/agents/lead.go`); it is sent once per live process, so a byre restart can send it again once the window is known. The lead calls `compact_self`; when that turn ends normally, byre sends the same request. The handoff turn ends the session, and a new lead session starts from `leadHandoffPreamble` plus the handoff; held input follows once that turn ends. - **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. @@ -161,9 +161,9 @@ The UI is two panes filling the window, with no navbar. The left has three tabs: A project's `TODO.md` is read from the root of its default branch in the project's checkout (`git cat-file blob :TODO.md`), so it shows what has been merged, not uncommitted edits in the checkout. `GET /api/projects/{id}/todo` returns `exists` and the parsed `items` (`internal/todo`): every top-level list item (`-`, `*`, `+`, `1.` or `1)` at the start of a line) is an item. Its first line, with any `[ ]` checkbox removed, is its `title`; the lines indented under it (and lines continuing it without a blank line between) are its `body`, with the common indentation removed; `section` is the nearest heading above it. Checked items (`[x]`) are skipped, list markers inside fenced code don't count, and paragraphs between items are ignored. -The title is the item's identity. `POST /api/projects/{id}/todo/tasks` with a `title` re-reads `TODO.md`, refuses an unknown title (404) or one an active task already has (409), creates a task from the default branch with that title and `todo_item` (the `tasks.todo_item` column, empty for other tasks), and starts its session as the requesting user with `todoPrompt` (`internal/agents/tasks.go`): the item as written, and an instruction to remove it from `TODO.md` in the worktree when the work is done. The agent's guidance names the item too (`taskGuidance`, see "Agent sessions"), so the instruction survives compaction and resumes. The agent removes the item on its own branch, so the removal lands on the default branch in the same squash commit as the work. +The title is the item's identity. `POST /api/projects/{id}/todo/tasks` with a `title` re-reads `TODO.md`, refuses an unknown title (404) or one an active task already has (409), creates a task from the default branch with that title and `todo_item` (the `tasks.todo_item` column, empty for other tasks), and starts its session as the requesting user with `todoPrompt` (`internal/agents/tasks.go`): the item as written, and an instruction to remove it from `TODO.md` in the worktree when the work is done. With `discuss: true` the prompt adds that the human wants to talk the item through first: the agent reads what it needs, asks about the open questions and its proposed approach with `ask_human`, and changes nothing until answered. The agent's guidance names the item too (`taskGuidance`, see "Agent sessions"), so the instruction survives compaction and resumes. The agent removes the item on its own branch, so the removal lands on the default branch in the same squash commit as the work. -The **Project** tab is the dashboard of the right pane's project (the focused task's, or the project focused with no task). Under **Tasks** it lists the project's active tasks in the server's order (newest first), each with its session state, open inbox item count and **merge held** when it has `merge_queued_at`, as links that point the right pane at the task's transcript; the focused task is highlighted. Under **TODO** it lists the `TODO.md` items, grouped by section, with each body rendered as Markdown. An item with an active task whose `todo_item` equals its title shows that task's session state as a link to the task instead of a **Start** button. **Start** posts the item with the composer's default model and points the right pane at the new task's transcript. The task list follows byre's live state; the tab fetches the project's `TODO.md` when it opens, when the right pane moves to another project, when the project list changes, when the SSE stream reconnects, and on `task.merged`; a change pushed to the default branch outside byre shows the next time one of those happens. +The **Project** tab is the dashboard of the right pane's project (the focused task's, or the project focused with no task). Under **Tasks** it lists the project's active tasks in the server's order (newest first), each with its session state, open inbox item count and **merge held** when it has `merge_queued_at`, as links that point the right pane at the task's transcript; the focused task is highlighted. Under **TODO** it lists the `TODO.md` items, grouped by section, with each body rendered as Markdown. An item with an active task whose `todo_item` equals its title shows that task's session state as a link to the task instead of the **Start** and **Discuss** buttons. **Start** posts the item with the composer's default model; **Discuss** posts it the same way with `discuss: true`. Neither moves the right pane (see "Start hold"). The task list follows byre's live state; the tab fetches the project's `TODO.md` when it opens, when the right pane moves to another project, when the project list changes, when the SSE stream reconnects, and on `task.merged`; a change pushed to the default branch outside byre shows the next time one of those happens. ## Inbox diff --git a/internal/agents/leadtools.go b/internal/agents/leadtools.go index 142b234..86a7916 100644 --- a/internal/agents/leadtools.go +++ b/internal/agents/leadtools.go @@ -254,7 +254,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool { if err != nil { return "", err } - tasks, err := m.StartTodo(ctx, project, user, args.Title, m.modelOr(args.Model, l), leadActor(user.Login), args.Workflow) + tasks, err := m.StartTodo(ctx, project, user, args.Title, m.modelOr(args.Model, l), leadActor(user.Login), args.Workflow, false) if err != nil { return "", err } diff --git a/internal/agents/tasks.go b/internal/agents/tasks.go index ba3f06f..655ccbf 100644 --- a/internal/agents/tasks.go +++ b/internal/agents/tasks.go @@ -20,7 +20,7 @@ func (m *Manager) CreateTask(ctx context.Context, project api.Project, title, cr return m.createTask(ctx, project, api.Task{Title: title, CreatedBy: createdBy}, nil, base, actor) } -func (m *Manager) StartTodo(ctx context.Context, project api.Project, creator api.User, title, model, actor, workflowName string) ([]api.Task, error) { +func (m *Manager) StartTodo(ctx context.Context, project api.Project, creator api.User, title, model, actor, workflowName string, discuss bool) ([]api.Task, error) { if creator.GitName == "" || creator.GitEmail == "" { return nil, ErrNoGitIdentity } @@ -48,7 +48,7 @@ func (m *Manager) StartTodo(ctx context.Context, project api.Project, creator ap started := []api.Task{} if workflowName != "" { - started, err = m.StartWorkflow(ctx, project, creator, item.Title, project.DefaultBranch, actor, workflowName, todoPrompt(item), &item.Title) + started, err = m.StartWorkflow(ctx, project, creator, item.Title, project.DefaultBranch, actor, workflowName, todoPrompt(item, discuss), &item.Title) if err != nil { return nil, err } @@ -57,7 +57,7 @@ func (m *Manager) StartTodo(ctx context.Context, project api.Project, creator ap if err != nil { return nil, err } - _, err = m.create(ctx, task, creator, todoPrompt(item), model, actor, nil) + _, err = m.create(ctx, task, creator, todoPrompt(item, discuss), model, actor, nil) if err != nil { return nil, fmt.Errorf("task %s created, but its agent did not start: %w", task.Id, err) } @@ -69,9 +69,13 @@ func (m *Manager) StartTodo(ctx context.Context, project api.Project, creator ap return started, nil } -func todoPrompt(item api.TodoItem) string { - return fmt.Sprintf("Work on this item from %[1]s at the repo root:\n\n%[2]s\n\nWhen the work is done, remove this item from %[1]s in this worktree, so the removal lands in the same merge as the work.", +func todoPrompt(item api.TodoItem, discuss bool) string { + p := fmt.Sprintf("Work on this item from %[1]s at the repo root:\n\n%[2]s\n\nWhen the work is done, remove this item from %[1]s in this worktree, so the removal lands in the same merge as the work.", todo.File, todo.Markdown(item)) + if !discuss { + return p + } + return p + "\n\nThe human wants to talk this item through before any of it is built. Read what you need to understand it, then ask them about its open questions and your proposed approach with ask_human, and change nothing until they have answered." } func (m *Manager) createTask(ctx context.Context, project api.Project, t api.Task, frozen *store.FrozenWorkflow, base, actor string) (api.Task, error) { diff --git a/internal/api/api.gen.go b/internal/api/api.gen.go index 5057092..0729182 100644 --- a/internal/api/api.gen.go +++ b/internal/api/api.gen.go @@ -950,7 +950,9 @@ type TodoItem struct { // TodoStart defines model for TodoStart. type TodoStart struct { - Model *string `json:"model,omitempty"` + // Discuss Tell the agent the human wants to talk the item through, so it asks before changing anything. + Discuss *bool `json:"discuss,omitempty"` + Model *string `json:"model,omitempty"` // Title The title of the item to start. Title string `json:"title"` @@ -2897,177 +2899,178 @@ 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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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/server/server.go b/internal/server/server.go index 2c2317d..228bfcb 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -327,7 +327,7 @@ func (s *Server) StartTodoItem(w http.ResponseWriter, r *http.Request, projectID model = *req.Model } - tasks, err := s.agents.StartTodo(r.Context(), p, u, req.Title, model, u.Login, "") + tasks, err := s.agents.StartTodo(r.Context(), p, u, req.Title, model, u.Login, "", req.Discuss != nil && *req.Discuss) if err != nil { writeAgentError(w, err) return diff --git a/web/dist/project.js b/web/dist/project.js index f6287a9..5b9230d 100644 --- a/web/dist/project.js +++ b/web/dist/project.js @@ -33,12 +33,12 @@ export function mountProject(root) { void load(p.id); } }; - const start = async (project, item) => { + const start = async (project, item, discuss) => { const key = `${project.id}\n${item.title}`; starting.add(key); render(); try { - await post("/api/projects/{projectId}/todo/tasks", { path: { projectId: project.id }, body: { title: item.title, model: models[0] } }); + await post("/api/projects/{projectId}/todo/tasks", { path: { projectId: project.id }, body: { title: item.title, model: models[0], discuss } }); } catch (err) { void showAlert(errorText(err)); @@ -142,9 +142,11 @@ function todoBlock(project, todo, active, starting, start) { } else { const busy = starting.has(`${project.id}\n${item.title}`); - const button = h("button", { disabled: busy }, busy ? "Starting…" : "Start"); - button.onclick = () => void start(project, item); - action = button; + const startButton = h("button", { disabled: busy, title: "Start a task that gets straight to work" }, busy ? "Starting…" : "Start"); + startButton.onclick = () => void start(project, item, false); + const discussButton = h("button", { disabled: busy, title: "Start a task that talks it through with you before changing anything" }, "Discuss"); + discussButton.onclick = () => void start(project, item, true); + action = h("span", { class: "todo-buttons" }, startButton, discussButton); } list.append(h("li", { class: task && task.id === state.selectedTaskId ? "selected" : "", style: task ? taskStyle(task.id) : "" }, h("div", { class: "todo-head" }, h("span", { class: task ? "todo-title task-name" : "todo-title" }, item.title), action), item.body && markdown(item.body, "md todo-body"))); } diff --git a/web/dist/project.js.map b/web/dist/project.js.map index a79cf13..d163b8a 100644 --- a/web/dist/project.js.map +++ b/web/dist/project.js.map @@ -1 +1 @@ -{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/dist/todolink.js b/web/dist/todolink.js index 5a29a0d..91da9f4 100644 --- a/web/dist/todolink.js +++ b/web/dist/todolink.js @@ -35,12 +35,11 @@ function fill(el, model) { titleEl.classList.remove("task-name"); const key = `${projectId}\n${title}`; const busy = starting.has(key); - const button = h("button", { disabled: busy }, busy ? "Starting…" : "Start"); - button.onclick = async () => { + const start = async (discuss) => { starting.add(key); fill(el, model); try { - await post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model } }); + await post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model, discuss } }); } catch (err) { void showAlert(errorText(err)); @@ -48,6 +47,10 @@ function fill(el, model) { starting.delete(key); fill(el, model); }; - replace(action, button); + const startButton = h("button", { disabled: busy, title: "Start a task that gets straight to work" }, busy ? "Starting…" : "Start"); + startButton.onclick = () => void start(false); + const discussButton = h("button", { disabled: busy, title: "Start a task that talks it through with you before changing anything" }, "Discuss"); + discussButton.onclick = () => void start(true); + replace(action, startButton, " ", discussButton); } //# sourceMappingURL=todolink.js.map \ No newline at end of file diff --git a/web/dist/todolink.js.map b/web/dist/todolink.js.map index 39551c0..d44f7ff 100644 --- a/web/dist/todolink.js.map +++ b/web/dist/todolink.js.map @@ -1 +1 @@ -{"version":3,"file":"todolink.js","sourceRoot":"","sources":["../src/todolink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;AAEnC,MAAM,UAAU,QAAQ,CAAC,SAAiB,EAAE,KAAa,EAAE,QAAgB;IACzE,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,GAAG,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;AAC3K,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAiB,EAAE,KAAa;IAC5D,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,gBAAgB,CAAc,YAAY,CAAC,EAAE,CAAC;QAClE,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CAAC,EAAe,EAAE,KAAa;IAC1C,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAE,CAAC;IACzC,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAE,CAAC;IACnC,MAAM,MAAM,GAAG,EAAE,CAAC,aAAa,CAAc,cAAc,CAAE,CAAC;IAC9D,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAc,aAAa,CAAE,CAAC;IAC9D,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,CAAC;IAE5G,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACnC,OAAO,CACL,MAAM,EACN,CAAC,CACC,GAAG,EACH;YACE,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,UAAU,IAAI,CAAC,EAAE,EAAE;YACzB,OAAO,EAAE,CAAC,CAAa,EAAE,EAAE;gBACzB,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrB,CAAC;SACF,EACD,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,IAAI,EAAE,KAAK,IAAI,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,YAAY,EAAE,CAAC,EACxF,IAAI,EAAE,KAAK,IAAI,UAAU,CAC1B,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAC5B,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,GAAG,SAAS,KAAK,KAAK,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC7E,MAAM,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE;QAC1B,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,sCAAsC,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACtG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,CAAC;QACD,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC1B,CAAC"} \ No newline at end of file +{"version":3,"file":"todolink.js","sourceRoot":"","sources":["../src/todolink.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 753593e..aa1b05e 100644 --- a/web/src/api.gen.ts +++ b/web/src/api.gen.ts @@ -892,6 +892,8 @@ export interface components { /** @description The title of the item to start. */ title: string; model?: string; + /** @description Tell the agent the human wants to talk the item through, so it asks before changing anything. */ + discuss?: boolean; }; Unmerged: { /** @description Commits on the task branch that aren't on the default branch. */ diff --git a/web/src/project.ts b/web/src/project.ts index d33d086..d9e55da 100644 --- a/web/src/project.ts +++ b/web/src/project.ts @@ -41,12 +41,12 @@ export function mountProject(root: HTMLElement): () => void { } }; - const start = async (project: Project, item: TodoItem) => { + const start = async (project: Project, item: TodoItem, discuss: boolean) => { const key = `${project.id}\n${item.title}`; starting.add(key); render(); try { - await post("/api/projects/{projectId}/todo/tasks", { path: { projectId: project.id }, body: { title: item.title, model: models[0] } }); + await post("/api/projects/{projectId}/todo/tasks", { path: { projectId: project.id }, body: { title: item.title, model: models[0], discuss } }); } catch (err) { void showAlert(errorText(err)); } @@ -93,7 +93,7 @@ export function mountProject(root: HTMLElement): () => void { }; } -function projectBlock(project: Project, todo: Todo | string | undefined, starting: Set, start: (p: Project, item: TodoItem) => Promise): HTMLElement { +function projectBlock(project: Project, todo: Todo | string | undefined, starting: Set, start: (p: Project, item: TodoItem, discuss: boolean) => Promise): HTMLElement { const active = (state.tasks.get(project.id) ?? []).filter((t) => t.status === "active"); return h( "section", @@ -139,7 +139,7 @@ function tasksBlock(active: Task[]): HTMLElement { ); } -function todoBlock(project: Project, todo: Todo | string | undefined, active: Task[], starting: Set, start: (p: Project, item: TodoItem) => Promise): HTMLElement[] { +function todoBlock(project: Project, todo: Todo | string | undefined, active: Task[], starting: Set, start: (p: Project, item: TodoItem, discuss: boolean) => Promise): HTMLElement[] { if (todo === undefined) { return [h("p", { class: "empty-row" }, "Loading…")]; } @@ -185,9 +185,11 @@ function todoBlock(project: Project, todo: Todo | string | undefined, active: Ta ); } else { const busy = starting.has(`${project.id}\n${item.title}`); - const button = h("button", { disabled: busy }, busy ? "Starting…" : "Start"); - button.onclick = () => void start(project, item); - action = button; + const startButton = h("button", { disabled: busy, title: "Start a task that gets straight to work" }, busy ? "Starting…" : "Start"); + startButton.onclick = () => void start(project, item, false); + const discussButton = h("button", { disabled: busy, title: "Start a task that talks it through with you before changing anything" }, "Discuss"); + discussButton.onclick = () => void start(project, item, true); + action = h("span", { class: "todo-buttons" }, startButton, discussButton); } list.append( diff --git a/web/src/todolink.ts b/web/src/todolink.ts index f4b0f8a..8cd8e68 100644 --- a/web/src/todolink.ts +++ b/web/src/todolink.ts @@ -49,17 +49,20 @@ function fill(el: HTMLElement, model: string): void { titleEl.classList.remove("task-name"); const key = `${projectId}\n${title}`; const busy = starting.has(key); - const button = h("button", { disabled: busy }, busy ? "Starting…" : "Start"); - button.onclick = async () => { + const start = async (discuss: boolean) => { starting.add(key); fill(el, model); try { - await post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model } }); + await post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model, discuss } }); } catch (err) { void showAlert(errorText(err)); } starting.delete(key); fill(el, model); }; - replace(action, button); + const startButton = h("button", { disabled: busy, title: "Start a task that gets straight to work" }, busy ? "Starting…" : "Start"); + startButton.onclick = () => void start(false); + const discussButton = h("button", { disabled: busy, title: "Start a task that talks it through with you before changing anything" }, "Discuss"); + discussButton.onclick = () => void start(true); + replace(action, startButton, " ", discussButton); } diff --git a/web/style.css b/web/style.css index 156ddff..4e504e7 100644 --- a/web/style.css +++ b/web/style.css @@ -460,7 +460,9 @@ a.task-link { font-size: 11px; } -.todo-head button { +.todo-buttons { + display: flex; + gap: 6px; flex-shrink: 0; }