@borgee/agents-host 0.2.84 → 0.2.97

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 (54) hide show
  1. package/README.md +1 -1
  2. package/dist/agents-host.js +23 -5
  3. package/dist/background-runs.d.ts +6 -1
  4. package/dist/background-runs.js +56 -21
  5. package/dist/chat/chat-control-plane.d.ts +3 -1
  6. package/dist/chat/sdk-chat-control-plane.d.ts +6 -2
  7. package/dist/chat/sdk-chat-control-plane.js +18 -0
  8. package/dist/plugin-sdk.js +149 -21
  9. package/dist/plugin-sdk.js.map +3 -3
  10. package/dist/progress-to-activity.d.ts +3 -3
  11. package/dist/providers/claude/adapter.d.ts +3 -1
  12. package/dist/providers/claude/adapter.js +41 -3
  13. package/dist/providers/claude/background-run-observer.d.ts +32 -0
  14. package/dist/providers/claude/background-run-observer.js +381 -0
  15. package/dist/providers/claude/cli-client.d.ts +15 -1
  16. package/dist/providers/claude/cli-client.js +699 -69
  17. package/dist/providers/claude/foreground-handoff.d.ts +4 -0
  18. package/dist/providers/claude/foreground-handoff.js +45 -0
  19. package/dist/providers/claude/task-cancellation-protocol.d.ts +14 -0
  20. package/dist/providers/claude/task-cancellation-protocol.js +21 -0
  21. package/dist/providers/copilot/activity-metadata.d.ts +3 -0
  22. package/dist/providers/copilot/activity-metadata.js +19 -0
  23. package/dist/providers/copilot/cli-client.js +5 -0
  24. package/dist/providers/provider-adapter.d.ts +8 -0
  25. package/dist/providers/provider-adapter.js +4 -0
  26. package/dist/types.d.ts +8 -0
  27. package/dist/vendor/claude-agent-acp/LICENSE +191 -0
  28. package/dist/vendor/claude-agent-acp/NOTICE +8 -0
  29. package/dist/vendor/claude-agent-acp/dist/acp-agent.d.ts +1017 -0
  30. package/dist/vendor/claude-agent-acp/dist/acp-agent.d.ts.map +1 -0
  31. package/dist/vendor/claude-agent-acp/dist/acp-agent.js +6305 -0
  32. package/dist/vendor/claude-agent-acp/dist/borgee-foreground-handoff-bridge.js +322 -0
  33. package/dist/vendor/claude-agent-acp/dist/borgee-task-cancellation-bridge.js +101 -0
  34. package/dist/vendor/claude-agent-acp/dist/borgee-task-lifecycle-bridge.js +58 -0
  35. package/dist/vendor/claude-agent-acp/dist/elicitation.d.ts +130 -0
  36. package/dist/vendor/claude-agent-acp/dist/elicitation.d.ts.map +1 -0
  37. package/dist/vendor/claude-agent-acp/dist/elicitation.js +304 -0
  38. package/dist/vendor/claude-agent-acp/dist/index.d.ts +3 -0
  39. package/dist/vendor/claude-agent-acp/dist/index.d.ts.map +1 -0
  40. package/dist/vendor/claude-agent-acp/dist/index.js +75 -0
  41. package/dist/vendor/claude-agent-acp/dist/lib.d.ts +6 -0
  42. package/dist/vendor/claude-agent-acp/dist/lib.d.ts.map +1 -0
  43. package/dist/vendor/claude-agent-acp/dist/lib.js +5 -0
  44. package/dist/vendor/claude-agent-acp/dist/settings.d.ts +68 -0
  45. package/dist/vendor/claude-agent-acp/dist/settings.d.ts.map +1 -0
  46. package/dist/vendor/claude-agent-acp/dist/settings.js +185 -0
  47. package/dist/vendor/claude-agent-acp/dist/tools.d.ts +102 -0
  48. package/dist/vendor/claude-agent-acp/dist/tools.d.ts.map +1 -0
  49. package/dist/vendor/claude-agent-acp/dist/tools.js +1000 -0
  50. package/dist/vendor/claude-agent-acp/dist/utils.d.ts +16 -0
  51. package/dist/vendor/claude-agent-acp/dist/utils.d.ts.map +1 -0
  52. package/dist/vendor/claude-agent-acp/dist/utils.js +81 -0
  53. package/dist/vendor/claude-agent-acp/package.json +85 -0
  54. package/package.json +16 -12
@@ -1,8 +1,8 @@
1
1
  import type { AgentActivity } from './plugin-sdk.js';
2
2
  import type { ProviderProgressUpdate } from './types.js';
3
- /** Everything a provider reports. The turn boundary is the reporter's own and never arrives here. */
4
- export type ReportedActivity = Exclude<AgentActivity, {
5
- shape: 'turn' | 'background_run';
3
+ /** Absolute provider state accepted by the foreground activity coalescer. */
4
+ export type ReportedActivity = Extract<AgentActivity, {
5
+ shape: 'activity' | 'plan' | 'output';
6
6
  }>;
7
7
  /**
8
8
  * Restates one progress update in the rail's own vocabulary.
@@ -1,5 +1,5 @@
1
1
  import { type ProviderAdapter } from '../provider-adapter.js';
2
- import type { ProviderGenerateOptions, ProviderInput, ProviderReply } from '../../types.js';
2
+ import type { ProviderAutonomousReply, ProviderGenerateOptions, ProviderInput, ProviderReply } from '../../types.js';
3
3
  import { ProviderTurnPreparer } from '../../context/turn-preparation.js';
4
4
  import { ClaudeCliClient } from './cli-client.js';
5
5
  export declare const CLAUDE_HOSTED_PROVIDER_CAPABILITIES: import("../provider-adapter.js").ProviderCapabilities;
@@ -7,8 +7,10 @@ export declare class ClaudeProviderAdapter implements ProviderAdapter {
7
7
  private readonly cli;
8
8
  private readonly turnPreparer;
9
9
  readonly capabilities: import("../provider-adapter.js").ProviderCapabilities;
10
+ readonly cancelBackgroundRun?: (channelId: string, providerRunId: string) => Promise<boolean>;
10
11
  constructor(cli: ClaudeCliClient, turnPreparer: Pick<ProviderTurnPreparer, 'prepare'>);
11
12
  generateReply(input: ProviderInput, options?: ProviderGenerateOptions): Promise<ProviderReply>;
13
+ onAutonomousReply(handler: ((reply: ProviderAutonomousReply) => void) | undefined): void;
12
14
  cancelTurn(channelId: string): Promise<boolean>;
13
15
  dispose(): Promise<void>;
14
16
  }
@@ -11,17 +11,45 @@ export const CLAUDE_HOSTED_PROVIDER_CAPABILITIES = createHostedProviderCapabilit
11
11
  support: 'supported',
12
12
  },
13
13
  backgroundRuns: {
14
- lifecycle: 'not-supported',
15
- targetedCancellation: 'not-supported',
14
+ lifecycle: 'supported',
15
+ targetedCancellation: 'supported',
16
+ },
17
+ foregroundHandoff: {
18
+ support: 'not-supported',
16
19
  },
17
20
  });
18
21
  export class ClaudeProviderAdapter {
19
22
  cli;
20
23
  turnPreparer;
21
- capabilities = CLAUDE_HOSTED_PROVIDER_CAPABILITIES;
24
+ capabilities;
25
+ cancelBackgroundRun;
22
26
  constructor(cli, turnPreparer) {
23
27
  this.cli = cli;
24
28
  this.turnPreparer = turnPreparer;
29
+ const targetedCancellationSupported = cli.targetedBackgroundRunCancellationConfigured;
30
+ this.capabilities = targetedCancellationSupported
31
+ ? CLAUDE_HOSTED_PROVIDER_CAPABILITIES
32
+ : createHostedProviderCapabilities({
33
+ imageInputTransport: {
34
+ source: 'transport-derived',
35
+ support: 'supported',
36
+ reason: 'real-media-delivered',
37
+ delivery: ['blob'],
38
+ },
39
+ progressUpdates: {
40
+ support: 'supported',
41
+ },
42
+ backgroundRuns: {
43
+ lifecycle: 'supported',
44
+ targetedCancellation: 'not-supported',
45
+ },
46
+ foregroundHandoff: {
47
+ support: 'not-supported',
48
+ },
49
+ });
50
+ if (targetedCancellationSupported) {
51
+ this.cancelBackgroundRun = (channelId, providerRunId) => (this.cli.cancelBackgroundRun(channelId, providerRunId));
52
+ }
25
53
  }
26
54
  async generateReply(input, options) {
27
55
  const preparedTurn = await this.turnPreparer.prepare(input);
@@ -32,6 +60,16 @@ export class ClaudeProviderAdapter {
32
60
  // session as it runs, so before this point there is nothing to report.
33
61
  return { ...parseProviderReply(text), sessionId: this.cli.sessionIdForChannel(input.channelId) };
34
62
  }
63
+ onAutonomousReply(handler) {
64
+ this.cli.onAutonomousReply(handler
65
+ ? (reply) => {
66
+ const parsed = parseProviderReply(reply.text);
67
+ if (parsed.text.trim()) {
68
+ handler({ ...reply, text: parsed.text });
69
+ }
70
+ }
71
+ : undefined);
72
+ }
35
73
  async cancelTurn(channelId) {
36
74
  return this.cli.cancelTurn(channelId);
37
75
  }
@@ -0,0 +1,32 @@
1
+ import type { ProviderGenerateOptions } from '../../types.js';
2
+ export declare class ClaudeBackgroundRunObserver {
3
+ private onProgress?;
4
+ private readonly limits;
5
+ private readonly tasks;
6
+ private readonly emitted;
7
+ private backgroundTasksActive;
8
+ constructor(onProgress?: ProviderGenerateOptions['onProgress'], limits?: {
9
+ terminalRetentionMs?: number;
10
+ maxTrackedTasks?: number;
11
+ onBackgroundTasksActiveChanged?: (active: boolean) => void;
12
+ targetedCancellationSupported?: boolean;
13
+ });
14
+ setOnProgress(onProgress?: ProviderGenerateOptions['onProgress']): void;
15
+ dispose(): void;
16
+ fail(reason?: string): void;
17
+ consume(value: unknown): boolean;
18
+ private getOrCreate;
19
+ private mapTaskStatus;
20
+ private isConcreteTerminal;
21
+ private scheduleMissing;
22
+ private cancelMissing;
23
+ private scheduleRetention;
24
+ private cancelRetention;
25
+ private touch;
26
+ private enforceLimit;
27
+ private isTerminal;
28
+ private deleteTask;
29
+ private publish;
30
+ private reconcileBackgroundTasksActive;
31
+ private setBackgroundTasksActive;
32
+ }
@@ -0,0 +1,381 @@
1
+ const MISSING_TASK_GRACE_MS = 250;
2
+ const TERMINAL_TASK_RETENTION_MS = 30_000;
3
+ const MAX_TRACKED_TASKS = 256;
4
+ function isRecord(value) {
5
+ return typeof value === 'object' && value !== null;
6
+ }
7
+ function readOptionalString(record, key) {
8
+ const value = record[key];
9
+ return typeof value === 'string' ? value : undefined;
10
+ }
11
+ function parseClaudeTaskLifecycleUpdate(value) {
12
+ if (!isRecord(value) ||
13
+ value.sessionUpdate !== 'session_info_update' ||
14
+ !isRecord(value._meta) ||
15
+ !isRecord(value._meta.claudeCode) ||
16
+ !isRecord(value._meta.claudeCode.taskLifecycle)) {
17
+ return null;
18
+ }
19
+ return parseClaudeTaskLifecycleRecord(value._meta.claudeCode.taskLifecycle);
20
+ }
21
+ export class ClaudeBackgroundRunObserver {
22
+ onProgress;
23
+ limits;
24
+ tasks = new Map();
25
+ emitted = new Map();
26
+ backgroundTasksActive = false;
27
+ constructor(onProgress, limits = {}) {
28
+ this.onProgress = onProgress;
29
+ this.limits = limits;
30
+ }
31
+ setOnProgress(onProgress) {
32
+ if (onProgress) {
33
+ this.onProgress = onProgress;
34
+ }
35
+ }
36
+ dispose() {
37
+ for (const taskId of [...this.tasks.keys()]) {
38
+ this.deleteTask(taskId);
39
+ }
40
+ this.emitted.clear();
41
+ this.onProgress = undefined;
42
+ this.setBackgroundTasksActive(false);
43
+ }
44
+ fail(reason = 'Claude background run state is unknown because the provider session ended unexpectedly') {
45
+ for (const [taskId, record] of this.tasks) {
46
+ if (!record.background || this.isTerminal(record.state)) {
47
+ continue;
48
+ }
49
+ this.cancelMissing(record);
50
+ record.state = 'unknown';
51
+ record.reason = reason;
52
+ this.publish(taskId, record);
53
+ }
54
+ this.dispose();
55
+ }
56
+ consume(value) {
57
+ const update = parseClaudeTaskLifecycleUpdate(value);
58
+ if (!update) {
59
+ return false;
60
+ }
61
+ if (update.event === 'background_tasks_changed') {
62
+ const liveTaskIds = new Set(update.tasks.map((task) => task.taskId));
63
+ for (const [taskId, record] of this.tasks) {
64
+ if (record.background && !this.isConcreteTerminal(record.state)) {
65
+ if (liveTaskIds.has(taskId)) {
66
+ this.cancelMissing(record);
67
+ }
68
+ else {
69
+ this.scheduleMissing(taskId, record);
70
+ }
71
+ }
72
+ }
73
+ for (const task of update.tasks) {
74
+ const record = this.getOrCreate(task.taskId, task.description);
75
+ record.label = task.description;
76
+ record.background = true;
77
+ this.cancelMissing(record);
78
+ if (record.state === 'unknown') {
79
+ record.state = 'running';
80
+ record.reason = undefined;
81
+ this.cancelRetention(record);
82
+ }
83
+ this.touch(task.taskId, record);
84
+ this.publish(task.taskId, record);
85
+ }
86
+ this.enforceLimit();
87
+ this.reconcileBackgroundTasksActive();
88
+ return true;
89
+ }
90
+ const record = this.getOrCreate(update.taskId, update.event === 'started' ? update.description : 'Claude background task');
91
+ switch (update.event) {
92
+ case 'started':
93
+ record.label = update.description;
94
+ if (update.toolUseId) {
95
+ record.parentActivityId = update.toolUseId;
96
+ }
97
+ this.cancelRetention(record);
98
+ this.touch(update.taskId, record);
99
+ if (record.background) {
100
+ this.publish(update.taskId, record);
101
+ }
102
+ this.enforceLimit();
103
+ this.reconcileBackgroundTasksActive();
104
+ return true;
105
+ case 'updated':
106
+ if (update.patch.description) {
107
+ record.label = update.patch.description;
108
+ }
109
+ if (update.patch.is_backgrounded === true) {
110
+ record.background = true;
111
+ }
112
+ if (update.patch.status) {
113
+ const wasUnknown = record.state === 'unknown';
114
+ record.state = this.mapTaskStatus(update.patch.status);
115
+ this.cancelMissing(record);
116
+ if (wasUnknown && !this.isConcreteTerminal(record.state)) {
117
+ record.reason = undefined;
118
+ }
119
+ if (this.isConcreteTerminal(record.state)) {
120
+ this.scheduleRetention(update.taskId, record);
121
+ }
122
+ else {
123
+ this.cancelRetention(record);
124
+ }
125
+ }
126
+ if (update.patch.error) {
127
+ record.reason = update.patch.error;
128
+ }
129
+ if (record.background) {
130
+ this.publish(update.taskId, record);
131
+ }
132
+ this.touch(update.taskId, record);
133
+ this.enforceLimit();
134
+ this.reconcileBackgroundTasksActive();
135
+ return true;
136
+ case 'notification':
137
+ if (update.toolUseId) {
138
+ record.parentActivityId = update.toolUseId;
139
+ }
140
+ record.state =
141
+ update.status === 'completed'
142
+ ? 'completed'
143
+ : update.status === 'failed'
144
+ ? 'failed'
145
+ : 'cancelled';
146
+ this.cancelMissing(record);
147
+ if (update.status !== 'completed' && update.summary.trim().length > 0) {
148
+ record.reason = update.summary;
149
+ }
150
+ this.scheduleRetention(update.taskId, record);
151
+ if (record.background) {
152
+ this.publish(update.taskId, record);
153
+ }
154
+ this.touch(update.taskId, record);
155
+ this.enforceLimit();
156
+ this.reconcileBackgroundTasksActive();
157
+ return true;
158
+ }
159
+ }
160
+ getOrCreate(taskId, label) {
161
+ const existing = this.tasks.get(taskId);
162
+ if (existing) {
163
+ this.touch(taskId, existing);
164
+ return existing;
165
+ }
166
+ const record = {
167
+ label,
168
+ background: false,
169
+ missingFromSnapshot: false,
170
+ state: 'running',
171
+ };
172
+ this.tasks.set(taskId, record);
173
+ return record;
174
+ }
175
+ mapTaskStatus(status) {
176
+ switch (status) {
177
+ case 'pending':
178
+ case 'running':
179
+ return 'running';
180
+ case 'paused':
181
+ return 'waiting';
182
+ case 'completed':
183
+ return 'completed';
184
+ case 'failed':
185
+ return 'failed';
186
+ case 'killed':
187
+ return 'cancelled';
188
+ }
189
+ }
190
+ isConcreteTerminal(state) {
191
+ return state === 'completed' || state === 'failed' || state === 'cancelled';
192
+ }
193
+ scheduleMissing(taskId, record) {
194
+ if (record.missingFromSnapshot) {
195
+ return;
196
+ }
197
+ record.missingFromSnapshot = true;
198
+ record.missingTimer = setTimeout(() => {
199
+ record.missingTimer = undefined;
200
+ if (!record.missingFromSnapshot || this.isConcreteTerminal(record.state)) {
201
+ return;
202
+ }
203
+ record.state = 'unknown';
204
+ record.reason =
205
+ 'Provider background task disappeared before a terminal lifecycle event was observed';
206
+ this.publish(taskId, record);
207
+ this.reconcileBackgroundTasksActive();
208
+ this.scheduleRetention(taskId, record);
209
+ }, MISSING_TASK_GRACE_MS);
210
+ }
211
+ cancelMissing(record) {
212
+ record.missingFromSnapshot = false;
213
+ if (record.missingTimer) {
214
+ clearTimeout(record.missingTimer);
215
+ record.missingTimer = undefined;
216
+ }
217
+ }
218
+ scheduleRetention(taskId, record) {
219
+ this.cancelRetention(record);
220
+ record.retentionTimer = setTimeout(() => {
221
+ if (this.tasks.get(taskId) === record) {
222
+ this.deleteTask(taskId);
223
+ }
224
+ }, this.limits.terminalRetentionMs ?? TERMINAL_TASK_RETENTION_MS);
225
+ }
226
+ cancelRetention(record) {
227
+ if (record.retentionTimer) {
228
+ clearTimeout(record.retentionTimer);
229
+ record.retentionTimer = undefined;
230
+ }
231
+ }
232
+ touch(taskId, record) {
233
+ this.tasks.delete(taskId);
234
+ this.tasks.set(taskId, record);
235
+ }
236
+ enforceLimit() {
237
+ const limit = this.limits.maxTrackedTasks ?? MAX_TRACKED_TASKS;
238
+ const countsAsHistory = (record) => !record.background || this.isTerminal(record.state);
239
+ let historySize = [...this.tasks.values()].filter(countsAsHistory).length;
240
+ while (historySize > limit) {
241
+ const candidate = [...this.tasks].find(([, record]) => countsAsHistory(record) && !record.retentionTimer);
242
+ if (!candidate) {
243
+ // Live identities and terminal enrichment windows are required state.
244
+ // Their timers converge the temporary history excess after the window.
245
+ return;
246
+ }
247
+ this.deleteTask(candidate[0]);
248
+ historySize -= 1;
249
+ }
250
+ }
251
+ isTerminal(state) {
252
+ return this.isConcreteTerminal(state) || state === 'unknown';
253
+ }
254
+ deleteTask(taskId) {
255
+ const record = this.tasks.get(taskId);
256
+ if (!record) {
257
+ return;
258
+ }
259
+ this.cancelMissing(record);
260
+ this.cancelRetention(record);
261
+ this.tasks.delete(taskId);
262
+ this.emitted.delete(taskId);
263
+ this.reconcileBackgroundTasksActive();
264
+ }
265
+ publish(taskId, record) {
266
+ if (!this.onProgress) {
267
+ return;
268
+ }
269
+ const run = {
270
+ providerRunId: taskId,
271
+ executionId: taskId,
272
+ label: record.label,
273
+ state: record.state,
274
+ ...(record.parentActivityId ? { parentActivityId: record.parentActivityId } : {}),
275
+ ...(record.reason ? { reason: record.reason } : {}),
276
+ stopSupported: this.limits.targetedCancellationSupported === true,
277
+ };
278
+ const fingerprint = JSON.stringify(run);
279
+ if (this.emitted.get(taskId) === fingerprint) {
280
+ return;
281
+ }
282
+ this.emitted.set(taskId, fingerprint);
283
+ this.onProgress({ type: 'background_run', run });
284
+ }
285
+ reconcileBackgroundTasksActive() {
286
+ this.setBackgroundTasksActive([...this.tasks.values()].some((record) => record.background && !this.isTerminal(record.state)));
287
+ }
288
+ setBackgroundTasksActive(active) {
289
+ if (this.backgroundTasksActive === active) {
290
+ return;
291
+ }
292
+ this.backgroundTasksActive = active;
293
+ this.limits.onBackgroundTasksActiveChanged?.(active);
294
+ }
295
+ }
296
+ function parseClaudeTaskLifecycleRecord(lifecycle) {
297
+ const event = lifecycle.event;
298
+ if (event === 'background_tasks_changed') {
299
+ if (!Array.isArray(lifecycle.tasks)) {
300
+ return null;
301
+ }
302
+ const tasks = lifecycle.tasks.flatMap((task) => {
303
+ if (!isRecord(task)) {
304
+ return [];
305
+ }
306
+ const taskId = readOptionalString(task, 'taskId');
307
+ const taskType = readOptionalString(task, 'taskType');
308
+ const description = readOptionalString(task, 'description');
309
+ return taskId && taskType && description ? [{ taskId, taskType, description }] : [];
310
+ });
311
+ return tasks.length === lifecycle.tasks.length ? { event, tasks } : null;
312
+ }
313
+ const taskId = readOptionalString(lifecycle, 'taskId');
314
+ if (!taskId) {
315
+ return null;
316
+ }
317
+ if (event === 'started') {
318
+ const description = readOptionalString(lifecycle, 'description');
319
+ if (!description) {
320
+ return null;
321
+ }
322
+ const toolUseId = readOptionalString(lifecycle, 'toolUseId');
323
+ const subagentType = readOptionalString(lifecycle, 'subagentType');
324
+ const taskType = readOptionalString(lifecycle, 'taskType');
325
+ return {
326
+ event,
327
+ taskId,
328
+ description,
329
+ ...(toolUseId ? { toolUseId } : {}),
330
+ ...(subagentType ? { subagentType } : {}),
331
+ ...(taskType ? { taskType } : {}),
332
+ };
333
+ }
334
+ if (event === 'updated') {
335
+ if (!isRecord(lifecycle.patch)) {
336
+ return null;
337
+ }
338
+ const status = readOptionalString(lifecycle.patch, 'status');
339
+ const validStatuses = new Set([
340
+ 'pending',
341
+ 'running',
342
+ 'completed',
343
+ 'failed',
344
+ 'killed',
345
+ 'paused',
346
+ ]);
347
+ if (status !== undefined && !validStatuses.has(status)) {
348
+ return null;
349
+ }
350
+ const description = readOptionalString(lifecycle.patch, 'description');
351
+ const error = readOptionalString(lifecycle.patch, 'error');
352
+ return {
353
+ event,
354
+ taskId,
355
+ patch: {
356
+ ...(status ? { status: status } : {}),
357
+ ...(description ? { description } : {}),
358
+ ...(error ? { error } : {}),
359
+ ...(typeof lifecycle.patch.is_backgrounded === 'boolean'
360
+ ? { is_backgrounded: lifecycle.patch.is_backgrounded }
361
+ : {}),
362
+ },
363
+ };
364
+ }
365
+ if (event === 'notification') {
366
+ const status = readOptionalString(lifecycle, 'status');
367
+ const summary = readOptionalString(lifecycle, 'summary');
368
+ if (!summary || (status !== 'completed' && status !== 'failed' && status !== 'stopped')) {
369
+ return null;
370
+ }
371
+ const toolUseId = readOptionalString(lifecycle, 'toolUseId');
372
+ return {
373
+ event,
374
+ taskId,
375
+ status,
376
+ summary,
377
+ ...(toolUseId ? { toolUseId } : {}),
378
+ };
379
+ }
380
+ return null;
381
+ }
@@ -1,7 +1,7 @@
1
1
  import spawn from 'cross-spawn';
2
2
  import { PROTOCOL_VERSION, client, methods, ndJsonStream } from '@agentclientprotocol/sdk';
3
3
  import { type DebugLogger } from '../../debug.js';
4
- import type { PreparedProviderTurnInput, ProviderGenerateOptions } from '../../types.js';
4
+ import type { PreparedProviderTurnInput, ProviderAutonomousReply, ProviderGenerateOptions } from '../../types.js';
5
5
  import type { ClaudeChannelSessionStore } from './session-store.js';
6
6
  interface ClaudeAcpRuntime {
7
7
  spawn: typeof spawn;
@@ -37,15 +37,22 @@ export declare class ClaudeCliClient {
37
37
  private readonly imageInputConfig;
38
38
  private readonly runtime;
39
39
  private readonly channels;
40
+ private readonly channelWorkerRoutes;
41
+ readonly targetedBackgroundRunCancellationConfigured: boolean;
40
42
  /**
41
43
  * The provider session currently bound to channelId, or undefined before a
42
44
  * turn has opened one. Surfaced so agents-host can record which session
43
45
  * worked a task without the agent being asked to report its own id.
44
46
  */
45
47
  sessionIdForChannel(channelId: string): string | undefined;
48
+ handoffForegroundTurn(channelId: string): Promise<{
49
+ outcome: 'admitted' | 'not_found';
50
+ }>;
46
51
  cancelTurn(channelId: string): Promise<boolean>;
52
+ cancelBackgroundRun(channelId: string, providerRunId: string): Promise<boolean>;
47
53
  private readonly persistedSessions;
48
54
  private readonly closingSessions;
55
+ private readonly sessionUpdatePumps;
49
56
  private readonly pendingSessionStarts;
50
57
  private readonly pendingSessionCloses;
51
58
  private readonly pendingSessionStoreOperations;
@@ -70,15 +77,19 @@ export declare class ClaudeCliClient {
70
77
  private sessionStoreLoadPromise;
71
78
  private sessionStoreWriteQueue;
72
79
  private sessionCapabilities;
80
+ private targetedBackgroundRunCancellationAvailable;
81
+ private autonomousReplyHandler?;
73
82
  private readonly idleBackendShutdown;
74
83
  private childStderr;
75
84
  constructor(command: string, args?: string[], runtimeOverrides?: Partial<ClaudeAcpRuntime>, sessionStore?: ClaudeChannelSessionStore | undefined, resolveSessionStoreAgentId?: () => string | undefined, logger?: DebugLogger, imageInputConfig?: ClaudeHostedImageInputConfig);
85
+ onAutonomousReply(handler: ((reply: ProviderAutonomousReply) => void) | undefined): void;
76
86
  generateReply(turn: PreparedProviderTurnInput, options?: ProviderGenerateOptions): Promise<string>;
77
87
  generateReply(channelId: string, prompt: string, options?: ProviderGenerateOptions): Promise<string>;
78
88
  dispose(): Promise<void>;
79
89
  private ensureStarted;
80
90
  private startBackend;
81
91
  private getOrCreateChannelState;
92
+ private resolveChannelState;
82
93
  private processChannelQueue;
83
94
  private getOrCreateSession;
84
95
  private startFreshSession;
@@ -92,6 +103,9 @@ export declare class ClaudeCliClient {
92
103
  private failAll;
93
104
  private handlePermissionRequest;
94
105
  private invalidateSession;
106
+ private promoteWorkerRoute;
107
+ private releaseWorkerRoute;
108
+ private reconcileIdleChannelState;
95
109
  private closeSession;
96
110
  private rejectQueuedTurnsAfterSessionTaint;
97
111
  private findChannelStateBySessionId;