From f5a495997f301cf3692d2de83d9c1d91bbbe8272 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sat, 17 Oct 2026 08:10:55 -0700 Subject: [PATCH] Add Start and Discuss buttons to lead suggestions --- api/openapi.yaml | 8 +- docs/macos.md | 2 +- docs/operations.md | 2 +- internal/agents/lead.go | 1 + internal/agents/tasks.go | 15 ++ internal/api/api.gen.go | 236 ++++++++++++++-------------- internal/server/server.go | 29 +++- mac/Sources/Byre/MarkdownView.swift | 30 +++- mac/Sources/Byre/Store.swift | 28 ++++ web/dist/markdown.js | 9 ++ web/dist/markdown.js.map | 2 +- web/dist/todolink.js | 46 ++++-- web/dist/todolink.js.map | 2 +- web/src/api.gen.ts | 6 +- web/src/markdown.ts | 8 + web/src/todolink.ts | 50 ++++-- 16 files changed, 318 insertions(+), 156 deletions(-) diff --git a/api/openapi.yaml b/api/openapi.yaml index b958f10..e9d1405 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -222,8 +222,8 @@ paths: post: operationId: createTask description: > - Creates the task's branch and worktree from the project's default branch, or with workflow, starts a run of - that workflow from it. + Creates the task's branch and worktree from the project's default branch, and with prompt starts its agent, or + with workflow, starts a run of that workflow from it. requestBody: required: true content: @@ -1149,6 +1149,10 @@ components: required: [title] properties: title: { type: string } + prompt: + type: string + description: Starts the task's agent with this as its first message, in the same request. Not with workflow. + model: { type: string, description: The agent's model when prompt is given. } workflow: type: string description: > diff --git a/docs/macos.md b/docs/macos.md index 04b7102..7ed46e9 100644 --- a/docs/macos.md +++ b/docs/macos.md @@ -105,7 +105,7 @@ Each view does what its TypeScript counterpart does, with the same text, refresh ## Markdown -`Markdown.swift` ports `markdown.ts` line for line into a block tree (paragraph, heading, list, choice list, choice grid, quote, rule, table, code, diff, details, diagram, image), because byre's dialect (choice markers, `
` sections, `#/task/` and `#/todo/` links, worktree image paths, `NO_REPLY`) matches no library. Inline content becomes an `AttributedString` with code, strong, emphasis and links. Links: `http` and `https` open in the default browser; `#/task/` focuses the task; `#/todo//` becomes the TODO link with its start and discuss actions or the task's state; anything else is plain text. +`Markdown.swift` ports `markdown.ts` line for line into a block tree (paragraph, heading, list, choice list, choice grid, quote, rule, table, code, diff, details, diagram, image), because byre's dialect (choice markers, `<details>` sections, `#/task/`, `#/todo/` and `#/suggest/` links, worktree image paths, `NO_REPLY`) matches no library. Inline content becomes an `AttributedString` with code, strong, emphasis and links. Links: `http` and `https` open in the default browser; `#/task/<id>` focuses the task; `#/todo/<project>/<title>` becomes the TODO link with its start and discuss actions or the task's state; `#/suggest/<project>/<title>/<brief>` becomes the same, its start creating the task with the brief and its discuss messaging the lead; anything else is plain text. ## Diagrams diff --git a/docs/operations.md b/docs/operations.md index f57db14..3059796 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -202,7 +202,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 (a question's signal also carries its text and the agent's recommendation, so the lead sees where the human departed from it), `task.created` (naming the TODO item it was started from, or a subtask's parent, if any), `task.merge_started` ("<task> is merging, started by <login>."), `task.merged`, `task.discarded`, `turn.ended` with `summary: true` ("<task> finished a turn:" with its `result` cut to 1500 characters), `task.workflow_stage` ("<task> started stage "<stage>" of workflow "<workflow>".") and `task.workflow_finished` ("<task> finished workflow "<workflow>":" with its output cut to 1500 characters), `review.started` ("<task> started a review of snapshot <n>."), `review.finished` ("<task> review of snapshot <n>:" with the review's summary, `change` and findings, or why it failed or was skipped; `reviewLine` in `internal/agents/review.go`), `user.message` on a task from a human (see "Pane lock"), and `task.state` ("<task> state: <from> → <to>.", or "<task> state: <to>." for a new task; see "Task state in the store"). The store hands `Observe` all of one transaction's events together, and they become one signal, its `task.state` lines first, so a turn's summary always arrives with the state its turn end left the task in. The human switching the right pane is not a signal. A signal caused by the lead itself (actor `<login> (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 `<login> (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, the turn isn't opened, so the scanner stays off, its partial message stays hidden, and its tool calls, subagents and thinking are rendered into an off-screen fragment instead of the transcript. The turn is released, inserting that fragment where the turn belongs, when it draws anything else: a real message, a note, or its own `turn.ended` when it ends without `NO_REPLY`. When it ends in `NO_REPLY` while still held, the fragment is dropped, so nothing of the turn ever appears; a turn that draws a real message anywhere in it keeps all of it, even when a later message is `NO_REPLY`. - **Tools.** `list_tasks` (each project's active tasks with their state, each subtask noting its parent, 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`; closed tasks too), `search_closed_tasks` (see "Closing a task"), `read_inbox`, `read_status` (the `GET /api/admin/status` body as JSON, built by the same `Server.status`, which the server hands `agents.New`), `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), `create_project` (`name` and `repo_path`, created as the user by the same `Server.createProject` as `POST /api/projects`, which the server hands `agents.New`, so it publishes the same `project.created` event, and returned as JSON), `interrupt`, `compact_task`, `take_snapshot` (see "Snapshots"), `merge_task` (optional `target`: `main`, or `parent` for a subtask, see "Subtasks"), `discard_task`, `show`, `compact_self`, the note tools (see "Notes") 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 `<login> (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/<id>`, `#/project/<id>`, 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` or `finalizing` set), or its selected tab is `inbox` and the task has no open items, or the human is waiting on the task's agent (`Manager.paneWaiting`): the selected tab is `transcript`, the task's implementer session is running, the page reports no unsent text in the pane, and either the `user.message` that started the running turn came from the user after the pane last moved, or the pane last moved 10 seconds ago or more (`watchHold`). The pane's last move is the last `PUT /api/me/focus` or `show` that set it (`Manager.paneMoved`, in memory, so a restart counts as long ago). For the user's own message, unsent text reported before the turn started doesn't count, since the page's report of the composer emptying on send can arrive after the message does. A `user.message` on a task from a human (not `byre`, an agent or a lead) signals every lead "<actor> sent <task> a message; its agent is working on it.", and the sender's own lead, when its pane shows that task and is waiting that way, also gets "Your right pane is free: the human is waiting on <task>'s agent." Each `PUT /api/me/focus` from the user starts a 10-second timer (`endWatchHold`); when it fires, if the pane hasn't moved since, the page still reports the human in it, the user hasn't messaged the task since the move (that already freed it, above), and the pane is waiting that way, the lead gets the signal "Your right pane is free: the human has watched <task>'s agent work for 10 seconds without typing." The lead's own `show` starts no timer. 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: <task> 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/<project_id>/<URL-encoded title>`; Markdown views draw that (`web/src/todolink.ts`) as the title followed by small `start` and `discuss` buttons, styled like a snapshot row's, 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` and `drafting` whenever either changes: `focused` is true while the browser window has focus and the focused element is inside the right pane, and `drafting` while any textarea in the right pane (other than xterm's helper) holds non-blank text, checked on focus changes, `input` and `submit`. 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 both flags and the time of the last report in memory per user (`Manager.paneFocus`, `Manager.paneReported`), so they start false after a restart until the page resends them. +- **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` or `finalizing` set), or its selected tab is `inbox` and the task has no open items, or the human is waiting on the task's agent (`Manager.paneWaiting`): the selected tab is `transcript`, the task's implementer session is running, the page reports no unsent text in the pane, and either the `user.message` that started the running turn came from the user after the pane last moved, or the pane last moved 10 seconds ago or more (`watchHold`). The pane's last move is the last `PUT /api/me/focus` or `show` that set it (`Manager.paneMoved`, in memory, so a restart counts as long ago). For the user's own message, unsent text reported before the turn started doesn't count, since the page's report of the composer emptying on send can arrive after the message does. A `user.message` on a task from a human (not `byre`, an agent or a lead) signals every lead "<actor> sent <task> a message; its agent is working on it.", and the sender's own lead, when its pane shows that task and is waiting that way, also gets "Your right pane is free: the human is waiting on <task>'s agent." Each `PUT /api/me/focus` from the user starts a 10-second timer (`endWatchHold`); when it fires, if the pane hasn't moved since, the page still reports the human in it, the user hasn't messaged the task since the move (that already freed it, above), and the pane is waiting that way, the lead gets the signal "Your right pane is free: the human has watched <task>'s agent work for 10 seconds without typing." The lead's own `show` starts no timer. 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: <task> 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/<project_id>/<URL-encoded title>`; Markdown views draw that (`web/src/todolink.ts`) as the title followed by small `start` and `discuss` buttons, styled like a snapshot row's, 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. When the lead suggests new work that isn't in TODO.md, its guidance tells it to write a link to `#/suggest/<project_id>/<URL-encoded title>/<URL-encoded brief>`, drawn by the same code with `start` and `discuss` buttons: `start` calls `POST /api/projects/{id}/tasks` with the title, the brief as `prompt` and the first model, which checks the user's git identity, creates the task and starts its agent in one request, with no lead turn in between; `discuss` sends the lead `POST /api/me/lead/messages` asking to discuss the suggestion, quoting its title and brief (with the first model only when the user has no live lead session). Once an active task in that project has the suggestion's title, it shows that task's state the same way. 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` and `drafting` whenever either changes: `focused` is true while the browser window has focus and the focused element is inside the right pane, and `drafting` while any textarea in the right pane (other than xterm's helper) holds non-blank text, checked on focus changes, `input` and `submit`. 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 both flags and the time of the last report in memory per user (`Manager.paneFocus`, `Manager.paneReported`), so they start false after a restart until the page resends them. - **Move hold.** Each `PUT /api/me/focus` from the user (switching task or tab, by any means: the switcher, a tab, a link, a notification, or the page's own switch to Inbox when a question arrives) records the time in `Manager.humanMoved`, and for 10 seconds after it (`moveHold`) every `show` that would change the view is refused, whatever the pane lock above would allow, with an error giving how long ago the move was. A `show` of what the pane already shows still applies its tab order. When the 10 seconds pass without another move by the user (`endMoveHold`, on a timer), byre clears it and sends the lead the signal "The move hold is over: …", every time, whether or not a `show` was refused; its guidance tells it to show what it held back if the pane's other rules allow, or reply `NO_REPLY`. It is in memory, so a restart clears 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 a quarter of 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. diff --git a/internal/agents/lead.go b/internal/agents/lead.go index 93667f3..3d5bdcf 100644 --- a/internal/agents/lead.go +++ b/internal/agents/lead.go @@ -18,6 +18,7 @@ const leadGuidance = `You are the human's lead agent in byre, shown in the left - Signals: byre sends you, as messages from byre, what happens across tasks: questions and errors that task agents file, turns they finish with their final message, questions the human answered, tasks created, reviews started and finished, starting to merge, merged or discarded, and every change of a task's state, as "<task> state: <before> → <now>." listed first among what happened at the same moment. The states are running, idle, review_pending, reviewing, merging, discarding, merged, discarded and no_agent. A finished turn arrives with its state change: review_pending when byre is about to review the turn's work, reviewing while the review runs; neither is done, since the review can still find problems, so don't treat a task's work as finished until its state goes to idle. Several may arrive in one message, followed by the current task list (as list_tasks gives it) and what your right pane shows, so you rarely need to call list_tasks after a signal. The human doesn't see signals. Messages from the human arrive separately. - Don't respond to what the human just did. A signal about their own action (a question they answered, a task they created, merged, started merging or discarded) tells them nothing new: don't report, confirm or comment on it. Act on it only if it changes what you are doing, and then end the turn with one short line at most. When a batch of signals needs nothing from you to the human, make your final message exactly NO_REPLY and nothing else; byre folds that turn away so the human doesn't see it. - "Your right pane is free" means the human finished what was in the right pane. Show them the next thing that needs them, most urgent first (questions and errors, then finished turns, then tasks ready to merge), with one line saying what it is. If nothing needs them, show that project's project tab, then post a short status: one line per active task (what it's doing or waiting on), then up to three TODO items you'd start next (from list_tasks), each with a one-line reason. Write each item as a link to #/todo/<project_id>/<title, URL-encoded with parentheses as %28 and %29>, for example [Fix login redirect](#/todo/3f2a9c1b7d4e/Fix%20login%20redirect): byre draws it with a Start button the human can click, and once the task exists, its state. Start one with start_todo only when the human picks it. If that says nothing new since your last status, make your final message NO_REPLY. +- Whenever you suggest new work that isn't in TODO.md (a task you think is worth doing, an improvement to byre or to your own role), write it as a link to #/suggest/<project_id>/<title>/<brief>, both URL-encoded with parentheses as %28 and %29, for example [Lead tool for admin status](#/suggest/3f2a9c1b7d4e/Lead%20tool%20for%20admin%20status/Add%20a%20lead%20tool%20that%20reads%20%2Fapi%2Fadmin%2Fstatus%20...). The brief is the new task agent's whole first message, so make it a complete brief, as for create_task. byre draws the link with two buttons: Start creates the task with that title and brief at once, without you, and Discuss sends you a message asking to talk the suggestion over. Once an active task has that title, it shows the task's state instead. Don't ask whether to start a suggestion; the buttons do that. - Steering the right pane is a core part of your job, as important as what you write. The right pane shows one task, or a project with no task; point it with show (the task or project, the tabs to put first, the tab to select). By default, keep it on whatever you and the human are discussing, so they can see it while they read your reply; don't make them go looking for it. Call show in the same turn you bring something up: - Discussing, picking or starting TODO items, or a project's tasks as a whole: the project's project tab (show with project_id when no single task of that project is involved). - A question that needs the human: that task's inbox tab, with one line naming it and what you recommend. diff --git a/internal/agents/tasks.go b/internal/agents/tasks.go index 901b7e8..c9cd380 100644 --- a/internal/agents/tasks.go +++ b/internal/agents/tasks.go @@ -18,6 +18,21 @@ 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) StartTask(ctx context.Context, project api.Project, creator api.User, title, prompt, model string) (api.Task, error) { + if creator.GitName == "" || creator.GitEmail == "" { + return api.Task{}, ErrNoGitIdentity + } + task, err := m.CreateTask(ctx, project, title, creator.Login, project.DefaultBranch, creator.Login) + if err != nil { + return api.Task{}, err + } + _, err = m.create(ctx, task, creator, prompt, model, creator.Login, nil) + if err != nil { + return api.Task{}, fmt.Errorf("task %s created, but its agent did not start: %w", task.Id, err) + } + return task, nil +} + 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 diff --git a/internal/api/api.gen.go b/internal/api/api.gen.go index a95c153..9925775 100644 --- a/internal/api/api.gen.go +++ b/internal/api/api.gen.go @@ -1153,7 +1153,12 @@ type TaskChanges struct { // TaskCreate defines model for TaskCreate. type TaskCreate struct { - Title string `json:"title"` + // Model The agent's model when prompt is given. + Model *string `json:"model,omitempty"` + + // Prompt Starts the task's agent with this as its first message, in the same request. Not with workflow. + Prompt *string `json:"prompt,omitempty"` + Title string `json:"title"` // Workflow The name of a saved workflow to run instead of creating one task with no agent: each stage with no after stages becomes its own task, titled "<title>: <stage>", with the title as the run's brief. The response is the first of those tasks. Workflow *string `json:"workflow,omitempty"` @@ -3583,120 +3588,121 @@ var swaggerSpec = []string{ "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", + "uSK4Ozxjb/vP3n1+r/YeHz/+vwAAAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/server/server.go b/internal/server/server.go index f65e42e..094bec4 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -286,6 +286,10 @@ func (s *Server) CreateTask(w http.ResponseWriter, r *http.Request, projectID st } if req.Workflow != nil { + if req.Prompt != nil { + writeError(w, http.StatusBadRequest, errors.New("prompt can't be given with workflow")) + return + } u, err := s.store.GetUser(r.Context(), actor(r)) if err != nil { writeStoreError(w, err) @@ -300,7 +304,30 @@ func (s *Server) CreateTask(w http.ResponseWriter, r *http.Request, projectID st return } - t, err := s.agents.CreateTask(r.Context(), p, req.Title, actor(r), p.DefaultBranch, actor(r)) + if req.Prompt == nil { + t, err := s.agents.CreateTask(r.Context(), p, req.Title, actor(r), p.DefaultBranch, actor(r)) + if err != nil { + writeAgentError(w, err) + return + } + writeJSON(w, http.StatusCreated, t) + return + } + + if strings.TrimSpace(*req.Prompt) == "" { + writeError(w, http.StatusBadRequest, errors.New("prompt is empty")) + return + } + u, err := s.store.GetUser(r.Context(), actor(r)) + if err != nil { + writeStoreError(w, err) + return + } + model := "" + if req.Model != nil { + model = *req.Model + } + t, err := s.agents.StartTask(r.Context(), p, u, req.Title, *req.Prompt, model) if err != nil { writeAgentError(w, err) return diff --git a/mac/Sources/Byre/MarkdownView.swift b/mac/Sources/Byre/MarkdownView.swift index 2e0eae1..51cf7c5 100644 --- a/mac/Sources/Byre/MarkdownView.swift +++ b/mac/Sources/Byre/MarkdownView.swift @@ -21,6 +21,14 @@ enum AppLink { c.queryItems = [URLQueryItem(name: "project", value: projectId), URLQueryItem(name: "title", value: title), URLQueryItem(name: "discuss", value: discuss ? "1" : "0")] return c.url! } + + static func suggest(_ projectId: String, _ title: String, _ brief: String, discuss: Bool) -> URL { + var c = URLComponents() + c.scheme = "byre-app" + c.host = "suggest" + c.queryItems = [URLQueryItem(name: "project", value: projectId), URLQueryItem(name: "title", value: title), URLQueryItem(name: "brief", value: brief), URLQueryItem(name: "discuss", value: discuss ? "1" : "0")] + return c.url! + } } @MainActor @@ -34,6 +42,12 @@ func openAppLink(_ url: URL, _ store: Store, _ overlays: Overlays) -> OpenURLAct store.focusTask(q["id"] ?? "") case "todo": store.startTodo(q["project"] ?? "", q["title"] ?? "", discuss: q["discuss"] == "1", overlays) + case "suggest": + if q["discuss"] == "1" { + store.discussSuggestion(q["title"] ?? "", brief: q["brief"] ?? "", overlays) + } else { + store.startSuggestion(q["project"] ?? "", q["title"] ?? "", brief: q["brief"] ?? "", overlays) + } default: break } @@ -43,6 +57,7 @@ func openAppLink(_ url: URL, _ store: Store, _ overlays: Overlays) -> OpenURLAct private let httpLink = Re(#"^https?://"#, caseless: true) private let taskHref = Re(#"^#/task/(\w+)(/\w+)?$"#) private let todoHref = Re(#"^#/todo/(\w+)/(.+)$"#) +private let suggestHref = Re(#"^#/suggest/(\w+)/([^/]+)/(.+)$"#) @MainActor struct InlineRenderer { @@ -140,14 +155,18 @@ struct InlineRenderer { return } if let m = todoHref.exec(href), let title = m[2]!.removingPercentEncoding { - todo(m[1]!, title, inner, style, &out) + todo(m[1]!, title, nil, inner, style, &out) + return + } + if let m = suggestHref.exec(href), let title = m[2]!.removingPercentEncoding, let brief = m[3]!.removingPercentEncoding { + todo(m[1]!, title, brief, inner, style, &out) return } render(inner, style, &out) } - private func todo(_ projectId: String, _ title: String, _ inner: [MDInline], _ style: Style, _ out: inout [MDSegment]) { - let task = (store.tasks[projectId] ?? []).first { $0.status == .active && $0.todoItem == title } + private func todo(_ projectId: String, _ title: String, _ brief: String?, _ inner: [MDInline], _ style: Style, _ out: inout [MDSegment]) { + let task = (store.tasks[projectId] ?? []).first { $0.status == .active && (brief == nil ? $0.todoItem == title : $0.title == title) } var s = style if let task { s.color = taskPalette[task.color] @@ -166,9 +185,10 @@ struct InlineRenderer { append(run("starting…", Style(color: Palette.muted, small: true)), &out) return } - append(run("start", Style(link: AppLink.todo(projectId, title, discuss: false), color: Palette.accent, small: true)), &out) + let link = { (discuss: Bool) in brief.map { AppLink.suggest(projectId, title, $0, discuss: discuss) } ?? AppLink.todo(projectId, title, discuss: discuss) } + append(run("start", Style(link: link(false), color: Palette.accent, small: true)), &out) append(run(" ", style), &out) - append(run("discuss", Style(link: AppLink.todo(projectId, title, discuss: true), color: Palette.accent, small: true)), &out) + append(run("discuss", Style(link: link(true), color: Palette.accent, small: true)), &out) } } diff --git a/mac/Sources/Byre/Store.swift b/mac/Sources/Byre/Store.swift index 775e5c9..df3804f 100644 --- a/mac/Sources/Byre/Store.swift +++ b/mac/Sources/Byre/Store.swift @@ -91,6 +91,34 @@ final class Store { } } + func startSuggestion(_ projectId: String, _ title: String, brief: String, _ overlays: Overlays) { + let key = "\(projectId)\n\(title)" + if todoStarting.contains(key) { + return + } + todoStarting.insert(key) + Task { + do { + _ = try await api.client.createTask(path: .init(projectId: projectId), body: .json(.init(title: title, prompt: brief, model: models[0]))).created + } catch { + overlays.showAlert(errorText(error)) + } + todoStarting.remove(key) + } + } + + func discussSuggestion(_ title: String, brief: String, _ overlays: Overlays) { + let lead = currentLead() + let live = lead != nil && lead!.state != .completed + Task { + do { + _ = try await api.client.messageLead(body: .json(.init(text: "Let's discuss your suggestion \"\(title)\" before starting it:\n\n\(brief)", model: live ? nil : models[0]))).accepted + } catch { + overlays.showAlert(errorText(error)) + } + } + } + var transcript: [ByreEvent] { selectedFeed?.events ?? [] } diff --git a/web/dist/markdown.js b/web/dist/markdown.js index 004591f..9e3c1d1 100644 --- a/web/dist/markdown.js +++ b/web/dist/markdown.js @@ -300,6 +300,15 @@ function link(href, children) { return h("span", {}, ...children); } } + const suggest = /^#\/suggest\/(\w+)\/([^/]+)\/(.+)$/.exec(href); + if (suggest) { + try { + return todoLink(suggest[1], decodeURIComponent(suggest[2]), children, decodeURIComponent(suggest[3])); + } + catch { + return h("span", {}, ...children); + } + } if (href.startsWith("#/")) { return h("a", { href }, ...children); } diff --git a/web/dist/markdown.js.map b/web/dist/markdown.js.map index 7bd89d0..6c2e9c4 100644 --- a/web/dist/markdown.js.map +++ b/web/dist/markdown.js.map @@ -1 +1 @@ -{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.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 824fd0a..4a8aed0 100644 --- a/web/dist/todolink.js +++ b/web/dist/todolink.js @@ -1,10 +1,14 @@ import { post } from "./api.js"; import { errorText, h, replace, showAlert } from "./dom.js"; -import { currentSession, focusTask, state } from "./state.js"; +import { currentLead, currentSession, focusTask, state } from "./state.js"; import { taskStyle } from "./taskcolor.js"; -const starting = new Set(); -export function todoLink(projectId, title, children) { - return h("span", { class: "todo-link", data: { project: projectId, title } }, h("span", { class: "todo-title" }, ...children), " ", h("span", { class: "todo-action" })); +const busy = new Map(); +export function todoLink(projectId, title, children, brief) { + const data = { project: projectId, title }; + if (brief !== undefined) { + data["brief"] = brief; + } + return h("span", { class: "todo-link", data }, h("span", { class: "todo-title" }, ...children), " ", h("span", { class: "todo-action" })); } export function fillTodoLinks(root, model) { for (const el of root.querySelectorAll(".todo-link")) { @@ -14,9 +18,10 @@ export function fillTodoLinks(root, model) { function fill(el, model) { const projectId = el.dataset["project"]; const title = el.dataset["title"]; + const brief = el.dataset["brief"]; const action = el.querySelector(".todo-action"); const titleEl = el.querySelector(".todo-title"); - const task = (state.tasks.get(projectId) ?? []).find((t) => t.status === "active" && t.todo_item === title); + const task = (state.tasks.get(projectId) ?? []).find((t) => t.status === "active" && (brief === undefined ? t.todo_item === title : t.title === title)); if (task) { const sess = currentSession(task.id); el.setAttribute("style", taskStyle(task.id)); @@ -34,23 +39,36 @@ function fill(el, model) { el.removeAttribute("style"); titleEl.classList.remove("task-name"); const key = `${projectId}\n${title}`; - const busy = starting.has(key); - const start = async (discuss) => { - starting.add(key); + const label = busy.get(key); + const run = async (busyLabel, act) => { + busy.set(key, busyLabel); fill(el, model); try { - await post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model, discuss } }); + await act(); } catch (err) { void showAlert(errorText(err)); } - starting.delete(key); + busy.delete(key); fill(el, model); }; - 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 discusses it with you in chat before building anything" }, "discuss"); - discussButton.onclick = () => void start(true); + if (brief === undefined) { + const start = (discuss) => run(discuss ? "discuss" : "start", () => post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model, discuss } })); + const startButton = h("button", { disabled: !!label, title: "Start a task that gets straight to work" }, label === "start" ? "starting…" : "start"); + startButton.onclick = () => void start(false); + const discussButton = h("button", { disabled: !!label, title: "Start a task that discusses it with you in chat before building anything" }, label === "discuss" ? "starting…" : "discuss"); + discussButton.onclick = () => void start(true); + replace(action, startButton, discussButton); + return; + } + const startButton = h("button", { disabled: !!label, title: "Start a task with the lead's brief" }, label === "start" ? "starting…" : "start"); + startButton.onclick = () => void run("start", () => post("/api/projects/{projectId}/tasks", { path: { projectId }, body: { title, prompt: brief, model } })); + const discussButton = h("button", { disabled: !!label, title: "Ask your lead to talk it over in chat" }, label === "discuss" ? "sending…" : "discuss"); + discussButton.onclick = () => void run("discuss", () => { + const lead = currentLead(); + const live = lead !== undefined && lead.state !== "completed"; + return post("/api/me/lead/messages", { body: { text: `Let's discuss your suggestion "${title}" before starting it:\n\n${brief}`, model: live ? undefined : model } }); + }); 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 45ceff2..1c16af8 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":"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"} \ 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 c974cd6..f347cad 100644 --- a/web/src/api.gen.ts +++ b/web/src/api.gen.ts @@ -218,7 +218,7 @@ export interface paths { }; get: operations["listTasks"]; put?: never; - /** @description Creates the task's branch and worktree from the project's default branch, or with workflow, starts a run of that workflow from it. */ + /** @description Creates the task's branch and worktree from the project's default branch, and with prompt starts its agent, or with workflow, starts a run of that workflow from it. */ post: operations["createTask"]; delete?: never; options?: never; @@ -1097,6 +1097,10 @@ export interface components { }; TaskCreate: { title: string; + /** @description Starts the task's agent with this as its first message, in the same request. Not with workflow. */ + prompt?: string; + /** @description The agent's model when prompt is given. */ + model?: string; /** @description The name of a saved workflow to run instead of creating one task with no agent: each stage with no after stages becomes its own task, titled "<title>: <stage>", with the title as the run's brief. The response is the first of those tasks. */ workflow?: string; }; diff --git a/web/src/markdown.ts b/web/src/markdown.ts index add752b..f22633f 100644 --- a/web/src/markdown.ts +++ b/web/src/markdown.ts @@ -339,6 +339,14 @@ function link(href: string, children: Node[]): Node { return h("span", {}, ...children); } } + const suggest = /^#\/suggest\/(\w+)\/([^/]+)\/(.+)$/.exec(href); + if (suggest) { + try { + return todoLink(suggest[1]!, decodeURIComponent(suggest[2]!), children, decodeURIComponent(suggest[3]!)); + } catch { + return h("span", {}, ...children); + } + } if (href.startsWith("#/")) { return h("a", { href }, ...children); } diff --git a/web/src/todolink.ts b/web/src/todolink.ts index c43d4e0..7476792 100644 --- a/web/src/todolink.ts +++ b/web/src/todolink.ts @@ -1,12 +1,16 @@ import { post } from "./api.js"; import { errorText, h, replace, showAlert } from "./dom.js"; -import { currentSession, focusTask, state } from "./state.js"; +import { currentLead, currentSession, focusTask, state } from "./state.js"; import { taskStyle } from "./taskcolor.js"; -const starting = new Set<string>(); +const busy = new Map<string, string>(); -export function todoLink(projectId: string, title: string, children: Node[]): HTMLElement { - return h("span", { class: "todo-link", data: { project: projectId, title } }, h("span", { class: "todo-title" }, ...children), " ", h("span", { class: "todo-action" })); +export function todoLink(projectId: string, title: string, children: Node[], brief?: string): HTMLElement { + const data: Record<string, string> = { project: projectId, title }; + if (brief !== undefined) { + data["brief"] = brief; + } + return h("span", { class: "todo-link", data }, h("span", { class: "todo-title" }, ...children), " ", h("span", { class: "todo-action" })); } export function fillTodoLinks(root: ParentNode, model: string): void { @@ -18,9 +22,10 @@ export function fillTodoLinks(root: ParentNode, model: string): void { function fill(el: HTMLElement, model: string): void { const projectId = el.dataset["project"]!; const title = el.dataset["title"]!; + const brief = el.dataset["brief"]; const action = el.querySelector<HTMLElement>(".todo-action")!; const titleEl = el.querySelector<HTMLElement>(".todo-title")!; - const task = (state.tasks.get(projectId) ?? []).find((t) => t.status === "active" && t.todo_item === title); + const task = (state.tasks.get(projectId) ?? []).find((t) => t.status === "active" && (brief === undefined ? t.todo_item === title : t.title === title)); if (task) { const sess = currentSession(task.id); @@ -48,21 +53,38 @@ function fill(el: HTMLElement, model: string): void { el.removeAttribute("style"); titleEl.classList.remove("task-name"); const key = `${projectId}\n${title}`; - const busy = starting.has(key); - const start = async (discuss: boolean) => { - starting.add(key); + const label = busy.get(key); + const run = async (busyLabel: string, act: () => Promise<unknown>) => { + busy.set(key, busyLabel); fill(el, model); try { - await post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model, discuss } }); + await act(); } catch (err) { void showAlert(errorText(err)); } - starting.delete(key); + busy.delete(key); fill(el, model); }; - 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 discusses it with you in chat before building anything" }, "discuss"); - discussButton.onclick = () => void start(true); + + if (brief === undefined) { + const start = (discuss: boolean) => run(discuss ? "discuss" : "start", () => post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model, discuss } })); + const startButton = h("button", { disabled: !!label, title: "Start a task that gets straight to work" }, label === "start" ? "starting…" : "start"); + startButton.onclick = () => void start(false); + const discussButton = h("button", { disabled: !!label, title: "Start a task that discusses it with you in chat before building anything" }, label === "discuss" ? "starting…" : "discuss"); + discussButton.onclick = () => void start(true); + replace(action, startButton, discussButton); + return; + } + + const startButton = h("button", { disabled: !!label, title: "Start a task with the lead's brief" }, label === "start" ? "starting…" : "start"); + startButton.onclick = () => + void run("start", () => post("/api/projects/{projectId}/tasks", { path: { projectId }, body: { title, prompt: brief, model } })); + const discussButton = h("button", { disabled: !!label, title: "Ask your lead to talk it over in chat" }, label === "discuss" ? "sending…" : "discuss"); + discussButton.onclick = () => + void run("discuss", () => { + const lead = currentLead(); + const live = lead !== undefined && lead.state !== "completed"; + return post("/api/me/lead/messages", { body: { text: `Let's discuss your suggestion "${title}" before starting it:\n\n${brief}`, model: live ? undefined : model } }); + }); replace(action, startButton, discussButton); }