openapi: 3.0.3 info: title: byre version: 0.0.0 paths: /api/me: get: operationId: getMe responses: "200": description: The calling user. content: application/json: schema: { $ref: "#/components/schemas/User" } put: operationId: updateMe requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/UserUpdate" } responses: "200": description: The updated user. content: application/json: schema: { $ref: "#/components/schemas/User" } "400": { $ref: "#/components/responses/Error" } /api/me/notifications: put: operationId: updateNotificationPrefs description: Sets which new inbox items notify the calling user in their open byre pages. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/NotificationPrefs" } responses: "200": description: The updated user. content: application/json: schema: { $ref: "#/components/schemas/User" } "400": { $ref: "#/components/responses/Error" } /api/me/lead/sessions: get: operationId: listLeadSessions description: The calling user's lead agent sessions, oldest first. A compaction completes one and starts the next. responses: "200": description: The sessions. content: application/json: schema: type: array items: { $ref: "#/components/schemas/AgentSession" } /api/me/lead/messages: post: operationId: messageLead description: > Sends a message to the calling user's lead agent, starting a lead session when there is none. While the lead is mid-turn the message is held and sent as its next turn. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/MessageCreate" } responses: "202": description: The lead session the message went to or is held for. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "400": { $ref: "#/components/responses/Error" } /api/me/lead/notes: get: operationId: listLeadNotes description: What the calling user's lead agent has noted about how they work, oldest first. The lead keeps them with its remember and forget tools. responses: "200": description: The notes. content: application/json: schema: type: array items: { $ref: "#/components/schemas/LeadNote" } /api/me/lead/notes/{noteId}: parameters: - { name: noteId, in: path, required: true, schema: { type: string } } delete: operationId: deleteLeadNote responses: "204": description: Deleted. "404": { $ref: "#/components/responses/Error" } /api/me/focus: get: operationId: getFocus responses: "200": description: What the calling user's right pane shows. content: application/json: schema: { $ref: "#/components/schemas/Focus" } put: operationId: setFocus description: Records the human switching the right pane's project, task or tab. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/Focus" } responses: "200": description: The stored focus. content: application/json: schema: { $ref: "#/components/schemas/Focus" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } /api/me/pane-focus: put: operationId: setPaneFocus description: Records whether the human is working in the right pane, and whether they have unsent text there. While they are working in it, the lead agent can move it only in the cases its show tool describes. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/PaneFocus" } responses: "204": description: Recorded. "400": { $ref: "#/components/responses/Error" } /api/projects: get: operationId: listProjects responses: "200": description: All projects. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Project" } post: operationId: createProject requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/ProjectCreate" } responses: "201": description: The new project. content: application/json: schema: { $ref: "#/components/schemas/Project" } "400": { $ref: "#/components/responses/Error" } /api/projects/{projectId}: parameters: - { name: projectId, in: path, required: true, schema: { type: string } } get: operationId: getProject responses: "200": description: The project. content: application/json: schema: { $ref: "#/components/schemas/Project" } "404": { $ref: "#/components/responses/Error" } /api/projects/{projectId}/tasks: parameters: - { name: projectId, in: path, required: true, schema: { type: string } } get: operationId: listTasks responses: "200": description: The project's tasks, newest first. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Task" } "404": { $ref: "#/components/responses/Error" } 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. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/TaskCreate" } responses: "201": description: The new task. content: application/json: schema: { $ref: "#/components/schemas/Task" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } /api/projects/{projectId}/todo: parameters: - { name: projectId, in: path, required: true, schema: { type: string } } get: operationId: getTodo description: The items of TODO.md at the root of the project's default branch, in file order. responses: "200": description: The items; exists is false when the default branch has no TODO.md. content: application/json: schema: { $ref: "#/components/schemas/Todo" } "404": { $ref: "#/components/responses/Error" } /api/projects/{projectId}/todo/tasks: parameters: - { name: projectId, in: path, required: true, schema: { type: string } } post: operationId: startTodoItem description: > Creates a task for a TODO.md item, recording the item as its todo_item, and starts its agent with the item as the first message. Refused while another active task has the same item. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/TodoStart" } responses: "201": description: The new task. content: application/json: schema: { $ref: "#/components/schemas/Task" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTask responses: "200": description: The task. content: application/json: schema: { $ref: "#/components/schemas/Task" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/workflow: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTaskWorkflow description: > The workflow the task froze when it was created, as it was then. Later edits and deletes of the workflow don't change it. responses: "200": description: The frozen workflow. content: application/json: schema: { $ref: "#/components/schemas/TaskWorkflow" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/unmerged: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getUnmerged description: What the task's worktree holds that its project's default branch doesn't. responses: "200": description: The unmerged changes. content: application/json: schema: { $ref: "#/components/schemas/Unmerged" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/co-authors: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getCoAuthors description: > The humans other than the caller with a message in the task's transcript (sent its agent a message, or had an inbox answer delivered under their name), in order of their first message. A merge by the caller gives each one with a git identity a Co-authored-by trailer. responses: "200": description: The co-authors. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Participant" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/merge: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } post: operationId: mergeTask description: > Sets the task's merge_title to the confirmed title, then starts the same agent turn as merge-in, without its invitation to revise the title. When that turn ends normally, byre squashes the task's worktree into one commit titled with the task's merge_title on the project's default branch, authored by the caller with a Co-authored-by trailer for each of the task's co-authors, pushes it to origin, fast-forwards the project's checkout to it, then removes the worktree and branch and marks the task merged. While another task in the project is merging, the merge is held instead (merge_queued_at is set) and starts when no merge is in progress in the project and the task's session is idle, oldest first. The title is fixed from here until the task closes. Refused while a turn is running, or the merge is already held. With target parent, for a subtask only, the subtask's branch is merged into its parent task's branch instead: the parent's agent is asked to merge it (queued if it is mid-turn), and the subtask closes as merged once its branch is in the parent's HEAD at the end of one of the parent's turns (merging_into_parent is set until then). Refused while the subtask's turn is running or it is already merging into its parent. Either target is refused while the task has active subtasks of its own. requestBody: required: true content: application/json: schema: type: object additionalProperties: false properties: merge_title: { type: string, description: "The squash commit's title: one line, at most 72 characters. Required for target main." } target: type: string enum: [main, parent] x-enum-varnames: [MergeTargetMain, MergeTargetParent] description: "main (the default): squash onto the project's default branch. parent: merge into the parent task's branch; only for a subtask." responses: "202": description: The merge was started or held. content: application/json: schema: { $ref: "#/components/schemas/Task" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/merge-in: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } post: operationId: mergeIn description: > Asks the task's agent to merge the project's default branch into the task branch, resolving any conflicts and regenerating generated files. Sent to the task's idle session, or starts a session when it has none. Refused while a turn is running. responses: "202": description: The merge turn was started. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/discard: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } post: operationId: discardTask description: > Gives the task's agent one dedicated turn to write the task summary, started at once when its session is idle (or in a new session when it has none) and otherwise as soon as the running turn ends, with no other turn admitted meanwhile; drops any held merge; and when that turn ends however it ends, removes the task's worktree and branch without merging and marks the task discarded. The task's record, summary and events remain. Refused while the task is merging, already being discarded, or has active subtasks; on a task whose cleanup failed, retries the cleanup. responses: "202": description: The task, still active, whose discard was started. content: application/json: schema: { $ref: "#/components/schemas/Task" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/events: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: listTaskEvents description: The task's events after a seq, oldest first. Page by passing the last seq back as after. parameters: - { name: after, in: query, required: false, schema: { type: integer, format: int64 } } - { name: limit, in: query, required: false, schema: { type: integer, minimum: 1, maximum: 1000 } } responses: "200": description: Up to limit events (default 500). content: application/json: schema: type: array items: { $ref: "#/components/schemas/Event" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/changes: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTaskChanges description: > Everything in the task's worktree (committed, staged, unstaged and untracked, respecting .gitignore) as a tree, compared with the merge-base of the task branch and the project's default branch, or with since when given. The worktree's own index is not touched. With snapshot, the tree is that snapshot's instead, compared with the merge-base of its commit and the default branch, or with the previous snapshot's tree when step is true. parameters: - { name: since, in: query, required: false, schema: { type: string }, description: "A commit to compare with instead of the merge-base, such as a user.message event's head. Not allowed with snapshot." } - { name: snapshot, in: query, required: false, schema: { type: integer }, description: "A snapshot's n: show the task as it was in that snapshot rather than the live worktree." } - { name: step, in: query, required: false, schema: { type: boolean }, description: "With snapshot: compare with the previous snapshot (the snapshot commit's parent for the first one)." } responses: "200": description: Per-file stats. content: application/json: schema: { $ref: "#/components/schemas/TaskChanges" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/image: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTaskImage description: > An image file from the task's worktree, for Markdown images and image attachments. path is absolute or relative to the worktree; after resolving symlinks it must be inside the worktree. PNG, JPEG, GIF, WebP and SVG, chosen by extension. parameters: - { name: path, in: query, required: true, schema: { type: string } } responses: "200": description: The file's bytes. content: image/png: { schema: { type: string, format: binary } } image/jpeg: { schema: { type: string, format: binary } } image/gif: { schema: { type: string, format: binary } } image/webp: { schema: { type: string, format: binary } } image/svg+xml: { schema: { type: string, format: binary } } "400": { $ref: "#/components/responses/Error" } "403": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/diff: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTaskDiff description: The unified diff of one file between a base and tree from getTaskChanges. parameters: - { name: base, in: query, required: true, schema: { type: string } } - { name: tree, in: query, required: true, schema: { type: string } } - { name: path, in: query, required: true, schema: { type: string } } - { name: old_path, in: query, required: false, schema: { type: string } } responses: "200": description: The patch. content: application/json: schema: { $ref: "#/components/schemas/FileDiff" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/dir: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTaskDir description: > One directory of the task's worktree, directories first, then by name. Entries named .git are left out; gitignored entries are included and marked. A path that leaves the worktree, through .. or a symlink, is refused. parameters: - { name: path, in: query, required: false, schema: { type: string }, description: "Slash-separated, relative to the worktree root; empty or absent for the root." } responses: "200": description: The directory's entries. content: application/json: schema: { $ref: "#/components/schemas/DirListing" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/file: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTaskFile description: > A regular file in the task's worktree. Text is returned up to a size limit; binary files return no content. A path that leaves the worktree, through .. or a symlink, is refused. parameters: - { name: path, in: query, required: true, schema: { type: string }, description: "Slash-separated, relative to the worktree root." } responses: "200": description: The file. content: application/json: schema: { $ref: "#/components/schemas/FileContent" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/terminal: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTaskTerminal description: > A WebSocket attached to the task's terminal, a login shell in its worktree, started at cols by rows if none is running. The server first sends what the terminal has recently printed, then its output as it comes, all as binary messages. The client sends input as binary messages and resizes as text messages holding a TerminalSize. When the shell exits the server closes with code 4000 and the exit status as the reason. parameters: - { name: cols, in: query, required: true, schema: { type: integer, minimum: 1 } } - { name: rows, in: query, required: true, schema: { type: integer, minimum: 1 } } responses: "101": description: Switched to the WebSocket protocol. "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/previews: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: listPreviews description: > The ports the task's agent exposed with expose_port, by name. Each is served by tailscale serve on the same port number of byre's host, over HTTPS, until the task is merged or discarded. responses: "200": description: The previews. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Preview" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/snapshots: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: listSnapshots description: > The task's snapshots, oldest first. Each is a commit of the worktree as if everything were staged, kept at refs/byre/tasks/{taskId}/snap/{n} until the task is merged or discarded; the rows remain after that. responses: "200": description: The snapshots. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Snapshot" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/reviews: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: listReviews description: The task's reviews, one per snapshot, oldest first. responses: "200": description: The reviews. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Review" } "404": { $ref: "#/components/responses/Error" } /api/reviews/{reviewId}/findings/{index}: parameters: - { name: reviewId, in: path, required: true, schema: { type: string } } - { name: index, in: path, required: true, schema: { type: integer }, description: "The finding's position in the review's findings, from 0." } put: operationId: setFindingState description: Records that the human addressed a finding of a done review, by sending it to the agent to fix or by ignoring it. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/FindingStateUpdate" } responses: "200": description: The review. content: application/json: schema: { $ref: "#/components/schemas/Review" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/snapshots/{n}/fork: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } - { name: n, in: path, required: true, schema: { type: integer } } post: operationId: forkSnapshot description: > Creates a new task whose branch and worktree start from the snapshot's commit, with an idle agent session that continues the snapshot's agent conversation as it stood at the snapshot (the vendor's own session fork). The new session's first turn is the first message sent to it. Refused while the task is closed, and for a snapshot with no recorded agent message at or before it. responses: "201": description: The new task. content: application/json: schema: { $ref: "#/components/schemas/Task" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/sessions: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: listSessions responses: "200": description: The task's agent sessions, oldest first. content: application/json: schema: type: array items: { $ref: "#/components/schemas/AgentSession" } "404": { $ref: "#/components/responses/Error" } post: operationId: createSession description: Starts an agent session in the task's worktree and sends it the prompt as its first turn. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/SessionCreate" } responses: "201": description: The new session. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/sessions/{sessionId}: parameters: - { name: sessionId, in: path, required: true, schema: { type: string } } get: operationId: getSession responses: "200": description: The session. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "404": { $ref: "#/components/responses/Error" } /api/sessions/{sessionId}/messages: parameters: - { name: sessionId, in: path, required: true, schema: { type: string } } post: operationId: sendMessage description: Starts a new turn with this message when the session is idle. While a task session's turn is running, the message is queued and reaches the agent after its next tool call, or as the next turn. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/MessageCreate" } responses: "202": description: The turn has started. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/sessions/{sessionId}/compact: parameters: - { name: sessionId, in: path, required: true, schema: { type: string } } post: operationId: compactSession description: > Asks the idle session's agent for a handoff (goal, decisions, state, dead ends, open questions, files). When that turn ends, the session is completed and a new session on the same task and model starts with the handoff as its first message. responses: "202": description: The handoff turn was started. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/sessions/{sessionId}/interrupt: parameters: - { name: sessionId, in: path, required: true, schema: { type: string } } post: operationId: interruptSession description: Ends the current turn. responses: "202": description: The interrupt was delivered. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/blobs: post: operationId: uploadBlob description: > Stores an image for use in a message. The body is the raw image; its type is detected from the bytes and must be PNG, JPEG, GIF or WebP. At most 5 MiB. requestBody: required: true content: image/png: { schema: { type: string, format: binary } } image/jpeg: { schema: { type: string, format: binary } } image/gif: { schema: { type: string, format: binary } } image/webp: { schema: { type: string, format: binary } } responses: "201": description: The stored blob. content: application/json: schema: { $ref: "#/components/schemas/Blob" } "400": { $ref: "#/components/responses/Error" } "413": { $ref: "#/components/responses/Error" } /api/blobs/{blobId}: parameters: - { name: blobId, in: path, required: true, schema: { type: string } } get: operationId: getBlob responses: "200": description: The blob's bytes, with its content type. content: image/png: { schema: { type: string, format: binary } } image/jpeg: { schema: { type: string, format: binary } } image/gif: { schema: { type: string, format: binary } } image/webp: { schema: { type: string, format: binary } } "404": { $ref: "#/components/responses/Error" } /api/inbox: get: operationId: listInbox description: > Inbox items, oldest first. Filters narrow the one query to a project's or a task's view. parameters: - { name: project_id, in: query, required: false, schema: { type: string } } - { name: task_id, in: query, required: false, schema: { type: string } } - { name: state, in: query, required: false, schema: { $ref: "#/components/schemas/InboxState" } } responses: "200": description: Matching items with their responses. Defaults to open items. content: application/json: schema: type: array items: { $ref: "#/components/schemas/InboxItem" } /api/inbox/{itemId}: parameters: - { name: itemId, in: path, required: true, schema: { type: string } } get: operationId: getInboxItem responses: "200": description: The item with its responses. content: application/json: schema: { $ref: "#/components/schemas/InboxItem" } "404": { $ref: "#/components/responses/Error" } /api/inbox/responses: post: operationId: respondInbox description: > Answers one or more items in one submission. Answers reach the agent as one message once it is idle and none of its questions are unanswered. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/InboxRespond" } responses: "200": description: The updated items. content: application/json: schema: type: array items: { $ref: "#/components/schemas/InboxItem" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/events: get: operationId: streamEvents description: > Server-sent events. Each event's id is its seq; data is the Event as JSON. Events after Last-Event-ID (or the after query parameter) are replayed before live events. With task_id, only that task's events are sent; with lead=true, only the events of the caller's lead agent. Events with an owner go only to that user. parameters: - { name: Last-Event-ID, in: header, required: false, schema: { type: integer, format: int64 } } - { name: after, in: query, required: false, schema: { type: integer, format: int64 } } - { name: task_id, in: query, required: false, schema: { type: string } } - { name: lead, in: query, required: false, schema: { type: boolean } } responses: "200": description: Event stream. content: text/event-stream: schema: { type: string } "404": { $ref: "#/components/responses/Error" } /api/admin/status: get: operationId: getStatus responses: "200": description: Server health and usage. content: application/json: schema: { $ref: "#/components/schemas/Status" } /api/workflows: get: operationId: listWorkflows responses: "200": description: Every workflow's name and description, by name. content: application/json: schema: type: array items: { $ref: "#/components/schemas/WorkflowSummary" } /api/workflows/{name}: parameters: - { name: name, in: path, required: true, schema: { type: string } } get: operationId: getWorkflow responses: "200": description: "The workflow's file: its WorkflowDefinition as YAML, as an attachment named after it." content: application/yaml: schema: { type: string } "404": { $ref: "#/components/responses/Error" } put: operationId: putWorkflow description: > Creates or replaces the workflow from its file, a WorkflowDefinition as YAML (or JSON). The name is one line of 1 to 100 characters. Tasks that already froze the workflow keep their copy. requestBody: required: true content: application/yaml: schema: { type: string } responses: "200": description: The stored workflow. content: application/json: schema: { $ref: "#/components/schemas/WorkflowSummary" } "400": { $ref: "#/components/responses/Error" } delete: operationId: deleteWorkflow responses: "204": description: Deleted. Tasks that froze it keep their copy. "404": { $ref: "#/components/responses/Error" } components: responses: Error: description: Error. content: application/json: schema: { $ref: "#/components/schemas/Error" } schemas: Error: type: object required: [message] properties: message: { type: string } User: type: object required: [login, display_name, git_name, git_email, notification_prefs] properties: login: { type: string } display_name: { type: string } git_name: { type: string } git_email: { type: string } notification_prefs: { $ref: "#/components/schemas/NotificationPrefs" } NotificationPrefs: type: object description: Which new inbox items and finished turns notify this user in their open byre pages. required: [questions, reports, errors, rate_limits] properties: questions: { type: boolean, description: Questions. On by default. } reports: { type: boolean, description: "Task turns that end with a summary (turn.ended with summary: true)." } errors: { type: boolean, description: session_error items. } rate_limits: { type: boolean, description: rate_limited items. } UserUpdate: type: object required: [git_name, git_email] properties: git_name: { type: string } git_email: { type: string } Project: type: object required: [id, name, repo_path, default_branch, remote, created_by, created_at] properties: id: { type: string } name: { type: string } repo_path: { type: string } default_branch: { type: string } remote: { type: string } created_by: { type: string } created_at: { type: string, format: date-time } ProjectCreate: type: object required: [name, repo_path] properties: name: { type: string } repo_path: { type: string } Task: type: object required: [id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at, reviewing, merging, discarding, merging_into_parent] properties: id: { type: string } project_id: { type: string } title: { type: string } merge_title: { type: string, description: "The title of the squash commit Merge makes: the task title until the agent sets another with set_merge_title." } branch: { type: string } worktree_path: { type: string } base_ref: { type: string } port_base: { type: integer, description: "The first of the task's block of ports (port_base to port_base+9), passed to its agent and terminal as PORT." } color: { type: integer, description: "Index into the UI's task palette, assigned at creation: a colour no active task holds, the one given out longest ago." } status: type: string enum: [active, merged, discarded] x-enum-varnames: [TaskStatusActive, TaskStatusMerged, TaskStatusDiscarded] created_by: { type: string } created_at: { type: string, format: date-time } closed_at: { type: string, format: date-time, description: When the task was merged or discarded. } merge_commit: { type: string, description: "merged: the squash commit on the default branch; empty when there was nothing to merge." } todo_item: { type: string, description: "The title of the TODO.md item the task was started from; absent for other tasks." } forked_from: { type: string, description: "The task this one was forked from; absent for other tasks." } forked_at: { type: integer, description: "With forked_from: the n of the snapshot it was forked at." } merge_queued_at: { type: string, format: date-time, description: "When Merge was requested while another task in the project was merging; absent once the merge starts or when none is held." } workflow: { type: string, description: "The name of the workflow the task froze at creation (getTaskWorkflow has its copy); absent for a task without one." } workflow_run: { type: string, description: "With workflow: the id every task of one run of the workflow shares." } workflow_stage: { type: string, description: "With workflow: the name of the stage this task runs." } reviewing: { type: boolean, description: "Whether a review of one of the task's snapshots is running." } merging: { type: boolean, description: "Whether a Merge was started and its turn hasn't ended yet." } discarding: { type: boolean, description: "Whether a Discard was started and the task isn't closed yet: its summary turn is waiting for the running turn, running, or done and the task is being removed." } parent_task_id: { type: string, description: "The task whose agent created this one as its subtask; absent for other tasks." } merging_into_parent: { type: boolean, description: "Whether a merge of this subtask into its parent was requested and the parent hasn't merged it yet." } Todo: type: object required: [exists, items] properties: exists: { type: boolean, description: Whether the default branch has a TODO.md at its root. } items: type: array items: { $ref: "#/components/schemas/TodoItem" } TodoItem: type: object required: [title, body, section] properties: title: { type: string, description: "The item's first line, without its list marker: the item's identity." } body: { type: string, description: The item's further lines, as Markdown with the item's indentation removed. } section: { type: string, description: The text of the nearest heading above the item; empty when there is none. } TodoStart: type: object required: [title] 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 discuss the item in chat before anything is built." } Unmerged: type: object required: [commits, files, insertions, deletions, uncommitted] properties: commits: { type: integer, description: Commits on the task branch that aren't on the default branch. } files: { type: integer, description: Files that differ from the merge base, uncommitted changes included. } insertions: { type: integer } deletions: { type: integer } uncommitted: { type: integer, description: Paths with uncommitted changes in the worktree. } Participant: type: object required: [login, display_name, git_name, git_email] properties: login: { type: string } display_name: { type: string } git_name: { type: string, description: Empty when the user hasn't set a git identity; they then get no trailer. } git_email: { type: string } TaskCreate: type: object required: [title] properties: title: { type: string } workflow: type: 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 "