@automatalabs/acp-agents 0.13.0 → 0.15.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.
@@ -1,10 +1,10 @@
1
- import { type ContentBlock, type AgentNotificationMethod, type AgentNotificationParamsByMethod, type AgentRequestMethod, type AgentRequestParamsByMethod, type AgentRequestResponsesByMethod, type PromptRequest, type PromptResponse, type RequestPermissionResponse, type SendRequestOptions, type SessionConfigOption, type SessionModeState, type SessionNotification, type SetSessionConfigOptionRequest, type SetSessionConfigOptionResponse, type SetSessionModeRequest, type SetSessionModeResponse } from "@agentclientprotocol/sdk";
1
+ import { type CreateElicitationResponse, type ContentBlock, type AgentNotificationMethod, type AgentNotificationParamsByMethod, type AgentRequestMethod, type AgentRequestParamsByMethod, type AgentRequestResponsesByMethod, type DeleteSessionRequest, type ListSessionsRequest, type ListSessionsResponse, type PromptRequest, type PromptResponse, type RequestPermissionResponse, type SendRequestOptions, type SessionConfigOption, type SessionModeState, type SessionNotification, type SetSessionConfigOptionRequest, type SetSessionConfigOptionResponse, type SetSessionModeRequest, type SetSessionModeResponse } from "@agentclientprotocol/sdk";
2
2
  import type { TSchema } from "typebox";
3
3
  import { type AgentHistoryEntry, type McpServerConfig } from "@automatalabs/shared-types";
4
4
  import type { Backend, BackendId, StructuredSource } from "./backend.js";
5
5
  import { type NegotiatedCapabilities } from "./capabilities.js";
6
6
  import { type AcpEventSink } from "./events.js";
7
- import { type PermissionResolver, type ToolPolicy } from "./permissions.js";
7
+ import { type ElicitationResolver, type PermissionResolver, type ToolPolicy } from "./permissions.js";
8
8
  import { UsageAccumulator } from "./usage.js";
9
9
  import { type ClientHandlers } from "./client-handlers.js";
10
10
  interface RawResultSuccess {
@@ -18,6 +18,7 @@ declare class SessionState {
18
18
  readonly cwd: string;
19
19
  readonly policy: ToolPolicy;
20
20
  readonly permissionResolver?: PermissionResolver | undefined;
21
+ readonly elicitationResolver?: ElicitationResolver | undefined;
21
22
  readonly label?: string | undefined;
22
23
  readonly runId?: string | undefined;
23
24
  private readonly retainSessionLog;
@@ -25,12 +26,14 @@ declare class SessionState {
25
26
  readonly history: AgentHistoryEntry[];
26
27
  readonly usage: UsageAccumulator;
27
28
  readonly pendingPermissions: Set<(outcome: RequestPermissionResponse) => void>;
29
+ readonly pendingElicitations: Set<(outcome: CreateElicitationResponse) => void>;
30
+ readonly urlElicitationIds: Set<string>;
28
31
  rawResultSuccess: RawResultSuccess | undefined;
29
32
  modes: SessionModeState | null | undefined;
30
33
  private turnStartIndex;
31
34
  /** `label`/`runId` are carried here ONLY so the MultiplexClient can stamp them onto emitted
32
35
  * events as context — they never affect routing or the wire request. */
33
- constructor(cwd: string, policy: ToolPolicy, permissionResolver?: PermissionResolver | undefined, label?: string | undefined, runId?: string | undefined, modes?: SessionModeState | null, retainSessionLog?: boolean);
36
+ constructor(cwd: string, policy: ToolPolicy, permissionResolver?: PermissionResolver | undefined, elicitationResolver?: ElicitationResolver | undefined, label?: string | undefined, runId?: string | undefined, modes?: SessionModeState | null, retainSessionLog?: boolean);
34
37
  /** Mark the start of a new turn so currentTurnText()/structured_output read only this turn.
35
38
  * Long-lived interactive sessions can opt out of retaining old text/history because hosts
36
39
  * stream live events and keep their own transcript; clearing here prevents dead logs from
@@ -42,6 +45,9 @@ declare class SessionState {
42
45
  /** Settle every deferred permission still parked on this session. Used by release/cancel/death
43
46
  * teardown so an interactive resolver can never strand an ACP prompt turn. */
44
47
  settlePendingPermissions(): void;
48
+ /** Same teardown guarantee for elicitation/create: a parked human prompt must not survive
49
+ * release/cancel/death after its ACP session is gone. */
50
+ settlePendingElicitations(): void;
45
51
  }
46
52
  export interface AcpSessionOptions {
47
53
  /** Absolute working directory for the ACP session (worktree isolation). */
@@ -52,6 +58,9 @@ export interface AcpSessionOptions {
52
58
  /** Session-scoped permission resolver. When present it wins over the runner default and
53
59
  * replaces the synchronous ToolPolicy auto-response path for this session. */
54
60
  permissionResolver?: PermissionResolver;
61
+ /** Session-scoped elicitation resolver. When present it wins over the runner default for this
62
+ * session; initialize-time advertisement still depends on the runner-wide resolver. */
63
+ elicitationResolver?: ElicitationResolver;
55
64
  signal?: AbortSignal;
56
65
  /** Client-provided MCP servers to attach at session/new. Omitted => `[]` (the default). */
57
66
  mcpServers?: McpServerConfig[];
@@ -83,6 +92,11 @@ export interface PooledConnectionDeps {
83
92
  onEvent?: AcpEventSink;
84
93
  /** Runner-wide permission resolver default. SessionState.permissionResolver overrides it. */
85
94
  permissionResolver?: PermissionResolver;
95
+ /** Runner-wide elicitation resolver default. SessionState.elicitationResolver overrides it. */
96
+ elicitationResolver?: ElicitationResolver;
97
+ /** Initialize-time elicitation advertisement; fixed per connection, so it is driven by the
98
+ * runner-wide resolver rather than session-scoped responders attached later. */
99
+ advertiseElicitation?: boolean;
86
100
  /** Client-side ACP fs/terminal handlers advertised once and routed by sessionId. */
87
101
  clientHandlers?: ClientHandlers;
88
102
  }
@@ -102,6 +116,7 @@ export declare class PooledConnection {
102
116
  private readonly onDead;
103
117
  private readonly onEvent;
104
118
  private readonly clientHandlers;
119
+ private readonly advertiseElicitation;
105
120
  /** Set true at the start of dispose() so the graceful-shutdown death is NOT reported as a crash. */
106
121
  private disposing;
107
122
  /** Resolves once `initialize` completed (or rejects if the process died first). */
@@ -127,6 +142,9 @@ export declare class PooledConnection {
127
142
  /** Drop the backend-declared bare `_meta` keys the connected agent did not advertise support
128
143
  * for (see gateCustomMeta). Applied to BOTH session/new and session/prompt `_meta`. */
129
144
  gateCustomMeta(meta: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
145
+ private assertSupportedMcpServers;
146
+ private sessionRequestMeta;
147
+ private assertLifecycleSupported;
130
148
  /** Mark this connection dead exactly once, then ask the pool to evict it. Idempotent. */
131
149
  private die;
132
150
  private stderrSuffix;
@@ -140,6 +158,16 @@ export declare class PooledConnection {
140
158
  * synchronously (before the first await) so the pool's load accounting is race-free.
141
159
  */
142
160
  openSession(opts: AcpSessionOptions): Promise<SessionHandle>;
161
+ /** Reopen an existing session and replay its transcript through the router before resolving. */
162
+ loadSession(sessionId: string, opts: AcpSessionOptions): Promise<SessionHandle>;
163
+ /** Reopen an existing session without transcript replay. */
164
+ resumeSession(sessionId: string, opts: AcpSessionOptions): Promise<SessionHandle>;
165
+ private rawAgentRequest;
166
+ private reattachSession;
167
+ /** session/list on a dedicated connection, gated on the initialize advertisement. */
168
+ listSessions(request: ListSessionsRequest, label?: string): Promise<ListSessionsResponse>;
169
+ /** session/delete on a dedicated connection, gated on the initialize advertisement. */
170
+ deleteSession(request: DeleteSessionRequest, label?: string): Promise<void>;
143
171
  /** session/prompt on this connection, raced against process death. */
144
172
  prompt(request: PromptRequest): Promise<PromptResponse>;
145
173
  /** session/set_config_option on this connection, raced against process death. */
@@ -187,6 +215,8 @@ export declare class SessionHandle implements StructuredSource {
187
215
  get usage(): UsageAccumulator;
188
216
  /** Diagnostic message/tool history accumulated across this session's run. */
189
217
  get history(): AgentHistoryEntry[];
218
+ /** Assistant text accumulated across the retained session log. */
219
+ get text(): string;
190
220
  /** Agent-advertised session mode catalog plus the currently active mode, if supported. */
191
221
  get modes(): SessionModeState | null | undefined;
192
222
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"acp-client.d.ts","sourceRoot":"","sources":["../src/acp-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"acp-client.d.ts","sourceRoot":"","sources":["../src/acp-client.ts"],"names":[],"mappings":"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"}
@@ -24,9 +24,9 @@ import { spawn } from "node:child_process";
24
24
  import { Readable, Writable } from "node:stream";
25
25
  import { AGENT_METHODS, client, CLIENT_METHODS, ndJsonStream, PROTOCOL_VERSION, RequestError, } from "@agentclientprotocol/sdk";
26
26
  import { META_KEYS, WorkflowError, WorkflowErrorCode, } from "@automatalabs/shared-types";
27
- import { adaptPromptContent, gateCustomMeta, isSupportedProtocolVersion, negotiateCapabilities, unsupportedMcpServer, } from "./capabilities.js";
27
+ import { adaptPromptContent, describeLifecycleAdvertisement, gateCustomMeta, isSupportedProtocolVersion, negotiateCapabilities, unsupportedMcpServer, } from "./capabilities.js";
28
28
  import { emitSessionUpdate } from "./events.js";
29
- import { decidePermission } from "./permissions.js";
29
+ import { decidePermission, } from "./permissions.js";
30
30
  import { UsageAccumulator } from "./usage.js";
31
31
  import { clientCapabilitiesFor, } from "./client-handlers.js";
32
32
  /** A benign client identity. NOT JetBrains/IntelliJ 2026.1 — that exact identity makes
@@ -42,12 +42,22 @@ const CLOSE_SESSION_TIMEOUT_MS = 5_000;
42
42
  /** Bound the graceful SIGTERM shutdown before escalating to SIGKILL. */
43
43
  const DISPOSE_SIGKILL_GRACE_MS = 2_000;
44
44
  const TOMBSTONE_SESSION_CAP = 64;
45
+ const GUARDED_STATEFUL_REQUESTS = new Map([
46
+ [AGENT_METHODS.session_new, "use openSession()"],
47
+ [AGENT_METHODS.session_load, "use loadSession()"],
48
+ [AGENT_METHODS.session_resume, "use resumeSession()"],
49
+ [
50
+ AGENT_METHODS.session_fork,
51
+ "no driven wrapper yet; raw forked sessions cannot be routed (permissions auto-cancel)",
52
+ ],
53
+ ]);
45
54
  /** Per-session accumulator: assistant text, tool history, usage, the Claude raw structured_output,
46
55
  * and the permission policy/resolver used to answer permission requests for THIS session. */
47
56
  class SessionState {
48
57
  cwd;
49
58
  policy;
50
59
  permissionResolver;
60
+ elicitationResolver;
51
61
  label;
52
62
  runId;
53
63
  retainSessionLog;
@@ -55,15 +65,18 @@ class SessionState {
55
65
  history = [];
56
66
  usage = new UsageAccumulator();
57
67
  pendingPermissions = new Set();
68
+ pendingElicitations = new Set();
69
+ urlElicitationIds = new Set();
58
70
  rawResultSuccess;
59
71
  modes;
60
72
  turnStartIndex = 0;
61
73
  /** `label`/`runId` are carried here ONLY so the MultiplexClient can stamp them onto emitted
62
74
  * events as context — they never affect routing or the wire request. */
63
- constructor(cwd, policy, permissionResolver, label, runId, modes, retainSessionLog = true) {
75
+ constructor(cwd, policy, permissionResolver, elicitationResolver, label, runId, modes, retainSessionLog = true) {
64
76
  this.cwd = cwd;
65
77
  this.policy = policy;
66
78
  this.permissionResolver = permissionResolver;
79
+ this.elicitationResolver = elicitationResolver;
67
80
  this.label = label;
68
81
  this.runId = runId;
69
82
  this.retainSessionLog = retainSessionLog;
@@ -140,6 +153,12 @@ class SessionState {
140
153
  for (const settle of [...this.pendingPermissions])
141
154
  settle(cancelledPermissionResponse());
142
155
  }
156
+ /** Same teardown guarantee for elicitation/create: a parked human prompt must not survive
157
+ * release/cancel/death after its ACP session is gone. */
158
+ settlePendingElicitations() {
159
+ for (const settle of [...this.pendingElicitations])
160
+ settle(cancelledElicitationResponse());
161
+ }
143
162
  }
144
163
  /** The single client-side handler set for one pooled connection (registered on the SDK's fluent
145
164
  * client() app). It ROUTES every notification and permission request to the per-session
@@ -150,7 +169,9 @@ class MultiplexClient {
150
169
  onEvent;
151
170
  handlers;
152
171
  permissionResolver;
172
+ elicitationResolver;
153
173
  sessions = new Map();
174
+ urlElicitationContexts = new Map();
154
175
  /** Recently unregistered sessions kept ONLY for the teardown window: ACP agents may
155
176
  * legitimately release terminals (or finish fs/terminal cleanup) after this client releases
156
177
  * the session because session/close is cancel + free resources and the Agent owns terminal
@@ -159,11 +180,12 @@ class MultiplexClient {
159
180
  /** `backendId` stamps event context; `onEvent` (optional) bubbles every notification, permission
160
181
  * request and session lifecycle change up to the runner's typed bus. `permissionResolver` is
161
182
  * the runner-wide default; a SessionState resolver wins when present. */
162
- constructor(backendId, onEvent, handlers, permissionResolver) {
183
+ constructor(backendId, onEvent, handlers, permissionResolver, elicitationResolver) {
163
184
  this.backendId = backendId;
164
185
  this.onEvent = onEvent;
165
186
  this.handlers = handlers;
166
187
  this.permissionResolver = permissionResolver;
188
+ this.elicitationResolver = elicitationResolver;
167
189
  }
168
190
  contextFor(sessionId, state) {
169
191
  return { sessionId, backendId: this.backendId, label: state?.label, runId: state?.runId };
@@ -191,8 +213,11 @@ class MultiplexClient {
191
213
  unregister(sessionId) {
192
214
  const state = this.sessions.get(sessionId);
193
215
  state?.settlePendingPermissions();
216
+ state?.settlePendingElicitations();
194
217
  this.sessions.delete(sessionId);
195
218
  if (state) {
219
+ for (const elicitationId of state.urlElicitationIds)
220
+ this.urlElicitationContexts.delete(elicitationId);
196
221
  this.tombstones.set(sessionId, {
197
222
  cwd: state.cwd,
198
223
  label: state.label,
@@ -210,11 +235,19 @@ class MultiplexClient {
210
235
  settlePendingPermissions(sessionId) {
211
236
  this.sessions.get(sessionId)?.settlePendingPermissions();
212
237
  }
238
+ settlePendingElicitations(sessionId) {
239
+ this.sessions.get(sessionId)?.settlePendingElicitations();
240
+ }
213
241
  settleAllPendingPermissions() {
214
242
  for (const state of this.sessions.values()) {
215
243
  state.settlePendingPermissions();
216
244
  }
217
245
  }
246
+ settleAllPendingElicitations() {
247
+ for (const state of this.sessions.values()) {
248
+ state.settlePendingElicitations();
249
+ }
250
+ }
218
251
  requestPermission(params) {
219
252
  const state = this.sessions.get(params.sessionId);
220
253
  // Unknown/closed session: refuse rather than silently allow a tool we can't attribute.
@@ -262,6 +295,63 @@ class MultiplexClient {
262
295
  response.catch(() => { });
263
296
  return response;
264
297
  }
298
+ requestElicitation(params) {
299
+ const sessionId = sessionIdFromElicitationRequest(params);
300
+ if (!sessionId)
301
+ return declinedElicitationResponse();
302
+ const state = this.sessions.get(sessionId);
303
+ const ctx = this.contextFor(sessionId, state);
304
+ // Unknown/closed session: decline rather than asking a human for a prompt we cannot route.
305
+ if (!state) {
306
+ const outcome = declinedElicitationResponse();
307
+ this.onEvent?.("elicitation_request", { ...ctx, request: params, outcome });
308
+ return outcome;
309
+ }
310
+ this.trackUrlElicitation(params, state, ctx);
311
+ const resolver = state.elicitationResolver ?? this.elicitationResolver;
312
+ if (resolver)
313
+ return this.requestElicitationViaResolver(params, state, ctx, resolver);
314
+ const outcome = declinedElicitationResponse();
315
+ this.onEvent?.("elicitation_request", { ...ctx, request: params, outcome });
316
+ return outcome;
317
+ }
318
+ requestElicitationViaResolver(params, state, ctx, resolver) {
319
+ let settled = false;
320
+ let settle;
321
+ const response = new Promise((resolve) => {
322
+ settle = (outcome) => {
323
+ if (settled)
324
+ return;
325
+ settled = true;
326
+ state.pendingElicitations.delete(settle);
327
+ this.onEvent?.("elicitation_request", { ...ctx, request: params, outcome });
328
+ resolve(outcome);
329
+ };
330
+ state.pendingElicitations.add(settle);
331
+ this.onEvent?.("elicitation_pending", { ...ctx, request: params });
332
+ try {
333
+ Promise.resolve(resolver(params, ctx)).then((outcome) => {
334
+ settle(outcome);
335
+ }, () => {
336
+ // Resolver failure is observable as the FINAL cancel outcome; no extra error event is
337
+ // needed, and the prompt turn continues instead of hanging behind a rejected promise.
338
+ settle(cancelledElicitationResponse());
339
+ });
340
+ }
341
+ catch {
342
+ settle(cancelledElicitationResponse());
343
+ }
344
+ });
345
+ response.catch(() => { });
346
+ return response;
347
+ }
348
+ trackUrlElicitation(params, state, ctx) {
349
+ const elicitationId = urlElicitationId(params);
350
+ if (!elicitationId)
351
+ return;
352
+ state.urlElicitationIds.add(elicitationId);
353
+ this.urlElicitationContexts.set(elicitationId, ctx);
354
+ }
265
355
  readTextFile(params) {
266
356
  return this.dispatch(params, CLIENT_METHODS.fs_read_text_file, this.handlers?.fs?.readTextFile);
267
357
  }
@@ -308,6 +398,14 @@ class MultiplexClient {
308
398
  message: rawMessage,
309
399
  });
310
400
  }
401
+ elicitationComplete(params) {
402
+ const ctx = this.urlElicitationContexts.get(params.elicitationId);
403
+ if (!ctx)
404
+ return;
405
+ this.urlElicitationContexts.delete(params.elicitationId);
406
+ this.sessions.get(ctx.sessionId)?.urlElicitationIds.delete(params.elicitationId);
407
+ this.onEvent?.("elicitation_complete", { ...ctx, notification: params });
408
+ }
311
409
  }
312
410
  function unknownSession(sessionId) {
313
411
  return RequestError.invalidParams({ sessionId }, `unknown session: ${sessionId}`);
@@ -315,9 +413,31 @@ function unknownSession(sessionId) {
315
413
  function cancelledPermissionResponse() {
316
414
  return { outcome: { outcome: "cancelled" } };
317
415
  }
416
+ function declinedElicitationResponse() {
417
+ return { action: "decline" };
418
+ }
419
+ function cancelledElicitationResponse() {
420
+ return { action: "cancel" };
421
+ }
422
+ function sessionIdFromElicitationRequest(params) {
423
+ return "sessionId" in params && typeof params.sessionId === "string" ? params.sessionId : undefined;
424
+ }
425
+ function urlElicitationId(params) {
426
+ return params.mode === "url" && "elicitationId" in params && typeof params.elicitationId === "string"
427
+ ? params.elicitationId
428
+ : undefined;
429
+ }
318
430
  function methodNotAdvertised(method) {
319
431
  return new RequestError(-32601, `${method} was not advertised by this client`, { method });
320
432
  }
433
+ function assertSafeRawRequest(method) {
434
+ const guidance = GUARDED_STATEFUL_REQUESTS.get(method);
435
+ if (!guidance)
436
+ return;
437
+ throw new Error(`Raw ACP request "${method}" is guarded: ${guidance}. Sessions created, reopened, or forked ` +
438
+ "outside the router are unregistered: session/update notifications do not fold into an " +
439
+ "accumulator, permission requests auto-cancel, and fs/terminal dispatch fails for unknown sessions.");
440
+ }
321
441
  function modeIds(modes) {
322
442
  return modes?.availableModes.map((mode) => mode.id) ?? [];
323
443
  }
@@ -326,6 +446,12 @@ function modeSelectionError(backendId, requested, advertisedIds, label, cause) {
326
446
  const suffix = cause ? `: ${thrownMessage(cause)}` : "";
327
447
  return new WorkflowError(`ACP agent (${backendId}) cannot apply session mode "${requested}" (advertised modes: ${advertised})${suffix}`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: label, details: cause });
328
448
  }
449
+ function lifecycleCapabilityError(backendId, method, capabilities, label) {
450
+ const advertised = capabilities
451
+ ? describeLifecycleAdvertisement(capabilities.agent)
452
+ : "initialize did not complete";
453
+ return new WorkflowError(`ACP agent (${backendId}) does not advertise ${method}; advertised lifecycle capabilities: ${advertised}`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: label });
454
+ }
329
455
  function thrownMessage(error) {
330
456
  if (error instanceof Error)
331
457
  return error.message;
@@ -388,6 +514,7 @@ export class PooledConnection {
388
514
  onDead;
389
515
  onEvent;
390
516
  clientHandlers;
517
+ advertiseElicitation;
391
518
  /** Set true at the start of dispose() so the graceful-shutdown death is NOT reported as a crash. */
392
519
  disposing = false;
393
520
  /** Resolves once `initialize` completed (or rejects if the process died first). */
@@ -407,7 +534,8 @@ export class PooledConnection {
407
534
  this.onDead = deps.onDead;
408
535
  this.onEvent = deps.onEvent;
409
536
  this.clientHandlers = deps.clientHandlers;
410
- this.client = new MultiplexClient(this.backendId, this.onEvent, deps.clientHandlers, deps.permissionResolver);
537
+ this.advertiseElicitation = deps.advertiseElicitation ?? Boolean(deps.elicitationResolver);
538
+ this.client = new MultiplexClient(this.backendId, this.onEvent, deps.clientHandlers, deps.permissionResolver, deps.elicitationResolver);
411
539
  const { command, args, env } = backend.spawnConfig();
412
540
  // NOTE: deliberately NO `cwd` here. cwd is per-SESSION (session/new), so one pooled process
413
541
  // serves runs in different worktrees without losing isolation.
@@ -445,7 +573,9 @@ export class PooledConnection {
445
573
  this.connection = client({ name: CLIENT_INFO.name })
446
574
  .onNotification(CLIENT_METHODS.session_update, ({ params }) => this.client.sessionUpdate(params))
447
575
  .onNotification(CLAUDE_RAW_MESSAGE_METHOD, (params) => (params ?? {}), ({ params }) => this.client.extNotification(CLAUDE_RAW_MESSAGE_METHOD, params))
576
+ .onNotification(CLIENT_METHODS.elicitation_complete, ({ params }) => this.client.elicitationComplete(params))
448
577
  .onRequest(CLIENT_METHODS.session_request_permission, ({ params }) => this.client.requestPermission(params))
578
+ .onRequest(CLIENT_METHODS.elicitation_create, ({ params }) => this.client.requestElicitation(params))
449
579
  .onRequest(CLIENT_METHODS.fs_read_text_file, ({ params }) => this.client.readTextFile(params))
450
580
  .onRequest(CLIENT_METHODS.fs_write_text_file, ({ params }) => this.client.writeTextFile(params))
451
581
  .onRequest(CLIENT_METHODS.terminal_create, ({ params }) => this.client.createTerminal(params))
@@ -490,6 +620,35 @@ export class PooledConnection {
490
620
  gateCustomMeta(meta) {
491
621
  return gateCustomMeta(meta, this.negotiated?.customMetaSupport, this.negotiated?.gatedKeys);
492
622
  }
623
+ assertSupportedMcpServers(opts) {
624
+ const unsupported = this.negotiated
625
+ ? unsupportedMcpServer(opts.mcpServers, this.negotiated.agent)
626
+ : undefined;
627
+ if (!unsupported)
628
+ return;
629
+ throw new WorkflowError(`MCP server "${unsupported.name}" uses the "${unsupported.transport}" transport, which the ` +
630
+ `${this.backendId} agent does not support`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: opts.label });
631
+ }
632
+ sessionRequestMeta(opts) {
633
+ return this.gateCustomMeta(stampRunId(layerMeta(this.backend.sessionMetaDefaults?.(), opts.meta, this.backend.sessionMeta(opts.schema, {
634
+ baseInstructions: opts.baseInstructions,
635
+ developerInstructions: opts.developerInstructions,
636
+ })), opts.runId));
637
+ }
638
+ assertLifecycleSupported(method, label) {
639
+ const supported = method === AGENT_METHODS.session_load
640
+ ? this.negotiated?.supportsLoadSession
641
+ : method === AGENT_METHODS.session_list
642
+ ? this.negotiated?.supportsListSessions
643
+ : method === AGENT_METHODS.session_delete
644
+ ? this.negotiated?.supportsDeleteSession
645
+ : method === AGENT_METHODS.session_resume
646
+ ? this.negotiated?.supportsResumeSession
647
+ : false;
648
+ if (supported)
649
+ return;
650
+ throw lifecycleCapabilityError(this.backendId, method, this.negotiated, label);
651
+ }
493
652
  /** Mark this connection dead exactly once, then ask the pool to evict it. Idempotent. */
494
653
  die(error) {
495
654
  if (!this._alive)
@@ -498,6 +657,7 @@ export class PooledConnection {
498
657
  this.deathError = error;
499
658
  this.resolveDead();
500
659
  this.client.settleAllPendingPermissions();
660
+ this.client.settleAllPendingElicitations();
501
661
  // A crash (not a graceful dispose) is worth surfacing for observability; the engine still
502
662
  // handles it by retrying the run on a fresh process. Best-effort, after death is recorded.
503
663
  if (this.onEvent && !this.disposing) {
@@ -541,7 +701,9 @@ export class PooledConnection {
541
701
  protocolVersion: PROTOCOL_VERSION,
542
702
  // Truthful advertisement: computed from the consumer-provided handlers registered on
543
703
  // this runner. Omitted flags are unsupported; false flags are never sent deliberately.
544
- clientCapabilities: clientCapabilitiesFor(this.clientHandlers),
704
+ clientCapabilities: clientCapabilitiesFor(this.clientHandlers, {
705
+ elicitation: this.advertiseElicitation,
706
+ }),
545
707
  clientInfo: { ...CLIENT_INFO },
546
708
  })),
547
709
  deadline,
@@ -577,23 +739,14 @@ export class PooledConnection {
577
739
  // does not advertise (http/sse gated on mcpCapabilities; stdio is always serviceable).
578
740
  // Fail-fast and non-recoverable — re-running the same incompatible transport can never
579
741
  // succeed. Lenient for agents that advertise no mcpCapabilities (the legacy passthrough).
580
- const unsupported = this.negotiated
581
- ? unsupportedMcpServer(opts.mcpServers, this.negotiated.agent)
582
- : undefined;
583
- if (unsupported) {
584
- throw new WorkflowError(`MCP server "${unsupported.name}" uses the "${unsupported.transport}" transport, which the ` +
585
- `${this.backendId} agent does not support`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: opts.label });
586
- }
742
+ this.assertSupportedMcpServers(opts);
587
743
  // session/new `_meta`, layered lowest-to-highest precedence: the backend's static
588
744
  // defaults (a custom registry entry's `sessionMeta`), then the generic user passthrough
589
745
  // (opts.meta), then the backend's protocol-critical `_meta` (Claude schema channel;
590
746
  // Codex base/developer instructions), then the engine runId correlation stamp. The result
591
747
  // is gated against the agent's advertised custom capabilities (a declared key the agent
592
748
  // said it does not honor is dropped). When no layer survives, no `_meta` is sent.
593
- const meta = this.gateCustomMeta(stampRunId(layerMeta(this.backend.sessionMetaDefaults?.(), opts.meta, this.backend.sessionMeta(opts.schema, {
594
- baseInstructions: opts.baseInstructions,
595
- developerInstructions: opts.developerInstructions,
596
- })), opts.runId));
749
+ const meta = this.sessionRequestMeta(opts);
597
750
  const request = {
598
751
  cwd: opts.cwd,
599
752
  // Client-provided MCP servers (additive run input), else the default empty list.
@@ -601,7 +754,7 @@ export class PooledConnection {
601
754
  ...(meta ? { _meta: meta } : {}),
602
755
  };
603
756
  const response = await this.race(this.connection.agent.request(AGENT_METHODS.session_new, request));
604
- const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.label, opts.runId, response.modes, opts.retainSessionLog ?? true);
757
+ const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.elicitationResolver, opts.label, opts.runId, response.modes, opts.retainSessionLog ?? true);
605
758
  this.client.register(response.sessionId, state);
606
759
  return new SessionHandle(this, response.sessionId, state, response.configOptions ?? [], opts);
607
760
  }
@@ -610,6 +763,71 @@ export class PooledConnection {
610
763
  throw error;
611
764
  }
612
765
  }
766
+ /** Reopen an existing session and replay its transcript through the router before resolving. */
767
+ loadSession(sessionId, opts) {
768
+ return this.reattachSession(AGENT_METHODS.session_load, sessionId, opts);
769
+ }
770
+ /** Reopen an existing session without transcript replay. */
771
+ resumeSession(sessionId, opts) {
772
+ return this.reattachSession(AGENT_METHODS.session_resume, sessionId, opts);
773
+ }
774
+ rawAgentRequest(method, params) {
775
+ // SDK 1.2.0 still maps session/load through emptyObjectResponse in ClientContext.request(),
776
+ // but both supported adapters return configOptions/modes there and the driven wrapper must
777
+ // adopt them. This bypasses only the SDK response mapper, not JSON-RPC validation/racing.
778
+ const agent = this.connection.agent;
779
+ return this.race(agent.sendRequest(method, params));
780
+ }
781
+ async reattachSession(method, sessionId, opts) {
782
+ this._activeSessions += 1;
783
+ let registered = false;
784
+ const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.elicitationResolver, opts.label, opts.runId, undefined, opts.retainSessionLog ?? true);
785
+ try {
786
+ await this.ready;
787
+ this.assertLifecycleSupported(method, opts.label);
788
+ this.assertSupportedMcpServers(opts);
789
+ const meta = this.sessionRequestMeta(opts);
790
+ const request = {
791
+ sessionId,
792
+ cwd: opts.cwd,
793
+ mcpServers: opts.mcpServers ?? [],
794
+ ...(meta ? { _meta: meta } : {}),
795
+ };
796
+ // Replayed updates and permission requests can arrive before the response, so the
797
+ // caller-provided id must be routable before the wire call leaves this process.
798
+ this.client.register(sessionId, state);
799
+ registered = true;
800
+ let response;
801
+ if (method === AGENT_METHODS.session_load) {
802
+ const loadRequest = request;
803
+ response = await this.rawAgentRequest(AGENT_METHODS.session_load, loadRequest);
804
+ }
805
+ else {
806
+ const resumeRequest = request;
807
+ response = await this.rawAgentRequest(AGENT_METHODS.session_resume, resumeRequest);
808
+ }
809
+ state.modes = response.modes;
810
+ return new SessionHandle(this, sessionId, state, response.configOptions ?? [], opts);
811
+ }
812
+ catch (error) {
813
+ if (registered)
814
+ this.client.unregister(sessionId);
815
+ this._activeSessions -= 1;
816
+ throw error;
817
+ }
818
+ }
819
+ /** session/list on a dedicated connection, gated on the initialize advertisement. */
820
+ async listSessions(request, label) {
821
+ await this.ready;
822
+ this.assertLifecycleSupported(AGENT_METHODS.session_list, label);
823
+ return this.race(this.connection.agent.request(AGENT_METHODS.session_list, request));
824
+ }
825
+ /** session/delete on a dedicated connection, gated on the initialize advertisement. */
826
+ async deleteSession(request, label) {
827
+ await this.ready;
828
+ this.assertLifecycleSupported(AGENT_METHODS.session_delete, label);
829
+ await this.race(this.connection.agent.request(AGENT_METHODS.session_delete, request));
830
+ }
613
831
  /** session/prompt on this connection, raced against process death. */
614
832
  prompt(request) {
615
833
  return this.race(this.connection.agent.request(AGENT_METHODS.session_prompt, request));
@@ -623,6 +841,7 @@ export class PooledConnection {
623
841
  return this.race(this.connection.agent.request(AGENT_METHODS.session_set_mode, request));
624
842
  }
625
843
  request(method, params, options) {
844
+ assertSafeRawRequest(method);
626
845
  return this.race(this.connection.agent.request(method, params, options));
627
846
  }
628
847
  notify(method, params) {
@@ -631,6 +850,7 @@ export class PooledConnection {
631
850
  /** Best-effort ACP cancel for one session (wired to opts.signal). The PROCESS stays pooled. */
632
851
  async cancelSession(sessionId) {
633
852
  this.client.settlePendingPermissions(sessionId);
853
+ this.client.settlePendingElicitations(sessionId);
634
854
  if (!this._alive)
635
855
  return;
636
856
  try {
@@ -743,6 +963,10 @@ export class SessionHandle {
743
963
  get history() {
744
964
  return this.state.history;
745
965
  }
966
+ /** Assistant text accumulated across the retained session log. */
967
+ get text() {
968
+ return this.state.textChunks.join("");
969
+ }
746
970
  /** Agent-advertised session mode catalog plus the currently active mode, if supported. */
747
971
  get modes() {
748
972
  return this.state.modes;
@@ -18,6 +18,15 @@ export interface NegotiatedCapabilities {
18
18
  agentInfo: Implementation | undefined;
19
19
  /** Whether session/close is advertised (gates the best-effort release-time close). */
20
20
  supportsClose: boolean;
21
+ /** Whether session/load is advertised. The current SDK keeps this as the legacy top-level
22
+ * `loadSession` flag; tolerate a future sessionCapabilities.load shape for forward compat. */
23
+ supportsLoadSession: boolean;
24
+ /** Whether session/list is advertised. */
25
+ supportsListSessions: boolean;
26
+ /** Whether session/delete is advertised. */
27
+ supportsDeleteSession: boolean;
28
+ /** Whether session/resume is advertised. */
29
+ supportsResumeSession: boolean;
21
30
  /** The parsed backend-declared custom-capability block (the namespaced `_meta` object), or
22
31
  * undefined when the backend declared none or the agent did not advertise it — passthrough. */
23
32
  customMetaSupport: Record<string, unknown> | undefined;
@@ -27,6 +36,8 @@ export interface NegotiatedCapabilities {
27
36
  }
28
37
  /** Parse an initialize response into the connection's derived capability state. */
29
38
  export declare function negotiateCapabilities(response: InitializeResponse, customCapabilities?: Backend["customCapabilities"]): NegotiatedCapabilities;
39
+ /** Human-readable lifecycle advertisement summary for strict wrapper gate errors. */
40
+ export declare function describeLifecycleAdvertisement(agent: AgentCapabilities): string;
30
41
  /** True only when the agent selected EXACTLY PROTOCOL_VERSION. This client implements that one wire
31
42
  * version and adapts its behavior to no other, so any other selected version — older or newer —
32
43
  * means close the connection per the ACP spec's SHOULD-close rule. Per the spec the agent echoes
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAkBA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQ5C;;;iGAGiG;AACjG,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAInD,CAAC;AAEF,qFAAqF;AACrF,MAAM,WAAW,sBAAsB;IACrC;0FACsF;IACtF,eAAe,EAAE,MAAM,CAAC;IACxB;4DACwD;IACxD,KAAK,EAAE,iBAAiB,CAAC;IACzB,+DAA+D;IAC/D,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,sFAAsF;IACtF,aAAa,EAAE,OAAO,CAAC;IACvB;oGACgG;IAChG,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACvD;+EAC2E;IAC3E,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAC1C;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,kBAAkB,EAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACjD,sBAAsB,CAYxB;AAaD;;;;+DAI+D;AAC/D,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED;;;gEAGgE;AAChE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC5C,SAAS,GAAE,SAAS,MAAM,EAA2B,GACpD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAWrC;AAED;;;;;2EAK2E;AAC3E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EAAE,EACtB,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,MAAM,GAChB,YAAY,EAAE,CAchB;AAkCD;;;;0EAI0E;AAC1E,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,eAAe,EAAE,GAAG,SAAS,EACtC,KAAK,EAAE,iBAAiB,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAAA;CAAE,GAAG,SAAS,CAYzD"}
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAkBA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQ5C;;;iGAGiG;AACjG,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAInD,CAAC;AAEF,qFAAqF;AACrF,MAAM,WAAW,sBAAsB;IACrC;0FACsF;IACtF,eAAe,EAAE,MAAM,CAAC;IACxB;4DACwD;IACxD,KAAK,EAAE,iBAAiB,CAAC;IACzB,+DAA+D;IAC/D,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,sFAAsF;IACtF,aAAa,EAAE,OAAO,CAAC;IACvB;mGAC+F;IAC/F,mBAAmB,EAAE,OAAO,CAAC;IAC7B,0CAA0C;IAC1C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,4CAA4C;IAC5C,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4CAA4C;IAC5C,qBAAqB,EAAE,OAAO,CAAC;IAC/B;oGACgG;IAChG,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACvD;+EAC2E;IAC3E,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAC1C;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,kBAAkB,EAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACjD,sBAAsB,CAkBxB;AAMD,qFAAqF;AACrF,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAiB/E;AAaD;;;;+DAI+D;AAC/D,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED;;;gEAGgE;AAChE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC5C,SAAS,GAAE,SAAS,MAAM,EAA2B,GACpD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAWrC;AAED;;;;;2EAK2E;AAC3E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EAAE,EACtB,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,MAAM,GAChB,YAAY,EAAE,CAchB;AAkCD;;;;0EAI0E;AAC1E,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,eAAe,EAAE,GAAG,SAAS,EACtC,KAAK,EAAE,iBAAiB,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAAA;CAAE,GAAG,SAAS,CAYzD"}