acpx 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +8 -2
  2. package/dist/{cli-Ddxpnz9X.js → cli-BGYGVo3b.js} +35 -10
  3. package/dist/cli-BGYGVo3b.js.map +1 -0
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +204 -19
  7. package/dist/cli.js.map +1 -1
  8. package/dist/{client-2fTFutRH.d.ts → client-FzXPdgP7.d.ts} +10 -4
  9. package/dist/client-FzXPdgP7.d.ts.map +1 -0
  10. package/dist/{flags-yXzUm7Aq.js → flags-D706STfk.js} +46 -6
  11. package/dist/flags-D706STfk.js.map +1 -0
  12. package/dist/{flows-CDsfbaA2.js → flows-hcjHmU7P.js} +117 -11
  13. package/dist/flows-hcjHmU7P.js.map +1 -0
  14. package/dist/flows.d.ts +19 -3
  15. package/dist/flows.d.ts.map +1 -1
  16. package/dist/flows.js +2 -2
  17. package/dist/{prompt-turn-BY5SwU1F.js → live-checkpoint-B9ctAuqV.js} +1335 -82
  18. package/dist/live-checkpoint-B9ctAuqV.js.map +1 -0
  19. package/dist/output-BL9XRWzS.js +3712 -0
  20. package/dist/output-BL9XRWzS.js.map +1 -0
  21. package/dist/runtime.d.ts +32 -6
  22. package/dist/runtime.d.ts.map +1 -1
  23. package/dist/runtime.js +169 -32
  24. package/dist/runtime.js.map +1 -1
  25. package/dist/{types-CVBeQyi3.d.ts → session-options-BJyG6zEH.d.ts} +56 -3
  26. package/dist/session-options-BJyG6zEH.d.ts.map +1 -0
  27. package/package.json +27 -25
  28. package/skills/acpx/SKILL.md +200 -9
  29. package/dist/cli-Ddxpnz9X.js.map +0 -1
  30. package/dist/client-2fTFutRH.d.ts.map +0 -1
  31. package/dist/flags-yXzUm7Aq.js.map +0 -1
  32. package/dist/flows-CDsfbaA2.js.map +0 -1
  33. package/dist/ipc-BruTG5Fb.js +0 -1241
  34. package/dist/ipc-BruTG5Fb.js.map +0 -1
  35. package/dist/jsonrpc-DSxh2w5R.js +0 -68
  36. package/dist/jsonrpc-DSxh2w5R.js.map +0 -1
  37. package/dist/output-DmHvT8vm.js +0 -807
  38. package/dist/output-DmHvT8vm.js.map +0 -1
  39. package/dist/perf-metrics-C2pXfxvR.js +0 -598
  40. package/dist/perf-metrics-C2pXfxvR.js.map +0 -1
  41. package/dist/prompt-turn-BY5SwU1F.js.map +0 -1
  42. package/dist/render-yqwtaOX4.js +0 -172
  43. package/dist/render-yqwtaOX4.js.map +0 -1
  44. package/dist/rolldown-runtime-CiIaOW0V.js +0 -13
  45. package/dist/session-BwgaPK8-.js +0 -1526
  46. package/dist/session-BwgaPK8-.js.map +0 -1
  47. package/dist/session-options-pCbHn_n7.d.ts +0 -13
  48. package/dist/session-options-pCbHn_n7.d.ts.map +0 -1
  49. package/dist/types-CVBeQyi3.d.ts.map +0 -1
@@ -1,5 +1,3 @@
1
- import { B as PermissionDeniedError, C as isAcpResourceNotFoundError, F as AgentStartupError, G as SessionModeReplayError, I as AuthPolicyError, J as SessionResolutionError, K as SessionModelReplayError, L as ClaudeAcpSessionCreateTimeoutError, M as SESSION_RECORD_SCHEMA, N as AgentDisconnectedError, P as AgentSpawnError, R as CopilotAcpUnsupportedError, S as extractAcpError, V as PermissionPromptUnavailableError, W as SessionConfigOptionReplayError, Y as SessionResumeRequiredError, g as textPrompt, i as measurePerf, l as extractRuntimeSessionId, q as SessionNotFoundError, r as incrementPerfCounter, u as normalizeRuntimeSessionId, v as formatErrorMessage, y as isAcpQueryClosedBeforeResponseError, z as GeminiAcpStartupTimeoutError } from "./perf-metrics-C2pXfxvR.js";
2
- import { r as isSessionUpdateNotification } from "./jsonrpc-DSxh2w5R.js";
3
1
  import fs, { statSync } from "node:fs";
4
2
  import { fileURLToPath } from "node:url";
5
3
  import path from "node:path";
@@ -11,6 +9,397 @@ import { ClientSideConnection, PROTOCOL_VERSION } from "@agentclientprotocol/sdk
11
9
  import readline from "node:readline/promises";
12
10
  import { promisify } from "node:util";
13
11
  import { randomUUID } from "node:crypto";
12
+ //#region src/errors.ts
13
+ var AcpxOperationalError = class extends Error {
14
+ outputCode;
15
+ detailCode;
16
+ origin;
17
+ retryable;
18
+ acp;
19
+ outputAlreadyEmitted;
20
+ constructor(message, options) {
21
+ super(message, options);
22
+ this.name = new.target.name;
23
+ this.outputCode = options?.outputCode;
24
+ this.detailCode = options?.detailCode;
25
+ this.origin = options?.origin;
26
+ this.retryable = options?.retryable;
27
+ this.acp = options?.acp;
28
+ this.outputAlreadyEmitted = options?.outputAlreadyEmitted;
29
+ }
30
+ };
31
+ var SessionNotFoundError = class extends AcpxOperationalError {
32
+ sessionId;
33
+ constructor(sessionId) {
34
+ super(`Session not found: ${sessionId}`);
35
+ this.sessionId = sessionId;
36
+ }
37
+ };
38
+ var SessionResolutionError = class extends AcpxOperationalError {};
39
+ var AgentSpawnError = class extends AcpxOperationalError {
40
+ agentCommand;
41
+ constructor(agentCommand, cause) {
42
+ super(`Failed to spawn agent command: ${agentCommand}`, { cause: cause instanceof Error ? cause : void 0 });
43
+ this.agentCommand = agentCommand;
44
+ }
45
+ };
46
+ var AgentStartupError = class extends AcpxOperationalError {
47
+ agentCommand;
48
+ exitCode;
49
+ signal;
50
+ stderrSummary;
51
+ constructor(params) {
52
+ const exitSummary = `exit=${params.exitCode ?? "null"}, signal=${params.signal ?? "null"}`;
53
+ const stderrSuffix = typeof params.stderrSummary === "string" && params.stderrSummary.trim().length > 0 ? `: ${params.stderrSummary.trim()}` : "";
54
+ super(`ACP agent exited before initialize completed (${exitSummary})${stderrSuffix}`, {
55
+ cause: params.cause instanceof Error ? params.cause : void 0,
56
+ outputCode: "RUNTIME",
57
+ detailCode: "AGENT_STARTUP_FAILED",
58
+ origin: "acp"
59
+ });
60
+ this.agentCommand = params.agentCommand;
61
+ this.exitCode = params.exitCode;
62
+ this.signal = params.signal;
63
+ this.stderrSummary = params.stderrSummary?.trim() || void 0;
64
+ }
65
+ };
66
+ var AgentDisconnectedError = class extends AcpxOperationalError {
67
+ reason;
68
+ exitCode;
69
+ signal;
70
+ constructor(reason, exitCode, signal, options) {
71
+ super(`ACP agent disconnected during request (${reason}, exit=${exitCode ?? "null"}, signal=${signal ?? "null"})`, {
72
+ outputCode: "RUNTIME",
73
+ detailCode: "AGENT_DISCONNECTED",
74
+ origin: "acp",
75
+ ...options
76
+ });
77
+ this.reason = reason;
78
+ this.exitCode = exitCode;
79
+ this.signal = signal;
80
+ }
81
+ };
82
+ var SessionResumeRequiredError = class extends AcpxOperationalError {
83
+ constructor(message, options) {
84
+ super(message, {
85
+ outputCode: "RUNTIME",
86
+ detailCode: "SESSION_RESUME_REQUIRED",
87
+ origin: "acp",
88
+ retryable: true,
89
+ ...options
90
+ });
91
+ }
92
+ };
93
+ var GeminiAcpStartupTimeoutError = class extends AcpxOperationalError {
94
+ constructor(message, options) {
95
+ super(message, {
96
+ outputCode: "TIMEOUT",
97
+ detailCode: "GEMINI_ACP_STARTUP_TIMEOUT",
98
+ origin: "acp",
99
+ ...options
100
+ });
101
+ }
102
+ };
103
+ var SessionModeReplayError = class extends AcpxOperationalError {
104
+ constructor(message, options) {
105
+ super(message, {
106
+ outputCode: "RUNTIME",
107
+ detailCode: "SESSION_MODE_REPLAY_FAILED",
108
+ origin: "acp",
109
+ ...options
110
+ });
111
+ }
112
+ };
113
+ var SessionModelReplayError = class extends AcpxOperationalError {
114
+ constructor(message, options) {
115
+ super(message, {
116
+ outputCode: "RUNTIME",
117
+ detailCode: "SESSION_MODEL_REPLAY_FAILED",
118
+ origin: "acp",
119
+ ...options
120
+ });
121
+ }
122
+ };
123
+ var SessionConfigOptionReplayError = class extends AcpxOperationalError {
124
+ constructor(message, options) {
125
+ super(message, {
126
+ outputCode: "RUNTIME",
127
+ detailCode: "SESSION_CONFIG_OPTION_REPLAY_FAILED",
128
+ origin: "acp",
129
+ ...options
130
+ });
131
+ }
132
+ };
133
+ var ClaudeAcpSessionCreateTimeoutError = class extends AcpxOperationalError {
134
+ constructor(message, options) {
135
+ super(message, {
136
+ outputCode: "TIMEOUT",
137
+ detailCode: "CLAUDE_ACP_SESSION_CREATE_TIMEOUT",
138
+ origin: "acp",
139
+ ...options
140
+ });
141
+ }
142
+ };
143
+ var CopilotAcpUnsupportedError = class extends AcpxOperationalError {
144
+ constructor(message, options) {
145
+ super(message, {
146
+ outputCode: "RUNTIME",
147
+ detailCode: "COPILOT_ACP_UNSUPPORTED",
148
+ origin: "acp",
149
+ ...options
150
+ });
151
+ }
152
+ };
153
+ var AuthPolicyError = class extends AcpxOperationalError {
154
+ constructor(message, options) {
155
+ super(message, {
156
+ outputCode: "RUNTIME",
157
+ detailCode: "AUTH_REQUIRED",
158
+ origin: "acp",
159
+ ...options
160
+ });
161
+ }
162
+ };
163
+ var QueueConnectionError = class extends AcpxOperationalError {};
164
+ var QueueProtocolError = class extends AcpxOperationalError {};
165
+ var PermissionDeniedError = class extends AcpxOperationalError {};
166
+ var PermissionPromptUnavailableError = class extends AcpxOperationalError {
167
+ constructor() {
168
+ super("Permission prompt unavailable in non-interactive mode");
169
+ }
170
+ };
171
+ //#endregion
172
+ //#region src/types.ts
173
+ const EXIT_CODES = {
174
+ SUCCESS: 0,
175
+ ERROR: 1,
176
+ USAGE: 2,
177
+ TIMEOUT: 3,
178
+ NO_SESSION: 4,
179
+ PERMISSION_DENIED: 5,
180
+ INTERRUPTED: 130
181
+ };
182
+ const OUTPUT_FORMATS = [
183
+ "text",
184
+ "json",
185
+ "quiet"
186
+ ];
187
+ const PERMISSION_MODES = [
188
+ "approve-all",
189
+ "approve-reads",
190
+ "deny-all"
191
+ ];
192
+ const AUTH_POLICIES = ["skip", "fail"];
193
+ const NON_INTERACTIVE_PERMISSION_POLICIES = ["deny", "fail"];
194
+ const PERMISSION_POLICY_ACTIONS = [
195
+ "approve",
196
+ "deny",
197
+ "escalate"
198
+ ];
199
+ const OUTPUT_ERROR_CODES = [
200
+ "NO_SESSION",
201
+ "TIMEOUT",
202
+ "PERMISSION_DENIED",
203
+ "PERMISSION_PROMPT_UNAVAILABLE",
204
+ "RUNTIME",
205
+ "USAGE"
206
+ ];
207
+ const OUTPUT_ERROR_ORIGINS = [
208
+ "cli",
209
+ "runtime",
210
+ "queue",
211
+ "acp"
212
+ ];
213
+ const SESSION_RECORD_SCHEMA = "acpx.session.v1";
214
+ //#endregion
215
+ //#region src/acp/error-shapes.ts
216
+ const RESOURCE_NOT_FOUND_ACP_CODES = new Set([-32001, -32002]);
217
+ function asRecord$7(value) {
218
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
219
+ return value;
220
+ }
221
+ function toAcpErrorPayload(value) {
222
+ const record = asRecord$7(value);
223
+ if (!record) return;
224
+ if (typeof record.code !== "number" || !Number.isFinite(record.code)) return;
225
+ if (typeof record.message !== "string" || record.message.length === 0) return;
226
+ return {
227
+ code: record.code,
228
+ message: record.message,
229
+ data: record.data
230
+ };
231
+ }
232
+ function extractAcpErrorInternal(value, depth) {
233
+ if (depth > 5) return;
234
+ const direct = toAcpErrorPayload(value);
235
+ if (direct) return direct;
236
+ const record = asRecord$7(value);
237
+ if (!record) return;
238
+ if ("error" in record) {
239
+ const nested = extractAcpErrorInternal(record.error, depth + 1);
240
+ if (nested) return nested;
241
+ }
242
+ if ("acp" in record) {
243
+ const nested = extractAcpErrorInternal(record.acp, depth + 1);
244
+ if (nested) return nested;
245
+ }
246
+ if ("cause" in record) {
247
+ const nested = extractAcpErrorInternal(record.cause, depth + 1);
248
+ if (nested) return nested;
249
+ }
250
+ }
251
+ function formatUnknownErrorMessage(error) {
252
+ if (error instanceof Error) return error.message;
253
+ if (error && typeof error === "object") {
254
+ const maybeMessage = error.message;
255
+ if (typeof maybeMessage === "string" && maybeMessage.length > 0) return maybeMessage;
256
+ try {
257
+ return JSON.stringify(error);
258
+ } catch {}
259
+ }
260
+ return String(error);
261
+ }
262
+ const SESSION_NOT_FOUND_PATTERN = /session\s+["'\w-]+\s+not found/i;
263
+ function isSessionNotFoundText(value) {
264
+ if (typeof value !== "string") return false;
265
+ const normalized = value.toLowerCase();
266
+ return normalized.includes("resource_not_found") || normalized.includes("resource not found") || normalized.includes("session not found") || normalized.includes("unknown session") || normalized.includes("invalid session identifier") || SESSION_NOT_FOUND_PATTERN.test(value);
267
+ }
268
+ function hasSessionNotFoundHint(value, depth = 0) {
269
+ if (depth > 4) return false;
270
+ if (isSessionNotFoundText(value)) return true;
271
+ if (Array.isArray(value)) return value.some((entry) => hasSessionNotFoundHint(entry, depth + 1));
272
+ const record = asRecord$7(value);
273
+ if (!record) return false;
274
+ return Object.values(record).some((entry) => hasSessionNotFoundHint(entry, depth + 1));
275
+ }
276
+ function extractAcpError(error) {
277
+ return extractAcpErrorInternal(error, 0);
278
+ }
279
+ function isAcpResourceNotFoundError(error) {
280
+ const acp = extractAcpError(error);
281
+ if (acp && RESOURCE_NOT_FOUND_ACP_CODES.has(acp.code)) return true;
282
+ if (acp) {
283
+ if (isSessionNotFoundText(acp.message)) return true;
284
+ if (hasSessionNotFoundHint(acp.data)) return true;
285
+ }
286
+ return isSessionNotFoundText(formatUnknownErrorMessage(error));
287
+ }
288
+ //#endregion
289
+ //#region src/acp/error-normalization.ts
290
+ const AUTH_REQUIRED_ACP_CODES = new Set([-32e3]);
291
+ const QUERY_CLOSED_BEFORE_RESPONSE_DETAIL = "query closed before response received";
292
+ function asRecord$6(value) {
293
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
294
+ return value;
295
+ }
296
+ function isAuthRequiredMessage(value) {
297
+ if (!value) return false;
298
+ const normalized = value.toLowerCase();
299
+ return normalized.includes("auth required") || normalized.includes("authentication required") || normalized.includes("authorization required") || normalized.includes("credential required") || normalized.includes("credentials required") || normalized.includes("token required") || normalized.includes("login required");
300
+ }
301
+ function isAcpAuthRequiredPayload(acp) {
302
+ if (!acp) return false;
303
+ if (!AUTH_REQUIRED_ACP_CODES.has(acp.code)) return false;
304
+ if (isAuthRequiredMessage(acp.message)) return true;
305
+ const data = asRecord$6(acp.data);
306
+ if (!data) return false;
307
+ if (data.authRequired === true) return true;
308
+ const methodId = data.methodId;
309
+ if (typeof methodId === "string" && methodId.trim().length > 0) return true;
310
+ const methods = data.methods;
311
+ if (Array.isArray(methods) && methods.length > 0) return true;
312
+ return false;
313
+ }
314
+ function isOutputErrorCode(value) {
315
+ return typeof value === "string" && OUTPUT_ERROR_CODES.includes(value);
316
+ }
317
+ function isOutputErrorOrigin(value) {
318
+ return typeof value === "string" && OUTPUT_ERROR_ORIGINS.includes(value);
319
+ }
320
+ function readOutputErrorMeta(error) {
321
+ const record = asRecord$6(error);
322
+ if (!record) return {};
323
+ return {
324
+ outputCode: isOutputErrorCode(record.outputCode) ? record.outputCode : void 0,
325
+ detailCode: typeof record.detailCode === "string" && record.detailCode.trim().length > 0 ? record.detailCode : void 0,
326
+ origin: isOutputErrorOrigin(record.origin) ? record.origin : void 0,
327
+ retryable: typeof record.retryable === "boolean" ? record.retryable : void 0,
328
+ acp: extractAcpError(record.acp)
329
+ };
330
+ }
331
+ function isTimeoutLike(error) {
332
+ return error instanceof Error && error.name === "TimeoutError";
333
+ }
334
+ function isNoSessionLike(error) {
335
+ return error instanceof Error && error.name === "NoSessionError";
336
+ }
337
+ function isUsageLike(error) {
338
+ if (!(error instanceof Error)) return false;
339
+ return error.name === "CommanderError" || error.name === "InvalidArgumentError" || asRecord$6(error)?.code === "commander.invalidArgument";
340
+ }
341
+ function formatErrorMessage(error) {
342
+ return formatUnknownErrorMessage(error);
343
+ }
344
+ function isAcpQueryClosedBeforeResponseError(error) {
345
+ const acp = extractAcpError(error);
346
+ if (!acp || acp.code !== -32603) return false;
347
+ const details = asRecord$6(acp.data)?.details;
348
+ if (typeof details !== "string") return false;
349
+ return details.toLowerCase().includes(QUERY_CLOSED_BEFORE_RESPONSE_DETAIL);
350
+ }
351
+ function mapErrorCode(error) {
352
+ if (error instanceof PermissionPromptUnavailableError) return "PERMISSION_PROMPT_UNAVAILABLE";
353
+ if (error instanceof PermissionDeniedError) return "PERMISSION_DENIED";
354
+ if (isTimeoutLike(error)) return "TIMEOUT";
355
+ if (isNoSessionLike(error) || isAcpResourceNotFoundError(error)) return "NO_SESSION";
356
+ if (isUsageLike(error)) return "USAGE";
357
+ }
358
+ function normalizeOutputError(error, options = {}) {
359
+ const meta = readOutputErrorMeta(error);
360
+ let code = mapErrorCode(error) ?? options.defaultCode ?? "RUNTIME";
361
+ if (meta.outputCode) code = meta.outputCode;
362
+ if (code === "RUNTIME" && isAcpResourceNotFoundError(error)) code = "NO_SESSION";
363
+ const acp = options.acp ?? meta.acp ?? extractAcpError(error);
364
+ const detailCode = meta.detailCode ?? options.detailCode ?? (error instanceof AuthPolicyError || isAcpAuthRequiredPayload(acp) ? "AUTH_REQUIRED" : void 0);
365
+ return {
366
+ code,
367
+ message: formatErrorMessage(error),
368
+ detailCode,
369
+ origin: meta.origin ?? options.origin,
370
+ retryable: meta.retryable ?? options.retryable,
371
+ acp
372
+ };
373
+ }
374
+ /**
375
+ * Returns true when an error from `client.prompt()` looks transient and
376
+ * can reasonably be retried (e.g. model-API 400/500, network hiccups that
377
+ * surface as ACP internal errors).
378
+ *
379
+ * Errors that are definitively non-recoverable (auth, missing session,
380
+ * invalid params, timeout, permission) return false.
381
+ */
382
+ function isRetryablePromptError(error) {
383
+ if (error instanceof PermissionDeniedError || error instanceof PermissionPromptUnavailableError) return false;
384
+ if (isTimeoutLike(error) || isNoSessionLike(error) || isUsageLike(error)) return false;
385
+ const acp = extractAcpError(error);
386
+ if (!acp) return false;
387
+ if (acp.code === -32001 || acp.code === -32002) return false;
388
+ if (isAcpAuthRequiredPayload(acp)) return false;
389
+ if (acp.code === -32601 || acp.code === -32602) return false;
390
+ return acp.code === -32603 || acp.code === -32700;
391
+ }
392
+ function exitCodeForOutputErrorCode(code) {
393
+ switch (code) {
394
+ case "USAGE": return EXIT_CODES.USAGE;
395
+ case "TIMEOUT": return EXIT_CODES.TIMEOUT;
396
+ case "NO_SESSION": return EXIT_CODES.NO_SESSION;
397
+ case "PERMISSION_DENIED":
398
+ case "PERMISSION_PROMPT_UNAVAILABLE": return EXIT_CODES.PERMISSION_DENIED;
399
+ default: return EXIT_CODES.ERROR;
400
+ }
401
+ }
402
+ //#endregion
14
403
  //#region src/agent-registry.ts
15
404
  const ACP_ADAPTER_PACKAGE_RANGES = {
16
405
  pi: "^0.0.26",
@@ -223,6 +612,149 @@ async function withInterrupt(run, onInterrupt) {
223
612
  });
224
613
  }
225
614
  //#endregion
615
+ //#region src/prompt-content.ts
616
+ var PromptInputValidationError = class extends Error {
617
+ constructor(message) {
618
+ super(message);
619
+ this.name = "PromptInputValidationError";
620
+ }
621
+ };
622
+ function asRecord$5(value) {
623
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
624
+ return value;
625
+ }
626
+ function isNonEmptyString(value) {
627
+ return typeof value === "string" && value.trim().length > 0;
628
+ }
629
+ function isBase64Data(value) {
630
+ if (value.length === 0 || value.length % 4 !== 0) return false;
631
+ return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value);
632
+ }
633
+ function isImageMimeType(value) {
634
+ return /^image\/[A-Za-z0-9.+-]+$/i.test(value);
635
+ }
636
+ function isTextBlock(value) {
637
+ const record = asRecord$5(value);
638
+ return record?.type === "text" && typeof record.text === "string";
639
+ }
640
+ function isImageBlock(value) {
641
+ const record = asRecord$5(value);
642
+ return record?.type === "image" && isNonEmptyString(record.mimeType) && isImageMimeType(record.mimeType) && typeof record.data === "string" && isBase64Data(record.data);
643
+ }
644
+ function isResourceLinkBlock(value) {
645
+ const record = asRecord$5(value);
646
+ return record?.type === "resource_link" && isNonEmptyString(record.uri) && (record.title === void 0 || typeof record.title === "string") && (record.name === void 0 || typeof record.name === "string");
647
+ }
648
+ function isResourcePayload(value) {
649
+ const record = asRecord$5(value);
650
+ if (!record || !isNonEmptyString(record.uri)) return false;
651
+ return record.text === void 0 || typeof record.text === "string";
652
+ }
653
+ function isResourceBlock(value) {
654
+ const record = asRecord$5(value);
655
+ return record?.type === "resource" && isResourcePayload(record.resource);
656
+ }
657
+ function isContentBlock(value) {
658
+ return isTextBlock(value) || isImageBlock(value) || isResourceLinkBlock(value) || isResourceBlock(value);
659
+ }
660
+ function getContentBlockValidationError(value, index) {
661
+ const record = asRecord$5(value);
662
+ if (!record || typeof record.type !== "string") return `prompt[${index}] must be an ACP content block object`;
663
+ switch (record.type) {
664
+ case "text": return typeof record.text === "string" ? void 0 : `prompt[${index}] text block must include a string text field`;
665
+ case "image":
666
+ if (!isNonEmptyString(record.mimeType)) return `prompt[${index}] image block must include a non-empty mimeType`;
667
+ if (!isImageMimeType(record.mimeType)) return `prompt[${index}] image block mimeType must start with image/`;
668
+ if (typeof record.data !== "string" || record.data.length === 0) return `prompt[${index}] image block must include non-empty base64 data`;
669
+ if (!isBase64Data(record.data)) return `prompt[${index}] image block data must be valid base64`;
670
+ return;
671
+ case "resource_link":
672
+ if (!isNonEmptyString(record.uri)) return `prompt[${index}] resource_link block must include a non-empty uri`;
673
+ if (record.title !== void 0 && typeof record.title !== "string") return `prompt[${index}] resource_link block title must be a string when present`;
674
+ if (record.name !== void 0 && typeof record.name !== "string") return `prompt[${index}] resource_link block name must be a string when present`;
675
+ return;
676
+ case "resource":
677
+ if (!asRecord$5(record.resource)) return `prompt[${index}] resource block must include a resource object`;
678
+ if (!isResourcePayload(record.resource)) return `prompt[${index}] resource block resource must include a non-empty uri and optional text`;
679
+ return;
680
+ default: return `prompt[${index}] has unsupported content block type ${JSON.stringify(record.type)}`;
681
+ }
682
+ }
683
+ function isPromptInput(value) {
684
+ return Array.isArray(value) && value.every((entry) => isContentBlock(entry));
685
+ }
686
+ function textPrompt(text) {
687
+ return [{
688
+ type: "text",
689
+ text
690
+ }];
691
+ }
692
+ function parseStructuredPrompt(source) {
693
+ if (!source.startsWith("[")) return;
694
+ try {
695
+ const parsed = JSON.parse(source);
696
+ if (isPromptInput(parsed)) return parsed;
697
+ if (Array.isArray(parsed)) throw new PromptInputValidationError(parsed.map((entry, index) => getContentBlockValidationError(entry, index)).find((message) => message !== void 0) ?? "Structured prompt JSON must be an array of valid ACP content blocks");
698
+ return;
699
+ } catch (error) {
700
+ if (error instanceof PromptInputValidationError) throw error;
701
+ return;
702
+ }
703
+ }
704
+ function parsePromptSource(source) {
705
+ const trimmed = source.trim();
706
+ const structured = parseStructuredPrompt(trimmed);
707
+ if (structured) return structured;
708
+ if (!trimmed) return [];
709
+ return textPrompt(trimmed);
710
+ }
711
+ function mergePromptSourceWithText(source, suffixText) {
712
+ const prompt = parsePromptSource(source);
713
+ const appended = suffixText.trim();
714
+ if (!appended) return prompt;
715
+ if (prompt.length === 0) return textPrompt(appended);
716
+ return [...prompt, ...textPrompt(appended)];
717
+ }
718
+ function promptToDisplayText(prompt) {
719
+ return prompt.map((block) => {
720
+ switch (block.type) {
721
+ case "text": return block.text;
722
+ case "resource_link": return block.title ?? block.name ?? block.uri;
723
+ case "resource": return "text" in block.resource && typeof block.resource.text === "string" ? block.resource.text : block.resource.uri;
724
+ case "image": return `[image] ${block.mimeType}`;
725
+ default: return "";
726
+ }
727
+ }).filter((entry) => entry.trim().length > 0).join("\n\n").trim();
728
+ }
729
+ //#endregion
730
+ //#region src/acp/agent-session-id.ts
731
+ const AGENT_SESSION_ID_META_KEYS = ["agentSessionId", "sessionId"];
732
+ function normalizeAgentSessionId(value) {
733
+ if (typeof value !== "string") return;
734
+ const trimmed = value.trim();
735
+ return trimmed.length > 0 ? trimmed : void 0;
736
+ }
737
+ function asMetaRecord(meta) {
738
+ if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
739
+ return meta;
740
+ }
741
+ function extractAgentSessionId(meta) {
742
+ const record = asMetaRecord(meta);
743
+ if (!record) return;
744
+ for (const key of AGENT_SESSION_ID_META_KEYS) {
745
+ const normalized = normalizeAgentSessionId(record[key]);
746
+ if (normalized) return normalized;
747
+ }
748
+ }
749
+ //#endregion
750
+ //#region src/session/runtime-session-id.ts
751
+ function normalizeRuntimeSessionId(value) {
752
+ return normalizeAgentSessionId(value);
753
+ }
754
+ function extractRuntimeSessionId(meta) {
755
+ return extractAgentSessionId(meta);
756
+ }
757
+ //#endregion
226
758
  //#region src/session/persistence/serialize.ts
227
759
  function serializeSessionRecordForDisk(record) {
228
760
  const canonical = {
@@ -262,6 +794,72 @@ function serializeSessionRecordForDisk(record) {
262
794
  };
263
795
  }
264
796
  //#endregion
797
+ //#region src/perf-metrics.ts
798
+ const counters = /* @__PURE__ */ new Map();
799
+ const gauges = /* @__PURE__ */ new Map();
800
+ const timings = /* @__PURE__ */ new Map();
801
+ function hrNow() {
802
+ return process.hrtime.bigint();
803
+ }
804
+ function durationMs(start) {
805
+ return Number(process.hrtime.bigint() - start) / 1e6;
806
+ }
807
+ function roundMetric(value) {
808
+ return Number(value.toFixed(3));
809
+ }
810
+ function incrementPerfCounter(name, delta = 1) {
811
+ counters.set(name, (counters.get(name) ?? 0) + delta);
812
+ }
813
+ function setPerfGauge(name, value) {
814
+ gauges.set(name, value);
815
+ }
816
+ function recordPerfDuration(name, durationMsValue) {
817
+ const next = timings.get(name) ?? {
818
+ count: 0,
819
+ totalMs: 0,
820
+ maxMs: 0
821
+ };
822
+ next.count += 1;
823
+ next.totalMs += durationMsValue;
824
+ next.maxMs = Math.max(next.maxMs, durationMsValue);
825
+ timings.set(name, next);
826
+ }
827
+ async function measurePerf(name, run) {
828
+ const startedAt = hrNow();
829
+ try {
830
+ return await run();
831
+ } finally {
832
+ recordPerfDuration(name, durationMs(startedAt));
833
+ }
834
+ }
835
+ function startPerfTimer(name) {
836
+ const startedAt = hrNow();
837
+ return () => {
838
+ const elapsedMs = durationMs(startedAt);
839
+ recordPerfDuration(name, elapsedMs);
840
+ return elapsedMs;
841
+ };
842
+ }
843
+ function getPerfMetricsSnapshot() {
844
+ return {
845
+ counters: Object.fromEntries(counters.entries()),
846
+ gauges: Object.fromEntries(gauges.entries()),
847
+ timings: Object.fromEntries([...timings.entries()].map(([name, bucket]) => [name, {
848
+ count: bucket.count,
849
+ totalMs: roundMetric(bucket.totalMs),
850
+ maxMs: roundMetric(bucket.maxMs)
851
+ }]))
852
+ };
853
+ }
854
+ function resetPerfMetrics() {
855
+ counters.clear();
856
+ gauges.clear();
857
+ timings.clear();
858
+ }
859
+ function formatPerfMetric(name, durationMsValue) {
860
+ return `${name}=${roundMetric(durationMsValue)}ms`;
861
+ }
862
+ //#endregion
265
863
  //#region src/persisted-key-policy.ts
266
864
  const SNAKE_CASE_KEY = /^[a-z][a-z0-9_]*$/;
267
865
  const ZED_TAG_KEYS = new Set([
@@ -358,7 +956,7 @@ function defaultSessionEventLog(sessionId) {
358
956
  }
359
957
  //#endregion
360
958
  //#region src/session/persistence/parse.ts
361
- function asRecord$3(value) {
959
+ function asRecord$4(value) {
362
960
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
363
961
  return value;
364
962
  }
@@ -370,7 +968,7 @@ function isStringArray(value) {
370
968
  }
371
969
  function parseTokenUsage(raw) {
372
970
  if (raw === void 0 || raw === null) return;
373
- const record = asRecord$3(raw);
971
+ const record = asRecord$4(raw);
374
972
  if (!record) return null;
375
973
  const usage = {};
376
974
  for (const field of [
@@ -388,7 +986,7 @@ function parseTokenUsage(raw) {
388
986
  }
389
987
  function parseRequestTokenUsage(raw) {
390
988
  if (raw === void 0 || raw === null) return;
391
- const record = asRecord$3(raw);
989
+ const record = asRecord$4(raw);
392
990
  if (!record) return null;
393
991
  const usage = {};
394
992
  for (const [key, value] of Object.entries(record)) {
@@ -399,44 +997,44 @@ function parseRequestTokenUsage(raw) {
399
997
  return usage;
400
998
  }
401
999
  function isSessionMessageImage(raw) {
402
- const record = asRecord$3(raw);
1000
+ const record = asRecord$4(raw);
403
1001
  if (!record || typeof record.source !== "string") return false;
404
1002
  if (record.size === void 0 || record.size === null) return true;
405
- const size = asRecord$3(record.size);
1003
+ const size = asRecord$4(record.size);
406
1004
  return !!size && typeof size.width === "number" && Number.isFinite(size.width) && typeof size.height === "number" && Number.isFinite(size.height);
407
1005
  }
408
1006
  function isUserContent(raw) {
409
- const record = asRecord$3(raw);
1007
+ const record = asRecord$4(raw);
410
1008
  if (!record) return false;
411
1009
  if (typeof record.Text === "string") return true;
412
1010
  if (record.Mention !== void 0) {
413
- const mention = asRecord$3(record.Mention);
1011
+ const mention = asRecord$4(record.Mention);
414
1012
  return !!mention && typeof mention.uri === "string" && typeof mention.content === "string";
415
1013
  }
416
1014
  if (record.Image !== void 0) return isSessionMessageImage(record.Image);
417
1015
  return false;
418
1016
  }
419
1017
  function isToolUse(raw) {
420
- const record = asRecord$3(raw);
1018
+ const record = asRecord$4(raw);
421
1019
  return !!record && typeof record.id === "string" && typeof record.name === "string" && typeof record.raw_input === "string" && hasOwn$1(record, "input") && typeof record.is_input_complete === "boolean" && (record.thought_signature === void 0 || record.thought_signature === null || typeof record.thought_signature === "string");
422
1020
  }
423
1021
  function isToolResultContent(raw) {
424
- const record = asRecord$3(raw);
1022
+ const record = asRecord$4(raw);
425
1023
  if (!record) return false;
426
1024
  if (typeof record.Text === "string") return true;
427
1025
  if (record.Image !== void 0) return isSessionMessageImage(record.Image);
428
1026
  return false;
429
1027
  }
430
1028
  function isToolResult(raw) {
431
- const record = asRecord$3(raw);
1029
+ const record = asRecord$4(raw);
432
1030
  return !!record && typeof record.tool_use_id === "string" && typeof record.tool_name === "string" && typeof record.is_error === "boolean" && isToolResultContent(record.content);
433
1031
  }
434
1032
  function isAgentContent(raw) {
435
- const record = asRecord$3(raw);
1033
+ const record = asRecord$4(raw);
436
1034
  if (!record) return false;
437
1035
  if (typeof record.Text === "string") return true;
438
1036
  if (record.Thinking !== void 0) {
439
- const thinking = asRecord$3(record.Thinking);
1037
+ const thinking = asRecord$4(record.Thinking);
440
1038
  return !!thinking && typeof thinking.text === "string" && (thinking.signature === void 0 || thinking.signature === null || typeof thinking.signature === "string");
441
1039
  }
442
1040
  if (typeof record.RedactedThinking === "string") return true;
@@ -444,17 +1042,17 @@ function isAgentContent(raw) {
444
1042
  return false;
445
1043
  }
446
1044
  function isUserMessage$1(raw) {
447
- const record = asRecord$3(raw);
1045
+ const record = asRecord$4(raw);
448
1046
  if (!record || record.User === void 0) return false;
449
- const user = asRecord$3(record.User);
1047
+ const user = asRecord$4(record.User);
450
1048
  return !!user && typeof user.id === "string" && Array.isArray(user.content) && user.content.every((entry) => isUserContent(entry));
451
1049
  }
452
1050
  function isAgentMessage$1(raw) {
453
- const record = asRecord$3(raw);
1051
+ const record = asRecord$4(raw);
454
1052
  if (!record || record.Agent === void 0) return false;
455
- const agent = asRecord$3(record.Agent);
1053
+ const agent = asRecord$4(record.Agent);
456
1054
  if (!agent || !Array.isArray(agent.content) || !agent.content.every(isAgentContent)) return false;
457
- const toolResults = asRecord$3(agent.tool_results);
1055
+ const toolResults = asRecord$4(agent.tool_results);
458
1056
  if (!toolResults) return false;
459
1057
  return Object.values(toolResults).every(isToolResult);
460
1058
  }
@@ -476,13 +1074,13 @@ function parseConversationRecord(record) {
476
1074
  };
477
1075
  }
478
1076
  function parseAcpxState(raw) {
479
- const record = asRecord$3(raw);
1077
+ const record = asRecord$4(raw);
480
1078
  if (!record) return;
481
1079
  const state = {};
482
1080
  if (record.reset_on_next_ensure === true) state.reset_on_next_ensure = true;
483
1081
  if (typeof record.current_mode_id === "string") state.current_mode_id = record.current_mode_id;
484
1082
  if (typeof record.desired_mode_id === "string") state.desired_mode_id = record.desired_mode_id;
485
- const desiredConfigOptions = asRecord$3(record.desired_config_options);
1083
+ const desiredConfigOptions = asRecord$4(record.desired_config_options);
486
1084
  if (desiredConfigOptions) {
487
1085
  const parsed = {};
488
1086
  for (const [key, value] of Object.entries(desiredConfigOptions)) if (typeof key === "string" && typeof value === "string") parsed[key] = value;
@@ -492,7 +1090,7 @@ function parseAcpxState(raw) {
492
1090
  if (isStringArray(record.available_models)) state.available_models = [...record.available_models];
493
1091
  if (isStringArray(record.available_commands)) state.available_commands = [...record.available_commands];
494
1092
  if (Array.isArray(record.config_options)) state.config_options = record.config_options;
495
- const sessionOptions = asRecord$3(record.session_options);
1093
+ const sessionOptions = asRecord$4(record.session_options);
496
1094
  if (sessionOptions) {
497
1095
  const parsedSessionOptions = {};
498
1096
  if (typeof sessionOptions.model === "string") parsedSessionOptions.model = sessionOptions.model;
@@ -501,7 +1099,7 @@ function parseAcpxState(raw) {
501
1099
  const rawSystemPrompt = sessionOptions.system_prompt;
502
1100
  if (typeof rawSystemPrompt === "string" && rawSystemPrompt.length > 0) parsedSessionOptions.system_prompt = rawSystemPrompt;
503
1101
  else {
504
- const appendRecord = asRecord$3(rawSystemPrompt);
1102
+ const appendRecord = asRecord$4(rawSystemPrompt);
505
1103
  if (appendRecord && typeof appendRecord.append === "string" && appendRecord.append.length > 0) parsedSessionOptions.system_prompt = { append: appendRecord.append };
506
1104
  }
507
1105
  if (Object.keys(parsedSessionOptions).length > 0) state.session_options = parsedSessionOptions;
@@ -509,7 +1107,7 @@ function parseAcpxState(raw) {
509
1107
  return state;
510
1108
  }
511
1109
  function parseEventLog(raw, sessionId) {
512
- const record = asRecord$3(raw);
1110
+ const record = asRecord$4(raw);
513
1111
  if (!record) return defaultSessionEventLog(sessionId);
514
1112
  if (typeof record.active_path !== "string" || typeof record.segment_count !== "number" || !Number.isInteger(record.segment_count) || record.segment_count < 1 || typeof record.max_segment_bytes !== "number" || !Number.isInteger(record.max_segment_bytes) || record.max_segment_bytes < 1 || typeof record.max_segments !== "number" || !Number.isInteger(record.max_segments) || record.max_segments < 1) return defaultSessionEventLog(sessionId);
515
1113
  return {
@@ -553,7 +1151,7 @@ function normalizeOptionalSignal(value) {
553
1151
  return Symbol("invalid");
554
1152
  }
555
1153
  function parseSessionRecord(raw) {
556
- const record = asRecord$3(raw);
1154
+ const record = asRecord$4(raw);
557
1155
  if (!record) return null;
558
1156
  if (record.schema !== "acpx.session.v1") return null;
559
1157
  const name = normalizeOptionalName(record.name);
@@ -595,7 +1193,7 @@ function parseSessionRecord(raw) {
595
1193
  lastAgentExitAt,
596
1194
  lastAgentDisconnectReason,
597
1195
  protocolVersion: typeof record.protocol_version === "number" ? record.protocol_version : void 0,
598
- agentCapabilities: asRecord$3(record.agent_capabilities),
1196
+ agentCapabilities: asRecord$4(record.agent_capabilities),
599
1197
  title: conversation.title,
600
1198
  messages: conversation.messages,
601
1199
  updated_at: conversation.updated_at,
@@ -607,12 +1205,12 @@ function parseSessionRecord(raw) {
607
1205
  //#endregion
608
1206
  //#region src/session/persistence/index.ts
609
1207
  const SESSION_INDEX_SCHEMA = "acpx.session-index.v1";
610
- function asRecord$2(value) {
1208
+ function asRecord$3(value) {
611
1209
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
612
1210
  return value;
613
1211
  }
614
1212
  function parseIndexEntry(raw) {
615
- const record = asRecord$2(raw);
1213
+ const record = asRecord$3(raw);
616
1214
  if (!record) return;
617
1215
  if (typeof record.file !== "string" || typeof record.acpxRecordId !== "string" || typeof record.acpSessionId !== "string" || typeof record.agentCommand !== "string" || typeof record.cwd !== "string" || typeof record.lastUsedAt !== "string" || typeof record.closed !== "boolean") return;
618
1216
  if (record.name !== void 0 && typeof record.name !== "string") return;
@@ -646,7 +1244,7 @@ async function readSessionIndex(sessionDir) {
646
1244
  const filePath = sessionIndexPath(sessionDir);
647
1245
  try {
648
1246
  const payload = await fs$1.readFile(filePath, "utf8");
649
- const record = asRecord$2(JSON.parse(payload));
1247
+ const record = asRecord$3(JSON.parse(payload));
650
1248
  if (!record || record.schema !== SESSION_INDEX_SCHEMA || !Array.isArray(record.files)) return;
651
1249
  const files = record.files.filter((entry) => typeof entry === "string");
652
1250
  if (files.length !== record.files.length || !Array.isArray(record.entries)) return;
@@ -1076,6 +1674,18 @@ function selected(optionId) {
1076
1674
  function cancelled() {
1077
1675
  return { outcome: { outcome: "cancelled" } };
1078
1676
  }
1677
+ function withEscalationMetadata(response, event) {
1678
+ return {
1679
+ ...response,
1680
+ _meta: {
1681
+ ...response._meta,
1682
+ acpx: {
1683
+ ...response._meta?.acpx && typeof response._meta.acpx === "object" && !Array.isArray(response._meta.acpx) ? response._meta.acpx : {},
1684
+ permissionEscalation: event
1685
+ }
1686
+ }
1687
+ };
1688
+ }
1079
1689
  function pickOption(options, kinds) {
1080
1690
  for (const kind of kinds) {
1081
1691
  const match = options.find((option) => option.kind === kind);
@@ -1107,32 +1717,149 @@ async function promptForToolPermission(params) {
1107
1717
  function canPromptForPermission$1() {
1108
1718
  return process.stdin.isTTY && process.stderr.isTTY;
1109
1719
  }
1720
+ function readStringProperty(value, keys) {
1721
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
1722
+ const record = value;
1723
+ for (const key of keys) {
1724
+ const entry = record[key];
1725
+ if (typeof entry === "string" && entry.trim().length > 0) return entry.trim();
1726
+ }
1727
+ }
1728
+ function readToolName(params) {
1729
+ const rawInputName = readStringProperty(params.toolCall.rawInput, [
1730
+ "name",
1731
+ "tool",
1732
+ "toolName"
1733
+ ]);
1734
+ if (rawInputName) return rawInputName;
1735
+ const head = (params.toolCall.title?.trim())?.split(/[:\s]/, 1)[0]?.trim();
1736
+ return head && head.length > 0 ? head : void 0;
1737
+ }
1738
+ function normalizeMatcher(value) {
1739
+ return value.trim().toLowerCase();
1740
+ }
1741
+ function permissionMatchTokens(params) {
1742
+ const tokens = /* @__PURE__ */ new Set();
1743
+ const kind = inferToolKind(params);
1744
+ const rawKind = params.toolCall.kind;
1745
+ const title = params.toolCall.title?.trim();
1746
+ const toolName = readToolName(params);
1747
+ for (const value of [
1748
+ kind,
1749
+ rawKind,
1750
+ title,
1751
+ toolName
1752
+ ]) if (typeof value === "string" && value.trim().length > 0) tokens.add(normalizeMatcher(value));
1753
+ if (title) {
1754
+ const head = title.split(/[:\s]/, 1)[0]?.trim();
1755
+ if (head) tokens.add(normalizeMatcher(head));
1756
+ }
1757
+ return [...tokens];
1758
+ }
1759
+ function findPolicyRule(rules, params) {
1760
+ if (!rules || rules.length === 0) return;
1761
+ const tokens = permissionMatchTokens(params);
1762
+ for (const rule of rules) {
1763
+ const normalized = normalizeMatcher(rule);
1764
+ if (normalized === "*" || tokens.includes(normalized)) return rule;
1765
+ }
1766
+ }
1767
+ function matchPermissionPolicy(params, policy) {
1768
+ if (!policy) return;
1769
+ const denyRule = findPolicyRule(policy.autoDeny, params);
1770
+ if (denyRule) return {
1771
+ action: "deny",
1772
+ matchedRule: denyRule
1773
+ };
1774
+ const approveRule = findPolicyRule(policy.autoApprove, params);
1775
+ if (approveRule) return {
1776
+ action: "approve",
1777
+ matchedRule: approveRule
1778
+ };
1779
+ const escalateRule = findPolicyRule(policy.escalate, params);
1780
+ if (escalateRule) return {
1781
+ action: "escalate",
1782
+ matchedRule: escalateRule
1783
+ };
1784
+ return policy.defaultAction ? { action: policy.defaultAction } : void 0;
1785
+ }
1786
+ function buildEscalationEvent(params, matchedRule) {
1787
+ const toolKind = inferToolKind(params);
1788
+ const toolTitle = params.toolCall.title?.trim() || "tool";
1789
+ const toolName = readToolName(params);
1790
+ return {
1791
+ type: "permission_escalation",
1792
+ sessionId: params.sessionId,
1793
+ toolCallId: params.toolCall.toolCallId,
1794
+ ...toolName ? { toolName } : {},
1795
+ toolTitle,
1796
+ ...params.toolCall.rawInput !== void 0 ? { toolInput: params.toolCall.rawInput } : {},
1797
+ ...toolKind ? { toolKind } : {},
1798
+ action: "escalate",
1799
+ ...matchedRule ? { matchedRule } : {},
1800
+ message: `Permission escalation required for ${toolTitle}`,
1801
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1802
+ };
1803
+ }
1110
1804
  function permissionModeSatisfies(actual, required) {
1111
1805
  return PERMISSION_MODE_RANK[actual] >= PERMISSION_MODE_RANK[required];
1112
1806
  }
1113
- async function resolvePermissionRequest(params, mode, nonInteractivePolicy = "deny") {
1807
+ async function resolvePermissionRequestWithDetails(params, mode, nonInteractivePolicy = "deny", policy) {
1114
1808
  const options = params.options ?? [];
1115
- if (options.length === 0) return cancelled();
1809
+ if (options.length === 0) return { response: cancelled() };
1116
1810
  const allowOption = pickOption(options, ["allow_once", "allow_always"]);
1117
1811
  const rejectOption = pickOption(options, ["reject_once", "reject_always"]);
1812
+ const policyMatch = matchPermissionPolicy(params, policy);
1813
+ if (policyMatch?.action === "approve") {
1814
+ if (allowOption) return { response: selected(allowOption.optionId) };
1815
+ return { response: selected(options[0].optionId) };
1816
+ }
1817
+ if (policyMatch?.action === "deny") {
1818
+ if (rejectOption) return { response: selected(rejectOption.optionId) };
1819
+ return { response: cancelled() };
1820
+ }
1821
+ if (policyMatch?.action === "escalate") {
1822
+ if (canPromptForPermission$1()) {
1823
+ const approved = await promptForToolPermission(params);
1824
+ if (approved && allowOption) return { response: selected(allowOption.optionId) };
1825
+ if (!approved && rejectOption) return { response: selected(rejectOption.optionId) };
1826
+ return { response: cancelled() };
1827
+ }
1828
+ const escalation = buildEscalationEvent(params, policyMatch.matchedRule);
1829
+ return {
1830
+ response: withEscalationMetadata(rejectOption ? selected(rejectOption.optionId) : cancelled(), escalation),
1831
+ escalation
1832
+ };
1833
+ }
1118
1834
  if (mode === "approve-all") {
1119
- if (allowOption) return selected(allowOption.optionId);
1120
- return selected(options[0].optionId);
1835
+ if (allowOption) return { response: selected(allowOption.optionId) };
1836
+ return { response: selected(options[0].optionId) };
1121
1837
  }
1122
1838
  if (mode === "deny-all") {
1123
- if (rejectOption) return selected(rejectOption.optionId);
1124
- return cancelled();
1839
+ if (rejectOption) return { response: selected(rejectOption.optionId) };
1840
+ return { response: cancelled() };
1125
1841
  }
1126
- if (isAutoApprovedReadKind(inferToolKind(params)) && allowOption) return selected(allowOption.optionId);
1842
+ if (isAutoApprovedReadKind(inferToolKind(params)) && allowOption) return { response: selected(allowOption.optionId) };
1127
1843
  if (!canPromptForPermission$1()) {
1128
1844
  if (nonInteractivePolicy === "fail") throw new PermissionPromptUnavailableError();
1129
- if (rejectOption) return selected(rejectOption.optionId);
1130
- return cancelled();
1845
+ if (rejectOption) return { response: selected(rejectOption.optionId) };
1846
+ return { response: cancelled() };
1131
1847
  }
1132
1848
  const approved = await promptForToolPermission(params);
1133
- if (approved && allowOption) return selected(allowOption.optionId);
1134
- if (!approved && rejectOption) return selected(rejectOption.optionId);
1135
- return cancelled();
1849
+ if (approved && allowOption) return { response: selected(allowOption.optionId) };
1850
+ if (!approved && rejectOption) return { response: selected(rejectOption.optionId) };
1851
+ return { response: cancelled() };
1852
+ }
1853
+ const DECISION_FALLBACK_ORDER = {
1854
+ allow_once: ["allow_once", "allow_always"],
1855
+ allow_always: ["allow_always", "allow_once"],
1856
+ reject_once: ["reject_once", "reject_always"],
1857
+ reject_always: ["reject_always", "reject_once"]
1858
+ };
1859
+ function decisionToResponse(params, decision) {
1860
+ if (decision.outcome === "cancel") return cancelled();
1861
+ const matched = pickOption(params.options ?? [], DECISION_FALLBACK_ORDER[decision.outcome]);
1862
+ return matched ? selected(matched.optionId) : cancelled();
1136
1863
  }
1137
1864
  function classifyPermissionDecision(params, response) {
1138
1865
  if (response.outcome.outcome !== "selected") return "cancelled";
@@ -1176,6 +1903,30 @@ function buildSpawnCommandOptions(command, options, platform = process.platform,
1176
1903
  shell: true
1177
1904
  };
1178
1905
  }
1906
+ function buildTerminalSpawnCommand(command, args) {
1907
+ return {
1908
+ command,
1909
+ args: args ?? [],
1910
+ killProcessGroup: false
1911
+ };
1912
+ }
1913
+ function buildTerminalShellSpawnCommand(command, platform = process.platform) {
1914
+ if (platform === "win32") return {
1915
+ command: "cmd.exe",
1916
+ args: [
1917
+ "/d",
1918
+ "/s",
1919
+ "/c",
1920
+ command
1921
+ ],
1922
+ killProcessGroup: true
1923
+ };
1924
+ return {
1925
+ command: "/bin/sh",
1926
+ args: ["-c", command],
1927
+ killProcessGroup: true
1928
+ };
1929
+ }
1179
1930
  //#endregion
1180
1931
  //#region src/acp/client-process.ts
1181
1932
  const execFileAsync = promisify(execFile);
@@ -1290,9 +2041,10 @@ function isWsl(options) {
1290
2041
  if ((options.platform ?? process.platform) !== "linux") return false;
1291
2042
  return (options.existsSync ?? fs.existsSync)("/proc/sys/fs/binfmt_misc/WSLInterop");
1292
2043
  }
2044
+ const WINDOWS_EXECUTABLE_EXTENSION_RE = /\.(?:exe|cmd|bat)$/u;
1293
2045
  function isWindowsExecutableCommand(command) {
1294
- const normalized = command.replace(/\\/g, "/").toLowerCase();
1295
- return normalized.endsWith(".exe") || normalized.startsWith("/mnt/c/");
2046
+ const normalized = command.toLowerCase();
2047
+ return WINDOWS_EXECUTABLE_EXTENSION_RE.test(normalized);
1296
2048
  }
1297
2049
  async function runWslpath(cwd) {
1298
2050
  const { stdout } = await execFileAsync("wslpath", ["-w", cwd], { encoding: "utf8" });
@@ -1490,6 +2242,13 @@ function buildClaudeCodeOptionsMeta(options) {
1490
2242
  if (Object.keys(meta).length === 0) return;
1491
2243
  return meta;
1492
2244
  }
2245
+ function resolveClaudeCodeExecutable(platform = process.platform, env = process.env) {
2246
+ if (platform !== "win32") return;
2247
+ if (readWindowsEnvValue(env, "CLAUDE_CODE_EXECUTABLE")) return;
2248
+ const resolved = resolveWindowsCommand("claude", env);
2249
+ if (!resolved) return;
2250
+ return path.resolve(resolved);
2251
+ }
1493
2252
  //#endregion
1494
2253
  //#region src/acp/auth-env.ts
1495
2254
  const AUTH_ENV_PREFIX = "ACPX_AUTH_";
@@ -1556,6 +2315,71 @@ function buildAgentSpawnOptions(cwd, authCredentials) {
1556
2315
  };
1557
2316
  }
1558
2317
  //#endregion
2318
+ //#region src/acp/jsonrpc.ts
2319
+ function asRecord$2(value) {
2320
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
2321
+ return value;
2322
+ }
2323
+ function hasValidId(value) {
2324
+ return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
2325
+ }
2326
+ function isErrorObject(value) {
2327
+ const record = asRecord$2(value);
2328
+ return !!record && typeof record.code === "number" && Number.isFinite(record.code) && typeof record.message === "string";
2329
+ }
2330
+ function hasResultOrError(value) {
2331
+ const hasResult = Object.hasOwn(value, "result");
2332
+ const hasError = Object.hasOwn(value, "error");
2333
+ if (hasResult && hasError) return false;
2334
+ if (!hasResult && !hasError) return false;
2335
+ if (hasError && !isErrorObject(value.error)) return false;
2336
+ return true;
2337
+ }
2338
+ function isAcpJsonRpcMessage(value) {
2339
+ const record = asRecord$2(value);
2340
+ if (!record || record.jsonrpc !== "2.0") return false;
2341
+ const hasMethod = typeof record.method === "string" && record.method.length > 0;
2342
+ const hasId = Object.hasOwn(record, "id");
2343
+ if (hasMethod && !hasId) return true;
2344
+ if (hasMethod && hasId) return hasValidId(record.id);
2345
+ if (!hasMethod && hasId) {
2346
+ if (!hasValidId(record.id)) return false;
2347
+ return hasResultOrError(record);
2348
+ }
2349
+ return false;
2350
+ }
2351
+ function isJsonRpcNotification(message) {
2352
+ return Object.hasOwn(message, "method") && typeof message.method === "string" && !Object.hasOwn(message, "id");
2353
+ }
2354
+ function isSessionUpdateNotification(message) {
2355
+ return isJsonRpcNotification(message) && message.method === "session/update";
2356
+ }
2357
+ function extractSessionUpdateNotification(message) {
2358
+ if (!isSessionUpdateNotification(message)) return;
2359
+ const params = asRecord$2(message.params);
2360
+ if (!params) return;
2361
+ const sessionId = typeof params.sessionId === "string" ? params.sessionId : null;
2362
+ if (!sessionId) return;
2363
+ const update = asRecord$2(params.update);
2364
+ if (!update || typeof update.sessionUpdate !== "string") return;
2365
+ return {
2366
+ sessionId,
2367
+ update
2368
+ };
2369
+ }
2370
+ function parsePromptStopReason(message) {
2371
+ if (!Object.hasOwn(message, "id") || !Object.hasOwn(message, "result")) return;
2372
+ const record = asRecord$2(message.result);
2373
+ if (!record) return;
2374
+ return typeof record.stopReason === "string" ? record.stopReason : void 0;
2375
+ }
2376
+ function parseJsonRpcErrorMessage(message) {
2377
+ if (!Object.hasOwn(message, "error")) return;
2378
+ const errorRecord = asRecord$2(message.error);
2379
+ if (!errorRecord || typeof errorRecord.message !== "string") return;
2380
+ return errorRecord.message;
2381
+ }
2382
+ //#endregion
1559
2383
  //#region src/acp/session-control-errors.ts
1560
2384
  const SESSION_CONTROL_UNSUPPORTED_ACP_CODES = new Set([-32601, -32602]);
1561
2385
  function asRecord$1(value) {
@@ -1679,14 +2503,15 @@ var TerminalManager = class {
1679
2503
  try {
1680
2504
  if (!await this.isExecuteApproved(commandLine)) throw new PermissionDeniedError("Permission denied for terminal/create");
1681
2505
  const outputByteLimit = Math.max(0, Math.round(params.outputByteLimit ?? DEFAULT_TERMINAL_OUTPUT_LIMIT_BYTES));
1682
- const proc = spawn(params.command, params.args ?? [], buildTerminalSpawnOptions(params.command, params.cwd ?? this.cwd, params.env));
1683
- await waitForSpawn(proc);
2506
+ const { proc, spawnCommand } = await spawnTerminalProcess(params, this.cwd);
1684
2507
  let resolveExit = () => {};
1685
2508
  const exitPromise = new Promise((resolve) => {
1686
2509
  resolveExit = resolve;
1687
2510
  });
1688
2511
  const terminal = {
1689
2512
  process: proc,
2513
+ killProcessGroup: spawnCommand.killProcessGroup,
2514
+ descendantPids: /* @__PURE__ */ new Set(),
1690
2515
  output: Buffer.alloc(0),
1691
2516
  truncated: false,
1692
2517
  outputByteLimit,
@@ -1709,10 +2534,14 @@ var TerminalManager = class {
1709
2534
  proc.once("exit", (exitCode, signal) => {
1710
2535
  terminal.exitCode = exitCode;
1711
2536
  terminal.signal = signal;
1712
- terminal.resolveExit({
1713
- exitCode: exitCode ?? null,
1714
- signal: signal ?? null
1715
- });
2537
+ terminal.processGroupSnapshotPromise = rememberProcessGroupPids(terminal);
2538
+ (async () => {
2539
+ await terminal.processGroupSnapshotPromise;
2540
+ terminal.resolveExit({
2541
+ exitCode: exitCode ?? null,
2542
+ signal: signal ?? null
2543
+ });
2544
+ })();
1716
2545
  });
1717
2546
  const terminalId = randomUUID();
1718
2547
  this.terminals.set(terminalId, terminal);
@@ -1864,21 +2693,284 @@ var TerminalManager = class {
1864
2693
  return terminal.exitCode === void 0 && terminal.signal === void 0;
1865
2694
  }
1866
2695
  async killProcess(terminal) {
1867
- if (!this.isRunning(terminal)) return;
2696
+ if (!this.isRunning(terminal) && !terminal.killProcessGroup) return;
1868
2697
  try {
1869
- terminal.process.kill("SIGTERM");
2698
+ await this.signalProcess(terminal, "SIGTERM");
1870
2699
  } catch {
1871
2700
  return;
1872
2701
  }
1873
- if (await Promise.race([terminal.exitPromise.then(() => true), waitMs(this.killGraceMs).then(() => false)]) || !this.isRunning(terminal)) return;
2702
+ if (await this.waitForCleanupAfterSignal(terminal) && !terminal.killProcessGroup) return;
1874
2703
  try {
1875
- terminal.process.kill("SIGKILL");
2704
+ await this.signalProcess(terminal, "SIGKILL");
1876
2705
  } catch {
1877
2706
  return;
1878
2707
  }
1879
- await Promise.race([terminal.exitPromise.then(() => void 0), waitMs(this.killGraceMs)]);
2708
+ await this.waitForCleanupAfterSignal(terminal);
2709
+ }
2710
+ async signalProcess(terminal, signal) {
2711
+ const pid = terminal.process.pid;
2712
+ if (terminal.killProcessGroup && pid && process.platform === "win32") {
2713
+ if (!this.isRunning(terminal)) await terminal.processGroupSnapshotPromise?.catch(() => {});
2714
+ for (const descendantPid of await listDescendantPids(pid)) terminal.descendantPids.add(descendantPid);
2715
+ if (this.isRunning(terminal)) {
2716
+ await killWindowsProcessTree(pid, signal);
2717
+ return;
2718
+ }
2719
+ for (const descendantPid of terminal.descendantPids) await killWindowsProcessTree(descendantPid, signal);
2720
+ return;
2721
+ }
2722
+ if (terminal.killProcessGroup && pid) {
2723
+ if (!this.isRunning(terminal)) await terminal.processGroupSnapshotPromise?.catch(() => {});
2724
+ for (const descendantPid of await listDescendantPids(pid)) terminal.descendantPids.add(descendantPid);
2725
+ if (process.platform !== "win32" && hasLiveProcessGroup(pid)) {
2726
+ sendSignal(-pid, signal);
2727
+ return;
2728
+ }
2729
+ for (const descendantPid of terminal.descendantPids) sendSignal(descendantPid, signal);
2730
+ return;
2731
+ }
2732
+ terminal.process.kill(signal);
2733
+ }
2734
+ async waitForCleanupAfterSignal(terminal) {
2735
+ return await Promise.race([this.waitForTerminalAndTrackedDescendants(terminal).then(() => true), waitMs(this.killGraceMs).then(() => false)]);
2736
+ }
2737
+ async waitForTerminalAndTrackedDescendants(terminal) {
2738
+ await terminal.exitPromise;
2739
+ while (hasLiveTerminalProcessGroup(terminal)) await waitMs(25);
2740
+ while (hasLivePid(terminal.descendantPids)) await waitMs(25);
1880
2741
  }
1881
2742
  };
2743
+ async function spawnTerminalProcess(params, defaultCwd) {
2744
+ const directCommand = buildTerminalSpawnCommand(params.command, params.args);
2745
+ try {
2746
+ return {
2747
+ proc: await spawnAndWait(directCommand, params, defaultCwd),
2748
+ spawnCommand: directCommand
2749
+ };
2750
+ } catch (error) {
2751
+ const fallbackCommand = params.args === void 0 && isNotFoundSpawnError(error) ? buildTerminalFallbackSpawnCommand(params.command, params.cwd ?? defaultCwd) : void 0;
2752
+ if (!fallbackCommand) throw error;
2753
+ return {
2754
+ proc: await spawnAndWait(fallbackCommand, params, defaultCwd),
2755
+ spawnCommand: fallbackCommand
2756
+ };
2757
+ }
2758
+ }
2759
+ async function spawnAndWait(spawnCommand, params, defaultCwd) {
2760
+ const spawnOptions = buildTerminalSpawnOptions(spawnCommand.command, params.cwd ?? defaultCwd, params.env);
2761
+ if (spawnCommand.killProcessGroup) spawnOptions.detached = true;
2762
+ const proc = spawn(spawnCommand.command, spawnCommand.args, spawnOptions);
2763
+ await waitForSpawn(proc);
2764
+ return proc;
2765
+ }
2766
+ function isNotFoundSpawnError(error) {
2767
+ return error instanceof Error && error.code === "ENOENT";
2768
+ }
2769
+ function buildTerminalFallbackSpawnCommand(command, cwd, platform = process.platform) {
2770
+ if (commandPathExists(command, cwd)) return;
2771
+ if (platform === "win32") return hasWindowsShellSyntax(command) || /\s/u.test(command) ? buildTerminalShellSpawnCommand(command, platform) : void 0;
2772
+ if (hasShellSyntax(command) || /\s/u.test(command)) return buildTerminalShellSpawnCommand(command, platform);
2773
+ }
2774
+ function hasShellSyntax(command) {
2775
+ return /[|&;<>()>$`*?[\]{}'"\\\r\n]/u.test(command);
2776
+ }
2777
+ function hasWindowsShellSyntax(command) {
2778
+ return /[|&;<>()>$`*?[\]{}'"\r\n]/u.test(command);
2779
+ }
2780
+ function commandPathExists(command, cwd) {
2781
+ if (!/[\\/]/u.test(command)) return false;
2782
+ const resolvedPath = path.isAbsolute(command) ? command : path.resolve(cwd, command);
2783
+ return fs.existsSync(resolvedPath);
2784
+ }
2785
+ async function listDescendantPids(rootPid) {
2786
+ let output;
2787
+ try {
2788
+ output = await runProcessListCommand();
2789
+ } catch {
2790
+ return [];
2791
+ }
2792
+ const childrenByParent = /* @__PURE__ */ new Map();
2793
+ for (const line of output.split("\n")) {
2794
+ const match = line.trim().match(/^(\d+)\s+(\d+)$/);
2795
+ if (!match) continue;
2796
+ const pid = Number(match[1]);
2797
+ const parentPid = Number(match[2]);
2798
+ if (!Number.isInteger(pid) || !Number.isInteger(parentPid) || pid <= 0 || parentPid <= 0) continue;
2799
+ const children = childrenByParent.get(parentPid);
2800
+ if (children) children.push(pid);
2801
+ else childrenByParent.set(parentPid, [pid]);
2802
+ }
2803
+ const descendants = [];
2804
+ const queue = [...childrenByParent.get(rootPid) ?? []];
2805
+ for (let index = 0; index < queue.length; index += 1) {
2806
+ const pid = queue[index];
2807
+ descendants.push(pid);
2808
+ queue.push(...childrenByParent.get(pid) ?? []);
2809
+ }
2810
+ return descendants;
2811
+ }
2812
+ async function runProcessListCommand() {
2813
+ if (process.platform === "win32") return await runWindowsProcessListCommand();
2814
+ return await new Promise((resolve, reject) => {
2815
+ const child = spawn("ps", ["-eo", "pid=,ppid="], { stdio: [
2816
+ "ignore",
2817
+ "pipe",
2818
+ "pipe"
2819
+ ] });
2820
+ let stdout = "";
2821
+ let stderr = "";
2822
+ child.stdout.setEncoding("utf8");
2823
+ child.stderr.setEncoding("utf8");
2824
+ child.stdout.on("data", (chunk) => {
2825
+ stdout += chunk;
2826
+ });
2827
+ child.stderr.on("data", (chunk) => {
2828
+ stderr += chunk;
2829
+ });
2830
+ child.once("error", reject);
2831
+ child.once("close", (code, signal) => {
2832
+ if (code === 0) {
2833
+ resolve(stdout);
2834
+ return;
2835
+ }
2836
+ reject(/* @__PURE__ */ new Error(`ps exited with code ${code ?? "null"} signal ${signal ?? "null"}: ${stderr}`));
2837
+ });
2838
+ });
2839
+ }
2840
+ async function rememberProcessGroupPids(terminal) {
2841
+ const processGroupId = terminal.process.pid;
2842
+ if (!terminal.killProcessGroup || !processGroupId) return;
2843
+ if (process.platform === "win32") {
2844
+ for (const pid of await listDescendantPids(processGroupId)) terminal.descendantPids.add(pid);
2845
+ return;
2846
+ }
2847
+ for (const pid of await listProcessGroupPids(processGroupId)) if (pid !== processGroupId) terminal.descendantPids.add(pid);
2848
+ }
2849
+ async function listProcessGroupPids(processGroupId) {
2850
+ let output;
2851
+ try {
2852
+ output = await runProcessGroupListCommand();
2853
+ } catch {
2854
+ return [];
2855
+ }
2856
+ const pids = [];
2857
+ for (const line of output.split("\n")) {
2858
+ const match = line.trim().match(/^(\d+)\s+(\d+)$/);
2859
+ if (!match) continue;
2860
+ const pid = Number(match[1]);
2861
+ const pgid = Number(match[2]);
2862
+ if (Number.isInteger(pid) && Number.isInteger(pgid) && pid > 0 && pgid === processGroupId) pids.push(pid);
2863
+ }
2864
+ return pids;
2865
+ }
2866
+ async function runProcessGroupListCommand() {
2867
+ return await new Promise((resolve, reject) => {
2868
+ const child = spawn("ps", ["-eo", "pid=,pgid="], { stdio: [
2869
+ "ignore",
2870
+ "pipe",
2871
+ "pipe"
2872
+ ] });
2873
+ let stdout = "";
2874
+ let stderr = "";
2875
+ child.stdout.setEncoding("utf8");
2876
+ child.stderr.setEncoding("utf8");
2877
+ child.stdout.on("data", (chunk) => {
2878
+ stdout += chunk;
2879
+ });
2880
+ child.stderr.on("data", (chunk) => {
2881
+ stderr += chunk;
2882
+ });
2883
+ child.once("error", reject);
2884
+ child.once("close", (code, signal) => {
2885
+ if (code === 0) {
2886
+ resolve(stdout);
2887
+ return;
2888
+ }
2889
+ reject(/* @__PURE__ */ new Error(`ps exited with code ${code ?? "null"} signal ${signal ?? "null"}: ${stderr}`));
2890
+ });
2891
+ });
2892
+ }
2893
+ async function runWindowsProcessListCommand() {
2894
+ return await new Promise((resolve, reject) => {
2895
+ const child = spawn("powershell.exe", [
2896
+ "-NoProfile",
2897
+ "-NonInteractive",
2898
+ "-Command",
2899
+ ["Get-CimInstance Win32_Process |", "ForEach-Object { \"$($_.ProcessId) $($_.ParentProcessId)\" }"].join(" ")
2900
+ ], {
2901
+ stdio: [
2902
+ "ignore",
2903
+ "pipe",
2904
+ "pipe"
2905
+ ],
2906
+ windowsHide: true
2907
+ });
2908
+ let stdout = "";
2909
+ let stderr = "";
2910
+ child.stdout.setEncoding("utf8");
2911
+ child.stderr.setEncoding("utf8");
2912
+ child.stdout.on("data", (chunk) => {
2913
+ stdout += chunk;
2914
+ });
2915
+ child.stderr.on("data", (chunk) => {
2916
+ stderr += chunk;
2917
+ });
2918
+ child.once("error", reject);
2919
+ child.once("close", (code, signal) => {
2920
+ if (code === 0) {
2921
+ resolve(stdout);
2922
+ return;
2923
+ }
2924
+ reject(/* @__PURE__ */ new Error(`powershell process list exited with code ${code ?? "null"} signal ${signal ?? "null"}: ${stderr}`));
2925
+ });
2926
+ });
2927
+ }
2928
+ async function killWindowsProcessTree(pid, signal) {
2929
+ const args = [
2930
+ "/pid",
2931
+ String(pid),
2932
+ "/t"
2933
+ ];
2934
+ if (signal === "SIGKILL") args.push("/f");
2935
+ await new Promise((resolve) => {
2936
+ const child = spawn("taskkill", args, {
2937
+ stdio: [
2938
+ "ignore",
2939
+ "ignore",
2940
+ "ignore"
2941
+ ],
2942
+ windowsHide: true
2943
+ });
2944
+ child.once("error", () => resolve());
2945
+ child.once("close", () => resolve());
2946
+ });
2947
+ }
2948
+ function sendSignal(pid, signal) {
2949
+ try {
2950
+ process.kill(pid, signal);
2951
+ } catch {}
2952
+ }
2953
+ function hasLiveProcessGroup(processGroupId) {
2954
+ try {
2955
+ process.kill(-processGroupId, 0);
2956
+ return true;
2957
+ } catch {
2958
+ return false;
2959
+ }
2960
+ }
2961
+ function hasLiveTerminalProcessGroup(terminal) {
2962
+ const pid = terminal.process.pid;
2963
+ return Boolean(terminal.killProcessGroup && pid && process.platform !== "win32" && hasLiveProcessGroup(pid));
2964
+ }
2965
+ function hasLivePid(pids) {
2966
+ for (const pid of pids) try {
2967
+ process.kill(pid, 0);
2968
+ return true;
2969
+ } catch {
2970
+ pids.delete(pid);
2971
+ }
2972
+ return false;
2973
+ }
1882
2974
  //#endregion
1883
2975
  //#region src/acp/client.ts
1884
2976
  const REPLAY_IDLE_MS = 80;
@@ -1965,6 +3057,7 @@ var AcpClient = class {
1965
3057
  suppressReplaySessionUpdateMessages = false;
1966
3058
  activePrompt;
1967
3059
  cancellingSessionIds = /* @__PURE__ */ new Set();
3060
+ permissionAbortControllers = /* @__PURE__ */ new Map();
1968
3061
  closing = false;
1969
3062
  agentStartedAt;
1970
3063
  lastAgentExit;
@@ -1981,7 +3074,8 @@ var AcpClient = class {
1981
3074
  onAcpMessage: this.options.onAcpMessage,
1982
3075
  onAcpOutputMessage: this.options.onAcpOutputMessage,
1983
3076
  onSessionUpdate: this.options.onSessionUpdate,
1984
- onClientOperation: this.options.onClientOperation
3077
+ onClientOperation: this.options.onClientOperation,
3078
+ onPermissionEscalation: this.options.onPermissionEscalation
1985
3079
  };
1986
3080
  this.filesystem = new FileSystemHandlers({
1987
3081
  cwd: this.options.cwd,
@@ -2034,6 +3128,7 @@ var AcpClient = class {
2034
3128
  updateRuntimeOptions(options) {
2035
3129
  if (options.permissionMode) this.options.permissionMode = options.permissionMode;
2036
3130
  if (options.nonInteractivePermissions !== void 0) this.options.nonInteractivePermissions = options.nonInteractivePermissions;
3131
+ if (Object.prototype.hasOwnProperty.call(options, "permissionPolicy")) this.options.permissionPolicy = options.permissionPolicy;
2037
3132
  if (options.terminal !== void 0) this.options.terminal = options.terminal;
2038
3133
  if (options.permissionMode || options.nonInteractivePermissions !== void 0) {
2039
3134
  this.filesystem.updatePermissionPolicy(this.options.permissionMode, this.options.nonInteractivePermissions);
@@ -2064,7 +3159,15 @@ var AcpClient = class {
2064
3159
  else this.log(`spawning agent: ${spawnCommand} ${args.join(" ")}`);
2065
3160
  const geminiAcp = isGeminiAcpCommand(spawnCommand, args);
2066
3161
  if (isCopilotAcpCommand(spawnCommand, args)) await ensureCopilotAcpSupport(spawnCommand);
2067
- const spawnedChild = spawn(spawnCommand, args, buildSpawnCommandOptions(spawnCommand, buildAgentSpawnOptions(this.options.cwd, this.options.authCredentials)));
3162
+ const agentSpawnOptions = buildAgentSpawnOptions(this.options.cwd, this.options.authCredentials);
3163
+ if (isClaudeAcpCommand(spawnCommand, args)) {
3164
+ const claudeExe = resolveClaudeCodeExecutable(process.platform, agentSpawnOptions.env);
3165
+ if (claudeExe) {
3166
+ agentSpawnOptions.env.CLAUDE_CODE_EXECUTABLE = claudeExe;
3167
+ this.log(`resolved system Claude Code executable: ${claudeExe}`);
3168
+ }
3169
+ }
3170
+ const spawnedChild = spawn(spawnCommand, args, buildSpawnCommandOptions(spawnCommand, agentSpawnOptions));
2068
3171
  try {
2069
3172
  await waitForSpawn$1(spawnedChild);
2070
3173
  } catch (error) {
@@ -2216,6 +3319,7 @@ var AcpClient = class {
2216
3319
  return {
2217
3320
  sessionId: result.sessionId,
2218
3321
  agentSessionId: extractRuntimeSessionId(result._meta),
3322
+ configOptions: result.configOptions ?? void 0,
2219
3323
  models: result.models ?? void 0
2220
3324
  };
2221
3325
  }
@@ -2245,6 +3349,7 @@ var AcpClient = class {
2245
3349
  this.loadedSessionId = sessionId;
2246
3350
  return {
2247
3351
  agentSessionId: extractRuntimeSessionId(response?._meta),
3352
+ configOptions: response?.configOptions ?? void 0,
2248
3353
  models: response?.models ?? void 0
2249
3354
  };
2250
3355
  }
@@ -2278,6 +3383,7 @@ var AcpClient = class {
2278
3383
  restoreConsoleError?.();
2279
3384
  if (this.activePrompt?.promise === promptPromise) this.activePrompt = void 0;
2280
3385
  this.cancellingSessionIds.delete(sessionId);
3386
+ this.abortAndDropPermissionSignal(sessionId);
2281
3387
  this.promptPermissionFailures.delete(sessionId);
2282
3388
  }
2283
3389
  }
@@ -2323,11 +3429,12 @@ var AcpClient = class {
2323
3429
  async cancel(sessionId) {
2324
3430
  const connection = this.getConnection();
2325
3431
  this.cancellingSessionIds.add(sessionId);
3432
+ this.abortAndDropPermissionSignal(sessionId);
2326
3433
  await this.runConnectionRequest(() => connection.cancel({ sessionId }));
2327
3434
  }
2328
3435
  async closeSession(sessionId) {
2329
3436
  const connection = this.getConnection();
2330
- await this.runConnectionRequest(() => connection.unstable_closeNes({ sessionId }));
3437
+ await this.runConnectionRequest(() => connection.closeSession({ sessionId }));
2331
3438
  if (this.loadedSessionId === sessionId) this.loadedSessionId = void 0;
2332
3439
  }
2333
3440
  async requestCancelActivePrompt() {
@@ -2369,6 +3476,8 @@ var AcpClient = class {
2369
3476
  this.suppressReplaySessionUpdateMessages = false;
2370
3477
  this.activePrompt = void 0;
2371
3478
  this.cancellingSessionIds.clear();
3479
+ for (const controller of this.permissionAbortControllers.values()) controller.abort();
3480
+ this.permissionAbortControllers.clear();
2372
3481
  this.promptPermissionFailures.clear();
2373
3482
  this.loadedSessionId = void 0;
2374
3483
  this.initResult = void 0;
@@ -2517,9 +3626,36 @@ var AcpClient = class {
2517
3626
  }
2518
3627
  async handlePermissionRequest(params) {
2519
3628
  if (this.cancellingSessionIds.has(params.sessionId)) return { outcome: { outcome: "cancelled" } };
3629
+ if (this.options.onPermissionRequest) {
3630
+ const signal = this.cancellationSignalForSession(params.sessionId);
3631
+ try {
3632
+ const decision = await this.options.onPermissionRequest({
3633
+ sessionId: params.sessionId,
3634
+ raw: params,
3635
+ inferredKind: inferToolKind(params)
3636
+ }, { signal });
3637
+ if (signal.aborted || this.cancellingSessionIds.has(params.sessionId)) {
3638
+ this.recordPermissionDecision("cancelled");
3639
+ return { outcome: { outcome: "cancelled" } };
3640
+ }
3641
+ if (decision) {
3642
+ const response = decisionToResponse(params, decision);
3643
+ this.recordPermissionDecision(classifyPermissionDecision(params, response));
3644
+ return response;
3645
+ }
3646
+ } catch (error) {
3647
+ if (signal.aborted || this.cancellingSessionIds.has(params.sessionId)) {
3648
+ this.recordPermissionDecision("cancelled");
3649
+ return { outcome: { outcome: "cancelled" } };
3650
+ }
3651
+ this.log(`onPermissionRequest threw, falling through to mode-based resolver: ${error instanceof Error ? error.message : String(error)}`);
3652
+ }
3653
+ }
2520
3654
  let response;
2521
3655
  try {
2522
- response = await resolvePermissionRequest(params, this.options.permissionMode, this.options.nonInteractivePermissions ?? "deny");
3656
+ const result = await resolvePermissionRequestWithDetails(params, this.options.permissionMode, this.options.nonInteractivePermissions ?? "deny", this.options.permissionPolicy);
3657
+ response = result.response;
3658
+ if (result.escalation) this.eventHandlers.onPermissionEscalation?.(result.escalation);
2523
3659
  } catch (error) {
2524
3660
  if (error instanceof PermissionPromptUnavailableError) {
2525
3661
  this.notePromptPermissionFailure(params.sessionId, error);
@@ -2625,6 +3761,21 @@ var AcpClient = class {
2625
3761
  async handleReleaseTerminal(params) {
2626
3762
  return await this.terminalManager.releaseTerminal(params);
2627
3763
  }
3764
+ cancellationSignalForSession(sessionId) {
3765
+ let controller = this.permissionAbortControllers.get(sessionId);
3766
+ if (!controller) {
3767
+ controller = new AbortController();
3768
+ this.permissionAbortControllers.set(sessionId, controller);
3769
+ }
3770
+ return controller.signal;
3771
+ }
3772
+ abortAndDropPermissionSignal(sessionId) {
3773
+ const controller = this.permissionAbortControllers.get(sessionId);
3774
+ if (controller) {
3775
+ controller.abort();
3776
+ this.permissionAbortControllers.delete(sessionId);
3777
+ }
3778
+ }
2628
3779
  recordPermissionDecision(decision) {
2629
3780
  this.permissionStats.requested += 1;
2630
3781
  if (decision === "approved") {
@@ -2686,6 +3837,47 @@ var AcpClient = class {
2686
3837
  }
2687
3838
  };
2688
3839
  //#endregion
3840
+ //#region src/runtime/engine/session-options.ts
3841
+ function mergeSessionOptions(preferred, fallback) {
3842
+ const merged = { ...fallback };
3843
+ if (preferred?.model !== void 0) merged.model = preferred.model;
3844
+ if (preferred?.allowedTools !== void 0) merged.allowedTools = preferred.allowedTools;
3845
+ if (preferred?.maxTurns !== void 0) merged.maxTurns = preferred.maxTurns;
3846
+ if (preferred?.systemPrompt !== void 0) merged.systemPrompt = preferred.systemPrompt;
3847
+ return Object.keys(merged).length > 0 ? merged : void 0;
3848
+ }
3849
+ function persistSessionOptions(record, options) {
3850
+ const systemPromptOption = options?.systemPrompt;
3851
+ const normalizedSystemPrompt = typeof systemPromptOption === "string" && systemPromptOption.length > 0 ? systemPromptOption : systemPromptOption && typeof systemPromptOption === "object" && typeof systemPromptOption.append === "string" && systemPromptOption.append.length > 0 ? { append: systemPromptOption.append } : void 0;
3852
+ const next = options && {
3853
+ model: typeof options.model === "string" ? options.model : void 0,
3854
+ allowed_tools: Array.isArray(options.allowedTools) ? [...options.allowedTools] : void 0,
3855
+ max_turns: typeof options.maxTurns === "number" ? options.maxTurns : void 0,
3856
+ system_prompt: normalizedSystemPrompt
3857
+ };
3858
+ if (Boolean(next && (typeof next.model === "string" && next.model.trim().length > 0 || Array.isArray(next.allowed_tools) || typeof next.max_turns === "number" || next.system_prompt !== void 0)) && next) {
3859
+ record.acpx = {
3860
+ ...record.acpx,
3861
+ session_options: next
3862
+ };
3863
+ return;
3864
+ }
3865
+ if (!record.acpx) return;
3866
+ delete record.acpx.session_options;
3867
+ }
3868
+ function sessionOptionsFromRecord(record) {
3869
+ const stored = record.acpx?.session_options;
3870
+ if (!stored) return;
3871
+ const sessionOptions = {};
3872
+ if (typeof stored.model === "string" && stored.model.trim().length > 0) sessionOptions.model = stored.model;
3873
+ if (Array.isArray(stored.allowed_tools)) sessionOptions.allowedTools = [...stored.allowed_tools];
3874
+ if (typeof stored.max_turns === "number") sessionOptions.maxTurns = stored.max_turns;
3875
+ const storedSystemPrompt = stored.system_prompt;
3876
+ if (typeof storedSystemPrompt === "string" && storedSystemPrompt.length > 0) sessionOptions.systemPrompt = storedSystemPrompt;
3877
+ else if (storedSystemPrompt && typeof storedSystemPrompt === "object" && typeof storedSystemPrompt.append === "string" && storedSystemPrompt.append.length > 0) sessionOptions.systemPrompt = { append: storedSystemPrompt.append };
3878
+ return Object.keys(sessionOptions).length > 0 ? sessionOptions : void 0;
3879
+ }
3880
+ //#endregion
2689
3881
  //#region src/session/conversation-model.ts
2690
3882
  const MAX_RUNTIME_MESSAGES = 200;
2691
3883
  const MAX_RUNTIME_AGENT_TEXT_CHARS = 8e3;
@@ -3061,6 +4253,15 @@ function trimConversationForRuntime(conversation) {
3061
4253
  if (requestUsageEntries.length > MAX_RUNTIME_REQUEST_TOKEN_USAGE) conversation.request_token_usage = Object.fromEntries(requestUsageEntries.slice(-MAX_RUNTIME_REQUEST_TOKEN_USAGE));
3062
4254
  }
3063
4255
  //#endregion
4256
+ //#region src/session/config-options.ts
4257
+ function applyConfigOptionsToRecord(record, result) {
4258
+ const configOptions = result?.configOptions;
4259
+ if (!configOptions) return;
4260
+ const acpxState = cloneSessionAcpxState(record.acpx) ?? {};
4261
+ acpxState.config_options = structuredClone(configOptions);
4262
+ record.acpx = acpxState;
4263
+ }
4264
+ //#endregion
3064
4265
  //#region src/session/mode-preference.ts
3065
4266
  function ensureAcpxState(state) {
3066
4267
  return state ?? {};
@@ -3156,6 +4357,22 @@ function assertRequestedModelSupported(params) {
3156
4357
  if (!new Set(params.models.availableModels.map((model) => model.modelId)).has(params.requestedModel)) throw new RequestedModelUnsupportedError(`Cannot ${params.context === "replay" ? "replay saved model" : "apply --model"} "${params.requestedModel}": the ACP agent did not advertise that model. Available models: ${formatAvailableModelIds(params.models)}.`);
3157
4358
  }
3158
4359
  //#endregion
4360
+ //#region src/session/model-application.ts
4361
+ async function applyRequestedModelIfAdvertised(params) {
4362
+ const requestedModel = typeof params.requestedModel === "string" ? params.requestedModel.trim() : "";
4363
+ if (!requestedModel) return false;
4364
+ assertRequestedModelSupported({
4365
+ requestedModel,
4366
+ models: params.models,
4367
+ agentCommand: params.agentCommand,
4368
+ context: "apply"
4369
+ });
4370
+ if (!params.models) return false;
4371
+ if (params.models.currentModelId === requestedModel) return true;
4372
+ await withTimeout(params.client.setSessionModel(params.sessionId, requestedModel), params.timeoutMs);
4373
+ return true;
4374
+ }
4375
+ //#endregion
3159
4376
  //#region src/runtime/engine/lifecycle.ts
3160
4377
  function applyLifecycleSnapshotToRecord(record, snapshot) {
3161
4378
  if (!snapshot) return;
@@ -3296,6 +4513,7 @@ async function connectAndLoadSession(options) {
3296
4513
  else if (client.supportsLoadSession()) try {
3297
4514
  const loadResult = await withTimeout(client.loadSessionWithOptions(record.acpSessionId, record.cwd, { suppressReplayUpdates: true }), options.timeoutMs);
3298
4515
  reconcileAgentSessionId(record, loadResult.agentSessionId);
4516
+ applyConfigOptionsToRecord(record, loadResult);
3299
4517
  sessionModels = loadResult.models;
3300
4518
  resumed = true;
3301
4519
  } catch (error) {
@@ -3310,6 +4528,7 @@ async function connectAndLoadSession(options) {
3310
4528
  sessionId = createdSession.sessionId;
3311
4529
  createdFreshSession = true;
3312
4530
  pendingAgentSessionId = createdSession.agentSessionId;
4531
+ applyConfigOptionsToRecord(record, createdSession);
3313
4532
  sessionModels = createdSession.models;
3314
4533
  }
3315
4534
  else {
@@ -3321,6 +4540,7 @@ async function connectAndLoadSession(options) {
3321
4540
  sessionId = createdSession.sessionId;
3322
4541
  createdFreshSession = true;
3323
4542
  pendingAgentSessionId = createdSession.agentSessionId;
4543
+ applyConfigOptionsToRecord(record, createdSession);
3324
4544
  sessionModels = createdSession.models;
3325
4545
  }
3326
4546
  if (createdFreshSession) {
@@ -3374,28 +4594,6 @@ async function connectAndLoadSession(options) {
3374
4594
  };
3375
4595
  }
3376
4596
  //#endregion
3377
- //#region src/runtime/engine/session-options.ts
3378
- function mergeSessionOptions(preferred, fallback) {
3379
- const merged = { ...fallback };
3380
- if (preferred?.model !== void 0) merged.model = preferred.model;
3381
- if (preferred?.allowedTools !== void 0) merged.allowedTools = preferred.allowedTools;
3382
- if (preferred?.maxTurns !== void 0) merged.maxTurns = preferred.maxTurns;
3383
- if (preferred?.systemPrompt !== void 0) merged.systemPrompt = preferred.systemPrompt;
3384
- return Object.keys(merged).length > 0 ? merged : void 0;
3385
- }
3386
- function sessionOptionsFromRecord(record) {
3387
- const stored = record.acpx?.session_options;
3388
- if (!stored) return;
3389
- const sessionOptions = {};
3390
- if (typeof stored.model === "string" && stored.model.trim().length > 0) sessionOptions.model = stored.model;
3391
- if (Array.isArray(stored.allowed_tools)) sessionOptions.allowedTools = [...stored.allowed_tools];
3392
- if (typeof stored.max_turns === "number") sessionOptions.maxTurns = stored.max_turns;
3393
- const storedSystemPrompt = stored.system_prompt;
3394
- if (typeof storedSystemPrompt === "string" && storedSystemPrompt.length > 0) sessionOptions.systemPrompt = storedSystemPrompt;
3395
- else if (storedSystemPrompt && typeof storedSystemPrompt === "object" && typeof storedSystemPrompt.append === "string" && storedSystemPrompt.append.length > 0) sessionOptions.systemPrompt = { append: storedSystemPrompt.append };
3396
- return Object.keys(sessionOptions).length > 0 ? sessionOptions : void 0;
3397
- }
3398
- //#endregion
3399
4597
  //#region src/runtime/engine/connected-session.ts
3400
4598
  function createActiveSessionController(params) {
3401
4599
  const getActiveSessionId = () => params.getActiveSessionId();
@@ -3421,6 +4619,7 @@ async function withConnectedSession(options) {
3421
4619
  mcpServers: options.mcpServers,
3422
4620
  permissionMode: options.permissionMode ?? "approve-reads",
3423
4621
  nonInteractivePermissions: options.nonInteractivePermissions,
4622
+ onPermissionRequest: options.onPermissionRequest,
3424
4623
  authCredentials: options.authCredentials,
3425
4624
  authPolicy: options.authPolicy,
3426
4625
  terminal: options.terminal,
@@ -3432,6 +4631,7 @@ async function withConnectedSession(options) {
3432
4631
  mcpServers: options.mcpServers,
3433
4632
  permissionMode: options.permissionMode ?? "approve-reads",
3434
4633
  nonInteractivePermissions: options.nonInteractivePermissions,
4634
+ onPermissionRequest: options.onPermissionRequest,
3435
4635
  authCredentials: options.authCredentials,
3436
4636
  authPolicy: options.authPolicy,
3437
4637
  terminal: options.terminal,
@@ -3532,6 +4732,59 @@ async function runPromptTurn(params) {
3532
4732
  }
3533
4733
  }
3534
4734
  //#endregion
3535
- export { listSessions as A, sessionEventActivePath as B, permissionModeSatisfies as C, findSession as D, findGitRepositoryRoot as E, writeSessionRecord as F, InterruptedError as G, sessionEventSegmentPath as H, parseSessionRecord as I, withTimeout as J, TimeoutError as K, DEFAULT_EVENT_SEGMENT_MAX_BYTES as L, normalizeName as M, pruneSessions as N, findSessionByDirectoryWalk as O, resolveSessionRecord as P, resolveAgentCommand as Q, defaultSessionEventLog as R, AcpClient as S, absolutePath as T, assertPersistedKeyPolicy as U, sessionEventLockPath as V, serializeSessionRecordForDisk as W, listBuiltInAgents as X, DEFAULT_AGENT_NAME as Y, normalizeAgentName$1 as Z, createSessionConversation as _, connectAndLoadSession as a, recordSessionUpdate as b, reconcileAgentSessionId as c, setDesiredConfigOption as d, setDesiredModeId as f, cloneSessionConversation as g, cloneSessionAcpxState as h, sessionOptionsFromRecord as i, listSessionsForAgent as j, isoNow$2 as k, assertRequestedModelSupported as l, syncAdvertisedModelState as m, withConnectedSession as n, applyConversation as o, setDesiredModelId as p, withInterrupt as q, mergeSessionOptions as r, applyLifecycleSnapshotToRecord as s, runPromptTurn as t, setCurrentModelId as u, recordClientOperation as v, DEFAULT_HISTORY_LIMIT as w, trimConversationForRuntime as x, recordPromptSubmission as y, sessionBaseDir$1 as z };
4735
+ //#region src/session/live-checkpoint.ts
4736
+ const DEFAULT_LIVE_CHECKPOINT_INTERVAL_MS = 500;
4737
+ var LiveSessionCheckpoint = class {
4738
+ save;
4739
+ intervalMs;
4740
+ onError;
4741
+ dirty = false;
4742
+ flushing;
4743
+ timer;
4744
+ constructor(options) {
4745
+ this.save = options.save;
4746
+ this.intervalMs = options.intervalMs ?? DEFAULT_LIVE_CHECKPOINT_INTERVAL_MS;
4747
+ this.onError = options.onError;
4748
+ }
4749
+ request() {
4750
+ this.dirty = true;
4751
+ if (this.timer) return;
4752
+ this.timer = setTimeout(() => {
4753
+ this.timer = void 0;
4754
+ this.flush().catch((error) => {
4755
+ this.onError?.(error);
4756
+ });
4757
+ }, this.intervalMs);
4758
+ this.timer.unref?.();
4759
+ }
4760
+ async checkpoint() {
4761
+ this.dirty = true;
4762
+ await this.flush();
4763
+ }
4764
+ async flush() {
4765
+ if (this.timer) {
4766
+ clearTimeout(this.timer);
4767
+ this.timer = void 0;
4768
+ }
4769
+ if (this.flushing) {
4770
+ await this.flushing;
4771
+ if (!this.dirty) return;
4772
+ }
4773
+ this.flushing = this.flushDirty();
4774
+ try {
4775
+ await this.flushing;
4776
+ } finally {
4777
+ this.flushing = void 0;
4778
+ }
4779
+ }
4780
+ async flushDirty() {
4781
+ while (this.dirty) {
4782
+ this.dirty = false;
4783
+ await this.save();
4784
+ }
4785
+ }
4786
+ };
4787
+ //#endregion
4788
+ export { getPerfMetricsSnapshot as $, parsePromptStopReason as A, EXIT_CODES as At, normalizeName as B, mergeSessionOptions as C, formatErrorMessage as Ct, extractSessionUpdateNotification as D, isAcpResourceNotFoundError as Dt, AcpClient as E, extractAcpError as Et, findSession as F, PERMISSION_MODES as Ft, DEFAULT_EVENT_SEGMENT_MAX_BYTES as G, resolveSessionRecord as H, findSessionByDirectoryWalk as I, PERMISSION_POLICY_ACTIONS as It, sessionEventActivePath as J, defaultSessionEventLog as K, isoNow$2 as L, SESSION_RECORD_SCHEMA as Lt, DEFAULT_HISTORY_LIMIT as M, OUTPUT_ERROR_CODES as Mt, absolutePath as N, OUTPUT_ERROR_ORIGINS as Nt, isAcpJsonRpcMessage as O, toAcpErrorPayload as Ot, findGitRepositoryRoot as P, OUTPUT_FORMATS as Pt, formatPerfMetric as Q, listSessions as R, QueueConnectionError as Rt, trimConversationForRuntime as S, exitCodeForOutputErrorCode as St, sessionOptionsFromRecord as T, normalizeOutputError as Tt, writeSessionRecord as U, pruneSessions as V, parseSessionRecord as W, sessionEventSegmentPath as X, sessionEventLockPath as Y, assertPersistedKeyPolicy as Z, cloneSessionConversation as _, withTimeout as _t, applyConversation as a, startPerfTimer as at, recordPromptSubmission as b, normalizeAgentName$1 as bt, applyRequestedModelIfAdvertised as c, PromptInputValidationError as ct, setDesiredConfigOption as d, parsePromptSource as dt, incrementPerfCounter as et, setDesiredModeId as f, promptToDisplayText as ft, cloneSessionAcpxState as g, withInterrupt as gt, applyConfigOptionsToRecord as h, TimeoutError as ht, connectAndLoadSession as i, setPerfGauge as it, permissionModeSatisfies as j, NON_INTERACTIVE_PERMISSION_POLICIES as jt, parseJsonRpcErrorMessage as k, AUTH_POLICIES as kt, assertRequestedModelSupported as l, isPromptInput as lt, syncAdvertisedModelState as m, InterruptedError as mt, runPromptTurn as n, recordPerfDuration as nt, applyLifecycleSnapshotToRecord as o, serializeSessionRecordForDisk as ot, setDesiredModelId as p, textPrompt as pt, sessionBaseDir$1 as q, withConnectedSession as r, resetPerfMetrics as rt, reconcileAgentSessionId as s, normalizeRuntimeSessionId as st, LiveSessionCheckpoint as t, measurePerf as tt, setCurrentModelId as u, mergePromptSourceWithText as ut, createSessionConversation as v, DEFAULT_AGENT_NAME as vt, persistSessionOptions as w, isRetryablePromptError as wt, recordSessionUpdate as x, resolveAgentCommand as xt, recordClientOperation as y, listBuiltInAgents as yt, listSessionsForAgent as z, QueueProtocolError as zt };
3536
4789
 
3537
- //# sourceMappingURL=prompt-turn-BY5SwU1F.js.map
4790
+ //# sourceMappingURL=live-checkpoint-B9ctAuqV.js.map