acpx 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/{cli-CXlEcGWV.js → cli-CxsS1XQp.js} +4 -4
- package/dist/{cli-CXlEcGWV.js.map → cli-CxsS1XQp.js.map} +1 -1
- package/dist/cli.js +25 -10
- package/dist/cli.js.map +1 -1
- package/dist/{client-DIlpCkHw.d.ts → client-DwNyFauq.d.ts} +4 -1
- package/dist/{client-DIlpCkHw.d.ts.map → client-DwNyFauq.d.ts.map} +1 -1
- package/dist/{flags-Dl_mhic3.js → flags-Bjq_XQ4-.js} +4 -4
- package/dist/{flags-Dl_mhic3.js.map → flags-Bjq_XQ4-.js.map} +1 -1
- package/dist/{flows-7OHjgEgq.js → flows-Db_LZKu9.js} +3 -3
- package/dist/flows-Db_LZKu9.js.map +1 -0
- package/dist/flows.js +1 -1
- package/dist/{live-checkpoint-mdAaF3qJ.js → live-checkpoint-ClPCSdrW.js} +28 -1
- package/dist/live-checkpoint-ClPCSdrW.js.map +1 -0
- package/dist/{output-Smw6kFL_.js → output-CjdF5rHk.js} +303 -74
- package/dist/output-CjdF5rHk.js.map +1 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +1 -1
- package/package.json +9 -9
- package/skills/acpx/SKILL.md +2 -1
- package/dist/flows-7OHjgEgq.js.map +0 -1
- package/dist/live-checkpoint-mdAaF3qJ.js.map +0 -1
- package/dist/output-Smw6kFL_.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as getPerfMetricsSnapshot, B as absolutePath, C as mergeSessionOptions, Ct as promptToDisplayText, D as applyLifecycleSnapshotToRecord, Dt as withInterrupt, E as applyConversation, Et as TimeoutError, F as modelStateFromConfigOptions, Ft as isRetryablePromptError, G as listSessions, H as findSession, I as splitCommandLine, It as normalizeOutputError, J as pruneSessions, K as listSessionsForAgent, N as assertRequestedModelSupported, Ot as withTimeout, Pt as formatErrorMessage, Q as formatPerfMetric, Qt as QueueProtocolError, S as advertisedModelState, T as sessionOptionsFromRecord, Tt as InterruptedError, U as findSessionByDirectoryWalk, Ut as OUTPUT_ERROR_CODES, V as findGitRepositoryRoot, W as isoNow, Wt as OUTPUT_ERROR_ORIGINS, X as writeSessionRecord, Y as resolveSessionRecord, Zt as QueueConnectionError, _ as createSessionConversation, _t as parseJsonRpcErrorMessage, a as applyRequestedModelIfAdvertised, at as startPerfTimer, b as recordSessionUpdate, bt as isPromptInput, c as setCurrentModelId, ct as normalizeRuntimeSessionId, d as setDesiredModelId, dt as sessionBaseDir, et as incrementPerfCounter, f as syncAdvertisedModelState, ft as sessionEventActivePath, g as cloneSessionConversation, gt as isAcpJsonRpcMessage, h as cloneSessionAcpxState, ht as extractSessionUpdateNotification, i as connectAndLoadSession, it as setPerfGauge, k as AcpClient, l as setDesiredConfigOption, m as applyConfigOptionsToState, mt as sessionEventSegmentPath, n as runPromptTurn, nt as recordPerfDuration, o as currentModelIdFromSetModelResponse, p as applyConfigOptionsToRecord, pt as sessionEventLockPath, q as normalizeName, r as withConnectedSession, rt as resetPerfMetrics, s as clearDesiredConfigOption, t as LiveSessionCheckpoint, tt as measurePerf, u as setDesiredModeId, ut as defaultSessionEventLog, v as recordClientOperation, vt as parsePromptStopReason, w as persistSessionOptions, wt as textPrompt, x as trimConversationForRuntime, y as recordPromptSubmission, zt as toAcpErrorPayload } from "./live-checkpoint-
|
|
1
|
+
import { $ as getPerfMetricsSnapshot, B as absolutePath, C as mergeSessionOptions, Ct as promptToDisplayText, D as applyLifecycleSnapshotToRecord, Dt as withInterrupt, E as applyConversation, Et as TimeoutError, F as modelStateFromConfigOptions, Ft as isRetryablePromptError, G as listSessions, H as findSession, I as splitCommandLine, It as normalizeOutputError, J as pruneSessions, K as listSessionsForAgent, Lt as extractAcpError, N as assertRequestedModelSupported, Ot as withTimeout, Pt as formatErrorMessage, Q as formatPerfMetric, Qt as QueueProtocolError, S as advertisedModelState, T as sessionOptionsFromRecord, Tt as InterruptedError, U as findSessionByDirectoryWalk, Ut as OUTPUT_ERROR_CODES, V as findGitRepositoryRoot, W as isoNow, Wt as OUTPUT_ERROR_ORIGINS, X as writeSessionRecord, Y as resolveSessionRecord, Zt as QueueConnectionError, _ as createSessionConversation, _t as parseJsonRpcErrorMessage, a as applyRequestedModelIfAdvertised, at as startPerfTimer, b as recordSessionUpdate, bt as isPromptInput, c as setCurrentModelId, ct as normalizeRuntimeSessionId, d as setDesiredModelId, dt as sessionBaseDir, et as incrementPerfCounter, f as syncAdvertisedModelState, ft as sessionEventActivePath, g as cloneSessionConversation, gt as isAcpJsonRpcMessage, h as cloneSessionAcpxState, ht as extractSessionUpdateNotification, i as connectAndLoadSession, it as setPerfGauge, k as AcpClient, l as setDesiredConfigOption, m as applyConfigOptionsToState, mt as sessionEventSegmentPath, n as runPromptTurn, nt as recordPerfDuration, o as currentModelIdFromSetModelResponse, p as applyConfigOptionsToRecord, pt as sessionEventLockPath, q as normalizeName, r as withConnectedSession, rt as resetPerfMetrics, s as clearDesiredConfigOption, t as LiveSessionCheckpoint, tt as measurePerf, u as setDesiredModeId, ut as defaultSessionEventLog, v as recordClientOperation, vt as parsePromptStopReason, w as persistSessionOptions, wt as textPrompt, x as trimConversationForRuntime, y as recordPromptSubmission, zt as toAcpErrorPayload } from "./live-checkpoint-ClPCSdrW.js";
|
|
2
2
|
import fs, { mkdtempSync, realpathSync, writeFileSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import fs$1 from "node:fs/promises";
|
|
@@ -62,7 +62,8 @@ function queueSocketPath(sessionId, homeDir = os.homedir()) {
|
|
|
62
62
|
}
|
|
63
63
|
//#endregion
|
|
64
64
|
//#region src/cli/queue/lease-store.ts
|
|
65
|
-
const
|
|
65
|
+
const PROCESS_SIGTERM_GRACE_MS = 4e3;
|
|
66
|
+
const PROCESS_SIGKILL_GRACE_MS = 1500;
|
|
66
67
|
const PROCESS_POLL_MS = 50;
|
|
67
68
|
const QUEUE_OWNER_STALE_HEARTBEAT_MS = 15e3;
|
|
68
69
|
function parseQueueOwnerRecord(raw) {
|
|
@@ -160,13 +161,13 @@ async function terminateProcess(pid) {
|
|
|
160
161
|
} catch {
|
|
161
162
|
return false;
|
|
162
163
|
}
|
|
163
|
-
if (await waitForProcessExit(pid,
|
|
164
|
+
if (await waitForProcessExit(pid, PROCESS_SIGTERM_GRACE_MS)) return true;
|
|
164
165
|
try {
|
|
165
166
|
process.kill(pid, "SIGKILL");
|
|
166
167
|
} catch {
|
|
167
168
|
return false;
|
|
168
169
|
}
|
|
169
|
-
await waitForProcessExit(pid,
|
|
170
|
+
await waitForProcessExit(pid, PROCESS_SIGKILL_GRACE_MS);
|
|
170
171
|
return true;
|
|
171
172
|
}
|
|
172
173
|
async function ensureOwnerIsUsable(sessionId, owner) {
|
|
@@ -753,6 +754,7 @@ function isValidOwnerErrorCore(message) {
|
|
|
753
754
|
}
|
|
754
755
|
//#endregion
|
|
755
756
|
//#region src/cli/queue/ipc-server.ts
|
|
757
|
+
const QUEUE_SOCKET_DRAIN_TIMEOUT_MS = 1e3;
|
|
756
758
|
function makeQueueOwnerError(requestId, message, detailCode, options = {}) {
|
|
757
759
|
return {
|
|
758
760
|
type: "error",
|
|
@@ -795,6 +797,9 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
795
797
|
onQueueDepthChanged;
|
|
796
798
|
pending = [];
|
|
797
799
|
waiters = [];
|
|
800
|
+
sockets = /* @__PURE__ */ new Set();
|
|
801
|
+
taskSockets = /* @__PURE__ */ new Set();
|
|
802
|
+
drainingSockets = /* @__PURE__ */ new Set();
|
|
798
803
|
closed = false;
|
|
799
804
|
constructor(server, controlHandlers, lease, options) {
|
|
800
805
|
this.server = server;
|
|
@@ -824,7 +829,7 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
824
829
|
});
|
|
825
830
|
return ownerRef.current;
|
|
826
831
|
}
|
|
827
|
-
|
|
832
|
+
beginShutdown() {
|
|
828
833
|
if (this.closed) return;
|
|
829
834
|
this.closed = true;
|
|
830
835
|
for (const waiter of this.waiters.splice(0)) waiter(void 0);
|
|
@@ -832,9 +837,20 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
832
837
|
if (task.waitForCompletion) task.send(makeQueueOwnerError(task.requestId, "Queue owner shutting down before prompt execution", "QUEUE_OWNER_SHUTTING_DOWN", { retryable: true }));
|
|
833
838
|
task.close();
|
|
834
839
|
}
|
|
840
|
+
for (const socket of this.sockets) if (!this.taskSockets.has(socket) && !this.drainingSockets.has(socket)) socket.destroy();
|
|
835
841
|
this.emitQueueDepth();
|
|
842
|
+
}
|
|
843
|
+
async close() {
|
|
844
|
+
this.beginShutdown();
|
|
836
845
|
await new Promise((resolve) => {
|
|
837
|
-
|
|
846
|
+
const forceCloseTimer = setTimeout(() => {
|
|
847
|
+
for (const socket of this.sockets) socket.destroy();
|
|
848
|
+
}, QUEUE_SOCKET_DRAIN_TIMEOUT_MS);
|
|
849
|
+
forceCloseTimer.unref();
|
|
850
|
+
this.server.close(() => {
|
|
851
|
+
clearTimeout(forceCloseTimer);
|
|
852
|
+
resolve();
|
|
853
|
+
});
|
|
838
854
|
});
|
|
839
855
|
}
|
|
840
856
|
async nextTask(timeoutMs) {
|
|
@@ -904,7 +920,16 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
904
920
|
ownerGeneration: this.ownerGeneration
|
|
905
921
|
});
|
|
906
922
|
}).finally(() => {
|
|
907
|
-
|
|
923
|
+
this.endSocket(options.socket);
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
endSocket(socket) {
|
|
927
|
+
if (socket.destroyed || this.drainingSockets.has(socket)) return;
|
|
928
|
+
this.taskSockets.delete(socket);
|
|
929
|
+
this.drainingSockets.add(socket);
|
|
930
|
+
socket.end(() => {
|
|
931
|
+
this.drainingSockets.delete(socket);
|
|
932
|
+
socket.destroy();
|
|
908
933
|
});
|
|
909
934
|
}
|
|
910
935
|
failRequest(socket, requestId, message, detailCode) {
|
|
@@ -912,7 +937,7 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
912
937
|
...makeQueueOwnerError(requestId, message, detailCode, { retryable: false }),
|
|
913
938
|
ownerGeneration: this.ownerGeneration
|
|
914
939
|
});
|
|
915
|
-
|
|
940
|
+
this.endSocket(socket);
|
|
916
941
|
}
|
|
917
942
|
parseRequestLine(socket, line) {
|
|
918
943
|
let parsed;
|
|
@@ -931,6 +956,15 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
931
956
|
this.failRequest(socket, request.requestId, "Queue request targeted a stale queue owner generation", "QUEUE_OWNER_GENERATION_MISMATCH");
|
|
932
957
|
return true;
|
|
933
958
|
}
|
|
959
|
+
rejectClosedOwner(socket, request) {
|
|
960
|
+
if (!this.closed) return false;
|
|
961
|
+
writeQueueMessage(socket, {
|
|
962
|
+
...makeQueueOwnerError(request.requestId, "Queue owner is shutting down", "QUEUE_OWNER_CLOSED", { retryable: true }),
|
|
963
|
+
ownerGeneration: this.ownerGeneration
|
|
964
|
+
});
|
|
965
|
+
this.endSocket(socket);
|
|
966
|
+
return true;
|
|
967
|
+
}
|
|
934
968
|
handleControlQueueRequest(socket, request) {
|
|
935
969
|
if (request.type === "cancel_prompt") {
|
|
936
970
|
this.handleControlRequest({
|
|
@@ -1005,6 +1039,7 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
1005
1039
|
return false;
|
|
1006
1040
|
}
|
|
1007
1041
|
enqueuePromptRequest(socket, request) {
|
|
1042
|
+
this.taskSockets.add(socket);
|
|
1008
1043
|
const task = {
|
|
1009
1044
|
requestId: request.requestId,
|
|
1010
1045
|
message: request.message,
|
|
@@ -1026,7 +1061,7 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
1026
1061
|
});
|
|
1027
1062
|
},
|
|
1028
1063
|
close: () => {
|
|
1029
|
-
|
|
1064
|
+
this.endSocket(socket);
|
|
1030
1065
|
}
|
|
1031
1066
|
};
|
|
1032
1067
|
if (!this.enqueue(task)) return;
|
|
@@ -1038,19 +1073,20 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
1038
1073
|
if (!request.waitForCompletion) task.close();
|
|
1039
1074
|
}
|
|
1040
1075
|
handleConnection(socket) {
|
|
1076
|
+
this.sockets.add(socket);
|
|
1041
1077
|
socket.setEncoding("utf8");
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
}
|
|
1078
|
+
socket.once("close", () => {
|
|
1079
|
+
this.sockets.delete(socket);
|
|
1080
|
+
this.taskSockets.delete(socket);
|
|
1081
|
+
this.drainingSockets.delete(socket);
|
|
1082
|
+
});
|
|
1047
1083
|
let buffer = "";
|
|
1048
1084
|
let handled = false;
|
|
1049
1085
|
const processLine = (line) => {
|
|
1050
1086
|
if (handled) return;
|
|
1051
1087
|
handled = true;
|
|
1052
1088
|
const request = this.parseRequestLine(socket, line);
|
|
1053
|
-
if (!request || this.rejectStaleOwnerGeneration(socket, request)) return;
|
|
1089
|
+
if (!request || this.rejectClosedOwner(socket, request) || this.rejectStaleOwnerGeneration(socket, request)) return;
|
|
1054
1090
|
if (this.handleControlQueueRequest(socket, request)) return;
|
|
1055
1091
|
if (request.type !== "submit_prompt") {
|
|
1056
1092
|
this.failRequest(socket, request.requestId, "Invalid queue request", "QUEUE_REQUEST_INVALID");
|
|
@@ -1112,7 +1148,8 @@ function makeMalformedQueueMessageError() {
|
|
|
1112
1148
|
function emitQueueOwnerError(formatter, policy, sessionId, message) {
|
|
1113
1149
|
formatter.setContext({ sessionId });
|
|
1114
1150
|
const queueErrorAlreadyEmitted = policy?.queueErrorAlreadyEmitted ?? true;
|
|
1115
|
-
|
|
1151
|
+
const shouldEmitInFormatter = message.outputAlreadyEmitted !== true || !queueErrorAlreadyEmitted;
|
|
1152
|
+
if (shouldEmitInFormatter) {
|
|
1116
1153
|
formatter.onError({
|
|
1117
1154
|
code: message.code ?? "RUNTIME",
|
|
1118
1155
|
detailCode: message.detailCode,
|
|
@@ -1123,7 +1160,7 @@ function emitQueueOwnerError(formatter, policy, sessionId, message) {
|
|
|
1123
1160
|
});
|
|
1124
1161
|
formatter.flush();
|
|
1125
1162
|
}
|
|
1126
|
-
return queueConnectionErrorFromOwner(message, queueErrorAlreadyEmitted);
|
|
1163
|
+
return queueConnectionErrorFromOwner(message, queueErrorAlreadyEmitted || shouldEmitInFormatter);
|
|
1127
1164
|
}
|
|
1128
1165
|
function parseQueueOwnerResponseLine(owner, requestId, line) {
|
|
1129
1166
|
let parsed;
|
|
@@ -2527,6 +2564,51 @@ const DISCARD_OUTPUT_FORMATTER = {
|
|
|
2527
2564
|
onPermissionEscalation() {},
|
|
2528
2565
|
flush() {}
|
|
2529
2566
|
};
|
|
2567
|
+
function markOutputAlreadyEmitted(error, outputAlreadyEmitted) {
|
|
2568
|
+
if (!outputAlreadyEmitted || !error || typeof error !== "object") return;
|
|
2569
|
+
error.outputAlreadyEmitted = true;
|
|
2570
|
+
}
|
|
2571
|
+
async function runWithOptionalInterrupt(options) {
|
|
2572
|
+
if (options.handleProcessInterrupts === false) return await options.run();
|
|
2573
|
+
return await withInterrupt(options.run, options.handleInterrupt);
|
|
2574
|
+
}
|
|
2575
|
+
function attachAcpErrorPayload(error, acp) {
|
|
2576
|
+
if (!acp || !error || typeof error !== "object") return;
|
|
2577
|
+
error.acp = acp;
|
|
2578
|
+
}
|
|
2579
|
+
function rendersAcpErrors(policy) {
|
|
2580
|
+
return policy?.queueErrorAlreadyEmitted ?? true;
|
|
2581
|
+
}
|
|
2582
|
+
function normalizedErrorText(value) {
|
|
2583
|
+
return value.trim().toLowerCase();
|
|
2584
|
+
}
|
|
2585
|
+
function outboundAcpErrorMatches(error, acp) {
|
|
2586
|
+
const errorText = normalizedErrorText(formatErrorMessage(error));
|
|
2587
|
+
const details = acp.data?.details;
|
|
2588
|
+
const candidateText = normalizedErrorText(typeof details === "string" && details.trim().length > 0 ? details : acp.message);
|
|
2589
|
+
return errorText === candidateText || errorText.includes(candidateText);
|
|
2590
|
+
}
|
|
2591
|
+
var AcpErrorTracker = class {
|
|
2592
|
+
latestInbound;
|
|
2593
|
+
outbound = [];
|
|
2594
|
+
reset() {
|
|
2595
|
+
this.latestInbound = void 0;
|
|
2596
|
+
this.outbound.length = 0;
|
|
2597
|
+
}
|
|
2598
|
+
observe(output, direction, message) {
|
|
2599
|
+
output.onAcpMessage(message);
|
|
2600
|
+
const acp = extractAcpError(message);
|
|
2601
|
+
if (!acp) return;
|
|
2602
|
+
if (direction === "inbound") {
|
|
2603
|
+
this.latestInbound = acp;
|
|
2604
|
+
return;
|
|
2605
|
+
}
|
|
2606
|
+
this.outbound.push(acp);
|
|
2607
|
+
}
|
|
2608
|
+
match(error) {
|
|
2609
|
+
return this.latestInbound ?? this.outbound.findLast((acp) => outboundAcpErrorMatches(error, acp));
|
|
2610
|
+
}
|
|
2611
|
+
};
|
|
2530
2612
|
function toPromptResult(stopReason, sessionId, client) {
|
|
2531
2613
|
return {
|
|
2532
2614
|
stopReason,
|
|
@@ -2636,6 +2718,11 @@ function filterRecoverableLoadFallbackOutput(messages) {
|
|
|
2636
2718
|
return true;
|
|
2637
2719
|
});
|
|
2638
2720
|
}
|
|
2721
|
+
function filterBufferedConnectOutput(messages, loadError) {
|
|
2722
|
+
if (loadError == null) return messages;
|
|
2723
|
+
const filteredMessages = new Set(filterRecoverableLoadFallbackOutput(messages.map(({ message }) => message)));
|
|
2724
|
+
return messages.filter(({ message }) => filteredMessages.has(message));
|
|
2725
|
+
}
|
|
2639
2726
|
function emitPromptRetryNotice(params) {
|
|
2640
2727
|
if (params.suppressSdkConsoleErrors) return;
|
|
2641
2728
|
process.stderr.write(`[acpx] prompt failed (${formatErrorMessage(params.error)}), retrying in ${params.delayMs}ms (attempt ${params.attempt}/${params.maxRetries})\n`);
|
|
@@ -2687,6 +2774,7 @@ function buildQueuedTaskRunOptions(sessionRecordId, task, options, outputFormatt
|
|
|
2687
2774
|
authCredentials: options.authCredentials,
|
|
2688
2775
|
authPolicy: options.authPolicy,
|
|
2689
2776
|
outputFormatter,
|
|
2777
|
+
errorEmissionPolicy: { queueErrorAlreadyEmitted: true },
|
|
2690
2778
|
timeoutMs: task.timeoutMs,
|
|
2691
2779
|
suppressSdkConsoleErrors: task.suppressSdkConsoleErrors ?? options.suppressSdkConsoleErrors,
|
|
2692
2780
|
verbose: options.verbose,
|
|
@@ -2695,6 +2783,7 @@ function buildQueuedTaskRunOptions(sessionRecordId, task, options, outputFormatt
|
|
|
2695
2783
|
onClientAvailable: options.onClientAvailable,
|
|
2696
2784
|
onClientClosed: options.onClientClosed,
|
|
2697
2785
|
onPromptActive: options.onPromptActive,
|
|
2786
|
+
handleProcessInterrupts: options.handleProcessInterrupts,
|
|
2698
2787
|
client: options.sharedClient
|
|
2699
2788
|
};
|
|
2700
2789
|
}
|
|
@@ -2739,6 +2828,7 @@ async function runQueuedTask(sessionRecordId, task, options) {
|
|
|
2739
2828
|
async function runSessionPrompt(options) {
|
|
2740
2829
|
const stopTotalTimer = startPerfTimer("runtime.prompt.total");
|
|
2741
2830
|
const output = options.outputFormatter;
|
|
2831
|
+
const shouldMarkAcpErrorsEmitted = rendersAcpErrors(options.errorEmissionPolicy);
|
|
2742
2832
|
const record = await measurePerf("session.resolve_prompt_record", async () => {
|
|
2743
2833
|
return await resolveSessionRecord(options.sessionRecordId);
|
|
2744
2834
|
});
|
|
@@ -2761,7 +2851,7 @@ async function runSessionPrompt(options) {
|
|
|
2761
2851
|
let bufferingConnectOutput = true;
|
|
2762
2852
|
let promptTurnActive = false;
|
|
2763
2853
|
let promptTurnHadSideEffects = false;
|
|
2764
|
-
|
|
2854
|
+
const acpErrors = new AcpErrorTracker();
|
|
2765
2855
|
let eventWriterClosed = false;
|
|
2766
2856
|
const closeEventWriter = async (checkpoint) => {
|
|
2767
2857
|
if (eventWriterClosed) return;
|
|
@@ -2824,16 +2914,18 @@ async function runSessionPrompt(options) {
|
|
|
2824
2914
|
});
|
|
2825
2915
|
client.setEventHandlers({
|
|
2826
2916
|
onAcpMessage: (direction, message) => {
|
|
2827
|
-
sawAcpMessage = true;
|
|
2828
2917
|
pendingMessages.push(message);
|
|
2829
2918
|
options.onAcpMessage?.(direction, message);
|
|
2830
2919
|
},
|
|
2831
|
-
onAcpOutputMessage: (
|
|
2920
|
+
onAcpOutputMessage: (direction, message) => {
|
|
2832
2921
|
if (bufferingConnectOutput) {
|
|
2833
|
-
pendingConnectOutputMessages.push(
|
|
2922
|
+
pendingConnectOutputMessages.push({
|
|
2923
|
+
direction,
|
|
2924
|
+
message
|
|
2925
|
+
});
|
|
2834
2926
|
return;
|
|
2835
2927
|
}
|
|
2836
|
-
|
|
2928
|
+
acpErrors.observe(output, direction, message);
|
|
2837
2929
|
},
|
|
2838
2930
|
onSessionUpdate: (notification) => {
|
|
2839
2931
|
if (promptTurnActive) promptTurnHadSideEffects = true;
|
|
@@ -2898,8 +2990,8 @@ async function runSessionPrompt(options) {
|
|
|
2898
2990
|
};
|
|
2899
2991
|
const flushConnectOutput = (loadError) => {
|
|
2900
2992
|
bufferingConnectOutput = false;
|
|
2901
|
-
const
|
|
2902
|
-
for (const message of
|
|
2993
|
+
const outputMessages = filterBufferedConnectOutput(pendingConnectOutputMessages, loadError);
|
|
2994
|
+
for (const { direction, message } of outputMessages) acpErrors.observe(output, direction, message);
|
|
2903
2995
|
pendingConnectOutputMessages.length = 0;
|
|
2904
2996
|
};
|
|
2905
2997
|
const connectForPrompt = async () => {
|
|
@@ -2946,6 +3038,7 @@ async function runSessionPrompt(options) {
|
|
|
2946
3038
|
};
|
|
2947
3039
|
};
|
|
2948
3040
|
const runPromptAttempt = async (sessionId, attempt) => {
|
|
3041
|
+
acpErrors.reset();
|
|
2949
3042
|
const promptStartedAt = Date.now();
|
|
2950
3043
|
const response = await measurePerf("runtime.prompt.agent_turn", async () => {
|
|
2951
3044
|
return await runPromptTurn({
|
|
@@ -2973,14 +3066,19 @@ async function runSessionPrompt(options) {
|
|
|
2973
3066
|
promptTurnActive = false;
|
|
2974
3067
|
applyLifecycleSnapshotToRecord(record, snapshot);
|
|
2975
3068
|
emitPromptDisconnectNotice(snapshot, options.verbose);
|
|
2976
|
-
const
|
|
3069
|
+
const matchedAcpError = acpErrors.match(error);
|
|
3070
|
+
const normalizedError = normalizeOutputError(error, {
|
|
3071
|
+
origin: "runtime",
|
|
3072
|
+
acp: matchedAcpError
|
|
3073
|
+
});
|
|
2977
3074
|
await flushPendingMessages(false).catch(() => {});
|
|
2978
3075
|
output.flush();
|
|
2979
3076
|
record.lastUsedAt = isoNow();
|
|
2980
3077
|
applyConversation(record, conversation);
|
|
2981
3078
|
record.acpx = acpxState;
|
|
2982
3079
|
const propagated = error instanceof Error ? error : new Error(formatErrorMessage(error));
|
|
2983
|
-
propagated.
|
|
3080
|
+
attachAcpErrorPayload(propagated, normalizedError.acp);
|
|
3081
|
+
propagated.outputAlreadyEmitted = matchedAcpError !== void 0 && shouldMarkAcpErrorsEmitted;
|
|
2984
3082
|
propagated.normalizedOutputError = normalizedError;
|
|
2985
3083
|
throw propagated;
|
|
2986
3084
|
};
|
|
@@ -3006,37 +3104,48 @@ async function runSessionPrompt(options) {
|
|
|
3006
3104
|
stopTotalTimer();
|
|
3007
3105
|
return response;
|
|
3008
3106
|
};
|
|
3107
|
+
const runPrompt = async () => {
|
|
3108
|
+
const { sessionId: activeSessionId, resumed, loadError } = await connectForPrompt();
|
|
3109
|
+
await applyPromptModelIfAdvertised({
|
|
3110
|
+
client,
|
|
3111
|
+
sessionId: activeSessionId,
|
|
3112
|
+
requestedModel: sessionOptions?.model,
|
|
3113
|
+
record,
|
|
3114
|
+
timeoutMs: options.timeoutMs,
|
|
3115
|
+
suppressWarnings: options.suppressSdkConsoleErrors
|
|
3116
|
+
});
|
|
3117
|
+
acpxState = cloneSessionAcpxState(record.acpx);
|
|
3118
|
+
output.setContext({ sessionId: record.acpxRecordId });
|
|
3119
|
+
await liveCheckpoint.checkpoint();
|
|
3120
|
+
const response = await savePromptSuccess(await runPromptWithRetries(activeSessionId));
|
|
3121
|
+
promptTurnActive = false;
|
|
3122
|
+
return {
|
|
3123
|
+
...toPromptResult(response.stopReason, record.acpxRecordId, client),
|
|
3124
|
+
record,
|
|
3125
|
+
resumed,
|
|
3126
|
+
loadError
|
|
3127
|
+
};
|
|
3128
|
+
};
|
|
3129
|
+
const handleInterrupt = async () => {
|
|
3130
|
+
await client.cancelActivePrompt(INTERRUPT_CANCEL_WAIT_MS);
|
|
3131
|
+
applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());
|
|
3132
|
+
record.lastUsedAt = isoNow();
|
|
3133
|
+
applyConversation(record, conversation);
|
|
3134
|
+
record.acpx = acpxState;
|
|
3135
|
+
await flushPendingMessages(false).catch(() => {});
|
|
3136
|
+
if (ownClient) await client.close();
|
|
3137
|
+
};
|
|
3009
3138
|
try {
|
|
3010
|
-
return await
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
sessionId: activeSessionId,
|
|
3015
|
-
requestedModel: sessionOptions?.model,
|
|
3016
|
-
record,
|
|
3017
|
-
timeoutMs: options.timeoutMs,
|
|
3018
|
-
suppressWarnings: options.suppressSdkConsoleErrors
|
|
3019
|
-
});
|
|
3020
|
-
acpxState = cloneSessionAcpxState(record.acpx);
|
|
3021
|
-
output.setContext({ sessionId: record.acpxRecordId });
|
|
3022
|
-
await liveCheckpoint.checkpoint();
|
|
3023
|
-
const response = await savePromptSuccess(await runPromptWithRetries(activeSessionId));
|
|
3024
|
-
promptTurnActive = false;
|
|
3025
|
-
return {
|
|
3026
|
-
...toPromptResult(response.stopReason, record.acpxRecordId, client),
|
|
3027
|
-
record,
|
|
3028
|
-
resumed,
|
|
3029
|
-
loadError
|
|
3030
|
-
};
|
|
3031
|
-
}, async () => {
|
|
3032
|
-
await client.cancelActivePrompt(INTERRUPT_CANCEL_WAIT_MS);
|
|
3033
|
-
applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());
|
|
3034
|
-
record.lastUsedAt = isoNow();
|
|
3035
|
-
applyConversation(record, conversation);
|
|
3036
|
-
record.acpx = acpxState;
|
|
3037
|
-
await flushPendingMessages(false).catch(() => {});
|
|
3038
|
-
if (ownClient) await client.close();
|
|
3139
|
+
return await runWithOptionalInterrupt({
|
|
3140
|
+
handleProcessInterrupts: options.handleProcessInterrupts,
|
|
3141
|
+
run: runPrompt,
|
|
3142
|
+
handleInterrupt
|
|
3039
3143
|
});
|
|
3144
|
+
} catch (error) {
|
|
3145
|
+
const matchedAcpError = acpErrors.match(error);
|
|
3146
|
+
attachAcpErrorPayload(error, matchedAcpError);
|
|
3147
|
+
markOutputAlreadyEmitted(error, matchedAcpError !== void 0 && shouldMarkAcpErrorsEmitted);
|
|
3148
|
+
throw error;
|
|
3040
3149
|
} finally {
|
|
3041
3150
|
if (options.verbose) process.stderr.write(`[acpx] ${formatPerfMetric("prompt.total", stopTotalTimer())}\n`);
|
|
3042
3151
|
else stopTotalTimer();
|
|
@@ -3054,8 +3163,10 @@ async function runSessionPrompt(options) {
|
|
|
3054
3163
|
}
|
|
3055
3164
|
async function runOnce(options) {
|
|
3056
3165
|
const output = options.outputFormatter;
|
|
3166
|
+
const shouldMarkAcpErrorsEmitted = rendersAcpErrors(options.errorEmissionPolicy);
|
|
3057
3167
|
let promptTurnActive = false;
|
|
3058
3168
|
let promptTurnHadSideEffects = false;
|
|
3169
|
+
const acpErrors = new AcpErrorTracker();
|
|
3059
3170
|
const client = new AcpClient({
|
|
3060
3171
|
agentCommand: options.agentCommand,
|
|
3061
3172
|
cwd: absolutePath(options.cwd),
|
|
@@ -3069,7 +3180,9 @@ async function runOnce(options) {
|
|
|
3069
3180
|
suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,
|
|
3070
3181
|
verbose: options.verbose,
|
|
3071
3182
|
onAcpMessage: options.onAcpMessage,
|
|
3072
|
-
onAcpOutputMessage: (
|
|
3183
|
+
onAcpOutputMessage: (direction, message) => {
|
|
3184
|
+
acpErrors.observe(output, direction, message);
|
|
3185
|
+
},
|
|
3073
3186
|
onSessionUpdate: (notification) => {
|
|
3074
3187
|
if (promptTurnActive) promptTurnHadSideEffects = true;
|
|
3075
3188
|
options.onSessionUpdate?.(notification);
|
|
@@ -3085,6 +3198,7 @@ async function runOnce(options) {
|
|
|
3085
3198
|
sessionOptions: options.sessionOptions
|
|
3086
3199
|
});
|
|
3087
3200
|
const runExecPromptAttempt = async (sessionId) => {
|
|
3201
|
+
acpErrors.reset();
|
|
3088
3202
|
return await measurePerf("runtime.exec.prompt", async () => {
|
|
3089
3203
|
return await withTimeout(client.prompt(sessionId, options.prompt), options.timeoutMs);
|
|
3090
3204
|
});
|
|
@@ -3130,6 +3244,11 @@ async function runOnce(options) {
|
|
|
3130
3244
|
await client.cancelActivePrompt(INTERRUPT_CANCEL_WAIT_MS);
|
|
3131
3245
|
await client.close();
|
|
3132
3246
|
});
|
|
3247
|
+
} catch (error) {
|
|
3248
|
+
const matchedAcpError = acpErrors.match(error);
|
|
3249
|
+
attachAcpErrorPayload(error, matchedAcpError);
|
|
3250
|
+
markOutputAlreadyEmitted(error, matchedAcpError !== void 0 && shouldMarkAcpErrorsEmitted);
|
|
3251
|
+
throw error;
|
|
3133
3252
|
} finally {
|
|
3134
3253
|
await client.close();
|
|
3135
3254
|
}
|
|
@@ -3147,6 +3266,7 @@ async function sendSessionDirect(options) {
|
|
|
3147
3266
|
authPolicy: options.authPolicy,
|
|
3148
3267
|
terminal: options.terminal,
|
|
3149
3268
|
outputFormatter: options.outputFormatter,
|
|
3269
|
+
errorEmissionPolicy: options.errorEmissionPolicy,
|
|
3150
3270
|
onAcpMessage: options.onAcpMessage,
|
|
3151
3271
|
onSessionUpdate: options.onSessionUpdate,
|
|
3152
3272
|
onClientOperation: options.onClientOperation,
|
|
@@ -3161,6 +3281,7 @@ async function sendSessionDirect(options) {
|
|
|
3161
3281
|
//#region src/cli/session/queue-owner-runtime.ts
|
|
3162
3282
|
const QUEUE_OWNER_STARTUP_MAX_ATTEMPTS = 120;
|
|
3163
3283
|
const QUEUE_OWNER_HEARTBEAT_INTERVAL_MS = 5e3;
|
|
3284
|
+
const QUEUE_OWNER_ACTIVE_TURN_CANCEL_GRACE_MS = 750;
|
|
3164
3285
|
async function submitToRunningOwner(options, waitForCompletion) {
|
|
3165
3286
|
return await trySubmitToRunningOwner({
|
|
3166
3287
|
sessionId: options.sessionId,
|
|
@@ -3252,8 +3373,8 @@ function logQueueOwnerReady(params) {
|
|
|
3252
3373
|
async function closeQueueOwnerRuntime(params) {
|
|
3253
3374
|
if (params.heartbeatTimer) clearInterval(params.heartbeatTimer);
|
|
3254
3375
|
params.turnController.beginClosing();
|
|
3255
|
-
await params.owner?.close();
|
|
3256
3376
|
await params.sharedClient.close().catch(() => {});
|
|
3377
|
+
await params.owner?.close();
|
|
3257
3378
|
await writeQueueOwnerLifecycleSnapshot(params.sessionId, params.sharedClient);
|
|
3258
3379
|
await releaseQueueOwnerLease(params.lease);
|
|
3259
3380
|
if (params.verbose) process.stderr.write(`[acpx] queue owner stopped for session ${params.sessionId}\n`);
|
|
@@ -3265,6 +3386,75 @@ async function writeQueueOwnerLifecycleSnapshot(sessionId, sharedClient) {
|
|
|
3265
3386
|
await writeSessionRecord(record);
|
|
3266
3387
|
} catch {}
|
|
3267
3388
|
}
|
|
3389
|
+
async function settlesWithin(promise, timeoutMs) {
|
|
3390
|
+
let timer;
|
|
3391
|
+
const timeout = new Promise((resolve) => {
|
|
3392
|
+
timer = setTimeout(() => resolve(false), timeoutMs);
|
|
3393
|
+
});
|
|
3394
|
+
try {
|
|
3395
|
+
return await Promise.race([promise.then(() => true, () => true), timeout]);
|
|
3396
|
+
} finally {
|
|
3397
|
+
if (timer) clearTimeout(timer);
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
function createQueueOwnerShutdownController(params) {
|
|
3401
|
+
let requested = false;
|
|
3402
|
+
let activeTurn;
|
|
3403
|
+
let activeTurnShutdown;
|
|
3404
|
+
let shutdownPromise;
|
|
3405
|
+
const drainActiveTurn = async () => {
|
|
3406
|
+
const turn = activeTurn;
|
|
3407
|
+
if (!turn) return;
|
|
3408
|
+
params.turnController.requestCancel().catch((error) => {
|
|
3409
|
+
logDeferredCancelFailure(error, params.verbose);
|
|
3410
|
+
});
|
|
3411
|
+
if (!await settlesWithin(turn, QUEUE_OWNER_ACTIVE_TURN_CANCEL_GRACE_MS)) await params.sharedClient.close().catch(() => {});
|
|
3412
|
+
await turn.catch(() => {});
|
|
3413
|
+
};
|
|
3414
|
+
const request = () => {
|
|
3415
|
+
requested = true;
|
|
3416
|
+
params.stopHeartbeat();
|
|
3417
|
+
params.getOwner()?.beginShutdown();
|
|
3418
|
+
activeTurnShutdown ??= drainActiveTurn();
|
|
3419
|
+
};
|
|
3420
|
+
return {
|
|
3421
|
+
get requested() {
|
|
3422
|
+
return requested;
|
|
3423
|
+
},
|
|
3424
|
+
request,
|
|
3425
|
+
setActiveTurn: (turn) => {
|
|
3426
|
+
activeTurn = turn;
|
|
3427
|
+
},
|
|
3428
|
+
clearActiveTurn: (turn) => {
|
|
3429
|
+
if (activeTurn === turn) activeTurn = void 0;
|
|
3430
|
+
},
|
|
3431
|
+
shutdown: () => {
|
|
3432
|
+
request();
|
|
3433
|
+
shutdownPromise ??= (async () => {
|
|
3434
|
+
await activeTurnShutdown;
|
|
3435
|
+
await closeQueueOwnerRuntime({
|
|
3436
|
+
lease: params.lease,
|
|
3437
|
+
owner: params.getOwner(),
|
|
3438
|
+
heartbeatTimer: void 0,
|
|
3439
|
+
turnController: params.turnController,
|
|
3440
|
+
sharedClient: params.sharedClient,
|
|
3441
|
+
sessionId: params.sessionId,
|
|
3442
|
+
verbose: params.verbose
|
|
3443
|
+
});
|
|
3444
|
+
})();
|
|
3445
|
+
return shutdownPromise;
|
|
3446
|
+
}
|
|
3447
|
+
};
|
|
3448
|
+
}
|
|
3449
|
+
function applyRequestedShutdown(owner, shutdown) {
|
|
3450
|
+
if (shutdown.requested) owner.beginShutdown();
|
|
3451
|
+
}
|
|
3452
|
+
function startQueueOwnerHeartbeat(params) {
|
|
3453
|
+
if (!params.enabled) return;
|
|
3454
|
+
return setInterval(() => {
|
|
3455
|
+
refreshQueueOwnerLease(params.lease, { queueDepth: params.owner.queueDepth() }).catch(() => {});
|
|
3456
|
+
}, QUEUE_OWNER_HEARTBEAT_INTERVAL_MS);
|
|
3457
|
+
}
|
|
3268
3458
|
async function runSessionQueueOwner(options) {
|
|
3269
3459
|
const lease = await tryAcquireQueueOwnerLease(options.sessionId, {
|
|
3270
3460
|
path: options.mcpConfigPath,
|
|
@@ -3309,6 +3499,26 @@ async function runSessionQueueOwner(options) {
|
|
|
3309
3499
|
turnController.endTurn();
|
|
3310
3500
|
}
|
|
3311
3501
|
};
|
|
3502
|
+
const shutdown = createQueueOwnerShutdownController({
|
|
3503
|
+
lease,
|
|
3504
|
+
getOwner: () => owner,
|
|
3505
|
+
stopHeartbeat: () => {
|
|
3506
|
+
if (heartbeatTimer) {
|
|
3507
|
+
clearInterval(heartbeatTimer);
|
|
3508
|
+
heartbeatTimer = void 0;
|
|
3509
|
+
}
|
|
3510
|
+
},
|
|
3511
|
+
turnController,
|
|
3512
|
+
sharedClient,
|
|
3513
|
+
sessionId: options.sessionId,
|
|
3514
|
+
verbose: options.verbose
|
|
3515
|
+
});
|
|
3516
|
+
const onSignal = () => {
|
|
3517
|
+
shutdown.request();
|
|
3518
|
+
};
|
|
3519
|
+
process.once("SIGINT", onSignal);
|
|
3520
|
+
process.once("SIGTERM", onSignal);
|
|
3521
|
+
process.once("SIGHUP", onSignal);
|
|
3312
3522
|
try {
|
|
3313
3523
|
owner = await SessionQueueOwner.start(lease, {
|
|
3314
3524
|
cancelPrompt: async () => {
|
|
@@ -3331,6 +3541,7 @@ async function runSessionQueueOwner(options) {
|
|
|
3331
3541
|
refreshQueueOwnerLease(lease, { queueDepth }).catch(() => {});
|
|
3332
3542
|
}
|
|
3333
3543
|
});
|
|
3544
|
+
applyRequestedShutdown(owner, shutdown);
|
|
3334
3545
|
logQueueOwnerReady({
|
|
3335
3546
|
sessionId: options.sessionId,
|
|
3336
3547
|
ttlMs,
|
|
@@ -3338,16 +3549,18 @@ async function runSessionQueueOwner(options) {
|
|
|
3338
3549
|
verbose: options.verbose
|
|
3339
3550
|
});
|
|
3340
3551
|
await refreshQueueOwnerLease(lease, { queueDepth: owner.queueDepth() }).catch(() => {});
|
|
3341
|
-
heartbeatTimer =
|
|
3342
|
-
|
|
3343
|
-
|
|
3552
|
+
heartbeatTimer = startQueueOwnerHeartbeat({
|
|
3553
|
+
enabled: !shutdown.requested,
|
|
3554
|
+
lease,
|
|
3555
|
+
owner
|
|
3556
|
+
});
|
|
3344
3557
|
let isFirstTask = true;
|
|
3345
3558
|
while (true) {
|
|
3346
3559
|
const pollTimeoutMs = isFirstTask ? initialTaskPollTimeoutMs : taskPollTimeoutMs;
|
|
3347
3560
|
const task = await owner.nextTask(pollTimeoutMs);
|
|
3348
3561
|
if (!task) break;
|
|
3349
3562
|
isFirstTask = false;
|
|
3350
|
-
|
|
3563
|
+
const turnPromise = runPromptTurn(async () => {
|
|
3351
3564
|
try {
|
|
3352
3565
|
await runQueuedTask(options.sessionId, task, {
|
|
3353
3566
|
sharedClient,
|
|
@@ -3364,23 +3577,25 @@ async function runSessionQueueOwner(options) {
|
|
|
3364
3577
|
onPromptActive: async () => {
|
|
3365
3578
|
turnController.markPromptActive();
|
|
3366
3579
|
await applyPendingCancel();
|
|
3367
|
-
}
|
|
3580
|
+
},
|
|
3581
|
+
handleProcessInterrupts: false
|
|
3368
3582
|
});
|
|
3369
3583
|
} finally {
|
|
3370
3584
|
checkpointPerfMetricsCapture();
|
|
3371
3585
|
}
|
|
3372
3586
|
});
|
|
3587
|
+
shutdown.setActiveTurn(turnPromise);
|
|
3588
|
+
try {
|
|
3589
|
+
await turnPromise;
|
|
3590
|
+
} finally {
|
|
3591
|
+
shutdown.clearActiveTurn(turnPromise);
|
|
3592
|
+
}
|
|
3373
3593
|
}
|
|
3374
3594
|
} finally {
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
turnController,
|
|
3380
|
-
sharedClient,
|
|
3381
|
-
sessionId: options.sessionId,
|
|
3382
|
-
verbose: options.verbose
|
|
3383
|
-
});
|
|
3595
|
+
process.off("SIGINT", onSignal);
|
|
3596
|
+
process.off("SIGTERM", onSignal);
|
|
3597
|
+
process.off("SIGHUP", onSignal);
|
|
3598
|
+
await shutdown.shutdown();
|
|
3384
3599
|
}
|
|
3385
3600
|
}
|
|
3386
3601
|
async function sendSession(options) {
|
|
@@ -3695,6 +3910,12 @@ function asRecord(value) {
|
|
|
3695
3910
|
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
3696
3911
|
return value;
|
|
3697
3912
|
}
|
|
3913
|
+
function parseJsonRpcErrorSummary(message) {
|
|
3914
|
+
const fallback = parseJsonRpcErrorMessage(message);
|
|
3915
|
+
if (!fallback) return;
|
|
3916
|
+
const details = asRecord(asRecord(message.error)?.data)?.details;
|
|
3917
|
+
return typeof details === "string" && details.trim().length > 0 ? details.trim() : fallback;
|
|
3918
|
+
}
|
|
3698
3919
|
function extractJsonRpcMethod(message) {
|
|
3699
3920
|
return Object.hasOwn(message, "method") ? message.method?.toString() : void 0;
|
|
3700
3921
|
}
|
|
@@ -4060,7 +4281,7 @@ var TextOutputFormatter = class {
|
|
|
4060
4281
|
this.renderDone(stopReason);
|
|
4061
4282
|
return;
|
|
4062
4283
|
}
|
|
4063
|
-
const errorMessage =
|
|
4284
|
+
const errorMessage = parseJsonRpcErrorSummary(message);
|
|
4064
4285
|
if (errorMessage) this.onError({
|
|
4065
4286
|
code: "RUNTIME",
|
|
4066
4287
|
origin: "acp",
|
|
@@ -4286,7 +4507,11 @@ var QuietOutputFormatter = class {
|
|
|
4286
4507
|
this.flushMetadata(message);
|
|
4287
4508
|
}
|
|
4288
4509
|
}
|
|
4289
|
-
onError(
|
|
4510
|
+
onError(params) {
|
|
4511
|
+
const qualifier = params.detailCode ? `${params.code} ${params.detailCode}` : params.code;
|
|
4512
|
+
const message = preferredAcpErrorDetails(params.acp) ?? params.message;
|
|
4513
|
+
this.stderr.write(`[acpx] error: ${qualifier} ${message.replace(/\r\n?|\n/g, " ")}\n`);
|
|
4514
|
+
}
|
|
4290
4515
|
onPermissionEscalation(_event) {}
|
|
4291
4516
|
flush() {}
|
|
4292
4517
|
flushBufferedOutput() {
|
|
@@ -4347,6 +4572,10 @@ var QuietOutputFormatter = class {
|
|
|
4347
4572
|
if (typeof cost === "string" && cost.trim()) return `[acpx] cost: ${cost.trim()}`;
|
|
4348
4573
|
}
|
|
4349
4574
|
};
|
|
4575
|
+
function preferredAcpErrorDetails(acp) {
|
|
4576
|
+
const details = asRecord(acp?.data)?.details;
|
|
4577
|
+
return typeof details === "string" && details.trim().length > 0 ? details.trim() : void 0;
|
|
4578
|
+
}
|
|
4350
4579
|
function createOutputFormatter(format, options = {}) {
|
|
4351
4580
|
const stdout = options.stdout ?? process.stdout;
|
|
4352
4581
|
const stderr = options.stderr ?? process.stderr;
|
|
@@ -4361,4 +4590,4 @@ function createOutputFormatter(format, options = {}) {
|
|
|
4361
4590
|
//#endregion
|
|
4362
4591
|
export { runSessionQueueOwner as a, buildQueueOwnerArgOverride as c, createSessionWithClient as d, cancelSessionPrompt as f, __exportAll as g, isProcessAlive 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 };
|
|
4363
4592
|
|
|
4364
|
-
//# sourceMappingURL=output-
|
|
4593
|
+
//# sourceMappingURL=output-CjdF5rHk.js.map
|