@automatalabs/acp-agents 0.8.0 → 0.9.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.
package/README.md CHANGED
@@ -94,9 +94,46 @@ const runner = createAcpRunner({
94
94
  });
95
95
  ```
96
96
 
97
+ ## Interactive sessions
98
+
99
+ Use `runner.openSession(options)` when a host needs to hold one ACP session open across multiple prompt turns. It uses the same backend selection and session/new inputs as `run()` (`model` / `tier`, absolute `cwd`, tool policy, `mcpServers`, `meta`, `runId`, Codex instruction overrides), but it spawns a **dedicated** agent process for that session instead of borrowing from the pool. A long-lived interactive session therefore never starves `run()` calls on the same backend, even with the default pool size of one.
100
+
101
+ Prompt turns are explicit and serialized: call `prompt(content, { images?, promptMeta? })`, await the returned `{ stopReason, text }`, then send the next turn. A second `prompt()` while one is in flight rejects with a host-side error; queue turns in your host if you want queued UX. `text` is only the assistant text from that turn. Per-turn `images` use the same ACP image block path as `run()` and still degrade through capability negotiation when the agent does not advertise image prompts.
102
+
103
+ `cancel()` sends ACP `session/cancel` for the active turn. `release()` is idempotent: it best-effort closes the ACP session and then disposes the dedicated process. Passing `signal` to `openSession()` releases the session on abort, and `runner.dispose()` releases any still-open interactive sessions before closing the pooled processes. Dedicated process death is observed per session: the wrapper auto-releases, session-scoped listeners see `session_close`, and an in-flight prompt rejects through the normal connection-closed path. `backend_error` is connection-scoped observability on the runner bus only; it is not delivered through `session.on()`.
104
+
105
+ ```ts
106
+ const runner = createAcpRunner();
107
+
108
+ try {
109
+ const session = await runner.openSession({
110
+ model: "anthropic/claude-sonnet-4",
111
+ cwd: "/abs/path/to/worktree",
112
+ onPermissionRequest: async (request) => choosePermission(request),
113
+ });
114
+
115
+ const off = session.on("agent_message_chunk", (e) => {
116
+ if (e.content.type === "text") process.stdout.write(e.content.text);
117
+ });
118
+
119
+ try {
120
+ const first = await session.prompt("Inspect the failing test.");
121
+ const second = await session.prompt("Patch the smallest fix.", {
122
+ images: [{ data: base64Png, mimeType: "image/png" }],
123
+ });
124
+ console.log(first.stopReason, second.text);
125
+ } finally {
126
+ off();
127
+ await session.release();
128
+ }
129
+ } finally {
130
+ await runner.dispose();
131
+ }
132
+ ```
133
+
97
134
  ## Listening in: live ACP events
98
135
 
99
- `AcpAgentRunner` is also a typed event bus — `runner.on(name, listener)` bubbles up the live ACP stream of every run (streaming text, tool calls, usage, permissions). Event names are the ACP `sessionUpdate` discriminants (`agent_message_chunk`, `tool_call`, `usage_update`, …) plus the cross-cutting `session_update` (catch-all), `permission_request`, `raw_message`, `session_open` / `session_close`, and `backend_error`. Each payload carries a `{ sessionId, backendId, label?, runId? }` context envelope (a pooled runner multiplexes many runs at once). `on()` / `once()` return an unsubscribe thunk; `off()` and `removeAllListeners()` round it out. Listeners are best-effort observers — a throwing listener never affects the run.
136
+ `AcpAgentRunner` is also a typed event bus — `runner.on(name, listener)` bubbles up the live ACP stream of every run (streaming text, tool calls, usage, permissions). Event names are the ACP `sessionUpdate` discriminants (`agent_message_chunk`, `tool_call`, `usage_update`, …) plus the cross-cutting `session_update` (catch-all), `permission_pending`, `permission_request`, `raw_message`, `session_open` / `session_close`, and `backend_error`. Each payload carries a `{ sessionId, backendId, label?, runId? }` context envelope (a pooled runner multiplexes many runs at once). `permission_pending` is resolver-only and carries `{ request }` before the host resolver is invoked; `permission_request` fires exactly once with the final `{ request, outcome }` returned to the agent. `on()` / `once()` return an unsubscribe thunk; `off()` and `removeAllListeners()` round it out. Listeners are best-effort observers — a throwing listener never affects the run.
100
137
 
101
138
  ```ts
102
139
  const off = runner.on("agent_message_chunk", (e) => {
@@ -114,15 +151,17 @@ The full event map (`AcpRunnerEventMap`) and helpers (`TypedEventEmitter`) are e
114
151
  From [`src/index.ts`](./src/index.ts):
115
152
 
116
153
  - **`createAcpRunner(options?)`** — factory returning an `AcpAgentRunner` (this is what `@automatalabs/workflows` injects into the engine).
117
- - **`AcpAgentRunner`** — the `AgentRunner` implementation; `run(prompt, options)` and `dispose()`.
154
+ - **`AcpAgentRunner`** — the `AgentRunner` implementation; `run(prompt, options)`, `openSession(options)`, and `dispose()`.
155
+ - **`InteractiveSession` / `InteractiveSessionOptions` / `InteractiveTurn`** — the held-open multi-turn session surface returned by `openSession()`.
118
156
  - **`selectBackend({ model, tier }, registry?)`** — the cross-provider routing rule: which backend a spec maps to (registered custom names match first, exact or `name/<inner-model>`).
119
157
  - **`ClaudeBackend` / `CodexBackend`** — the two built-in backend strategies (spawn config + per-backend schema wiring).
120
158
  - **`CustomAcpBackend` / `resolveBackendRegistry` / `BACKENDS_ENV`** — the custom-backend registry: run **any** ACP agent as a named backend via `createAcpRunner({ backends: { name: { command, args?, env?, sessionMeta?, customCapabilities? } } })` or the `AGENTPRISM_BACKENDS` env var (JSON, same shape; the option wins per name; `claude`/`codex` reserved). Custom backends carry a `schema` as turn-level `_meta.outputSchema` and read the result off the final message as JSON. `customCapabilities: { namespace, gatedKeys }` declares the agent's `agentCapabilities._meta` negotiation contract: once the agent advertises that namespace, each declared bare `_meta` key is sent only when its same-named flag is `true` (no declaration = never gated).
159
+ - **`PermissionResolver`** — async human-in-the-loop permission resolution for runner-wide or interactive sessions.
121
160
  - **`clientCapabilitiesFor` + the `ClientHandlers` / `FsHandlers` / `TerminalHandlers` / `AcpSessionContext` types** — the client-side fs/terminal interposition surface (see above).
122
161
  - **`negotiateCapabilities` / `adaptPromptContent` / `gateCustomMeta` / `unsupportedMcpServer` + `NegotiatedCapabilities`** — the `initialize` capability-negotiation primitives; the negotiated record for a live connection is exposed on `PooledConnection.capabilities`.
123
162
  - **`toJsonSchema(schema)` / `toStrictJsonSchema(schema)`** — turn a typebox schema into the on-the-wire shapes: a plain JSON Schema for Claude `outputFormat`, and an OpenAI-strict-normalized schema for Codex `outputSchema`.
124
163
 
125
- Also exported: `AcpAgentPool` / `resolvePoolSize`, `PooledConnection` / `SessionHandle`, `decidePermission`, `UsageAccumulator`, `resolveStructuredOutput` / `extractValidated` / `findJsonBlock` / `validateValue`, `errorText` / `mapThrownError`, and the event surface `TypedEventEmitter` / `AcpRunnerEventMap` / `AcpEventName` / `AcpEventListener` / `AcpEventContext` / `AcpSessionUpdate` (+ the per-event payload types), plus their associated types.
164
+ Also exported: `AcpAgentPool` / `resolvePoolSize`, `PooledConnection` / `SessionHandle`, `decidePermission`, `UsageAccumulator`, `resolveStructuredOutput` / `extractValidated` / `findJsonBlock` / `validateValue`, `errorText` / `mapThrownError`, and the event surface `TypedEventEmitter` / `AcpRunnerEventMap` / `AcpEventName` / `AcpEventListener` / `AcpEventContext` / `AcpSessionUpdate` (+ the per-event payload types, including `AcpPermissionPendingEvent`), plus their associated types.
126
165
 
127
166
  ## Environment overrides
128
167
 
@@ -1,10 +1,10 @@
1
- import { ClientSideConnection, type ContentBlock, type PromptResponse, type SessionConfigOption, type SessionNotification } from "@agentclientprotocol/sdk";
1
+ import { ClientSideConnection, type ContentBlock, type PromptResponse, type RequestPermissionResponse, type SessionConfigOption, type SessionNotification } 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 ToolPolicy } from "./permissions.js";
7
+ import { 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 {
@@ -13,25 +13,34 @@ interface RawResultSuccess {
13
13
  structured_output?: unknown;
14
14
  }
15
15
  /** Per-session accumulator: assistant text, tool history, usage, the Claude raw structured_output,
16
- * and the tool policy used to auto-answer permission requests for THIS session. */
16
+ * and the permission policy/resolver used to answer permission requests for THIS session. */
17
17
  declare class SessionState {
18
18
  readonly cwd: string;
19
19
  readonly policy: ToolPolicy;
20
+ readonly permissionResolver?: PermissionResolver | undefined;
20
21
  readonly label?: string | undefined;
21
22
  readonly runId?: string | undefined;
23
+ private readonly retainSessionLog;
22
24
  readonly textChunks: string[];
23
25
  readonly history: AgentHistoryEntry[];
24
26
  readonly usage: UsageAccumulator;
27
+ readonly pendingPermissions: Set<(outcome: RequestPermissionResponse) => void>;
25
28
  rawResultSuccess: RawResultSuccess | undefined;
26
29
  private turnStartIndex;
27
30
  /** `label`/`runId` are carried here ONLY so the MultiplexClient can stamp them onto emitted
28
31
  * events as context — they never affect routing or the wire request. */
29
- constructor(cwd: string, policy: ToolPolicy, label?: string | undefined, runId?: string | undefined);
30
- /** Mark the start of a new turn so currentTurnText()/structured_output read only this turn. */
32
+ constructor(cwd: string, policy: ToolPolicy, permissionResolver?: PermissionResolver | undefined, label?: string | undefined, runId?: string | undefined, retainSessionLog?: boolean);
33
+ /** Mark the start of a new turn so currentTurnText()/structured_output read only this turn.
34
+ * Long-lived interactive sessions can opt out of retaining old text/history because hosts
35
+ * stream live events and keep their own transcript; clearing here prevents dead logs from
36
+ * growing for the lifetime of a held-open session. */
31
37
  beginTurn(): void;
32
38
  currentTurnText(): string;
33
39
  applyUpdate(update: SessionNotification["update"]): void;
34
40
  applyRawMessage(message: RawResultSuccess | undefined): void;
41
+ /** Settle every deferred permission still parked on this session. Used by release/cancel/death
42
+ * teardown so an interactive resolver can never strand an ACP prompt turn. */
43
+ settlePendingPermissions(): void;
35
44
  }
36
45
  export interface AcpSessionOptions {
37
46
  /** Absolute working directory for the ACP session (worktree isolation). */
@@ -39,6 +48,9 @@ export interface AcpSessionOptions {
39
48
  /** The schema for this run, if any (drives the backend's session/prompt `_meta`). */
40
49
  schema: TSchema | undefined;
41
50
  policy: ToolPolicy;
51
+ /** Session-scoped permission resolver. When present it wins over the runner default and
52
+ * replaces the synchronous ToolPolicy auto-response path for this session. */
53
+ permissionResolver?: PermissionResolver;
42
54
  signal?: AbortSignal;
43
55
  /** Client-provided MCP servers to attach at session/new. Omitted => `[]` (the default). */
44
56
  mcpServers?: McpServerConfig[];
@@ -55,6 +67,11 @@ export interface AcpSessionOptions {
55
67
  * (bare keys) for the codex-acp adapter; the Claude backend ignores them. Omitted => unset. */
56
68
  baseInstructions?: string;
57
69
  developerInstructions?: string;
70
+ /** Retain accumulated assistant text/tool history for the lifetime of this ACP session.
71
+ * Default true preserves run()'s diagnostic history contract. Held-open interactive sessions
72
+ * pass false because hosts stream live events / keep their own transcript; retaining old turns
73
+ * there is dead memory for day-long sessions. */
74
+ retainSessionLog?: boolean;
58
75
  }
59
76
  /** Notified by a PooledConnection when its process dies, so the pool can drop it. */
60
77
  export interface PooledConnectionDeps {
@@ -63,6 +80,8 @@ export interface PooledConnectionDeps {
63
80
  * session lifecycle change on this connection is bubbled up through it (additive observability;
64
81
  * it is invoked AFTER the drain accumulation and never affects the run). */
65
82
  onEvent?: AcpEventSink;
83
+ /** Runner-wide permission resolver default. SessionState.permissionResolver overrides it. */
84
+ permissionResolver?: PermissionResolver;
66
85
  /** Client-side ACP fs/terminal handlers advertised once and routed by sessionId. */
67
86
  clientHandlers?: ClientHandlers;
68
87
  }
@@ -139,7 +158,7 @@ export declare class PooledConnection {
139
158
  */
140
159
  export declare class SessionHandle implements StructuredSource {
141
160
  private readonly pooled;
142
- private readonly sessionId;
161
+ readonly sessionId: string;
143
162
  private readonly state;
144
163
  private readonly opts;
145
164
  private configOptions;
@@ -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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"}
@@ -43,28 +43,43 @@ const CLOSE_SESSION_TIMEOUT_MS = 5_000;
43
43
  const DISPOSE_SIGKILL_GRACE_MS = 2_000;
44
44
  const TOMBSTONE_SESSION_CAP = 64;
45
45
  /** Per-session accumulator: assistant text, tool history, usage, the Claude raw structured_output,
46
- * and the tool policy used to auto-answer permission requests for THIS session. */
46
+ * and the permission policy/resolver used to answer permission requests for THIS session. */
47
47
  class SessionState {
48
48
  cwd;
49
49
  policy;
50
+ permissionResolver;
50
51
  label;
51
52
  runId;
53
+ retainSessionLog;
52
54
  textChunks = [];
53
55
  history = [];
54
56
  usage = new UsageAccumulator();
57
+ pendingPermissions = new Set();
55
58
  rawResultSuccess;
56
59
  turnStartIndex = 0;
57
60
  /** `label`/`runId` are carried here ONLY so the MultiplexClient can stamp them onto emitted
58
61
  * events as context — they never affect routing or the wire request. */
59
- constructor(cwd, policy, label, runId) {
62
+ constructor(cwd, policy, permissionResolver, label, runId, retainSessionLog = true) {
60
63
  this.cwd = cwd;
61
64
  this.policy = policy;
65
+ this.permissionResolver = permissionResolver;
62
66
  this.label = label;
63
67
  this.runId = runId;
68
+ this.retainSessionLog = retainSessionLog;
64
69
  }
65
- /** Mark the start of a new turn so currentTurnText()/structured_output read only this turn. */
70
+ /** Mark the start of a new turn so currentTurnText()/structured_output read only this turn.
71
+ * Long-lived interactive sessions can opt out of retaining old text/history because hosts
72
+ * stream live events and keep their own transcript; clearing here prevents dead logs from
73
+ * growing for the lifetime of a held-open session. */
66
74
  beginTurn() {
67
- this.turnStartIndex = this.textChunks.length;
75
+ if (this.retainSessionLog) {
76
+ this.turnStartIndex = this.textChunks.length;
77
+ }
78
+ else {
79
+ this.textChunks.length = 0;
80
+ this.history.length = 0;
81
+ this.turnStartIndex = 0;
82
+ }
68
83
  this.rawResultSuccess = undefined;
69
84
  }
70
85
  currentTurnText() {
@@ -110,6 +125,12 @@ class SessionState {
110
125
  this.rawResultSuccess = message;
111
126
  }
112
127
  }
128
+ /** Settle every deferred permission still parked on this session. Used by release/cancel/death
129
+ * teardown so an interactive resolver can never strand an ACP prompt turn. */
130
+ settlePendingPermissions() {
131
+ for (const settle of [...this.pendingPermissions])
132
+ settle(cancelledPermissionResponse());
133
+ }
113
134
  }
114
135
  /** The single ACP Client handler for one pooled connection. It ROUTES every notification and
115
136
  * permission request to the per-session SessionState by `sessionId`, so one process can serve
@@ -118,6 +139,7 @@ class MultiplexClient {
118
139
  backendId;
119
140
  onEvent;
120
141
  handlers;
142
+ permissionResolver;
121
143
  sessions = new Map();
122
144
  /** Recently unregistered sessions kept ONLY for the teardown window: ACP agents may
123
145
  * legitimately release terminals (or finish fs/terminal cleanup) after this client releases
@@ -125,11 +147,13 @@ class MultiplexClient {
125
147
  * release. Store only the slim routing context and cap it FIFO so the memory cost is bounded. */
126
148
  tombstones = new Map();
127
149
  /** `backendId` stamps event context; `onEvent` (optional) bubbles every notification, permission
128
- * request and session lifecycle change up to the runner's typed bus. */
129
- constructor(backendId, onEvent, handlers) {
150
+ * request and session lifecycle change up to the runner's typed bus. `permissionResolver` is
151
+ * the runner-wide default; a SessionState resolver wins when present. */
152
+ constructor(backendId, onEvent, handlers, permissionResolver) {
130
153
  this.backendId = backendId;
131
154
  this.onEvent = onEvent;
132
155
  this.handlers = handlers;
156
+ this.permissionResolver = permissionResolver;
133
157
  }
134
158
  contextFor(sessionId, state) {
135
159
  return { sessionId, backendId: this.backendId, label: state?.label, runId: state?.runId };
@@ -156,6 +180,7 @@ class MultiplexClient {
156
180
  }
157
181
  unregister(sessionId) {
158
182
  const state = this.sessions.get(sessionId);
183
+ state?.settlePendingPermissions();
159
184
  this.sessions.delete(sessionId);
160
185
  if (state) {
161
186
  this.tombstones.set(sessionId, {
@@ -172,19 +197,61 @@ class MultiplexClient {
172
197
  this.onEvent?.("session_close", this.contextFor(sessionId, state));
173
198
  }
174
199
  }
200
+ settlePendingPermissions(sessionId) {
201
+ this.sessions.get(sessionId)?.settlePendingPermissions();
202
+ }
203
+ settleAllPendingPermissions() {
204
+ for (const state of this.sessions.values()) {
205
+ state.settlePendingPermissions();
206
+ }
207
+ }
175
208
  requestPermission(params) {
176
209
  const state = this.sessions.get(params.sessionId);
177
210
  // Unknown/closed session: refuse rather than silently allow a tool we can't attribute.
178
211
  if (!state)
179
- return { outcome: { outcome: "cancelled" } };
212
+ return cancelledPermissionResponse();
213
+ const ctx = this.contextFor(params.sessionId, state);
214
+ const resolver = state.permissionResolver ?? this.permissionResolver;
215
+ if (resolver)
216
+ return this.requestPermissionViaResolver(params, state, ctx, resolver);
180
217
  const outcome = decidePermission(params, state.policy);
181
218
  this.onEvent?.("permission_request", {
182
- ...this.contextFor(params.sessionId, state),
219
+ ...ctx,
183
220
  request: params,
184
221
  outcome,
185
222
  });
186
223
  return outcome;
187
224
  }
225
+ requestPermissionViaResolver(params, state, ctx, resolver) {
226
+ let settled = false;
227
+ let settle;
228
+ const response = new Promise((resolve) => {
229
+ settle = (outcome) => {
230
+ if (settled)
231
+ return;
232
+ settled = true;
233
+ state.pendingPermissions.delete(settle);
234
+ this.onEvent?.("permission_request", { ...ctx, request: params, outcome });
235
+ resolve(outcome);
236
+ };
237
+ state.pendingPermissions.add(settle);
238
+ this.onEvent?.("permission_pending", { ...ctx, request: params });
239
+ try {
240
+ Promise.resolve(resolver(params, ctx)).then((outcome) => {
241
+ settle(outcome);
242
+ }, () => {
243
+ // No session-scoped resolver-error event exists; the permission_request event still
244
+ // reports the FINAL outcome exactly once, so rejection is observable as cancellation.
245
+ settle(cancelledPermissionResponse());
246
+ });
247
+ }
248
+ catch {
249
+ settle(cancelledPermissionResponse());
250
+ }
251
+ });
252
+ response.catch(() => { });
253
+ return response;
254
+ }
188
255
  readTextFile(params) {
189
256
  return this.dispatch(params, CLIENT_METHODS.fs_read_text_file, this.handlers?.fs?.readTextFile);
190
257
  }
@@ -235,6 +302,9 @@ class MultiplexClient {
235
302
  function unknownSession(sessionId) {
236
303
  return RequestError.invalidParams({ sessionId }, `unknown session: ${sessionId}`);
237
304
  }
305
+ function cancelledPermissionResponse() {
306
+ return { outcome: { outcome: "cancelled" } };
307
+ }
238
308
  function methodNotAdvertised(method) {
239
309
  return new RequestError(-32601, `${method} was not advertised by this client`, { method });
240
310
  }
@@ -311,7 +381,7 @@ export class PooledConnection {
311
381
  this.onDead = deps.onDead;
312
382
  this.onEvent = deps.onEvent;
313
383
  this.clientHandlers = deps.clientHandlers;
314
- this.client = new MultiplexClient(this.backendId, this.onEvent, deps.clientHandlers);
384
+ this.client = new MultiplexClient(this.backendId, this.onEvent, deps.clientHandlers, deps.permissionResolver);
315
385
  const { command, args, env } = backend.spawnConfig();
316
386
  // NOTE: deliberately NO `cwd` here. cwd is per-SESSION (session/new), so one pooled process
317
387
  // serves runs in different worktrees without losing isolation.
@@ -376,6 +446,7 @@ export class PooledConnection {
376
446
  this._alive = false;
377
447
  this.deathError = error;
378
448
  this.resolveDead();
449
+ this.client.settleAllPendingPermissions();
379
450
  // A crash (not a graceful dispose) is worth surfacing for observability; the engine still
380
451
  // handles it by retrying the run on a fresh process. Best-effort, after death is recorded.
381
452
  if (this.onEvent && !this.disposing) {
@@ -462,7 +533,7 @@ export class PooledConnection {
462
533
  throw new WorkflowError(`MCP server "${unsupported.name}" uses the "${unsupported.transport}" transport, which the ` +
463
534
  `${this.backendId} agent does not support`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: opts.label });
464
535
  }
465
- const state = new SessionState(opts.cwd, opts.policy, opts.label, opts.runId);
536
+ const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.label, opts.runId, opts.retainSessionLog ?? true);
466
537
  // session/new `_meta`, layered lowest-to-highest precedence: the backend's static
467
538
  // defaults (a custom registry entry's `sessionMeta`), then the generic user passthrough
468
539
  // (opts.meta), then the backend's protocol-critical `_meta` (Claude schema channel;
@@ -490,6 +561,7 @@ export class PooledConnection {
490
561
  }
491
562
  /** Best-effort ACP cancel for one session (wired to opts.signal). The PROCESS stays pooled. */
492
563
  async cancelSession(sessionId) {
564
+ this.client.settlePendingPermissions(sessionId);
493
565
  if (!this._alive)
494
566
  return;
495
567
  try {
package/dist/events.d.ts CHANGED
@@ -22,7 +22,16 @@ type AcpSessionUpdateEvents = {
22
22
  sessionUpdate: K;
23
23
  }> & AcpEventContext;
24
24
  };
25
- /** A tool-permission request the runner auto-answered, paired with the decision it returned. */
25
+ /** A tool-permission request parked on an async resolver. This is the FIRST phase of the
26
+ * resolver path only: it fires after the request is tracked for teardown cancellation and before
27
+ * the host resolver is invoked. It carries no outcome because no ACP response has been returned
28
+ * yet. Synchronous ToolPolicy decisions never emit this event. */
29
+ export interface AcpPermissionPendingEvent extends AcpEventContext {
30
+ request: RequestPermissionRequest;
31
+ }
32
+ /** A tool-permission request the runner answered, paired with the FINAL decision it returned.
33
+ * This is the SECOND phase for resolver-backed permissions and the ONLY phase for synchronous
34
+ * ToolPolicy permissions. It fires exactly once per request with the outcome sent to the agent. */
26
35
  export interface AcpPermissionEvent extends AcpEventContext {
27
36
  request: RequestPermissionRequest;
28
37
  outcome: RequestPermissionResponse;
@@ -48,7 +57,9 @@ export type AcpRunnerEventMap = AcpSessionUpdateEvents & {
48
57
  session_update: {
49
58
  update: AcpSessionUpdate;
50
59
  } & AcpEventContext;
51
- /** A permission request the runner auto-answered, with the decision returned. */
60
+ /** A permission request parked on an async resolver; resolver path only, no outcome yet. */
61
+ permission_pending: AcpPermissionPendingEvent;
62
+ /** A permission request the runner answered, with the FINAL decision returned. */
52
63
  permission_request: AcpPermissionEvent;
53
64
  /** A vendor extension notification arrived for a session. */
54
65
  raw_message: AcpRawMessageEvent;
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,+FAA+F;AAC/F,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AAC7D,qGAAqG;AACrG,MAAM,MAAM,aAAa,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAC;AAE9D;oGACoG;AACpG,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,SAAS,EAAE,SAAS,CAAC;IACrB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,mGAAmG;AACnG,KAAK,sBAAsB,GAAG;KAC3B,CAAC,IAAI,aAAa,GAAG,OAAO,CAAC,gBAAgB,EAAE;QAAE,aAAa,EAAE,CAAC,CAAA;KAAE,CAAC,GAAG,eAAe;CACxF,CAAC;AAEF;;;mEAGmE;AACnE,MAAM,WAAW,yBAA0B,SAAQ,eAAe;IAChE,OAAO,EAAE,wBAAwB,CAAC;CACnC;AAED;;oGAEoG;AACpG,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,OAAO,EAAE,wBAAwB,CAAC;IAClC,OAAO,EAAE,yBAAyB,CAAC;CACpC;AAED,8FAA8F;AAC9F,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;4FAC4F;AAC5F,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,sBAAsB,GAAG;IACvD,6FAA6F;IAC7F,cAAc,EAAE;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,GAAG,eAAe,CAAC;IAC/D,4FAA4F;IAC5F,kBAAkB,EAAE,yBAAyB,CAAC;IAC9C,kFAAkF;IAClF,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,6DAA6D;IAC7D,WAAW,EAAE,kBAAkB,CAAC;IAChC,uDAAuD;IACvD,YAAY,EAAE,eAAe,CAAC;IAC9B,uCAAuC;IACvC,aAAa,EAAE,eAAe,CAAC;IAC/B,iEAAiE;IACjE,aAAa,EAAE,oBAAoB,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAAC;AACnD,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,YAAY,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAE7F,8FAA8F;AAC9F,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,SAAS,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CACtE;AAED;;;;;GAKG;AACH,qBAAa,iBAAiB,CAAC,QAAQ;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4D;IAEtF,6FAA6F;IAC7F,EAAE,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAUzF,+EAA+E;IAC/E,IAAI,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAQ3F,GAAG,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI;IAOpF,kBAAkB,CAAC,IAAI,CAAC,EAAE,MAAM,QAAQ,GAAG,IAAI;IAK/C,aAAa,CAAC,IAAI,EAAE,MAAM,QAAQ,GAAG,MAAM;IAI3C,IAAI,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;CAYlE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAI1G"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { AcpAgentRunner, createAcpRunner, selectBackend } from "./runner.js";
2
2
  export type { AcpRunnerOptions } from "./runner.js";
3
+ export { InteractiveSession } from "./interactive.js";
4
+ export type { InteractiveSessionOptions, InteractiveTurn } from "./interactive.js";
3
5
  export { BACKENDS_ENV, registryWithRunBackends, resolveBackendRegistry } from "./registry.js";
4
6
  export type { BackendRegistry, CustomBackendConfig, RegisteredBackend } from "./registry.js";
5
7
  export { PooledConnection, SessionHandle } from "./acp-client.js";
@@ -11,13 +13,13 @@ export type { AcpPoolOptions, AcpPoolDeps } from "./pool.js";
11
13
  export { clientCapabilitiesFor } from "./client-handlers.js";
12
14
  export type { AcpSessionContext, ClientHandlers, FsHandlers, TerminalHandlers } from "./client-handlers.js";
13
15
  export { TypedEventEmitter, emitSessionUpdate } from "./events.js";
14
- export type { AcpRunnerEventMap, AcpEventName, AcpEventListener, AcpEventContext, AcpEventSink, AcpSessionUpdate, AcpUpdateKind, AcpPermissionEvent, AcpRawMessageEvent, AcpBackendErrorEvent, } from "./events.js";
16
+ export type { AcpRunnerEventMap, AcpEventName, AcpEventListener, AcpEventContext, AcpEventSink, AcpSessionUpdate, AcpUpdateKind, AcpPermissionPendingEvent, AcpPermissionEvent, AcpRawMessageEvent, AcpBackendErrorEvent, } from "./events.js";
15
17
  export type { Backend, BackendId, BuiltinBackendId, SessionMetaInputs, SpawnConfig, StructuredSource, } from "./backend.js";
16
18
  export { ClaudeBackend } from "./backends/claude.js";
17
19
  export { CodexBackend } from "./backends/codex.js";
18
20
  export { CustomAcpBackend } from "./backends/custom.js";
19
21
  export { decidePermission } from "./permissions.js";
20
- export type { ToolPolicy } from "./permissions.js";
22
+ export type { PermissionResolver, ToolPolicy } from "./permissions.js";
21
23
  export { UsageAccumulator } from "./usage.js";
22
24
  export { toJsonSchema, toStrictJsonSchema } from "./schema-strict.js";
23
25
  export { extractValidated, findJsonBlock, parseFinalJson, resolveStructuredOutput, validateValue, } from "./structured-output.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7E,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC9F,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE7F,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAClE,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAI/E,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,cAAc,EACd,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG5G,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEtE,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,uBAAuB,EACvB,aAAa,GACd,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7E,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,YAAY,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC9F,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE7F,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAClE,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAI/E,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,cAAc,EACd,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG5G,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEtE,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,uBAAuB,EACvB,aAAa,GACd,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@
5
5
  // @automatalabs/workflow-engine; the two siblings meet ONLY at AgentRunner, injected by the
6
6
  // @automatalabs/workflows facade (which mcp-server builds on) via createAcpRunner().
7
7
  export { AcpAgentRunner, createAcpRunner, selectBackend } from "./runner.js";
8
+ export { InteractiveSession } from "./interactive.js";
8
9
  // The custom-backend registry: run ANY ACP agent as an agent() target.
9
10
  export { BACKENDS_ENV, registryWithRunBackends, resolveBackendRegistry } from "./registry.js";
10
11
  export { PooledConnection, SessionHandle } from "./acp-client.js";
@@ -0,0 +1,114 @@
1
+ import type { ContentBlock, StopReason } from "@agentclientprotocol/sdk";
2
+ import type { McpServerConfig, PromptImage } from "@automatalabs/shared-types";
3
+ import type { RunOptions } from "@automatalabs/shared-types";
4
+ import type { Backend, BackendId } from "./backend.js";
5
+ import type { NegotiatedCapabilities } from "./capabilities.js";
6
+ import type { PooledConnection, SessionHandle } from "./acp-client.js";
7
+ import type { AcpEventListener, AcpEventName } from "./events.js";
8
+ import type { PermissionResolver } from "./permissions.js";
9
+ /** Options for AcpAgentRunner.openSession(): backend selection and session/new inputs for one
10
+ * held-open interactive ACP session. `cwd` is required and absolute; unlike run(), there is no
11
+ * default to process.cwd() because the session can span many turns. The session-scoped
12
+ * permission resolver wins over the runner-wide default; tool allow/deny policy is used only
13
+ * when no resolver is present. */
14
+ export interface InteractiveSessionOptions {
15
+ /** Model spec (`provider/modelId`, bare model id, or registered custom backend route). */
16
+ model?: string;
17
+ /** Coarse tier consulted only when `model` is unset. */
18
+ tier?: string;
19
+ /** Absolute working directory for ACP session/new. Required for held-open sessions. */
20
+ cwd: string;
21
+ /** Tool allow-list used by the headless permission auto-responder. */
22
+ toolNames?: string[];
23
+ /** Tool deny-list, applied after the allow-list. */
24
+ disallowedToolNames?: string[];
25
+ /** Session-scoped permission resolver; overrides the runner-wide resolver for this session. */
26
+ onPermissionRequest?: PermissionResolver;
27
+ /** The actually-resolved concrete model id (display/telemetry). */
28
+ onModelResolved?: RunOptions["onModelResolved"];
29
+ /** A requested model/tier spec that was not found and fell back to the session default. */
30
+ onModelFallback?: RunOptions["onModelFallback"];
31
+ /** Event/telemetry label stamped onto this session's emitted ACP events. */
32
+ label?: string;
33
+ /** Correlation id stamped into session/new `_meta` and emitted event context. */
34
+ runId?: string;
35
+ /** Generic session-scoped `_meta` passthrough merged under backend-computed session meta. */
36
+ meta?: Record<string, unknown>;
37
+ /** CODEX-ONLY base instruction override, forwarded at session/new. */
38
+ baseInstructions?: string;
39
+ /** CODEX-ONLY developer instruction override, forwarded at session/new. */
40
+ developerInstructions?: string;
41
+ /** Client-provided MCP servers to attach at session/new. */
42
+ mcpServers?: McpServerConfig[];
43
+ /** Host-owned cancellation. Aborting releases this interactive session. */
44
+ signal?: AbortSignal;
45
+ }
46
+ /** One completed interactive prompt turn. `text` is the assistant text from THIS turn only:
47
+ * it is read from SessionHandle.currentTurnText(), the same turn-segmented accessor run() uses
48
+ * for structured-output repair turns. */
49
+ export interface InteractiveTurn {
50
+ readonly stopReason: StopReason;
51
+ readonly text: string;
52
+ }
53
+ type Subscribe = <K extends AcpEventName>(name: K, listener: AcpEventListener<K>) => () => void;
54
+ /** Internal construction bag for the runner-owned wrapper around an already-open ACP session. */
55
+ interface InteractiveSessionDeps {
56
+ readonly session: SessionHandle;
57
+ readonly connection: PooledConnection;
58
+ readonly backend: Backend;
59
+ readonly subscribe: Subscribe;
60
+ readonly onRelease: (self: InteractiveSession) => void;
61
+ readonly signal?: AbortSignal;
62
+ readonly label?: string;
63
+ }
64
+ /** A held-open multi-turn ACP session backed by a dedicated agent process. Only one prompt may
65
+ * be in flight at a time; hosts that want queued turns should serialize calls themselves so
66
+ * cancellation, permissions, and turn text stay attributable to a single active turn. If the
67
+ * dedicated process dies, the runner observes that per session by auto-releasing this wrapper:
68
+ * session-scoped listeners are removed, later prompt() calls fail with the released-session
69
+ * error, and `session_close` is emitted on this session's event stream. The connection-scoped
70
+ * `backend_error` event is emitted on the runner bus only; it is not delivered through
71
+ * session.on(). */
72
+ export declare class InteractiveSession {
73
+ readonly sessionId: string;
74
+ readonly backendId: BackendId;
75
+ private readonly session;
76
+ private readonly connection;
77
+ private readonly backend;
78
+ private readonly subscribe;
79
+ private readonly onReleaseCallback;
80
+ private readonly signal;
81
+ private readonly label;
82
+ private readonly subscriptions;
83
+ private removeAbort;
84
+ private promptInFlight;
85
+ private releasePromise;
86
+ /** Construct the public wrapper around an already-open ACP session. Hosts normally receive
87
+ * instances from AcpAgentRunner.openSession(), which supplies the internal session/connection
88
+ * dependencies and owns lifecycle tracking. */
89
+ constructor(deps: InteractiveSessionDeps);
90
+ /** Negotiated initialize capabilities for this session's dedicated connection. */
91
+ get capabilities(): NegotiatedCapabilities | undefined;
92
+ /** Send one prompt turn. A concurrent prompt on the same InteractiveSession is rejected with a
93
+ * clear host-side error; queueing is deliberately left to the host so turn boundaries remain
94
+ * explicit. Per-turn images are appended only to this prompt, and SessionHandle.prompt()
95
+ * performs capability adaptation before sending. */
96
+ prompt(content: string | ContentBlock[], opts?: {
97
+ images?: readonly PromptImage[];
98
+ promptMeta?: Record<string, unknown>;
99
+ }): Promise<InteractiveTurn>;
100
+ /** Best-effort ACP session/cancel for the active turn. Pending permission resolvers are
101
+ * settled as cancelled by the SessionHandle/PooledConnection cancel path. */
102
+ cancel(): Promise<void>;
103
+ /** Subscribe to runner events for THIS ACP session only. Events from other one-shot or
104
+ * interactive sessions on the same runner are filtered out by sessionId. The returned
105
+ * unsubscribe thunk and every still-live subscription are removed automatically on release. */
106
+ on<K extends AcpEventName>(name: K, listener: AcpEventListener<K>): () => void;
107
+ /** Release the ACP session and close the dedicated process. Idempotent. Session close is
108
+ * best-effort and bounded by SessionHandle; process disposal mirrors pool teardown. */
109
+ release(): Promise<void>;
110
+ private doRelease;
111
+ private removeSubscriptions;
112
+ }
113
+ export {};
114
+ //# sourceMappingURL=interactive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAO3D;;;;mCAImC;AACnC,MAAM,WAAW,yBAAyB;IACxC,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uFAAuF;IACvF,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,oDAAoD;IACpD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,+FAA+F;IAC/F,mBAAmB,CAAC,EAAE,kBAAkB,CAAC;IACzC,mEAAmE;IACnE,eAAe,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAChD,2FAA2F;IAC3F,eAAe,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAChD,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,2EAA2E;IAC3E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;0CAE0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,KAAK,SAAS,GAAG,CAAC,CAAC,SAAS,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC;AAEhG,iGAAiG;AACjG,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;oBAOoB;AACpB,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqC;IACvE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;IACvD,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,cAAc,CAA4B;IAElD;;oDAEgD;gBACpC,IAAI,EAAE,sBAAsB;IAsBxC,kFAAkF;IAClF,IAAI,YAAY,IAAI,sBAAsB,GAAG,SAAS,CAErD;IAED;;;yDAGqD;IAC/C,MAAM,CACV,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,EAChC,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAO,GACnF,OAAO,CAAC,eAAe,CAAC;IAsB3B;kFAC8E;IACxE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAK7B;;oGAEgG;IAChG,EAAE,CAAC,CAAC,SAAS,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAiB9E;4FACwF;IACxF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAKV,SAAS;IAkBvB,OAAO,CAAC,mBAAmB;CAK5B"}