@agentclientprotocol/claude-agent-acp 0.89.2-preview.2 → 0.89.2-preview.20

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.
Files changed (52) hide show
  1. package/README.md +51 -8
  2. package/dist/acp-agent.d.ts +131 -23
  3. package/dist/acp-agent.d.ts.map +1 -1
  4. package/dist/acp-agent.js +879 -239
  5. package/dist/acp-subagents.d.ts +16 -6
  6. package/dist/acp-subagents.d.ts.map +1 -1
  7. package/dist/acp-subagents.js +8 -2
  8. package/dist/async-tasks.d.ts +4 -1
  9. package/dist/async-tasks.d.ts.map +1 -1
  10. package/dist/auth-status.d.ts +2 -2
  11. package/dist/auth-status.d.ts.map +1 -1
  12. package/dist/auth-status.js +18 -4
  13. package/dist/exit-plan.d.ts +17 -0
  14. package/dist/exit-plan.d.ts.map +1 -1
  15. package/dist/exit-plan.js +34 -0
  16. package/dist/native-subagents.d.ts +190 -11
  17. package/dist/native-subagents.d.ts.map +1 -1
  18. package/dist/native-subagents.js +419 -40
  19. package/dist/settings.d.ts +6 -0
  20. package/dist/settings.d.ts.map +1 -1
  21. package/dist/settings.js +13 -0
  22. package/dist/subagent-history.d.ts +27 -2
  23. package/dist/subagent-history.d.ts.map +1 -1
  24. package/dist/subagent-history.js +38 -10
  25. package/dist/subagent-replay.d.ts +108 -0
  26. package/dist/subagent-replay.d.ts.map +1 -0
  27. package/dist/subagent-replay.js +261 -0
  28. package/dist/tool-calls/background.d.ts +9 -0
  29. package/dist/tool-calls/background.d.ts.map +1 -1
  30. package/dist/tool-calls/background.js +25 -0
  31. package/dist/tool-calls/renderer.d.ts +32 -7
  32. package/dist/tool-calls/renderer.d.ts.map +1 -1
  33. package/dist/tool-calls/renderer.js +54 -21
  34. package/dist/turn-events.d.ts +39 -17
  35. package/dist/turn-events.d.ts.map +1 -1
  36. package/dist/v2/agent.d.ts.map +1 -1
  37. package/dist/v2/agent.js +52 -14
  38. package/dist/v2/initialize.d.ts.map +1 -1
  39. package/dist/v2/initialize.js +10 -1
  40. package/dist/v2/prompt.d.ts +29 -18
  41. package/dist/v2/prompt.d.ts.map +1 -1
  42. package/dist/v2/prompt.js +54 -43
  43. package/dist/v2/session-update.d.ts +11 -0
  44. package/dist/v2/session-update.d.ts.map +1 -1
  45. package/dist/v2/session-update.js +67 -0
  46. package/dist/v2/session.d.ts +3 -12
  47. package/dist/v2/session.d.ts.map +1 -1
  48. package/dist/v2/session.js +5 -18
  49. package/dist/v2/tool-call-meta.d.ts +44 -0
  50. package/dist/v2/tool-call-meta.d.ts.map +1 -0
  51. package/dist/v2/tool-call-meta.js +72 -0
  52. package/package.json +1 -1
@@ -85,12 +85,31 @@ export declare class AcpToolCallRenderer {
85
85
  replay?: boolean);
86
86
  static for(capabilities: AcpClientCapabilities | null | undefined, replay?: boolean): AcpToolCallRenderer;
87
87
  /**
88
- * The status of a tool result. `nonExecution` is why Claude Code stamped an
89
- * error result instead of the tool's output. A run that was aborted is
90
- * `cancelled` for a v2 client, which has that status; every other client
91
- * gets `failed`, with the kind in `_meta.claudeCode.nonExecutionKind`.
88
+ * Whether the client keeps a tool call's `_meta` across reports: AIR merges
89
+ * its keys, and v2 stores it. Such a client gets no `toolResponse` text that
90
+ * the tool call's content already shows, which it would otherwise keep.
92
91
  */
93
- resultStatus(isError: boolean, nonExecution: ToolResultMeta | undefined): ToolCallStatus;
92
+ private get keepsMeta();
93
+ /**
94
+ * The status of a tool result. Claude Code reports a run that it aborted in
95
+ * one of three ways:
96
+ * - an error result whose `nonExecution` kind says so (`interrupted`,
97
+ * `cancelled`);
98
+ * - a command result that says `interrupted` (for example, a steering
99
+ * message landed just before the command started);
100
+ * - any error result of the work that a `session/cancel` stopped
101
+ * (`run.cancelled`). The kind does not say so there: CLI 2.1.293 stamps a
102
+ * command that the interrupt killed `user-rejected`, as if the user had
103
+ * refused it.
104
+ *
105
+ * Such a run is `cancelled` for a v2 client, which has that status. Every
106
+ * other client gets `failed` for the error, with the kind in
107
+ * `_meta.claudeCode.nonExecutionKind`, and `completed` for the command.
108
+ */
109
+ resultStatus(isError: boolean, nonExecution: ToolResultMeta | undefined, run?: {
110
+ interrupted?: boolean;
111
+ cancelled?: boolean;
112
+ }): ToolCallStatus;
94
113
  /** The facts of a tool use. */
95
114
  facts(toolUse: Pick<ToolUse, "name" | "input">, cwd?: string): ToolUseFacts;
96
115
  /** The standard fields of a tool use: the title, the kind, the content, and the locations. */
@@ -146,6 +165,7 @@ export declare class AcpToolCallRenderer {
146
165
  resultFacts(toolUse: ToolUse, result: ResultBlock, structured?: unknown): ToolResultFacts;
147
166
  /** The result fields of a tool result, before the status and the tool name. */
148
167
  resultFields(toolUse: ToolUse, result: ResultBlock, structured?: unknown): RenderedResult;
168
+ private fieldsOfResult;
149
169
  /**
150
170
  * The reports of a tool result. A command sends its output as a separate
151
171
  * report first, like codex-acp: the output, then the exit and the status.
@@ -155,6 +175,7 @@ export declare class AcpToolCallRenderer {
155
175
  result(toolUse: ToolUse, result: ResultBlock, options?: {
156
176
  structured?: unknown;
157
177
  nonExecution?: ToolResultMeta;
178
+ cancelled?: boolean;
158
179
  }): ToolCallUpdate[];
159
180
  /**
160
181
  * Whether AIR shows [toolUse] as the list of viewed files: a read or a
@@ -165,7 +186,8 @@ export declare class AcpToolCallRenderer {
165
186
  /**
166
187
  * The report of a PostToolUse hook: the final change of an edit tool, and
167
188
  * the `status` and `isAsync` markers of the `tool_response`. The rest of the
168
- * `tool_response` repeats output that the content already carries.
189
+ * `tool_response` repeats output that the content already carries, such as
190
+ * the whole text of a written file.
169
191
  */
170
192
  hookResult(toolUse: Pick<ToolUse, "id" | "name">, toolResponse: unknown, cwd?: string): Promise<ToolCallUpdate | undefined>;
171
193
  /**
@@ -199,11 +221,14 @@ export declare class AcpToolCallRenderer {
199
221
  * reached a complete assistant message, for example because Claude switched
200
222
  * to a steering message), a v2 client gets `cancelled` and every other
201
223
  * client `failed`, since v1 has no `cancelled`. If Claude Code ran it but
202
- * returned no result, it failed.
224
+ * returned no result, it failed, unless a `session/cancel` ended the turn
225
+ * (`cancelled`): the cancel stopped the run, so a v2 client gets `cancelled`
226
+ * for it too.
203
227
  */
204
228
  unfinished(call: {
205
229
  toolCallId: string;
206
230
  ran: boolean;
231
+ cancelled?: boolean;
207
232
  }): ToolCallUpdate;
208
233
  /**
209
234
  * The report of a tool progress beat. The field tracker sends the
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/tool-calls/renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/tool-calls/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,IAAI,qBAAqB,EAC3C,wBAAwB,EACxB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACf,MAAM,0BAA0B,CAAC;AAQlC,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK5F,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AAa3D,wFAAwF;AACxF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAExF;AAED,yCAAyC;AACzC,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,CAAC,EAAE;QAKX,QAAQ,CAAC,EAAE,MAAM,CAAC;QAKlB,YAAY,CAAC,EAAE,OAAO,CAAC;QAIvB,eAAe,CAAC,EAAE,MAAM,CAAC;QAMzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAG1B,YAAY,CAAC,EAAE,MAAM,CAAC;QAEtB,SAAS,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KAC9C,CAAC;IAEF,SAAS,CAAC,EAAE;QACV,GAAG,CAAC,EAAE;YACJ,OAAO,CAAC,EAAE,MAAM,CAAC;YAGjB,YAAY,CAAC,EAAE,MAAM,CAAC;YAGtB,QAAQ,CAAC,EAAE,IAAI,CAAC;YAGhB,KAAK,CAAC,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,IAAI,CAAC,EAAE,MAAM,CAAA;aAAE,CAAC;YACxC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;SACxB,CAAC;KACH,CAAC;IAEF,gBAAgB,CAAC,EAAE,IAAI,CAAC;IAExB,aAAa,CAAC,EAAE;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,eAAe,CAAC,EAAE;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,qBAAqB,CAAC,EAAE;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,aAAa,CAAC,EAAE;QACd,WAAW,EAAE,MAAM,CAAC;QACpB;;;WAGG;QACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;CACH,CAAC;AAEF,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,IAAI,CACV,cAAc,EACd,eAAe,GAAG,iBAAiB,GAAG,uBAAuB,GAAG,eAAe,CAChF,CAAC;CACH;AAED,4DAA4D;AAC5D,KAAK,WAAW,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AAE/C;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAE5B,QAAQ,CAAC,YAAY,EAAE,kBAAkB;IACzC,sEAAsE;IACtE,QAAQ,CAAC,MAAM;gBAFN,YAAY,GAAE,kBAA6C;IACpE,sEAAsE;IAC7D,MAAM,UAAQ;IAGzB,MAAM,CAAC,GAAG,CACR,YAAY,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,EACtD,MAAM,UAAQ,GACb,mBAAmB;IAItB;;;;OAIG;IACH,OAAO,KAAK,SAAS,GAEpB;IAED;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CACV,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,cAAc,GAAG,SAAS,EACxC,GAAG,GAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO,GACvD,cAAc;IAQjB,+BAA+B;IAC/B,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,YAAY;IAQ3E,8FAA8F;IAC9F,QAAQ,CACN,OAAO,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,MAAM,GACX;QACD,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QAC3B,OAAO,EAAE,eAAe,EAAE,CAAC;QAC3B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;KAChC;IAUD;;;OAGG;IACH,QAAQ,CACN,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,eAAe,EAAE,CAAA;KAAO,GAC1F,cAAc;IA4BjB,6DAA6D;IAC7D,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,cAAc;IAc1D;;;;;;OAMG;IACH,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM;;;;;;;;;IAarF;;;;;OAKG;IACH,kBAAkB,CAChB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE;QACP,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,eAAe,EAAE,CAAC;QACnC,cAAc,CAAC,EAAE,gBAAgB,EAAE,CAAC;QACpC,IAAI,CAAC,EAAE,cAAc,CAAC;QACtB,4EAA4E;QAC5E,eAAe,CAAC,EAAE,eAAe,EAAE,CAAC;KAChC,GACL,wBAAwB,CAAC,UAAU,CAAC;IAgCvC,kCAAkC;IAClC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,eAAe;IAqBzF,+EAA+E;IAC/E,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,cAAc;IAIzF,OAAO,CAAC,cAAc;IA0DtB;;;;;OAKG;IACH,MAAM,CACJ,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,cAAc,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO,GACzF,cAAc,EAAE;IA2EnB;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAWvB;;;;;OAKG;IACG,UAAU,CACd,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,MAAM,CAAC,EACrC,YAAY,EAAE,OAAO,EACrB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IA4BtC;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAChD,GAAG,cAAc;IAyBlB;;;;OAIG;IACH,gBAAgB,CAAC,MAAM,EAAE;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,cAAc;IA2BlB;;;;;;;;;OASG;IACH,UAAU,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,cAAc;IAkB3F;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,GAAG,cAAc;IAsBlB;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO;IAgBzD;;;;OAIG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,eAAe,EAAE;IAS1E;;;;;OAKG;IACH,WAAW,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,cAAc;CA0BtF"}
@@ -41,15 +41,35 @@ export class AcpToolCallRenderer {
41
41
  return new AcpToolCallRenderer(ClientCapabilities.from(capabilities), replay);
42
42
  }
43
43
  /**
44
- * The status of a tool result. `nonExecution` is why Claude Code stamped an
45
- * error result instead of the tool's output. A run that was aborted is
46
- * `cancelled` for a v2 client, which has that status; every other client
47
- * gets `failed`, with the kind in `_meta.claudeCode.nonExecutionKind`.
44
+ * Whether the client keeps a tool call's `_meta` across reports: AIR merges
45
+ * its keys, and v2 stores it. Such a client gets no `toolResponse` text that
46
+ * the tool call's content already shows, which it would otherwise keep.
48
47
  */
49
- resultStatus(isError, nonExecution) {
50
- if (!isError)
51
- return "completed";
52
- return this.capabilities.v2 && isAbortedToolResult(nonExecution) ? V2_CANCELLED : "failed";
48
+ get keepsMeta() {
49
+ return this.capabilities.air.client || this.capabilities.v2;
50
+ }
51
+ /**
52
+ * The status of a tool result. Claude Code reports a run that it aborted in
53
+ * one of three ways:
54
+ * - an error result whose `nonExecution` kind says so (`interrupted`,
55
+ * `cancelled`);
56
+ * - a command result that says `interrupted` (for example, a steering
57
+ * message landed just before the command started);
58
+ * - any error result of the work that a `session/cancel` stopped
59
+ * (`run.cancelled`). The kind does not say so there: CLI 2.1.293 stamps a
60
+ * command that the interrupt killed `user-rejected`, as if the user had
61
+ * refused it.
62
+ *
63
+ * Such a run is `cancelled` for a v2 client, which has that status. Every
64
+ * other client gets `failed` for the error, with the kind in
65
+ * `_meta.claudeCode.nonExecutionKind`, and `completed` for the command.
66
+ */
67
+ resultStatus(isError, nonExecution, run = {}) {
68
+ const aborted = run.interrupted === true ||
69
+ (isError && (run.cancelled === true || isAbortedToolResult(nonExecution)));
70
+ if (this.capabilities.v2 && aborted)
71
+ return V2_CANCELLED;
72
+ return isError ? "failed" : "completed";
53
73
  }
54
74
  /** The facts of a tool use. */
55
75
  facts(toolUse, cwd) {
@@ -191,7 +211,9 @@ export class AcpToolCallRenderer {
191
211
  }
192
212
  /** The result fields of a tool result, before the status and the tool name. */
193
213
  resultFields(toolUse, result, structured) {
194
- const facts = this.resultFacts(toolUse, result, structured);
214
+ return this.fieldsOfResult(toolUse, result, this.resultFacts(toolUse, result, structured));
215
+ }
216
+ fieldsOfResult(toolUse, result, facts) {
195
217
  const { command, ...fields } = facts;
196
218
  if (!command)
197
219
  return fields;
@@ -252,7 +274,8 @@ export class AcpToolCallRenderer {
252
274
  * when no other field carries the result.
253
275
  */
254
276
  result(toolUse, result, options = {}) {
255
- const { _meta: resultMeta, ...fields } = this.resultFields(toolUse, result, options.structured);
277
+ const facts = this.resultFacts(toolUse, result, options.structured);
278
+ const { _meta: resultMeta, ...fields } = this.fieldsOfResult(toolUse, result, facts);
256
279
  // AIR shows a read or a search that names a path as the list of viewed
257
280
  // files. That view does not show the text of the result, so it stays out.
258
281
  const viewedFiles = this.capabilities.air.client && result.is_error !== true && this.namesViewedFile(toolUse);
@@ -299,7 +322,10 @@ export class AcpToolCallRenderer {
299
322
  },
300
323
  toolCallId: toolUse.id,
301
324
  sessionUpdate: "tool_call_update",
302
- status: this.resultStatus(result.is_error === true, options.nonExecution),
325
+ status: this.resultStatus(result.is_error === true, options.nonExecution, {
326
+ interrupted: facts.command?.interrupted === true,
327
+ cancelled: options.cancelled,
328
+ }),
303
329
  ...(rawOutput !== undefined ? { rawOutput } : {}),
304
330
  ...(planFilePath ? { rawInput: planFileInput(toolUse.input, planFilePath) } : {}),
305
331
  ...fields,
@@ -339,14 +365,15 @@ export class AcpToolCallRenderer {
339
365
  /**
340
366
  * The report of a PostToolUse hook: the final change of an edit tool, and
341
367
  * the `status` and `isAsync` markers of the `tool_response`. The rest of the
342
- * `tool_response` repeats output that the content already carries.
368
+ * `tool_response` repeats output that the content already carries, such as
369
+ * the whole text of a written file.
343
370
  */
344
371
  async hookResult(toolUse, toolResponse, cwd) {
345
372
  const reporter = reporterFor(toolUse.name);
346
373
  const change = reporter.hookResult
347
374
  ? await reporter.hookResult(toolResponse, { cwd, capabilities: this.capabilities })
348
375
  : {};
349
- if (!this.capabilities.air.client) {
376
+ if (!this.keepsMeta) {
350
377
  // The upstream shape: the whole tool_response, on every hook.
351
378
  return {
352
379
  _meta: { claudeCode: { toolResponse, toolName: toolUse.name } },
@@ -402,9 +429,10 @@ export class AcpToolCallRenderer {
402
429
  */
403
430
  permissionDenied(denial) {
404
431
  const reason = denial.decisionReason ?? denial.message;
405
- // AIR gets the SDK message only when it differs from the reason, which
406
- // the content shows. Every other client gets the upstream toolResponse.
407
- const extraMessage = !this.capabilities.air.client
432
+ // AIR and v2 get the SDK message only when it differs from the reason,
433
+ // which the content shows. Every other client gets the upstream
434
+ // toolResponse.
435
+ const extraMessage = !this.keepsMeta
408
436
  ? { decisionReason: denial.decisionReason, message: denial.message }
409
437
  : denial.decisionReason !== undefined &&
410
438
  denial.message !== undefined &&
@@ -431,17 +459,22 @@ export class AcpToolCallRenderer {
431
459
  * reached a complete assistant message, for example because Claude switched
432
460
  * to a steering message), a v2 client gets `cancelled` and every other
433
461
  * client `failed`, since v1 has no `cancelled`. If Claude Code ran it but
434
- * returned no result, it failed.
462
+ * returned no result, it failed, unless a `session/cancel` ended the turn
463
+ * (`cancelled`): the cancel stopped the run, so a v2 client gets `cancelled`
464
+ * for it too.
435
465
  */
436
466
  unfinished(call) {
467
+ const stopped = !call.ran || call.cancelled === true;
437
468
  return {
438
469
  sessionUpdate: "tool_call_update",
439
470
  toolCallId: call.toolCallId,
440
- status: !call.ran && this.capabilities.v2 ? V2_CANCELLED : "failed",
471
+ status: stopped && this.capabilities.v2 ? V2_CANCELLED : "failed",
441
472
  content: [
442
- textContent(call.ran
443
- ? "Claude ended the turn without returning a result for this tool."
444
- : "Claude stopped this tool call before it ran."),
473
+ textContent(!call.ran
474
+ ? "Claude stopped this tool call before it ran."
475
+ : call.cancelled
476
+ ? "The turn was cancelled before this tool call returned a result."
477
+ : "Claude ended the turn without returning a result for this tool."),
445
478
  ],
446
479
  };
447
480
  }
@@ -1,10 +1,11 @@
1
1
  /**
2
- * A prompt turn as the adapter understands it, independent of the ACP version.
2
+ * A prompt turn and the foreground work of a session, as the adapter
3
+ * understands them, independent of the ACP version.
3
4
  *
4
- * The agent reports each turn through {@link TurnEvents}, and each ACP version
5
- * maps the events to its own messages. ACP v1 answers `session/prompt` when the
6
- * turn ends or fails. ACP v2 answers it when the prompt is inserted, and
7
- * reports the rest as session state.
5
+ * The agent reports how each prompt is answered through {@link TurnEvents}:
6
+ * ACP v1 answers `session/prompt` when the turn ends or fails, and ACP v2 when
7
+ * the prompt is inserted. ACP v2 also reports the session's work as state,
8
+ * which the agent reports through {@link ForegroundEvents}.
8
9
  *
9
10
  * The agent calls these synchronously while it updates its own state, so a
10
11
  * handler must not throw, nor call back into the agent before it returns.
@@ -23,18 +24,6 @@ export interface TurnEvents {
23
24
  * `/compact`), it is the command's result, after any output it streamed.
24
25
  */
25
26
  inserted(messageId: string): void;
26
- /**
27
- * The turn waits for the user: a permission request or a question is open in
28
- * the session. Requests do not say which prompt they are for, so this
29
- * includes one opened before the turn was inserted. Only reported after
30
- * {@link inserted}.
31
- */
32
- awaitingUser(): void;
33
- /**
34
- * The turn works again: no request is open any more. A turn that ends or
35
- * fails while it waits reports that instead.
36
- */
37
- resumed(): void;
38
27
  /**
39
28
  * The turn ended. A queued turn that is cancelled before it is inserted
40
29
  * ends too, without {@link inserted}; Claude Code may still run its prompt.
@@ -47,6 +36,39 @@ export interface TurnEvents {
47
36
  */
48
37
  failed(error: unknown): void;
49
38
  }
39
+ /**
40
+ * The foreground work of a session: what a client would wait for before it
41
+ * sends the next prompt. One piece of work runs at a time, and the next starts
42
+ * with {@link running}. The work is either:
43
+ *
44
+ * - A prompt's turn, from {@link TurnEvents.inserted} until its result, or
45
+ * until it fails or is cancelled. A turn that v1 holds open for the
46
+ * background subagents it spawned (`Turn.deferredSettle`) ends its work at
47
+ * its result all the same: the hold only delays v1's answer.
48
+ * - A model cycle that Claude Code starts on its own while no work runs: for
49
+ * example, its follow-up after a background command or subagent finished,
50
+ * or its answer to a message from another session. It runs until its result.
51
+ *
52
+ * A prompt that Claude Code takes in while a cycle runs takes the cycle over:
53
+ * the cycle reports nothing more, and the turn reports from there.
54
+ */
55
+ export interface ForegroundEvents {
56
+ /** The work started, or works again after it waited for the user. */
57
+ running(): void;
58
+ /**
59
+ * The work waits for the user: a permission request or a question is open in
60
+ * the session. Requests do not say which work they are for, so this includes
61
+ * one opened before the work started.
62
+ */
63
+ awaitingUser(): void;
64
+ /** The work ended. */
65
+ ended(outcome: TurnOutcome): void;
66
+ /**
67
+ * The work failed with `error`, the JSON-RPC error that v1 answers the
68
+ * prompt with.
69
+ */
70
+ failed(error: unknown): void;
71
+ }
50
72
  /** Why a turn ended. Every ACP version has these reasons. */
51
73
  export type StopReason = "end_turn" | "max_tokens" | "max_turn_requests" | "refusal" | "cancelled";
52
74
  /** How a turn ended. */
@@ -1 +1 @@
1
- {"version":3,"file":"turn-events.d.ts","sourceRoot":"","sources":["../src/turn-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;;OAKG;IACH,YAAY,IAAI,IAAI,CAAC;IACrB;;;OAGG;IACH,OAAO,IAAI,IAAI,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,YAAY,GAAG,mBAAmB,GAAG,SAAS,GAAG,WAAW,CAAC;AAEnG,wBAAwB;AACxB,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,UAAU,CAAC;IACvB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC"}
1
+ {"version":3,"file":"turn-events.d.ts","sourceRoot":"","sources":["../src/turn-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,OAAO,IAAI,IAAI,CAAC;IAChB;;;;OAIG;IACH,YAAY,IAAI,IAAI,CAAC;IACrB,sBAAsB;IACtB,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,YAAY,GAAG,mBAAmB,GAAG,SAAS,GAAG,WAAW,CAAC;AAEnG,wBAAwB;AACxB,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,UAAU,CAAC;IACvB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/v2/agent.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAkB,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAmB9E;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GACvC,EAAE,CAAC,QAAQ,CAoEb"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/v2/agent.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAkB,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAoB9E;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GACvC,EAAE,CAAC,QAAQ,CA2Eb"}
package/dist/v2/agent.js CHANGED
@@ -2,10 +2,11 @@ import * as v2 from "@agentclientprotocol/sdk/experimental/v2";
2
2
  import { ClaudeAcpAgent } from "../acp-agent.js";
3
3
  import { v1InitializeRequest, v2InitializeResponse } from "./initialize.js";
4
4
  import { v1PermissionResponse, v2PermissionRequest } from "./permission.js";
5
- import { v2Prompt } from "./prompt.js";
6
- import { v1ForkSessionRequests, v1NewSessionRequest, v1RestoreSessionRequest, v1SetSessionConfigOptionRequest, v2AvailableCommands, v2ConfigOptions, v2NewSessionResponse, v2ResumeSessionResponse, } from "./session.js";
7
- import { v2SessionUpdate } from "./session-update.js";
5
+ import { v2Foreground, v2Prompt } from "./prompt.js";
6
+ import { v1ForkSessionRequest, v1NewSessionRequest, v1RestoreSessionRequest, v1SetSessionConfigOptionRequest, v2AvailableCommands, v2ConfigOptions, v2NewSessionResponse, v2ResumeSessionResponse, } from "./session.js";
7
+ import { v2ChildStateUpdate, v2SessionUpdate } from "./session-update.js";
8
8
  import { V2Terminals } from "./terminal.js";
9
+ import { V2ToolCallMeta } from "./tool-call-meta.js";
9
10
  /**
10
11
  * The ACP v2 surface, for one connection.
11
12
  *
@@ -22,7 +23,12 @@ export function v2AgentApp(logger, onAgent) {
22
23
  .agent({ name: "claude-code-acp" })
23
24
  .onConnect((connection) => {
24
25
  client = new V2ClientConnection(connection.client, logger ?? console);
25
- agent = new ClaudeAcpAgent(client, logger, { v2: true });
26
+ agent = new ClaudeAcpAgent(client, logger, {
27
+ v2: true,
28
+ foreground: (sessionId) => v2Foreground((update) => {
29
+ void client.send({ sessionId, update });
30
+ }),
31
+ });
26
32
  onAgent(agent);
27
33
  })
28
34
  .onRequest(v2.methods.agent.initialize, async ({ params }) => v2InitializeResponse(await agent.initialize(v1InitializeRequest(params))))
@@ -50,17 +56,18 @@ export function v2AgentApp(logger, onAgent) {
50
56
  };
51
57
  })
52
58
  .onRequest(v2.methods.agent.session.fork, async ({ params }) => {
53
- const requests = v1ForkSessionRequests(params);
54
- const { sessionId } = await agent.unstable_forkSession(requests.fork);
59
+ // The agent starts the forked session, so the client can prompt it.
60
+ const response = await agent.unstable_forkSession(v1ForkSessionRequest(params));
55
61
  return {
56
- sessionId,
57
- ...v2ResumeSessionResponse(await agent.resumeSession(requests.resume(sessionId))),
58
- ...(await setupCommands(agent, sessionId, logger)),
62
+ sessionId: response.sessionId,
63
+ ...v2ResumeSessionResponse(response),
64
+ ...(await setupCommands(agent, response.sessionId, logger)),
59
65
  };
60
66
  })
61
67
  .onRequest(v2.methods.agent.session.close, async ({ params }) => {
62
68
  const response = await agent.closeSession(params);
63
69
  client.terminals.forget(params.sessionId);
70
+ client.toolCallMeta.forget(params.sessionId);
64
71
  return response;
65
72
  })
66
73
  .onRequest(v2.methods.agent.session.delete, ({ params }) => agent.deleteSession(params))
@@ -100,11 +107,16 @@ class V2ClientConnection {
100
107
  logger;
101
108
  /**
102
109
  * The sessions whose history replays, each with the messages that the
103
- * replay has cleared so far.
110
+ * replay has cleared so far. A subagent that a replay announces replays
111
+ * with it.
104
112
  */
105
113
  replays = new Map();
114
+ /** The session whose replay announced each replaying subagent. */
115
+ replayRoots = new Map();
106
116
  /** The display terminals of the commands that the agent runs. */
107
117
  terminals = new V2Terminals();
118
+ /** The `_meta` that the client stores for each tool call. */
119
+ toolCallMeta = new V2ToolCallMeta();
108
120
  constructor(ctx, logger) {
109
121
  this.ctx = ctx;
110
122
  this.logger = logger;
@@ -124,6 +136,12 @@ class V2ClientConnection {
124
136
  }
125
137
  finally {
126
138
  this.replays.delete(sessionId);
139
+ for (const [child, root] of this.replayRoots) {
140
+ if (root !== sessionId)
141
+ continue;
142
+ this.replays.delete(child);
143
+ this.replayRoots.delete(child);
144
+ }
127
145
  }
128
146
  }
129
147
  /**
@@ -147,17 +165,32 @@ class V2ClientConnection {
147
165
  return this.ctx.notify(method, params);
148
166
  }
149
167
  async sessionUpdate({ update, ...notification }) {
168
+ // A subagent that a replay announces replays too, so its messages are
169
+ // cleared before their first replayed chunk, as the parent's are.
170
+ if (update.sessionUpdate === "subagent_update" &&
171
+ this.replays.has(notification.sessionId) &&
172
+ !this.replays.has(update.sessionId)) {
173
+ this.replays.set(update.sessionId, new Set());
174
+ this.replayRoots.set(update.sessionId, this.replayRoots.get(notification.sessionId) ?? notification.sessionId);
175
+ }
150
176
  const updates = this.v2Updates(notification.sessionId, update).flatMap((v2Update) => {
151
177
  const clear = this.replayClear(notification.sessionId, v2Update);
152
178
  return clear ? [clear, v2Update] : [v2Update];
153
179
  });
180
+ // A subagent's work state also goes to the child's own stream, after the
181
+ // parent's copy.
182
+ const childState = v2ChildStateUpdate(update);
154
183
  // Every update goes to the connection before any is awaited, so an update
155
184
  // that another call sends meanwhile cannot come between them.
156
- await Promise.all(updates.map((v2Update) => this.ctx.notify(v2.methods.client.session.update, { ...notification, update: v2Update })));
185
+ await Promise.all([
186
+ ...updates.map((v2Update) => this.ctx.notify(v2.methods.client.session.update, { ...notification, update: v2Update })),
187
+ ...(childState ? [this.ctx.notify(v2.methods.client.session.update, childState)] : []),
188
+ ]);
157
189
  }
158
190
  /**
159
191
  * The v2 updates of a v1 update: for a tool call report, the updates of its
160
- * terminal first, then the report itself (see {@link V2Terminals}).
192
+ * terminal first (see {@link V2Terminals}), then the report itself, with the
193
+ * `_meta` that the client stores (see {@link V2ToolCallMeta}).
161
194
  */
162
195
  v2Updates(sessionId, update) {
163
196
  if (update.sessionUpdate !== "tool_call" && update.sessionUpdate !== "tool_call_update") {
@@ -165,7 +198,10 @@ class V2ClientConnection {
165
198
  return v2Update ? [v2Update] : [];
166
199
  }
167
200
  const { terminal, report } = this.terminals.split(sessionId, update);
168
- const reportUpdate = report && v2SessionUpdate(report);
201
+ if (!report)
202
+ return terminal;
203
+ const starts = report.sessionUpdate === "tool_call";
204
+ const reportUpdate = v2SessionUpdate(this.toolCallMeta.apply(sessionId, report, starts));
169
205
  return [...terminal, ...(reportUpdate ? [reportUpdate] : [])];
170
206
  }
171
207
  /**
@@ -187,7 +223,9 @@ class V2ClientConnection {
187
223
  return emptyMessage(kind, messageId);
188
224
  }
189
225
  async requestPermission(params, signal) {
190
- const response = await this.ctx.request(v2.methods.client.session.requestPermission, v2PermissionRequest(params), { cancellationSignal: signal });
226
+ // The subject is an update of the tool call, with its stored `_meta`.
227
+ const toolCall = this.toolCallMeta.subject(params.sessionId, params.toolCall);
228
+ const response = await this.ctx.request(v2.methods.client.session.requestPermission, v2PermissionRequest({ ...params, toolCall }), { cancellationSignal: signal });
191
229
  return v1PermissionResponse(response);
192
230
  }
193
231
  // Elicitation is the same in v1 and v2.
@@ -1 +1 @@
1
- {"version":3,"file":"initialize.d.ts","sourceRoot":"","sources":["../../src/v2/initialize.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAE/D,0DAA0D;AAC1D,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,EAAE,CAAC,iBAAiB,GAAG,iBAAiB,CA0BpF;AASD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,EAAE,CAAC,kBAAkB,CAuBxF"}
1
+ {"version":3,"file":"initialize.d.ts","sourceRoot":"","sources":["../../src/v2/initialize.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAE/D,0DAA0D;AAC1D,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,EAAE,CAAC,iBAAiB,GAAG,iBAAiB,CAmCpF;AASD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,EAAE,CAAC,kBAAkB,CAuBxF"}
@@ -26,6 +26,15 @@ export function v1InitializeRequest(request) {
26
26
  // compaction as a compaction entity rather than as a "Compact
27
27
  // conversation" tool call, also on replay.
28
28
  session: { configOptions: { boolean: {} }, notices: {}, compaction: {} },
29
+ // Every v2 client takes `plan_update`, with the draft's markdown and file
30
+ // plans, and `plan_removed`; v1 asks for the `plan` marker. With it, the
31
+ // agent shows an approved ExitPlanMode plan as a markdown plan.
32
+ plan: {},
33
+ // Subagent updates are part of v2's baseline session model (the subagents
34
+ // RFD), so every v2 client takes them; v1 asks for the `subagents`
35
+ // capability. With it, the agent reports each Agent or Task subagent as a
36
+ // child session.
37
+ subagents: {},
29
38
  // v1 marks terminal auth support with a boolean, v2 with an object.
30
39
  auth: {
31
40
  terminal: capabilities?.auth?.terminal != null,
@@ -78,7 +87,7 @@ export function v2InitializeResponse(response) {
78
87
  * - The session baseline: `session/new`, `list`, `resume` (with replay),
79
88
  * `close`, `prompt`, `cancel`, and `update`.
80
89
  * - `session/delete`, `session/fork` (which returns a session the client can
81
- * prompt, see `v1ForkSessionRequests`), and `additionalDirectories`.
90
+ * prompt at once), and `additionalDirectories`.
82
91
  * - The prompt content and MCP transports that the agent's v1 `initialize`
83
92
  * lists: images, embedded context, and HTTP servers. Stdio servers are in the
84
93
  * v1 baseline; v2 has no SSE transport.
@@ -7,31 +7,42 @@
7
7
  import { type PromptRequest } from "@agentclientprotocol/sdk";
8
8
  import * as v2 from "@agentclientprotocol/sdk/experimental/v2";
9
9
  import type { ClaudeAcpAgent } from "../acp-agent.js";
10
+ import type { ForegroundEvents } from "../turn-events.js";
10
11
  /**
11
12
  * Starts a turn for `params`, and answers when Claude Code takes the prompt
12
- * in. `send` delivers a session update of the prompt's session; it must not
13
- * throw, and must deliver updates in the order it is called, also relative to
14
- * the agent's own updates.
13
+ * in, with the id of the user message it became. `send` delivers a session
14
+ * update of the prompt's session; it must not throw, and must deliver updates
15
+ * in the order it is called, also relative to the agent's own updates.
15
16
  *
16
- * - Taken in: the prompt's `user_message`, then `running`, then the answer.
17
- * - Waiting on a permission request or a question: `requires_action`, and
18
- * `running` once none is open.
19
- * - Ended: `idle` with the stop reason, usage, and `_meta` of the turn.
20
- * - Failed after it was taken in: `idle` with the `error` stop reason and the
21
- * JSON-RPC error that v1 answers the prompt with, so a client can show its
22
- * message and handle its code as for an error response (for example,
23
- * `-32000` starts the client's sign-in).
17
+ * - Taken in: the prompt's `user_message`, then the answer. From then on, the
18
+ * turn is the session's foreground work, which reports its states (see
19
+ * {@link v2Foreground}).
24
20
  * - Ended or failed before it was taken in: the answer is a JSON-RPC error,
25
21
  * `-32800` for a prompt that a cancel ended in the queue.
26
- *
27
- * Deferred decision: a turn whose background subagents still run ends only
28
- * when they finish (`Turn.deferredSettle`), so `idle` waits for them too. The
29
- * hold exists for v1, whose clients stop listening at the prompt response.
30
- * v2 allows background updates while idle, so it could report `idle` at the
31
- * turn's result instead, with a turn event for the hold. To be decided with
32
- * async tasks (step 6 in `docs/acp-v2.md`).
33
22
  */
34
23
  export declare function v2Prompt(agent: ClaudeAcpAgent, params: v2.PromptRequest, send: (update: v2.SessionUpdate) => void): Promise<v2.PromptResponse>;
24
+ /**
25
+ * Reports the foreground work of a session (see {@link ForegroundEvents}) as
26
+ * its `state_update`s. `send` delivers a session update of that session, as
27
+ * for {@link v2Prompt}.
28
+ *
29
+ * - Started: `running`. For a prompt's turn, right after its `user_message`.
30
+ * - Waiting on a permission request or a question: `requires_action`, and
31
+ * `running` once none is open.
32
+ * - Ended: `idle` with the stop reason, usage, and `_meta` of the work.
33
+ * - Failed: `idle` with the `error` stop reason and the JSON-RPC error that v1
34
+ * answers the prompt with, so a client can show its message and handle its
35
+ * code as for an error response (for example, `-32000` starts the client's
36
+ * sign-in).
37
+ *
38
+ * The work is a prompt's turn or a model cycle that Claude Code started on its
39
+ * own, such as its follow-up after a background subagent finished. A turn's
40
+ * work ends at its result, also when v1 holds the turn's answer for the
41
+ * background subagents it spawned (`Turn.deferredSettle`): v2 allows
42
+ * background updates while idle, so the subagents' output and requests arrive
43
+ * after `idle`, and their follow-up is a cycle of its own.
44
+ */
45
+ export declare function v2Foreground(send: (update: v2.SessionUpdate) => void): ForegroundEvents;
35
46
  /**
36
47
  * A v2 prompt may hold content blocks that v1 cannot express: a custom one,
37
48
  * or one from a newer ACP version. Clients send only the kinds the agent
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/v2/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,EAAE,CAAC,aAAa,EACxB,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,KAAK,IAAI,GACvC,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,CAoD5B;AAgCD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC,aAAa,GAAG,aAAa,CAEvF"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/v2/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAuC,MAAM,mBAAmB,CAAC;AAE/F;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,EAAE,CAAC,aAAa,EACxB,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,KAAK,IAAI,GACvC,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,CAiC5B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,KAAK,IAAI,GAAG,gBAAgB,CAoBvF;AAgCD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC,aAAa,GAAG,aAAa,CAEvF"}