@agentclientprotocol/claude-agent-acp 0.81.3-preview.1 → 0.82.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.
Files changed (95) hide show
  1. package/README.md +8 -5
  2. package/dist/acp-agent.d.ts +31 -37
  3. package/dist/acp-agent.d.ts.map +1 -1
  4. package/dist/acp-agent.js +546 -534
  5. package/dist/acp-subagents.d.ts +6 -0
  6. package/dist/acp-subagents.d.ts.map +1 -1
  7. package/dist/air-extension.d.ts +31 -1
  8. package/dist/air-extension.d.ts.map +1 -1
  9. package/dist/air-extension.js +35 -1
  10. package/dist/async-tasks.d.ts +39 -2
  11. package/dist/async-tasks.d.ts.map +1 -1
  12. package/dist/async-tasks.js +147 -44
  13. package/dist/context-compaction-meta.d.ts +6 -5
  14. package/dist/context-compaction-meta.d.ts.map +1 -1
  15. package/dist/context-compaction-meta.js +10 -10
  16. package/dist/context-compaction.d.ts +3 -0
  17. package/dist/context-compaction.d.ts.map +1 -1
  18. package/dist/context-compaction.js +23 -57
  19. package/dist/diff.d.ts +73 -5
  20. package/dist/diff.d.ts.map +1 -1
  21. package/dist/diff.js +435 -64
  22. package/dist/elicitation.d.ts +1 -1
  23. package/dist/elicitation.d.ts.map +1 -1
  24. package/dist/elicitation.js +12 -14
  25. package/dist/native-subagents.d.ts +58 -0
  26. package/dist/native-subagents.d.ts.map +1 -1
  27. package/dist/native-subagents.js +186 -34
  28. package/dist/paths.d.ts +3 -0
  29. package/dist/paths.d.ts.map +1 -0
  30. package/dist/paths.js +6 -0
  31. package/dist/permissions/presentation.d.ts +13 -2
  32. package/dist/permissions/presentation.d.ts.map +1 -1
  33. package/dist/permissions/presentation.js +49 -44
  34. package/dist/resumed-session.d.ts +11 -0
  35. package/dist/resumed-session.d.ts.map +1 -1
  36. package/dist/resumed-session.js +106 -4
  37. package/dist/session-mode.d.ts +2 -0
  38. package/dist/session-mode.d.ts.map +1 -1
  39. package/dist/session-mode.js +12 -5
  40. package/dist/settings.js +2 -2
  41. package/dist/subagent-history.d.ts +20 -0
  42. package/dist/subagent-history.d.ts.map +1 -0
  43. package/dist/subagent-history.js +46 -0
  44. package/dist/tool-calls/background.d.ts +20 -0
  45. package/dist/tool-calls/background.d.ts.map +1 -0
  46. package/dist/tool-calls/background.js +41 -0
  47. package/dist/tool-calls/changed-meta-filter.d.ts +27 -0
  48. package/dist/tool-calls/changed-meta-filter.d.ts.map +1 -0
  49. package/dist/tool-calls/changed-meta-filter.js +102 -0
  50. package/dist/tool-calls/client-capabilities.d.ts +51 -0
  51. package/dist/tool-calls/client-capabilities.d.ts.map +1 -0
  52. package/dist/tool-calls/client-capabilities.js +43 -0
  53. package/dist/tool-calls/content.d.ts +59 -0
  54. package/dist/tool-calls/content.d.ts.map +1 -0
  55. package/dist/tool-calls/content.js +194 -0
  56. package/dist/tool-calls/facts.d.ts +116 -0
  57. package/dist/tool-calls/facts.d.ts.map +1 -0
  58. package/dist/tool-calls/facts.js +1 -0
  59. package/dist/tool-calls/field-tracker.d.ts +58 -0
  60. package/dist/tool-calls/field-tracker.d.ts.map +1 -0
  61. package/dist/tool-calls/field-tracker.js +167 -0
  62. package/dist/tool-calls/renderer.d.ts +216 -0
  63. package/dist/tool-calls/renderer.d.ts.map +1 -0
  64. package/dist/tool-calls/renderer.js +487 -0
  65. package/dist/tool-calls/reporters/agent.d.ts +7 -0
  66. package/dist/tool-calls/reporters/agent.d.ts.map +1 -0
  67. package/dist/tool-calls/reporters/agent.js +190 -0
  68. package/dist/tool-calls/reporters/bash.d.ts +9 -0
  69. package/dist/tool-calls/reporters/bash.d.ts.map +1 -0
  70. package/dist/tool-calls/reporters/bash.js +83 -0
  71. package/dist/tool-calls/reporters/compaction.d.ts +24 -0
  72. package/dist/tool-calls/reporters/compaction.d.ts.map +1 -0
  73. package/dist/tool-calls/reporters/compaction.js +66 -0
  74. package/dist/tool-calls/reporters/file-edit.d.ts +46 -0
  75. package/dist/tool-calls/reporters/file-edit.d.ts.map +1 -0
  76. package/dist/tool-calls/reporters/file-edit.js +180 -0
  77. package/dist/tool-calls/reporters/index.d.ts +4 -0
  78. package/dist/tool-calls/reporters/index.d.ts.map +1 -0
  79. package/dist/tool-calls/reporters/index.js +40 -0
  80. package/dist/tool-calls/reporters/interaction.d.ts +71 -0
  81. package/dist/tool-calls/reporters/interaction.d.ts.map +1 -0
  82. package/dist/tool-calls/reporters/interaction.js +222 -0
  83. package/dist/tool-calls/reporters/read.d.ts +7 -0
  84. package/dist/tool-calls/reporters/read.d.ts.map +1 -0
  85. package/dist/tool-calls/reporters/read.js +64 -0
  86. package/dist/tool-calls/reporters/search.d.ts +10 -0
  87. package/dist/tool-calls/reporters/search.d.ts.map +1 -0
  88. package/dist/tool-calls/reporters/search.js +50 -0
  89. package/dist/tool-calls/reporters/web.d.ts +11 -0
  90. package/dist/tool-calls/reporters/web.d.ts.map +1 -0
  91. package/dist/tool-calls/reporters/web.js +42 -0
  92. package/dist/tools.d.ts +32 -37
  93. package/dist/tools.d.ts.map +1 -1
  94. package/dist/tools.js +48 -970
  95. package/package.json +4 -1
@@ -5,6 +5,11 @@ export type NativeSubagent = {
5
5
  parentToolUseId?: string;
6
6
  name: string;
7
7
  task: string;
8
+ /**
9
+ * The exact prompt of this generation, sent as `prompt` in
10
+ * `subagent_spawned`. It is absent when the adapter has no prompt.
11
+ */
12
+ prompt?: string;
8
13
  announced?: boolean;
9
14
  terminalState?: SubagentState;
10
15
  /** Connection-local single-flight state; never serialized on the wire. */
@@ -44,6 +49,12 @@ export declare class NativeSubagentRuntime {
44
49
  private readonly identityByToolUse;
45
50
  private readonly controlByToolUse;
46
51
  private readonly childByParentToolUse;
52
+ /**
53
+ * The child session of each tool call that went to a child session. A later
54
+ * update of that tool call can lose `parentToolUseId`, for example a progress
55
+ * beat after the child finished. It still belongs to the child session.
56
+ */
57
+ private readonly childByToolCall;
47
58
  private readonly taskFinishPromises;
48
59
  private readonly generationByTaskId;
49
60
  private readonly pending;
@@ -51,18 +62,65 @@ export declare class NativeSubagentRuntime {
51
62
  constructor(enabled: boolean, rootSessionId: string, session: NativeSubagentSession, publish: Publish, logger: Logger);
52
63
  route(notification: AcpSessionNotification, deliver: Publish, forcedSessionId?: string): Promise<AcpSessionNotification | null>;
53
64
  taskStarted(task: TaskStarted, deliver: Publish): Promise<void>;
65
+ /**
66
+ * Opens a new generation of a finished child when the SDK resumes the same
67
+ * agent id. The SDK can resume a child without a new `task_started`, so a
68
+ * running `task_updated` patch or a SendMessage `resumedAgentId` is the
69
+ * signal. A child that did not finish is not changed. The `prompt` is the
70
+ * SendMessage text that resumed the child, when the adapter knows it.
71
+ */
72
+ taskResumed(taskId: string, deliver: Publish, prompt?: string): Promise<void>;
54
73
  finishTask(taskId: string, status: unknown, deliver: Publish, toolUseId?: string | null): Promise<void>;
55
74
  finishAll(state: SubagentState, deliver: Publish): Promise<void>;
56
75
  discardPending(parentToolUseId: string): void;
76
+ /**
77
+ * Routes an update to the child session. An update of a finished child is
78
+ * dropped: it never goes to the root session.
79
+ */
80
+ private toChild;
81
+ /**
82
+ * The route of the work that a child tool call started, for example an async
83
+ * task. The route sends each update to the child generation that owned the
84
+ * tool call when the work started, and drops the update after that child
85
+ * finished. `undefined` means that the root session owns the tool call.
86
+ * `eagerSessionId` is the session where a permission request created the
87
+ * tool call before the stream routed it.
88
+ */
89
+ routeOfToolCall(toolCallId: string, eagerSessionId?: string): ((notification: AcpSessionNotification) => AcpSessionNotification | null) | undefined;
90
+ private rememberToolCallOwner;
91
+ /** The child generation with the ACP session `sessionId`, if one exists. */
92
+ private childOfSession;
57
93
  clear(): void;
58
94
  private takePending;
59
95
  private buffer;
60
96
  private cleanupControl;
97
+ /** The parent of a resumed generation: the old parent while it is live, else the root. */
98
+ private resumedParentSessionId;
61
99
  private isLiveSession;
100
+ /**
101
+ * Registers a new child session for the task and makes it the owner of its
102
+ * parent tool call. With `announce`, it publishes `subagent_spawned` and
103
+ * delivers the updates that waited for the child.
104
+ */
105
+ private openGeneration;
62
106
  private nextChildSessionId;
63
107
  }
64
108
  export declare function announceNativeSubagent(child: NativeSubagent, publish: Publish): Promise<void>;
65
109
  export declare function finishNativeSubagent(session: NativeSubagentSession, taskId: string, state: SubagentState, publish: Publish): Promise<void>;
110
+ /**
111
+ * The agent id that a successful SendMessage result resumed. The SDK puts it
112
+ * in `tool_use_result.resumedAgentId` when a finished agent runs again.
113
+ */
114
+ export declare function resumedNativeSubagentId(toolUseResult: unknown): string | undefined;
115
+ /**
116
+ * The SendMessage text that resumed the agent `agentId`. The tool uses of
117
+ * `resultToolUseIds` come first: they are the SendMessage calls whose result
118
+ * carried the resume. Otherwise the latest SendMessage call to `agentId` counts.
119
+ */
120
+ export declare function sendMessageResumePrompt(toolUses: Record<string, {
121
+ name: string;
122
+ input: unknown;
123
+ } | undefined>, agentId: string, resultToolUseIds?: readonly string[]): string | undefined;
66
124
  export declare function nativeSubagentState(status: unknown): SubagentState | undefined;
67
125
  export declare function isNativeSubagentControlUpdate(update: AcpSessionNotification["update"]): update is Extract<AcpSessionNotification["update"], {
68
126
  sessionUpdate: "tool_call" | "tool_call_update";
@@ -1 +1 @@
1
- {"version":3,"file":"native-subagents.d.ts","sourceRoot":"","sources":["../src/native-subagents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"native-subagents.d.ts","sourceRoot":"","sources":["../src/native-subagents.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,9 @@
1
+ import { AIR_SUBAGENT_KEY, airExtensionMeta } from "./air-extension.js";
1
2
  const MAX_PENDING_PARENTS = 64;
2
3
  const MAX_PENDING_UPDATES = 256;
3
4
  const MAX_PENDING_UPDATES_PER_PARENT = 32;
5
+ /** The number of child tool calls whose owning child session the runtime remembers. */
6
+ const MAX_CHILD_TOOL_CALLS = 2048;
4
7
  /**
5
8
  * Owns the connection-local native subagent registry and all ACP lifecycle
6
9
  * ordering. The main agent only supplies SDK facts and delivers routed output.
@@ -17,6 +20,12 @@ export class NativeSubagentRuntime {
17
20
  identityByToolUse = new Map();
18
21
  controlByToolUse = new Map();
19
22
  childByParentToolUse = new Map();
23
+ /**
24
+ * The child session of each tool call that went to a child session. A later
25
+ * update of that tool call can lose `parentToolUseId`, for example a progress
26
+ * beat after the child finished. It still belongs to the child session.
27
+ */
28
+ childByToolCall = new Map();
20
29
  taskFinishPromises = new Map();
21
30
  generationByTaskId = new Map();
22
31
  pending = new Map();
@@ -74,23 +83,29 @@ export class NativeSubagentRuntime {
74
83
  }
75
84
  return forcedSessionId ? { ...notification, sessionId: forcedSessionId } : null;
76
85
  }
86
+ const toolCallId = update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update"
87
+ ? update.toolCallId
88
+ : undefined;
77
89
  // A permission request may have had to create the tool call before native
78
90
  // child ownership was known. Keep every later update in that original ACP
79
91
  // session; moving a lifecycle after its initial call creates an orphan in
80
92
  // both transcripts.
81
- if (forcedSessionId)
93
+ if (forcedSessionId) {
94
+ const forcedChild = this.childOfSession(forcedSessionId);
95
+ if (toolCallId && forcedChild)
96
+ this.rememberToolCallOwner(toolCallId, forcedChild);
82
97
  return { ...notification, sessionId: forcedSessionId };
98
+ }
99
+ const owner = toolCallId ? this.childByToolCall.get(toolCallId) : undefined;
100
+ if (owner)
101
+ return this.toChild(owner, notification, toolCallId);
83
102
  if (this.enabled && claudeMeta?.parentToolUseId) {
84
103
  const child = this.childByParentToolUse.get(claudeMeta.parentToolUseId);
85
104
  if (!child || !child.announced) {
86
105
  this.buffer(claudeMeta.parentToolUseId, notification);
87
106
  return null;
88
107
  }
89
- if (child.terminalState !== undefined || child.terminalPromise) {
90
- this.logger.log(`Session ${this.rootSessionId}: ignoring late update for terminal subagent ${child.sessionId}`);
91
- return null;
92
- }
93
- return { ...notification, sessionId: child.sessionId };
108
+ return this.toChild(child, notification, toolCallId);
94
109
  }
95
110
  return notification;
96
111
  }
@@ -108,36 +123,45 @@ export class NativeSubagentRuntime {
108
123
  if (previous && previous.terminalState === undefined)
109
124
  return;
110
125
  // A SendMessage resume reuses the finished generation's tool id, whose
111
- // control state is already cleaned up. Keep its parent while that session
112
- // is still live; a finished parent can no longer host the new generation.
113
- const resumedParentSessionId = previous &&
114
- (this.isLiveSession(previous.parentSessionId)
115
- ? previous.parentSessionId
116
- : this.rootSessionId);
126
+ // control state is already cleaned up.
117
127
  const knownParentSessionId = (task.toolUseId ? this.parentByToolUse.get(task.toolUseId) : undefined) ??
118
- resumedParentSessionId;
128
+ (previous && this.resumedParentSessionId(previous));
119
129
  const identity = task.toolUseId ? this.identityByToolUse.get(task.toolUseId) : undefined;
120
- const child = {
121
- sessionId: this.nextChildSessionId(task.taskId, previous),
130
+ // A nested child must wait for the spawning Agent/Task frame to establish
131
+ // its immediate parent. Root children without a tool id can be announced.
132
+ await this.openGeneration(task.taskId, previous, {
122
133
  parentSessionId: knownParentSessionId ?? this.rootSessionId,
123
134
  parentToolUseId: task.toolUseId ?? undefined,
124
135
  name: subagentDisplayName(identity?.name, identity?.description ?? task.description, identity?.subagentType ?? task.subagentType, task.taskId),
125
136
  task: subagentDescription(identity?.prompt ?? task.prompt, identity?.description ?? task.description),
126
- };
127
- this.children.set(task.taskId, child);
128
- if (task.toolUseId) {
129
- this.taskByToolUse.set(task.toolUseId, task.taskId);
130
- this.childByParentToolUse.set(task.toolUseId, child);
131
- this.controlByToolUse.delete(task.toolUseId);
132
- }
133
- // A nested child must wait for the spawning Agent/Task frame to establish
134
- // its immediate parent. Root children without a tool id can be announced.
135
- if (knownParentSessionId || !task.toolUseId) {
136
- await announceNativeSubagent(child, this.publish);
137
- for (const pending of task.toolUseId ? this.takePending(task.toolUseId) : []) {
138
- await deliver(pending);
139
- }
140
- }
137
+ ...promptField(promptText(task.prompt) ?? identity?.prompt),
138
+ }, !!knownParentSessionId || !task.toolUseId, deliver);
139
+ }
140
+ /**
141
+ * Opens a new generation of a finished child when the SDK resumes the same
142
+ * agent id. The SDK can resume a child without a new `task_started`, so a
143
+ * running `task_updated` patch or a SendMessage `resumedAgentId` is the
144
+ * signal. A child that did not finish is not changed. The `prompt` is the
145
+ * SendMessage text that resumed the child, when the adapter knows it.
146
+ */
147
+ async taskResumed(taskId, deliver, prompt) {
148
+ if (!this.enabled)
149
+ return;
150
+ const previous = this.children.get(taskId);
151
+ if (!previous)
152
+ return;
153
+ const finishing = this.taskFinishPromises.get(taskId) ?? previous.terminalPromise;
154
+ if (finishing)
155
+ await finishing.catch(() => { });
156
+ if (this.children.get(taskId) !== previous || previous.terminalState === undefined)
157
+ return;
158
+ await this.openGeneration(taskId, previous, {
159
+ parentSessionId: this.resumedParentSessionId(previous),
160
+ parentToolUseId: previous.parentToolUseId,
161
+ name: previous.name,
162
+ task: previous.task,
163
+ ...promptField(promptText(prompt)),
164
+ }, true, deliver);
141
165
  }
142
166
  async finishTask(taskId, status, deliver, toolUseId) {
143
167
  if (!this.enabled)
@@ -202,8 +226,56 @@ export class NativeSubagentRuntime {
202
226
  discardPending(parentToolUseId) {
203
227
  this.takePending(parentToolUseId);
204
228
  }
229
+ /**
230
+ * Routes an update to the child session. An update of a finished child is
231
+ * dropped: it never goes to the root session.
232
+ */
233
+ toChild(child, notification, toolCallId) {
234
+ if (child.terminalState !== undefined || child.terminalPromise) {
235
+ this.logger.log(`Session ${this.rootSessionId}: ignoring late update for terminal subagent ${child.sessionId}`);
236
+ return null;
237
+ }
238
+ if (toolCallId)
239
+ this.rememberToolCallOwner(toolCallId, child);
240
+ return { ...notification, sessionId: child.sessionId };
241
+ }
242
+ /**
243
+ * The route of the work that a child tool call started, for example an async
244
+ * task. The route sends each update to the child generation that owned the
245
+ * tool call when the work started, and drops the update after that child
246
+ * finished. `undefined` means that the root session owns the tool call.
247
+ * `eagerSessionId` is the session where a permission request created the
248
+ * tool call before the stream routed it.
249
+ */
250
+ routeOfToolCall(toolCallId, eagerSessionId) {
251
+ if (!this.enabled)
252
+ return undefined;
253
+ const owner = this.childByToolCall.get(toolCallId) ??
254
+ (eagerSessionId ? this.childOfSession(eagerSessionId) : undefined);
255
+ return owner && ((notification) => this.toChild(owner, notification, undefined));
256
+ }
257
+ rememberToolCallOwner(toolCallId, child) {
258
+ this.childByToolCall.delete(toolCallId);
259
+ this.childByToolCall.set(toolCallId, child);
260
+ if (this.childByToolCall.size > MAX_CHILD_TOOL_CALLS) {
261
+ const oldest = this.childByToolCall.keys().next().value;
262
+ if (oldest !== undefined)
263
+ this.childByToolCall.delete(oldest);
264
+ }
265
+ }
266
+ /** The child generation with the ACP session `sessionId`, if one exists. */
267
+ childOfSession(sessionId) {
268
+ if (sessionId === this.rootSessionId)
269
+ return undefined;
270
+ for (const child of this.children.values()) {
271
+ if (child.sessionId === sessionId)
272
+ return child;
273
+ }
274
+ return undefined;
275
+ }
205
276
  clear() {
206
277
  this.children.clear();
278
+ this.childByToolCall.clear();
207
279
  this.taskByToolUse.clear();
208
280
  this.parentByToolUse.clear();
209
281
  this.identityByToolUse.clear();
@@ -241,6 +313,12 @@ export class NativeSubagentRuntime {
241
313
  this.controlByToolUse.delete(toolUseId);
242
314
  this.parentByToolUse.delete(toolUseId);
243
315
  }
316
+ /** The parent of a resumed generation: the old parent while it is live, else the root. */
317
+ resumedParentSessionId(previous) {
318
+ return this.isLiveSession(previous.parentSessionId)
319
+ ? previous.parentSessionId
320
+ : this.rootSessionId;
321
+ }
244
322
  isLiveSession(sessionId) {
245
323
  if (sessionId === this.rootSessionId)
246
324
  return true;
@@ -250,6 +328,29 @@ export class NativeSubagentRuntime {
250
328
  }
251
329
  return false;
252
330
  }
331
+ /**
332
+ * Registers a new child session for the task and makes it the owner of its
333
+ * parent tool call. With `announce`, it publishes `subagent_spawned` and
334
+ * delivers the updates that waited for the child.
335
+ */
336
+ async openGeneration(taskId, previous, fields, announce, deliver) {
337
+ const child = {
338
+ sessionId: this.nextChildSessionId(taskId, previous),
339
+ ...fields,
340
+ };
341
+ const toolUseId = child.parentToolUseId;
342
+ this.children.set(taskId, child);
343
+ if (toolUseId) {
344
+ this.taskByToolUse.set(toolUseId, taskId);
345
+ this.childByParentToolUse.set(toolUseId, child);
346
+ this.controlByToolUse.delete(toolUseId);
347
+ }
348
+ if (!announce)
349
+ return;
350
+ await announceNativeSubagent(child, this.publish);
351
+ for (const pending of toolUseId ? this.takePending(toolUseId) : [])
352
+ await deliver(pending);
353
+ }
253
354
  nextChildSessionId(taskId, previous) {
254
355
  if (!previous) {
255
356
  this.generationByTaskId.set(taskId, 1);
@@ -273,6 +374,7 @@ export async function announceNativeSubagent(child, publish) {
273
374
  subagentSessionId: child.sessionId,
274
375
  name: child.name,
275
376
  task: child.task,
377
+ ...promptField(child.prompt),
276
378
  capabilities: {},
277
379
  },
278
380
  });
@@ -314,6 +416,41 @@ export async function finishNativeSubagent(session, taskId, state, publish) {
314
416
  child.terminalPromise = undefined;
315
417
  }
316
418
  }
419
+ /**
420
+ * The agent id that a successful SendMessage result resumed. The SDK puts it
421
+ * in `tool_use_result.resumedAgentId` when a finished agent runs again.
422
+ */
423
+ export function resumedNativeSubagentId(toolUseResult) {
424
+ if (typeof toolUseResult !== "object" || toolUseResult === null)
425
+ return undefined;
426
+ const result = toolUseResult;
427
+ return result.success === true ? nonBlankString(result.resumedAgentId) : undefined;
428
+ }
429
+ /**
430
+ * The SendMessage text that resumed the agent `agentId`. The tool uses of
431
+ * `resultToolUseIds` come first: they are the SendMessage calls whose result
432
+ * carried the resume. Otherwise the latest SendMessage call to `agentId` counts.
433
+ */
434
+ export function sendMessageResumePrompt(toolUses, agentId, resultToolUseIds = []) {
435
+ for (const toolUseId of resultToolUseIds) {
436
+ const toolUse = toolUses[toolUseId];
437
+ if (toolUse?.name !== "SendMessage")
438
+ continue;
439
+ const text = promptText(toolUse.input?.message);
440
+ if (text)
441
+ return text;
442
+ }
443
+ if (resultToolUseIds.length > 0)
444
+ return undefined;
445
+ for (const toolUse of Object.values(toolUses).reverse()) {
446
+ if (toolUse?.name !== "SendMessage")
447
+ continue;
448
+ const input = toolUse.input;
449
+ if (input?.to === agentId)
450
+ return promptText(input.message);
451
+ }
452
+ return undefined;
453
+ }
317
454
  export function nativeSubagentState(status) {
318
455
  if (status === "completed")
319
456
  return "completed";
@@ -330,7 +467,8 @@ export function isNativeSubagentControlUpdate(update) {
330
467
  return false;
331
468
  }
332
469
  const claudeMeta = update._meta?.claudeCode;
333
- return claudeMeta?.subagent === true || isNativeSubagentControlTool(claudeMeta?.toolName);
470
+ return (airExtensionMeta(update._meta)?.[AIR_SUBAGENT_KEY] === true ||
471
+ isNativeSubagentControlTool(claudeMeta?.toolName));
334
472
  }
335
473
  export function isNativeSubagentControlTool(toolName) {
336
474
  return toolName === "Agent" || toolName === "Task";
@@ -387,8 +525,14 @@ function failedControlFallback(initial, terminal, sessionId) {
387
525
  function ordinaryToolMeta(...values) {
388
526
  const merged = Object.assign({}, ...values);
389
527
  const claudeCode = Object.assign({}, ...values.map((value) => value?.claudeCode ?? {}));
390
- delete claudeCode.subagent;
391
- return { ...merged, claudeCode };
528
+ const result = { ...merged, claudeCode };
529
+ const air = airExtensionMeta(merged);
530
+ if (air && AIR_SUBAGENT_KEY in air) {
531
+ const rest = { ...air };
532
+ delete rest[AIR_SUBAGENT_KEY];
533
+ result.jetbrains = { ...merged.jetbrains, air: rest };
534
+ }
535
+ return result;
392
536
  }
393
537
  function subagentDisplayName(explicitName, description, type, taskId) {
394
538
  for (const value of [explicitName, description, type]) {
@@ -412,7 +556,7 @@ function subagentIdentity(input) {
412
556
  const identity = {
413
557
  name: nonBlankString(value.name),
414
558
  description: nonBlankString(value.description),
415
- prompt: nonBlankString(value.prompt),
559
+ prompt: promptText(value.prompt),
416
560
  subagentType: nonBlankString(value.subagent_type),
417
561
  };
418
562
  return Object.values(identity).some(Boolean) ? identity : undefined;
@@ -434,6 +578,14 @@ function applySubagentIdentity(child, identity) {
434
578
  if (identity.prompt || identity.description) {
435
579
  child.task = subagentDescription(identity.prompt, identity.description);
436
580
  }
581
+ child.prompt ??= identity.prompt;
582
+ }
583
+ /** The prompt text unchanged, or `undefined` when it is not a non-blank string. */
584
+ function promptText(value) {
585
+ return typeof value === "string" && value.trim().length > 0 ? value : undefined;
586
+ }
587
+ function promptField(prompt) {
588
+ return prompt === undefined ? {} : { prompt };
437
589
  }
438
590
  function nonBlankString(value) {
439
591
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
@@ -0,0 +1,3 @@
1
+ /** The Claude configuration directory: `CLAUDE_CONFIG_DIR`, or `~/.claude`. */
2
+ export declare function claudeConfigDir(): string;
3
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAGA,+EAA+E;AAC/E,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
package/dist/paths.js ADDED
@@ -0,0 +1,6 @@
1
+ import * as os from "node:os";
2
+ import * as path from "node:path";
3
+ /** The Claude configuration directory: `CLAUDE_CONFIG_DIR`, or `~/.claude`. */
4
+ export function claudeConfigDir() {
5
+ return process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
6
+ }
@@ -1,10 +1,13 @@
1
- import type { RequestPermissionRequest } from "@agentclientprotocol/sdk";
1
+ import type { RequestPermissionRequest, ToolCallContent } from "@agentclientprotocol/sdk";
2
+ import { ClientCapabilities } from "../tool-calls/client-capabilities.js";
2
3
  export interface ClaudePermissionPresentationInput {
3
4
  toolName: string;
4
5
  input: Record<string, unknown>;
5
6
  toolUseID: string;
6
7
  cwd?: string;
7
- supportsTerminalOutput?: boolean;
8
+ capabilities?: ClientCapabilities;
9
+ /** The exact patch of the change to approve, for a negotiated `diffPatch` client. */
10
+ previewContent?: ToolCallContent[];
8
11
  blockedPath?: string;
9
12
  title?: string;
10
13
  displayName?: string;
@@ -12,5 +15,13 @@ export interface ClaudePermissionPresentationInput {
12
15
  decisionReason?: string;
13
16
  defaultToNo?: boolean;
14
17
  }
18
+ /**
19
+ * The permission request presentation.
20
+ *
21
+ * The request `toolCall` carries `toolCallId`, `title`, and `rawInput`. The
22
+ * adapter emits the `tool_call` before the request, so the client already
23
+ * holds the rest. The request adds only what it shows new: the exact preview
24
+ * patch, and the blocked path when the tool call has no such location.
25
+ */
15
26
  export declare function buildClaudePermissionPresentation(value: ClaudePermissionPresentationInput): Pick<RequestPermissionRequest, "toolCall" | "_meta">;
16
27
  //# sourceMappingURL=presentation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../src/permissions/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAoB,MAAM,0BAA0B,CAAC;AAG3F,MAAM,WAAW,iCAAiC;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAqCD,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,iCAAiC,GACvC,IAAI,CAAC,wBAAwB,EAAE,UAAU,GAAG,OAAO,CAAC,CA+DtD"}
1
+ {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../src/permissions/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG1E,MAAM,WAAW,iCAAiC;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,qFAAqF;IACrF,cAAc,CAAC,EAAE,eAAe,EAAE,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA0BD;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,iCAAiC,GACvC,IAAI,CAAC,wBAAwB,EAAE,UAAU,GAAG,OAAO,CAAC,CAgEtD"}
@@ -1,4 +1,6 @@
1
- import { toolInfoFromToolUse } from "../tools.js";
1
+ import { AIR_PERMISSION_KEY, withAirMeta } from "../air-extension.js";
2
+ import { ClientCapabilities } from "../tool-calls/client-capabilities.js";
3
+ import { AcpToolCallRenderer } from "../tool-calls/renderer.js";
2
4
  function humanText(value, maxLength, singleLine = false) {
3
5
  if (typeof value !== "string")
4
6
  return undefined;
@@ -20,36 +22,27 @@ function humanText(value, maxLength, singleLine = false) {
20
22
  function compactText(value) {
21
23
  return humanText(value, 160, true);
22
24
  }
23
- function withBlockedPath(locations, blockedPath) {
24
- const path = humanText(blockedPath, 4_096, true);
25
- if (!path)
26
- return locations;
27
- const result = [...(locations ?? [])];
28
- if (!result.some((location) => location.path === path))
29
- result.push({ path });
30
- return result;
31
- }
25
+ /**
26
+ * The permission request presentation.
27
+ *
28
+ * The request `toolCall` carries `toolCallId`, `title`, and `rawInput`. The
29
+ * adapter emits the `tool_call` before the request, so the client already
30
+ * holds the rest. The request adds only what it shows new: the exact preview
31
+ * patch, and the blocked path when the tool call has no such location.
32
+ */
32
33
  export function buildClaudePermissionPresentation(value) {
33
- const info = toolInfoFromToolUse({ id: value.toolUseID, name: value.toolName, input: value.input }, value.supportsTerminalOutput ?? false, value.cwd);
34
+ const capabilities = value.capabilities ?? new ClientCapabilities();
35
+ const renderer = new AcpToolCallRenderer(capabilities);
36
+ const toolUse = { id: value.toolUseID, name: value.toolName, input: value.input };
37
+ const facts = renderer.facts(toolUse, value.cwd);
34
38
  const host = value.toolName === "SandboxNetworkAccess" ? compactText(value.input.host) : undefined;
35
39
  const isComputerUse = value.toolName.startsWith("mcp__computer-use__");
36
40
  const subjectTitle = host ?? (isComputerUse ? compactText(value.displayName) : undefined);
37
- const subjectContent = (host || isComputerUse) && info.content.length === 0
38
- ? [
39
- {
40
- type: "content",
41
- content: {
42
- type: "text",
43
- text: `\`\`\`json\n${JSON.stringify(value.input, null, 2)}\n\`\`\``,
44
- },
45
- },
46
- ]
47
- : info.content;
48
41
  // Reuse the exact standard tool-call heading as the permission heading so
49
42
  // the approval never maintains a second, divergent name for the operation.
50
43
  // decisionReason is temporarily exposed as the permission description so
51
44
  // its actual SDK values can be inspected; it remains diagnostic policy text.
52
- const toolCallTitle = subjectTitle ?? info.title;
45
+ const toolCallTitle = subjectTitle ?? facts.title;
53
46
  const permissionTitle = value.toolName === "ExitPlanMode" ? "Ready to code?" : toolCallTitle;
54
47
  // Shell titles are executable input: compacting whitespace changes quoted
55
48
  // arguments and comment boundaries, and length limits can hide the command.
@@ -58,30 +51,42 @@ export function buildClaudePermissionPresentation(value) {
58
51
  : (humanText(permissionTitle, 4_000, true) ?? "Use tool?");
59
52
  const decisionReason = humanText(value.decisionReason, 4_000);
60
53
  const description = decisionReason ? `Reason: ${decisionReason}` : undefined;
54
+ const blockedPath = humanText(value.blockedPath, 4_096, true);
55
+ const extraLocations = blockedPath && !(facts.locations ?? []).some((location) => location.path === blockedPath)
56
+ ? [{ path: blockedPath }]
57
+ : undefined;
61
58
  return {
62
- toolCall: {
63
- toolCallId: value.toolUseID,
64
- name: value.toolName,
65
- status: "pending",
66
- rawInput: value.input,
67
- ...info,
59
+ toolCall: renderer.permissionToolCall(toolUse, {
60
+ cwd: value.cwd,
68
61
  title: toolCallTitle,
69
- content: subjectContent,
70
- locations: withBlockedPath(info.locations, value.blockedPath),
71
- },
72
- ...(title
73
- ? {
74
- _meta: {
75
- permission: {
76
- version: 1,
77
- title,
78
- ...(description ? { description } : {}),
79
- // The CLI's own hint, forwarded so a client that can pre-select
80
- // an option keeps the decline focused; the option order already
81
- // leads with the reject options when this is set.
82
- ...(value.defaultToNo === true ? { defaultToNo: true } : {}),
62
+ previewContent: value.previewContent,
63
+ extraLocations,
64
+ // The upstream request shows the input of a network or computer-use
65
+ // request that has no content of its own.
66
+ fallbackContent: host || isComputerUse
67
+ ? [
68
+ {
69
+ type: "content",
70
+ content: {
71
+ type: "text",
72
+ text: `\`\`\`json\n${JSON.stringify(value.input, null, 2)}\n\`\`\``,
73
+ },
83
74
  },
84
- },
75
+ ]
76
+ : undefined,
77
+ }),
78
+ // Only AIR gets the permission presentation.
79
+ ...(title && capabilities.air.client
80
+ ? {
81
+ _meta: withAirMeta(undefined, AIR_PERMISSION_KEY, {
82
+ version: 1,
83
+ title,
84
+ ...(description ? { description } : {}),
85
+ // The CLI's own hint, forwarded so a client that can pre-select
86
+ // an option keeps the decline focused; the option order already
87
+ // leads with the reject options when this is set.
88
+ ...(value.defaultToNo === true ? { defaultToNo: true } : {}),
89
+ }),
85
90
  }
86
91
  : {}),
87
92
  };
@@ -15,5 +15,16 @@ export declare function resumedModelFromTranscript(messages: SessionMessage[]):
15
15
  /** Read the resume model from the local transcript without starting a Claude
16
16
  * control request. This is intentionally on the load critical path. */
17
17
  export declare function readResumedSession(sessionId: string, logger?: ResumeLogger): Promise<ResumedSessionSnapshot>;
18
+ /**
19
+ * Read the resume model of a session from the end of its local transcript.
20
+ *
21
+ * A resume needs only the model, not the messages. The transcript file is
22
+ * read backwards until the last real assistant record of the main thread, so
23
+ * the cost does not grow with the length of the session. A session without a
24
+ * local transcript file falls back to {@link readResumedSession}.
25
+ */
26
+ export declare function readResumedModel(sessionId: string, logger?: ResumeLogger): Promise<string | undefined>;
27
+ /** The local transcript of a session in any project directory, as the SDK looks it up. */
28
+ export declare function findTranscript(sessionId: string): Promise<string | undefined>;
18
29
  export {};
19
30
  //# sourceMappingURL=resumed-session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resumed-session.d.ts","sourceRoot":"","sources":["../src/resumed-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGzF,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;iDAGiD;AACjD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,GAAG,SAAS,CAkBzF;AAED;uEACuE;AACvE,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,sBAAsB,CAAC,CAejC"}
1
+ {"version":3,"file":"resumed-session.d.ts","sourceRoot":"","sources":["../src/resumed-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AASzF,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;iDAGiD;AACjD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,GAAG,SAAS,CAgBzF;AASD;uEACuE;AACvE,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,sBAAsB,CAAC,CAejC;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAc7B;AAED,0FAA0F;AAC1F,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkBnF"}