acpx 0.19.1 → 0.19.2
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/dist/{cli-BerngYEz.js → cli-D-s_eTUy.js} +5 -5
- package/dist/{cli-BerngYEz.js.map → cli-D-s_eTUy.js.map} +1 -1
- package/dist/cli.js +8 -8
- package/dist/{flows-DimX0it5.js → flows-DdxEaeZo.js} +4 -4
- package/dist/{flows-DimX0it5.js.map → flows-DdxEaeZo.js.map} +1 -1
- package/dist/flows.js +1 -1
- package/dist/{invocation-options-vobVApfO.js → invocation-options-HjxSBsK0.js} +4 -4
- package/dist/{invocation-options-vobVApfO.js.map → invocation-options-HjxSBsK0.js.map} +1 -1
- package/dist/{ipc-DAApJ5mi.js → ipc-D0ZMQ0q9.js} +906 -78
- package/dist/ipc-D0ZMQ0q9.js.map +1 -0
- package/dist/{output-Cnuji8Bo.js → output-GQnhkJMU.js} +3 -3
- package/dist/{output-Cnuji8Bo.js.map → output-GQnhkJMU.js.map} +1 -1
- package/dist/{queue-owner-runtime-C4OOosbo.js → queue-owner-runtime-W0lly6ap.js} +94 -540
- package/dist/queue-owner-runtime-W0lly6ap.js.map +1 -0
- package/dist/runtime.js +3 -3
- package/dist/{session-watch-Bj9LoYUq.js → session-watch-_8yxQ6ba.js} +4 -4
- package/dist/{session-watch-Bj9LoYUq.js.map → session-watch-_8yxQ6ba.js.map} +1 -1
- package/dist/watch-C0mwpJcN.js +85 -0
- package/dist/watch-C0mwpJcN.js.map +1 -0
- package/package.json +1 -1
- package/dist/ipc-DAApJ5mi.js.map +0 -1
- package/dist/queue-owner-runtime-C4OOosbo.js.map +0 -1
- package/dist/watch-Cz6jbrRs.js +0 -32
- package/dist/watch-Cz6jbrRs.js.map +0 -1
|
@@ -11,6 +11,7 @@ import { createHash, randomInt, randomUUID } from "node:crypto";
|
|
|
11
11
|
import { isHardlinkFallbackError } from "@openclaw/fs-safe/durability";
|
|
12
12
|
import { acquireFileLock } from "@openclaw/fs-safe/file-lock";
|
|
13
13
|
import net from "node:net";
|
|
14
|
+
import { resolveSecureTempRoot } from "@openclaw/fs-safe/secure-temp-root";
|
|
14
15
|
//#region src/errors.ts
|
|
15
16
|
var AcpxOperationalError = class extends Error {
|
|
16
17
|
outputCode;
|
|
@@ -231,12 +232,12 @@ const SESSION_RECORD_SCHEMA = "acpx.session.v1";
|
|
|
231
232
|
//#endregion
|
|
232
233
|
//#region src/acp/error-shapes.ts
|
|
233
234
|
const RESOURCE_NOT_FOUND_ACP_CODES = /* @__PURE__ */ new Set([-32001, -32002]);
|
|
234
|
-
function asRecord$
|
|
235
|
+
function asRecord$5(value) {
|
|
235
236
|
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
236
237
|
return value;
|
|
237
238
|
}
|
|
238
239
|
function toAcpErrorPayload(value) {
|
|
239
|
-
const record = asRecord$
|
|
240
|
+
const record = asRecord$5(value);
|
|
240
241
|
if (!record) return;
|
|
241
242
|
if (typeof record.code !== "number" || !Number.isFinite(record.code)) return;
|
|
242
243
|
if (typeof record.message !== "string" || record.message.length === 0) return;
|
|
@@ -250,7 +251,7 @@ function extractAcpErrorInternal(value, depth) {
|
|
|
250
251
|
if (depth > 5) return;
|
|
251
252
|
const direct = toAcpErrorPayload(value);
|
|
252
253
|
if (direct) return direct;
|
|
253
|
-
const record = asRecord$
|
|
254
|
+
const record = asRecord$5(value);
|
|
254
255
|
if (!record) return;
|
|
255
256
|
return extractNestedAcpError(record, depth);
|
|
256
257
|
}
|
|
@@ -285,7 +286,7 @@ function hasSessionNotFoundHint(value, depth = 0) {
|
|
|
285
286
|
if (depth > 4) return false;
|
|
286
287
|
if (isSessionNotFoundText(value)) return true;
|
|
287
288
|
if (Array.isArray(value)) return value.some((entry) => hasSessionNotFoundHint(entry, depth + 1));
|
|
288
|
-
const record = asRecord$
|
|
289
|
+
const record = asRecord$5(value);
|
|
289
290
|
if (!record) return false;
|
|
290
291
|
return Object.values(record).some((entry) => hasSessionNotFoundHint(entry, depth + 1));
|
|
291
292
|
}
|
|
@@ -302,6 +303,136 @@ function isAcpResourceNotFoundError(error) {
|
|
|
302
303
|
return isSessionNotFoundText(formatUnknownErrorMessage(error));
|
|
303
304
|
}
|
|
304
305
|
//#endregion
|
|
306
|
+
//#region src/acp/error-normalization.ts
|
|
307
|
+
const AUTH_REQUIRED_ACP_CODES = /* @__PURE__ */ new Set([-32e3]);
|
|
308
|
+
const QUERY_CLOSED_BEFORE_RESPONSE_DETAIL = "query closed before response received";
|
|
309
|
+
function asRecord$4(value) {
|
|
310
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
311
|
+
return value;
|
|
312
|
+
}
|
|
313
|
+
function isAuthRequiredMessage(value) {
|
|
314
|
+
if (!value) return false;
|
|
315
|
+
const normalized = value.toLowerCase();
|
|
316
|
+
return [
|
|
317
|
+
"auth required",
|
|
318
|
+
"authentication required",
|
|
319
|
+
"authorization required",
|
|
320
|
+
"credential required",
|
|
321
|
+
"credentials required",
|
|
322
|
+
"token required",
|
|
323
|
+
"login required"
|
|
324
|
+
].some((needle) => normalized.includes(needle));
|
|
325
|
+
}
|
|
326
|
+
function isAcpAuthRequiredPayload(acp) {
|
|
327
|
+
if (!acp) return false;
|
|
328
|
+
if (!AUTH_REQUIRED_ACP_CODES.has(acp.code)) return false;
|
|
329
|
+
if (isAuthRequiredMessage(acp.message)) return true;
|
|
330
|
+
const data = asRecord$4(acp.data);
|
|
331
|
+
if (!data) return false;
|
|
332
|
+
return hasAuthRequiredData(data);
|
|
333
|
+
}
|
|
334
|
+
function hasAuthRequiredData(data) {
|
|
335
|
+
return data.authRequired === true || hasNonEmptyString(data.methodId) || hasNonEmptyArray(data.methods);
|
|
336
|
+
}
|
|
337
|
+
function hasNonEmptyString(value) {
|
|
338
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
339
|
+
}
|
|
340
|
+
function hasNonEmptyArray(value) {
|
|
341
|
+
return Array.isArray(value) && value.length > 0;
|
|
342
|
+
}
|
|
343
|
+
function isOutputErrorCode$1(value) {
|
|
344
|
+
return typeof value === "string" && OUTPUT_ERROR_CODES.includes(value);
|
|
345
|
+
}
|
|
346
|
+
function isOutputErrorOrigin$1(value) {
|
|
347
|
+
return typeof value === "string" && OUTPUT_ERROR_ORIGINS.includes(value);
|
|
348
|
+
}
|
|
349
|
+
function readOutputErrorMeta(error) {
|
|
350
|
+
const record = asRecord$4(error);
|
|
351
|
+
if (!record) return {};
|
|
352
|
+
return {
|
|
353
|
+
outputCode: isOutputErrorCode$1(record.outputCode) ? record.outputCode : void 0,
|
|
354
|
+
detailCode: typeof record.detailCode === "string" && record.detailCode.trim().length > 0 ? record.detailCode : void 0,
|
|
355
|
+
origin: isOutputErrorOrigin$1(record.origin) ? record.origin : void 0,
|
|
356
|
+
retryable: typeof record.retryable === "boolean" ? record.retryable : void 0,
|
|
357
|
+
acp: extractAcpError(record.acp)
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function isTimeoutLike(error) {
|
|
361
|
+
return error instanceof Error && error.name === "TimeoutError";
|
|
362
|
+
}
|
|
363
|
+
function isNoSessionLike(error) {
|
|
364
|
+
return error instanceof Error && error.name === "NoSessionError";
|
|
365
|
+
}
|
|
366
|
+
function isUsageLike(error) {
|
|
367
|
+
if (!(error instanceof Error)) return false;
|
|
368
|
+
return error.name === "CommanderError" || error.name === "InvalidArgumentError" || asRecord$4(error)?.code === "commander.invalidArgument";
|
|
369
|
+
}
|
|
370
|
+
function formatErrorMessage(error) {
|
|
371
|
+
return formatUnknownErrorMessage(error);
|
|
372
|
+
}
|
|
373
|
+
function isAcpQueryClosedBeforeResponseError(error) {
|
|
374
|
+
const acp = extractAcpError(error);
|
|
375
|
+
if (!acp || acp.code !== -32603) return false;
|
|
376
|
+
const details = asRecord$4(acp.data)?.details;
|
|
377
|
+
if (typeof details !== "string") return false;
|
|
378
|
+
return details.toLowerCase().includes(QUERY_CLOSED_BEFORE_RESPONSE_DETAIL);
|
|
379
|
+
}
|
|
380
|
+
function mapErrorCode(error) {
|
|
381
|
+
if (error instanceof PermissionPromptUnavailableError) return "PERMISSION_PROMPT_UNAVAILABLE";
|
|
382
|
+
if (error instanceof PermissionDeniedError) return "PERMISSION_DENIED";
|
|
383
|
+
if (isTimeoutLike(error)) return "TIMEOUT";
|
|
384
|
+
if (isNoSessionLike(error) || isAcpResourceNotFoundError(error)) return "NO_SESSION";
|
|
385
|
+
if (isUsageLike(error)) return "USAGE";
|
|
386
|
+
}
|
|
387
|
+
function normalizeOutputError(error, options = {}) {
|
|
388
|
+
const meta = readOutputErrorMeta(error);
|
|
389
|
+
const code = resolveOutputErrorCode(error, options, meta);
|
|
390
|
+
const acp = options.acp ?? meta.acp ?? extractAcpError(error);
|
|
391
|
+
return {
|
|
392
|
+
code,
|
|
393
|
+
message: formatErrorMessage(error),
|
|
394
|
+
detailCode: resolveDetailCode(error, acp, options, meta),
|
|
395
|
+
origin: meta.origin ?? options.origin,
|
|
396
|
+
retryable: meta.retryable ?? options.retryable,
|
|
397
|
+
acp
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
function resolveOutputErrorCode(error, options, meta) {
|
|
401
|
+
const code = meta.outputCode ?? mapErrorCode(error) ?? options.defaultCode ?? "RUNTIME";
|
|
402
|
+
if (code === "RUNTIME" && isAcpResourceNotFoundError(error)) return "NO_SESSION";
|
|
403
|
+
return code;
|
|
404
|
+
}
|
|
405
|
+
function resolveDetailCode(error, acp, options, meta) {
|
|
406
|
+
return meta.detailCode ?? options.detailCode ?? (error instanceof AuthPolicyError || isAcpAuthRequiredPayload(acp) ? "AUTH_REQUIRED" : void 0);
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Returns true when an error from `client.prompt()` looks transient and
|
|
410
|
+
* can reasonably be retried (e.g. model-API 400/500, network hiccups that
|
|
411
|
+
* surface as ACP internal errors).
|
|
412
|
+
*
|
|
413
|
+
* Errors that are definitively non-recoverable (auth, missing session,
|
|
414
|
+
* invalid params, timeout, permission) return false.
|
|
415
|
+
*/
|
|
416
|
+
function isRetryablePromptError(error) {
|
|
417
|
+
if (isNonRetryablePromptError(error)) return false;
|
|
418
|
+
const acp = extractAcpError(error);
|
|
419
|
+
if (!acp) return false;
|
|
420
|
+
return acp.code === -32603 || acp.code === -32700;
|
|
421
|
+
}
|
|
422
|
+
function isNonRetryablePromptError(error) {
|
|
423
|
+
return error instanceof PermissionDeniedError || error instanceof PermissionPromptUnavailableError || isTimeoutLike(error) || isNoSessionLike(error) || isUsageLike(error);
|
|
424
|
+
}
|
|
425
|
+
function exitCodeForOutputErrorCode(code) {
|
|
426
|
+
switch (code) {
|
|
427
|
+
case "USAGE": return EXIT_CODES.USAGE;
|
|
428
|
+
case "TIMEOUT": return EXIT_CODES.TIMEOUT;
|
|
429
|
+
case "NO_SESSION": return EXIT_CODES.NO_SESSION;
|
|
430
|
+
case "PERMISSION_DENIED":
|
|
431
|
+
case "PERMISSION_PROMPT_UNAVAILABLE": return EXIT_CODES.PERMISSION_DENIED;
|
|
432
|
+
default: return EXIT_CODES.ERROR;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
//#endregion
|
|
305
436
|
//#region src/process-liveness.ts
|
|
306
437
|
function isProcessAlive(pid) {
|
|
307
438
|
if (!pid || !Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -686,7 +817,15 @@ function parseCursor(recordId, cursor) {
|
|
|
686
817
|
return parsed.data[1];
|
|
687
818
|
}
|
|
688
819
|
function fileIdentity(stat) {
|
|
689
|
-
return `${stat.dev}:${stat.ino}:${stat.
|
|
820
|
+
return `${stat.dev}:${stat.ino}:${stat.birthtimeNs}`;
|
|
821
|
+
}
|
|
822
|
+
async function pathIdentity(filePath) {
|
|
823
|
+
try {
|
|
824
|
+
return fileIdentity(await fs$1.lstat(filePath, { bigint: true }));
|
|
825
|
+
} catch (error) {
|
|
826
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return;
|
|
827
|
+
throw error;
|
|
828
|
+
}
|
|
690
829
|
}
|
|
691
830
|
function emptySegment() {
|
|
692
831
|
return {
|
|
@@ -718,12 +857,9 @@ var SessionJournalReader = class {
|
|
|
718
857
|
const segments = [];
|
|
719
858
|
try {
|
|
720
859
|
const paths = await this.openPresentSegments(segments);
|
|
721
|
-
const current = await Promise.all(paths.map(
|
|
860
|
+
const current = await Promise.all(paths.map(pathIdentity));
|
|
722
861
|
const identities = new Map(segments.map((entry) => [entry.filePath, entry.identity]));
|
|
723
|
-
if (paths.every((filePath, index) =>
|
|
724
|
-
const entry = current[index];
|
|
725
|
-
return (entry.missing ? void 0 : fileIdentity(entry.stat)) === identities.get(filePath);
|
|
726
|
-
})) return segments;
|
|
862
|
+
if (paths.every((filePath, index) => current[index] === identities.get(filePath))) return segments;
|
|
727
863
|
} catch (error) {
|
|
728
864
|
if (!retryableSnapshotError(error)) {
|
|
729
865
|
await this.closeSnapshot(segments);
|
|
@@ -744,11 +880,16 @@ var SessionJournalReader = class {
|
|
|
744
880
|
symlinks: "reject",
|
|
745
881
|
nonBlockingRead: true
|
|
746
882
|
});
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
883
|
+
try {
|
|
884
|
+
return {
|
|
885
|
+
filePath,
|
|
886
|
+
opened,
|
|
887
|
+
identity: fileIdentity(await opened.handle.stat({ bigint: true }))
|
|
888
|
+
};
|
|
889
|
+
} catch (error) {
|
|
890
|
+
await opened[Symbol.asyncDispose]();
|
|
891
|
+
throw error;
|
|
892
|
+
}
|
|
752
893
|
}));
|
|
753
894
|
let failure;
|
|
754
895
|
for (const result of results) if (result.status === "fulfilled") segments.push(result.value);
|
|
@@ -978,6 +1119,7 @@ async function* iterateJournal(record, options) {
|
|
|
978
1119
|
let after = options.cursor === void 0 ? -1 : parseCursor(record.acpxRecordId, options.cursor);
|
|
979
1120
|
const reader = new SessionJournalReader(record);
|
|
980
1121
|
let first = true;
|
|
1122
|
+
const observation = {};
|
|
981
1123
|
for (;;) {
|
|
982
1124
|
if (signal.aborted) return;
|
|
983
1125
|
const snapshot = await settleUnlessAborted(reader.read(signal, {
|
|
@@ -992,16 +1134,34 @@ async function* iterateJournal(record, options) {
|
|
|
992
1134
|
after = sequence;
|
|
993
1135
|
yield event;
|
|
994
1136
|
}
|
|
995
|
-
if (!await continueAfterPage(record, snapshot, options)) return;
|
|
1137
|
+
if (!await continueAfterPage(record, snapshot, options, observation)) return;
|
|
996
1138
|
}
|
|
997
1139
|
}
|
|
998
|
-
async function continueAfterPage(record, snapshot, options) {
|
|
1140
|
+
async function continueAfterPage(record, snapshot, options, observation) {
|
|
1141
|
+
if (options.signal.aborted || confirmsTerminalObservation(snapshot, observation)) return false;
|
|
999
1142
|
if (!snapshot.hasMore && options.continueWatching) {
|
|
1000
|
-
|
|
1143
|
+
const decision = await settleUnlessAborted(options.continueWatching(record, snapshot.requestId), options.signal).catch((error) => {
|
|
1144
|
+
if (error instanceof SessionWatchError && error.code === "WATCH_OUTCOME_UNKNOWN") return error;
|
|
1145
|
+
throw error;
|
|
1146
|
+
});
|
|
1147
|
+
if (decision !== true) {
|
|
1148
|
+
observation.terminal = {
|
|
1149
|
+
requestId: snapshot.requestId,
|
|
1150
|
+
error: decision instanceof SessionWatchError ? decision : void 0
|
|
1151
|
+
};
|
|
1152
|
+
return !options.signal.aborted;
|
|
1153
|
+
}
|
|
1001
1154
|
}
|
|
1002
1155
|
await settleUnlessAborted(setTimeout$1(snapshot.hasMore ? 0 : 100, void 0, { signal: options.signal }), options.signal);
|
|
1003
1156
|
return !options.signal.aborted;
|
|
1004
1157
|
}
|
|
1158
|
+
function confirmsTerminalObservation(snapshot, observation) {
|
|
1159
|
+
const terminal = observation.terminal;
|
|
1160
|
+
delete observation.terminal;
|
|
1161
|
+
if (!terminal || snapshot.events.length > 0 || snapshot.hasMore || snapshot.requestId !== terminal.requestId) return false;
|
|
1162
|
+
if (terminal.error) throw terminal.error;
|
|
1163
|
+
return true;
|
|
1164
|
+
}
|
|
1005
1165
|
function assertRetainedCursor(after, snapshot, first) {
|
|
1006
1166
|
if (after < 0) return;
|
|
1007
1167
|
if (after > snapshot.sequence) throw new SessionWatchError(first ? "WATCH_CURSOR_FUTURE" : "WATCH_CURSOR_EXPIRED", "Cursor is beyond the available session journal");
|
|
@@ -2697,16 +2857,30 @@ function retirementTimeRemaining(deadline, maximumMs = 2e3) {
|
|
|
2697
2857
|
if (remaining <= 0) throw queueRetirementIncomplete();
|
|
2698
2858
|
return Math.min(maximumMs, remaining);
|
|
2699
2859
|
}
|
|
2700
|
-
async function
|
|
2860
|
+
async function readRetirementSnapshot(deadline) {
|
|
2861
|
+
if (process.platform !== "win32") throw queueRetirementIncomplete();
|
|
2862
|
+
return await readProcessTable(retirementTimeRemaining(deadline)).catch(() => {
|
|
2863
|
+
throw queueRetirementIncomplete();
|
|
2864
|
+
});
|
|
2865
|
+
}
|
|
2866
|
+
function observeRetirementSnapshot(witness, table) {
|
|
2867
|
+
if (process.platform !== "win32" || !isWindowsRetirementIdentity(witness.processIdentity)) return "unknown";
|
|
2868
|
+
const observed = table?.get(witness.pid);
|
|
2869
|
+
const comparison = observed ? compareProcessBirthIdentity(witness.processIdentity, observed.birth) : "unknown";
|
|
2870
|
+
if (comparison === "different" || isProcessDefinitelyDead(witness.pid)) return "gone";
|
|
2871
|
+
return witness.pid === process.pid ? "unknown" : comparison;
|
|
2872
|
+
}
|
|
2873
|
+
function isWindowsRetirementIdentity(identity) {
|
|
2874
|
+
return identity === void 0 || identity.kind === "windows-creation";
|
|
2875
|
+
}
|
|
2876
|
+
function captureQueueRetirementReceipt(owner, previous, rootRunning, snapshot) {
|
|
2701
2877
|
const root = parseWitness({
|
|
2702
2878
|
pid: owner.pid,
|
|
2703
2879
|
processIdentity: owner.processIdentity
|
|
2704
2880
|
});
|
|
2705
2881
|
if (!root || process.platform !== "win32") throw queueRetirementIncomplete();
|
|
2706
|
-
const
|
|
2707
|
-
|
|
2708
|
-
});
|
|
2709
|
-
const saved = unsettledSnapshotWitnesses(table, previous ? previous.descendants : []);
|
|
2882
|
+
const saved = previous ? previous.descendants : [];
|
|
2883
|
+
const table = new Map(snapshot);
|
|
2710
2884
|
const owned = matchingSnapshotPids(table, rootRunning ? [root, ...saved] : saved);
|
|
2711
2885
|
if (rootRunning && !owned.has(root.pid)) throw queueRetirementIncomplete();
|
|
2712
2886
|
table.delete(1);
|
|
@@ -2716,7 +2890,7 @@ async function captureQueueRetirementReceipt(owner, previous, rootRunning, deadl
|
|
|
2716
2890
|
const receipt = {
|
|
2717
2891
|
ownerGeneration: owner.ownerGeneration,
|
|
2718
2892
|
root,
|
|
2719
|
-
descendants: mergeSnapshotDescendants(table, owned, saved)
|
|
2893
|
+
descendants: unsettledSnapshotWitnesses(snapshot, mergeSnapshotDescendants(table, owned, saved))
|
|
2720
2894
|
};
|
|
2721
2895
|
if (!parseQueueRetirementReceipt(receipt, owner)) throw queueRetirementIncomplete();
|
|
2722
2896
|
return receipt;
|
|
@@ -2752,7 +2926,11 @@ async function observeRetirementWitness(witness, deadline) {
|
|
|
2752
2926
|
}
|
|
2753
2927
|
async function assertQueueRetirementComplete(receipt, deadline) {
|
|
2754
2928
|
if (receipt === null) throw queueRetirementIncomplete();
|
|
2755
|
-
|
|
2929
|
+
const witnesses = receipt?.descendants ?? [];
|
|
2930
|
+
if (witnesses.length === 0) return;
|
|
2931
|
+
const live = witnesses.filter((witness) => observeRetirementSnapshot(witness, void 0) !== "gone");
|
|
2932
|
+
const table = live.length > 0 ? await readRetirementSnapshot(deadline) : void 0;
|
|
2933
|
+
for (const witness of live) if (observeRetirementSnapshot(witness, table) !== "gone") throw queueRetirementIncomplete();
|
|
2756
2934
|
}
|
|
2757
2935
|
//#endregion
|
|
2758
2936
|
//#region src/session/queue/lease-mutation.ts
|
|
@@ -3255,17 +3433,37 @@ function unverifiedQueueOwnerError(owner) {
|
|
|
3255
3433
|
function retirementDeadline() {
|
|
3256
3434
|
return performance.now() + PROCESS_SIGTERM_GRACE_MS + PROCESS_SIGKILL_GRACE_MS;
|
|
3257
3435
|
}
|
|
3436
|
+
async function createQueueOwnerRetirement(deadline) {
|
|
3437
|
+
const snapshot = process.platform === "win32" ? await readRetirementSnapshot(deadline).catch(() => void 0) : void 0;
|
|
3438
|
+
return {
|
|
3439
|
+
gone: false,
|
|
3440
|
+
unverified: false,
|
|
3441
|
+
leaseReleased: false,
|
|
3442
|
+
deadline,
|
|
3443
|
+
snapshot,
|
|
3444
|
+
capturedIdentity: process.platform === "win32" ? { processIdentity: snapshot?.get(process.pid)?.birth } : void 0
|
|
3445
|
+
};
|
|
3446
|
+
}
|
|
3258
3447
|
async function observeRetiringOwner(owner, deadline) {
|
|
3259
3448
|
return await observeProcessIncarnation(owner.pid, owner.processIdentity, process.platform === "win32" ? retirementTimeRemaining(deadline) : void 0);
|
|
3260
3449
|
}
|
|
3261
3450
|
function retirementBlockedByHeartbeat(owner, signal, requireStale) {
|
|
3262
3451
|
return requireStale && owner.retirement === void 0 && signal === "SIGTERM" && !isQueueOwnerHeartbeatStale(owner);
|
|
3263
3452
|
}
|
|
3264
|
-
async function prepareWindowsRetirement(owner, deadline) {
|
|
3265
|
-
if (owner.retirement === null) throw queueRetirementIncomplete();
|
|
3266
|
-
owner.retirement =
|
|
3453
|
+
async function prepareWindowsRetirement(owner, table, deadline) {
|
|
3454
|
+
if (owner.retirement === null || !table) throw queueRetirementIncomplete();
|
|
3455
|
+
owner.retirement = captureQueueRetirementReceipt(owner, owner.retirement, true, table);
|
|
3267
3456
|
await replaceQueueOwnerRecord(owner);
|
|
3268
|
-
return await observeRetirementWitness(owner.retirement.root, deadline)
|
|
3457
|
+
return await observeRetirementWitness(owner.retirement.root, deadline);
|
|
3458
|
+
}
|
|
3459
|
+
async function prepareRetiringOwner(owner, signal, retirement) {
|
|
3460
|
+
const windows = process.platform === "win32";
|
|
3461
|
+
const table = windows && signal !== "SIGTERM" ? await readRetirementSnapshot(retirement.deadline) : retirement.snapshot;
|
|
3462
|
+
let identity = windows ? observeRetirementSnapshot(owner, table) : await observeRetiringOwner(owner, retirement.deadline);
|
|
3463
|
+
if (identity === "matching" && windows) identity = await prepareWindowsRetirement(owner, table, retirement.deadline);
|
|
3464
|
+
retirement.gone = identity === "gone";
|
|
3465
|
+
retirement.unverified = identity === "unknown";
|
|
3466
|
+
return identity === "matching";
|
|
3269
3467
|
}
|
|
3270
3468
|
async function dispatchVerifiedQueueOwnerSignal(owner, signal, requireStale, retirement) {
|
|
3271
3469
|
return await withQueueLeaseMutation(owner.sessionId, async () => {
|
|
@@ -3273,26 +3471,15 @@ async function dispatchVerifiedQueueOwnerSignal(owner, signal, requireStale, ret
|
|
|
3273
3471
|
retirement.leaseReleased = current?.pid !== owner.pid;
|
|
3274
3472
|
if (!matchesQueueOwner(current, owner) || retirementBlockedByHeartbeat(current, signal, requireStale)) return false;
|
|
3275
3473
|
if (current.retirement === null) throw queueRetirementIncomplete();
|
|
3276
|
-
|
|
3277
|
-
if (identity !== "matching") {
|
|
3278
|
-
retirement.gone = identity === "gone";
|
|
3279
|
-
retirement.unverified = identity === "unknown";
|
|
3280
|
-
return false;
|
|
3281
|
-
}
|
|
3282
|
-
if (process.platform === "win32" && !await prepareWindowsRetirement(current, retirement.deadline)) return false;
|
|
3474
|
+
if (!await prepareRetiringOwner(current, signal, retirement)) return false;
|
|
3283
3475
|
return await dispatchQueueOwnerSignal(owner.pid, signal, retirement.deadline);
|
|
3284
|
-
});
|
|
3476
|
+
}, { capturedIdentity: retirement.capturedIdentity });
|
|
3285
3477
|
}
|
|
3286
|
-
async function retireQueueOwner(owner, requireStale,
|
|
3287
|
-
const
|
|
3288
|
-
|
|
3289
|
-
unverified: false,
|
|
3290
|
-
leaseReleased: false,
|
|
3291
|
-
deadline
|
|
3292
|
-
};
|
|
3293
|
-
await terminateWithDispatch(owner.pid, (signal) => dispatchVerifiedQueueOwnerSignal(owner, signal, requireStale, retirement), isProcessDefinitelyDead, process.platform === "win32" ? deadline : Infinity);
|
|
3478
|
+
async function retireQueueOwner(owner, requireStale, retirement) {
|
|
3479
|
+
const { deadline } = retirement;
|
|
3480
|
+
const exited = await terminateWithDispatch(owner.pid, (signal) => dispatchVerifiedQueueOwnerSignal(owner, signal, requireStale, retirement), isProcessDefinitelyDead, process.platform === "win32" ? deadline : Infinity);
|
|
3294
3481
|
if (await waitForReleasedOwner(owner, requireStale, retirement)) return false;
|
|
3295
|
-
const gone = retirement.gone || await observeRetiringOwner(owner, deadline) === "gone";
|
|
3482
|
+
const gone = retirement.gone || process.platform === "win32" && exited || await observeRetiringOwner(owner, deadline) === "gone";
|
|
3296
3483
|
if (retirement.unverified && !gone) throw unverifiedQueueOwnerError(owner);
|
|
3297
3484
|
return gone;
|
|
3298
3485
|
}
|
|
@@ -3307,44 +3494,80 @@ async function waitForReleasedOwner(owner, requireStale, retirement) {
|
|
|
3307
3494
|
}
|
|
3308
3495
|
return false;
|
|
3309
3496
|
}
|
|
3310
|
-
async function retireRecordedDescendants(owner,
|
|
3497
|
+
async function retireRecordedDescendants(owner, retirement) {
|
|
3311
3498
|
await withQueueLeaseMutation(owner.sessionId, async () => {
|
|
3312
3499
|
const current = await readQueueOwnerRecord(owner.sessionId);
|
|
3313
3500
|
if (!matchesQueueOwner(current, owner) || current.retirement === void 0) return;
|
|
3314
3501
|
if (current.retirement === null || process.platform !== "win32") throw queueRetirementIncomplete();
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
}
|
|
3322
|
-
async function
|
|
3323
|
-
|
|
3324
|
-
const
|
|
3325
|
-
|
|
3326
|
-
if (
|
|
3502
|
+
await retireSnapshotDescendants(current, current.retirement, retirement.deadline);
|
|
3503
|
+
}, { capturedIdentity: retirement.capturedIdentity });
|
|
3504
|
+
}
|
|
3505
|
+
function hasNewRetirementWitness(previous, receipt) {
|
|
3506
|
+
const saved = new Map(previous.descendants.map((witness) => [witness.pid, witness.processIdentity]));
|
|
3507
|
+
return receipt.descendants.some((witness) => compareProcessBirthIdentity(saved.get(witness.pid), witness.processIdentity) !== "matching");
|
|
3508
|
+
}
|
|
3509
|
+
async function retireSnapshotDescendants(owner, receipt, deadline) {
|
|
3510
|
+
while (receipt.descendants.length > 0) {
|
|
3511
|
+
const table = await readRetirementSnapshot(deadline);
|
|
3512
|
+
const discovered = captureQueueRetirementReceipt(owner, receipt, false, table);
|
|
3513
|
+
if (hasNewRetirementWitness(receipt, discovered)) {
|
|
3514
|
+
receipt = discovered;
|
|
3515
|
+
owner.retirement = receipt;
|
|
3516
|
+
await replaceQueueOwnerRecord(owner);
|
|
3517
|
+
continue;
|
|
3518
|
+
}
|
|
3519
|
+
signalRecordedDescendants(discovered, table, deadline);
|
|
3520
|
+
await waitForRecordedDescendants(discovered, deadline);
|
|
3521
|
+
discovered.descendants = discovered.descendants.filter((witness) => !isProcessDefinitelyDead(witness.pid));
|
|
3522
|
+
receipt = discovered;
|
|
3523
|
+
owner.retirement = receipt;
|
|
3524
|
+
await replaceQueueOwnerRecord(owner);
|
|
3327
3525
|
}
|
|
3328
|
-
return false;
|
|
3329
3526
|
}
|
|
3330
|
-
|
|
3527
|
+
function leafFirstRetirementWitnesses(receipt, table) {
|
|
3528
|
+
const children = new Map(receipt.descendants.map((witness) => [witness.pid, 0]));
|
|
3331
3529
|
for (const witness of receipt.descendants) {
|
|
3332
|
-
const
|
|
3333
|
-
|
|
3334
|
-
if (
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3530
|
+
const parent = retirementParent(witness.pid, table);
|
|
3531
|
+
const count = children.get(parent);
|
|
3532
|
+
if (count !== void 0) children.set(parent, count + 1);
|
|
3533
|
+
}
|
|
3534
|
+
const pending = receipt.descendants.filter((witness) => children.get(witness.pid) === 0);
|
|
3535
|
+
const byPid = new Map(receipt.descendants.map((witness) => [witness.pid, witness]));
|
|
3536
|
+
for (let index = 0; index < pending.length; index += 1) {
|
|
3537
|
+
const parent = retirementParent(pending[index].pid, table);
|
|
3538
|
+
const count = children.get(parent);
|
|
3539
|
+
if (count !== void 0) {
|
|
3540
|
+
const remaining = count - 1;
|
|
3541
|
+
children.set(parent, remaining);
|
|
3542
|
+
if (remaining === 0) pending.push(byPid.get(parent));
|
|
3341
3543
|
}
|
|
3342
3544
|
}
|
|
3545
|
+
if (pending.length !== receipt.descendants.length) throw queueRetirementIncomplete();
|
|
3546
|
+
return pending;
|
|
3547
|
+
}
|
|
3548
|
+
function retirementParent(pid, table) {
|
|
3549
|
+
const identity = table.get(pid);
|
|
3550
|
+
return identity && !hasStaleWindowsParent(identity, table.get(identity.parentPid)) ? identity.parentPid : 0;
|
|
3551
|
+
}
|
|
3552
|
+
function signalRecordedDescendants(receipt, table, deadline) {
|
|
3553
|
+
if (receipt.descendants.some((witness) => observeRetirementSnapshot(witness, table) === "unknown")) throw queueRetirementIncomplete();
|
|
3554
|
+
const ordered = leafFirstRetirementWitnesses(receipt, table);
|
|
3555
|
+
let failure;
|
|
3556
|
+
for (const witness of ordered) {
|
|
3557
|
+
if (observeRetirementSnapshot(witness, table) !== "matching") continue;
|
|
3558
|
+
retirementTimeRemaining(deadline);
|
|
3559
|
+
try {
|
|
3560
|
+
process.kill(witness.pid, "SIGKILL");
|
|
3561
|
+
} catch (error) {
|
|
3562
|
+
if (!isProcessDefinitelyDead(witness.pid)) failure ??= error;
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
if (failure) throw failure;
|
|
3343
3566
|
}
|
|
3344
3567
|
async function waitForRecordedDescendants(receipt, deadline) {
|
|
3345
|
-
|
|
3346
|
-
if (
|
|
3347
|
-
await waitMs(Math.min(
|
|
3568
|
+
for (let waited = 0; waited < 1e3; waited += PROCESS_POLL_MS) {
|
|
3569
|
+
if (receipt.descendants.every((witness) => isProcessDefinitelyDead(witness.pid))) return;
|
|
3570
|
+
await waitMs(Math.min(PROCESS_POLL_MS, retirementTimeRemaining(deadline)));
|
|
3348
3571
|
}
|
|
3349
3572
|
}
|
|
3350
3573
|
async function assertNoPendingRetirement(owner) {
|
|
@@ -3360,12 +3583,13 @@ async function terminateQueueOwnerForSession(sessionId, expectedOwner, requireSt
|
|
|
3360
3583
|
return;
|
|
3361
3584
|
}
|
|
3362
3585
|
const deadline = retirementDeadline();
|
|
3363
|
-
|
|
3586
|
+
const retirement = await createQueueOwnerRetirement(deadline);
|
|
3587
|
+
if (!await retireQueueOwner(owner, requireStale, retirement)) {
|
|
3364
3588
|
await assertNoPendingRetirement(owner);
|
|
3365
3589
|
return;
|
|
3366
3590
|
}
|
|
3367
|
-
await retireRecordedDescendants(owner,
|
|
3368
|
-
await cleanupQueueOwnerFiles(sessionId, owner.socketPath, () => ownsQueueLease(owner),
|
|
3591
|
+
await retireRecordedDescendants(owner, retirement);
|
|
3592
|
+
await cleanupQueueOwnerFiles(sessionId, owner.socketPath, () => ownsQueueLease(owner), retirement.capturedIdentity, deadline);
|
|
3369
3593
|
}
|
|
3370
3594
|
async function waitMs(ms) {
|
|
3371
3595
|
await new Promise((resolve) => {
|
|
@@ -3870,6 +4094,610 @@ function assertQueueRequestSize(line) {
|
|
|
3870
4094
|
});
|
|
3871
4095
|
}
|
|
3872
4096
|
//#endregion
|
|
4097
|
+
//#region src/session/queue/socket-output.ts
|
|
4098
|
+
const OUTPUT_CHUNK_BYTES = 65536;
|
|
4099
|
+
const DRAIN_TIMEOUT_MS = 1e3;
|
|
4100
|
+
const DEFAULT_LIMITS = Object.freeze({
|
|
4101
|
+
observerBytes: 67108864,
|
|
4102
|
+
totalBytes: 268435456,
|
|
4103
|
+
observers: 64
|
|
4104
|
+
});
|
|
4105
|
+
var QueueOutputBudget = class {
|
|
4106
|
+
limits;
|
|
4107
|
+
bytes = 0;
|
|
4108
|
+
files = 0;
|
|
4109
|
+
observers = 0;
|
|
4110
|
+
constructor(limits = DEFAULT_LIMITS) {
|
|
4111
|
+
this.limits = limits;
|
|
4112
|
+
}
|
|
4113
|
+
acquire() {
|
|
4114
|
+
if (this.files >= this.limits.observers) throw new Error("Queue output spool descriptor limit reached");
|
|
4115
|
+
this.files += 1;
|
|
4116
|
+
}
|
|
4117
|
+
grow(bytes) {
|
|
4118
|
+
if (bytes > this.limits.totalBytes - this.bytes) throw new Error("Queue output spool storage limit reached");
|
|
4119
|
+
this.bytes += bytes;
|
|
4120
|
+
}
|
|
4121
|
+
release(bytes) {
|
|
4122
|
+
this.bytes -= bytes;
|
|
4123
|
+
this.files -= 1;
|
|
4124
|
+
}
|
|
4125
|
+
acquireObserver() {
|
|
4126
|
+
if (this.observers >= this.limits.observers) throw new Error("Queue blocked observer limit reached");
|
|
4127
|
+
this.observers += 1;
|
|
4128
|
+
}
|
|
4129
|
+
releaseObserver() {
|
|
4130
|
+
this.observers -= 1;
|
|
4131
|
+
}
|
|
4132
|
+
};
|
|
4133
|
+
var OutputRing = class {
|
|
4134
|
+
budget;
|
|
4135
|
+
fd;
|
|
4136
|
+
physicalBytes = 0;
|
|
4137
|
+
readOffset = 0;
|
|
4138
|
+
length = 0;
|
|
4139
|
+
constructor(budget) {
|
|
4140
|
+
this.budget = budget;
|
|
4141
|
+
budget.acquire();
|
|
4142
|
+
try {
|
|
4143
|
+
const root = resolveSecureTempRoot({ fallbackPrefix: "acpx-output" });
|
|
4144
|
+
const file = path.join(root, `${randomUUID()}.tmp`);
|
|
4145
|
+
this.fd = fs.openSync(file, "wx+", 384);
|
|
4146
|
+
fs.unlinkSync(file);
|
|
4147
|
+
} catch (error) {
|
|
4148
|
+
if (this.fd === void 0) budget.release(0);
|
|
4149
|
+
else this.close();
|
|
4150
|
+
throw error;
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
append(bytes, offset) {
|
|
4154
|
+
const capacity = this.budget.limits.observerBytes;
|
|
4155
|
+
if (bytes.length - offset > capacity - this.length) throw new Error("Queue observer output backlog limit reached");
|
|
4156
|
+
while (offset < bytes.length) {
|
|
4157
|
+
const position = (this.readOffset + this.length) % capacity;
|
|
4158
|
+
const count = Math.min(OUTPUT_CHUNK_BYTES, bytes.length - offset, capacity - position);
|
|
4159
|
+
const growth = Math.max(0, position + count - this.physicalBytes);
|
|
4160
|
+
this.budget.grow(growth);
|
|
4161
|
+
this.physicalBytes += growth;
|
|
4162
|
+
const written = fs.writeSync(this.fd, bytes, offset, count, position);
|
|
4163
|
+
if (written <= 0) throw new Error("Queue output spool write made no progress");
|
|
4164
|
+
offset += written;
|
|
4165
|
+
this.length += written;
|
|
4166
|
+
}
|
|
4167
|
+
}
|
|
4168
|
+
read() {
|
|
4169
|
+
const capacity = this.budget.limits.observerBytes;
|
|
4170
|
+
const bytes = Buffer.allocUnsafeSlow(Math.min(OUTPUT_CHUNK_BYTES, this.length, capacity - this.readOffset));
|
|
4171
|
+
let offset = 0;
|
|
4172
|
+
while (offset < bytes.length) {
|
|
4173
|
+
const read = fs.readSync(this.fd, bytes, offset, bytes.length - offset, this.readOffset + offset);
|
|
4174
|
+
if (read <= 0) throw new Error("Queue output spool ended before its committed bytes");
|
|
4175
|
+
offset += read;
|
|
4176
|
+
}
|
|
4177
|
+
this.readOffset = (this.readOffset + bytes.length) % capacity;
|
|
4178
|
+
this.length -= bytes.length;
|
|
4179
|
+
return bytes;
|
|
4180
|
+
}
|
|
4181
|
+
close() {
|
|
4182
|
+
const fd = this.fd;
|
|
4183
|
+
this.fd = void 0;
|
|
4184
|
+
if (fd !== void 0) {
|
|
4185
|
+
fs.closeSync(fd);
|
|
4186
|
+
this.budget.release(this.physicalBytes);
|
|
4187
|
+
}
|
|
4188
|
+
}
|
|
4189
|
+
};
|
|
4190
|
+
var QueueSocketOutput = class {
|
|
4191
|
+
socket;
|
|
4192
|
+
budget;
|
|
4193
|
+
ring;
|
|
4194
|
+
blocked = false;
|
|
4195
|
+
ending = false;
|
|
4196
|
+
disposed = false;
|
|
4197
|
+
reserved = false;
|
|
4198
|
+
pendingWrites = 0;
|
|
4199
|
+
constructor(socket, budget) {
|
|
4200
|
+
this.socket = socket;
|
|
4201
|
+
this.budget = budget;
|
|
4202
|
+
socket.on("drain", this.onDrain);
|
|
4203
|
+
socket.once("close", () => {
|
|
4204
|
+
this.disposed = true;
|
|
4205
|
+
socket.off("drain", this.onDrain);
|
|
4206
|
+
this.closeSpool();
|
|
4207
|
+
this.releaseObserver();
|
|
4208
|
+
});
|
|
4209
|
+
}
|
|
4210
|
+
send(message) {
|
|
4211
|
+
if (this.ending || this.socket.destroyed || !this.socket.writable) return;
|
|
4212
|
+
try {
|
|
4213
|
+
this.writeFrame(Buffer.from(`${JSON.stringify(message)}\n`));
|
|
4214
|
+
} catch (error) {
|
|
4215
|
+
this.fail(error);
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
writeFrame(bytes) {
|
|
4219
|
+
let offset = 0;
|
|
4220
|
+
while (!this.blocked && offset < bytes.length) {
|
|
4221
|
+
const end = Math.min(offset + OUTPUT_CHUNK_BYTES, bytes.length);
|
|
4222
|
+
const chunk = Buffer.allocUnsafeSlow(end - offset);
|
|
4223
|
+
bytes.copy(chunk, 0, offset, end);
|
|
4224
|
+
this.write(chunk);
|
|
4225
|
+
offset = end;
|
|
4226
|
+
}
|
|
4227
|
+
if (offset < bytes.length) {
|
|
4228
|
+
this.ring ??= new OutputRing(this.budget);
|
|
4229
|
+
this.ring.append(bytes, offset);
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
end() {
|
|
4233
|
+
if (this.ending || this.socket.destroyed) return;
|
|
4234
|
+
this.ending = true;
|
|
4235
|
+
this.armTimeout();
|
|
4236
|
+
this.finishIfDrained();
|
|
4237
|
+
}
|
|
4238
|
+
write(bytes) {
|
|
4239
|
+
if (!this.reserved) {
|
|
4240
|
+
this.budget.acquireObserver();
|
|
4241
|
+
this.reserved = true;
|
|
4242
|
+
}
|
|
4243
|
+
this.pendingWrites += 1;
|
|
4244
|
+
try {
|
|
4245
|
+
this.blocked = !this.socket.write(bytes, this.onWrite);
|
|
4246
|
+
} catch (error) {
|
|
4247
|
+
this.pendingWrites -= 1;
|
|
4248
|
+
throw error;
|
|
4249
|
+
}
|
|
4250
|
+
if (this.blocked && !this.socket.timeout) this.armTimeout();
|
|
4251
|
+
}
|
|
4252
|
+
onWrite = (error) => {
|
|
4253
|
+
this.pendingWrites -= 1;
|
|
4254
|
+
if (this.disposed) return;
|
|
4255
|
+
if (error) {
|
|
4256
|
+
this.fail(error);
|
|
4257
|
+
return;
|
|
4258
|
+
}
|
|
4259
|
+
this.releaseIfIdle();
|
|
4260
|
+
};
|
|
4261
|
+
armTimeout() {
|
|
4262
|
+
if (process.platform !== "win32") this.socket.setTimeout(DRAIN_TIMEOUT_MS);
|
|
4263
|
+
}
|
|
4264
|
+
onDrain = () => {
|
|
4265
|
+
if (this.disposed) return;
|
|
4266
|
+
this.blocked = false;
|
|
4267
|
+
if (!this.ending) this.socket.setTimeout(0);
|
|
4268
|
+
try {
|
|
4269
|
+
this.pump();
|
|
4270
|
+
this.releaseIfIdle();
|
|
4271
|
+
this.finishIfDrained();
|
|
4272
|
+
} catch (error) {
|
|
4273
|
+
this.fail(error);
|
|
4274
|
+
}
|
|
4275
|
+
};
|
|
4276
|
+
pump() {
|
|
4277
|
+
while (!this.blocked && this.ring && this.ring.length > 0) this.write(this.ring.read());
|
|
4278
|
+
if (this.ring?.length === 0) this.closeSpool();
|
|
4279
|
+
}
|
|
4280
|
+
finishIfDrained() {
|
|
4281
|
+
if (this.ending && !this.ring?.length && !this.socket.writableEnded) this.socket.end(() => this.socket.destroy());
|
|
4282
|
+
}
|
|
4283
|
+
releaseObserver() {
|
|
4284
|
+
if (this.reserved) {
|
|
4285
|
+
this.reserved = false;
|
|
4286
|
+
this.budget.releaseObserver();
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
releaseIfIdle() {
|
|
4290
|
+
if (this.pendingWrites === 0 && !this.blocked && !this.ring?.length) this.releaseObserver();
|
|
4291
|
+
}
|
|
4292
|
+
closeSpool() {
|
|
4293
|
+
const ring = this.ring;
|
|
4294
|
+
this.ring = void 0;
|
|
4295
|
+
try {
|
|
4296
|
+
ring?.close();
|
|
4297
|
+
} catch (error) {
|
|
4298
|
+
this.socket.destroy(error instanceof Error ? error : new Error(String(error)));
|
|
4299
|
+
}
|
|
4300
|
+
}
|
|
4301
|
+
fail(error) {
|
|
4302
|
+
this.disposed = true;
|
|
4303
|
+
this.socket.destroy(error instanceof Error ? error : new Error(String(error)));
|
|
4304
|
+
this.closeSpool();
|
|
4305
|
+
}
|
|
4306
|
+
};
|
|
4307
|
+
//#endregion
|
|
4308
|
+
//#region src/session/queue/ipc-server.ts
|
|
4309
|
+
const QUEUE_SOCKET_DRAIN_TIMEOUT_MS = 1e3;
|
|
4310
|
+
function makeQueueOwnerError(requestId, message, detailCode, options = {}) {
|
|
4311
|
+
return {
|
|
4312
|
+
type: "error",
|
|
4313
|
+
requestId,
|
|
4314
|
+
ownerGeneration: void 0,
|
|
4315
|
+
code: "RUNTIME",
|
|
4316
|
+
detailCode,
|
|
4317
|
+
origin: "queue",
|
|
4318
|
+
retryable: options.retryable,
|
|
4319
|
+
message
|
|
4320
|
+
};
|
|
4321
|
+
}
|
|
4322
|
+
function makeQueueOwnerErrorFromUnknown(requestId, error, detailCode, options = {}) {
|
|
4323
|
+
const normalized = normalizeOutputError(error, {
|
|
4324
|
+
defaultCode: "RUNTIME",
|
|
4325
|
+
origin: "queue",
|
|
4326
|
+
detailCode,
|
|
4327
|
+
retryable: options.retryable
|
|
4328
|
+
});
|
|
4329
|
+
return {
|
|
4330
|
+
type: "error",
|
|
4331
|
+
requestId,
|
|
4332
|
+
code: normalized.code,
|
|
4333
|
+
detailCode: normalized.detailCode,
|
|
4334
|
+
origin: normalized.origin,
|
|
4335
|
+
message: normalized.message,
|
|
4336
|
+
retryable: normalized.retryable,
|
|
4337
|
+
acp: normalized.acp
|
|
4338
|
+
};
|
|
4339
|
+
}
|
|
4340
|
+
var SessionQueueOwner = class SessionQueueOwner {
|
|
4341
|
+
server;
|
|
4342
|
+
controlHandlers;
|
|
4343
|
+
ownerGeneration;
|
|
4344
|
+
maxQueueDepth;
|
|
4345
|
+
maxRequestBytes;
|
|
4346
|
+
onQueueDepthChanged;
|
|
4347
|
+
pending = [];
|
|
4348
|
+
activeTask;
|
|
4349
|
+
waiters = [];
|
|
4350
|
+
sockets = /* @__PURE__ */ new Set();
|
|
4351
|
+
taskSockets = /* @__PURE__ */ new Set();
|
|
4352
|
+
drainingSockets = /* @__PURE__ */ new Set();
|
|
4353
|
+
outputBudget = new QueueOutputBudget();
|
|
4354
|
+
outputs = /* @__PURE__ */ new Map();
|
|
4355
|
+
closed = false;
|
|
4356
|
+
constructor(server, controlHandlers, lease, options) {
|
|
4357
|
+
this.server = server;
|
|
4358
|
+
this.controlHandlers = controlHandlers;
|
|
4359
|
+
this.ownerGeneration = lease.ownerGeneration;
|
|
4360
|
+
this.maxQueueDepth = Math.max(1, Math.round(options.maxQueueDepth));
|
|
4361
|
+
this.maxRequestBytes = queueRequestByteLimit(options.maxRequestBytes?.toString());
|
|
4362
|
+
this.onQueueDepthChanged = options.onQueueDepthChanged;
|
|
4363
|
+
}
|
|
4364
|
+
static async start(lease, controlHandlers, options = { maxQueueDepth: 16 }) {
|
|
4365
|
+
const ownerRef = { current: void 0 };
|
|
4366
|
+
const server = net.createServer((socket) => {
|
|
4367
|
+
ownerRef.current?.handleConnection(socket);
|
|
4368
|
+
});
|
|
4369
|
+
ownerRef.current = new SessionQueueOwner(server, controlHandlers, lease, options);
|
|
4370
|
+
await new Promise((resolve, reject) => {
|
|
4371
|
+
const onListening = () => {
|
|
4372
|
+
server.off("error", onError);
|
|
4373
|
+
resolve();
|
|
4374
|
+
};
|
|
4375
|
+
const onError = (error) => {
|
|
4376
|
+
server.off("listening", onListening);
|
|
4377
|
+
reject(error);
|
|
4378
|
+
};
|
|
4379
|
+
server.once("listening", onListening);
|
|
4380
|
+
server.once("error", onError);
|
|
4381
|
+
server.listen(lease.socketPath);
|
|
4382
|
+
});
|
|
4383
|
+
return ownerRef.current;
|
|
4384
|
+
}
|
|
4385
|
+
beginShutdown() {
|
|
4386
|
+
if (this.closed) return;
|
|
4387
|
+
this.closed = true;
|
|
4388
|
+
for (const waiter of this.waiters.splice(0)) waiter(void 0);
|
|
4389
|
+
for (const task of this.pending.splice(0)) {
|
|
4390
|
+
if (task.waitForCompletion) task.send(makeQueueOwnerError(task.requestId, "Queue owner shutting down before prompt execution", "QUEUE_OWNER_SHUTTING_DOWN", { retryable: true }));
|
|
4391
|
+
task.close();
|
|
4392
|
+
}
|
|
4393
|
+
for (const socket of this.sockets) if (!this.taskSockets.has(socket) && !this.drainingSockets.has(socket)) socket.destroy();
|
|
4394
|
+
this.emitQueueDepth();
|
|
4395
|
+
}
|
|
4396
|
+
async close() {
|
|
4397
|
+
this.beginShutdown();
|
|
4398
|
+
await new Promise((resolve) => {
|
|
4399
|
+
const forceCloseTimer = setTimeout(() => {
|
|
4400
|
+
for (const socket of this.sockets) socket.destroy();
|
|
4401
|
+
}, QUEUE_SOCKET_DRAIN_TIMEOUT_MS);
|
|
4402
|
+
forceCloseTimer.unref();
|
|
4403
|
+
this.server.close(() => {
|
|
4404
|
+
clearTimeout(forceCloseTimer);
|
|
4405
|
+
resolve();
|
|
4406
|
+
});
|
|
4407
|
+
});
|
|
4408
|
+
}
|
|
4409
|
+
async nextTask(timeoutMs) {
|
|
4410
|
+
if (this.pending.length > 0) {
|
|
4411
|
+
const task = this.pending.shift();
|
|
4412
|
+
this.emitQueueDepth();
|
|
4413
|
+
if (task) {
|
|
4414
|
+
this.activeTask = task;
|
|
4415
|
+
recordPerfDuration("queue.owner.wait_ms", Date.now() - task.enqueuedAt);
|
|
4416
|
+
}
|
|
4417
|
+
return task;
|
|
4418
|
+
}
|
|
4419
|
+
if (this.closed) return;
|
|
4420
|
+
return await new Promise((resolve) => {
|
|
4421
|
+
const timer = timeoutMs != null && setTimeout(() => {
|
|
4422
|
+
const index = this.waiters.indexOf(waiter);
|
|
4423
|
+
if (index >= 0) this.waiters.splice(index, 1);
|
|
4424
|
+
resolve(void 0);
|
|
4425
|
+
}, Math.max(0, timeoutMs));
|
|
4426
|
+
const waiter = (task) => {
|
|
4427
|
+
if (timer) clearTimeout(timer);
|
|
4428
|
+
resolve(task);
|
|
4429
|
+
};
|
|
4430
|
+
this.waiters.push(waiter);
|
|
4431
|
+
});
|
|
4432
|
+
}
|
|
4433
|
+
queueDepth() {
|
|
4434
|
+
return this.pending.length;
|
|
4435
|
+
}
|
|
4436
|
+
completeTask(task) {
|
|
4437
|
+
if (this.activeTask === task) this.activeTask = void 0;
|
|
4438
|
+
}
|
|
4439
|
+
async cancelPrompt(targetRequestId) {
|
|
4440
|
+
if (targetRequestId === void 0) return await this.controlHandlers.cancelPrompt();
|
|
4441
|
+
const index = this.pending.findIndex((task) => task.requestId === targetRequestId);
|
|
4442
|
+
if (index >= 0) {
|
|
4443
|
+
const [task] = this.pending.splice(index, 1);
|
|
4444
|
+
task.send(makeQueueOwnerError(task.requestId, "Prompt cancelled before execution", "QUEUE_REQUEST_CANCELLED", { retryable: false }));
|
|
4445
|
+
task.close();
|
|
4446
|
+
this.emitQueueDepth();
|
|
4447
|
+
return true;
|
|
4448
|
+
}
|
|
4449
|
+
return this.activeTask?.requestId === targetRequestId ? await this.controlHandlers.cancelPrompt() : false;
|
|
4450
|
+
}
|
|
4451
|
+
emitQueueDepth() {
|
|
4452
|
+
this.onQueueDepthChanged?.(this.pending.length);
|
|
4453
|
+
}
|
|
4454
|
+
enqueue(task) {
|
|
4455
|
+
if (this.closed) {
|
|
4456
|
+
task.send(makeQueueOwnerError(task.requestId, "Queue owner is shutting down", "QUEUE_OWNER_SHUTTING_DOWN", { retryable: true }));
|
|
4457
|
+
task.close();
|
|
4458
|
+
return false;
|
|
4459
|
+
}
|
|
4460
|
+
if (this.activeTask?.requestId === task.requestId || this.pending.some((queued) => queued.requestId === task.requestId)) {
|
|
4461
|
+
task.send(makeQueueOwnerError(task.requestId, "Request is already queued or active", "QUEUE_REQUEST_DUPLICATE", { retryable: false }));
|
|
4462
|
+
task.close();
|
|
4463
|
+
return false;
|
|
4464
|
+
}
|
|
4465
|
+
const waiter = this.waiters.shift();
|
|
4466
|
+
if (waiter) {
|
|
4467
|
+
this.activeTask = task;
|
|
4468
|
+
waiter(task);
|
|
4469
|
+
return true;
|
|
4470
|
+
}
|
|
4471
|
+
if (this.pending.length >= this.maxQueueDepth) {
|
|
4472
|
+
task.send({
|
|
4473
|
+
...makeQueueOwnerError(task.requestId, `Queue owner is overloaded (${this.pending.length}/${this.maxQueueDepth} queued)`, "QUEUE_OWNER_OVERLOADED", { retryable: true }),
|
|
4474
|
+
ownerGeneration: this.ownerGeneration
|
|
4475
|
+
});
|
|
4476
|
+
task.close();
|
|
4477
|
+
return false;
|
|
4478
|
+
}
|
|
4479
|
+
this.pending.push(task);
|
|
4480
|
+
this.emitQueueDepth();
|
|
4481
|
+
return true;
|
|
4482
|
+
}
|
|
4483
|
+
handleControlRequest(options) {
|
|
4484
|
+
this.taskSockets.add(options.socket);
|
|
4485
|
+
this.writeQueueMessage(options.socket, {
|
|
4486
|
+
type: "accepted",
|
|
4487
|
+
requestId: options.requestId,
|
|
4488
|
+
ownerGeneration: this.ownerGeneration
|
|
4489
|
+
});
|
|
4490
|
+
options.run().then((message) => {
|
|
4491
|
+
this.writeQueueMessage(options.socket, {
|
|
4492
|
+
...message,
|
|
4493
|
+
ownerGeneration: this.ownerGeneration
|
|
4494
|
+
});
|
|
4495
|
+
}).catch((error) => {
|
|
4496
|
+
this.writeQueueMessage(options.socket, {
|
|
4497
|
+
...makeQueueOwnerErrorFromUnknown(options.requestId, error, "QUEUE_CONTROL_REQUEST_FAILED"),
|
|
4498
|
+
ownerGeneration: this.ownerGeneration
|
|
4499
|
+
});
|
|
4500
|
+
}).finally(() => {
|
|
4501
|
+
this.endSocket(options.socket);
|
|
4502
|
+
});
|
|
4503
|
+
}
|
|
4504
|
+
writeQueueMessage(socket, message) {
|
|
4505
|
+
this.outputs.get(socket)?.send(message);
|
|
4506
|
+
}
|
|
4507
|
+
endSocket(socket) {
|
|
4508
|
+
if (socket.destroyed || this.drainingSockets.has(socket)) return;
|
|
4509
|
+
this.taskSockets.delete(socket);
|
|
4510
|
+
this.drainingSockets.add(socket);
|
|
4511
|
+
this.outputs.get(socket)?.end();
|
|
4512
|
+
}
|
|
4513
|
+
failRequest(socket, requestId, message, detailCode) {
|
|
4514
|
+
this.writeQueueMessage(socket, {
|
|
4515
|
+
...makeQueueOwnerError(requestId, message, detailCode, { retryable: false }),
|
|
4516
|
+
ownerGeneration: this.ownerGeneration
|
|
4517
|
+
});
|
|
4518
|
+
this.endSocket(socket);
|
|
4519
|
+
}
|
|
4520
|
+
parseRequestLine(socket, line) {
|
|
4521
|
+
let parsed;
|
|
4522
|
+
try {
|
|
4523
|
+
parsed = JSON.parse(line);
|
|
4524
|
+
} catch {
|
|
4525
|
+
this.failRequest(socket, "unknown", "Invalid queue request payload", "QUEUE_REQUEST_PAYLOAD_INVALID_JSON");
|
|
4526
|
+
return;
|
|
4527
|
+
}
|
|
4528
|
+
const request = parseQueueRequest(parsed);
|
|
4529
|
+
if (!request) this.failRequest(socket, "unknown", "Invalid queue request", "QUEUE_REQUEST_INVALID");
|
|
4530
|
+
return request ?? void 0;
|
|
4531
|
+
}
|
|
4532
|
+
rejectStaleOwnerGeneration(socket, request) {
|
|
4533
|
+
if (request.ownerGeneration === void 0 || this.ownerGeneration === void 0 || request.ownerGeneration === this.ownerGeneration) return false;
|
|
4534
|
+
this.failRequest(socket, request.requestId, "Queue request targeted a stale queue owner generation", "QUEUE_OWNER_GENERATION_MISMATCH");
|
|
4535
|
+
return true;
|
|
4536
|
+
}
|
|
4537
|
+
rejectClosedOwner(socket, request) {
|
|
4538
|
+
if (!this.closed) return false;
|
|
4539
|
+
this.writeQueueMessage(socket, {
|
|
4540
|
+
...makeQueueOwnerError(request.requestId, "Queue owner is shutting down", "QUEUE_OWNER_CLOSED", { retryable: true }),
|
|
4541
|
+
ownerGeneration: this.ownerGeneration
|
|
4542
|
+
});
|
|
4543
|
+
this.endSocket(socket);
|
|
4544
|
+
return true;
|
|
4545
|
+
}
|
|
4546
|
+
handleControlQueueRequest(socket, request) {
|
|
4547
|
+
if (request.type === "cancel_prompt") {
|
|
4548
|
+
this.handleControlRequest({
|
|
4549
|
+
socket,
|
|
4550
|
+
requestId: request.requestId,
|
|
4551
|
+
run: async () => ({
|
|
4552
|
+
type: "cancel_result",
|
|
4553
|
+
requestId: request.requestId,
|
|
4554
|
+
cancelled: await this.cancelPrompt(request.targetRequestId)
|
|
4555
|
+
})
|
|
4556
|
+
});
|
|
4557
|
+
return true;
|
|
4558
|
+
}
|
|
4559
|
+
if (request.type === "close_session") {
|
|
4560
|
+
this.handleControlRequest({
|
|
4561
|
+
socket,
|
|
4562
|
+
requestId: request.requestId,
|
|
4563
|
+
run: async () => ({
|
|
4564
|
+
type: "close_session_result",
|
|
4565
|
+
requestId: request.requestId,
|
|
4566
|
+
closed: await this.controlHandlers.closeSession(request.timeoutMs)
|
|
4567
|
+
})
|
|
4568
|
+
});
|
|
4569
|
+
return true;
|
|
4570
|
+
}
|
|
4571
|
+
return this.handleSessionControlQueueRequest(socket, request);
|
|
4572
|
+
}
|
|
4573
|
+
handleSessionControlQueueRequest(socket, request) {
|
|
4574
|
+
if (request.type === "set_mode") {
|
|
4575
|
+
this.handleControlRequest({
|
|
4576
|
+
socket,
|
|
4577
|
+
requestId: request.requestId,
|
|
4578
|
+
run: async () => {
|
|
4579
|
+
await this.controlHandlers.setSessionMode(request.modeId, request.timeoutMs);
|
|
4580
|
+
return {
|
|
4581
|
+
type: "set_mode_result",
|
|
4582
|
+
requestId: request.requestId,
|
|
4583
|
+
modeId: request.modeId
|
|
4584
|
+
};
|
|
4585
|
+
}
|
|
4586
|
+
});
|
|
4587
|
+
return true;
|
|
4588
|
+
}
|
|
4589
|
+
if (request.type === "set_model") {
|
|
4590
|
+
this.handleControlRequest({
|
|
4591
|
+
socket,
|
|
4592
|
+
requestId: request.requestId,
|
|
4593
|
+
run: async () => {
|
|
4594
|
+
const response = await this.controlHandlers.setSessionModel(request.modelId, request.timeoutMs);
|
|
4595
|
+
return {
|
|
4596
|
+
type: "set_model_result",
|
|
4597
|
+
requestId: request.requestId,
|
|
4598
|
+
modelId: request.modelId,
|
|
4599
|
+
response
|
|
4600
|
+
};
|
|
4601
|
+
}
|
|
4602
|
+
});
|
|
4603
|
+
return true;
|
|
4604
|
+
}
|
|
4605
|
+
if (request.type === "set_config_option") {
|
|
4606
|
+
this.handleControlRequest({
|
|
4607
|
+
socket,
|
|
4608
|
+
requestId: request.requestId,
|
|
4609
|
+
run: async () => ({
|
|
4610
|
+
type: "set_config_option_result",
|
|
4611
|
+
requestId: request.requestId,
|
|
4612
|
+
response: await this.controlHandlers.setSessionConfigOption(request.configId, request.value, request.timeoutMs)
|
|
4613
|
+
})
|
|
4614
|
+
});
|
|
4615
|
+
return true;
|
|
4616
|
+
}
|
|
4617
|
+
return false;
|
|
4618
|
+
}
|
|
4619
|
+
enqueuePromptRequest(socket, request) {
|
|
4620
|
+
this.taskSockets.add(socket);
|
|
4621
|
+
const task = {
|
|
4622
|
+
requestId: request.requestId,
|
|
4623
|
+
message: request.message,
|
|
4624
|
+
prompt: request.prompt ?? textPrompt(request.message),
|
|
4625
|
+
permissionMode: request.permissionMode,
|
|
4626
|
+
resumePolicy: request.resumePolicy,
|
|
4627
|
+
nonInteractivePermissions: request.nonInteractivePermissions,
|
|
4628
|
+
permissionPolicy: request.permissionPolicy,
|
|
4629
|
+
timeoutMs: request.timeoutMs,
|
|
4630
|
+
suppressSdkConsoleErrors: request.suppressSdkConsoleErrors,
|
|
4631
|
+
promptRetries: request.promptRetries,
|
|
4632
|
+
sessionOptions: request.sessionOptions,
|
|
4633
|
+
waitForCompletion: request.waitForCompletion,
|
|
4634
|
+
reportPromptStarted: request.reportPromptStarted,
|
|
4635
|
+
enqueuedAt: Date.now(),
|
|
4636
|
+
send: (message) => {
|
|
4637
|
+
this.writeQueueMessage(socket, {
|
|
4638
|
+
...message,
|
|
4639
|
+
ownerGeneration: this.ownerGeneration
|
|
4640
|
+
});
|
|
4641
|
+
},
|
|
4642
|
+
close: () => {
|
|
4643
|
+
this.endSocket(socket);
|
|
4644
|
+
}
|
|
4645
|
+
};
|
|
4646
|
+
if (!this.enqueue(task)) return;
|
|
4647
|
+
this.writeQueueMessage(socket, {
|
|
4648
|
+
type: "accepted",
|
|
4649
|
+
requestId: request.requestId,
|
|
4650
|
+
ownerGeneration: this.ownerGeneration
|
|
4651
|
+
});
|
|
4652
|
+
if (!request.waitForCompletion) task.close();
|
|
4653
|
+
}
|
|
4654
|
+
handleConnection(socket) {
|
|
4655
|
+
this.sockets.add(socket);
|
|
4656
|
+
this.outputs.set(socket, new QueueSocketOutput(socket, this.outputBudget));
|
|
4657
|
+
socket.setEncoding("utf8");
|
|
4658
|
+
socket.on("timeout", () => socket.destroy());
|
|
4659
|
+
socket.once("close", () => {
|
|
4660
|
+
this.outputs.delete(socket);
|
|
4661
|
+
this.sockets.delete(socket);
|
|
4662
|
+
this.taskSockets.delete(socket);
|
|
4663
|
+
this.drainingSockets.delete(socket);
|
|
4664
|
+
});
|
|
4665
|
+
let buffer = "";
|
|
4666
|
+
let handled = false;
|
|
4667
|
+
const processLine = (line) => {
|
|
4668
|
+
if (handled) return;
|
|
4669
|
+
handled = true;
|
|
4670
|
+
const request = this.parseRequestLine(socket, line);
|
|
4671
|
+
if (!request || this.rejectClosedOwner(socket, request) || this.rejectStaleOwnerGeneration(socket, request)) return;
|
|
4672
|
+
if (this.handleControlQueueRequest(socket, request)) return;
|
|
4673
|
+
if (request.type !== "submit_prompt") {
|
|
4674
|
+
this.failRequest(socket, request.requestId, "Invalid queue request", "QUEUE_REQUEST_INVALID");
|
|
4675
|
+
return;
|
|
4676
|
+
}
|
|
4677
|
+
this.enqueuePromptRequest(socket, request);
|
|
4678
|
+
};
|
|
4679
|
+
socket.on("data", (chunk) => {
|
|
4680
|
+
buffer += chunk;
|
|
4681
|
+
let index = buffer.indexOf("\n");
|
|
4682
|
+
while (index >= 0) {
|
|
4683
|
+
const rawLine = buffer.slice(0, index);
|
|
4684
|
+
if (this.rejectOversizedRequest(socket, rawLine)) return;
|
|
4685
|
+
const line = rawLine.trim();
|
|
4686
|
+
buffer = buffer.slice(index + 1);
|
|
4687
|
+
if (line.length > 0) processLine(line);
|
|
4688
|
+
index = buffer.indexOf("\n");
|
|
4689
|
+
}
|
|
4690
|
+
this.rejectOversizedRequest(socket, buffer);
|
|
4691
|
+
});
|
|
4692
|
+
socket.on("error", () => {});
|
|
4693
|
+
}
|
|
4694
|
+
rejectOversizedRequest(socket, line) {
|
|
4695
|
+
if (!queueRequestExceedsLimit(line, this.maxRequestBytes)) return false;
|
|
4696
|
+
socket.destroy();
|
|
4697
|
+
return true;
|
|
4698
|
+
}
|
|
4699
|
+
};
|
|
4700
|
+
//#endregion
|
|
3873
4701
|
//#region src/session/queue/ipc.ts
|
|
3874
4702
|
const MAX_MESSAGE_BUFFER_SIZE = 10485760;
|
|
3875
4703
|
function assertOwnerGeneration(owner, message) {
|
|
@@ -4340,6 +5168,6 @@ async function trySetConfigOptionOnRunningOwner(sessionId, configId, value, time
|
|
|
4340
5168
|
});
|
|
4341
5169
|
}
|
|
4342
5170
|
//#endregion
|
|
4343
|
-
export {
|
|
5171
|
+
export { resetPerfMetrics as $, findSession as A, PERMISSION_POLICY_ACTIONS as At, assertPersistedKeyPolicy as B, PermissionDeniedError as Bt, mergePromptSourceWithText as C, extractAcpError as Ct, DEFAULT_HISTORY_LIMIT as D, NON_INTERACTIVE_PERMISSION_POLICIES as Dt, textPrompt as E, EXIT_CODES as Et, normalizeName as F, AgentStartupError as Ft, SESSION_JOURNAL_SCHEMA as G, SessionModelReplayError as Gt, serializeSessionRecordForDisk as H, QueueConnectionError as Ht, pruneSessions as I, AuthPolicyError as It, watchSession as J, UnsupportedPromptContentError as Jt, SessionJournalReader as K, SessionNotFoundError as Kt, readSessionRecord as L, ClaudeAcpSessionCreateTimeoutError as Lt, isoNow as M, AcpxOperationalError as Mt, listSessions as N, AgentDisconnectedError as Nt, absolutePath as O, OUTPUT_FORMATS as Ot, listSessionsForAgent as P, AgentSpawnError as Pt, measurePerf as Q, resolveSessionRecord as R, CopilotAcpUnsupportedError as Rt, getUnsupportedPromptContentMessage as S, normalizeOutputError as St, promptToDisplayText as T, AUTH_POLICIES as Tt, extractAgentSessionId as U, SessionConfigOptionReplayError as Ut, parseSessionRecord as V, PermissionPromptUnavailableError as Vt, normalizeAgentSessionId as W, SessionModeReplayError as Wt, getPerfMetricsSnapshot as X, formatPerfMetric as Y, incrementPerfCounter as Z, createLockOwner as _, isProcessAlive as _t, trySetModelOnRunningOwner as a, isSessionUpdateNotification as at, observeProcessIncarnation as b, isAcpQueryClosedBeforeResponseError as bt, probeQueueOwnerHealth as c, parsePromptStopReason as ct, releaseQueueOwnerLease as d, sessionBaseDir as dt, setPerfGauge as et, terminateProcess as f, sessionEventActivePath as ft, QueueLeaseGuardSettlementError as g, writePrivateJsonFile as gt, waitMs as h, writePrivateFile as ht, trySetModeOnRunningOwner as i, isAcpMessageObject as it, findSessionByDirectoryWalk as j, SESSION_RECORD_SCHEMA as jt, findGitRepositoryRoot as k, PERMISSION_MODES as kt, readQueueOwnerRecord as l, DEFAULT_EVENT_SEGMENT_MAX_BYTES as lt, tryAcquireQueueOwnerLease as m, sessionEventSegmentPath as mt, tryCloseSessionOnRunningOwner as n, extractSessionUpdateNotification as nt, trySubmitToRunningOwner as o, parseJsonRpcErrorMessage as ot, terminateQueueOwnerForSession as p, sessionEventLockPath as pt, SessionWatchError as q, SessionResumeRequiredError as qt, trySetConfigOptionOnRunningOwner as r, isAcpJsonRpcMessage as rt, SessionQueueOwner as s, parsePermissionNotice as st, tryCancelOnRunningOwner as t, startPerfTimer as tt, refreshQueueOwnerLease as u, defaultSessionEventLog as ut, lockOwnerPid as v, exitCodeForOutputErrorCode as vt, parsePromptSource as w, isAcpResourceNotFoundError as wt, PromptInputValidationError as x, isRetryablePromptError as xt, ProcessDescendants as y, formatErrorMessage as yt, writeSessionRecord as z, GeminiAcpStartupTimeoutError as zt };
|
|
4344
5172
|
|
|
4345
|
-
//# sourceMappingURL=ipc-
|
|
5173
|
+
//# sourceMappingURL=ipc-D0ZMQ0q9.js.map
|