acpx 0.3.0 → 0.4.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 +67 -16
- package/dist/{acp-jsonrpc-BNHXq7qK.js → acp-jsonrpc-C7pPk9Tw.js} +1 -1
- package/dist/{acp-jsonrpc-BNHXq7qK.js.map → acp-jsonrpc-C7pPk9Tw.js.map} +1 -1
- package/dist/cli-5s-E-Y99.js +176 -0
- package/dist/cli-5s-E-Y99.js.map +1 -0
- package/dist/cli.d.ts +1 -118
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +235 -331
- package/dist/cli.js.map +1 -1
- package/dist/flags-BkWInxAq.js +194 -0
- package/dist/flags-BkWInxAq.js.map +1 -0
- package/dist/flows-DnIYoHI1.js +1551 -0
- package/dist/flows-DnIYoHI1.js.map +1 -0
- package/dist/flows.d.ts +292 -0
- package/dist/flows.d.ts.map +1 -0
- package/dist/flows.js +2 -0
- package/dist/{output-BmkPP7qE.js → output-C58ukIo3.js} +137 -14
- package/dist/output-C58ukIo3.js.map +1 -0
- package/dist/{output-render-DEAaMxg8.js → output-render-C7w9NZ2H.js} +10 -10
- package/dist/output-render-C7w9NZ2H.js.map +1 -0
- package/dist/{queue-ipc-EQLpBMKv.js → queue-ipc-CgWf63GN.js} +258 -95
- package/dist/queue-ipc-CgWf63GN.js.map +1 -0
- package/dist/{session-C2Q8ktsN.js → session-BtpTC2pM.js} +687 -138
- package/dist/session-BtpTC2pM.js.map +1 -0
- package/dist/types-CeRKmEQ1.d.ts +137 -0
- package/dist/types-CeRKmEQ1.d.ts.map +1 -0
- package/package.json +36 -16
- package/skills/acpx/SKILL.md +23 -6
- package/dist/output-BmkPP7qE.js.map +0 -1
- package/dist/output-render-DEAaMxg8.js.map +0 -1
- package/dist/queue-ipc-EQLpBMKv.js.map +0 -1
- package/dist/runtime-session-id-C544sPPL.js +0 -31
- package/dist/runtime-session-id-C544sPPL.js.map +0 -1
- package/dist/session-C2Q8ktsN.js.map +0 -1
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
|
|
2
|
-
import {
|
|
3
|
-
import { n as isSessionUpdateNotification, t as isAcpJsonRpcMessage } from "./acp-jsonrpc-
|
|
4
|
-
import { n as normalizeRuntimeSessionId, t as extractRuntimeSessionId } from "./runtime-session-id-C544sPPL.js";
|
|
2
|
+
import { $ as extractAcpError, B as AgentSpawnError, C as formatErrorMessage, E as normalizeOutputError, G as PermissionDeniedError, H as ClaudeAcpSessionCreateTimeoutError, J as SessionModeReplayError, K as PermissionPromptUnavailableError, L as promptToDisplayText, M as extractRuntimeSessionId, N as normalizeRuntimeSessionId, Q as SessionResumeRequiredError, R as textPrompt, T as isRetryablePromptError, U as CopilotAcpUnsupportedError, V as AuthPolicyError, W as GeminiAcpStartupTimeoutError, X as SessionNotFoundError, Y as SessionModelReplayError, Z as SessionResolutionError, _ as incrementPerfCounter, a as trySubmitToRunningOwner, b as setPerfGauge, c as isProcessAlive, d as terminateProcess, et as isAcpResourceNotFoundError, f as terminateQueueOwnerForSession, g as getPerfMetricsSnapshot, h as formatPerfMetric, i as trySetModelOnRunningOwner, j as SESSION_RECORD_SCHEMA, l as refreshQueueOwnerLease, m as waitMs$1, n as trySetConfigOptionOnRunningOwner, o as SessionQueueOwner, p as tryAcquireQueueOwnerLease, q as QueueConnectionError, r as trySetModeOnRunningOwner, t as tryCancelOnRunningOwner, u as releaseQueueOwnerLease, v as measurePerf, w as isAcpQueryClosedBeforeResponseError, x as startPerfTimer, y as resetPerfMetrics, z as AgentDisconnectedError } from "./queue-ipc-CgWf63GN.js";
|
|
3
|
+
import { n as isSessionUpdateNotification, t as isAcpJsonRpcMessage } from "./acp-jsonrpc-C7pPk9Tw.js";
|
|
5
4
|
import fs, { realpathSync, statSync } from "node:fs";
|
|
6
5
|
import fs$1 from "node:fs/promises";
|
|
7
6
|
import path from "node:path";
|
|
7
|
+
import os from "node:os";
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
9
|
import { Readable, Writable } from "node:stream";
|
|
10
|
-
import { ClientSideConnection, PROTOCOL_VERSION
|
|
10
|
+
import { ClientSideConnection, PROTOCOL_VERSION } from "@agentclientprotocol/sdk";
|
|
11
11
|
import readline from "node:readline/promises";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
|
-
import os from "node:os";
|
|
14
13
|
//#region src/permission-prompt.ts
|
|
15
14
|
async function promptForPermission(options) {
|
|
16
15
|
if (!process.stdin.isTTY || !process.stderr.isTTY) return false;
|
|
@@ -159,8 +158,7 @@ var FileSystemHandlers = class {
|
|
|
159
158
|
sliceContent(content, line, limit) {
|
|
160
159
|
if (line == null && limit == null) return content;
|
|
161
160
|
const lines = content.split("\n");
|
|
162
|
-
const
|
|
163
|
-
const startIndex = Math.max(0, startLine - 1);
|
|
161
|
+
const startIndex = Math.max(0, (line == null ? 1 : Math.max(1, Math.trunc(line))) - 1);
|
|
164
162
|
const maxLines = limit == null ? void 0 : Math.max(0, Math.trunc(limit));
|
|
165
163
|
if (maxLines === 0) return "";
|
|
166
164
|
const endIndex = maxLines == null ? lines.length : Math.min(lines.length, startIndex + maxLines);
|
|
@@ -176,6 +174,11 @@ var FileSystemHandlers = class {
|
|
|
176
174
|
};
|
|
177
175
|
//#endregion
|
|
178
176
|
//#region src/permissions.ts
|
|
177
|
+
const PERMISSION_MODE_RANK = {
|
|
178
|
+
"deny-all": 0,
|
|
179
|
+
"approve-reads": 1,
|
|
180
|
+
"approve-all": 2
|
|
181
|
+
};
|
|
179
182
|
function selected(optionId) {
|
|
180
183
|
return { outcome: {
|
|
181
184
|
outcome: "selected",
|
|
@@ -216,6 +219,9 @@ async function promptForToolPermission(params) {
|
|
|
216
219
|
function canPromptForPermission$1() {
|
|
217
220
|
return Boolean(process.stdin.isTTY && process.stderr.isTTY);
|
|
218
221
|
}
|
|
222
|
+
function permissionModeSatisfies(actual, required) {
|
|
223
|
+
return PERMISSION_MODE_RANK[actual] >= PERMISSION_MODE_RANK[required];
|
|
224
|
+
}
|
|
219
225
|
async function resolvePermissionRequest(params, mode, nonInteractivePolicy = "deny") {
|
|
220
226
|
const options = params.options ?? [];
|
|
221
227
|
if (options.length === 0) return cancelled();
|
|
@@ -284,24 +290,64 @@ async function withInterrupt(run, onInterrupt) {
|
|
|
284
290
|
settled = true;
|
|
285
291
|
process.off("SIGINT", onSigint);
|
|
286
292
|
process.off("SIGTERM", onSigterm);
|
|
293
|
+
process.off("SIGHUP", onSighup);
|
|
287
294
|
cb();
|
|
288
295
|
};
|
|
289
|
-
const
|
|
296
|
+
const rejectInterrupted = () => {
|
|
290
297
|
onInterrupt().finally(() => {
|
|
291
298
|
finish(() => reject(new InterruptedError()));
|
|
292
299
|
});
|
|
293
300
|
};
|
|
301
|
+
const onSigint = () => {
|
|
302
|
+
rejectInterrupted();
|
|
303
|
+
};
|
|
294
304
|
const onSigterm = () => {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
305
|
+
rejectInterrupted();
|
|
306
|
+
};
|
|
307
|
+
const onSighup = () => {
|
|
308
|
+
rejectInterrupted();
|
|
298
309
|
};
|
|
299
310
|
process.once("SIGINT", onSigint);
|
|
300
311
|
process.once("SIGTERM", onSigterm);
|
|
312
|
+
process.once("SIGHUP", onSighup);
|
|
301
313
|
run().then((result) => finish(() => resolve(result)), (error) => finish(() => reject(error)));
|
|
302
314
|
});
|
|
303
315
|
}
|
|
304
316
|
//#endregion
|
|
317
|
+
//#region src/spawn-command-options.ts
|
|
318
|
+
function readWindowsEnvValue(env, key) {
|
|
319
|
+
const matchedKey = Object.keys(env).find((entry) => entry.toUpperCase() === key);
|
|
320
|
+
return matchedKey ? env[matchedKey] : void 0;
|
|
321
|
+
}
|
|
322
|
+
function resolveWindowsCommand(command, env = process.env) {
|
|
323
|
+
const extensions = (readWindowsEnvValue(env, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((value) => value.trim().toLowerCase()).filter((value) => value.length > 0);
|
|
324
|
+
const candidates = path.extname(command).length > 0 ? [command] : extensions.map((extension) => `${command}${extension}`);
|
|
325
|
+
if (command.includes("/") || command.includes("\\") || path.isAbsolute(command)) return candidates.find((candidate) => fs.existsSync(candidate));
|
|
326
|
+
const pathValue = readWindowsEnvValue(env, "PATH");
|
|
327
|
+
if (!pathValue) return;
|
|
328
|
+
for (const directory of pathValue.split(";")) {
|
|
329
|
+
const trimmedDirectory = directory.trim();
|
|
330
|
+
if (trimmedDirectory.length === 0) continue;
|
|
331
|
+
for (const candidate of candidates) {
|
|
332
|
+
const resolved = path.join(trimmedDirectory, candidate);
|
|
333
|
+
if (fs.existsSync(resolved)) return resolved;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function shouldUseWindowsBatchShell(command, platform = process.platform, env = process.env) {
|
|
338
|
+
if (platform !== "win32") return false;
|
|
339
|
+
const resolvedCommand = resolveWindowsCommand(command, env) ?? command;
|
|
340
|
+
const ext = path.extname(resolvedCommand).toLowerCase();
|
|
341
|
+
return ext === ".cmd" || ext === ".bat";
|
|
342
|
+
}
|
|
343
|
+
function buildSpawnCommandOptions(command, options, platform = process.platform, env = process.env) {
|
|
344
|
+
if (!shouldUseWindowsBatchShell(command, platform, env)) return options;
|
|
345
|
+
return {
|
|
346
|
+
...options,
|
|
347
|
+
shell: true
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
//#endregion
|
|
305
351
|
//#region src/terminal.ts
|
|
306
352
|
const DEFAULT_TERMINAL_OUTPUT_LIMIT_BYTES = 64 * 1024;
|
|
307
353
|
const DEFAULT_KILL_GRACE_MS = 1500;
|
|
@@ -318,17 +364,18 @@ function toEnvObject(env) {
|
|
|
318
364
|
for (const entry of env) merged[entry.name] = entry.value;
|
|
319
365
|
return merged;
|
|
320
366
|
}
|
|
321
|
-
function buildTerminalSpawnOptions(cwd, env) {
|
|
322
|
-
|
|
367
|
+
function buildTerminalSpawnOptions(command, cwd, env, platform = process.platform) {
|
|
368
|
+
const resolvedEnv = toEnvObject(env);
|
|
369
|
+
return buildSpawnCommandOptions(command, {
|
|
323
370
|
cwd,
|
|
324
|
-
env:
|
|
371
|
+
env: resolvedEnv,
|
|
325
372
|
stdio: [
|
|
326
373
|
"ignore",
|
|
327
374
|
"pipe",
|
|
328
375
|
"pipe"
|
|
329
376
|
],
|
|
330
377
|
windowsHide: true
|
|
331
|
-
};
|
|
378
|
+
}, platform, resolvedEnv ?? process.env);
|
|
332
379
|
}
|
|
333
380
|
function trimToUtf8Boundary(buffer, limit) {
|
|
334
381
|
if (limit <= 0) return Buffer.alloc(0);
|
|
@@ -397,7 +444,7 @@ var TerminalManager = class {
|
|
|
397
444
|
try {
|
|
398
445
|
if (!await this.isExecuteApproved(commandLine)) throw new PermissionDeniedError("Permission denied for terminal/create");
|
|
399
446
|
const outputByteLimit = Math.max(0, Math.round(params.outputByteLimit ?? DEFAULT_TERMINAL_OUTPUT_LIMIT_BYTES));
|
|
400
|
-
const proc = spawn(params.command, params.args ?? [], buildTerminalSpawnOptions(params.cwd ?? this.cwd, params.env));
|
|
447
|
+
const proc = spawn(params.command, params.args ?? [], buildTerminalSpawnOptions(params.command, params.cwd ?? this.cwd, params.env));
|
|
401
448
|
await waitForSpawn$1(proc);
|
|
402
449
|
let resolveExit = () => {};
|
|
403
450
|
const exitPromise = new Promise((resolve) => {
|
|
@@ -602,7 +649,8 @@ var TerminalManager = class {
|
|
|
602
649
|
const REPLAY_IDLE_MS = 80;
|
|
603
650
|
const REPLAY_DRAIN_TIMEOUT_MS = 5e3;
|
|
604
651
|
const DRAIN_POLL_INTERVAL_MS = 20;
|
|
605
|
-
const
|
|
652
|
+
const DEFAULT_AGENT_CLOSE_AFTER_STDIN_END_MS = 100;
|
|
653
|
+
const QODER_AGENT_CLOSE_AFTER_STDIN_END_MS = 750;
|
|
606
654
|
const AGENT_CLOSE_TERM_GRACE_MS = 1500;
|
|
607
655
|
const AGENT_CLOSE_KILL_GRACE_MS = 1e3;
|
|
608
656
|
const GEMINI_ACP_STARTUP_TIMEOUT_MS = 15e3;
|
|
@@ -615,6 +663,7 @@ const GEMINI_ACP_FLAG_VERSION = [
|
|
|
615
663
|
];
|
|
616
664
|
const COPILOT_HELP_TIMEOUT_MS = 2e3;
|
|
617
665
|
const SESSION_CONTROL_UNSUPPORTED_ACP_CODES = new Set([-32601, -32602]);
|
|
666
|
+
const QODER_BENIGN_STDOUT_LINES = new Set(["Received interrupt signal. Cleaning up resources...", "Cleanup completed. Exiting..."]);
|
|
618
667
|
function shouldSuppressSdkConsoleError(args) {
|
|
619
668
|
if (args.length === 0) return false;
|
|
620
669
|
return typeof args[0] === "string" && args[0] === "Error handling request";
|
|
@@ -723,6 +772,56 @@ function asAbsoluteCwd(cwd) {
|
|
|
723
772
|
function basenameToken(value) {
|
|
724
773
|
return path.basename(value).toLowerCase().replace(/\.(cmd|exe|bat)$/u, "");
|
|
725
774
|
}
|
|
775
|
+
function resolveAgentCloseAfterStdinEndMs(agentCommand) {
|
|
776
|
+
const { command } = splitCommandLine(agentCommand);
|
|
777
|
+
return basenameToken(command) === "qodercli" ? QODER_AGENT_CLOSE_AFTER_STDIN_END_MS : DEFAULT_AGENT_CLOSE_AFTER_STDIN_END_MS;
|
|
778
|
+
}
|
|
779
|
+
function shouldIgnoreNonJsonAgentOutputLine(agentCommand, trimmedLine) {
|
|
780
|
+
const { command } = splitCommandLine(agentCommand);
|
|
781
|
+
return basenameToken(command) === "qodercli" && QODER_BENIGN_STDOUT_LINES.has(trimmedLine);
|
|
782
|
+
}
|
|
783
|
+
function createNdJsonMessageStream(agentCommand, output, input) {
|
|
784
|
+
const textEncoder = new TextEncoder();
|
|
785
|
+
const textDecoder = new TextDecoder();
|
|
786
|
+
return {
|
|
787
|
+
readable: new ReadableStream({ async start(controller) {
|
|
788
|
+
let content = "";
|
|
789
|
+
const reader = input.getReader();
|
|
790
|
+
try {
|
|
791
|
+
while (true) {
|
|
792
|
+
const { value, done } = await reader.read();
|
|
793
|
+
if (done) break;
|
|
794
|
+
if (!value) continue;
|
|
795
|
+
content += textDecoder.decode(value, { stream: true });
|
|
796
|
+
const lines = content.split("\n");
|
|
797
|
+
content = lines.pop() || "";
|
|
798
|
+
for (const line of lines) {
|
|
799
|
+
const trimmedLine = line.trim();
|
|
800
|
+
if (!trimmedLine || shouldIgnoreNonJsonAgentOutputLine(agentCommand, trimmedLine)) continue;
|
|
801
|
+
try {
|
|
802
|
+
const message = JSON.parse(trimmedLine);
|
|
803
|
+
controller.enqueue(message);
|
|
804
|
+
} catch (err) {
|
|
805
|
+
console.error("Failed to parse JSON message:", trimmedLine, err);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
} finally {
|
|
810
|
+
reader.releaseLock();
|
|
811
|
+
controller.close();
|
|
812
|
+
}
|
|
813
|
+
} }),
|
|
814
|
+
writable: new WritableStream({ async write(message) {
|
|
815
|
+
const content = JSON.stringify(message) + "\n";
|
|
816
|
+
const writer = output.getWriter();
|
|
817
|
+
try {
|
|
818
|
+
await writer.write(textEncoder.encode(content));
|
|
819
|
+
} finally {
|
|
820
|
+
writer.releaseLock();
|
|
821
|
+
}
|
|
822
|
+
} })
|
|
823
|
+
};
|
|
824
|
+
}
|
|
726
825
|
function isGeminiAcpCommand(command, args) {
|
|
727
826
|
return basenameToken(command) === "gemini" && (args.includes("--acp") || args.includes("--experimental-acp"));
|
|
728
827
|
}
|
|
@@ -733,37 +832,32 @@ function isClaudeAcpCommand(command, args) {
|
|
|
733
832
|
function isCopilotAcpCommand(command, args) {
|
|
734
833
|
return basenameToken(command) === "copilot" && args.includes("--acp");
|
|
735
834
|
}
|
|
736
|
-
function
|
|
737
|
-
|
|
738
|
-
return matchedKey ? env[matchedKey] : void 0;
|
|
835
|
+
function isQoderAcpCommand(command, args) {
|
|
836
|
+
return basenameToken(command) === "qodercli" && args.includes("--acp");
|
|
739
837
|
}
|
|
740
|
-
function
|
|
741
|
-
|
|
742
|
-
const candidates = path.extname(command).length > 0 ? [command] : extensions.map((extension) => `${command}${extension}`);
|
|
743
|
-
if (command.includes("/") || command.includes("\\") || path.isAbsolute(command)) return candidates.find((candidate) => fs.existsSync(candidate));
|
|
744
|
-
const pathValue = readWindowsEnvValue(env, "PATH");
|
|
745
|
-
if (!pathValue) return;
|
|
746
|
-
for (const directory of pathValue.split(";")) {
|
|
747
|
-
const trimmedDirectory = directory.trim();
|
|
748
|
-
if (trimmedDirectory.length === 0) continue;
|
|
749
|
-
for (const candidate of candidates) {
|
|
750
|
-
const resolved = path.join(trimmedDirectory, candidate);
|
|
751
|
-
if (fs.existsSync(resolved)) return resolved;
|
|
752
|
-
}
|
|
753
|
-
}
|
|
838
|
+
function hasCommandFlag(args, flagName) {
|
|
839
|
+
return args.some((arg) => arg === flagName || arg.startsWith(`${flagName}=`));
|
|
754
840
|
}
|
|
755
|
-
function
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
841
|
+
function normalizeQoderAllowedToolName(tool) {
|
|
842
|
+
switch (tool.trim().toLowerCase()) {
|
|
843
|
+
case "bash":
|
|
844
|
+
case "glob":
|
|
845
|
+
case "grep":
|
|
846
|
+
case "ls":
|
|
847
|
+
case "read":
|
|
848
|
+
case "write": return tool.trim().toUpperCase();
|
|
849
|
+
default: return tool.trim();
|
|
850
|
+
}
|
|
760
851
|
}
|
|
761
|
-
function
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
852
|
+
function buildQoderAcpCommandArgs(initialArgs, options) {
|
|
853
|
+
const args = [...initialArgs];
|
|
854
|
+
const sessionOptions = options.sessionOptions;
|
|
855
|
+
if (typeof sessionOptions?.maxTurns === "number" && !hasCommandFlag(args, "--max-turns")) args.push(`--max-turns=${sessionOptions.maxTurns}`);
|
|
856
|
+
if (Array.isArray(sessionOptions?.allowedTools) && !hasCommandFlag(args, "--allowed-tools") && !hasCommandFlag(args, "--disallowed-tools")) {
|
|
857
|
+
const encodedTools = sessionOptions.allowedTools.map(normalizeQoderAllowedToolName).join(",");
|
|
858
|
+
args.push(`--allowed-tools=${encodedTools}`);
|
|
859
|
+
}
|
|
860
|
+
return args;
|
|
767
861
|
}
|
|
768
862
|
function resolveGeminiAcpStartupTimeoutMs() {
|
|
769
863
|
const raw = process.env.ACPX_GEMINI_ACP_STARTUP_TIMEOUT_MS;
|
|
@@ -904,7 +998,7 @@ async function buildGeminiAcpStartupTimeoutMessage(command) {
|
|
|
904
998
|
function buildClaudeAcpSessionCreateTimeoutMessage() {
|
|
905
999
|
return [
|
|
906
1000
|
"Claude ACP session creation timed out before session/new completed.",
|
|
907
|
-
"This matches the known persistent-session stall seen with some Claude Code and @
|
|
1001
|
+
"This matches the known persistent-session stall seen with some Claude Code and @agentclientprotocol/claude-agent-acp combinations.",
|
|
908
1002
|
"In harnessed or non-interactive runs, prefer --approve-all with nonInteractivePermissions=deny, upgrade Claude Code and the Claude ACP adapter, or use acpx claude exec as a one-shot fallback."
|
|
909
1003
|
].join(" ");
|
|
910
1004
|
}
|
|
@@ -922,7 +1016,7 @@ async function ensureCopilotAcpSupport(command) {
|
|
|
922
1016
|
function toEnvToken(value) {
|
|
923
1017
|
return value.trim().replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
|
|
924
1018
|
}
|
|
925
|
-
function
|
|
1019
|
+
function buildAuthEnvKeys(methodId) {
|
|
926
1020
|
const token = toEnvToken(methodId);
|
|
927
1021
|
const keys = new Set([methodId]);
|
|
928
1022
|
if (token) {
|
|
@@ -931,6 +1025,14 @@ function authEnvKeys(methodId) {
|
|
|
931
1025
|
}
|
|
932
1026
|
return [...keys];
|
|
933
1027
|
}
|
|
1028
|
+
const authEnvKeysCache = /* @__PURE__ */ new Map();
|
|
1029
|
+
function authEnvKeys(methodId) {
|
|
1030
|
+
const cached = authEnvKeysCache.get(methodId);
|
|
1031
|
+
if (cached) return cached;
|
|
1032
|
+
const keys = buildAuthEnvKeys(methodId);
|
|
1033
|
+
authEnvKeysCache.set(methodId, keys);
|
|
1034
|
+
return keys;
|
|
1035
|
+
}
|
|
934
1036
|
function readEnvCredential(methodId) {
|
|
935
1037
|
for (const key of authEnvKeys(methodId)) {
|
|
936
1038
|
const value = process.env[key];
|
|
@@ -1024,6 +1126,7 @@ var AcpClient = class {
|
|
|
1024
1126
|
lastAgentExit;
|
|
1025
1127
|
lastKnownPid;
|
|
1026
1128
|
promptPermissionFailures = /* @__PURE__ */ new Map();
|
|
1129
|
+
pendingConnectionRequests = /* @__PURE__ */ new Set();
|
|
1027
1130
|
constructor(options) {
|
|
1028
1131
|
this.options = {
|
|
1029
1132
|
...options,
|
|
@@ -1103,7 +1206,8 @@ var AcpClient = class {
|
|
|
1103
1206
|
if (this.connection && this.agent && isChildProcessRunning(this.agent)) return;
|
|
1104
1207
|
if (this.connection || this.agent) await this.close();
|
|
1105
1208
|
const { command, args: initialArgs } = splitCommandLine(this.options.agentCommand);
|
|
1106
|
-
|
|
1209
|
+
let args = await resolveGeminiCommandArgs(command, initialArgs);
|
|
1210
|
+
if (isQoderAcpCommand(command, args)) args = buildQoderAcpCommandArgs(args, this.options);
|
|
1107
1211
|
this.log(`spawning agent: ${command} ${args.join(" ")}`);
|
|
1108
1212
|
const geminiAcp = isGeminiAcpCommand(command, args);
|
|
1109
1213
|
if (isCopilotAcpCommand(command, args)) await ensureCopilotAcpSupport(command);
|
|
@@ -1153,7 +1257,7 @@ var AcpClient = class {
|
|
|
1153
1257
|
releaseTerminal: async (params) => {
|
|
1154
1258
|
return this.handleReleaseTerminal(params);
|
|
1155
1259
|
}
|
|
1156
|
-
}), this.createTappedStream(
|
|
1260
|
+
}), this.createTappedStream(createNdJsonMessageStream(this.options.agentCommand, input, output)));
|
|
1157
1261
|
connection.signal.addEventListener("abort", () => {
|
|
1158
1262
|
this.recordAgentExit("connection_close", child.exitCode ?? null, child.signalCode ?? null);
|
|
1159
1263
|
}, { once: true });
|
|
@@ -1230,11 +1334,11 @@ var AcpClient = class {
|
|
|
1230
1334
|
const claudeAcp = isClaudeAcpCommand(command, args);
|
|
1231
1335
|
let result;
|
|
1232
1336
|
try {
|
|
1233
|
-
const createPromise = connection.newSession({
|
|
1337
|
+
const createPromise = this.runConnectionRequest(() => connection.newSession({
|
|
1234
1338
|
cwd: asAbsoluteCwd(cwd),
|
|
1235
1339
|
mcpServers: this.options.mcpServers ?? [],
|
|
1236
1340
|
_meta: buildClaudeCodeOptionsMeta(this.options.sessionOptions)
|
|
1237
|
-
});
|
|
1341
|
+
}));
|
|
1238
1342
|
result = claudeAcp ? await withTimeout(createPromise, resolveClaudeAcpSessionCreateTimeoutMs()) : await createPromise;
|
|
1239
1343
|
} catch (error) {
|
|
1240
1344
|
if (claudeAcp && error instanceof TimeoutError) throw new ClaudeAcpSessionCreateTimeoutError(buildClaudeAcpSessionCreateTimeoutMessage(), {
|
|
@@ -1246,7 +1350,8 @@ var AcpClient = class {
|
|
|
1246
1350
|
this.loadedSessionId = result.sessionId;
|
|
1247
1351
|
return {
|
|
1248
1352
|
sessionId: result.sessionId,
|
|
1249
|
-
agentSessionId: extractRuntimeSessionId(result._meta)
|
|
1353
|
+
agentSessionId: extractRuntimeSessionId(result._meta),
|
|
1354
|
+
models: result.models ?? void 0
|
|
1250
1355
|
};
|
|
1251
1356
|
}
|
|
1252
1357
|
async loadSession(sessionId, cwd = this.options.cwd) {
|
|
@@ -1261,28 +1366,31 @@ var AcpClient = class {
|
|
|
1261
1366
|
this.suppressReplaySessionUpdateMessages = previousReplaySuppression || Boolean(options.suppressReplayUpdates);
|
|
1262
1367
|
let response;
|
|
1263
1368
|
try {
|
|
1264
|
-
response = await connection.loadSession({
|
|
1369
|
+
response = await this.runConnectionRequest(() => connection.loadSession({
|
|
1265
1370
|
sessionId,
|
|
1266
1371
|
cwd: asAbsoluteCwd(cwd),
|
|
1267
1372
|
mcpServers: this.options.mcpServers ?? []
|
|
1268
|
-
});
|
|
1373
|
+
}));
|
|
1269
1374
|
await this.waitForSessionUpdateDrain(options.replayIdleMs ?? REPLAY_IDLE_MS, options.replayDrainTimeoutMs ?? REPLAY_DRAIN_TIMEOUT_MS);
|
|
1270
1375
|
} finally {
|
|
1271
1376
|
this.suppressSessionUpdates = previousSuppression;
|
|
1272
1377
|
this.suppressReplaySessionUpdateMessages = previousReplaySuppression;
|
|
1273
1378
|
}
|
|
1274
1379
|
this.loadedSessionId = sessionId;
|
|
1275
|
-
return {
|
|
1380
|
+
return {
|
|
1381
|
+
agentSessionId: extractRuntimeSessionId(response?._meta),
|
|
1382
|
+
models: response?.models ?? void 0
|
|
1383
|
+
};
|
|
1276
1384
|
}
|
|
1277
1385
|
async prompt(sessionId, prompt) {
|
|
1278
1386
|
const connection = this.getConnection();
|
|
1279
1387
|
const restoreConsoleError = this.options.suppressSdkConsoleErrors ? installSdkConsoleErrorSuppression() : void 0;
|
|
1280
1388
|
let promptPromise;
|
|
1281
1389
|
try {
|
|
1282
|
-
promptPromise = connection.prompt({
|
|
1390
|
+
promptPromise = this.runConnectionRequest(() => connection.prompt({
|
|
1283
1391
|
sessionId,
|
|
1284
1392
|
prompt: typeof prompt === "string" ? textPrompt(prompt) : prompt
|
|
1285
|
-
});
|
|
1393
|
+
}));
|
|
1286
1394
|
} catch (error) {
|
|
1287
1395
|
restoreConsoleError?.();
|
|
1288
1396
|
throw error;
|
|
@@ -1310,10 +1418,10 @@ var AcpClient = class {
|
|
|
1310
1418
|
async setSessionMode(sessionId, modeId) {
|
|
1311
1419
|
const connection = this.getConnection();
|
|
1312
1420
|
try {
|
|
1313
|
-
await connection.setSessionMode({
|
|
1421
|
+
await this.runConnectionRequest(() => connection.setSessionMode({
|
|
1314
1422
|
sessionId,
|
|
1315
1423
|
modeId
|
|
1316
|
-
});
|
|
1424
|
+
}));
|
|
1317
1425
|
} catch (error) {
|
|
1318
1426
|
throw maybeWrapSessionControlError("session/set_mode", error, `for mode "${modeId}"`);
|
|
1319
1427
|
}
|
|
@@ -1321,19 +1429,35 @@ var AcpClient = class {
|
|
|
1321
1429
|
async setSessionConfigOption(sessionId, configId, value) {
|
|
1322
1430
|
const connection = this.getConnection();
|
|
1323
1431
|
try {
|
|
1324
|
-
return await connection.setSessionConfigOption({
|
|
1432
|
+
return await this.runConnectionRequest(() => connection.setSessionConfigOption({
|
|
1325
1433
|
sessionId,
|
|
1326
1434
|
configId,
|
|
1327
1435
|
value
|
|
1328
|
-
});
|
|
1436
|
+
}));
|
|
1329
1437
|
} catch (error) {
|
|
1330
1438
|
throw maybeWrapSessionControlError("session/set_config_option", error, `for "${configId}"="${value}"`);
|
|
1331
1439
|
}
|
|
1332
1440
|
}
|
|
1441
|
+
async setSessionModel(sessionId, modelId) {
|
|
1442
|
+
const connection = this.getConnection();
|
|
1443
|
+
try {
|
|
1444
|
+
await this.runConnectionRequest(() => connection.unstable_setSessionModel({
|
|
1445
|
+
sessionId,
|
|
1446
|
+
modelId
|
|
1447
|
+
}));
|
|
1448
|
+
} catch (error) {
|
|
1449
|
+
const wrapped = maybeWrapSessionControlError("session/set_model", error, `for model "${modelId}"`);
|
|
1450
|
+
if (wrapped !== error) throw wrapped;
|
|
1451
|
+
const acp = extractAcpError(error);
|
|
1452
|
+
const summary = acp ? formatSessionControlAcpSummary(acp) : error instanceof Error ? error.message : String(error);
|
|
1453
|
+
if (error instanceof Error) throw new Error(`Failed session/set_model for model "${modelId}": ${summary}`, { cause: error });
|
|
1454
|
+
throw new Error(`Failed session/set_model for model "${modelId}": ${summary}`, { cause: error });
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1333
1457
|
async cancel(sessionId) {
|
|
1334
1458
|
const connection = this.getConnection();
|
|
1335
1459
|
this.cancellingSessionIds.add(sessionId);
|
|
1336
|
-
await connection.cancel({ sessionId });
|
|
1460
|
+
await this.runConnectionRequest(() => connection.cancel({ sessionId }));
|
|
1337
1461
|
}
|
|
1338
1462
|
async requestCancelActivePrompt() {
|
|
1339
1463
|
const active = this.activePrompt;
|
|
@@ -1366,6 +1490,7 @@ var AcpClient = class {
|
|
|
1366
1490
|
await this.terminalManager.shutdown();
|
|
1367
1491
|
const agent = this.agent;
|
|
1368
1492
|
if (agent) await this.terminateAgentProcess(agent);
|
|
1493
|
+
if (this.pendingConnectionRequests.size > 0) this.rejectPendingConnectionRequests(this.lastAgentExit ? new AgentDisconnectedError(this.lastAgentExit.reason, this.lastAgentExit.exitCode, this.lastAgentExit.signal, { outputAlreadyEmitted: Boolean(this.activePrompt) }) : new AgentDisconnectedError("connection_close", null, null, { outputAlreadyEmitted: Boolean(this.activePrompt) }));
|
|
1369
1494
|
this.sessionUpdateChain = Promise.resolve();
|
|
1370
1495
|
this.observedSessionUpdates = 0;
|
|
1371
1496
|
this.processedSessionUpdates = 0;
|
|
@@ -1380,10 +1505,11 @@ var AcpClient = class {
|
|
|
1380
1505
|
this.agent = void 0;
|
|
1381
1506
|
}
|
|
1382
1507
|
async terminateAgentProcess(child) {
|
|
1508
|
+
const stdinCloseGraceMs = resolveAgentCloseAfterStdinEndMs(this.options.agentCommand);
|
|
1383
1509
|
if (!child.stdin.destroyed) try {
|
|
1384
1510
|
child.stdin.end();
|
|
1385
1511
|
} catch {}
|
|
1386
|
-
let exited = await waitForChildExit(child,
|
|
1512
|
+
let exited = await waitForChildExit(child, stdinCloseGraceMs);
|
|
1387
1513
|
if (!exited && isChildProcessRunning(child)) {
|
|
1388
1514
|
try {
|
|
1389
1515
|
child.kill("SIGTERM");
|
|
@@ -1483,6 +1609,7 @@ var AcpClient = class {
|
|
|
1483
1609
|
reason,
|
|
1484
1610
|
unexpectedDuringPrompt: !this.closing && Boolean(this.activePrompt)
|
|
1485
1611
|
};
|
|
1612
|
+
this.rejectPendingConnectionRequests(new AgentDisconnectedError(reason, exitCode, signal, { outputAlreadyEmitted: Boolean(this.activePrompt) }));
|
|
1486
1613
|
}
|
|
1487
1614
|
notePromptPermissionFailure(sessionId, error) {
|
|
1488
1615
|
if (!this.promptPermissionFailures.has(sessionId)) this.promptPermissionFailures.set(sessionId, error);
|
|
@@ -1492,6 +1619,33 @@ var AcpClient = class {
|
|
|
1492
1619
|
if (error) this.promptPermissionFailures.delete(sessionId);
|
|
1493
1620
|
return error;
|
|
1494
1621
|
}
|
|
1622
|
+
async runConnectionRequest(run) {
|
|
1623
|
+
return await new Promise((resolve, reject) => {
|
|
1624
|
+
const pending = {
|
|
1625
|
+
settled: false,
|
|
1626
|
+
reject
|
|
1627
|
+
};
|
|
1628
|
+
const finish = (cb) => {
|
|
1629
|
+
if (pending.settled) return;
|
|
1630
|
+
pending.settled = true;
|
|
1631
|
+
this.pendingConnectionRequests.delete(pending);
|
|
1632
|
+
cb();
|
|
1633
|
+
};
|
|
1634
|
+
this.pendingConnectionRequests.add(pending);
|
|
1635
|
+
Promise.resolve().then(run).then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
rejectPendingConnectionRequests(error) {
|
|
1639
|
+
for (const pending of this.pendingConnectionRequests) {
|
|
1640
|
+
if (pending.settled) {
|
|
1641
|
+
this.pendingConnectionRequests.delete(pending);
|
|
1642
|
+
continue;
|
|
1643
|
+
}
|
|
1644
|
+
pending.settled = true;
|
|
1645
|
+
this.pendingConnectionRequests.delete(pending);
|
|
1646
|
+
pending.reject(error);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1495
1649
|
async handleReadTextFile(params) {
|
|
1496
1650
|
try {
|
|
1497
1651
|
return await this.filesystem.readTextFile(params);
|
|
@@ -1908,8 +2062,15 @@ function cloneSessionAcpxState(state) {
|
|
|
1908
2062
|
return {
|
|
1909
2063
|
current_mode_id: state.current_mode_id,
|
|
1910
2064
|
desired_mode_id: state.desired_mode_id,
|
|
2065
|
+
current_model_id: state.current_model_id,
|
|
2066
|
+
available_models: state.available_models ? [...state.available_models] : void 0,
|
|
1911
2067
|
available_commands: state.available_commands ? [...state.available_commands] : void 0,
|
|
1912
|
-
config_options: state.config_options ? deepClone(state.config_options) : void 0
|
|
2068
|
+
config_options: state.config_options ? deepClone(state.config_options) : void 0,
|
|
2069
|
+
session_options: state.session_options ? {
|
|
2070
|
+
model: state.session_options.model,
|
|
2071
|
+
allowed_tools: state.session_options.allowed_tools ? [...state.session_options.allowed_tools] : void 0,
|
|
2072
|
+
max_turns: state.session_options.max_turns
|
|
2073
|
+
} : void 0
|
|
1913
2074
|
};
|
|
1914
2075
|
}
|
|
1915
2076
|
function recordPromptSubmission(conversation, prompt, timestamp = isoNow$1()) {
|
|
@@ -2264,8 +2425,18 @@ function parseAcpxState(raw) {
|
|
|
2264
2425
|
const state = {};
|
|
2265
2426
|
if (typeof record.current_mode_id === "string") state.current_mode_id = record.current_mode_id;
|
|
2266
2427
|
if (typeof record.desired_mode_id === "string") state.desired_mode_id = record.desired_mode_id;
|
|
2428
|
+
if (typeof record.current_model_id === "string") state.current_model_id = record.current_model_id;
|
|
2429
|
+
if (isStringArray(record.available_models)) state.available_models = [...record.available_models];
|
|
2267
2430
|
if (isStringArray(record.available_commands)) state.available_commands = [...record.available_commands];
|
|
2268
2431
|
if (Array.isArray(record.config_options)) state.config_options = record.config_options;
|
|
2432
|
+
const sessionOptions = asRecord$1(record.session_options);
|
|
2433
|
+
if (sessionOptions) {
|
|
2434
|
+
const parsedSessionOptions = {};
|
|
2435
|
+
if (typeof sessionOptions.model === "string") parsedSessionOptions.model = sessionOptions.model;
|
|
2436
|
+
if (isStringArray(sessionOptions.allowed_tools)) parsedSessionOptions.allowed_tools = [...sessionOptions.allowed_tools];
|
|
2437
|
+
if (typeof sessionOptions.max_turns === "number" && Number.isInteger(sessionOptions.max_turns) && sessionOptions.max_turns > 0) parsedSessionOptions.max_turns = sessionOptions.max_turns;
|
|
2438
|
+
if (Object.keys(parsedSessionOptions).length > 0) state.session_options = parsedSessionOptions;
|
|
2439
|
+
}
|
|
2269
2440
|
return state;
|
|
2270
2441
|
}
|
|
2271
2442
|
function parseEventLog(raw, sessionId) {
|
|
@@ -2865,6 +3036,15 @@ var QueueOwnerTurnController = class {
|
|
|
2865
3036
|
}
|
|
2866
3037
|
await this.options.setSessionModeFallback(modeId, timeoutMs);
|
|
2867
3038
|
}
|
|
3039
|
+
async setSessionModel(modelId, timeoutMs) {
|
|
3040
|
+
this.assertCanHandleControlRequest();
|
|
3041
|
+
const activeController = this.activeController;
|
|
3042
|
+
if (activeController) {
|
|
3043
|
+
await this.options.withTimeout(async () => await activeController.setSessionModel(modelId), timeoutMs);
|
|
3044
|
+
return;
|
|
3045
|
+
}
|
|
3046
|
+
await this.options.setSessionModelFallback(modelId, timeoutMs);
|
|
3047
|
+
}
|
|
2868
3048
|
async setSessionConfigOption(configId, value, timeoutMs) {
|
|
2869
3049
|
this.assertCanHandleControlRequest();
|
|
2870
3050
|
const activeController = this.activeController;
|
|
@@ -2882,6 +3062,11 @@ function normalizeModeId(modeId) {
|
|
|
2882
3062
|
const trimmed = modeId.trim();
|
|
2883
3063
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
2884
3064
|
}
|
|
3065
|
+
function normalizeModelId(modelId) {
|
|
3066
|
+
if (typeof modelId !== "string") return;
|
|
3067
|
+
const trimmed = modelId.trim();
|
|
3068
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
3069
|
+
}
|
|
2885
3070
|
function getDesiredModeId(state) {
|
|
2886
3071
|
return normalizeModeId(state?.desired_mode_id);
|
|
2887
3072
|
}
|
|
@@ -2892,6 +3077,33 @@ function setDesiredModeId(record, modeId) {
|
|
|
2892
3077
|
else delete acpx.desired_mode_id;
|
|
2893
3078
|
record.acpx = acpx;
|
|
2894
3079
|
}
|
|
3080
|
+
function getDesiredModelId(state) {
|
|
3081
|
+
return normalizeModelId(state?.session_options?.model);
|
|
3082
|
+
}
|
|
3083
|
+
function setDesiredModelId(record, modelId) {
|
|
3084
|
+
const acpx = ensureAcpxState(record.acpx);
|
|
3085
|
+
const normalized = normalizeModelId(modelId);
|
|
3086
|
+
const sessionOptions = { ...acpx.session_options };
|
|
3087
|
+
if (normalized) sessionOptions.model = normalized;
|
|
3088
|
+
else delete sessionOptions.model;
|
|
3089
|
+
if (typeof sessionOptions.model === "string" || Array.isArray(sessionOptions.allowed_tools) || typeof sessionOptions.max_turns === "number") acpx.session_options = sessionOptions;
|
|
3090
|
+
else delete acpx.session_options;
|
|
3091
|
+
record.acpx = acpx;
|
|
3092
|
+
}
|
|
3093
|
+
function setCurrentModelId(record, modelId) {
|
|
3094
|
+
const acpx = ensureAcpxState(record.acpx);
|
|
3095
|
+
const normalized = normalizeModelId(modelId);
|
|
3096
|
+
if (normalized) acpx.current_model_id = normalized;
|
|
3097
|
+
else delete acpx.current_model_id;
|
|
3098
|
+
record.acpx = acpx;
|
|
3099
|
+
}
|
|
3100
|
+
function syncAdvertisedModelState(record, models) {
|
|
3101
|
+
if (!models) return;
|
|
3102
|
+
const acpx = ensureAcpxState(record.acpx);
|
|
3103
|
+
acpx.current_model_id = models.currentModelId;
|
|
3104
|
+
acpx.available_models = models.availableModels.map((model) => model.modelId);
|
|
3105
|
+
record.acpx = acpx;
|
|
3106
|
+
}
|
|
2895
3107
|
//#endregion
|
|
2896
3108
|
//#region src/session-runtime/lifecycle.ts
|
|
2897
3109
|
function applyLifecycleSnapshotToRecord(record, snapshot) {
|
|
@@ -2926,21 +3138,32 @@ function applyConversation(record, conversation) {
|
|
|
2926
3138
|
}
|
|
2927
3139
|
//#endregion
|
|
2928
3140
|
//#region src/session-runtime/connect-load.ts
|
|
3141
|
+
const SESSION_LOAD_UNSUPPORTED_CODES = new Set([-32601, -32602]);
|
|
2929
3142
|
function shouldFallbackToNewSession(error, record) {
|
|
2930
3143
|
if (error instanceof TimeoutError || error instanceof InterruptedError) return false;
|
|
2931
3144
|
if (isAcpResourceNotFoundError(error)) return true;
|
|
3145
|
+
const acp = extractAcpError(error);
|
|
3146
|
+
if (acp && SESSION_LOAD_UNSUPPORTED_CODES.has(acp.code)) return true;
|
|
2932
3147
|
if (!sessionHasAgentMessages(record)) {
|
|
2933
3148
|
if (isAcpQueryClosedBeforeResponseError(error)) return true;
|
|
2934
|
-
if (
|
|
3149
|
+
if (acp?.code === -32603) return true;
|
|
2935
3150
|
}
|
|
2936
3151
|
return false;
|
|
2937
3152
|
}
|
|
3153
|
+
function requiresSameSession(resumePolicy) {
|
|
3154
|
+
return resumePolicy === "same-session-only";
|
|
3155
|
+
}
|
|
3156
|
+
function makeSessionResumeRequiredError(params) {
|
|
3157
|
+
return new SessionResumeRequiredError(`Persistent ACP session ${params.record.acpSessionId} could not be resumed: ${params.reason}`, { cause: params.cause instanceof Error ? params.cause : void 0 });
|
|
3158
|
+
}
|
|
2938
3159
|
async function connectAndLoadSession(options) {
|
|
2939
3160
|
const record = options.record;
|
|
2940
3161
|
const client = options.client;
|
|
3162
|
+
const sameSessionOnly = requiresSameSession(options.resumePolicy);
|
|
2941
3163
|
const originalSessionId = record.acpSessionId;
|
|
2942
3164
|
const originalAgentSessionId = record.agentSessionId;
|
|
2943
3165
|
const desiredModeId = getDesiredModeId(record.acpx);
|
|
3166
|
+
const desiredModelId = getDesiredModelId(record.acpx);
|
|
2944
3167
|
const storedProcessAlive = isProcessAlive(record.pid);
|
|
2945
3168
|
const shouldReconnect = Boolean(record.pid) && !storedProcessAlive;
|
|
2946
3169
|
if (options.verbose) {
|
|
@@ -2960,23 +3183,37 @@ async function connectAndLoadSession(options) {
|
|
|
2960
3183
|
let sessionId = record.acpSessionId;
|
|
2961
3184
|
let createdFreshSession = false;
|
|
2962
3185
|
let pendingAgentSessionId = record.agentSessionId;
|
|
3186
|
+
let sessionModels;
|
|
2963
3187
|
if (reusingLoadedSession) resumed = true;
|
|
2964
3188
|
else if (client.supportsLoadSession()) try {
|
|
2965
|
-
|
|
3189
|
+
const loadResult = await withTimeout(client.loadSessionWithOptions(record.acpSessionId, record.cwd, { suppressReplayUpdates: true }), options.timeoutMs);
|
|
3190
|
+
reconcileAgentSessionId(record, loadResult.agentSessionId);
|
|
3191
|
+
sessionModels = loadResult.models;
|
|
2966
3192
|
resumed = true;
|
|
2967
3193
|
} catch (error) {
|
|
2968
3194
|
loadError = formatErrorMessage(error);
|
|
3195
|
+
if (sameSessionOnly) throw makeSessionResumeRequiredError({
|
|
3196
|
+
record,
|
|
3197
|
+
reason: loadError,
|
|
3198
|
+
cause: error
|
|
3199
|
+
});
|
|
2969
3200
|
if (!shouldFallbackToNewSession(error, record)) throw error;
|
|
2970
3201
|
const createdSession = await withTimeout(client.createSession(record.cwd), options.timeoutMs);
|
|
2971
3202
|
sessionId = createdSession.sessionId;
|
|
2972
3203
|
createdFreshSession = true;
|
|
2973
3204
|
pendingAgentSessionId = createdSession.agentSessionId;
|
|
3205
|
+
sessionModels = createdSession.models;
|
|
2974
3206
|
}
|
|
2975
3207
|
else {
|
|
3208
|
+
if (sameSessionOnly) throw makeSessionResumeRequiredError({
|
|
3209
|
+
record,
|
|
3210
|
+
reason: "agent does not support session/load"
|
|
3211
|
+
});
|
|
2976
3212
|
const createdSession = await withTimeout(client.createSession(record.cwd), options.timeoutMs);
|
|
2977
3213
|
sessionId = createdSession.sessionId;
|
|
2978
3214
|
createdFreshSession = true;
|
|
2979
3215
|
pendingAgentSessionId = createdSession.agentSessionId;
|
|
3216
|
+
sessionModels = createdSession.models;
|
|
2980
3217
|
}
|
|
2981
3218
|
if (createdFreshSession && desiredModeId) try {
|
|
2982
3219
|
await withTimeout(client.setSessionMode(sessionId, desiredModeId), options.timeoutMs);
|
|
@@ -2991,10 +3228,26 @@ async function connectAndLoadSession(options) {
|
|
|
2991
3228
|
retryable: true
|
|
2992
3229
|
});
|
|
2993
3230
|
}
|
|
3231
|
+
if (createdFreshSession && desiredModelId && sessionModels && desiredModelId !== sessionModels.currentModelId) try {
|
|
3232
|
+
await withTimeout(client.setSessionModel(sessionId, desiredModelId), options.timeoutMs);
|
|
3233
|
+
setCurrentModelId(record, desiredModelId);
|
|
3234
|
+
if (options.verbose) process.stderr.write(`[acpx] replayed desired model ${desiredModelId} on fresh ACP session ${sessionId} (previous ${originalSessionId})\n`);
|
|
3235
|
+
} catch (error) {
|
|
3236
|
+
const message = `Failed to replay saved session model ${desiredModelId} on fresh ACP session ${sessionId}: ` + formatErrorMessage(error);
|
|
3237
|
+
record.acpSessionId = originalSessionId;
|
|
3238
|
+
record.agentSessionId = originalAgentSessionId;
|
|
3239
|
+
if (options.verbose) process.stderr.write(`[acpx] ${message}\n`);
|
|
3240
|
+
throw new SessionModelReplayError(message, {
|
|
3241
|
+
cause: error instanceof Error ? error : void 0,
|
|
3242
|
+
retryable: true
|
|
3243
|
+
});
|
|
3244
|
+
}
|
|
2994
3245
|
if (createdFreshSession) {
|
|
2995
3246
|
record.acpSessionId = sessionId;
|
|
2996
3247
|
reconcileAgentSessionId(record, pendingAgentSessionId);
|
|
2997
3248
|
}
|
|
3249
|
+
syncAdvertisedModelState(record, sessionModels);
|
|
3250
|
+
if (createdFreshSession && desiredModelId && sessionModels) setCurrentModelId(record, desiredModelId);
|
|
2998
3251
|
options.onSessionIdResolved?.(sessionId);
|
|
2999
3252
|
return {
|
|
3000
3253
|
sessionId,
|
|
@@ -3005,6 +3258,15 @@ async function connectAndLoadSession(options) {
|
|
|
3005
3258
|
}
|
|
3006
3259
|
//#endregion
|
|
3007
3260
|
//#region src/session-runtime/prompt-runner.ts
|
|
3261
|
+
function sessionOptionsFromRecord$1(record) {
|
|
3262
|
+
const stored = record.acpx?.session_options;
|
|
3263
|
+
if (!stored) return;
|
|
3264
|
+
const sessionOptions = {};
|
|
3265
|
+
if (typeof stored.model === "string" && stored.model.trim().length > 0) sessionOptions.model = stored.model;
|
|
3266
|
+
if (Array.isArray(stored.allowed_tools)) sessionOptions.allowedTools = [...stored.allowed_tools];
|
|
3267
|
+
if (typeof stored.max_turns === "number") sessionOptions.maxTurns = stored.max_turns;
|
|
3268
|
+
return Object.keys(sessionOptions).length > 0 ? sessionOptions : void 0;
|
|
3269
|
+
}
|
|
3008
3270
|
async function withConnectedSession(options) {
|
|
3009
3271
|
const record = await resolveSessionRecord(options.sessionRecordId);
|
|
3010
3272
|
const client = new AcpClient({
|
|
@@ -3015,7 +3277,8 @@ async function withConnectedSession(options) {
|
|
|
3015
3277
|
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
3016
3278
|
authCredentials: options.authCredentials,
|
|
3017
3279
|
authPolicy: options.authPolicy,
|
|
3018
|
-
verbose: options.verbose
|
|
3280
|
+
verbose: options.verbose,
|
|
3281
|
+
sessionOptions: sessionOptionsFromRecord$1(record)
|
|
3019
3282
|
});
|
|
3020
3283
|
let activeSessionIdForControl = record.acpSessionId;
|
|
3021
3284
|
let notifiedClientAvailable = false;
|
|
@@ -3025,6 +3288,9 @@ async function withConnectedSession(options) {
|
|
|
3025
3288
|
setSessionMode: async (modeId) => {
|
|
3026
3289
|
await client.setSessionMode(activeSessionIdForControl, modeId);
|
|
3027
3290
|
},
|
|
3291
|
+
setSessionModel: async (modelId) => {
|
|
3292
|
+
await client.setSessionModel(activeSessionIdForControl, modelId);
|
|
3293
|
+
},
|
|
3028
3294
|
setSessionConfigOption: async (configId, value) => {
|
|
3029
3295
|
return await client.setSessionConfigOption(activeSessionIdForControl, configId, value);
|
|
3030
3296
|
}
|
|
@@ -3095,6 +3361,29 @@ async function runSessionSetModeDirect(options) {
|
|
|
3095
3361
|
loadError: result.loadError
|
|
3096
3362
|
};
|
|
3097
3363
|
}
|
|
3364
|
+
async function runSessionSetModelDirect(options) {
|
|
3365
|
+
const result = await withConnectedSession({
|
|
3366
|
+
sessionRecordId: options.sessionRecordId,
|
|
3367
|
+
mcpServers: options.mcpServers,
|
|
3368
|
+
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
3369
|
+
authCredentials: options.authCredentials,
|
|
3370
|
+
authPolicy: options.authPolicy,
|
|
3371
|
+
timeoutMs: options.timeoutMs,
|
|
3372
|
+
verbose: options.verbose,
|
|
3373
|
+
onClientAvailable: options.onClientAvailable,
|
|
3374
|
+
onClientClosed: options.onClientClosed,
|
|
3375
|
+
run: async (client, sessionId, record) => {
|
|
3376
|
+
await withTimeout(client.setSessionModel(sessionId, options.modelId), options.timeoutMs);
|
|
3377
|
+
setDesiredModelId(record, options.modelId);
|
|
3378
|
+
setCurrentModelId(record, options.modelId);
|
|
3379
|
+
}
|
|
3380
|
+
});
|
|
3381
|
+
return {
|
|
3382
|
+
record: result.record,
|
|
3383
|
+
resumed: result.resumed,
|
|
3384
|
+
loadError: result.loadError
|
|
3385
|
+
};
|
|
3386
|
+
}
|
|
3098
3387
|
async function runSessionSetConfigOptionDirect(options) {
|
|
3099
3388
|
const result = await withConnectedSession({
|
|
3100
3389
|
sessionRecordId: options.sessionRecordId,
|
|
@@ -3121,7 +3410,40 @@ async function runSessionSetConfigOptionDirect(options) {
|
|
|
3121
3410
|
}
|
|
3122
3411
|
//#endregion
|
|
3123
3412
|
//#region src/session-runtime/queue-owner-process.ts
|
|
3413
|
+
function sanitizeQueueOwnerExecArgv(execArgv = process.execArgv) {
|
|
3414
|
+
const sanitized = [];
|
|
3415
|
+
for (let index = 0; index < execArgv.length; index += 1) {
|
|
3416
|
+
const value = execArgv[index];
|
|
3417
|
+
if (value === "--experimental-test-coverage" || value === "--test") continue;
|
|
3418
|
+
if (value === "--test-name-pattern" || value === "--test-reporter" || value === "--test-reporter-destination") {
|
|
3419
|
+
index += 1;
|
|
3420
|
+
continue;
|
|
3421
|
+
}
|
|
3422
|
+
if (value.startsWith("--test-")) continue;
|
|
3423
|
+
if (value === "--inspect" || value === "--inspect-brk" || value === "--inspect-port" || value === "--inspect-publish-uid" || value.startsWith("--inspect=") || value.startsWith("--inspect-brk=") || value.startsWith("--inspect-port=") || value.startsWith("--inspect-publish-uid=") || value === "--debug-port" || value.startsWith("--debug-port=")) {
|
|
3424
|
+
if (value === "--inspect" || value === "--inspect-brk" || value === "--inspect-port" || value === "--inspect-publish-uid" || value === "--debug-port") index += 1;
|
|
3425
|
+
continue;
|
|
3426
|
+
}
|
|
3427
|
+
sanitized.push(value);
|
|
3428
|
+
}
|
|
3429
|
+
return sanitized;
|
|
3430
|
+
}
|
|
3431
|
+
function buildQueueOwnerArgOverride(entryPath, execArgv = process.execArgv) {
|
|
3432
|
+
const sanitized = sanitizeQueueOwnerExecArgv(execArgv);
|
|
3433
|
+
if (sanitized.length === 0) return null;
|
|
3434
|
+
return JSON.stringify([
|
|
3435
|
+
...sanitized,
|
|
3436
|
+
entryPath,
|
|
3437
|
+
"__queue-owner"
|
|
3438
|
+
]);
|
|
3439
|
+
}
|
|
3124
3440
|
function resolveQueueOwnerSpawnArgs(argv = process.argv) {
|
|
3441
|
+
const override = process.env.ACPX_QUEUE_OWNER_ARGS;
|
|
3442
|
+
if (override) {
|
|
3443
|
+
const parsed = JSON.parse(override);
|
|
3444
|
+
if (Array.isArray(parsed) && parsed.length > 0 && parsed.every((value) => typeof value === "string" && value.length > 0)) return [...parsed];
|
|
3445
|
+
throw new Error("acpx self-spawn failed: invalid ACPX_QUEUE_OWNER_ARGS");
|
|
3446
|
+
}
|
|
3125
3447
|
const entry = argv[1];
|
|
3126
3448
|
if (!entry || entry.trim().length === 0) throw new Error("acpx self-spawn failed: missing CLI entry path");
|
|
3127
3449
|
return [realpathSync(entry), "__queue-owner"];
|
|
@@ -3137,7 +3459,8 @@ function queueOwnerRuntimeOptionsFromSend(options) {
|
|
|
3137
3459
|
suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,
|
|
3138
3460
|
verbose: options.verbose,
|
|
3139
3461
|
ttlMs: options.ttlMs,
|
|
3140
|
-
maxQueueDepth: options.maxQueueDepth
|
|
3462
|
+
maxQueueDepth: options.maxQueueDepth,
|
|
3463
|
+
promptRetries: options.promptRetries
|
|
3141
3464
|
};
|
|
3142
3465
|
}
|
|
3143
3466
|
function buildQueueOwnerSpawnOptions(payload) {
|
|
@@ -3161,6 +3484,31 @@ const DEFAULT_QUEUE_OWNER_TTL_MS = 3e5;
|
|
|
3161
3484
|
const INTERRUPT_CANCEL_WAIT_MS = 2500;
|
|
3162
3485
|
const QUEUE_OWNER_STARTUP_MAX_ATTEMPTS = 120;
|
|
3163
3486
|
const QUEUE_OWNER_HEARTBEAT_INTERVAL_MS = 5e3;
|
|
3487
|
+
function sessionOptionsFromRecord(record) {
|
|
3488
|
+
const stored = record.acpx?.session_options;
|
|
3489
|
+
if (!stored) return;
|
|
3490
|
+
const sessionOptions = {};
|
|
3491
|
+
if (typeof stored.model === "string" && stored.model.trim().length > 0) sessionOptions.model = stored.model;
|
|
3492
|
+
if (Array.isArray(stored.allowed_tools)) sessionOptions.allowedTools = [...stored.allowed_tools];
|
|
3493
|
+
if (typeof stored.max_turns === "number") sessionOptions.maxTurns = stored.max_turns;
|
|
3494
|
+
return Object.keys(sessionOptions).length > 0 ? sessionOptions : void 0;
|
|
3495
|
+
}
|
|
3496
|
+
function persistSessionOptions(record, options) {
|
|
3497
|
+
const next = options && {
|
|
3498
|
+
model: typeof options.model === "string" ? options.model : void 0,
|
|
3499
|
+
allowed_tools: Array.isArray(options.allowedTools) ? [...options.allowedTools] : void 0,
|
|
3500
|
+
max_turns: typeof options.maxTurns === "number" ? options.maxTurns : void 0
|
|
3501
|
+
};
|
|
3502
|
+
if (Boolean(next && (typeof next.model === "string" && next.model.trim().length > 0 || Array.isArray(next.allowed_tools) && next.allowed_tools.length > 0 || typeof next.max_turns === "number")) && next) {
|
|
3503
|
+
record.acpx = {
|
|
3504
|
+
...record.acpx,
|
|
3505
|
+
session_options: next
|
|
3506
|
+
};
|
|
3507
|
+
return;
|
|
3508
|
+
}
|
|
3509
|
+
if (!record.acpx) return;
|
|
3510
|
+
delete record.acpx.session_options;
|
|
3511
|
+
}
|
|
3164
3512
|
function toPromptResult(stopReason, sessionId, client) {
|
|
3165
3513
|
return {
|
|
3166
3514
|
stopReason,
|
|
@@ -3168,6 +3516,13 @@ function toPromptResult(stopReason, sessionId, client) {
|
|
|
3168
3516
|
permissionStats: client.getPermissionStats()
|
|
3169
3517
|
};
|
|
3170
3518
|
}
|
|
3519
|
+
async function applyRequestedModelIfAdvertised(params) {
|
|
3520
|
+
const requestedModel = typeof params.requestedModel === "string" ? params.requestedModel.trim() : "";
|
|
3521
|
+
if (!requestedModel || !params.models) return false;
|
|
3522
|
+
if (params.models.currentModelId === requestedModel) return true;
|
|
3523
|
+
await withTimeout(params.client.setSessionModel(params.sessionId, requestedModel), params.timeoutMs);
|
|
3524
|
+
return true;
|
|
3525
|
+
}
|
|
3171
3526
|
var QueueTaskOutputFormatter = class {
|
|
3172
3527
|
requestId;
|
|
3173
3528
|
send;
|
|
@@ -3255,6 +3610,10 @@ function normalizeQueueOwnerTtlMs(ttlMs) {
|
|
|
3255
3610
|
if (!Number.isFinite(ttlMs) || ttlMs < 0) return DEFAULT_QUEUE_OWNER_TTL_MS;
|
|
3256
3611
|
return Math.round(ttlMs);
|
|
3257
3612
|
}
|
|
3613
|
+
function emitPromptRetryNotice(params) {
|
|
3614
|
+
if (params.suppressSdkConsoleErrors) return;
|
|
3615
|
+
process.stderr.write(`[acpx] prompt failed (${formatErrorMessage(params.error)}), retrying in ${params.delayMs}ms (attempt ${params.attempt}/${params.maxRetries})\n`);
|
|
3616
|
+
}
|
|
3258
3617
|
async function runQueuedTask(sessionRecordId, task, options) {
|
|
3259
3618
|
const outputFormatter = task.waitForCompletion ? new QueueTaskOutputFormatter(task) : DISCARD_OUTPUT_FORMATTER;
|
|
3260
3619
|
try {
|
|
@@ -3263,6 +3622,7 @@ async function runQueuedTask(sessionRecordId, task, options) {
|
|
|
3263
3622
|
mcpServers: options.mcpServers,
|
|
3264
3623
|
prompt: task.prompt ?? textPrompt(task.message),
|
|
3265
3624
|
permissionMode: task.permissionMode,
|
|
3625
|
+
resumePolicy: task.resumePolicy,
|
|
3266
3626
|
nonInteractivePermissions: task.nonInteractivePermissions ?? options.nonInteractivePermissions,
|
|
3267
3627
|
authCredentials: options.authCredentials,
|
|
3268
3628
|
authPolicy: options.authPolicy,
|
|
@@ -3270,6 +3630,7 @@ async function runQueuedTask(sessionRecordId, task, options) {
|
|
|
3270
3630
|
timeoutMs: task.timeoutMs,
|
|
3271
3631
|
suppressSdkConsoleErrors: task.suppressSdkConsoleErrors ?? options.suppressSdkConsoleErrors,
|
|
3272
3632
|
verbose: options.verbose,
|
|
3633
|
+
promptRetries: options.promptRetries,
|
|
3273
3634
|
onClientAvailable: options.onClientAvailable,
|
|
3274
3635
|
onClientClosed: options.onClientClosed,
|
|
3275
3636
|
onPromptActive: options.onPromptActive,
|
|
@@ -3318,6 +3679,8 @@ async function runSessionPrompt(options) {
|
|
|
3318
3679
|
const pendingMessages = [];
|
|
3319
3680
|
const pendingConnectOutputMessages = [];
|
|
3320
3681
|
let bufferingConnectOutput = true;
|
|
3682
|
+
let promptTurnActive = false;
|
|
3683
|
+
let promptTurnHadSideEffects = false;
|
|
3321
3684
|
let sawAcpMessage = false;
|
|
3322
3685
|
let eventWriterClosed = false;
|
|
3323
3686
|
const closeEventWriter = async (checkpoint) => {
|
|
@@ -3342,7 +3705,8 @@ async function runSessionPrompt(options) {
|
|
|
3342
3705
|
authCredentials: options.authCredentials,
|
|
3343
3706
|
authPolicy: options.authPolicy,
|
|
3344
3707
|
suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,
|
|
3345
|
-
verbose: options.verbose
|
|
3708
|
+
verbose: options.verbose,
|
|
3709
|
+
sessionOptions: sessionOptionsFromRecord(record)
|
|
3346
3710
|
});
|
|
3347
3711
|
client.updateRuntimeOptions({
|
|
3348
3712
|
permissionMode: options.permissionMode,
|
|
@@ -3351,9 +3715,10 @@ async function runSessionPrompt(options) {
|
|
|
3351
3715
|
verbose: options.verbose
|
|
3352
3716
|
});
|
|
3353
3717
|
client.setEventHandlers({
|
|
3354
|
-
onAcpMessage: (
|
|
3718
|
+
onAcpMessage: (direction, message) => {
|
|
3355
3719
|
sawAcpMessage = true;
|
|
3356
3720
|
pendingMessages.push(message);
|
|
3721
|
+
options.onAcpMessage?.(direction, message);
|
|
3357
3722
|
},
|
|
3358
3723
|
onAcpOutputMessage: (_direction, message) => {
|
|
3359
3724
|
if (bufferingConnectOutput) {
|
|
@@ -3363,12 +3728,16 @@ async function runSessionPrompt(options) {
|
|
|
3363
3728
|
output.onAcpMessage(message);
|
|
3364
3729
|
},
|
|
3365
3730
|
onSessionUpdate: (notification) => {
|
|
3731
|
+
if (promptTurnActive) promptTurnHadSideEffects = true;
|
|
3366
3732
|
acpxState = recordSessionUpdate(conversation, acpxState, notification);
|
|
3367
3733
|
trimConversationForRuntime(conversation);
|
|
3734
|
+
options.onSessionUpdate?.(notification);
|
|
3368
3735
|
},
|
|
3369
3736
|
onClientOperation: (operation) => {
|
|
3737
|
+
if (promptTurnActive) promptTurnHadSideEffects = true;
|
|
3370
3738
|
acpxState = recordClientOperation(conversation, acpxState, operation);
|
|
3371
3739
|
trimConversationForRuntime(conversation);
|
|
3740
|
+
options.onClientOperation?.(operation);
|
|
3372
3741
|
}
|
|
3373
3742
|
});
|
|
3374
3743
|
let activeSessionIdForControl = record.acpSessionId;
|
|
@@ -3379,6 +3748,9 @@ async function runSessionPrompt(options) {
|
|
|
3379
3748
|
setSessionMode: async (modeId) => {
|
|
3380
3749
|
await client.setSessionMode(activeSessionIdForControl, modeId);
|
|
3381
3750
|
},
|
|
3751
|
+
setSessionModel: async (modelId) => {
|
|
3752
|
+
await client.setSessionModel(activeSessionIdForControl, modelId);
|
|
3753
|
+
},
|
|
3382
3754
|
setSessionConfigOption: async (configId, value) => {
|
|
3383
3755
|
return await client.setSessionConfigOption(activeSessionIdForControl, configId, value);
|
|
3384
3756
|
}
|
|
@@ -3391,6 +3763,7 @@ async function runSessionPrompt(options) {
|
|
|
3391
3763
|
return await connectAndLoadSession({
|
|
3392
3764
|
client,
|
|
3393
3765
|
record,
|
|
3766
|
+
resumePolicy: options.resumePolicy,
|
|
3394
3767
|
timeoutMs: options.timeoutMs,
|
|
3395
3768
|
verbose: options.verbose,
|
|
3396
3769
|
activeController,
|
|
@@ -3419,11 +3792,13 @@ async function runSessionPrompt(options) {
|
|
|
3419
3792
|
if (options.verbose) process.stderr.write(`[acpx] ${formatPerfMetric("prompt.connect_and_load", Date.now() - connectStartedAt)}\n`);
|
|
3420
3793
|
output.setContext({ sessionId: record.acpxRecordId });
|
|
3421
3794
|
await flushPendingMessages(false);
|
|
3795
|
+
const maxRetries = options.promptRetries ?? 0;
|
|
3422
3796
|
let response;
|
|
3423
|
-
|
|
3797
|
+
promptTurnActive = true;
|
|
3798
|
+
for (let attempt = 0;; attempt++) try {
|
|
3424
3799
|
const promptStartedAt = Date.now();
|
|
3425
3800
|
const promptPromise = client.prompt(activeSessionId, options.prompt);
|
|
3426
|
-
if (options.onPromptActive) try {
|
|
3801
|
+
if (attempt === 0 && options.onPromptActive) try {
|
|
3427
3802
|
await options.onPromptActive();
|
|
3428
3803
|
} catch (error) {
|
|
3429
3804
|
if (options.verbose) process.stderr.write("[acpx] onPromptActive hook failed: " + formatErrorMessage(error) + "\n");
|
|
@@ -3432,10 +3807,26 @@ async function runSessionPrompt(options) {
|
|
|
3432
3807
|
return await withTimeout(promptPromise, options.timeoutMs);
|
|
3433
3808
|
});
|
|
3434
3809
|
if (options.verbose) process.stderr.write(`[acpx] ${formatPerfMetric("prompt.agent_turn", Date.now() - promptStartedAt)}\n`);
|
|
3810
|
+
break;
|
|
3435
3811
|
} catch (error) {
|
|
3436
3812
|
const snapshot = client.getAgentLifecycleSnapshot();
|
|
3813
|
+
const agentCrashed = snapshot.lastExit?.unexpectedDuringPrompt === true;
|
|
3814
|
+
if (attempt < maxRetries && !agentCrashed && !promptTurnHadSideEffects && isRetryablePromptError(error)) {
|
|
3815
|
+
const delayMs = Math.min(1e3 * 2 ** attempt, 1e4);
|
|
3816
|
+
emitPromptRetryNotice({
|
|
3817
|
+
error,
|
|
3818
|
+
delayMs,
|
|
3819
|
+
attempt: attempt + 1,
|
|
3820
|
+
maxRetries,
|
|
3821
|
+
suppressSdkConsoleErrors: options.suppressSdkConsoleErrors
|
|
3822
|
+
});
|
|
3823
|
+
await waitMs$1(delayMs);
|
|
3824
|
+
if (!promptTurnHadSideEffects) continue;
|
|
3825
|
+
}
|
|
3826
|
+
promptTurnActive = false;
|
|
3437
3827
|
applyLifecycleSnapshotToRecord(record, snapshot);
|
|
3438
|
-
|
|
3828
|
+
const lastExit = snapshot.lastExit;
|
|
3829
|
+
if (lastExit?.unexpectedDuringPrompt && options.verbose) process.stderr.write("[acpx] agent disconnected during prompt (" + lastExit.reason + ", exit=" + lastExit.exitCode + ", signal=" + (lastExit.signal ?? "none") + ")\n");
|
|
3439
3830
|
const normalizedError = normalizeOutputError(error, { origin: "runtime" });
|
|
3440
3831
|
await flushPendingMessages(false).catch(() => {});
|
|
3441
3832
|
output.flush();
|
|
@@ -3447,6 +3838,7 @@ async function runSessionPrompt(options) {
|
|
|
3447
3838
|
propagated.normalizedOutputError = normalizedError;
|
|
3448
3839
|
throw propagated;
|
|
3449
3840
|
}
|
|
3841
|
+
promptTurnActive = false;
|
|
3450
3842
|
await flushPendingMessages(false);
|
|
3451
3843
|
output.flush();
|
|
3452
3844
|
record.lastUsedAt = isoNow();
|
|
@@ -3488,6 +3880,8 @@ async function runSessionPrompt(options) {
|
|
|
3488
3880
|
}
|
|
3489
3881
|
async function runOnce(options) {
|
|
3490
3882
|
const output = options.outputFormatter;
|
|
3883
|
+
let promptTurnActive = false;
|
|
3884
|
+
let promptTurnHadSideEffects = false;
|
|
3491
3885
|
const client = new AcpClient({
|
|
3492
3886
|
agentCommand: options.agentCommand,
|
|
3493
3887
|
cwd: absolutePath(options.cwd),
|
|
@@ -3498,7 +3892,16 @@ async function runOnce(options) {
|
|
|
3498
3892
|
authPolicy: options.authPolicy,
|
|
3499
3893
|
suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,
|
|
3500
3894
|
verbose: options.verbose,
|
|
3895
|
+
onAcpMessage: options.onAcpMessage,
|
|
3501
3896
|
onAcpOutputMessage: (_direction, message) => output.onAcpMessage(message),
|
|
3897
|
+
onSessionUpdate: (notification) => {
|
|
3898
|
+
if (promptTurnActive) promptTurnHadSideEffects = true;
|
|
3899
|
+
options.onSessionUpdate?.(notification);
|
|
3900
|
+
},
|
|
3901
|
+
onClientOperation: (operation) => {
|
|
3902
|
+
if (promptTurnActive) promptTurnHadSideEffects = true;
|
|
3903
|
+
options.onClientOperation?.(operation);
|
|
3904
|
+
},
|
|
3502
3905
|
sessionOptions: options.sessionOptions
|
|
3503
3906
|
});
|
|
3504
3907
|
try {
|
|
@@ -3506,13 +3909,43 @@ async function runOnce(options) {
|
|
|
3506
3909
|
await measurePerf("runtime.exec.start", async () => {
|
|
3507
3910
|
await withTimeout(client.start(), options.timeoutMs);
|
|
3508
3911
|
});
|
|
3509
|
-
const
|
|
3912
|
+
const createdSession = await measurePerf("runtime.exec.create_session", async () => {
|
|
3510
3913
|
return await withTimeout(client.createSession(absolutePath(options.cwd)), options.timeoutMs);
|
|
3511
|
-
})).sessionId;
|
|
3512
|
-
output.setContext({ sessionId });
|
|
3513
|
-
const response = await measurePerf("runtime.exec.prompt", async () => {
|
|
3514
|
-
return await withTimeout(client.prompt(sessionId, options.prompt), options.timeoutMs);
|
|
3515
3914
|
});
|
|
3915
|
+
const sessionId = createdSession.sessionId;
|
|
3916
|
+
await applyRequestedModelIfAdvertised({
|
|
3917
|
+
client,
|
|
3918
|
+
sessionId,
|
|
3919
|
+
requestedModel: options.sessionOptions?.model,
|
|
3920
|
+
models: createdSession.models,
|
|
3921
|
+
timeoutMs: options.timeoutMs
|
|
3922
|
+
});
|
|
3923
|
+
output.setContext({ sessionId });
|
|
3924
|
+
const maxRetries = options.promptRetries ?? 0;
|
|
3925
|
+
let response;
|
|
3926
|
+
promptTurnActive = true;
|
|
3927
|
+
for (let attempt = 0;; attempt++) try {
|
|
3928
|
+
response = await measurePerf("runtime.exec.prompt", async () => {
|
|
3929
|
+
return await withTimeout(client.prompt(sessionId, options.prompt), options.timeoutMs);
|
|
3930
|
+
});
|
|
3931
|
+
break;
|
|
3932
|
+
} catch (error) {
|
|
3933
|
+
if (attempt < maxRetries && !promptTurnHadSideEffects && isRetryablePromptError(error)) {
|
|
3934
|
+
const delayMs = Math.min(1e3 * 2 ** attempt, 1e4);
|
|
3935
|
+
emitPromptRetryNotice({
|
|
3936
|
+
error,
|
|
3937
|
+
delayMs,
|
|
3938
|
+
attempt: attempt + 1,
|
|
3939
|
+
maxRetries,
|
|
3940
|
+
suppressSdkConsoleErrors: options.suppressSdkConsoleErrors
|
|
3941
|
+
});
|
|
3942
|
+
await waitMs$1(delayMs);
|
|
3943
|
+
if (!promptTurnHadSideEffects) continue;
|
|
3944
|
+
}
|
|
3945
|
+
promptTurnActive = false;
|
|
3946
|
+
throw error;
|
|
3947
|
+
}
|
|
3948
|
+
promptTurnActive = false;
|
|
3516
3949
|
output.flush();
|
|
3517
3950
|
return toPromptResult(response.stopReason, sessionId, client);
|
|
3518
3951
|
}, async () => {
|
|
@@ -3523,7 +3956,78 @@ async function runOnce(options) {
|
|
|
3523
3956
|
await client.close();
|
|
3524
3957
|
}
|
|
3525
3958
|
}
|
|
3526
|
-
async function
|
|
3959
|
+
async function createSessionRecordWithClient(client, options) {
|
|
3960
|
+
const cwd = absolutePath(options.cwd);
|
|
3961
|
+
await measurePerf("runtime.session_create.start", async () => {
|
|
3962
|
+
await withTimeout(client.start(), options.timeoutMs);
|
|
3963
|
+
});
|
|
3964
|
+
let sessionId;
|
|
3965
|
+
let agentSessionId;
|
|
3966
|
+
let sessionModels;
|
|
3967
|
+
let requestedModelApplied = false;
|
|
3968
|
+
if (options.resumeSessionId) {
|
|
3969
|
+
if (!client.supportsLoadSession()) throw new Error(`Agent command "${options.agentCommand}" does not support session/load; cannot resume session ${options.resumeSessionId}`);
|
|
3970
|
+
try {
|
|
3971
|
+
const loadedSession = await withTimeout(client.loadSession(options.resumeSessionId, cwd), options.timeoutMs);
|
|
3972
|
+
sessionId = options.resumeSessionId;
|
|
3973
|
+
agentSessionId = normalizeRuntimeSessionId(loadedSession.agentSessionId);
|
|
3974
|
+
sessionModels = loadedSession.models;
|
|
3975
|
+
requestedModelApplied = await applyRequestedModelIfAdvertised({
|
|
3976
|
+
client,
|
|
3977
|
+
sessionId,
|
|
3978
|
+
requestedModel: options.sessionOptions?.model,
|
|
3979
|
+
models: loadedSession.models,
|
|
3980
|
+
timeoutMs: options.timeoutMs
|
|
3981
|
+
});
|
|
3982
|
+
} catch (error) {
|
|
3983
|
+
throw new Error(`Failed to resume ACP session ${options.resumeSessionId}: ${formatErrorMessage(error)}`, { cause: error });
|
|
3984
|
+
}
|
|
3985
|
+
} else {
|
|
3986
|
+
const createdSession = await measurePerf("runtime.session_create.create_session", async () => {
|
|
3987
|
+
return await withTimeout(client.createSession(cwd), options.timeoutMs);
|
|
3988
|
+
});
|
|
3989
|
+
sessionId = createdSession.sessionId;
|
|
3990
|
+
agentSessionId = normalizeRuntimeSessionId(createdSession.agentSessionId);
|
|
3991
|
+
sessionModels = createdSession.models;
|
|
3992
|
+
requestedModelApplied = await applyRequestedModelIfAdvertised({
|
|
3993
|
+
client,
|
|
3994
|
+
sessionId,
|
|
3995
|
+
requestedModel: options.sessionOptions?.model,
|
|
3996
|
+
models: createdSession.models,
|
|
3997
|
+
timeoutMs: options.timeoutMs
|
|
3998
|
+
});
|
|
3999
|
+
}
|
|
4000
|
+
const lifecycle = client.getAgentLifecycleSnapshot();
|
|
4001
|
+
const now = isoNow();
|
|
4002
|
+
const record = {
|
|
4003
|
+
schema: SESSION_RECORD_SCHEMA,
|
|
4004
|
+
acpxRecordId: sessionId,
|
|
4005
|
+
acpSessionId: sessionId,
|
|
4006
|
+
agentSessionId,
|
|
4007
|
+
agentCommand: options.agentCommand,
|
|
4008
|
+
cwd,
|
|
4009
|
+
name: normalizeName(options.name),
|
|
4010
|
+
createdAt: now,
|
|
4011
|
+
lastUsedAt: now,
|
|
4012
|
+
lastSeq: 0,
|
|
4013
|
+
lastRequestId: void 0,
|
|
4014
|
+
eventLog: defaultSessionEventLog(sessionId),
|
|
4015
|
+
closed: false,
|
|
4016
|
+
closedAt: void 0,
|
|
4017
|
+
pid: lifecycle.pid,
|
|
4018
|
+
agentStartedAt: lifecycle.startedAt,
|
|
4019
|
+
protocolVersion: client.initializeResult?.protocolVersion,
|
|
4020
|
+
agentCapabilities: client.initializeResult?.agentCapabilities,
|
|
4021
|
+
...createSessionConversation(now),
|
|
4022
|
+
acpx: {}
|
|
4023
|
+
};
|
|
4024
|
+
persistSessionOptions(record, options.sessionOptions);
|
|
4025
|
+
syncAdvertisedModelState(record, sessionModels);
|
|
4026
|
+
if (requestedModelApplied) setCurrentModelId(record, options.sessionOptions?.model);
|
|
4027
|
+
await writeSessionRecord(record);
|
|
4028
|
+
return record;
|
|
4029
|
+
}
|
|
4030
|
+
async function createSessionWithClient(options) {
|
|
3527
4031
|
const client = new AcpClient({
|
|
3528
4032
|
agentCommand: options.agentCommand,
|
|
3529
4033
|
cwd: absolutePath(options.cwd),
|
|
@@ -3536,56 +4040,23 @@ async function createSession(options) {
|
|
|
3536
4040
|
sessionOptions: options.sessionOptions
|
|
3537
4041
|
});
|
|
3538
4042
|
try {
|
|
3539
|
-
return
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
const createdSession = await measurePerf("runtime.session_create.create_session", async () => await withTimeout(client.createSession(cwd), options.timeoutMs));
|
|
3557
|
-
sessionId = createdSession.sessionId;
|
|
3558
|
-
agentSessionId = normalizeRuntimeSessionId(createdSession.agentSessionId);
|
|
3559
|
-
}
|
|
3560
|
-
const lifecycle = client.getAgentLifecycleSnapshot();
|
|
3561
|
-
const now = isoNow();
|
|
3562
|
-
const record = {
|
|
3563
|
-
schema: SESSION_RECORD_SCHEMA,
|
|
3564
|
-
acpxRecordId: sessionId,
|
|
3565
|
-
acpSessionId: sessionId,
|
|
3566
|
-
agentSessionId,
|
|
3567
|
-
agentCommand: options.agentCommand,
|
|
3568
|
-
cwd,
|
|
3569
|
-
name: normalizeName(options.name),
|
|
3570
|
-
createdAt: now,
|
|
3571
|
-
lastUsedAt: now,
|
|
3572
|
-
lastSeq: 0,
|
|
3573
|
-
lastRequestId: void 0,
|
|
3574
|
-
eventLog: defaultSessionEventLog(sessionId),
|
|
3575
|
-
closed: false,
|
|
3576
|
-
closedAt: void 0,
|
|
3577
|
-
pid: lifecycle.pid,
|
|
3578
|
-
agentStartedAt: lifecycle.startedAt,
|
|
3579
|
-
protocolVersion: client.initializeResult?.protocolVersion,
|
|
3580
|
-
agentCapabilities: client.initializeResult?.agentCapabilities,
|
|
3581
|
-
...createSessionConversation(now),
|
|
3582
|
-
acpx: {}
|
|
3583
|
-
};
|
|
3584
|
-
await writeSessionRecord(record);
|
|
3585
|
-
return record;
|
|
3586
|
-
}, async () => {
|
|
3587
|
-
await client.close();
|
|
3588
|
-
});
|
|
4043
|
+
return {
|
|
4044
|
+
record: await withInterrupt(async () => {
|
|
4045
|
+
return await createSessionRecordWithClient(client, options);
|
|
4046
|
+
}, async () => {
|
|
4047
|
+
await client.close();
|
|
4048
|
+
}),
|
|
4049
|
+
client
|
|
4050
|
+
};
|
|
4051
|
+
} catch (error) {
|
|
4052
|
+
await client.close();
|
|
4053
|
+
throw error;
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
async function createSession(options) {
|
|
4057
|
+
const { record, client } = await createSessionWithClient(options);
|
|
4058
|
+
try {
|
|
4059
|
+
return record;
|
|
3589
4060
|
} finally {
|
|
3590
4061
|
await client.close();
|
|
3591
4062
|
}
|
|
@@ -3600,10 +4071,26 @@ async function ensureSession(options) {
|
|
|
3600
4071
|
name: options.name,
|
|
3601
4072
|
boundary: walkBoundary
|
|
3602
4073
|
});
|
|
3603
|
-
if (existing)
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
4074
|
+
if (existing) {
|
|
4075
|
+
const requestedModel = options.sessionOptions?.model;
|
|
4076
|
+
if (requestedModel) return {
|
|
4077
|
+
record: (await setSessionModel({
|
|
4078
|
+
sessionId: existing.acpxRecordId,
|
|
4079
|
+
modelId: requestedModel,
|
|
4080
|
+
mcpServers: options.mcpServers,
|
|
4081
|
+
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
4082
|
+
authCredentials: options.authCredentials,
|
|
4083
|
+
authPolicy: options.authPolicy,
|
|
4084
|
+
timeoutMs: options.timeoutMs,
|
|
4085
|
+
verbose: options.verbose
|
|
4086
|
+
})).record,
|
|
4087
|
+
created: false
|
|
4088
|
+
};
|
|
4089
|
+
return {
|
|
4090
|
+
record: existing,
|
|
4091
|
+
created: false
|
|
4092
|
+
};
|
|
4093
|
+
}
|
|
3607
4094
|
return {
|
|
3608
4095
|
record: await createSession({
|
|
3609
4096
|
agentCommand: options.agentCommand,
|
|
@@ -3647,12 +4134,13 @@ async function runSessionQueueOwner(options) {
|
|
|
3647
4134
|
agentCommand: sessionRecord.agentCommand,
|
|
3648
4135
|
cwd: absolutePath(sessionRecord.cwd),
|
|
3649
4136
|
mcpServers: options.mcpServers,
|
|
3650
|
-
permissionMode:
|
|
4137
|
+
permissionMode: options.permissionMode,
|
|
3651
4138
|
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
3652
4139
|
authCredentials: options.authCredentials,
|
|
3653
4140
|
authPolicy: options.authPolicy,
|
|
3654
4141
|
suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,
|
|
3655
|
-
verbose: options.verbose
|
|
4142
|
+
verbose: options.verbose,
|
|
4143
|
+
sessionOptions: sessionOptionsFromRecord(sessionRecord)
|
|
3656
4144
|
});
|
|
3657
4145
|
const ttlMs = normalizeQueueOwnerTtlMs(options.ttlMs);
|
|
3658
4146
|
const maxQueueDepth = Math.max(1, Math.round(options.maxQueueDepth ?? 16));
|
|
@@ -3672,6 +4160,18 @@ async function runSessionQueueOwner(options) {
|
|
|
3672
4160
|
verbose: options.verbose
|
|
3673
4161
|
});
|
|
3674
4162
|
},
|
|
4163
|
+
setSessionModelFallback: async (modelId, timeoutMs) => {
|
|
4164
|
+
await runSessionSetModelDirect({
|
|
4165
|
+
sessionRecordId: options.sessionId,
|
|
4166
|
+
modelId,
|
|
4167
|
+
mcpServers: options.mcpServers,
|
|
4168
|
+
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
4169
|
+
authCredentials: options.authCredentials,
|
|
4170
|
+
authPolicy: options.authPolicy,
|
|
4171
|
+
timeoutMs,
|
|
4172
|
+
verbose: options.verbose
|
|
4173
|
+
});
|
|
4174
|
+
},
|
|
3675
4175
|
setSessionConfigOptionFallback: async (configId, value, timeoutMs) => {
|
|
3676
4176
|
return (await runSessionSetConfigOptionDirect({
|
|
3677
4177
|
sessionRecordId: options.sessionId,
|
|
@@ -3719,6 +4219,9 @@ async function runSessionQueueOwner(options) {
|
|
|
3719
4219
|
setSessionMode: async (modeId, timeoutMs) => {
|
|
3720
4220
|
await turnController.setSessionMode(modeId, timeoutMs);
|
|
3721
4221
|
},
|
|
4222
|
+
setSessionModel: async (modelId, timeoutMs) => {
|
|
4223
|
+
await turnController.setSessionModel(modelId, timeoutMs);
|
|
4224
|
+
},
|
|
3722
4225
|
setSessionConfigOption: async (configId, value, timeoutMs) => {
|
|
3723
4226
|
return await turnController.setSessionConfigOption(configId, value, timeoutMs);
|
|
3724
4227
|
}
|
|
@@ -3750,6 +4253,7 @@ async function runSessionQueueOwner(options) {
|
|
|
3750
4253
|
authCredentials: options.authCredentials,
|
|
3751
4254
|
authPolicy: options.authPolicy,
|
|
3752
4255
|
suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,
|
|
4256
|
+
promptRetries: options.promptRetries,
|
|
3753
4257
|
onClientAvailable: setActiveController,
|
|
3754
4258
|
onClientClosed: clearActiveController,
|
|
3755
4259
|
onPromptActive: async () => {
|
|
@@ -3788,6 +4292,26 @@ async function sendSession(options) {
|
|
|
3788
4292
|
}
|
|
3789
4293
|
throw new Error(`Session queue owner failed to start for session ${options.sessionId}`);
|
|
3790
4294
|
}
|
|
4295
|
+
async function sendSessionDirect(options) {
|
|
4296
|
+
return await runSessionPrompt({
|
|
4297
|
+
sessionRecordId: options.sessionId,
|
|
4298
|
+
prompt: options.prompt,
|
|
4299
|
+
mcpServers: options.mcpServers,
|
|
4300
|
+
permissionMode: options.permissionMode,
|
|
4301
|
+
resumePolicy: options.resumePolicy,
|
|
4302
|
+
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
4303
|
+
authCredentials: options.authCredentials,
|
|
4304
|
+
authPolicy: options.authPolicy,
|
|
4305
|
+
outputFormatter: options.outputFormatter,
|
|
4306
|
+
onAcpMessage: options.onAcpMessage,
|
|
4307
|
+
onSessionUpdate: options.onSessionUpdate,
|
|
4308
|
+
onClientOperation: options.onClientOperation,
|
|
4309
|
+
timeoutMs: options.timeoutMs,
|
|
4310
|
+
suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,
|
|
4311
|
+
verbose: options.verbose,
|
|
4312
|
+
client: options.client
|
|
4313
|
+
});
|
|
4314
|
+
}
|
|
3791
4315
|
async function cancelSessionPrompt(options) {
|
|
3792
4316
|
const cancelled = await tryCancelOnRunningOwner(options);
|
|
3793
4317
|
return {
|
|
@@ -3816,6 +4340,28 @@ async function setSessionMode(options) {
|
|
|
3816
4340
|
verbose: options.verbose
|
|
3817
4341
|
});
|
|
3818
4342
|
}
|
|
4343
|
+
async function setSessionModel(options) {
|
|
4344
|
+
if (await trySetModelOnRunningOwner(options.sessionId, options.modelId, options.timeoutMs, options.verbose)) {
|
|
4345
|
+
const record = await resolveSessionRecord(options.sessionId);
|
|
4346
|
+
setDesiredModelId(record, options.modelId);
|
|
4347
|
+
setCurrentModelId(record, options.modelId);
|
|
4348
|
+
await writeSessionRecord(record);
|
|
4349
|
+
return {
|
|
4350
|
+
record,
|
|
4351
|
+
resumed: false
|
|
4352
|
+
};
|
|
4353
|
+
}
|
|
4354
|
+
return await runSessionSetModelDirect({
|
|
4355
|
+
sessionRecordId: options.sessionId,
|
|
4356
|
+
modelId: options.modelId,
|
|
4357
|
+
mcpServers: options.mcpServers,
|
|
4358
|
+
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
4359
|
+
authCredentials: options.authCredentials,
|
|
4360
|
+
authPolicy: options.authPolicy,
|
|
4361
|
+
timeoutMs: options.timeoutMs,
|
|
4362
|
+
verbose: options.verbose
|
|
4363
|
+
});
|
|
4364
|
+
}
|
|
3819
4365
|
async function setSessionConfigOption(options) {
|
|
3820
4366
|
const ownerResponse = await trySetConfigOptionOnRunningOwner(options.sessionId, options.configId, options.value, options.timeoutMs, options.verbose);
|
|
3821
4367
|
if (ownerResponse) {
|
|
@@ -3882,6 +4428,7 @@ var session_exports = /* @__PURE__ */ __exportAll({
|
|
|
3882
4428
|
cancelSessionPrompt: () => cancelSessionPrompt,
|
|
3883
4429
|
closeSession: () => closeSession,
|
|
3884
4430
|
createSession: () => createSession,
|
|
4431
|
+
createSessionWithClient: () => createSessionWithClient,
|
|
3885
4432
|
ensureSession: () => ensureSession,
|
|
3886
4433
|
findGitRepositoryRoot: () => findGitRepositoryRoot,
|
|
3887
4434
|
findSession: () => findSession,
|
|
@@ -3893,10 +4440,12 @@ var session_exports = /* @__PURE__ */ __exportAll({
|
|
|
3893
4440
|
runOnce: () => runOnce,
|
|
3894
4441
|
runSessionQueueOwner: () => runSessionQueueOwner,
|
|
3895
4442
|
sendSession: () => sendSession,
|
|
4443
|
+
sendSessionDirect: () => sendSessionDirect,
|
|
3896
4444
|
setSessionConfigOption: () => setSessionConfigOption,
|
|
3897
|
-
setSessionMode: () => setSessionMode
|
|
4445
|
+
setSessionMode: () => setSessionMode,
|
|
4446
|
+
setSessionModel: () => setSessionModel
|
|
3898
4447
|
});
|
|
3899
4448
|
//#endregion
|
|
3900
|
-
export {
|
|
4449
|
+
export { TimeoutError as C, permissionModeSatisfies as E, InterruptedError as S, withTimeout as T, recordClientOperation as _, runOnce as a, flushPerfMetricsCapture as b, buildQueueOwnerArgOverride as c, findSession as d, findSessionByDirectoryWalk as f, createSessionConversation as g, cloneSessionAcpxState as h, createSessionWithClient as i, DEFAULT_HISTORY_LIMIT as l, defaultSessionEventLog as m, DEFAULT_QUEUE_OWNER_TTL_MS as n, runSessionQueueOwner as o, resolveSessionRecord as p, cancelSessionPrompt as r, sendSessionDirect as s, session_exports as t, findGitRepositoryRoot as u, recordPromptSubmission as v, withInterrupt as w, installPerfMetricsCapture as x, recordSessionUpdate as y };
|
|
3901
4450
|
|
|
3902
|
-
//# sourceMappingURL=session-
|
|
4451
|
+
//# sourceMappingURL=session-BtpTC2pM.js.map
|