Add a per-user lead agent and make the right pane task-focused

This commit is contained in:
Ian Gulliver
2026-10-15 09:40:30 -07:00
parent d212590cdc
commit bdd1ae48f0
68 changed files with 3332 additions and 1364 deletions
+82 -4
View File
@@ -65,6 +65,64 @@ paths:
"204":
description: Removed, or was not registered.
/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/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 task or tab. The lead agent is told.
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/push/key:
get:
operationId: getPushKey
@@ -627,11 +685,13 @@ paths:
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 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.
@@ -877,10 +937,11 @@ components:
AgentSession:
type: object
required: [id, task_id, vendor, model, vendor_session_id, state, role, created_by, created_at]
required: [id, task_id, owner, vendor, model, vendor_session_id, state, role, created_by, created_at]
properties:
id: { type: string }
task_id: { type: string }
task_id: { type: string, description: Empty for a lead session. }
owner: { type: string, description: "The login whose lead agent this is; empty for a task's session." }
vendor: { type: string, enum: [claude] }
model: { type: string, description: Requested model; empty means the vendor's default. }
vendor_session_id: { type: string }
@@ -889,7 +950,7 @@ components:
enum: [idle, queued, running, completed]
x-enum-varnames: [AgentSessionStateIdle, AgentSessionStateQueued, AgentSessionStateRunning, AgentSessionStateCompleted]
description: queued means a turn is waiting for a free slot under the concurrency caps.
role: { type: string, enum: [implementer] }
role: { type: string, enum: [implementer, lead] }
created_by: { type: string }
created_at: { type: string, format: date-time }
@@ -1029,10 +1090,27 @@ components:
project_id: { type: string }
task_id: { type: string }
agent_session_id: { type: string }
owner: { type: string, description: "Set on a lead agent's events and a user's focus.updated: the login they belong to. Only that user is sent them." }
actor: { type: string }
payload: { type: object }
created_at: { type: string, format: date-time }
Focus:
type: object
required: [tabs, tab]
properties:
task_id: { type: string, description: The task the right pane shows; absent for none. }
tabs:
type: array
description: The tabs the lead put first, in order. The other task tabs follow them.
items: { $ref: "#/components/schemas/TaskTab" }
tab: { $ref: "#/components/schemas/TaskTab" }
TaskTab:
type: string
enum: [transcript, changes, files, inbox, todo]
x-enum-varnames: [TabTranscript, TabChanges, TabFiles, TabInbox, TabTodo]
Status:
type: object
required: [started_at, db_bytes, last_event_seq, projects, active_tasks, sse_clients, live_agents, running_turns, queued_turns, caps, rate_limits, agent_processes, zombies, stuck_after_seconds, protocol_errors]