@khorsheed/dsh-local-agent 0.2.0-rc.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,15 +21,22 @@ const MEMBER_BRIDGE_TOKEN_ENV = "DSH_MEMBER_TOKEN";
21
21
  * it bare: `node <this file>`, with the socket path and token in its
22
22
  * environment (written into the CLI's scoped MCP config by the provider).
23
23
  * Covers the MCP handshake subset a client needs: `initialize`,
24
- * `notifications/initialized`, `ping`, `tools/list`, `tools/call`.
24
+ * `notifications/initialized`, `ping`, `tools/list`, `tools/call`. A member
25
+ * with a mode also gets that preset's plugin tools: `tools/list` asks the
26
+ * host for them and any other tool name is forwarded as a mode-tool call.
25
27
  * @module @khorsheed/dsh-local-agent/member-bridge
26
28
  */
27
29
  /** The one tool this server exposes. */
28
30
  const MEMBER_MESSAGE_TOOL = "member_message";
29
31
  const TOOL_DESCRIPTION = [
30
- "Notify another CLI member of this room/session group (member-to-member message).",
31
- "`to` is the target member's dsh child session id (or a member name when a room manages the group).",
32
- "The delivery receipt is returned verbatim: sent / pending-confirm / busy / an error reason."
32
+ "Send a message to another member of this room/session group.",
33
+ "`to` is the member name (or its dsh child session id).",
34
+ "kind \"task\" (default) hands it work: in a room, its final reply is reported back to you automatically, citing the message id — do not poll.",
35
+ "kind \"notify\" is an FYI and is never reported back. Pass inReplyTo (e.g. m12) when answering a message.",
36
+ "Never sleep or poll for the result (room_read included): end your turn, the report arrives on its own.",
37
+ "Writing \"@name\" in a reply reaches nobody; only this tool does.",
38
+ "Optional note: what you will wait for before acting on the result; optional task: \"new\" or a task number from room_read.",
39
+ "The receipt is returned verbatim: sent #m<id> … / pending-confirm … / busy / an error reason."
33
40
  ].join(" ");
34
41
  const TOOL_SCHEMA = {
35
42
  type: "object",
@@ -40,7 +47,24 @@ const TOOL_SCHEMA = {
40
47
  },
41
48
  text: {
42
49
  type: "string",
43
- description: "The notification text, delivered with your provenance."
50
+ description: "The message text, delivered with your provenance."
51
+ },
52
+ kind: {
53
+ type: "string",
54
+ enum: ["task", "notify"],
55
+ description: "task (default): the reply is reported back to you; notify: FYI only."
56
+ },
57
+ inReplyTo: {
58
+ type: "string",
59
+ description: "Optional id of the message this answers, e.g. m12."
60
+ },
61
+ note: {
62
+ type: "string",
63
+ description: "Optional: what you will wait for before acting on the result (the room uses it to decide when to hand you the report)."
64
+ },
65
+ task: {
66
+ type: "string",
67
+ description: "Optional: \"new\" or a task number from room_read; omit to stay in the task you are working on."
44
68
  }
45
69
  },
46
70
  required: ["to", "text"],
@@ -62,7 +86,7 @@ const ROOM_TOOLS = [
62
86
  },
63
87
  {
64
88
  name: "room_read",
65
- description: "Read your room roster, coordinator, deliveries, recent outcomes and available harness providers. Identity comes from the host.",
89
+ description: "Read your room: roster with roles, coordinator, tasks with their numbers, deliveries, recent outcomes and available harness providers. Identity comes from the host. Use it to look around, not to wait for a result.",
66
90
  inputSchema: {
67
91
  type: "object",
68
92
  properties: {},
@@ -77,27 +101,128 @@ const ROOM_TOOLS = [
77
101
  properties: {
78
102
  provider: { type: "string" },
79
103
  name: { type: "string" },
80
- instructions: { type: "string" },
104
+ note: {
105
+ type: "string",
106
+ description: "What you will wait for before acting on the first task result."
107
+ },
108
+ role: {
109
+ type: "string",
110
+ description: "Short public role (≤30 chars) the other members see, e.g. 代码审查."
111
+ },
112
+ instructions: {
113
+ type: "string",
114
+ description: "Private instructions only this member reads."
115
+ },
81
116
  cwd: { type: "string" },
82
117
  model: { type: "string" },
83
- firstTask: { type: "string" }
118
+ firstTask: { type: "string" },
119
+ mode: {
120
+ type: "string",
121
+ description: "The member's dsh mode (a host preset id, e.g. dsh-gamedev). Omit to keep this room's own mode; \"none\" for only its own CLI tools."
122
+ }
84
123
  },
85
124
  required: ["provider", "name"],
86
125
  additionalProperties: false
87
126
  }
88
127
  },
128
+ {
129
+ name: "ask_user_question",
130
+ description: "Ask the human questions they answer by picking options (or typing), instead of writing the questions into your reply. Use it whenever you need the human to decide or fill in something before you go on: give each question 2-4 short options with a one-line description each. The call waits for the answer and returns {answers:[{id, selected:[labels], custom?}]}; if nobody answers it fails — then go on with your best judgement and say what you assumed.",
131
+ inputSchema: {
132
+ type: "object",
133
+ properties: { questions: {
134
+ type: "array",
135
+ description: "At most 4 questions.",
136
+ items: {
137
+ type: "object",
138
+ properties: {
139
+ id: {
140
+ type: "string",
141
+ description: "Short unique id, echoed in the answer."
142
+ },
143
+ question: {
144
+ type: "string",
145
+ description: "The full question."
146
+ },
147
+ header: {
148
+ type: "string",
149
+ description: "Optional 2-6 word topic chip."
150
+ },
151
+ options: {
152
+ type: "array",
153
+ items: {
154
+ type: "object",
155
+ properties: {
156
+ label: { type: "string" },
157
+ description: { type: "string" }
158
+ },
159
+ required: ["label"]
160
+ }
161
+ },
162
+ multi_select: {
163
+ type: "boolean",
164
+ description: "True when several options may be picked."
165
+ }
166
+ },
167
+ required: ["id", "question"]
168
+ }
169
+ } },
170
+ required: ["questions"],
171
+ additionalProperties: false
172
+ }
173
+ },
89
174
  {
90
175
  name: "room_message",
91
- description: "Coordinator only: dispatch background work to a room member by name. Returns acceptance immediately; completion arrives as a correlated report. Do not poll.",
176
+ description: "Send a room member a message by name (same as member_message). kind \"task\" (default): its reply comes back to you as a report citing the message id; kind \"notify\": FYI only. Do not poll.",
92
177
  inputSchema: {
93
178
  type: "object",
94
179
  properties: {
95
180
  member: { type: "string" },
96
- text: { type: "string" }
181
+ text: { type: "string" },
182
+ kind: {
183
+ type: "string",
184
+ enum: ["task", "notify"]
185
+ },
186
+ inReplyTo: { type: "string" },
187
+ note: {
188
+ type: "string",
189
+ description: "What you will wait for before acting on the result."
190
+ },
191
+ task: {
192
+ type: "string",
193
+ description: "\"new\" or a task number; omit to stay in your current task."
194
+ }
97
195
  },
98
196
  required: ["member", "text"],
99
197
  additionalProperties: false
100
198
  }
199
+ },
200
+ {
201
+ name: "room_help",
202
+ description: "Ask another session outside this room for help — typically the one that built what you are stuck on. It works in its own session (a busy one queues you); its final answer plus a short handoff comes back to you on its own, so end your turn after asking and do not poll. Name the session by title, id or the @ mention the human wrote; a session that is another room goes to its coordinator, or to the member you name. The first ask of a session the human did not @ in the room waits for their approval. To answer its question or ask more, call again with the help id and no session.",
203
+ inputSchema: {
204
+ type: "object",
205
+ properties: {
206
+ session: {
207
+ type: "string",
208
+ description: "The session to ask (title, id, or @ mention). Omit when continuing a thread."
209
+ },
210
+ member: {
211
+ type: "string",
212
+ description: "When the session is another room: the member to ask. Omit to let its coordinator decide."
213
+ },
214
+ help: {
215
+ type: "string",
216
+ description: "The help id of an existing thread."
217
+ },
218
+ text: {
219
+ type: "string",
220
+ description: "What you need, self-contained: the helper does not see this room."
221
+ }
222
+ },
223
+ required: ["text"],
224
+ additionalProperties: false
225
+ }
101
226
  }
102
227
  ];
103
228
  async function callRoomCommand(env, name, args) {
@@ -116,6 +241,35 @@ async function callRoomCommand(env, name, args) {
116
241
  return toolText(`Room command unavailable: ${String(error)}`, true);
117
242
  }
118
243
  }
244
+ /** The member's mode tools (the preset's plugin tools), empty when it has none or the host is unreachable. */
245
+ async function listModeTools(env) {
246
+ if (env.socket === void 0 || env.token === void 0) return [];
247
+ try {
248
+ const outcome = await callHost(env.socket, {
249
+ token: env.token,
250
+ modeTools: { list: true }
251
+ });
252
+ return outcome.ok && Array.isArray(outcome.tools) ? outcome.tools : [];
253
+ } catch {
254
+ return [];
255
+ }
256
+ }
257
+ /** Run one mode tool on the host; the host's MCP result passes through. */
258
+ async function callModeTool(env, name, args) {
259
+ if (env.socket === void 0 || env.token === void 0) return toolText("member channel is not configured for this run", true);
260
+ try {
261
+ const outcome = await callHost(env.socket, {
262
+ token: env.token,
263
+ modeTools: { call: {
264
+ name,
265
+ arguments: args
266
+ } }
267
+ });
268
+ return outcome.ok && outcome.result !== void 0 ? outcome.result : toolText(outcome.error ?? `Tool ${name} failed`, true);
269
+ } catch (error) {
270
+ return toolText(`Mode tool unavailable: ${String(error)}`, true);
271
+ }
272
+ }
119
273
  /** One socket round trip: send the request line, read the one-line response. */
120
274
  function callHost(socket, payload) {
121
275
  return new Promise((resolve, reject) => {
@@ -163,7 +317,11 @@ async function callMemberMessage(env, args) {
163
317
  const outcome = await callHost(env.socket, {
164
318
  token: env.token,
165
319
  to: args.to,
166
- text: args.text
320
+ text: args.text,
321
+ ...args.kind === "task" || args.kind === "notify" ? { kind: args.kind } : {},
322
+ ...typeof args.inReplyTo === "string" ? { inReplyTo: args.inReplyTo } : {},
323
+ ...typeof args.note === "string" ? { note: args.note } : {},
324
+ ...typeof args.task === "string" ? { task: args.task } : {}
167
325
  });
168
326
  if (outcome.ok) return toolText(outcome.receipt ?? "sent");
169
327
  return toolText(outcome.error ?? "member channel rejected the message", true);
@@ -229,15 +387,19 @@ function serveMemberBridge(env, input, output) {
229
387
  });
230
388
  return;
231
389
  case "tools/list":
232
- write({
390
+ listModeTools(env).then((modeTools) => write({
233
391
  jsonrpc: "2.0",
234
392
  id: id ?? null,
235
- result: { tools: [{
236
- name: MEMBER_MESSAGE_TOOL,
237
- description: TOOL_DESCRIPTION,
238
- inputSchema: TOOL_SCHEMA
239
- }, ...ROOM_TOOLS] }
240
- });
393
+ result: { tools: [
394
+ {
395
+ name: MEMBER_MESSAGE_TOOL,
396
+ description: TOOL_DESCRIPTION,
397
+ inputSchema: TOOL_SCHEMA
398
+ },
399
+ ...ROOM_TOOLS,
400
+ ...modeTools.filter((tool) => tool["name"] !== "member_message" && !ROOM_TOOLS.some((room) => room.name === tool["name"]))
401
+ ] }
402
+ }));
241
403
  return;
242
404
  case "tools/call": {
243
405
  const params = request.params;
@@ -250,14 +412,22 @@ function serveMemberBridge(env, input, output) {
250
412
  return;
251
413
  }
252
414
  if (params?.name !== "member_message") {
253
- write({
415
+ if (typeof params?.name !== "string") {
416
+ write({
417
+ jsonrpc: "2.0",
418
+ id: id ?? null,
419
+ error: {
420
+ code: -32602,
421
+ message: "tools/call requires a tool name"
422
+ }
423
+ });
424
+ return;
425
+ }
426
+ callModeTool(env, params.name, params.arguments ?? {}).then((result) => write({
254
427
  jsonrpc: "2.0",
255
428
  id: id ?? null,
256
- error: {
257
- code: -32602,
258
- message: `unknown tool ${String(params?.name)}`
259
- }
260
- });
429
+ result
430
+ }));
261
431
  return;
262
432
  }
263
433
  callMemberMessage(env, params.arguments ?? {}).then((result) => {
@@ -295,4 +465,4 @@ if (isMain()) serveMemberBridge({
295
465
  token: process.env[MEMBER_BRIDGE_TOKEN_ENV]
296
466
  }, process.stdin, process.stdout);
297
467
  //#endregion
298
- export { MEMBER_MESSAGE_TOOL, callMemberMessage, callRoomCommand, serveMemberBridge };
468
+ export { MEMBER_MESSAGE_TOOL, callMemberMessage, callModeTool, callRoomCommand, listModeTools, serveMemberBridge };
@@ -15,7 +15,7 @@ let _khorsheed_dsh_local_agent_localAgentGateway_cancelMemberConfiguration_resul
15
15
  const _khorsheed_dsh_local_agent_localAgentGateway_cancelMemberConfiguration_result$schema = () => (_khorsheed_dsh_local_agent_localAgentGateway_cancelMemberConfiguration_result$schema$value ??= z.object({
16
16
  'requestId': z.string(),
17
17
  'revision': z.number(),
18
- 'status': z.union([z.literal("cancelled"), z.literal("failed"), z.literal("pending"), z.literal("applied"), z.literal("locked"), z.literal("applying"), z.literal("unsupported"), z.literal("conflict")]),
18
+ 'status': z.union([z.literal("cancelled"), z.literal("failed"), z.literal("pending"), z.literal("applied"), z.literal("conflict"), z.literal("unsupported"), z.literal("locked"), z.literal("applying")]),
19
19
  'error': z.string().optional(),
20
20
  }))
21
21
  let _khorsheed_dsh_local_agent_localAgentGateway_checkEndpoint_parameter_0$schema$value
@@ -1106,7 +1106,7 @@ let _khorsheed_dsh_local_agent_localAgentGateway_selectMemberConfiguration_resul
1106
1106
  const _khorsheed_dsh_local_agent_localAgentGateway_selectMemberConfiguration_result$schema = () => (_khorsheed_dsh_local_agent_localAgentGateway_selectMemberConfiguration_result$schema$value ??= z.object({
1107
1107
  'requestId': z.string(),
1108
1108
  'revision': z.number(),
1109
- 'status': z.union([z.literal("cancelled"), z.literal("failed"), z.literal("pending"), z.literal("applied"), z.literal("locked"), z.literal("applying"), z.literal("unsupported"), z.literal("conflict")]),
1109
+ 'status': z.union([z.literal("cancelled"), z.literal("failed"), z.literal("pending"), z.literal("applied"), z.literal("conflict"), z.literal("unsupported"), z.literal("locked"), z.literal("applying")]),
1110
1110
  'error': z.string().optional(),
1111
1111
  }))
1112
1112
  let _khorsheed_dsh_local_agent_localAgentGateway_sessions_parameter_0$schema$value
@@ -1363,7 +1363,7 @@ const $remote = createTypertRemoteInfo({
1363
1363
  typeSymbol: '@khorsheed/dsh-local-agent/types#LocalAgentControlReceipt',
1364
1364
  create: _khorsheed_dsh_local_agent_localAgentGateway_cancelMemberConfiguration_result$schema,
1365
1365
  schema: _khorsheed_dsh_local_agent_localAgentGateway_cancelMemberConfiguration_result$schema(),
1366
- jsonSchema: {"type":"object","properties":{"requestId":{"type":"string"},"revision":{"type":"number"},"status":{"type":"string","enum":["cancelled","failed","pending","applied","locked","applying","unsupported","conflict"]},"error":{"type":"string"}},"required":["requestId","revision","status"],"additionalProperties":true},
1366
+ jsonSchema: {"type":"object","properties":{"requestId":{"type":"string"},"revision":{"type":"number"},"status":{"type":"string","enum":["cancelled","failed","pending","applied","conflict","unsupported","locked","applying"]},"error":{"type":"string"}},"required":["requestId","revision","status"],"additionalProperties":true},
1367
1367
  },
1368
1368
  sourceLocation: {"file":"packages/local-agent/src/gateway.ts","line":414,"column":9},
1369
1369
  },
@@ -2399,7 +2399,7 @@ const $remote = createTypertRemoteInfo({
2399
2399
  typeSymbol: '@khorsheed/dsh-local-agent/types#LocalAgentControlReceipt',
2400
2400
  create: _khorsheed_dsh_local_agent_localAgentGateway_selectMemberConfiguration_result$schema,
2401
2401
  schema: _khorsheed_dsh_local_agent_localAgentGateway_selectMemberConfiguration_result$schema(),
2402
- jsonSchema: {"type":"object","properties":{"requestId":{"type":"string"},"revision":{"type":"number"},"status":{"type":"string","enum":["cancelled","failed","pending","applied","locked","applying","unsupported","conflict"]},"error":{"type":"string"}},"required":["requestId","revision","status"],"additionalProperties":true},
2402
+ jsonSchema: {"type":"object","properties":{"requestId":{"type":"string"},"revision":{"type":"number"},"status":{"type":"string","enum":["cancelled","failed","pending","applied","conflict","unsupported","locked","applying"]},"error":{"type":"string"}},"required":["requestId","revision","status"],"additionalProperties":true},
2403
2403
  },
2404
2404
  sourceLocation: {"file":"packages/local-agent/src/gateway.ts","line":409,"column":9},
2405
2405
  },
@@ -2970,7 +2970,7 @@ export const TYPERT = {
2970
2970
  "name": "resume",
2971
2971
  "signature": "async resume( parentSessionId: string, provider: string, childSessionId: string, prompt: ContentBlock[], options?: DelegationCallOptions, ): Promise<SubagentRun>",
2972
2972
  "summary": "Resume a recorded delegation: continue the SAME CLI session inside the SAME dsh child session.",
2973
- "jsDoc": "/**\n * Resume a recorded delegation: continue the SAME CLI session inside the\n * SAME dsh child session. One call performs, in order:\n *\n * 1. provider pre-check (`ctx.subagents.getProvider`) — fails loud WITHOUT\n * staging, so an unknown provider never leaves an orphan intent;\n * 2. `resolveDelegation` ownership check (unchanged semantics): the handle\n * must name a delegation THIS parent session recorded through THIS\n * provider;\n * 3. read-only resume-lock probe ({@link isResumeLocked}) — fails fast\n * without staging; the provider still takes the authoritative lock inside\n * its `start()`;\n * 4. live parent agent resolution (`ctx.agents.get`) — a harness hard\n * constraint, since `ctx.subagents.startActivation` requires a live parent;\n * 5. child-session REATTACH when `ctx.sessions.get(childSessionId)` is\n * undefined (recipe below; `opts.reattach === false` disables this step\n * and fails loud on a non-live child instead);\n * 6. stage `{ kind: 'resume', childSessionId, cliSessionId }` and, in the\n * same synchronous flow, `await ctx.subagents.startActivation({…})`;\n * 7. on start failure, roll the intent back via\n * {@link unstageDelegationIntent} (no-op once consumed);\n * 8. on success, track the run under `childSessionId` for {@link cancel}\n * until `run.result` settles.\n *\n * **Reattach recipe** (callers replicating this flow — e.g. room — copy\n * exactly this sequence):\n *\n * ```ts\n * const handle = await ctx.sessionPersistence.open(SessionId(childSessionId), 'write')\n * try {\n * const cold = await handle.read(0)\n * const session = ctx.sessions.prepare(SessionId(childSessionId), {\n * seed: [...cold.events],\n * meta: structuredClone(handle.header),\n * inheritedEventCount: handle.inheritedEventCount,\n * eventState: cold.eventState,\n * })\n * // The seeded constructor's session/end-seed marker lands before enter()\n * // installs publication hooks — push the unstored suffix through the\n * // handle directly, or the writer's contiguous cursor diverges.\n * const unstored = session.snapshotEvents().slice(cold.events.length)\n * if (unstored.length > 0) await handle.append(unstored)\n * const detach = ctx.sessions.enter(session)\n * try { ctx.sessions.announce(session) }\n * catch (error) { detach(); throw error }\n * // Hold BOTH for the reattached lifetime: the backend routes live\n * // session/event appends into the per-id writer only while the write\n * // handle is open; closing it ends persistence for the session.\n * } catch (error) {\n * await handle.close().catch(() => {})\n * throw error\n * }\n * ```\n *\n * Hold `detach` and `handle` for the plugin lifetime. Announce the restored\n * live session after entering it, rolling back detach if announcement fails.\n * History followers need this lifecycle edge to replay the constructor's\n * end-seed suffix before the provider publishes subsequent events.\n * @param parentSessionId - the delegating parent session id; must match the\n * recorded one and have a live agent.\n * @param provider - the `ctx.subagents` provider that owns the CLI session.\n * @param childSessionId - the dsh child session id from the first round (the\n * resume handle).\n * @param prompt - the follow-up user message content blocks.\n * @param options - optional label and caller-owned abort signal.\n * @returns the published subagent run.\n * @throws on unknown provider, unknown/foreign-parent/wrong-provider handle,\n * an in-flight resume of the same child, or a missing live parent agent —\n * all BEFORE anything is staged.\n */"
2973
+ "jsDoc": "/**\n * Resume a recorded delegation: continue the SAME CLI session inside the\n * SAME dsh child session. One call performs, in order:\n *\n * 1. provider pre-check (`ctx.subagents.getProvider`) — fails loud WITHOUT\n * staging, so an unknown provider never leaves an orphan intent;\n * 2. `resolveDelegation` ownership check (unchanged semantics): the handle\n * must name a delegation THIS parent session recorded through THIS\n * provider;\n * 3. read-only resume-lock probe ({@link isResumeLocked}) — fails fast\n * without staging; the provider still takes the authoritative lock inside\n * its `start()`;\n * 4. live parent agent resolution (`ctx.agents.get`) — a harness hard\n * constraint, since `ctx.subagents.startActivation` requires a live parent;\n * 5. child-session REATTACH when `ctx.sessions.get(childSessionId)` is\n * undefined (recipe below; `opts.reattach === false` disables this step\n * and fails loud on a non-live child instead);\n * 6. stage `{ kind: 'resume', childSessionId, cliSessionId }` and, in the\n * same synchronous flow, `await ctx.subagents.startActivation({…})`;\n * 7. on start failure, roll the intent back via\n * {@link unstageDelegationIntent} (no-op once consumed);\n * 8. on success, track the run under `childSessionId` for {@link cancel}\n * until `run.result` settles.\n *\n * **Reattach recipe** (callers replicating this flow — e.g. room — copy\n * exactly this sequence):\n *\n * ```ts\n * const handle = await ctx.sessionPersistence.open(SessionId(childSessionId), 'write')\n * try {\n * const cold = await handle.read(0)\n * // Close a turn a restart interrupted, or the next round's turn/start\n * // makes the stored log unreadable.\n * const closers = interruptedTurnClosers(cold.events)\n * if (closers.length > 0) await handle.append(closers)\n * const session = ctx.sessions.prepare(SessionId(childSessionId), {\n * seed: [...cold.events, ...closers],\n * meta: structuredClone(handle.header),\n * inheritedEventCount: handle.inheritedEventCount,\n * eventState: cold.eventState,\n * })\n * // The seeded constructor's session/end-seed marker lands before enter()\n * // installs publication hooks — push the unstored suffix through the\n * // handle directly, or the writer's contiguous cursor diverges.\n * const unstored = session.snapshotEvents().slice(cold.events.length + closers.length)\n * if (unstored.length > 0) await handle.append(unstored)\n * const detach = ctx.sessions.enter(session)\n * try { ctx.sessions.announce(session) }\n * catch (error) { detach(); throw error }\n * // Hold BOTH for the reattached lifetime: the backend routes live\n * // session/event appends into the per-id writer only while the write\n * // handle is open; closing it ends persistence for the session.\n * } catch (error) {\n * await handle.close().catch(() => {})\n * throw error\n * }\n * ```\n *\n * Hold `detach` and `handle` for the plugin lifetime. Announce the restored\n * live session after entering it, rolling back detach if announcement fails.\n * History followers need this lifecycle edge to replay the constructor's\n * end-seed suffix before the provider publishes subsequent events.\n * @param parentSessionId - the delegating parent session id; must match the\n * recorded one and have a live agent.\n * @param provider - the `ctx.subagents` provider that owns the CLI session.\n * @param childSessionId - the dsh child session id from the first round (the\n * resume handle).\n * @param prompt - the follow-up user message content blocks.\n * @param options - optional label and caller-owned abort signal.\n * @returns the published subagent run.\n * @throws on unknown provider, unknown/foreign-parent/wrong-provider handle,\n * an in-flight resume of the same child, or a missing live parent agent —\n * all BEFORE anything is staged.\n */"
2974
2974
  },
2975
2975
  {
2976
2976
  "kind": "method",
@@ -3559,7 +3559,7 @@ export const TYPERT = {
3559
3559
  },
3560
3560
  {
3561
3561
  "name": "MessageSourceMap",
3562
- "declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n model: ModelMessageSource;\n tool: ToolMessageSource;\n 'system-prompt': SystemPromptMessageSource;\n 'model-selection': { kind: 'model-selection'; } & ContextFormed;\n 'runtime-context': { kind: 'runtime-context'; } & ContextFormed;\n 'working-directory': { kind: 'working-directory'; };\n 'user-approval': { kind: 'user-approval'; } & ContextFormed;\n 'ptc-mode': { kind: 'ptc-mode'; };\n 'tool-registry': { kind: 'tool-registry'; };\n 'user-rpc': { kind: 'user'; rpcId: SessionRequestId; clientTimeZone?: string; principal?: Principal; };\n 'agent-message': AgentMessageSource;\n 'subagent-settled': SubagentSettledMessageSource;\n 'skill-invocation': SkillInvocationSource;\n 'compact-checkpoint': CompactionCheckpointSource;\n 'cordis-host-runner': { kind: 'cordis-host-runner'; };\n 'team-message': TeamMessageSource;\n 'user-question-reply': { kind: 'user-question-reply'; callId: ToolCallId; outcome: 'answered'; };\n goal: GoalMessageSource;\n 'plan-mode': { kind: 'plan-mode'; } & ContextFormed;\n schedule: { kind: 'schedule'; } & ContextFormed;\n 'session-reference': SessionReferenceSource;\n webhook: { readonly kind: 'webhook'; readonly provider: string; readonly source: WebhookSourceId; readonly deliveryId: WebhookDeliveryId; readonly ruleId: WebhookRuleId; readonly form: 'notice'; readonly summary: string; };\n 'message-tools': { kind: 'message-tools'; readonly op?: MessageToolsOp; } & ContextFormed;\n 'dsh-game': { kind: 'dsh-game'; plugin: '@khorsheed/dsh-game'; } & ContextFormed & Partial<GameMessageOp>;\n room: { kind: 'room'; } & ContextFormed;\n sidechat: { kind: 'sidechat'; } & ContextFormed;\n worktrees: { kind: 'worktrees'; } & ContextFormed;\n}"
3562
+ "declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n model: ModelMessageSource;\n tool: ToolMessageSource;\n 'system-prompt': SystemPromptMessageSource;\n 'model-selection': { kind: 'model-selection'; } & ContextFormed;\n 'runtime-context': { kind: 'runtime-context'; } & ContextFormed;\n 'working-directory': { kind: 'working-directory'; };\n 'user-approval': { kind: 'user-approval'; } & ContextFormed;\n 'ptc-mode': { kind: 'ptc-mode'; };\n 'tool-registry': { kind: 'tool-registry'; };\n 'user-rpc': { kind: 'user'; rpcId: SessionRequestId; clientTimeZone?: string; principal?: Principal; };\n 'agent-message': AgentMessageSource;\n 'subagent-settled': SubagentSettledMessageSource;\n 'skill-invocation': SkillInvocationSource;\n 'compact-checkpoint': CompactionCheckpointSource;\n 'cordis-host-runner': { kind: 'cordis-host-runner'; };\n 'team-message': TeamMessageSource;\n 'user-question-reply': { kind: 'user-question-reply'; callId: ToolCallId; outcome: 'answered'; };\n goal: GoalMessageSource;\n 'plan-mode': { kind: 'plan-mode'; } & ContextFormed;\n schedule: { kind: 'schedule'; } & ContextFormed;\n 'session-reference': SessionReferenceSource;\n webhook: { readonly kind: 'webhook'; readonly provider: string; readonly source: WebhookSourceId; readonly deliveryId: WebhookDeliveryId; readonly ruleId: WebhookRuleId; readonly form: 'notice'; readonly summary: string; };\n 'message-tools': { kind: 'message-tools'; readonly op?: MessageToolsOp; } & ContextFormed;\n 'dsh-game': { kind: 'dsh-game'; plugin: '@khorsheed/dsh-game'; } & ContextFormed & Partial<GameMessageOp>;\n room: { kind: 'room'; } & ContextFormed;\n 'room-help': { kind: 'room-help'; plugin: '@khorsheed/dsh-room'; help: string; room: string; roomTitle: string; from: string; op: 'request' | 'message'; text: string; } & ContextFormed;\n sidechat: { kind: 'sidechat'; } & ContextFormed;\n worktrees: { kind: 'worktrees'; } & ContextFormed;\n}"
3563
3563
  },
3564
3564
  {
3565
3565
  "name": "MessageToolsOp",
@@ -3645,6 +3645,14 @@ export const TYPERT = {
3645
3645
  "name": "RetryId",
3646
3646
  "declaration": "export type RetryId = Branded<'RetryId'>;"
3647
3647
  },
3648
+ {
3649
+ "name": "RoomApprovalEvent",
3650
+ "declaration": "export interface RoomApprovalEvent {\n readonly id: string;\n readonly member: string;\n readonly memberId: string;\n readonly tool: string;\n readonly reason?: string;\n}"
3651
+ },
3652
+ {
3653
+ "name": "RoomApprovalResolvedEvent",
3654
+ "declaration": "export interface RoomApprovalResolvedEvent {\n readonly id: string;\n readonly outcome: 'allowed-once' | 'rejected' | 'cancelled';\n}"
3655
+ },
3648
3656
  {
3649
3657
  "name": "RoomCoordinatorEvent",
3650
3658
  "declaration": "export interface RoomCoordinatorEvent {\n readonly version: 1;\n readonly memberId: string;\n readonly revision: number;\n readonly previousMemberId: string;\n readonly handoff: string;\n}"
@@ -3653,29 +3661,77 @@ export const TYPERT = {
3653
3661
  "name": "RoomCreatedEvent",
3654
3662
  "declaration": "export interface RoomCreatedEvent {\n readonly version: 1;\n}"
3655
3663
  },
3664
+ {
3665
+ "name": "RoomDecisionCall",
3666
+ "declaration": "export interface RoomDecisionCall {\n readonly model: string;\n readonly latencyMs?: number;\n readonly cached?: boolean;\n readonly inputTokens?: number;\n readonly outputTokens?: number;\n readonly request: { readonly state: RoomJsonValue; readonly questions: RoomJsonValue; };\n readonly response?: RoomJsonValue;\n readonly failure?: { readonly reason: string; readonly detail?: string; };\n}"
3667
+ },
3668
+ {
3669
+ "name": "RoomDecisionEvent",
3670
+ "declaration": "export interface RoomDecisionEvent {\n readonly id: string;\n readonly scenario: RoomDecisionScenario;\n readonly outcome: string;\n readonly rule?: string;\n readonly probability?: number;\n readonly call?: RoomDecisionCall;\n readonly about: { readonly message?: string; readonly task?: { readonly number: number; readonly title: string; }; readonly from?: string; readonly to?: string; };\n}"
3671
+ },
3672
+ {
3673
+ "name": "RoomDecisionScenario",
3674
+ "declaration": "export type RoomDecisionScenario = 'task-filing' | 'report-timing';"
3675
+ },
3656
3676
  {
3657
3677
  "name": "RoomDeliveryStateEvent",
3658
3678
  "declaration": "export interface RoomDeliveryStateEvent {\n readonly id: string;\n readonly dispatchSeq: number;\n readonly memberId: string;\n readonly state: 'running' | 'done' | 'cancelled' | 'failed' | 'uncertain';\n readonly text?: string;\n readonly error?: string;\n}"
3659
3679
  },
3660
3680
  {
3661
3681
  "name": "RoomDispatchEvent",
3662
- "declaration": "export interface RoomDispatchEvent {\n readonly plan?: { readonly goalId: string; readonly taskId?: string; readonly attemptId?: string; };\n readonly requestSignature?: string;\n readonly id?: string;\n readonly targetIds?: readonly string[];\n readonly origin?: 'human' | 'coordinator' | 'report' | 'relay';\n readonly replyTo?: string;\n readonly reportFor?: string;\n readonly targets: readonly string[];\n readonly text: string;\n}"
3682
+ "declaration": "export interface RoomDispatchEvent {\n readonly plan?: { readonly goalId: string; readonly taskId?: string; readonly attemptId?: string; };\n readonly requestSignature?: string;\n readonly id?: string;\n readonly targetIds?: readonly string[];\n readonly origin?: 'human' | 'coordinator' | 'member' | 'report' | 'relay' | 'help';\n readonly help?: RoomHelpOrigin;\n readonly from?: string;\n readonly kind?: 'task' | 'notify';\n readonly hop?: number;\n readonly inReplyTo?: number;\n readonly note?: string;\n readonly held?: true;\n readonly releases?: readonly number[];\n readonly task?: string;\n readonly parent?: string;\n readonly replyTo?: string;\n readonly reportFor?: string;\n readonly targets: readonly string[];\n readonly text: string;\n}"
3663
3683
  },
3664
3684
  {
3665
3685
  "name": "RoomExecutionMetadataEvent",
3666
- "declaration": "export interface RoomExecutionMetadataEvent {\n readonly runId: string;\n readonly model?: string;\n readonly effort?: string;\n readonly tokens?: number;\n}"
3686
+ "declaration": "export interface RoomExecutionMetadataEvent {\n readonly runId: string;\n readonly model?: string;\n readonly effort?: string;\n readonly tokens?: number;\n readonly usage?: RoomRunUsage;\n}"
3667
3687
  },
3668
3688
  {
3669
3689
  "name": "RoomGoalEvent",
3670
3690
  "declaration": "export interface RoomGoalEvent {\n readonly text: string;\n}"
3671
3691
  },
3692
+ {
3693
+ "name": "RoomHeldDispatch",
3694
+ "declaration": "export interface RoomHeldDispatch {\n readonly origin: 'coordinator' | 'member' | 'report' | 'help';\n readonly help?: RoomHelpOrigin;\n readonly from?: string;\n readonly kind?: 'task' | 'notify';\n readonly hop: number;\n readonly inReplyTo?: number;\n readonly replyTo?: string;\n readonly reportFor?: string;\n readonly plan?: { readonly goalId: string; };\n readonly note?: string;\n readonly task?: string;\n readonly parent?: string;\n}"
3695
+ },
3696
+ {
3697
+ "name": "RoomHelpEvent",
3698
+ "declaration": "export interface RoomHelpEvent {\n readonly id: string;\n readonly from: string;\n readonly fromName: string;\n readonly target: { readonly sessionId: string; readonly title: string; readonly room?: true; readonly member?: string; };\n readonly text: string;\n}"
3699
+ },
3700
+ {
3701
+ "name": "RoomHelpInEvent",
3702
+ "declaration": "export interface RoomHelpInEvent extends RoomHelpOrigin {\n readonly member: string;\n readonly text: string;\n readonly op: 'request' | 'message';\n readonly held?: true;\n}"
3703
+ },
3704
+ {
3705
+ "name": "RoomHelpMessageEvent",
3706
+ "declaration": "export interface RoomHelpMessageEvent {\n readonly help: string;\n readonly kind: 'question' | 'reply' | 'message';\n readonly text: string;\n readonly handoff?: string;\n readonly fallback?: true;\n}"
3707
+ },
3708
+ {
3709
+ "name": "RoomHelpOrigin",
3710
+ "declaration": "export interface RoomHelpOrigin {\n readonly id: string;\n readonly room: string;\n readonly roomTitle: string;\n readonly from: string;\n}"
3711
+ },
3712
+ {
3713
+ "name": "RoomHelpStateEvent",
3714
+ "declaration": "export interface RoomHelpStateEvent {\n readonly help: string;\n readonly state: RoomHelpStatus;\n readonly error?: string;\n}"
3715
+ },
3716
+ {
3717
+ "name": "RoomHelpStatus",
3718
+ "declaration": "export type RoomHelpStatus = 'queued' | 'running' | 'asking' | 'replied' | 'failed';"
3719
+ },
3720
+ {
3721
+ "name": "RoomHoldReason",
3722
+ "declaration": "export type RoomHoldReason = 'confirm' | 'hop-limit' | 'paused';"
3723
+ },
3724
+ {
3725
+ "name": "RoomJobStoppedEvent",
3726
+ "declaration": "export interface RoomJobStoppedEvent {\n readonly task: string;\n}"
3727
+ },
3672
3728
  {
3673
3729
  "name": "RoomJsonValue",
3674
3730
  "declaration": "export type RoomJsonValue = null | boolean | number | string | RoomJsonValue[] | { [key: string]: RoomJsonValue; };"
3675
3731
  },
3676
3732
  {
3677
3733
  "name": "RoomMemberAddedEvent",
3678
- "declaration": "export interface RoomMemberAddedEvent {\n readonly id?: string;\n readonly name: string;\n readonly kind: 'main-agent' | 'cli';\n readonly provider?: string;\n readonly instructions?: string;\n readonly invitedBy: 'human' | 'agent';\n readonly cwd?: string;\n readonly model?: string;\n readonly childSessionId?: SessionId;\n}"
3734
+ "declaration": "export interface RoomMemberAddedEvent {\n readonly id?: string;\n readonly name: string;\n readonly kind: 'main-agent' | 'cli' | 'native';\n readonly provider?: string;\n readonly preset?: string;\n readonly instructions?: string;\n readonly role?: string;\n readonly invitedBy: 'human' | 'agent';\n readonly cwd?: string;\n readonly model?: string;\n readonly effort?: string;\n readonly childSessionId?: SessionId;\n}"
3679
3735
  },
3680
3736
  {
3681
3737
  "name": "RoomMemberRemovedEvent",
@@ -3683,27 +3739,59 @@ export const TYPERT = {
3683
3739
  },
3684
3740
  {
3685
3741
  "name": "RoomMemberUpdatedEvent",
3686
- "declaration": "export interface RoomMemberUpdatedEvent {\n readonly name: string;\n readonly rename?: string;\n readonly instructions?: string | null;\n readonly cwd?: string | null;\n readonly model?: string | null;\n readonly childSessionId?: SessionId;\n}"
3742
+ "declaration": "export interface RoomMemberUpdatedEvent {\n readonly name: string;\n readonly rename?: string;\n readonly instructions?: string | null;\n readonly role?: string | null;\n readonly cwd?: string | null;\n readonly model?: string | null;\n readonly effort?: string | null;\n readonly childSessionId?: SessionId;\n}"
3687
3743
  },
3688
3744
  {
3689
3745
  "name": "RoomPlan",
3690
3746
  "declaration": "export interface RoomPlan {\n version: 1;\n id: string;\n revision: number;\n objective: string;\n status: 'draft' | 'running' | 'paused' | 'completed' | 'cancelled';\n reason?: string;\n budget: PlanBudget;\n activeMs: number;\n resumedAt?: number;\n stages: { id: string; title: string; }[];\n tasks: PlanTask[];\n completion?: PlanEvidence;\n requests: { id: string; signature: string; }[];\n}"
3691
3747
  },
3748
+ {
3749
+ "name": "RoomQuestionAnswer",
3750
+ "declaration": "export interface RoomQuestionAnswer {\n readonly id: string;\n readonly selected: readonly string[];\n readonly custom?: string;\n}"
3751
+ },
3752
+ {
3753
+ "name": "RoomQuestionEvent",
3754
+ "declaration": "export interface RoomQuestionEvent {\n readonly id: string;\n readonly member: string;\n readonly memberId: string;\n readonly questions: readonly RoomQuestionItem[];\n}"
3755
+ },
3756
+ {
3757
+ "name": "RoomQuestionItem",
3758
+ "declaration": "export interface RoomQuestionItem {\n readonly id: string;\n readonly question: string;\n readonly header?: string;\n readonly options?: readonly RoomQuestionOption[];\n readonly multiSelect?: boolean;\n}"
3759
+ },
3760
+ {
3761
+ "name": "RoomQuestionOption",
3762
+ "declaration": "export interface RoomQuestionOption {\n readonly label: string;\n readonly description?: string;\n}"
3763
+ },
3764
+ {
3765
+ "name": "RoomQuestionResolvedEvent",
3766
+ "declaration": "export interface RoomQuestionResolvedEvent {\n readonly id: string;\n readonly outcome: 'answered' | 'cancelled';\n readonly answers?: readonly RoomQuestionAnswer[];\n}"
3767
+ },
3692
3768
  {
3693
3769
  "name": "RoomRelayEvent",
3694
- "declaration": "export interface RoomRelayEvent {\n readonly id: string;\n readonly from: string;\n readonly to: string;\n readonly content: string;\n readonly provenance?: Record<string, RoomJsonValue>;\n}"
3770
+ "declaration": "export interface RoomRelayEvent {\n readonly id: string;\n readonly from: string;\n readonly to: string;\n readonly content: string;\n readonly provenance?: Record<string, RoomJsonValue>;\n readonly reason?: RoomHoldReason;\n readonly intent?: RoomHeldDispatch;\n}"
3695
3771
  },
3696
3772
  {
3697
3773
  "name": "RoomRelayResolvedEvent",
3698
3774
  "declaration": "export interface RoomRelayResolvedEvent {\n readonly id: string;\n readonly state: 'confirmed' | 'dismissed' | 'sent';\n}"
3699
3775
  },
3776
+ {
3777
+ "name": "RoomReportGateEvent",
3778
+ "declaration": "export interface RoomReportGateEvent {\n readonly dispatchSeq: number;\n readonly memberId: string;\n readonly member: string;\n readonly verdict: 'deliver' | 'hold' | 'release';\n readonly reason: string;\n readonly probability?: number;\n}"
3779
+ },
3700
3780
  {
3701
3781
  "name": "RoomRunStateEvent",
3702
- "declaration": "export interface RoomRunStateEvent {\n readonly childSessionId?: SessionId;\n readonly model?: string;\n readonly effort?: string;\n readonly tokens?: number;\n readonly runId?: string;\n readonly member: string;\n readonly state: 'running' | 'done' | 'cancelled' | 'failed';\n readonly startedAt: number;\n readonly elapsedMs?: number;\n readonly error?: string;\n}"
3782
+ "declaration": "export interface RoomRunStateEvent {\n readonly childSessionId?: SessionId;\n readonly childTurn?: number;\n readonly model?: string;\n readonly effort?: string;\n readonly tokens?: number;\n readonly runId?: string;\n readonly member: string;\n readonly state: 'running' | 'done' | 'cancelled' | 'failed';\n readonly startedAt: number;\n readonly elapsedMs?: number;\n readonly error?: string;\n}"
3783
+ },
3784
+ {
3785
+ "name": "RoomRunUsage",
3786
+ "declaration": "export interface RoomRunUsage {\n readonly inputTokens: number;\n readonly outputTokens: number;\n readonly cacheReadTokens?: number;\n readonly cacheWriteTokens?: number;\n readonly reasoningTokens?: number;\n}"
3787
+ },
3788
+ {
3789
+ "name": "RoomSettingsEvent",
3790
+ "declaration": "export interface RoomSettingsEvent {\n readonly memberMessages?: 'free' | 'confirm';\n readonly hopLimit?: number;\n readonly paused?: boolean;\n readonly reportTiming?: 'judge' | 'each';\n readonly autoTaskFiling?: boolean;\n readonly reportThreshold?: number;\n readonly reportWaitMinutes?: number;\n readonly helpReminderMinutes?: number;\n}"
3703
3791
  },
3704
3792
  {
3705
3793
  "name": "RoomSpeechEvent",
3706
- "declaration": "export interface RoomSpeechEvent {\n readonly interrupted?: 'cancelled' | 'failed';\n readonly member: string;\n readonly text: string;\n readonly childSessionId?: SessionId;\n readonly durationMs?: number;\n}"
3794
+ "declaration": "export interface RoomSpeechEvent {\n readonly interrupted?: 'cancelled' | 'failed';\n readonly reportedTo?: string;\n readonly member: string;\n readonly text: string;\n readonly childSessionId?: SessionId;\n readonly durationMs?: number;\n readonly runId?: string;\n readonly messageId?: string;\n}"
3707
3795
  },
3708
3796
  {
3709
3797
  "name": "RoomTaskAddedEvent",
@@ -3711,7 +3799,11 @@ export const TYPERT = {
3711
3799
  },
3712
3800
  {
3713
3801
  "name": "RoomTaskEditedEvent",
3714
- "declaration": "export interface RoomTaskEditedEvent {\n readonly id: string;\n readonly title?: string;\n readonly blockedBy?: string | null;\n}"
3802
+ "declaration": "export interface RoomTaskEditedEvent {\n readonly id: string;\n readonly title?: string;\n readonly blockedBy?: string | null;\n readonly member?: string;\n}"
3803
+ },
3804
+ {
3805
+ "name": "RoomTaskLinkEvent",
3806
+ "declaration": "export interface RoomTaskLinkEvent {\n readonly message: string;\n readonly task: string;\n readonly by: 'human' | 'coordinator' | 'model';\n readonly probability?: number;\n}"
3715
3807
  },
3716
3808
  {
3717
3809
  "name": "RoomTaskUpdatedEvent",
@@ -3751,7 +3843,7 @@ export const TYPERT = {
3751
3843
  },
3752
3844
  {
3753
3845
  "name": "SessionEventMap",
3754
- "declaration": "export interface SessionEventMap {\n 'turn/start': { turn: number; };\n 'turn/end': { turn: number; reason: TurnEndReason; };\n 'step/start': { turn: number; step: number; };\n 'step/end': { turn: number; step: number; };\n 'user/message': UserMessage;\n 'developer/message': { turn: number; step: number; message: DeveloperMessage; headerSeq?: SessionSeq; };\n 'system/message': { turn: number; step: number; message: SystemMessage; };\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; stream: AssistantStreamRecord[]; usage?: TokenUsage; interrupted?: true; };\n 'assistant/attempt': { turn: number; step: number; stream: AssistantStreamRecord[]; };\n 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string; };\n 'tool/result': { turn: number; step: number; message: ToolResultMessage; error?: { name: string; code: string; reason?: string; }; meta?: JsonValue; };\n 'request/header': { header: EpochHeader; reason: RequestHeaderReason; startsSeries?: true; };\n 'request/context': RequestContext;\n 'session/end-seed': { inherited?: true; };\n 'agent/inbox/spliced': { target: InboxTarget; start: number; removedCount?: number; inserted: UserMessage[]; outcome?: 'canceled'; };\n 'working-directory/change': { cwd: string; };\n 'sandbox/mode': { mode: SandboxMode; source?: 'delegation'; };\n 'approval/asked': { id: ApprovalRequestId; toolName: string; callId?: ToolCallId; reason?: string; };\n 'approval/decided': { id: ApprovalRequestId; outcome: ApprovalOutcome; };\n 'approval/policy': { policy: ApprovalPolicy; source?: 'delegation'; };\n 'tool/ptc-dispatch-start': PtcDispatchStartEventData;\n 'tool/ptc-dispatch': PtcDispatchEventData;\n 'agent-preset/selected': { agentPreset: string; };\n 'job/registered': JobRegisteredData;\n 'job/settled': JobSettledData;\n 'command/run': { commandId: CommandId; name: string; args?: string; source: CommandSource; };\n 'command/done': { commandId: CommandId; kind: 'success' | 'error'; text?: string; sourceEventSeq?: import('@deepseek-ai/dsh-session/types').SessionSeq; };\n 'image/offload': { targets: ImageOffloadTarget[]; };\n 'session/title': SessionTitleEventData;\n 'todo/write': { todos: TodoItem[]; };\n 'model/selection': ModelSelection;\n 'permission/preset': { preset: string; };\n 'subagent/descriptor': SubagentDescriptorData;\n 'subagent/catalog': SubagentCatalogEvent;\n 'compaction/start': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; };\n 'compaction/summary': { compactionId: CompactionId; sourceCommandId?: CommandId; summary: ContentBlock[]; shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; provider: string; model: string; maxTokens?: number; usage?: TokenUsage; } & ({ rawOutput: ContentBlock[]; llmStreamCall: true; } | { rawOutput?: ContentBlock[]; llmStreamCall?: never; });\n 'compaction/end': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; error?: string; };\n 'compaction/prune': { shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; };\n 'feedback/record': FeedbackRecord;\n 'llm/retry': LlmRetryEventData;\n 'llm/retry-started': LlmRetryStartedEventData;\n 'team/member': { version: 2; teamId: TeamId; member: TeamMemberSnapshot; };\n 'team/task': { version: 2; teamId: TeamId; task: TeamTaskSnapshot; };\n 'team/message/queued': { version: 2; teamId: TeamId; message: TeamMessageSnapshot; };\n 'team/message/delivered': { version: 2; teamId: TeamId; messageId: TeamMessageId; targetId: SessionId; };\n 'goal/change': GoalChangeMeta;\n 'feedback/message-put': MessageFeedbackPut;\n 'feedback/message-delete': MessageFeedbackDelete;\n 'plan/mode': { active: boolean; };\n 'schedule/change': ScheduleChange;\n 'subagent/model-selection-policy': { allowedModels: AllowedModelRoute[]; };\n 'workspace/changes': { turn: number; };\n 'local-agent/stream': LocalAgentStreamCheckpoint;\n 'room/created': RoomCreatedEvent;\n 'room/member-added': RoomMemberAddedEvent;\n 'room/member-updated': RoomMemberUpdatedEvent;\n 'room/member-removed': RoomMemberRemovedEvent;\n 'room/dispatch': RoomDispatchEvent;\n 'room/speech': RoomSpeechEvent;\n 'room/run-state': RoomRunStateEvent;\n 'room/execution-metadata': RoomExecutionMetadataEvent;\n 'room/relay': RoomRelayEvent;\n 'room/relay-resolved': RoomRelayResolvedEvent;\n 'room/task-added': RoomTaskAddedEvent;\n 'room/task-updated': RoomTaskUpdatedEvent;\n 'room/task-edited': RoomTaskEditedEvent;\n 'room/goal': RoomGoalEvent;\n 'room/plan-state': RoomPlan;\n 'room/coordinator': RoomCoordinatorEvent;\n 'room/delivery-state': RoomDeliveryStateEvent;\n}"
3846
+ "declaration": "export interface SessionEventMap {\n 'turn/start': { turn: number; };\n 'turn/end': { turn: number; reason: TurnEndReason; };\n 'step/start': { turn: number; step: number; };\n 'step/end': { turn: number; step: number; };\n 'user/message': UserMessage;\n 'developer/message': { turn: number; step: number; message: DeveloperMessage; headerSeq?: SessionSeq; };\n 'system/message': { turn: number; step: number; message: SystemMessage; };\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; stream: AssistantStreamRecord[]; usage?: TokenUsage; interrupted?: true; };\n 'assistant/attempt': { turn: number; step: number; stream: AssistantStreamRecord[]; };\n 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string; };\n 'tool/result': { turn: number; step: number; message: ToolResultMessage; error?: { name: string; code: string; reason?: string; }; meta?: JsonValue; };\n 'request/header': { header: EpochHeader; reason: RequestHeaderReason; startsSeries?: true; };\n 'request/context': RequestContext;\n 'session/end-seed': { inherited?: true; };\n 'agent/inbox/spliced': { target: InboxTarget; start: number; removedCount?: number; inserted: UserMessage[]; outcome?: 'canceled'; };\n 'working-directory/change': { cwd: string; };\n 'sandbox/mode': { mode: SandboxMode; source?: 'delegation'; };\n 'approval/asked': { id: ApprovalRequestId; toolName: string; callId?: ToolCallId; reason?: string; };\n 'approval/decided': { id: ApprovalRequestId; outcome: ApprovalOutcome; };\n 'approval/policy': { policy: ApprovalPolicy; source?: 'delegation'; };\n 'tool/ptc-dispatch-start': PtcDispatchStartEventData;\n 'tool/ptc-dispatch': PtcDispatchEventData;\n 'agent-preset/selected': { agentPreset: string; };\n 'job/registered': JobRegisteredData;\n 'job/settled': JobSettledData;\n 'command/run': { commandId: CommandId; name: string; args?: string; source: CommandSource; };\n 'command/done': { commandId: CommandId; kind: 'success' | 'error'; text?: string; sourceEventSeq?: import('@deepseek-ai/dsh-session/types').SessionSeq; };\n 'image/offload': { targets: ImageOffloadTarget[]; };\n 'session/title': SessionTitleEventData;\n 'todo/write': { todos: TodoItem[]; };\n 'model/selection': ModelSelection;\n 'permission/preset': { preset: string; };\n 'subagent/descriptor': SubagentDescriptorData;\n 'subagent/catalog': SubagentCatalogEvent;\n 'compaction/start': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; };\n 'compaction/summary': { compactionId: CompactionId; sourceCommandId?: CommandId; summary: ContentBlock[]; shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; provider: string; model: string; maxTokens?: number; usage?: TokenUsage; } & ({ rawOutput: ContentBlock[]; llmStreamCall: true; } | { rawOutput?: ContentBlock[]; llmStreamCall?: never; });\n 'compaction/end': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; error?: string; };\n 'compaction/prune': { shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; };\n 'feedback/record': FeedbackRecord;\n 'llm/retry': LlmRetryEventData;\n 'llm/retry-started': LlmRetryStartedEventData;\n 'team/member': { version: 2; teamId: TeamId; member: TeamMemberSnapshot; };\n 'team/task': { version: 2; teamId: TeamId; task: TeamTaskSnapshot; };\n 'team/message/queued': { version: 2; teamId: TeamId; message: TeamMessageSnapshot; };\n 'team/message/delivered': { version: 2; teamId: TeamId; messageId: TeamMessageId; targetId: SessionId; };\n 'goal/change': GoalChangeMeta;\n 'feedback/message-put': MessageFeedbackPut;\n 'feedback/message-delete': MessageFeedbackDelete;\n 'plan/mode': { active: boolean; };\n 'schedule/change': ScheduleChange;\n 'subagent/model-selection-policy': { allowedModels: AllowedModelRoute[]; };\n 'workspace/changes': { turn: number; };\n 'local-agent/stream': LocalAgentStreamCheckpoint;\n 'room/created': RoomCreatedEvent;\n 'room/member-added': RoomMemberAddedEvent;\n 'room/member-updated': RoomMemberUpdatedEvent;\n 'room/member-removed': RoomMemberRemovedEvent;\n 'room/dispatch': RoomDispatchEvent;\n 'room/speech': RoomSpeechEvent;\n 'room/run-state': RoomRunStateEvent;\n 'room/execution-metadata': RoomExecutionMetadataEvent;\n 'room/relay': RoomRelayEvent;\n 'room/relay-resolved': RoomRelayResolvedEvent;\n 'room/approval': RoomApprovalEvent;\n 'room/approval-resolved': RoomApprovalResolvedEvent;\n 'room/question': RoomQuestionEvent;\n 'room/question-resolved': RoomQuestionResolvedEvent;\n 'room/task-added': RoomTaskAddedEvent;\n 'room/task-updated': RoomTaskUpdatedEvent;\n 'room/task-edited': RoomTaskEditedEvent;\n 'room/goal': RoomGoalEvent;\n 'room/settings': RoomSettingsEvent;\n 'room/report-gate': RoomReportGateEvent;\n 'room/decision': RoomDecisionEvent;\n 'room/task-link': RoomTaskLinkEvent;\n 'room/job-stopped': RoomJobStoppedEvent;\n 'room/help': RoomHelpEvent;\n 'room/help-message': RoomHelpMessageEvent;\n 'room/help-state': RoomHelpStateEvent;\n 'room/help-in': RoomHelpInEvent;\n 'room/help-link': { readonly sessionId: string; readonly title: string; };\n 'room/help-unlink': { readonly sessionId: string; };\n 'room/help-nudge-dismissed': { readonly sessionId: string; };\n 'room/plan-state': RoomPlan;\n 'room/coordinator': RoomCoordinatorEvent;\n 'room/delivery-state': RoomDeliveryStateEvent;\n}"
3755
3847
  },
3756
3848
  {
3757
3849
  "name": "SessionEventType",