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
+159 -2
View File
@@ -54,6 +54,57 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/me/lead/sessions": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** @description The calling user's lead agent sessions, oldest first. A compaction completes one and starts the next. */
get: operations["listLeadSessions"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/me/lead/messages": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** @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. */
post: operations["messageLead"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/me/focus": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["getFocus"];
/** @description Records the human switching the right pane's task or tab. The lead agent is told. */
put: operations["setFocus"];
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/push/key": {
parameters: {
query?: never;
@@ -595,7 +646,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** @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. */
/** @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. */
get: operations["streamEvents"];
put?: never;
post?: never;
@@ -814,7 +865,10 @@ export interface components {
};
AgentSession: {
id: string;
/** @description Empty for a lead session. */
task_id: string;
/** @description The login whose lead agent this is; empty for a task's session. */
owner: string;
/** @enum {string} */
vendor: "claude";
/** @description Requested model; empty means the vendor's default. */
@@ -826,7 +880,7 @@ export interface components {
*/
state: "idle" | "queued" | "running" | "completed";
/** @enum {string} */
role: "implementer";
role: "implementer" | "lead";
created_by: string;
/** Format: date-time */
created_at: string;
@@ -927,11 +981,22 @@ export interface components {
project_id?: string;
task_id?: string;
agent_session_id?: 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. */
owner?: string;
actor: string;
payload: Record<string, never>;
/** Format: date-time */
created_at: string;
};
Focus: {
/** @description The task the right pane shows; absent for none. */
task_id?: string;
/** @description The tabs the lead put first, in order. The other task tabs follow them. */
tabs: components["schemas"]["TaskTab"][];
tab: components["schemas"]["TaskTab"];
};
/** @enum {string} */
TaskTab: "transcript" | "changes" | "files" | "inbox" | "todo";
Status: {
/** @description Agent processes currently running. */
live_agents: number;
@@ -1151,6 +1216,97 @@ export interface operations {
};
};
};
listLeadSessions: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description The sessions. */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AgentSession"][];
};
};
};
};
messageLead: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["MessageCreate"];
};
};
responses: {
/** @description The lead session the message went to or is held for. */
202: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AgentSession"];
};
};
400: components["responses"]["Error"];
};
};
getFocus: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description What the calling user's right pane shows. */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Focus"];
};
};
};
};
setFocus: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["Focus"];
};
};
responses: {
/** @description The stored focus. */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Focus"];
};
};
400: components["responses"]["Error"];
404: components["responses"]["Error"];
};
};
getPushKey: {
parameters: {
query?: never;
@@ -1971,6 +2127,7 @@ export interface operations {
query?: {
after?: number;
task_id?: string;
lead?: boolean;
};
header?: {
"Last-Event-ID"?: number;