acpx 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.
Files changed (34) hide show
  1. package/README.md +7 -4
  2. package/dist/{cli-BGYGVo3b.js → cli-Bf3yjqzE.js} +4 -4
  3. package/dist/{cli-BGYGVo3b.js.map → cli-Bf3yjqzE.js.map} +1 -1
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +545 -247
  7. package/dist/cli.js.map +1 -1
  8. package/dist/{client-FzXPdgP7.d.ts → client-BssohYqM.d.ts} +30 -3
  9. package/dist/client-BssohYqM.d.ts.map +1 -0
  10. package/dist/{flags-D706STfk.js → flags-C-rwARqg.js} +96 -39
  11. package/dist/flags-C-rwARqg.js.map +1 -0
  12. package/dist/{flows-hcjHmU7P.js → flows-WLs26_5Y.js} +400 -335
  13. package/dist/flows-WLs26_5Y.js.map +1 -0
  14. package/dist/flows.d.ts +21 -1
  15. package/dist/flows.d.ts.map +1 -1
  16. package/dist/flows.js +1 -1
  17. package/dist/{live-checkpoint-B9ctAuqV.js → live-checkpoint-D5d-K9s1.js} +1355 -700
  18. package/dist/live-checkpoint-D5d-K9s1.js.map +1 -0
  19. package/dist/{output-BL9XRWzS.js → output-DPg20dvn.js} +1151 -717
  20. package/dist/output-DPg20dvn.js.map +1 -0
  21. package/dist/runtime.d.ts +30 -2
  22. package/dist/runtime.d.ts.map +1 -1
  23. package/dist/runtime.js +579 -425
  24. package/dist/runtime.js.map +1 -1
  25. package/dist/{session-options-BJyG6zEH.d.ts → session-options-CFudjdkU.d.ts} +7 -1
  26. package/dist/session-options-CFudjdkU.d.ts.map +1 -0
  27. package/package.json +15 -12
  28. package/skills/acpx/SKILL.md +11 -3
  29. package/dist/client-FzXPdgP7.d.ts.map +0 -1
  30. package/dist/flags-D706STfk.js.map +0 -1
  31. package/dist/flows-hcjHmU7P.js.map +0 -1
  32. package/dist/live-checkpoint-B9ctAuqV.js.map +0 -1
  33. package/dist/output-BL9XRWzS.js.map +0 -1
  34. package/dist/session-options-BJyG6zEH.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- import { $ as getPerfMetricsSnapshot, A as parsePromptStopReason, B as normalizeName, C as mergeSessionOptions, Ct as formatErrorMessage, D as extractSessionUpdateNotification, E as AcpClient, F as findSession, H as resolveSessionRecord, I as findSessionByDirectoryWalk, J as sessionEventActivePath, K as defaultSessionEventLog, L as isoNow, Mt as OUTPUT_ERROR_CODES, N as absolutePath, Nt as OUTPUT_ERROR_ORIGINS, O as isAcpJsonRpcMessage, Ot as toAcpErrorPayload, P as findGitRepositoryRoot, Q as formatPerfMetric, R as listSessions, Rt as QueueConnectionError, S as trimConversationForRuntime, T as sessionOptionsFromRecord, Tt as normalizeOutputError, U as writeSessionRecord, V as pruneSessions, X as sessionEventSegmentPath, Y as sessionEventLockPath, _ as cloneSessionConversation, _t as withTimeout, a as applyConversation, at as startPerfTimer, b as recordPromptSubmission, c as applyRequestedModelIfAdvertised, d as setDesiredConfigOption, et as incrementPerfCounter, f as setDesiredModeId, ft as promptToDisplayText, g as cloneSessionAcpxState, gt as withInterrupt, h as applyConfigOptionsToRecord, ht as TimeoutError, i as connectAndLoadSession, it as setPerfGauge, k as parseJsonRpcErrorMessage, l as assertRequestedModelSupported, lt as isPromptInput, m as syncAdvertisedModelState, mt as InterruptedError, n as runPromptTurn, nt as recordPerfDuration, o as applyLifecycleSnapshotToRecord, p as setDesiredModelId, pt as textPrompt, q as sessionBaseDir, r as withConnectedSession, rt as resetPerfMetrics, st as normalizeRuntimeSessionId, t as LiveSessionCheckpoint, tt as measurePerf, u as setCurrentModelId, v as createSessionConversation, w as persistSessionOptions, wt as isRetryablePromptError, x as recordSessionUpdate, y as recordClientOperation, z as listSessionsForAgent, zt as QueueProtocolError } from "./live-checkpoint-B9ctAuqV.js";
1
+ import { $ as getPerfMetricsSnapshot, A as parsePromptStopReason, B as normalizeName, Bt as QueueProtocolError, C as applyConversation, Ct as formatErrorMessage, D as extractSessionUpdateNotification, E as AcpClient, F as findSession, H as resolveSessionRecord, I as findSessionByDirectoryWalk, J as sessionEventActivePath, K as defaultSessionEventLog, L as isoNow, Mt as OUTPUT_ERROR_CODES, N as absolutePath, Nt as OUTPUT_ERROR_ORIGINS, O as isAcpJsonRpcMessage, Ot as toAcpErrorPayload, P as findGitRepositoryRoot, Q as formatPerfMetric, R as listSessions, S as sessionOptionsFromRecord, Tt as normalizeOutputError, U as writeSessionRecord, V as pruneSessions, X as sessionEventSegmentPath, Y as sessionEventLockPath, _ as recordPromptSubmission, _t as withTimeout, a as applyRequestedModelIfAdvertised, at as startPerfTimer, b as mergeSessionOptions, c as setDesiredConfigOption, d as syncAdvertisedModelState, et as incrementPerfCounter, f as applyConfigOptionsToRecord, ft as promptToDisplayText, g as recordClientOperation, gt as withInterrupt, h as createSessionConversation, ht as TimeoutError, i as connectAndLoadSession, it as setPerfGauge, k as parseJsonRpcErrorMessage, l as setDesiredModeId, lt as isPromptInput, m as cloneSessionConversation, mt as InterruptedError, n as runPromptTurn, nt as recordPerfDuration, o as assertRequestedModelSupported, p as cloneSessionAcpxState, pt as textPrompt, q as sessionBaseDir, r as withConnectedSession, rt as resetPerfMetrics, s as setCurrentModelId, st as normalizeRuntimeSessionId, t as LiveSessionCheckpoint, tt as measurePerf, u as setDesiredModelId, v as recordSessionUpdate, w as applyLifecycleSnapshotToRecord, wt as isRetryablePromptError, x as persistSessionOptions, y as trimConversationForRuntime, z as listSessionsForAgent, zt as QueueConnectionError } from "./live-checkpoint-D5d-K9s1.js";
2
2
  import fs, { realpathSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import fs$1 from "node:fs/promises";
@@ -26,6 +26,17 @@ function normalizeQueueOwnerTtlMs(ttlMs) {
26
26
  return Math.round(ttlMs);
27
27
  }
28
28
  //#endregion
29
+ //#region src/process-liveness.ts
30
+ function isProcessAlive(pid) {
31
+ if (!pid || !Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
32
+ try {
33
+ process.kill(pid, 0);
34
+ return true;
35
+ } catch {
36
+ return false;
37
+ }
38
+ }
39
+ //#endregion
29
40
  //#region src/cli/queue/paths.ts
30
41
  function shortHash(value, length) {
31
42
  return createHash("sha256").update(value).digest("hex").slice(0, length);
@@ -56,7 +67,7 @@ const QUEUE_OWNER_STALE_HEARTBEAT_MS = 15e3;
56
67
  function parseQueueOwnerRecord(raw) {
57
68
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
58
69
  const record = raw;
59
- if (!Number.isInteger(record.pid) || record.pid <= 0 || typeof record.sessionId !== "string" || typeof record.socketPath !== "string" || typeof record.createdAt !== "string" || typeof record.heartbeatAt !== "string" || !Number.isInteger(record.ownerGeneration) || record.ownerGeneration <= 0 || !Number.isInteger(record.queueDepth) || record.queueDepth < 0) return null;
70
+ if (!hasValidQueueOwnerRecordFields(record)) return null;
60
71
  return {
61
72
  pid: record.pid,
62
73
  sessionId: record.sessionId,
@@ -67,6 +78,15 @@ function parseQueueOwnerRecord(raw) {
67
78
  queueDepth: record.queueDepth
68
79
  };
69
80
  }
81
+ function hasValidQueueOwnerRecordFields(record) {
82
+ return isPositiveInteger(record.pid) && typeof record.sessionId === "string" && typeof record.socketPath === "string" && typeof record.createdAt === "string" && typeof record.heartbeatAt === "string" && isPositiveInteger(record.ownerGeneration) && isNonNegativeInteger(record.queueDepth);
83
+ }
84
+ function isPositiveInteger(value) {
85
+ return Number.isInteger(value) && value > 0;
86
+ }
87
+ function isNonNegativeInteger(value) {
88
+ return Number.isInteger(value) && value >= 0;
89
+ }
70
90
  function createOwnerGeneration() {
71
91
  return randomInt(1, 2 ** 48);
72
92
  }
@@ -126,15 +146,6 @@ async function readQueueOwnerRecord(sessionId) {
126
146
  return;
127
147
  }
128
148
  }
129
- function isProcessAlive(pid) {
130
- if (!pid || !Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
131
- try {
132
- process.kill(pid, 0);
133
- return true;
134
- } catch {
135
- return false;
136
- }
137
- }
138
149
  async function terminateProcess(pid) {
139
150
  if (!isProcessAlive(pid)) return false;
140
151
  try {
@@ -351,18 +362,22 @@ function isNonInteractivePermissionPolicy(value) {
351
362
  return value === "deny" || value === "fail";
352
363
  }
353
364
  function isPermissionPolicy(value) {
354
- if (value == null) return false;
355
- if (typeof value !== "object" || Array.isArray(value)) return false;
356
- const record = value;
365
+ const record = asRecord$2(value);
366
+ if (!record) return false;
367
+ return hasValidPermissionRuleLists(record) && hasValidPermissionDefaultAction(record);
368
+ }
369
+ function hasValidPermissionRuleLists(record) {
357
370
  for (const key of [
358
371
  "autoApprove",
359
372
  "autoDeny",
360
373
  "escalate"
361
- ]) {
362
- const entry = record[key];
363
- if (entry == null) continue;
364
- if (!Array.isArray(entry) || entry.some((item) => typeof item !== "string")) return false;
365
- }
374
+ ]) if (!isOptionalStringList(record[key])) return false;
375
+ return true;
376
+ }
377
+ function isOptionalStringList(value) {
378
+ return value == null || Array.isArray(value) && value.every((item) => typeof item === "string");
379
+ }
380
+ function hasValidPermissionDefaultAction(record) {
366
381
  return record.defaultAction == null || record.defaultAction === "approve" || record.defaultAction === "deny" || record.defaultAction === "escalate";
367
382
  }
368
383
  function isOutputErrorCode(value) {
@@ -373,35 +388,58 @@ function isOutputErrorOrigin(value) {
373
388
  }
374
389
  function isPermissionEscalationEvent(value) {
375
390
  const event = asRecord$2(value);
376
- return event?.type === "permission_escalation" && typeof event.sessionId === "string" && typeof event.toolCallId === "string" && typeof event.toolTitle === "string" && event.action === "escalate" && typeof event.message === "string" && typeof event.timestamp === "string" && (event.toolName == null || typeof event.toolName === "string") && (event.toolKind == null || typeof event.toolKind === "string") && (event.matchedRule == null || typeof event.matchedRule === "string");
391
+ return !!event && hasRequiredPermissionEscalationFields(event) && hasOptionalStringFields(event, [
392
+ "toolName",
393
+ "toolKind",
394
+ "matchedRule"
395
+ ]);
396
+ }
397
+ function hasRequiredPermissionEscalationFields(event) {
398
+ return event.type === "permission_escalation" && typeof event.sessionId === "string" && typeof event.toolCallId === "string" && typeof event.toolTitle === "string" && event.action === "escalate" && typeof event.message === "string" && typeof event.timestamp === "string";
399
+ }
400
+ function hasOptionalStringFields(record, keys) {
401
+ return keys.every((key) => record[key] == null || typeof record[key] === "string");
377
402
  }
378
403
  function parseSessionOptions(value) {
379
404
  if (value == null) return;
380
405
  const record = asRecord$2(value);
381
406
  if (!record) return null;
382
407
  const sessionOptions = {};
383
- if (record.model != null) {
384
- if (typeof record.model !== "string" || record.model.trim().length === 0) return null;
385
- sessionOptions.model = record.model;
386
- }
387
- if (record.allowedTools != null) {
388
- if (!Array.isArray(record.allowedTools)) return null;
389
- const allowedTools = record.allowedTools.filter((tool) => typeof tool === "string");
390
- if (allowedTools.length !== record.allowedTools.length) return null;
391
- sessionOptions.allowedTools = allowedTools;
392
- }
393
- if (record.maxTurns != null) {
394
- if (typeof record.maxTurns !== "number" || !Number.isFinite(record.maxTurns)) return null;
395
- sessionOptions.maxTurns = Math.max(1, Math.round(record.maxTurns));
396
- }
397
- if (record.systemPrompt != null) if (typeof record.systemPrompt === "string") sessionOptions.systemPrompt = record.systemPrompt;
398
- else {
399
- const systemPrompt = asRecord$2(record.systemPrompt);
400
- if (!systemPrompt || typeof systemPrompt.append !== "string") return null;
401
- sessionOptions.systemPrompt = { append: systemPrompt.append };
402
- }
408
+ if (!assignSessionModel(sessionOptions, record.model)) return null;
409
+ if (!assignSessionAllowedTools(sessionOptions, record.allowedTools)) return null;
410
+ if (!assignSessionMaxTurns(sessionOptions, record.maxTurns)) return null;
411
+ if (!assignSessionSystemPrompt(sessionOptions, record.systemPrompt)) return null;
403
412
  return sessionOptions;
404
413
  }
414
+ function assignSessionModel(options, value) {
415
+ if (value == null) return true;
416
+ if (typeof value !== "string" || value.trim().length === 0) return false;
417
+ options.model = value;
418
+ return true;
419
+ }
420
+ function assignSessionAllowedTools(options, value) {
421
+ if (value == null) return true;
422
+ if (!Array.isArray(value) || value.some((tool) => typeof tool !== "string")) return false;
423
+ options.allowedTools = value;
424
+ return true;
425
+ }
426
+ function assignSessionMaxTurns(options, value) {
427
+ if (value == null) return true;
428
+ if (typeof value !== "number" || !Number.isFinite(value)) return false;
429
+ options.maxTurns = Math.max(1, Math.round(value));
430
+ return true;
431
+ }
432
+ function assignSessionSystemPrompt(options, value) {
433
+ if (value == null) return true;
434
+ if (typeof value === "string") {
435
+ options.systemPrompt = value;
436
+ return true;
437
+ }
438
+ const systemPrompt = asRecord$2(value);
439
+ if (!systemPrompt || typeof systemPrompt.append !== "string") return false;
440
+ options.systemPrompt = { append: systemPrompt.append };
441
+ return true;
442
+ }
405
443
  function parseOwnerGeneration(value) {
406
444
  if (value == null) return;
407
445
  if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) return null;
@@ -414,189 +452,245 @@ function parseNonNegativeInteger(value) {
414
452
  }
415
453
  function parseQueueRequest(raw) {
416
454
  const request = asRecord$2(raw);
417
- if (!request) return null;
418
- if (typeof request.type !== "string" || typeof request.requestId !== "string") return null;
455
+ if (!request || typeof request.type !== "string" || typeof request.requestId !== "string") return null;
419
456
  const ownerGeneration = parseOwnerGeneration(request.ownerGeneration);
420
457
  if (ownerGeneration === null) return null;
421
- const timeoutRaw = request.timeoutMs;
422
- const timeoutMs = typeof timeoutRaw === "number" && Number.isFinite(timeoutRaw) && timeoutRaw > 0 ? Math.round(timeoutRaw) : void 0;
423
- if (request.type === "submit_prompt") {
424
- const resumePolicy = request.resumePolicy == null ? void 0 : isSessionResumePolicy(request.resumePolicy) ? request.resumePolicy : null;
425
- const nonInteractivePermissions = request.nonInteractivePermissions == null ? void 0 : isNonInteractivePermissionPolicy(request.nonInteractivePermissions) ? request.nonInteractivePermissions : null;
426
- const permissionPolicy = request.permissionPolicy == null ? void 0 : isPermissionPolicy(request.permissionPolicy) ? request.permissionPolicy : null;
427
- const suppressSdkConsoleErrors = request.suppressSdkConsoleErrors == null ? void 0 : typeof request.suppressSdkConsoleErrors === "boolean" ? request.suppressSdkConsoleErrors : null;
428
- const promptRetries = parseNonNegativeInteger(request.promptRetries);
429
- const sessionOptions = parseSessionOptions(request.sessionOptions);
430
- const prompt = request.prompt == null ? void 0 : isPromptInput(request.prompt) ? request.prompt : null;
431
- if (typeof request.message !== "string" || !isPermissionMode(request.permissionMode) || resumePolicy === null || prompt === null || nonInteractivePermissions === null || permissionPolicy === null || suppressSdkConsoleErrors === null || promptRetries === null || sessionOptions === null || typeof request.waitForCompletion !== "boolean") return null;
432
- return {
433
- type: "submit_prompt",
434
- requestId: request.requestId,
435
- ownerGeneration,
436
- message: request.message,
437
- prompt: prompt ?? textPrompt(request.message),
438
- permissionMode: request.permissionMode,
439
- ...resumePolicy !== void 0 ? { resumePolicy } : {},
440
- nonInteractivePermissions,
441
- ...permissionPolicy !== void 0 ? { permissionPolicy } : {},
442
- timeoutMs,
443
- ...suppressSdkConsoleErrors !== void 0 ? { suppressSdkConsoleErrors } : {},
444
- ...promptRetries !== void 0 ? { promptRetries } : {},
445
- waitForCompletion: request.waitForCompletion,
446
- ...sessionOptions !== void 0 ? { sessionOptions } : {}
447
- };
448
- }
449
- if (request.type === "cancel_prompt") return {
450
- type: "cancel_prompt",
451
- requestId: request.requestId,
452
- ownerGeneration
453
- };
454
- if (request.type === "close_session") return {
455
- type: "close_session",
456
- requestId: request.requestId,
458
+ return parseTypedQueueRequest(request, parseQueueRequestContext(request.requestId, ownerGeneration, request.timeoutMs));
459
+ }
460
+ function parseQueueRequestContext(requestId, ownerGeneration, timeoutRaw) {
461
+ return {
462
+ requestId,
457
463
  ownerGeneration,
458
- timeoutMs
464
+ timeoutMs: parsePositiveTimeout(timeoutRaw)
459
465
  };
460
- if (request.type === "set_mode") {
461
- if (typeof request.modeId !== "string" || request.modeId.trim().length === 0) return null;
462
- return {
463
- type: "set_mode",
464
- requestId: request.requestId,
465
- ownerGeneration,
466
- modeId: request.modeId,
467
- timeoutMs
468
- };
469
- }
470
- if (request.type === "set_model") {
471
- if (typeof request.modelId !== "string" || request.modelId.trim().length === 0) return null;
472
- return {
473
- type: "set_model",
474
- requestId: request.requestId,
475
- ownerGeneration,
476
- modelId: request.modelId,
477
- timeoutMs
466
+ }
467
+ function parsePositiveTimeout(value) {
468
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return;
469
+ return Math.round(value);
470
+ }
471
+ function parseTypedQueueRequest(request, context) {
472
+ switch (request.type) {
473
+ case "submit_prompt": return parseSubmitRequest(request, context);
474
+ case "cancel_prompt": return {
475
+ type: "cancel_prompt",
476
+ requestId: context.requestId,
477
+ ownerGeneration: context.ownerGeneration
478
478
  };
479
- }
480
- if (request.type === "set_config_option") {
481
- if (typeof request.configId !== "string" || request.configId.trim().length === 0 || typeof request.value !== "string" || request.value.trim().length === 0) return null;
482
- return {
483
- type: "set_config_option",
484
- requestId: request.requestId,
485
- ownerGeneration,
486
- configId: request.configId,
487
- value: request.value,
488
- timeoutMs
479
+ case "close_session": return {
480
+ type: "close_session",
481
+ ...context
489
482
  };
483
+ case "set_mode": return parseStringFieldRequest(request, context, "set_mode", "modeId");
484
+ case "set_model": return parseStringFieldRequest(request, context, "set_model", "modelId");
485
+ case "set_config_option": return parseSetConfigOptionRequest(request, context);
486
+ default: return null;
490
487
  }
491
- return null;
488
+ }
489
+ function parseSubmitRequest(request, context) {
490
+ const parsed = parseSubmitRequestFields(request);
491
+ if (!parsed) return null;
492
+ return {
493
+ type: "submit_prompt",
494
+ requestId: context.requestId,
495
+ ownerGeneration: context.ownerGeneration,
496
+ message: parsed.message,
497
+ prompt: parsed.prompt ?? textPrompt(parsed.message),
498
+ permissionMode: parsed.permissionMode,
499
+ ...parsed.resumePolicy !== void 0 ? { resumePolicy: parsed.resumePolicy } : {},
500
+ nonInteractivePermissions: parsed.nonInteractivePermissions,
501
+ ...parsed.permissionPolicy !== void 0 ? { permissionPolicy: parsed.permissionPolicy } : {},
502
+ timeoutMs: context.timeoutMs,
503
+ ...parsed.suppressSdkConsoleErrors !== void 0 ? { suppressSdkConsoleErrors: parsed.suppressSdkConsoleErrors } : {},
504
+ ...parsed.promptRetries !== void 0 ? { promptRetries: parsed.promptRetries } : {},
505
+ waitForCompletion: parsed.waitForCompletion,
506
+ ...parsed.sessionOptions !== void 0 ? { sessionOptions: parsed.sessionOptions } : {}
507
+ };
508
+ }
509
+ function parseSubmitRequestFields(request) {
510
+ const parsed = {
511
+ message: typeof request.message === "string" ? request.message : null,
512
+ prompt: parseOptionalValue(request.prompt, isPromptInput),
513
+ permissionMode: parseRequiredValue(request.permissionMode, isPermissionMode),
514
+ resumePolicy: parseOptionalValue(request.resumePolicy, isSessionResumePolicy),
515
+ nonInteractivePermissions: parseOptionalValue(request.nonInteractivePermissions, isNonInteractivePermissionPolicy),
516
+ permissionPolicy: parseOptionalValue(request.permissionPolicy, isPermissionPolicy),
517
+ suppressSdkConsoleErrors: parseOptionalBoolean(request.suppressSdkConsoleErrors),
518
+ promptRetries: parseNonNegativeInteger(request.promptRetries),
519
+ waitForCompletion: typeof request.waitForCompletion === "boolean" ? request.waitForCompletion : null,
520
+ sessionOptions: parseSessionOptions(request.sessionOptions)
521
+ };
522
+ if (Object.values(parsed).some((value) => value === null)) return null;
523
+ return parsed;
524
+ }
525
+ function parseOptionalValue(value, guard) {
526
+ if (value == null) return;
527
+ return guard(value) ? value : null;
528
+ }
529
+ function parseRequiredValue(value, guard) {
530
+ return guard(value) ? value : null;
531
+ }
532
+ function parseOptionalBoolean(value) {
533
+ if (value == null) return;
534
+ return typeof value === "boolean" ? value : null;
535
+ }
536
+ function parseStringFieldRequest(request, context, type, field) {
537
+ const value = parseNonEmptyString(request[field]);
538
+ if (!value) return null;
539
+ return {
540
+ type,
541
+ ...context,
542
+ [field]: value
543
+ };
544
+ }
545
+ function parseSetConfigOptionRequest(request, context) {
546
+ const configId = parseNonEmptyString(request.configId);
547
+ const value = parseNonEmptyString(request.value);
548
+ if (!configId || !value) return null;
549
+ return {
550
+ type: "set_config_option",
551
+ ...context,
552
+ configId,
553
+ value
554
+ };
555
+ }
556
+ function parseNonEmptyString(value) {
557
+ if (typeof value !== "string" || value.trim().length === 0) return null;
558
+ return value;
492
559
  }
493
560
  function parseSessionSendResult(raw) {
494
561
  const result = asRecord$2(raw);
495
- if (!result) return null;
496
- if (typeof result.stopReason !== "string" || typeof result.sessionId !== "string" || typeof result.resumed !== "boolean") return null;
562
+ if (!result || !hasValidSessionSendResultCore(result)) return null;
497
563
  const permissionStats = asRecord$2(result.permissionStats);
498
564
  const record = asRecord$2(result.record);
499
565
  if (!permissionStats || !record) return null;
500
- if (!(typeof permissionStats.requested === "number" && typeof permissionStats.approved === "number" && typeof permissionStats.denied === "number" && typeof permissionStats.cancelled === "number")) return null;
501
- if (!(typeof record.acpxRecordId === "string" && typeof record.acpSessionId === "string" && typeof record.agentCommand === "string" && typeof record.cwd === "string" && typeof record.createdAt === "string" && typeof record.lastUsedAt === "string" && Array.isArray(record.messages) && typeof record.updated_at === "string" && typeof record.lastSeq === "number" && Number.isInteger(record.lastSeq) && !!record.eventLog && typeof record.eventLog === "object")) return null;
566
+ if (!hasValidPermissionStats(permissionStats)) return null;
567
+ if (!hasValidSessionRecordShape(record)) return null;
502
568
  return result;
503
569
  }
570
+ function hasValidSessionSendResultCore(result) {
571
+ return typeof result.stopReason === "string" && typeof result.sessionId === "string" && typeof result.resumed === "boolean";
572
+ }
573
+ function hasValidPermissionStats(permissionStats) {
574
+ return [
575
+ "requested",
576
+ "approved",
577
+ "denied",
578
+ "cancelled"
579
+ ].every((key) => typeof permissionStats[key] === "number");
580
+ }
581
+ function hasValidSessionRecordShape(record) {
582
+ return hasStringFields(record, [
583
+ "acpxRecordId",
584
+ "acpSessionId",
585
+ "agentCommand",
586
+ "cwd",
587
+ "createdAt",
588
+ "lastUsedAt",
589
+ "updated_at"
590
+ ]) && Array.isArray(record.messages) && typeof record.lastSeq === "number" && Number.isInteger(record.lastSeq) && !!record.eventLog && typeof record.eventLog === "object";
591
+ }
592
+ function hasStringFields(record, keys) {
593
+ return keys.every((key) => typeof record[key] === "string");
594
+ }
504
595
  function parseQueueOwnerMessage(raw) {
505
596
  const message = asRecord$2(raw);
506
- if (!message || typeof message.type !== "string") return null;
507
- if (typeof message.requestId !== "string") return null;
597
+ if (!message || typeof message.type !== "string" || typeof message.requestId !== "string") return null;
508
598
  const ownerGeneration = parseOwnerGeneration(message.ownerGeneration);
509
599
  if (ownerGeneration === null) return null;
510
- if (message.type === "accepted") return {
511
- type: "accepted",
600
+ return parseTypedQueueOwnerMessage(message, {
512
601
  requestId: message.requestId,
513
602
  ownerGeneration
603
+ });
604
+ }
605
+ function parseTypedQueueOwnerMessage(message, context) {
606
+ const parser = queueOwnerMessageParser(message.type);
607
+ return parser ? parser(message, context) : null;
608
+ }
609
+ const QUEUE_OWNER_MESSAGE_PARSERS = {
610
+ accepted: (_message, context) => ({
611
+ type: "accepted",
612
+ ...context
613
+ }),
614
+ event: parseEventOwnerMessage,
615
+ permission_escalation: parsePermissionEscalationOwnerMessage,
616
+ result: parseResultOwnerMessage,
617
+ cancel_result: (message, context) => parseBooleanResultOwnerMessage(message, context, "cancel_result", "cancelled"),
618
+ close_session_result: (message, context) => parseBooleanResultOwnerMessage(message, context, "close_session_result", "closed"),
619
+ set_mode_result: (message, context) => parseStringResultOwnerMessage(message, context, "set_mode_result", "modeId"),
620
+ set_model_result: (message, context) => parseStringResultOwnerMessage(message, context, "set_model_result", "modelId"),
621
+ set_config_option_result: parseSetConfigOptionOwnerMessage,
622
+ error: parseErrorOwnerMessage
623
+ };
624
+ function queueOwnerMessageParser(type) {
625
+ return Object.hasOwn(QUEUE_OWNER_MESSAGE_PARSERS, type) ? QUEUE_OWNER_MESSAGE_PARSERS[type] : void 0;
626
+ }
627
+ function parseEventOwnerMessage(message, context) {
628
+ if (!isAcpJsonRpcMessage(message.message)) return null;
629
+ return {
630
+ type: "event",
631
+ ...context,
632
+ message: message.message
514
633
  };
515
- if (message.type === "event") {
516
- if (!isAcpJsonRpcMessage(message.message)) return null;
517
- return {
518
- type: "event",
519
- requestId: message.requestId,
520
- ownerGeneration,
521
- message: message.message
522
- };
523
- }
524
- if (message.type === "permission_escalation") {
525
- if (!isPermissionEscalationEvent(message.event)) return null;
526
- return {
527
- type: "permission_escalation",
528
- requestId: message.requestId,
529
- ownerGeneration,
530
- event: message.event
531
- };
532
- }
533
- if (message.type === "result") {
534
- const parsedResult = parseSessionSendResult(message.result);
535
- if (!parsedResult) return null;
536
- return {
537
- type: "result",
538
- requestId: message.requestId,
539
- ownerGeneration,
540
- result: parsedResult
541
- };
542
- }
543
- if (message.type === "cancel_result") {
544
- if (typeof message.cancelled !== "boolean") return null;
545
- return {
546
- type: "cancel_result",
547
- requestId: message.requestId,
548
- ownerGeneration,
549
- cancelled: message.cancelled
550
- };
551
- }
552
- if (message.type === "set_mode_result") {
553
- if (typeof message.modeId !== "string") return null;
554
- return {
555
- type: "set_mode_result",
556
- requestId: message.requestId,
557
- ownerGeneration,
558
- modeId: message.modeId
559
- };
560
- }
561
- if (message.type === "set_model_result") {
562
- if (typeof message.modelId !== "string") return null;
563
- return {
564
- type: "set_model_result",
565
- requestId: message.requestId,
566
- ownerGeneration,
567
- modelId: message.modelId
568
- };
569
- }
570
- if (message.type === "set_config_option_result") {
571
- const response = asRecord$2(message.response);
572
- if (!response || !Array.isArray(response.configOptions)) return null;
573
- return {
574
- type: "set_config_option_result",
575
- requestId: message.requestId,
576
- ownerGeneration,
577
- response
578
- };
579
- }
580
- if (message.type === "error") {
581
- if (typeof message.message !== "string" || !isOutputErrorCode(message.code) || !isOutputErrorOrigin(message.origin)) return null;
582
- const detailCode = typeof message.detailCode === "string" && message.detailCode.trim().length > 0 ? message.detailCode : void 0;
583
- const retryable = typeof message.retryable === "boolean" ? message.retryable : void 0;
584
- const acp = toAcpErrorPayload(message.acp);
585
- const outputAlreadyEmitted = typeof message.outputAlreadyEmitted === "boolean" ? message.outputAlreadyEmitted : void 0;
586
- return {
587
- type: "error",
588
- requestId: message.requestId,
589
- ownerGeneration,
590
- code: message.code,
591
- detailCode,
592
- origin: message.origin,
593
- message: message.message,
594
- retryable,
595
- acp,
596
- ...outputAlreadyEmitted === void 0 ? {} : { outputAlreadyEmitted }
597
- };
598
- }
599
- return null;
634
+ }
635
+ function parsePermissionEscalationOwnerMessage(message, context) {
636
+ if (!isPermissionEscalationEvent(message.event)) return null;
637
+ return {
638
+ type: "permission_escalation",
639
+ ...context,
640
+ event: message.event
641
+ };
642
+ }
643
+ function parseResultOwnerMessage(message, context) {
644
+ const result = parseSessionSendResult(message.result);
645
+ if (!result) return null;
646
+ return {
647
+ type: "result",
648
+ ...context,
649
+ result
650
+ };
651
+ }
652
+ function parseBooleanResultOwnerMessage(message, context, type, field) {
653
+ if (typeof message[field] !== "boolean") return null;
654
+ return {
655
+ type,
656
+ ...context,
657
+ [field]: message[field]
658
+ };
659
+ }
660
+ function parseStringResultOwnerMessage(message, context, type, field) {
661
+ if (typeof message[field] !== "string") return null;
662
+ return {
663
+ type,
664
+ ...context,
665
+ [field]: message[field]
666
+ };
667
+ }
668
+ function parseSetConfigOptionOwnerMessage(message, context) {
669
+ const response = asRecord$2(message.response);
670
+ if (!response || !Array.isArray(response.configOptions)) return null;
671
+ return {
672
+ type: "set_config_option_result",
673
+ ...context,
674
+ response
675
+ };
676
+ }
677
+ function parseErrorOwnerMessage(message, context) {
678
+ if (!isValidOwnerErrorCore(message)) return null;
679
+ const outputAlreadyEmitted = typeof message.outputAlreadyEmitted === "boolean" ? message.outputAlreadyEmitted : void 0;
680
+ return {
681
+ type: "error",
682
+ ...context,
683
+ code: message.code,
684
+ detailCode: parseNonEmptyString(message.detailCode) ?? void 0,
685
+ origin: message.origin,
686
+ message: message.message,
687
+ retryable: typeof message.retryable === "boolean" ? message.retryable : void 0,
688
+ acp: toAcpErrorPayload(message.acp),
689
+ ...outputAlreadyEmitted === void 0 ? {} : { outputAlreadyEmitted }
690
+ };
691
+ }
692
+ function isValidOwnerErrorCore(message) {
693
+ return typeof message.message === "string" && isOutputErrorCode(message.code) && isOutputErrorOrigin(message.origin);
600
694
  }
601
695
  //#endregion
602
696
  //#region src/cli/queue/ipc-server.ts
@@ -753,6 +847,135 @@ var SessionQueueOwner = class SessionQueueOwner {
753
847
  if (!options.socket.destroyed) options.socket.end();
754
848
  });
755
849
  }
850
+ failRequest(socket, requestId, message, detailCode) {
851
+ writeQueueMessage(socket, {
852
+ ...makeQueueOwnerError(requestId, message, detailCode, { retryable: false }),
853
+ ownerGeneration: this.ownerGeneration
854
+ });
855
+ socket.end();
856
+ }
857
+ parseRequestLine(socket, line) {
858
+ let parsed;
859
+ try {
860
+ parsed = JSON.parse(line);
861
+ } catch {
862
+ this.failRequest(socket, "unknown", "Invalid queue request payload", "QUEUE_REQUEST_PAYLOAD_INVALID_JSON");
863
+ return;
864
+ }
865
+ const request = parseQueueRequest(parsed);
866
+ if (!request) this.failRequest(socket, "unknown", "Invalid queue request", "QUEUE_REQUEST_INVALID");
867
+ return request ?? void 0;
868
+ }
869
+ rejectStaleOwnerGeneration(socket, request) {
870
+ if (request.ownerGeneration === void 0 || this.ownerGeneration === void 0 || request.ownerGeneration === this.ownerGeneration) return false;
871
+ this.failRequest(socket, request.requestId, "Queue request targeted a stale queue owner generation", "QUEUE_OWNER_GENERATION_MISMATCH");
872
+ return true;
873
+ }
874
+ handleControlQueueRequest(socket, request) {
875
+ if (request.type === "cancel_prompt") {
876
+ this.handleControlRequest({
877
+ socket,
878
+ requestId: request.requestId,
879
+ run: async () => ({
880
+ type: "cancel_result",
881
+ requestId: request.requestId,
882
+ cancelled: await this.controlHandlers.cancelPrompt()
883
+ })
884
+ });
885
+ return true;
886
+ }
887
+ if (request.type === "close_session") {
888
+ this.handleControlRequest({
889
+ socket,
890
+ requestId: request.requestId,
891
+ run: async () => ({
892
+ type: "close_session_result",
893
+ requestId: request.requestId,
894
+ closed: await this.controlHandlers.closeSession(request.timeoutMs)
895
+ })
896
+ });
897
+ return true;
898
+ }
899
+ return this.handleSessionControlQueueRequest(socket, request);
900
+ }
901
+ handleSessionControlQueueRequest(socket, request) {
902
+ if (request.type === "set_mode") {
903
+ this.handleControlRequest({
904
+ socket,
905
+ requestId: request.requestId,
906
+ run: async () => {
907
+ await this.controlHandlers.setSessionMode(request.modeId, request.timeoutMs);
908
+ return {
909
+ type: "set_mode_result",
910
+ requestId: request.requestId,
911
+ modeId: request.modeId
912
+ };
913
+ }
914
+ });
915
+ return true;
916
+ }
917
+ if (request.type === "set_model") {
918
+ this.handleControlRequest({
919
+ socket,
920
+ requestId: request.requestId,
921
+ run: async () => {
922
+ await this.controlHandlers.setSessionModel(request.modelId, request.timeoutMs);
923
+ return {
924
+ type: "set_model_result",
925
+ requestId: request.requestId,
926
+ modelId: request.modelId
927
+ };
928
+ }
929
+ });
930
+ return true;
931
+ }
932
+ if (request.type === "set_config_option") {
933
+ this.handleControlRequest({
934
+ socket,
935
+ requestId: request.requestId,
936
+ run: async () => ({
937
+ type: "set_config_option_result",
938
+ requestId: request.requestId,
939
+ response: await this.controlHandlers.setSessionConfigOption(request.configId, request.value, request.timeoutMs)
940
+ })
941
+ });
942
+ return true;
943
+ }
944
+ return false;
945
+ }
946
+ enqueuePromptRequest(socket, request) {
947
+ const task = {
948
+ requestId: request.requestId,
949
+ message: request.message,
950
+ prompt: request.prompt ?? textPrompt(request.message),
951
+ permissionMode: request.permissionMode,
952
+ resumePolicy: request.resumePolicy,
953
+ nonInteractivePermissions: request.nonInteractivePermissions,
954
+ permissionPolicy: request.permissionPolicy,
955
+ timeoutMs: request.timeoutMs,
956
+ suppressSdkConsoleErrors: request.suppressSdkConsoleErrors,
957
+ promptRetries: request.promptRetries,
958
+ sessionOptions: request.sessionOptions,
959
+ waitForCompletion: request.waitForCompletion,
960
+ enqueuedAt: Date.now(),
961
+ send: (message) => {
962
+ writeQueueMessage(socket, {
963
+ ...message,
964
+ ownerGeneration: this.ownerGeneration
965
+ });
966
+ },
967
+ close: () => {
968
+ if (!socket.destroyed) socket.end();
969
+ }
970
+ };
971
+ writeQueueMessage(socket, {
972
+ type: "accepted",
973
+ requestId: request.requestId,
974
+ ownerGeneration: this.ownerGeneration
975
+ });
976
+ if (!request.waitForCompletion) task.close();
977
+ this.enqueue(task);
978
+ }
756
979
  handleConnection(socket) {
757
980
  socket.setEncoding("utf8");
758
981
  if (this.closed) {
@@ -762,129 +985,17 @@ var SessionQueueOwner = class SessionQueueOwner {
762
985
  }
763
986
  let buffer = "";
764
987
  let handled = false;
765
- const fail = (requestId, message, detailCode) => {
766
- writeQueueMessage(socket, {
767
- ...makeQueueOwnerError(requestId, message, detailCode, { retryable: false }),
768
- ownerGeneration: this.ownerGeneration
769
- });
770
- socket.end();
771
- };
772
988
  const processLine = (line) => {
773
989
  if (handled) return;
774
990
  handled = true;
775
- let parsed;
776
- try {
777
- parsed = JSON.parse(line);
778
- } catch {
779
- fail("unknown", "Invalid queue request payload", "QUEUE_REQUEST_PAYLOAD_INVALID_JSON");
780
- return;
781
- }
782
- const request = parseQueueRequest(parsed);
783
- if (!request) {
784
- fail("unknown", "Invalid queue request", "QUEUE_REQUEST_INVALID");
785
- return;
786
- }
787
- if (request.ownerGeneration !== void 0 && this.ownerGeneration !== void 0 && request.ownerGeneration !== this.ownerGeneration) {
788
- fail(request.requestId, "Queue request targeted a stale queue owner generation", "QUEUE_OWNER_GENERATION_MISMATCH");
789
- return;
790
- }
791
- if (request.type === "cancel_prompt") {
792
- this.handleControlRequest({
793
- socket,
794
- requestId: request.requestId,
795
- run: async () => ({
796
- type: "cancel_result",
797
- requestId: request.requestId,
798
- cancelled: await this.controlHandlers.cancelPrompt()
799
- })
800
- });
801
- return;
802
- }
803
- if (request.type === "close_session") {
804
- this.handleControlRequest({
805
- socket,
806
- requestId: request.requestId,
807
- run: async () => ({
808
- type: "close_session_result",
809
- requestId: request.requestId,
810
- closed: await this.controlHandlers.closeSession(request.timeoutMs)
811
- })
812
- });
813
- return;
814
- }
815
- if (request.type === "set_mode") {
816
- this.handleControlRequest({
817
- socket,
818
- requestId: request.requestId,
819
- run: async () => {
820
- await this.controlHandlers.setSessionMode(request.modeId, request.timeoutMs);
821
- return {
822
- type: "set_mode_result",
823
- requestId: request.requestId,
824
- modeId: request.modeId
825
- };
826
- }
827
- });
828
- return;
829
- }
830
- if (request.type === "set_model") {
831
- this.handleControlRequest({
832
- socket,
833
- requestId: request.requestId,
834
- run: async () => {
835
- await this.controlHandlers.setSessionModel(request.modelId, request.timeoutMs);
836
- return {
837
- type: "set_model_result",
838
- requestId: request.requestId,
839
- modelId: request.modelId
840
- };
841
- }
842
- });
843
- return;
844
- }
845
- if (request.type === "set_config_option") {
846
- this.handleControlRequest({
847
- socket,
848
- requestId: request.requestId,
849
- run: async () => ({
850
- type: "set_config_option_result",
851
- requestId: request.requestId,
852
- response: await this.controlHandlers.setSessionConfigOption(request.configId, request.value, request.timeoutMs)
853
- })
854
- });
991
+ const request = this.parseRequestLine(socket, line);
992
+ if (!request || this.rejectStaleOwnerGeneration(socket, request)) return;
993
+ if (this.handleControlQueueRequest(socket, request)) return;
994
+ if (request.type !== "submit_prompt") {
995
+ this.failRequest(socket, request.requestId, "Invalid queue request", "QUEUE_REQUEST_INVALID");
855
996
  return;
856
997
  }
857
- const task = {
858
- requestId: request.requestId,
859
- message: request.message,
860
- prompt: request.prompt ?? textPrompt(request.message),
861
- permissionMode: request.permissionMode,
862
- resumePolicy: request.resumePolicy,
863
- nonInteractivePermissions: request.nonInteractivePermissions,
864
- permissionPolicy: request.permissionPolicy,
865
- timeoutMs: request.timeoutMs,
866
- suppressSdkConsoleErrors: request.suppressSdkConsoleErrors,
867
- promptRetries: request.promptRetries,
868
- sessionOptions: request.sessionOptions,
869
- waitForCompletion: request.waitForCompletion,
870
- enqueuedAt: Date.now(),
871
- send: (message) => {
872
- writeQueueMessage(socket, {
873
- ...message,
874
- ownerGeneration: this.ownerGeneration
875
- });
876
- },
877
- close: () => {
878
- if (!socket.destroyed) socket.end();
879
- }
880
- };
881
- writeQueueMessage(socket, {
882
- type: "accepted",
883
- requestId: request.requestId,
884
- ownerGeneration: this.ownerGeneration
885
- });
886
- if (!request.waitForCompletion) task.close();
887
- this.enqueue(task);
998
+ this.enqueuePromptRequest(socket, request);
888
999
  };
889
1000
  socket.on("data", (chunk) => {
890
1001
  buffer += chunk;
@@ -920,6 +1031,16 @@ function assertOwnerGeneration(owner, message) {
920
1031
  });
921
1032
  return message;
922
1033
  }
1034
+ function queueConnectionErrorFromOwner(message, outputAlreadyEmitted) {
1035
+ return new QueueConnectionError(message.message, {
1036
+ outputCode: message.code,
1037
+ detailCode: message.detailCode,
1038
+ origin: message.origin ?? "queue",
1039
+ retryable: message.retryable,
1040
+ acp: message.acp,
1041
+ ...outputAlreadyEmitted ? { outputAlreadyEmitted: true } : {}
1042
+ });
1043
+ }
923
1044
  function makeMalformedQueueMessageError() {
924
1045
  return new QueueProtocolError("Queue owner sent malformed message", {
925
1046
  detailCode: "QUEUE_PROTOCOL_MALFORMED_MESSAGE",
@@ -927,6 +1048,22 @@ function makeMalformedQueueMessageError() {
927
1048
  retryable: true
928
1049
  });
929
1050
  }
1051
+ function emitQueueOwnerError(formatter, policy, sessionId, message) {
1052
+ formatter.setContext({ sessionId });
1053
+ const queueErrorAlreadyEmitted = policy?.queueErrorAlreadyEmitted ?? true;
1054
+ if (message.outputAlreadyEmitted !== true || !queueErrorAlreadyEmitted) {
1055
+ formatter.onError({
1056
+ code: message.code ?? "RUNTIME",
1057
+ detailCode: message.detailCode,
1058
+ origin: message.origin ?? "queue",
1059
+ message: message.message,
1060
+ retryable: message.retryable,
1061
+ acp: message.acp
1062
+ });
1063
+ formatter.flush();
1064
+ }
1065
+ return queueConnectionErrorFromOwner(message, queueErrorAlreadyEmitted);
1066
+ }
930
1067
  function parseQueueOwnerResponseLine(owner, requestId, line) {
931
1068
  let parsed;
932
1069
  try {
@@ -1011,6 +1148,47 @@ async function runQueueOwnerRequest(options) {
1011
1148
  socket.write(`${JSON.stringify(options.request)}\n`);
1012
1149
  });
1013
1150
  }
1151
+ function missingQueueAckError() {
1152
+ return new QueueConnectionError("Queue owner did not acknowledge request", {
1153
+ detailCode: "QUEUE_ACK_MISSING",
1154
+ origin: "queue",
1155
+ retryable: true
1156
+ });
1157
+ }
1158
+ function unexpectedQueueResponseError() {
1159
+ return new QueueProtocolError("Queue owner returned unexpected response", {
1160
+ detailCode: "QUEUE_PROTOCOL_UNEXPECTED_RESPONSE",
1161
+ origin: "queue",
1162
+ retryable: true
1163
+ });
1164
+ }
1165
+ function handleAcknowledgedSubmitMessage(message, controls, formatter) {
1166
+ if (message.type === "event") {
1167
+ formatter.onAcpMessage(message.message);
1168
+ return;
1169
+ }
1170
+ if (message.type === "permission_escalation") {
1171
+ formatter.onPermissionEscalation(message.event);
1172
+ return;
1173
+ }
1174
+ if (message.type === "result") {
1175
+ formatter.flush();
1176
+ controls.resolve(message.result);
1177
+ return;
1178
+ }
1179
+ controls.reject(unexpectedQueueResponseError());
1180
+ }
1181
+ function handleSubmitQueueOwnerMessage(message, controls, options) {
1182
+ if (message.type === "error") {
1183
+ controls.reject(emitQueueOwnerError(options.outputFormatter, options.errorEmissionPolicy, options.sessionId, message));
1184
+ return;
1185
+ }
1186
+ if (!controls.state.acknowledged) {
1187
+ controls.reject(missingQueueAckError());
1188
+ return;
1189
+ }
1190
+ handleAcknowledgedSubmitMessage(message, controls, options.outputFormatter);
1191
+ }
1014
1192
  async function submitToQueueOwner(owner, options) {
1015
1193
  const requestId = randomUUID();
1016
1194
  const request = {
@@ -1041,57 +1219,8 @@ async function submitToQueueOwner(owner, options) {
1041
1219
  requestId
1042
1220
  });
1043
1221
  },
1044
- onMessage: (message, { state, resolve, reject }) => {
1045
- if (message.type === "error") {
1046
- options.outputFormatter.setContext({ sessionId: options.sessionId });
1047
- const queueErrorAlreadyEmitted = options.errorEmissionPolicy?.queueErrorAlreadyEmitted ?? true;
1048
- if (!(message.outputAlreadyEmitted === true) || !queueErrorAlreadyEmitted) {
1049
- options.outputFormatter.onError({
1050
- code: message.code ?? "RUNTIME",
1051
- detailCode: message.detailCode,
1052
- origin: message.origin ?? "queue",
1053
- message: message.message,
1054
- retryable: message.retryable,
1055
- acp: message.acp
1056
- });
1057
- options.outputFormatter.flush();
1058
- }
1059
- reject(new QueueConnectionError(message.message, {
1060
- outputCode: message.code,
1061
- detailCode: message.detailCode,
1062
- origin: message.origin ?? "queue",
1063
- retryable: message.retryable,
1064
- acp: message.acp,
1065
- ...queueErrorAlreadyEmitted ? { outputAlreadyEmitted: true } : {}
1066
- }));
1067
- return;
1068
- }
1069
- if (!state.acknowledged) {
1070
- reject(new QueueConnectionError("Queue owner did not acknowledge request", {
1071
- detailCode: "QUEUE_ACK_MISSING",
1072
- origin: "queue",
1073
- retryable: true
1074
- }));
1075
- return;
1076
- }
1077
- if (message.type === "event") {
1078
- options.outputFormatter.onAcpMessage(message.message);
1079
- return;
1080
- }
1081
- if (message.type === "permission_escalation") {
1082
- options.outputFormatter.onPermissionEscalation(message.event);
1083
- return;
1084
- }
1085
- if (message.type === "result") {
1086
- options.outputFormatter.flush();
1087
- resolve(message.result);
1088
- return;
1089
- }
1090
- reject(new QueueProtocolError("Queue owner returned unexpected response", {
1091
- detailCode: "QUEUE_PROTOCOL_UNEXPECTED_RESPONSE",
1092
- origin: "queue",
1093
- retryable: true
1094
- }));
1222
+ onMessage: (message, controls) => {
1223
+ handleSubmitQueueOwnerMessage(message, controls, options);
1095
1224
  },
1096
1225
  onClose: ({ state, resolve, reject }) => {
1097
1226
  if (!state.acknowledged) {
@@ -1520,31 +1649,19 @@ async function closeSession(sessionId) {
1520
1649
  //#region src/cli/session/session-management.ts
1521
1650
  async function createSessionRecordWithClient(client, options) {
1522
1651
  const cwd = absolutePath(options.cwd);
1523
- await withTimeout(client.start(), options.timeoutMs);
1524
- let sessionId;
1525
- let agentSessionId;
1526
- let sessionResult;
1527
- let sessionModels;
1528
- let requestedModelApplied = false;
1529
- if (options.resumeSessionId) {
1530
- if (!client.supportsLoadSession()) throw new Error(`Agent command "${options.agentCommand}" does not support session/load; cannot resume session ${options.resumeSessionId}`);
1531
- try {
1532
- const loadedSession = await withTimeout(client.loadSession(options.resumeSessionId, cwd), options.timeoutMs);
1533
- sessionId = options.resumeSessionId;
1534
- agentSessionId = normalizeRuntimeSessionId(loadedSession.agentSessionId);
1535
- sessionResult = loadedSession;
1536
- sessionModels = loadedSession.models;
1537
- requestedModelApplied = await applyRequestedModelIfAdvertised({
1538
- client,
1539
- sessionId,
1540
- requestedModel: options.sessionOptions?.model,
1541
- models: sessionModels,
1542
- agentCommand: options.agentCommand,
1543
- timeoutMs: options.timeoutMs
1544
- });
1545
- } catch (error) {
1546
- throw new Error(`Failed to resume ACP session ${options.resumeSessionId}: ${formatErrorMessage(error)}`, { cause: error });
1547
- }
1652
+ await withTimeout(client.start(), options.timeoutMs);
1653
+ let sessionId;
1654
+ let agentSessionId;
1655
+ let sessionResult;
1656
+ let sessionModels;
1657
+ let requestedModelApplied = false;
1658
+ if (options.resumeSessionId) {
1659
+ const resumed = await resumeSessionRecordWithClient(client, options, cwd);
1660
+ sessionId = resumed.sessionId;
1661
+ agentSessionId = resumed.agentSessionId;
1662
+ sessionResult = resumed.sessionResult;
1663
+ sessionModels = resumed.sessionModels;
1664
+ requestedModelApplied = resumed.requestedModelApplied;
1548
1665
  } else {
1549
1666
  const createdSession = await withTimeout(client.createSession(cwd), options.timeoutMs);
1550
1667
  sessionId = createdSession.sessionId;
@@ -1577,7 +1694,7 @@ async function createSessionRecordWithClient(client, options) {
1577
1694
  eventLog: defaultSessionEventLog(sessionId),
1578
1695
  closed: false,
1579
1696
  closedAt: void 0,
1580
- pid: lifecycle.pid,
1697
+ pid: lifecycle.running ? lifecycle.pid : void 0,
1581
1698
  agentStartedAt: lifecycle.startedAt,
1582
1699
  protocolVersion: client.initializeResult?.protocolVersion,
1583
1700
  agentCapabilities: client.initializeResult?.agentCapabilities,
@@ -1591,6 +1708,31 @@ async function createSessionRecordWithClient(client, options) {
1591
1708
  await writeSessionRecord(record);
1592
1709
  return record;
1593
1710
  }
1711
+ async function resumeSessionRecordWithClient(client, options, cwd) {
1712
+ if (!options.resumeSessionId) throw new Error("resumeSessionId is required");
1713
+ const resumeMethod = client.supportsResumeSession() ? "session/resume" : client.supportsLoadSession() ? "session/load" : void 0;
1714
+ if (!resumeMethod) throw new Error(`Agent command "${options.agentCommand}" does not support session/resume or session/load; cannot resume session ${options.resumeSessionId}`);
1715
+ try {
1716
+ const resumedSession = await withTimeout(resumeMethod === "session/resume" ? client.resumeSession(options.resumeSessionId, cwd) : client.loadSession(options.resumeSessionId, cwd), options.timeoutMs);
1717
+ const sessionModels = resumedSession.models;
1718
+ return {
1719
+ sessionId: options.resumeSessionId,
1720
+ agentSessionId: normalizeRuntimeSessionId(resumedSession.agentSessionId),
1721
+ sessionResult: resumedSession,
1722
+ sessionModels,
1723
+ requestedModelApplied: await applyRequestedModelIfAdvertised({
1724
+ client,
1725
+ sessionId: options.resumeSessionId,
1726
+ requestedModel: options.sessionOptions?.model,
1727
+ models: sessionModels,
1728
+ agentCommand: options.agentCommand,
1729
+ timeoutMs: options.timeoutMs
1730
+ })
1731
+ };
1732
+ } catch (error) {
1733
+ throw new Error(`Failed to resume ACP session ${options.resumeSessionId}: ${formatErrorMessage(error)}`, { cause: error });
1734
+ }
1735
+ }
1594
1736
  async function createSessionWithClient(options) {
1595
1737
  const client = new AcpClient({
1596
1738
  agentCommand: options.agentCommand,
@@ -1621,6 +1763,45 @@ async function createSession(options) {
1621
1763
  const { record, client } = await createSessionWithClient(options);
1622
1764
  try {
1623
1765
  return record;
1766
+ } finally {
1767
+ await client.close();
1768
+ applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());
1769
+ await writeSessionRecord(record);
1770
+ }
1771
+ }
1772
+ async function listAgentSessions(options) {
1773
+ const client = new AcpClient({
1774
+ agentCommand: options.agentCommand,
1775
+ cwd: absolutePath(options.cwd),
1776
+ mcpServers: options.mcpServers,
1777
+ permissionMode: options.permissionMode,
1778
+ nonInteractivePermissions: options.nonInteractivePermissions,
1779
+ permissionPolicy: options.permissionPolicy,
1780
+ authCredentials: options.authCredentials,
1781
+ authPolicy: options.authPolicy,
1782
+ terminal: options.terminal,
1783
+ verbose: options.verbose
1784
+ });
1785
+ try {
1786
+ return await withInterrupt(async () => {
1787
+ await withTimeout(client.start(), options.timeoutMs);
1788
+ if (!client.supportsListSessions()) return;
1789
+ const cwd = options.filterCwd ? absolutePath(options.filterCwd) : void 0;
1790
+ const response = await withTimeout(client.listSessions({
1791
+ ...cwd ? { cwd } : {},
1792
+ ...options.cursor ? { cursor: options.cursor } : {}
1793
+ }), options.timeoutMs);
1794
+ return {
1795
+ _meta: response._meta,
1796
+ source: "agent",
1797
+ sessions: response.sessions,
1798
+ cursor: options.cursor,
1799
+ cwd,
1800
+ nextCursor: response.nextCursor
1801
+ };
1802
+ }, async () => {
1803
+ await client.close();
1804
+ });
1624
1805
  } finally {
1625
1806
  await client.close();
1626
1807
  }
@@ -1701,15 +1882,25 @@ function buildPayload(reason) {
1701
1882
  metrics: getPerfMetricsSnapshot()
1702
1883
  };
1703
1884
  }
1885
+ function payloadHasMetrics(payload) {
1886
+ const metrics = payload.metrics;
1887
+ return [
1888
+ metrics.counters,
1889
+ metrics.gauges,
1890
+ metrics.timings
1891
+ ].some((entries) => Object.keys(entries ?? {}).length > 0);
1892
+ }
1893
+ function appendPerfMetricsPayload(payload) {
1894
+ fs.mkdirSync(path.dirname(captureFilePath), { recursive: true });
1895
+ fs.appendFileSync(captureFilePath, `${JSON.stringify(payload)}\n`, "utf8");
1896
+ captureSequence += 1;
1897
+ }
1704
1898
  function writePerfMetricsCapture(reason, resetAfterWrite) {
1705
1899
  if (!shouldCapture()) return false;
1706
1900
  const payload = buildPayload(reason);
1707
- const metrics = payload.metrics;
1708
- if (!(Object.keys(metrics.counters ?? {}).length > 0 || Object.keys(metrics.gauges ?? {}).length > 0 || Object.keys(metrics.timings ?? {}).length > 0)) return false;
1901
+ if (!payloadHasMetrics(payload)) return false;
1709
1902
  try {
1710
- fs.mkdirSync(path.dirname(captureFilePath), { recursive: true });
1711
- fs.appendFileSync(captureFilePath, `${JSON.stringify(payload)}\n`, "utf8");
1712
- captureSequence += 1;
1903
+ appendPerfMetricsPayload(payload);
1713
1904
  if (resetAfterWrite) resetPerfMetrics();
1714
1905
  return true;
1715
1906
  } catch {
@@ -1839,20 +2030,53 @@ var QueueOwnerTurnController = class {
1839
2030
  };
1840
2031
  //#endregion
1841
2032
  //#region src/cli/session/queue-owner-process.ts
2033
+ function isNonEmptyStringArray(value) {
2034
+ return Array.isArray(value) && value.length > 0 && value.every((entry) => typeof entry === "string" && entry.length > 0);
2035
+ }
2036
+ const NODE_TEST_FLAGS = new Set([
2037
+ "--experimental-test-coverage",
2038
+ "--test",
2039
+ "--test-name-pattern",
2040
+ "--test-reporter",
2041
+ "--test-reporter-destination"
2042
+ ]);
2043
+ const NODE_TEST_FLAGS_WITH_VALUE = new Set([
2044
+ "--test-name-pattern",
2045
+ "--test-reporter",
2046
+ "--test-reporter-destination"
2047
+ ]);
2048
+ const INSPECTOR_FLAGS_WITH_VALUE = new Set([
2049
+ "--inspect",
2050
+ "--inspect-brk",
2051
+ "--inspect-port",
2052
+ "--inspect-publish-uid",
2053
+ "--debug-port"
2054
+ ]);
2055
+ const INSPECTOR_FLAG_PREFIXES = [
2056
+ "--inspect=",
2057
+ "--inspect-brk=",
2058
+ "--inspect-port=",
2059
+ "--inspect-publish-uid=",
2060
+ "--debug-port="
2061
+ ];
2062
+ function classifyExecArgv(value) {
2063
+ if (value === void 0) return "drop";
2064
+ if (NODE_TEST_FLAGS_WITH_VALUE.has(value) || INSPECTOR_FLAGS_WITH_VALUE.has(value)) return "drop-with-value";
2065
+ return dropSingleExecArgv(value) ? "drop" : "keep";
2066
+ }
2067
+ function dropSingleExecArgv(value) {
2068
+ return NODE_TEST_FLAGS.has(value) || value.startsWith("--test-") || INSPECTOR_FLAG_PREFIXES.some((prefix) => value.startsWith(prefix));
2069
+ }
1842
2070
  function sanitizeQueueOwnerExecArgv(execArgv = process.execArgv) {
1843
2071
  const sanitized = [];
1844
2072
  for (let index = 0; index < execArgv.length; index += 1) {
1845
- const value = execArgv[index];
1846
- if (value === "--experimental-test-coverage" || value === "--test") continue;
1847
- if (value === "--test-name-pattern" || value === "--test-reporter" || value === "--test-reporter-destination") {
2073
+ const value = execArgv[index] ?? "";
2074
+ const decision = classifyExecArgv(value);
2075
+ if (decision === "drop") continue;
2076
+ if (decision === "drop-with-value") {
1848
2077
  index += 1;
1849
2078
  continue;
1850
2079
  }
1851
- if (value.startsWith("--test-")) continue;
1852
- if (value === "--inspect" || value === "--inspect-brk" || value === "--inspect-port" || value === "--inspect-publish-uid" || value.startsWith("--inspect=") || value.startsWith("--inspect-brk=") || value.startsWith("--inspect-port=") || value.startsWith("--inspect-publish-uid=") || value === "--debug-port" || value.startsWith("--debug-port=")) {
1853
- if (value === "--inspect" || value === "--inspect-brk" || value === "--inspect-port" || value === "--inspect-publish-uid" || value === "--debug-port") index += 1;
1854
- continue;
1855
- }
1856
2080
  sanitized.push(value);
1857
2081
  }
1858
2082
  return sanitized;
@@ -1870,7 +2094,7 @@ function resolveQueueOwnerSpawnArgs(argv = process.argv) {
1870
2094
  const override = process.env.ACPX_QUEUE_OWNER_ARGS;
1871
2095
  if (override) {
1872
2096
  const parsed = JSON.parse(override);
1873
- if (Array.isArray(parsed) && parsed.length > 0 && parsed.every((value) => typeof value === "string" && value.length > 0)) return [...parsed];
2097
+ if (isNonEmptyStringArray(parsed)) return [...parsed];
1874
2098
  throw new Error("acpx self-spawn failed: invalid ACPX_QUEUE_OWNER_ARGS");
1875
2099
  }
1876
2100
  const entry = argv[1];
@@ -1937,6 +2161,10 @@ async function countExistingSegments(sessionId, maxSegments) {
1937
2161
  if (await pathExists(sessionEventActivePath(sessionId))) count += 1;
1938
2162
  return count;
1939
2163
  }
2164
+ async function resolveInitialSegmentCount(record, maxSegments) {
2165
+ if (Number.isInteger(record.eventLog.segment_count) && record.eventLog.segment_count > 0) return record.eventLog.segment_count;
2166
+ return await countExistingSegments(record.acpxRecordId, maxSegments) || 1;
2167
+ }
1940
2168
  async function rotateSegments(sessionId, maxSegments) {
1941
2169
  const active = sessionEventActivePath(sessionId);
1942
2170
  const overflow = sessionEventSegmentPath(sessionId, maxSegments);
@@ -2028,7 +2256,7 @@ var SessionEventWriter = class SessionEventWriter {
2028
2256
  const maxSegments = options.maxSegments ?? record.eventLog.max_segments ?? 5;
2029
2257
  const activePath = sessionEventActivePath(record.acpxRecordId);
2030
2258
  const activeSizeBytes = await statSize(activePath);
2031
- const segmentCount = Number.isInteger(record.eventLog.segment_count) && record.eventLog.segment_count > 0 ? record.eventLog.segment_count : await countExistingSegments(record.acpxRecordId, maxSegments) || 1;
2259
+ const segmentCount = await resolveInitialSegmentCount(record, maxSegments);
2032
2260
  return new SessionEventWriter(record, lock, {
2033
2261
  maxSegmentBytes,
2034
2262
  maxSegments
@@ -2148,23 +2376,31 @@ function toPromptResult(stopReason, sessionId, client) {
2148
2376
  permissionStats: client.getPermissionStats()
2149
2377
  };
2150
2378
  }
2379
+ function requestedModelId(value) {
2380
+ return typeof value === "string" ? value.trim() : "";
2381
+ }
2382
+ function advertisedModelsForRecord(record) {
2383
+ const availableModels = record.acpx?.available_models;
2384
+ if (!Array.isArray(availableModels)) return;
2385
+ return {
2386
+ currentModelId: record.acpx?.current_model_id ?? "",
2387
+ availableModels: availableModels.map((modelId) => ({
2388
+ modelId,
2389
+ name: modelId
2390
+ }))
2391
+ };
2392
+ }
2151
2393
  async function applyPromptModelIfAdvertised(params) {
2152
- const requestedModel = typeof params.requestedModel === "string" ? params.requestedModel.trim() : "";
2394
+ const requestedModel = requestedModelId(params.requestedModel);
2153
2395
  if (!requestedModel) return;
2154
- const availableModels = params.record.acpx?.available_models;
2396
+ const models = advertisedModelsForRecord(params.record);
2155
2397
  assertRequestedModelSupported({
2156
2398
  requestedModel,
2157
- models: Array.isArray(availableModels) ? {
2158
- currentModelId: params.record.acpx?.current_model_id ?? "",
2159
- availableModels: availableModels.map((modelId) => ({
2160
- modelId,
2161
- name: modelId
2162
- }))
2163
- } : void 0,
2399
+ models,
2164
2400
  agentCommand: params.record.agentCommand,
2165
2401
  context: "apply"
2166
2402
  });
2167
- if (!Array.isArray(availableModels)) return;
2403
+ if (!models) return;
2168
2404
  if (params.record.acpx?.current_model_id === requestedModel) {
2169
2405
  setDesiredModelId(params.record, requestedModel);
2170
2406
  return;
@@ -2198,6 +2434,7 @@ function extractJsonRpcResponseInfo(message) {
2198
2434
  hasError
2199
2435
  };
2200
2436
  }
2437
+ const SESSION_RECONNECT_METHODS = new Set(["session/load", "session/resume"]);
2201
2438
  function filterRecoverableLoadFallbackOutput(messages) {
2202
2439
  const requestMethodById = /* @__PURE__ */ new Map();
2203
2440
  const failedLoadRequestIds = /* @__PURE__ */ new Set();
@@ -2209,12 +2446,13 @@ function filterRecoverableLoadFallbackOutput(messages) {
2209
2446
  }
2210
2447
  const response = extractJsonRpcResponseInfo(message);
2211
2448
  if (!response || !response.hasError) continue;
2212
- if (requestMethodById.get(response.idKey) === "session/load") failedLoadRequestIds.add(response.idKey);
2449
+ const requestMethod = requestMethodById.get(response.idKey);
2450
+ if (requestMethod && SESSION_RECONNECT_METHODS.has(requestMethod)) failedLoadRequestIds.add(response.idKey);
2213
2451
  }
2214
2452
  if (failedLoadRequestIds.size === 0) return messages;
2215
2453
  return messages.filter((message) => {
2216
2454
  const request = extractJsonRpcRequestInfo(message);
2217
- if (request && request.method === "session/load" && failedLoadRequestIds.has(request.idKey)) return false;
2455
+ if (request && SESSION_RECONNECT_METHODS.has(request.method) && failedLoadRequestIds.has(request.idKey)) return false;
2218
2456
  const response = extractJsonRpcResponseInfo(message);
2219
2457
  if (response && failedLoadRequestIds.has(response.idKey)) return false;
2220
2458
  return true;
@@ -2224,52 +2462,97 @@ function emitPromptRetryNotice(params) {
2224
2462
  if (params.suppressSdkConsoleErrors) return;
2225
2463
  process.stderr.write(`[acpx] prompt failed (${formatErrorMessage(params.error)}), retrying in ${params.delayMs}ms (attempt ${params.attempt}/${params.maxRetries})\n`);
2226
2464
  }
2465
+ function emitConnectPerfMetric(startedAt, verbose) {
2466
+ if (!verbose) return;
2467
+ process.stderr.write(`[acpx] ${formatPerfMetric("prompt.connect_and_load", Date.now() - startedAt)}\n`);
2468
+ }
2469
+ function emitPromptPerfMetric(startedAt, verbose) {
2470
+ if (!verbose) return;
2471
+ process.stderr.write(`[acpx] ${formatPerfMetric("prompt.agent_turn", Date.now() - startedAt)}\n`);
2472
+ }
2473
+ function emitPromptHookError(error, verbose) {
2474
+ if (!verbose) return;
2475
+ process.stderr.write("[acpx] onPromptActive hook failed: " + formatErrorMessage(error) + "\n");
2476
+ }
2477
+ function emitPromptDisconnectNotice(snapshot, verbose) {
2478
+ const lastExit = snapshot.lastExit;
2479
+ if (!lastExit?.unexpectedDuringPrompt || !verbose) return;
2480
+ process.stderr.write("[acpx] agent disconnected during prompt (" + lastExit.reason + ", exit=" + lastExit.exitCode + ", signal=" + (lastExit.signal ?? "none") + ")\n");
2481
+ }
2482
+ function shouldRetryRuntimePrompt(error, attempt, maxRetries, snapshot, hasSideEffects) {
2483
+ if (!shouldRetryPromptAttempt(error, attempt, maxRetries, hasSideEffects)) return false;
2484
+ return snapshot.lastExit?.unexpectedDuringPrompt !== true;
2485
+ }
2486
+ function shouldRetryPromptAttempt(error, attempt, maxRetries, hasSideEffects) {
2487
+ return attempt < maxRetries && !hasSideEffects() && isRetryablePromptError(error);
2488
+ }
2489
+ async function waitBeforePromptRetry(error, attempt, maxRetries, suppressSdkConsoleErrors) {
2490
+ const delayMs = Math.min(1e3 * 2 ** attempt, 1e4);
2491
+ emitPromptRetryNotice({
2492
+ error,
2493
+ delayMs,
2494
+ attempt: attempt + 1,
2495
+ maxRetries,
2496
+ suppressSdkConsoleErrors
2497
+ });
2498
+ await waitMs(delayMs);
2499
+ }
2500
+ function buildQueuedTaskRunOptions(sessionRecordId, task, options, outputFormatter) {
2501
+ return {
2502
+ sessionRecordId,
2503
+ mcpServers: options.mcpServers,
2504
+ prompt: task.prompt ?? textPrompt(task.message),
2505
+ permissionMode: task.permissionMode,
2506
+ resumePolicy: task.resumePolicy,
2507
+ nonInteractivePermissions: task.nonInteractivePermissions ?? options.nonInteractivePermissions,
2508
+ permissionPolicy: task.permissionPolicy,
2509
+ authCredentials: options.authCredentials,
2510
+ authPolicy: options.authPolicy,
2511
+ outputFormatter,
2512
+ timeoutMs: task.timeoutMs,
2513
+ suppressSdkConsoleErrors: task.suppressSdkConsoleErrors ?? options.suppressSdkConsoleErrors,
2514
+ verbose: options.verbose,
2515
+ promptRetries: task.promptRetries ?? options.promptRetries ?? 0,
2516
+ sessionOptions: mergeSessionOptions(task.sessionOptions, options.sessionOptions),
2517
+ onClientAvailable: options.onClientAvailable,
2518
+ onClientClosed: options.onClientClosed,
2519
+ onPromptActive: options.onPromptActive,
2520
+ client: options.sharedClient
2521
+ };
2522
+ }
2523
+ function sendQueuedTaskResult(task, result) {
2524
+ if (!task.waitForCompletion) return;
2525
+ task.send({
2526
+ type: "result",
2527
+ requestId: task.requestId,
2528
+ result
2529
+ });
2530
+ }
2531
+ function sendQueuedTaskError(task, error) {
2532
+ if (!task.waitForCompletion) return;
2533
+ const normalizedError = normalizeOutputError(error, {
2534
+ origin: "runtime",
2535
+ detailCode: "QUEUE_RUNTIME_PROMPT_FAILED"
2536
+ });
2537
+ const alreadyEmitted = error.outputAlreadyEmitted === true;
2538
+ task.send({
2539
+ type: "error",
2540
+ requestId: task.requestId,
2541
+ code: normalizedError.code,
2542
+ detailCode: normalizedError.detailCode,
2543
+ origin: normalizedError.origin,
2544
+ message: normalizedError.message,
2545
+ retryable: normalizedError.retryable,
2546
+ acp: normalizedError.acp,
2547
+ outputAlreadyEmitted: alreadyEmitted
2548
+ });
2549
+ }
2227
2550
  async function runQueuedTask(sessionRecordId, task, options) {
2228
2551
  const outputFormatter = task.waitForCompletion ? new QueueTaskOutputFormatter(task) : DISCARD_OUTPUT_FORMATTER;
2229
2552
  try {
2230
- const result = await runSessionPrompt({
2231
- sessionRecordId,
2232
- mcpServers: options.mcpServers,
2233
- prompt: task.prompt ?? textPrompt(task.message),
2234
- permissionMode: task.permissionMode,
2235
- resumePolicy: task.resumePolicy,
2236
- nonInteractivePermissions: task.nonInteractivePermissions ?? options.nonInteractivePermissions,
2237
- permissionPolicy: task.permissionPolicy,
2238
- authCredentials: options.authCredentials,
2239
- authPolicy: options.authPolicy,
2240
- outputFormatter,
2241
- timeoutMs: task.timeoutMs,
2242
- suppressSdkConsoleErrors: task.suppressSdkConsoleErrors ?? options.suppressSdkConsoleErrors,
2243
- verbose: options.verbose,
2244
- promptRetries: task.promptRetries ?? options.promptRetries ?? 0,
2245
- sessionOptions: mergeSessionOptions(task.sessionOptions, options.sessionOptions),
2246
- onClientAvailable: options.onClientAvailable,
2247
- onClientClosed: options.onClientClosed,
2248
- onPromptActive: options.onPromptActive,
2249
- client: options.sharedClient
2250
- });
2251
- if (task.waitForCompletion) task.send({
2252
- type: "result",
2253
- requestId: task.requestId,
2254
- result
2255
- });
2553
+ sendQueuedTaskResult(task, await runSessionPrompt(buildQueuedTaskRunOptions(sessionRecordId, task, options, outputFormatter)));
2256
2554
  } catch (error) {
2257
- const normalizedError = normalizeOutputError(error, {
2258
- origin: "runtime",
2259
- detailCode: "QUEUE_RUNTIME_PROMPT_FAILED"
2260
- });
2261
- const alreadyEmitted = error.outputAlreadyEmitted === true;
2262
- if (task.waitForCompletion) task.send({
2263
- type: "error",
2264
- requestId: task.requestId,
2265
- code: normalizedError.code,
2266
- detailCode: normalizedError.detailCode,
2267
- origin: normalizedError.origin,
2268
- message: normalizedError.message,
2269
- retryable: normalizedError.retryable,
2270
- acp: normalizedError.acp,
2271
- outputAlreadyEmitted: alreadyEmitted
2272
- });
2555
+ sendQueuedTaskError(task, error);
2273
2556
  if (error instanceof InterruptedError) throw error;
2274
2557
  } finally {
2275
2558
  task.close();
@@ -2408,41 +2691,117 @@ async function runSessionPrompt(options) {
2408
2691
  return await client.setSessionConfigOption(activeSessionIdForControl, configId, value);
2409
2692
  }
2410
2693
  };
2694
+ const flushConnectOutput = (loadError) => {
2695
+ bufferingConnectOutput = false;
2696
+ const messages = loadError == null ? pendingConnectOutputMessages : filterRecoverableLoadFallbackOutput(pendingConnectOutputMessages);
2697
+ for (const message of messages) output.onAcpMessage(message);
2698
+ pendingConnectOutputMessages.length = 0;
2699
+ };
2700
+ const connectForPrompt = async () => {
2701
+ const connectStartedAt = Date.now();
2702
+ try {
2703
+ const connected = await measurePerf("runtime.connect_and_load", async () => {
2704
+ return await connectAndLoadSession({
2705
+ client,
2706
+ record,
2707
+ resumePolicy: options.resumePolicy,
2708
+ timeoutMs: options.timeoutMs,
2709
+ verbose: options.verbose,
2710
+ activeController,
2711
+ onClientAvailable: (controller) => {
2712
+ options.onClientAvailable?.(controller);
2713
+ notifiedClientAvailable = true;
2714
+ },
2715
+ onConnectedRecord: (connectedRecord) => {
2716
+ connectedRecord.lastPromptAt = isoNow();
2717
+ },
2718
+ onSessionIdResolved: (sessionId) => {
2719
+ activeSessionIdForControl = sessionId;
2720
+ }
2721
+ });
2722
+ });
2723
+ flushConnectOutput(connected.loadError);
2724
+ emitConnectPerfMetric(connectStartedAt, options.verbose);
2725
+ return connected;
2726
+ } catch (error) {
2727
+ flushConnectOutput();
2728
+ throw error;
2729
+ }
2730
+ };
2731
+ const buildPromptStartedHook = (attempt) => {
2732
+ if (attempt !== 0 || !options.onPromptActive) return;
2733
+ return async () => {
2734
+ try {
2735
+ await options.onPromptActive?.();
2736
+ } catch (error) {
2737
+ emitPromptHookError(error, options.verbose);
2738
+ }
2739
+ };
2740
+ };
2741
+ const runPromptAttempt = async (sessionId, attempt) => {
2742
+ const promptStartedAt = Date.now();
2743
+ const response = await measurePerf("runtime.prompt.agent_turn", async () => {
2744
+ return await runPromptTurn({
2745
+ client,
2746
+ sessionId,
2747
+ prompt: options.prompt,
2748
+ timeoutMs: options.timeoutMs,
2749
+ conversation,
2750
+ promptMessageId,
2751
+ onPromptStarted: buildPromptStartedHook(attempt)
2752
+ });
2753
+ });
2754
+ emitPromptPerfMetric(promptStartedAt, options.verbose);
2755
+ return response;
2756
+ };
2757
+ const handlePromptFailure = async (error, attempt) => {
2758
+ const snapshot = client.getAgentLifecycleSnapshot();
2759
+ if (shouldRetryRuntimePrompt(error, attempt, options.promptRetries ?? 0, snapshot, () => promptTurnHadSideEffects)) {
2760
+ await waitBeforePromptRetry(error, attempt, options.promptRetries ?? 0, options.suppressSdkConsoleErrors);
2761
+ return promptTurnHadSideEffects ? await failRuntimePrompt(error, snapshot) : "retry";
2762
+ }
2763
+ return await failRuntimePrompt(error, snapshot);
2764
+ };
2765
+ const failRuntimePrompt = async (error, snapshot) => {
2766
+ promptTurnActive = false;
2767
+ applyLifecycleSnapshotToRecord(record, snapshot);
2768
+ emitPromptDisconnectNotice(snapshot, options.verbose);
2769
+ const normalizedError = normalizeOutputError(error, { origin: "runtime" });
2770
+ await flushPendingMessages(false).catch(() => {});
2771
+ output.flush();
2772
+ record.lastUsedAt = isoNow();
2773
+ applyConversation(record, conversation);
2774
+ record.acpx = acpxState;
2775
+ const propagated = error instanceof Error ? error : new Error(formatErrorMessage(error));
2776
+ propagated.outputAlreadyEmitted = sawAcpMessage;
2777
+ propagated.normalizedOutputError = normalizedError;
2778
+ throw propagated;
2779
+ };
2780
+ const runPromptWithRetries = async (sessionId) => {
2781
+ promptTurnActive = true;
2782
+ for (let attempt = 0;; attempt++) try {
2783
+ return await runPromptAttempt(sessionId, attempt);
2784
+ } catch (error) {
2785
+ if (await handlePromptFailure(error, attempt) === "retry") continue;
2786
+ }
2787
+ };
2788
+ const savePromptSuccess = async (response) => {
2789
+ await flushPendingMessages(false);
2790
+ output.flush();
2791
+ record.lastUsedAt = isoNow();
2792
+ record.closed = false;
2793
+ record.closedAt = void 0;
2794
+ record.protocolVersion = client.initializeResult?.protocolVersion;
2795
+ record.agentCapabilities = client.initializeResult?.agentCapabilities;
2796
+ applyConversation(record, conversation);
2797
+ record.acpx = acpxState;
2798
+ applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());
2799
+ stopTotalTimer();
2800
+ return response;
2801
+ };
2411
2802
  try {
2412
2803
  return await withInterrupt(async () => {
2413
- const connectStartedAt = Date.now();
2414
- const { sessionId: activeSessionId, resumed, loadError } = await measurePerf("runtime.connect_and_load", async () => {
2415
- try {
2416
- return await connectAndLoadSession({
2417
- client,
2418
- record,
2419
- resumePolicy: options.resumePolicy,
2420
- timeoutMs: options.timeoutMs,
2421
- verbose: options.verbose,
2422
- activeController,
2423
- onClientAvailable: (controller) => {
2424
- options.onClientAvailable?.(controller);
2425
- notifiedClientAvailable = true;
2426
- },
2427
- onConnectedRecord: (connectedRecord) => {
2428
- connectedRecord.lastPromptAt = isoNow();
2429
- },
2430
- onSessionIdResolved: (sessionId) => {
2431
- activeSessionIdForControl = sessionId;
2432
- }
2433
- });
2434
- } catch (error) {
2435
- bufferingConnectOutput = false;
2436
- for (const message of pendingConnectOutputMessages) output.onAcpMessage(message);
2437
- pendingConnectOutputMessages.length = 0;
2438
- throw error;
2439
- }
2440
- });
2441
- bufferingConnectOutput = false;
2442
- const connectOutputMessages = loadError == null ? pendingConnectOutputMessages : filterRecoverableLoadFallbackOutput(pendingConnectOutputMessages);
2443
- for (const message of connectOutputMessages) output.onAcpMessage(message);
2444
- pendingConnectOutputMessages.length = 0;
2445
- if (options.verbose) process.stderr.write(`[acpx] ${formatPerfMetric("prompt.connect_and_load", Date.now() - connectStartedAt)}\n`);
2804
+ const { sessionId: activeSessionId, resumed, loadError } = await connectForPrompt();
2446
2805
  await applyPromptModelIfAdvertised({
2447
2806
  client,
2448
2807
  sessionId: activeSessionId,
@@ -2452,72 +2811,8 @@ async function runSessionPrompt(options) {
2452
2811
  });
2453
2812
  output.setContext({ sessionId: record.acpxRecordId });
2454
2813
  await liveCheckpoint.checkpoint();
2455
- const maxRetries = options.promptRetries ?? 0;
2456
- let response;
2457
- promptTurnActive = true;
2458
- for (let attempt = 0;; attempt++) try {
2459
- const promptStartedAt = Date.now();
2460
- response = await measurePerf("runtime.prompt.agent_turn", async () => {
2461
- return await runPromptTurn({
2462
- client,
2463
- sessionId: activeSessionId,
2464
- prompt: options.prompt,
2465
- timeoutMs: options.timeoutMs,
2466
- conversation,
2467
- promptMessageId,
2468
- onPromptStarted: attempt === 0 && options.onPromptActive ? async () => {
2469
- try {
2470
- await options.onPromptActive?.();
2471
- } catch (error) {
2472
- if (options.verbose) process.stderr.write("[acpx] onPromptActive hook failed: " + formatErrorMessage(error) + "\n");
2473
- }
2474
- } : void 0
2475
- });
2476
- });
2477
- if (options.verbose) process.stderr.write(`[acpx] ${formatPerfMetric("prompt.agent_turn", Date.now() - promptStartedAt)}\n`);
2478
- break;
2479
- } catch (error) {
2480
- const snapshot = client.getAgentLifecycleSnapshot();
2481
- const agentCrashed = snapshot.lastExit?.unexpectedDuringPrompt === true;
2482
- if (attempt < maxRetries && !agentCrashed && !promptTurnHadSideEffects && isRetryablePromptError(error)) {
2483
- const delayMs = Math.min(1e3 * 2 ** attempt, 1e4);
2484
- emitPromptRetryNotice({
2485
- error,
2486
- delayMs,
2487
- attempt: attempt + 1,
2488
- maxRetries,
2489
- suppressSdkConsoleErrors: options.suppressSdkConsoleErrors
2490
- });
2491
- await waitMs(delayMs);
2492
- if (!promptTurnHadSideEffects) continue;
2493
- }
2494
- promptTurnActive = false;
2495
- applyLifecycleSnapshotToRecord(record, snapshot);
2496
- const lastExit = snapshot.lastExit;
2497
- if (lastExit?.unexpectedDuringPrompt && options.verbose) process.stderr.write("[acpx] agent disconnected during prompt (" + lastExit.reason + ", exit=" + lastExit.exitCode + ", signal=" + (lastExit.signal ?? "none") + ")\n");
2498
- const normalizedError = normalizeOutputError(error, { origin: "runtime" });
2499
- await flushPendingMessages(false).catch(() => {});
2500
- output.flush();
2501
- record.lastUsedAt = isoNow();
2502
- applyConversation(record, conversation);
2503
- record.acpx = acpxState;
2504
- const propagated = error instanceof Error ? error : new Error(formatErrorMessage(error));
2505
- propagated.outputAlreadyEmitted = sawAcpMessage;
2506
- propagated.normalizedOutputError = normalizedError;
2507
- throw propagated;
2508
- }
2814
+ const response = await savePromptSuccess(await runPromptWithRetries(activeSessionId));
2509
2815
  promptTurnActive = false;
2510
- await flushPendingMessages(false);
2511
- output.flush();
2512
- record.lastUsedAt = isoNow();
2513
- record.closed = false;
2514
- record.closedAt = void 0;
2515
- record.protocolVersion = client.initializeResult?.protocolVersion;
2516
- record.agentCapabilities = client.initializeResult?.agentCapabilities;
2517
- applyConversation(record, conversation);
2518
- record.acpx = acpxState;
2519
- applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());
2520
- stopTotalTimer();
2521
2816
  return {
2522
2817
  ...toPromptResult(response.stopReason, record.acpxRecordId, client),
2523
2818
  record,
@@ -2580,6 +2875,25 @@ async function runOnce(options) {
2580
2875
  },
2581
2876
  sessionOptions: options.sessionOptions
2582
2877
  });
2878
+ const runExecPromptAttempt = async (sessionId) => {
2879
+ return await measurePerf("runtime.exec.prompt", async () => {
2880
+ return await withTimeout(client.prompt(sessionId, options.prompt), options.timeoutMs);
2881
+ });
2882
+ };
2883
+ const runExecPromptWithRetries = async (sessionId) => {
2884
+ const maxRetries = options.promptRetries ?? 0;
2885
+ promptTurnActive = true;
2886
+ for (let attempt = 0;; attempt++) try {
2887
+ return await runExecPromptAttempt(sessionId);
2888
+ } catch (error) {
2889
+ if (shouldRetryPromptAttempt(error, attempt, maxRetries, () => promptTurnHadSideEffects)) {
2890
+ await waitBeforePromptRetry(error, attempt, maxRetries, options.suppressSdkConsoleErrors);
2891
+ if (!promptTurnHadSideEffects) continue;
2892
+ }
2893
+ promptTurnActive = false;
2894
+ throw error;
2895
+ }
2896
+ };
2583
2897
  try {
2584
2898
  return await withInterrupt(async () => {
2585
2899
  await measurePerf("runtime.exec.start", async () => {
@@ -2598,30 +2912,7 @@ async function runOnce(options) {
2598
2912
  timeoutMs: options.timeoutMs
2599
2913
  });
2600
2914
  output.setContext({ sessionId });
2601
- const maxRetries = options.promptRetries ?? 0;
2602
- let response;
2603
- promptTurnActive = true;
2604
- for (let attempt = 0;; attempt++) try {
2605
- response = await measurePerf("runtime.exec.prompt", async () => {
2606
- return await withTimeout(client.prompt(sessionId, options.prompt), options.timeoutMs);
2607
- });
2608
- break;
2609
- } catch (error) {
2610
- if (attempt < maxRetries && !promptTurnHadSideEffects && isRetryablePromptError(error)) {
2611
- const delayMs = Math.min(1e3 * 2 ** attempt, 1e4);
2612
- emitPromptRetryNotice({
2613
- error,
2614
- delayMs,
2615
- attempt: attempt + 1,
2616
- maxRetries,
2617
- suppressSdkConsoleErrors: options.suppressSdkConsoleErrors
2618
- });
2619
- await waitMs(delayMs);
2620
- if (!promptTurnHadSideEffects) continue;
2621
- }
2622
- promptTurnActive = false;
2623
- throw error;
2624
- }
2915
+ const response = await runExecPromptWithRetries(sessionId);
2625
2916
  promptTurnActive = false;
2626
2917
  output.flush();
2627
2918
  return toPromptResult(response.stopReason, sessionId, client);
@@ -2678,13 +2969,8 @@ async function submitToRunningOwner(options, waitForCompletion) {
2678
2969
  sessionOptions: options.sessionOptions
2679
2970
  });
2680
2971
  }
2681
- async function runSessionQueueOwner(options) {
2682
- const lease = await tryAcquireQueueOwnerLease(options.sessionId);
2683
- if (!lease) return;
2684
- const sessionRecord = await resolveSessionRecord(options.sessionId);
2685
- let owner;
2686
- let heartbeatTimer;
2687
- const sharedClient = new AcpClient({
2972
+ function createQueueOwnerSharedClient(options, sessionRecord) {
2973
+ return new AcpClient({
2688
2974
  agentCommand: sessionRecord.agentCommand,
2689
2975
  cwd: absolutePath(sessionRecord.cwd),
2690
2976
  mcpServers: options.mcpServers,
@@ -2697,11 +2983,9 @@ async function runSessionQueueOwner(options) {
2697
2983
  verbose: options.verbose,
2698
2984
  sessionOptions: mergeSessionOptions(options.sessionOptions, sessionOptionsFromRecord(sessionRecord))
2699
2985
  });
2700
- const ttlMs = normalizeQueueOwnerTtlMs(options.ttlMs);
2701
- const maxQueueDepth = Math.max(1, Math.round(options.maxQueueDepth ?? 16));
2702
- const taskPollTimeoutMs = ttlMs === 0 ? void 0 : ttlMs;
2703
- const initialTaskPollTimeoutMs = taskPollTimeoutMs == null ? void 0 : Math.max(taskPollTimeoutMs, 1e3);
2704
- const turnController = new QueueOwnerTurnController({
2986
+ }
2987
+ function createQueueOwnerTurnController(options) {
2988
+ return new QueueOwnerTurnController({
2705
2989
  withTimeout: async (run, timeoutMs) => await withTimeout(run(), timeoutMs),
2706
2990
  setSessionModeFallback: async (modeId, timeoutMs) => {
2707
2991
  await runSessionSetModeDirect({
@@ -2744,12 +3028,49 @@ async function runSessionQueueOwner(options) {
2744
3028
  })).response;
2745
3029
  }
2746
3030
  });
3031
+ }
3032
+ function logDeferredCancelFailure(error, verbose) {
3033
+ if (!verbose) return;
3034
+ process.stderr.write(`[acpx] failed to apply deferred cancel: ${formatErrorMessage(error)}\n`);
3035
+ }
3036
+ function logQueueOwnerReady(params) {
3037
+ if (!params.verbose) return;
3038
+ process.stderr.write(`[acpx] queue owner ready for session ${params.sessionId} (ttlMs=${params.ttlMs}, maxQueueDepth=${params.maxQueueDepth})\n`);
3039
+ }
3040
+ async function closeQueueOwnerRuntime(params) {
3041
+ if (params.heartbeatTimer) clearInterval(params.heartbeatTimer);
3042
+ params.turnController.beginClosing();
3043
+ await params.owner?.close();
3044
+ await params.sharedClient.close().catch(() => {});
3045
+ await writeQueueOwnerLifecycleSnapshot(params.sessionId, params.sharedClient);
3046
+ await releaseQueueOwnerLease(params.lease);
3047
+ if (params.verbose) process.stderr.write(`[acpx] queue owner stopped for session ${params.sessionId}\n`);
3048
+ }
3049
+ async function writeQueueOwnerLifecycleSnapshot(sessionId, sharedClient) {
3050
+ try {
3051
+ const record = await resolveSessionRecord(sessionId);
3052
+ applyLifecycleSnapshotToRecord(record, sharedClient.getAgentLifecycleSnapshot());
3053
+ await writeSessionRecord(record);
3054
+ } catch {}
3055
+ }
3056
+ async function runSessionQueueOwner(options) {
3057
+ const lease = await tryAcquireQueueOwnerLease(options.sessionId);
3058
+ if (!lease) return;
3059
+ const sessionRecord = await resolveSessionRecord(options.sessionId);
3060
+ let owner;
3061
+ let heartbeatTimer;
3062
+ const sharedClient = createQueueOwnerSharedClient(options, sessionRecord);
3063
+ const ttlMs = normalizeQueueOwnerTtlMs(options.ttlMs);
3064
+ const maxQueueDepth = Math.max(1, Math.round(options.maxQueueDepth ?? 16));
3065
+ const taskPollTimeoutMs = ttlMs === 0 ? void 0 : ttlMs;
3066
+ const initialTaskPollTimeoutMs = taskPollTimeoutMs == null ? void 0 : Math.max(taskPollTimeoutMs, 1e3);
3067
+ const turnController = createQueueOwnerTurnController(options);
2747
3068
  const applyPendingCancel = async () => {
2748
3069
  return await turnController.applyPendingCancel();
2749
3070
  };
2750
3071
  const scheduleApplyPendingCancel = () => {
2751
3072
  applyPendingCancel().catch((error) => {
2752
- if (options.verbose) process.stderr.write(`[acpx] failed to apply deferred cancel: ${formatErrorMessage(error)}\n`);
3073
+ logDeferredCancelFailure(error, options.verbose);
2753
3074
  });
2754
3075
  };
2755
3076
  const setActiveController = (controller) => {
@@ -2797,7 +3118,12 @@ async function runSessionQueueOwner(options) {
2797
3118
  refreshQueueOwnerLease(lease, { queueDepth }).catch(() => {});
2798
3119
  }
2799
3120
  });
2800
- if (options.verbose) process.stderr.write(`[acpx] queue owner ready for session ${options.sessionId} (ttlMs=${ttlMs}, maxQueueDepth=${maxQueueDepth})\n`);
3121
+ logQueueOwnerReady({
3122
+ sessionId: options.sessionId,
3123
+ ttlMs,
3124
+ maxQueueDepth,
3125
+ verbose: options.verbose
3126
+ });
2801
3127
  await refreshQueueOwnerLease(lease, { queueDepth: owner.queueDepth() }).catch(() => {});
2802
3128
  heartbeatTimer = setInterval(() => {
2803
3129
  refreshQueueOwnerLease(lease, { queueDepth: owner?.queueDepth() ?? 0 }).catch(() => {});
@@ -2833,17 +3159,15 @@ async function runSessionQueueOwner(options) {
2833
3159
  });
2834
3160
  }
2835
3161
  } finally {
2836
- if (heartbeatTimer) clearInterval(heartbeatTimer);
2837
- turnController.beginClosing();
2838
- if (owner) await owner.close();
2839
- await sharedClient.close().catch(() => {});
2840
- try {
2841
- const record = await resolveSessionRecord(options.sessionId);
2842
- applyLifecycleSnapshotToRecord(record, sharedClient.getAgentLifecycleSnapshot());
2843
- await writeSessionRecord(record);
2844
- } catch {}
2845
- await releaseQueueOwnerLease(lease);
2846
- if (options.verbose) process.stderr.write(`[acpx] queue owner stopped for session ${options.sessionId}\n`);
3162
+ await closeQueueOwnerRuntime({
3163
+ lease,
3164
+ owner,
3165
+ heartbeatTimer,
3166
+ turnController,
3167
+ sharedClient,
3168
+ sessionId: options.sessionId,
3169
+ verbose: options.verbose
3170
+ });
2847
3171
  }
2848
3172
  }
2849
3173
  async function sendSession(options) {
@@ -2874,6 +3198,7 @@ var session_exports = /* @__PURE__ */ __exportAll({
2874
3198
  findSession: () => findSession,
2875
3199
  findSessionByDirectoryWalk: () => findSessionByDirectoryWalk,
2876
3200
  isProcessAlive: () => isProcessAlive,
3201
+ listAgentSessions: () => listAgentSessions,
2877
3202
  listSessions: () => listSessions,
2878
3203
  listSessionsForAgent: () => listSessionsForAgent,
2879
3204
  normalizeQueueOwnerTtlMs: () => normalizeQueueOwnerTtlMs,
@@ -2953,7 +3278,12 @@ function inferToolKindFromTitle(title) {
2953
3278
  if (!normalized) return;
2954
3279
  const head = normalized.split(":", 1)[0]?.trim();
2955
3280
  if (!head) return;
2956
- if (head.includes("read") || head.includes("cat") || head.includes("open") || head.includes("view")) return "read";
3281
+ if ([
3282
+ "read",
3283
+ "cat",
3284
+ "open",
3285
+ "view"
3286
+ ].some((needle) => head.includes(needle))) return "read";
2957
3287
  }
2958
3288
  function isReadLikeTool(tool) {
2959
3289
  return tool.kind?.trim().toLowerCase() === "read" || inferToolKindFromTitle(tool.title) === "read";
@@ -2996,14 +3326,25 @@ function sanitizeToolMessage(message) {
2996
3326
  ...root,
2997
3327
  params: {
2998
3328
  ...params,
2999
- update: {
3000
- ...update,
3001
- rawOutput: Object.prototype.hasOwnProperty.call(update, "rawOutput") && update.rawOutput !== void 0 ? { content: SUPPRESSED_READ_OUTPUT } : update.rawOutput,
3002
- content: Object.prototype.hasOwnProperty.call(update, "content") && update.content !== void 0 ? sanitizeToolContent(update.content) : update.content
3003
- }
3329
+ update: sanitizeToolUpdate(update)
3004
3330
  }
3005
3331
  };
3006
3332
  }
3333
+ function sanitizeToolUpdate(update) {
3334
+ return {
3335
+ ...update,
3336
+ rawOutput: sanitizedRawOutput(update),
3337
+ content: sanitizedContent(update)
3338
+ };
3339
+ }
3340
+ function sanitizedRawOutput(update) {
3341
+ if (Object.prototype.hasOwnProperty.call(update, "rawOutput") && update.rawOutput !== void 0) return { content: SUPPRESSED_READ_OUTPUT };
3342
+ return update.rawOutput;
3343
+ }
3344
+ function sanitizedContent(update) {
3345
+ if (Object.prototype.hasOwnProperty.call(update, "content") && update.content !== void 0) return sanitizeToolContent(update.content);
3346
+ return update.content;
3347
+ }
3007
3348
  var JsonOutputFormatter = class {
3008
3349
  stdout;
3009
3350
  suppressReads;
@@ -3052,23 +3393,30 @@ var JsonOutputFormatter = class {
3052
3393
  };
3053
3394
  }
3054
3395
  sanitizeReadToolMessage(message) {
3396
+ const update = this.readToolUpdate(message);
3397
+ if (!update) return message;
3398
+ const toolCallId = typeof update.toolCallId === "string" ? update.toolCallId : void 0;
3399
+ if (!toolCallId) return message;
3400
+ const current = this.mergeToolState(toolCallId, update);
3401
+ this.toolStateById.set(toolCallId, current);
3402
+ return isReadLikeTool(current) ? sanitizeToolMessage(message) : message;
3403
+ }
3404
+ readToolUpdate(message) {
3055
3405
  const root = asRecord$1(message);
3056
- if (root?.method !== "session/update") return message;
3406
+ if (root?.method !== "session/update") return;
3057
3407
  const params = asRecord$1(root.params);
3058
3408
  const update = asRecord$1(params?.update);
3059
- if (!params || !update) return message;
3409
+ if (!params || !update) return;
3060
3410
  const sessionUpdate = update.sessionUpdate;
3061
- if (sessionUpdate !== "tool_call" && sessionUpdate !== "tool_call_update") return message;
3062
- const toolCallId = typeof update.toolCallId === "string" ? update.toolCallId : void 0;
3063
- if (!toolCallId) return message;
3411
+ if (sessionUpdate !== "tool_call" && sessionUpdate !== "tool_call_update") return;
3412
+ return update;
3413
+ }
3414
+ mergeToolState(toolCallId, update) {
3064
3415
  const previous = this.toolStateById.get(toolCallId) ?? {};
3065
- const current = {
3416
+ return {
3066
3417
  title: typeof update.title === "string" ? update.title : previous.title,
3067
3418
  kind: typeof update.kind === "string" || update.kind === null ? update.kind : previous.kind
3068
3419
  };
3069
- this.toolStateById.set(toolCallId, current);
3070
- if (!isReadLikeTool(current)) return message;
3071
- return sanitizeToolMessage(message);
3072
3420
  }
3073
3421
  onError(params) {
3074
3422
  this.stdout.write(`${JSON.stringify(buildJsonRpcErrorResponse({
@@ -3218,15 +3566,16 @@ function parseAuthMethodIdsFromAcpData(data) {
3218
3566
  const methodIds = [];
3219
3567
  if (typeof record.methodId === "string" && record.methodId.trim().length > 0) methodIds.push(record.methodId.trim());
3220
3568
  if (Array.isArray(record.methods)) for (const entry of record.methods) {
3221
- if (typeof entry === "string" && entry.trim().length > 0) {
3222
- methodIds.push(entry.trim());
3223
- continue;
3224
- }
3225
- const id = asRecord(entry)?.id;
3226
- if (typeof id === "string" && id.trim().length > 0) methodIds.push(id.trim());
3569
+ const id = parseAuthMethodIdEntry(entry);
3570
+ if (id) methodIds.push(id);
3227
3571
  }
3228
3572
  return dedupeStrings(methodIds);
3229
3573
  }
3574
+ function parseAuthMethodIdEntry(entry) {
3575
+ if (typeof entry === "string" && entry.trim().length > 0) return entry.trim();
3576
+ const id = asRecord(entry)?.id;
3577
+ return typeof id === "string" && id.trim().length > 0 ? id.trim() : void 0;
3578
+ }
3230
3579
  function renderAuthRequiredHint(params) {
3231
3580
  const methodIds = dedupeStrings([...parseAuthMethodIdsFromAcpData(params.acp?.data), ...parseAuthMethodIdsFromMessage(params.message)]);
3232
3581
  if (methodIds.length === 0) return "hint: run `acpx config show` to locate the active config, then add the required credential under `auth` and retry.";
@@ -3236,48 +3585,104 @@ function getTextErrorRemediationHints(params) {
3236
3585
  const lowerMessage = params.message.toLowerCase();
3237
3586
  if (params.detailCode === "AUTH_REQUIRED") return [renderAuthRequiredHint(params)];
3238
3587
  if (params.code === "TIMEOUT") return ["hint: increase `--timeout <seconds>` for long-running prompts, or check whether the agent/provider is stalled."];
3239
- if (params.code === "NO_SESSION") {
3240
- if (lowerMessage.includes("create one:")) return [];
3241
- return ["hint: the saved ACP session is missing or stale; start a fresh session with `acpx <agent> sessions new`, then retry."];
3242
- }
3243
- if (lowerMessage.includes("does not support session/load")) return ["hint: this adapter cannot resume saved ACP sessions; create a fresh one with `acpx <agent> sessions new` instead of reusing `--resume-session`."];
3244
- if (lowerMessage.includes("failed to resume acp session") || lowerMessage.includes("session/load")) return ["hint: rerun with `--verbose` to capture the ACP load failure details.", "hint: if you do not need the old backend session, start a fresh one with `acpx <agent> sessions new` and retry."];
3245
- if (/\b429\b/u.test(params.message) || lowerMessage.includes("rate limit") || lowerMessage.includes("quota exceeded")) return ["hint: the provider appears rate-limited; retry later, switch model, or check provider quota/billing."];
3246
- if (lowerMessage.includes("model not found") || lowerMessage.includes("unknown model") || lowerMessage.includes("invalid model")) return ["hint: check the configured model name for this agent, then retry with `--model <model>` or `sessions set-model <model>`."];
3247
- if (lowerMessage.includes("session/set_mode") || lowerMessage.includes("session/set_model") || lowerMessage.includes("session/set_config_option")) return ["hint: rerun with `--verbose` to capture the ACP method/error details before retrying."];
3248
- if (params.origin === "acp" && params.code === "RUNTIME" && (params.acp?.code === -32602 || params.acp?.code === -32603 || lowerMessage.includes("internal error"))) return ["hint: rerun with `--verbose` to capture the underlying ACP error details."];
3249
- return [];
3588
+ if (params.code === "NO_SESSION") return noSessionHints(lowerMessage);
3589
+ return matchingTextErrorRule(params, lowerMessage)?.hints ?? [];
3590
+ }
3591
+ const TEXT_ERROR_HINT_RULES = [
3592
+ {
3593
+ matches: (_params, lowerMessage) => isUnsupportedSessionLoadError(lowerMessage),
3594
+ hints: ["hint: this adapter cannot resume saved ACP sessions; create a fresh one with `acpx <agent> sessions new` instead of reusing `--resume-session`."]
3595
+ },
3596
+ {
3597
+ matches: (_params, lowerMessage) => isSessionLoadError(lowerMessage),
3598
+ hints: ["hint: rerun with `--verbose` to capture the ACP load failure details.", "hint: if you do not need the old backend session, start a fresh one with `acpx <agent> sessions new` and retry."]
3599
+ },
3600
+ {
3601
+ matches: (params, lowerMessage) => isRateLimitError(params.message, lowerMessage),
3602
+ hints: ["hint: the provider appears rate-limited; retry later, switch model, or check provider quota/billing."]
3603
+ },
3604
+ {
3605
+ matches: (_params, lowerMessage) => isModelLookupError(lowerMessage),
3606
+ hints: ["hint: check the configured model name for this agent, then retry with `--model <model>` or `sessions set-model <model>`."]
3607
+ },
3608
+ {
3609
+ matches: (_params, lowerMessage) => isSessionConfigMethodError(lowerMessage),
3610
+ hints: ["hint: rerun with `--verbose` to capture the ACP method/error details before retrying."]
3611
+ },
3612
+ {
3613
+ matches: isRuntimeAcpProtocolError,
3614
+ hints: ["hint: rerun with `--verbose` to capture the underlying ACP error details."]
3615
+ }
3616
+ ];
3617
+ function matchingTextErrorRule(params, lowerMessage) {
3618
+ return TEXT_ERROR_HINT_RULES.find((rule) => rule.matches(params, lowerMessage));
3619
+ }
3620
+ function noSessionHints(lowerMessage) {
3621
+ if (lowerMessage.includes("create one:")) return [];
3622
+ return ["hint: the saved ACP session is missing or stale; start a fresh session with `acpx <agent> sessions new`, then retry."];
3623
+ }
3624
+ function isUnsupportedSessionLoadError(lowerMessage) {
3625
+ return lowerMessage.includes("does not support session/resume") || lowerMessage.includes("does not support session/load");
3626
+ }
3627
+ function isSessionLoadError(lowerMessage) {
3628
+ return lowerMessage.includes("failed to resume acp session") || lowerMessage.includes("session/resume") || lowerMessage.includes("session/load");
3629
+ }
3630
+ function isRateLimitError(message, lowerMessage) {
3631
+ return /\b429\b/u.test(message) || ["rate limit", "quota exceeded"].some((text) => lowerMessage.includes(text));
3632
+ }
3633
+ function isModelLookupError(lowerMessage) {
3634
+ return [
3635
+ "model not found",
3636
+ "unknown model",
3637
+ "invalid model"
3638
+ ].some((text) => lowerMessage.includes(text));
3639
+ }
3640
+ function isSessionConfigMethodError(lowerMessage) {
3641
+ return [
3642
+ "session/set_mode",
3643
+ "session/set_model",
3644
+ "session/set_config_option"
3645
+ ].some((text) => lowerMessage.includes(text));
3646
+ }
3647
+ function isRuntimeAcpProtocolError(params, lowerMessage) {
3648
+ return params.origin === "acp" && params.code === "RUNTIME" && (params.acp?.code === -32602 || params.acp?.code === -32603 || lowerMessage.includes("internal error"));
3250
3649
  }
3251
3650
  function summarizeToolInput(rawInput) {
3252
3651
  if (rawInput == null) return;
3253
- if (typeof rawInput === "string" || typeof rawInput === "number" || typeof rawInput === "boolean") return toInline(String(rawInput));
3652
+ if (isScalarToolInput(rawInput)) return toInline(String(rawInput));
3254
3653
  const record = asRecord(rawInput);
3255
- if (record) {
3256
- const command = readFirstString(record, [
3257
- "command",
3258
- "cmd",
3259
- "program"
3260
- ]);
3261
- const args = readFirstStringArray(record, ["args", "arguments"]);
3262
- if (command) return toInline([command, ...args ?? []].join(" "));
3263
- const location = readFirstString(record, [
3264
- "path",
3265
- "file",
3266
- "filePath",
3267
- "filepath",
3268
- "target",
3269
- "uri",
3270
- "url"
3271
- ]);
3272
- if (location) return toInline(location);
3273
- const query = readFirstString(record, [
3274
- "query",
3275
- "pattern",
3276
- "text",
3277
- "search"
3278
- ]);
3279
- if (query) return toInline(query);
3280
- }
3654
+ if (record) return summarizeToolInputRecord(record) ?? summarizeToolInputJson(rawInput);
3655
+ return summarizeToolInputJson(rawInput);
3656
+ }
3657
+ function isScalarToolInput(value) {
3658
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
3659
+ }
3660
+ function summarizeToolInputRecord(record) {
3661
+ const command = readFirstString(record, [
3662
+ "command",
3663
+ "cmd",
3664
+ "program"
3665
+ ]);
3666
+ const args = readFirstStringArray(record, ["args", "arguments"]);
3667
+ if (command) return toInline([command, ...args ?? []].join(" "));
3668
+ const location = readFirstString(record, [
3669
+ "path",
3670
+ "file",
3671
+ "filePath",
3672
+ "filepath",
3673
+ "target",
3674
+ "uri",
3675
+ "url"
3676
+ ]);
3677
+ const query = readFirstString(record, [
3678
+ "query",
3679
+ "pattern",
3680
+ "text",
3681
+ "search"
3682
+ ]);
3683
+ return location || query ? toInline(location ?? query ?? "") : void 0;
3684
+ }
3685
+ function summarizeToolInputJson(rawInput) {
3281
3686
  const json = safeJson(rawInput, 0);
3282
3687
  return json ? toInline(json) : void 0;
3283
3688
  }
@@ -3285,10 +3690,8 @@ function formatLocations(locations) {
3285
3690
  if (!locations || locations.length === 0) return;
3286
3691
  const unique = /* @__PURE__ */ new Set();
3287
3692
  for (const location of locations) {
3288
- const path = location.path?.trim();
3289
- if (!path) continue;
3290
- const line = typeof location.line === "number" && Number.isFinite(location.line) ? `:${Math.max(1, Math.trunc(location.line))}` : "";
3291
- unique.add(`${path}${line}`);
3693
+ const formatted = formatLocation(location);
3694
+ if (formatted) unique.add(formatted);
3292
3695
  }
3293
3696
  const items = [...unique];
3294
3697
  if (items.length === 0) return;
@@ -3297,6 +3700,11 @@ function formatLocations(locations) {
3297
3700
  if (hidden <= 0) return visible.join(", ");
3298
3701
  return `${visible.join(", ")}, +${hidden} more`;
3299
3702
  }
3703
+ function formatLocation(location) {
3704
+ const path = location.path?.trim();
3705
+ if (!path) return;
3706
+ return `${path}${typeof location.line === "number" && Number.isFinite(location.line) ? `:${Math.max(1, Math.trunc(location.line))}` : ""}`;
3707
+ }
3300
3708
  function summarizeDiff(path, oldText, newText) {
3301
3709
  const oldLines = oldText ? oldText.split("\n").length : 0;
3302
3710
  const delta = newText.split("\n").length - oldLines;
@@ -3307,64 +3715,74 @@ function textFromContentBlock(content) {
3307
3715
  switch (content.type) {
3308
3716
  case "text": return content.text;
3309
3717
  case "resource_link": return content.title ?? content.name ?? content.uri;
3310
- case "resource": {
3311
- if ("text" in content.resource && typeof content.resource.text === "string") return content.resource.text;
3312
- const uri = content.resource.uri;
3313
- const mimeType = content.resource.mimeType;
3314
- return `[resource] ${uri}${mimeType ? ` (${mimeType})` : ""}`;
3315
- }
3718
+ case "resource": return textFromResourceBlock(content);
3316
3719
  case "image": return `[image] ${content.mimeType}`;
3317
3720
  case "audio": return `[audio] ${content.mimeType}`;
3318
3721
  default: return;
3319
3722
  }
3320
3723
  }
3724
+ function textFromResourceBlock(content) {
3725
+ if ("text" in content.resource && typeof content.resource.text === "string") return content.resource.text;
3726
+ const uri = content.resource.uri;
3727
+ const mimeType = content.resource.mimeType;
3728
+ return `[resource] ${uri}${mimeType ? ` (${mimeType})` : ""}`;
3729
+ }
3321
3730
  function summarizeToolContent(content) {
3322
3731
  if (!content || content.length === 0) return;
3323
3732
  const fragments = [];
3324
3733
  for (const entry of content) {
3325
- if (entry.type === "content") {
3326
- const text = textFromContentBlock(entry.content);
3327
- if (text && text.trim()) fragments.push(text.trimEnd());
3328
- continue;
3329
- }
3330
- if (entry.type === "diff") {
3331
- fragments.push(summarizeDiff(entry.path, entry.oldText, entry.newText));
3332
- continue;
3333
- }
3334
- if (entry.type === "terminal") fragments.push(`[terminal] ${entry.terminalId}`);
3734
+ const fragment = summarizeToolContentEntry(entry);
3735
+ if (fragment) fragments.push(fragment);
3335
3736
  }
3336
3737
  const unique = dedupeStrings(fragments.map((fragment) => fragment.trim()).filter((fragment) => fragment.length > 0));
3337
3738
  if (unique.length === 0) return;
3338
3739
  return unique.join("\n\n");
3339
3740
  }
3741
+ function summarizeToolContentEntry(entry) {
3742
+ if (entry.type === "content") {
3743
+ const text = textFromContentBlock(entry.content);
3744
+ return text && text.trim() ? text.trimEnd() : void 0;
3745
+ }
3746
+ if (entry.type === "diff") return summarizeDiff(entry.path, entry.oldText, entry.newText);
3747
+ if (entry.type === "terminal") return `[terminal] ${entry.terminalId}`;
3748
+ }
3340
3749
  function extractOutputText(value, depth = 0, seen = /* @__PURE__ */ new Set()) {
3341
3750
  if (value == null) return;
3751
+ const scalar = extractScalarOutputText(value);
3752
+ if (scalar !== null) return scalar;
3753
+ if (depth >= 4) return;
3754
+ if (Array.isArray(value)) return extractOutputTextArray(value, depth, seen);
3755
+ return extractOutputTextRecord(value, depth, seen);
3756
+ }
3757
+ function extractOutputTextRecord(value, depth, seen) {
3758
+ const record = asRecord(value);
3759
+ if (!record || seen.has(record)) return;
3760
+ seen.add(record);
3761
+ return extractPreferredOutputText(record, depth, seen) ?? extractJsonOutputText(record);
3762
+ }
3763
+ function extractScalarOutputText(value) {
3342
3764
  if (typeof value === "string") {
3343
3765
  const trimmed = value.trimEnd();
3344
3766
  return trimmed.length > 0 ? trimmed : void 0;
3345
3767
  }
3346
3768
  if (typeof value === "number" || typeof value === "boolean") return String(value);
3347
- if (depth >= 4) return;
3348
- if (Array.isArray(value)) {
3349
- const parts = value.map((entry) => extractOutputText(entry, depth + 1, seen)).filter((entry) => Boolean(entry));
3350
- if (parts.length === 0) return;
3351
- return dedupeStrings(parts).join("\n");
3352
- }
3353
- const record = asRecord(value);
3354
- if (!record) return;
3355
- if (seen.has(record)) return;
3356
- seen.add(record);
3357
- const preferred = [];
3358
- for (const key of OUTPUT_PRIORITY_KEYS) {
3359
- if (!(key in record)) continue;
3769
+ return null;
3770
+ }
3771
+ function extractOutputTextArray(value, depth, seen) {
3772
+ const parts = value.map((entry) => extractOutputText(entry, depth + 1, seen)).filter((entry) => Boolean(entry));
3773
+ return parts.length > 0 ? dedupeStrings(parts).join("\n") : void 0;
3774
+ }
3775
+ function extractPreferredOutputText(record, depth, seen) {
3776
+ const uniquePreferred = dedupeStrings(OUTPUT_PRIORITY_KEYS.flatMap((key) => {
3777
+ if (!(key in record)) return [];
3360
3778
  const extracted = extractOutputText(record[key], depth + 1, seen);
3361
- if (extracted) preferred.push(extracted);
3362
- }
3363
- const uniquePreferred = dedupeStrings(preferred);
3364
- if (uniquePreferred.length > 0) return uniquePreferred.join("\n");
3779
+ return extracted ? [extracted] : [];
3780
+ }));
3781
+ return uniquePreferred.length > 0 ? uniquePreferred.join("\n") : void 0;
3782
+ }
3783
+ function extractJsonOutputText(record) {
3365
3784
  const json = safeJson(record, 2);
3366
- if (!json || json === "{}") return;
3367
- return json;
3785
+ return !json || json === "{}" ? void 0 : json;
3368
3786
  }
3369
3787
  function summarizeToolOutput(rawOutput, content) {
3370
3788
  const fragments = dedupeStrings([extractOutputText(rawOutput), summarizeToolContent(content)].map((fragment) => fragment?.trim()).filter((fragment) => Boolean(fragment)));
@@ -3434,6 +3852,9 @@ var TextOutputFormatter = class {
3434
3852
  renderSessionUpdate(notification) {
3435
3853
  const update = notification.update;
3436
3854
  if (update.sessionUpdate !== "agent_thought_chunk") this.flushThoughtBuffer();
3855
+ this.renderSessionUpdateBody(update);
3856
+ }
3857
+ renderSessionUpdateBody(update) {
3437
3858
  switch (update.sessionUpdate) {
3438
3859
  case "agent_message_chunk":
3439
3860
  if (update.content.type === "text") this.writeAssistantChunk(update.content.text);
@@ -3448,13 +3869,16 @@ var TextOutputFormatter = class {
3448
3869
  this.renderToolUpdate(update);
3449
3870
  return;
3450
3871
  case "plan":
3451
- this.beginSection("plan");
3452
- this.writeLine(this.bold("[plan]"));
3453
- for (const entry of update.entries) this.writeLine(` - [${entry.status}] ${entry.content}`);
3872
+ this.renderPlanUpdate(update.entries);
3454
3873
  return;
3455
3874
  default: return;
3456
3875
  }
3457
3876
  }
3877
+ renderPlanUpdate(entries) {
3878
+ this.beginSection("plan");
3879
+ this.writeLine(this.bold("[plan]"));
3880
+ for (const entry of entries) this.writeLine(` - [${entry.status}] ${entry.content}`);
3881
+ }
3458
3882
  renderDone(stopReason) {
3459
3883
  this.flushThoughtBuffer();
3460
3884
  this.beginSection("done");
@@ -3551,7 +3975,13 @@ var TextOutputFormatter = class {
3551
3975
  return created;
3552
3976
  }
3553
3977
  mergeToolState(state, update) {
3554
- if (typeof update.title === "string" && update.title.trim().length > 0) state.title = update.title;
3978
+ this.mergeToolTitle(state, update.title);
3979
+ this.mergeToolPayloadState(state, update);
3980
+ }
3981
+ mergeToolTitle(state, title) {
3982
+ if (typeof title === "string" && title.trim().length > 0) state.title = title;
3983
+ }
3984
+ mergeToolPayloadState(state, update) {
3555
3985
  if (update.status !== void 0) state.status = update.status;
3556
3986
  if (update.kind !== void 0) state.kind = update.kind;
3557
3987
  if (update.locations !== void 0) state.locations = update.locations;
@@ -3681,8 +4111,8 @@ var QuietOutputFormatter = class {
3681
4111
  return parts.length > 0 ? `[acpx] tokens: ${parts.join(" ")}` : void 0;
3682
4112
  }
3683
4113
  formatCostLine(cost) {
3684
- if (typeof cost === "number" && Number.isFinite(cost)) return `[acpx] cost: ${formatMetadataNumber(cost)}`;
3685
- if (typeof cost === "string" && cost.trim()) return `[acpx] cost: ${cost.trim()}`;
4114
+ const scalar = this.formatScalarCostLine(cost);
4115
+ if (scalar) return scalar;
3686
4116
  const record = asRecord(cost);
3687
4117
  if (!record) return;
3688
4118
  const amount = readFirstFiniteNumber(record, [
@@ -3694,6 +4124,10 @@ var QuietOutputFormatter = class {
3694
4124
  const currency = typeof record.currency === "string" && record.currency.trim() ? ` ${record.currency.trim()}` : "";
3695
4125
  return `[acpx] cost: ${formatMetadataNumber(amount)}${currency}`;
3696
4126
  }
4127
+ formatScalarCostLine(cost) {
4128
+ if (typeof cost === "number" && Number.isFinite(cost)) return `[acpx] cost: ${formatMetadataNumber(cost)}`;
4129
+ if (typeof cost === "string" && cost.trim()) return `[acpx] cost: ${cost.trim()}`;
4130
+ }
3697
4131
  };
3698
4132
  function createOutputFormatter(format, options = {}) {
3699
4133
  const stdout = options.stdout ?? process.stdout;
@@ -3709,4 +4143,4 @@ function createOutputFormatter(format, options = {}) {
3709
4143
  //#endregion
3710
4144
  export { runSessionQueueOwner as a, buildQueueOwnerArgOverride as c, createSessionWithClient as d, cancelSessionPrompt as f, __exportAll as h, session_exports as i, flushPerfMetricsCapture as l, DEFAULT_QUEUE_OWNER_TTL_MS as m, getTextErrorRemediationHints as n, runOnce as o, probeQueueOwnerHealth as p, output_exports as r, sendSessionDirect as s, createOutputFormatter as t, installPerfMetricsCapture as u };
3711
4145
 
3712
- //# sourceMappingURL=output-BL9XRWzS.js.map
4146
+ //# sourceMappingURL=output-DPg20dvn.js.map