acpx 0.12.1 → 0.13.1
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 +64 -375
- package/dist/{cli-pKoIEH5O.js → cli-_7Sei6dD.js} +5 -4
- package/dist/cli-_7Sei6dD.js.map +1 -0
- package/dist/cli.d.ts +2 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +72 -19
- package/dist/cli.js.map +1 -1
- package/dist/{client-CFo_9MIo.d.ts → client-CxNllqui.d.ts} +17 -3
- package/dist/client-CxNllqui.d.ts.map +1 -0
- package/dist/{flags-CjeFX5ki.js → flags-Ds6FzmHG.js} +36 -9
- package/dist/flags-Ds6FzmHG.js.map +1 -0
- package/dist/{flows-Cym6H3vg.js → flows-fzH0GKYF.js} +14 -4
- package/dist/flows-fzH0GKYF.js.map +1 -0
- package/dist/flows.d.ts +6 -2
- package/dist/flows.d.ts.map +1 -1
- package/dist/flows.js +1 -1
- package/dist/{live-checkpoint-DQp4JSHD.js → live-checkpoint-BSIrfgVo.js} +560 -196
- package/dist/live-checkpoint-BSIrfgVo.js.map +1 -0
- package/dist/{output-fNqTAsFQ.js → output-BZQE0gI1.js} +74 -11
- package/dist/output-BZQE0gI1.js.map +1 -0
- package/dist/runtime.d.ts +106 -19
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +631 -158
- package/dist/runtime.js.map +1 -1
- package/dist/{session-options-C4uYkKDy.d.ts → session-options-DwRDODlr.d.ts} +28 -3
- package/dist/session-options-DwRDODlr.d.ts.map +1 -0
- package/package.json +19 -19
- package/skills/acpx/SKILL.md +5 -2
- package/dist/cli-pKoIEH5O.js.map +0 -1
- package/dist/client-CFo_9MIo.d.ts.map +0 -1
- package/dist/flags-CjeFX5ki.js.map +0 -1
- package/dist/flows-Cym6H3vg.js.map +0 -1
- package/dist/live-checkpoint-DQp4JSHD.js.map +0 -1
- package/dist/output-fNqTAsFQ.js.map +0 -1
- package/dist/session-options-C4uYkKDy.d.ts.map +0 -1
|
@@ -6,9 +6,8 @@ import os from "node:os";
|
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
import { execFile, spawn } from "node:child_process";
|
|
8
8
|
import { Readable, Writable } from "node:stream";
|
|
9
|
-
import {
|
|
9
|
+
import { PROTOCOL_VERSION, client, methods } from "@agentclientprotocol/sdk";
|
|
10
10
|
import readline from "node:readline/promises";
|
|
11
|
-
import { promisify } from "node:util";
|
|
12
11
|
//#region src/errors.ts
|
|
13
12
|
var AcpxOperationalError = class extends Error {
|
|
14
13
|
outputCode;
|
|
@@ -452,9 +451,78 @@ const AGENT_REGISTRY = {
|
|
|
452
451
|
kiro: "kiro-cli-chat acp",
|
|
453
452
|
mux: `npx -y mux@${ACP_ADAPTER_PACKAGE_RANGES.mux} acp`,
|
|
454
453
|
opencode: "npx -y opencode-ai acp",
|
|
454
|
+
pool: "pool acp",
|
|
455
455
|
qoder: "qodercli --acp",
|
|
456
456
|
qwen: "qwen --acp",
|
|
457
|
-
trae: "traecli acp serve"
|
|
457
|
+
trae: "traecli acp serve",
|
|
458
|
+
zeroclaw: "zeroclaw acp"
|
|
459
|
+
};
|
|
460
|
+
const AGENT_ARGV_REGISTRY = {
|
|
461
|
+
pi: ["npx", `pi-acp@${ACP_ADAPTER_PACKAGE_RANGES.pi}`],
|
|
462
|
+
openclaw: ["openclaw", "acp"],
|
|
463
|
+
codex: [
|
|
464
|
+
"npx",
|
|
465
|
+
"-y",
|
|
466
|
+
`@agentclientprotocol/codex-acp@${ACP_ADAPTER_PACKAGE_RANGES.codex}`
|
|
467
|
+
],
|
|
468
|
+
claude: [
|
|
469
|
+
"npx",
|
|
470
|
+
"-y",
|
|
471
|
+
`@agentclientprotocol/claude-agent-acp@${ACP_ADAPTER_PACKAGE_RANGES.claude}`
|
|
472
|
+
],
|
|
473
|
+
gemini: ["gemini", "--acp"],
|
|
474
|
+
cursor: ["cursor-agent", "acp"],
|
|
475
|
+
copilot: [
|
|
476
|
+
"copilot",
|
|
477
|
+
"--acp",
|
|
478
|
+
"--stdio"
|
|
479
|
+
],
|
|
480
|
+
droid: [
|
|
481
|
+
"droid",
|
|
482
|
+
"exec",
|
|
483
|
+
"--output-format",
|
|
484
|
+
"acp"
|
|
485
|
+
],
|
|
486
|
+
"fast-agent": [
|
|
487
|
+
"uvx",
|
|
488
|
+
"fast-agent-mcp",
|
|
489
|
+
"acp"
|
|
490
|
+
],
|
|
491
|
+
"grok-build": [
|
|
492
|
+
"grok",
|
|
493
|
+
"agent",
|
|
494
|
+
"stdio"
|
|
495
|
+
],
|
|
496
|
+
iflow: ["iflow", "--experimental-acp"],
|
|
497
|
+
kilocode: [
|
|
498
|
+
"npx",
|
|
499
|
+
"-y",
|
|
500
|
+
"@kilocode/cli",
|
|
501
|
+
"acp"
|
|
502
|
+
],
|
|
503
|
+
kimi: ["kimi", "acp"],
|
|
504
|
+
kiro: ["kiro-cli-chat", "acp"],
|
|
505
|
+
mux: [
|
|
506
|
+
"npx",
|
|
507
|
+
"-y",
|
|
508
|
+
`mux@${ACP_ADAPTER_PACKAGE_RANGES.mux}`,
|
|
509
|
+
"acp"
|
|
510
|
+
],
|
|
511
|
+
opencode: [
|
|
512
|
+
"npx",
|
|
513
|
+
"-y",
|
|
514
|
+
"opencode-ai",
|
|
515
|
+
"acp"
|
|
516
|
+
],
|
|
517
|
+
pool: ["pool", "acp"],
|
|
518
|
+
qoder: ["qodercli", "--acp"],
|
|
519
|
+
qwen: ["qwen", "--acp"],
|
|
520
|
+
trae: [
|
|
521
|
+
"traecli",
|
|
522
|
+
"acp",
|
|
523
|
+
"serve"
|
|
524
|
+
],
|
|
525
|
+
zeroclaw: ["zeroclaw", "acp"]
|
|
458
526
|
};
|
|
459
527
|
const BUILT_IN_AGENT_PACKAGES = {
|
|
460
528
|
codex: {
|
|
@@ -480,6 +548,10 @@ const DEFAULT_AGENT_NAME = "codex";
|
|
|
480
548
|
function normalizeAgentName$1(value) {
|
|
481
549
|
return value.trim().toLowerCase();
|
|
482
550
|
}
|
|
551
|
+
function resolveCanonicalAgentName(value) {
|
|
552
|
+
const normalized = normalizeAgentName$1(value);
|
|
553
|
+
return AGENT_ALIASES[normalized] ?? normalized;
|
|
554
|
+
}
|
|
483
555
|
function mergeAgentRegistry(overrides) {
|
|
484
556
|
if (!overrides) return { ...AGENT_REGISTRY };
|
|
485
557
|
const merged = { ...AGENT_REGISTRY };
|
|
@@ -495,6 +567,11 @@ function resolveAgentCommand(agentName, overrides) {
|
|
|
495
567
|
const registry = mergeAgentRegistry(overrides);
|
|
496
568
|
return registry[normalized] ?? registry[AGENT_ALIASES[normalized] ?? normalized] ?? agentName;
|
|
497
569
|
}
|
|
570
|
+
function resolveAgentArgv(agentName) {
|
|
571
|
+
const normalized = normalizeAgentName$1(agentName);
|
|
572
|
+
const argv = AGENT_ARGV_REGISTRY[normalized] ?? AGENT_ARGV_REGISTRY[resolveCanonicalAgentName(agentName)];
|
|
573
|
+
return argv ? [...argv] : void 0;
|
|
574
|
+
}
|
|
498
575
|
function findBuiltInAgentPackage(agentCommand) {
|
|
499
576
|
const normalized = agentCommand.trim();
|
|
500
577
|
return Object.values(BUILT_IN_AGENT_PACKAGES).find((spec) => spec.fallbackCommand === normalized || spec.legacyFallbackCommands?.includes(normalized));
|
|
@@ -593,7 +670,7 @@ function resolveBuiltInAgentLaunch(agentCommand, options = {}) {
|
|
|
593
670
|
return resolveInstalledBuiltInAgentLaunch(agentCommand, options) ?? resolvePackageExecBuiltInAgentLaunch(agentCommand, options);
|
|
594
671
|
}
|
|
595
672
|
function listBuiltInAgents(overrides) {
|
|
596
|
-
return Object.keys(
|
|
673
|
+
return [.../* @__PURE__ */ new Set([...Object.keys(AGENT_REGISTRY), ...Object.keys(overrides ?? {})])];
|
|
597
674
|
}
|
|
598
675
|
//#endregion
|
|
599
676
|
//#region src/async-control.ts
|
|
@@ -972,6 +1049,7 @@ function serializeSessionRecordForDisk(record) {
|
|
|
972
1049
|
acp_session_id: canonical.acpSessionId,
|
|
973
1050
|
agent_session_id: normalizeRuntimeSessionId(canonical.agentSessionId),
|
|
974
1051
|
agent_command: canonical.agentCommand,
|
|
1052
|
+
agent_argv: canonical.agentArgv,
|
|
975
1053
|
cwd: canonical.cwd,
|
|
976
1054
|
name: canonical.name,
|
|
977
1055
|
created_at: canonical.createdAt,
|
|
@@ -1006,6 +1084,50 @@ function serializeSessionRecordForDisk(record) {
|
|
|
1006
1084
|
};
|
|
1007
1085
|
}
|
|
1008
1086
|
//#endregion
|
|
1087
|
+
//#region src/acp/builtin-command-migration.ts
|
|
1088
|
+
const LEGACY_AGENT_COMMANDS = {
|
|
1089
|
+
pi: [
|
|
1090
|
+
"npx pi-acp",
|
|
1091
|
+
"npx pi-acp@^0.0.22",
|
|
1092
|
+
"npx pi-acp@^0.0.26"
|
|
1093
|
+
],
|
|
1094
|
+
codex: [
|
|
1095
|
+
"npx @zed-industries/codex-acp",
|
|
1096
|
+
"npx @zed-industries/codex-acp@^0.9.5",
|
|
1097
|
+
"npx @zed-industries/codex-acp@^0.10.0",
|
|
1098
|
+
"npx @zed-industries/codex-acp@^0.11.1",
|
|
1099
|
+
"npx @zed-industries/codex-acp@^0.12.0",
|
|
1100
|
+
"npx -y @agentclientprotocol/codex-acp@^0.0.44",
|
|
1101
|
+
"npx -y @agentclientprotocol/codex-acp@^1.1.4"
|
|
1102
|
+
],
|
|
1103
|
+
claude: [
|
|
1104
|
+
"npx @zed-industries/claude-agent-acp",
|
|
1105
|
+
"npx -y @zed-industries/claude-agent-acp",
|
|
1106
|
+
"npx -y @zed-industries/claude-agent-acp@^0.21.0",
|
|
1107
|
+
"npx -y @zed-industries/claude-agent-acp@^0.23.1",
|
|
1108
|
+
"npx -y @zed-industries/claude-agent-acp@^0.24.2",
|
|
1109
|
+
"npx -y @zed-industries/claude-agent-acp@^0.25.0",
|
|
1110
|
+
"npx -y @zed-industries/claude-agent-acp@^0.31.0",
|
|
1111
|
+
"npx -y @agentclientprotocol/claude-agent-acp@^0.36.1",
|
|
1112
|
+
"npx -y @agentclientprotocol/claude-agent-acp@^0.37.0",
|
|
1113
|
+
"npm exec @agentclientprotocol/claude-agent-acp@^0.36.1",
|
|
1114
|
+
"npm exec @agentclientprotocol/claude-agent-acp@^0.37.0"
|
|
1115
|
+
],
|
|
1116
|
+
gemini: ["gemini", "gemini --experimental-acp"],
|
|
1117
|
+
kiro: ["kiro-cli acp"],
|
|
1118
|
+
mux: ["npx -y mux@^0.27.0 acp"],
|
|
1119
|
+
opencode: ["npx opencode-ai"]
|
|
1120
|
+
};
|
|
1121
|
+
function currentArgv(name) {
|
|
1122
|
+
const argv = AGENT_ARGV_REGISTRY[name];
|
|
1123
|
+
return argv ? [...argv] : void 0;
|
|
1124
|
+
}
|
|
1125
|
+
function resolveAgentArgvForCommand(agentCommand) {
|
|
1126
|
+
for (const [name, command] of Object.entries(AGENT_REGISTRY)) if (command === agentCommand) return currentArgv(name);
|
|
1127
|
+
for (const [name, spec] of Object.entries(BUILT_IN_AGENT_PACKAGES)) if ((spec.legacyFallbackCommands ?? []).includes(agentCommand)) return currentArgv(name);
|
|
1128
|
+
for (const [name, commands] of Object.entries(LEGACY_AGENT_COMMANDS)) if (commands.includes(agentCommand)) return currentArgv(name);
|
|
1129
|
+
}
|
|
1130
|
+
//#endregion
|
|
1009
1131
|
//#region src/session/persistence/parse.ts
|
|
1010
1132
|
function asRecord$4(value) {
|
|
1011
1133
|
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
@@ -1017,6 +1139,12 @@ function hasOwn$1(source, key) {
|
|
|
1017
1139
|
function isStringArray(value) {
|
|
1018
1140
|
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
1019
1141
|
}
|
|
1142
|
+
function parseOptionalAgentArgv(value) {
|
|
1143
|
+
return isStringArray(value) && value.length > 0 && value[0]?.length > 0 ? value : void 0;
|
|
1144
|
+
}
|
|
1145
|
+
function parsePersistedAgentArgv(record) {
|
|
1146
|
+
return parseOptionalAgentArgv(record.agent_argv) ?? (typeof record.agent_command === "string" ? resolveAgentArgvForCommand(record.agent_command) : void 0);
|
|
1147
|
+
}
|
|
1020
1148
|
function hasModelConfigOption(options) {
|
|
1021
1149
|
if (!Array.isArray(options)) return false;
|
|
1022
1150
|
return options.some((entry) => {
|
|
@@ -1394,6 +1522,7 @@ function parseSessionRecord(raw) {
|
|
|
1394
1522
|
acpSessionId: record.acp_session_id,
|
|
1395
1523
|
agentSessionId: normalizeRuntimeSessionId(record.agent_session_id),
|
|
1396
1524
|
agentCommand: record.agent_command,
|
|
1525
|
+
agentArgv: parsePersistedAgentArgv(record),
|
|
1397
1526
|
cwd: record.cwd,
|
|
1398
1527
|
name: optionals.name,
|
|
1399
1528
|
createdAt: record.created_at,
|
|
@@ -1589,6 +1718,12 @@ function assertPersistedKeyPolicy(value) {
|
|
|
1589
1718
|
throw new Error(`Persisted key policy violation (expected snake_case keys): ${violations.join(", ")}`);
|
|
1590
1719
|
}
|
|
1591
1720
|
//#endregion
|
|
1721
|
+
//#region src/session/persistence/atomic-write.ts
|
|
1722
|
+
function createAtomicWriteTempPath(filePath, createUniqueId = randomUUID) {
|
|
1723
|
+
const tempName = `.acpx-write.${process.pid}.${Date.now()}.${createUniqueId()}.tmp`;
|
|
1724
|
+
return path.join(path.dirname(filePath), tempName);
|
|
1725
|
+
}
|
|
1726
|
+
//#endregion
|
|
1592
1727
|
//#region src/session/persistence/index.ts
|
|
1593
1728
|
const SESSION_INDEX_SCHEMA = "acpx.session-index.v1";
|
|
1594
1729
|
function asRecord$3(value) {
|
|
@@ -1657,7 +1792,7 @@ async function readSessionIndex(sessionDir) {
|
|
|
1657
1792
|
}
|
|
1658
1793
|
async function writeSessionIndex(sessionDir, index) {
|
|
1659
1794
|
const filePath = sessionIndexPath(sessionDir);
|
|
1660
|
-
const tempFile =
|
|
1795
|
+
const tempFile = createAtomicWriteTempPath(filePath);
|
|
1661
1796
|
const payload = JSON.stringify({
|
|
1662
1797
|
schema: SESSION_INDEX_SCHEMA,
|
|
1663
1798
|
files: [...index.files].toSorted(),
|
|
@@ -1728,7 +1863,7 @@ async function writeSessionRecord(record) {
|
|
|
1728
1863
|
const persisted = serializeSessionRecordForDisk(record);
|
|
1729
1864
|
assertPersistedKeyPolicy(persisted);
|
|
1730
1865
|
const file = sessionFilePath(record.acpxRecordId);
|
|
1731
|
-
const tempFile =
|
|
1866
|
+
const tempFile = createAtomicWriteTempPath(file);
|
|
1732
1867
|
const payload = JSON.stringify(persisted, null, 2);
|
|
1733
1868
|
await fs$1.writeFile(tempFile, `${payload}\n`, "utf8");
|
|
1734
1869
|
await fs$1.rename(tempFile, file);
|
|
@@ -2394,6 +2529,36 @@ function shouldUseWindowsBatchShell(command, platform = process.platform, env =
|
|
|
2394
2529
|
const ext = path.extname(resolvedCommand).toLowerCase();
|
|
2395
2530
|
return ext === ".cmd" || ext === ".bat";
|
|
2396
2531
|
}
|
|
2532
|
+
const CMD_META_CHAR_RE = /([()\][%!^"`<>&|;, *?])/gu;
|
|
2533
|
+
const CMD_BACKSLASH_QUOTE_RE = /(?=(\\+?)?)\1"/gu;
|
|
2534
|
+
const CMD_TRAILING_BACKSLASH_RE = /(?=(\\+?)?)\1$/gu;
|
|
2535
|
+
const CMD_SHIM_RE = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/iu;
|
|
2536
|
+
function escapeCmdCommand(value) {
|
|
2537
|
+
return value.replace(CMD_META_CHAR_RE, "^$1");
|
|
2538
|
+
}
|
|
2539
|
+
function escapeCmdArgument(value, doubleEscapeMeta) {
|
|
2540
|
+
const escaped = `"${value.replace(CMD_BACKSLASH_QUOTE_RE, "$1$1\\\"").replace(CMD_TRAILING_BACKSLASH_RE, "$1$1")}"`.replace(CMD_META_CHAR_RE, "^$1");
|
|
2541
|
+
return doubleEscapeMeta ? escaped.replace(CMD_META_CHAR_RE, "^$1") : escaped;
|
|
2542
|
+
}
|
|
2543
|
+
function buildAgentSpawnCommand(command, args, platform = process.platform, env = process.env) {
|
|
2544
|
+
if (!shouldUseWindowsBatchShell(command, platform, env)) return {
|
|
2545
|
+
command,
|
|
2546
|
+
args: [...args]
|
|
2547
|
+
};
|
|
2548
|
+
const resolvedCommand = path.win32.normalize(resolveWindowsCommand(command, env) ?? command);
|
|
2549
|
+
const doubleEscapeMeta = CMD_SHIM_RE.test(resolvedCommand);
|
|
2550
|
+
const shellCommand = [escapeCmdCommand(resolvedCommand), ...args.map((arg) => escapeCmdArgument(arg, doubleEscapeMeta))].join(" ");
|
|
2551
|
+
return {
|
|
2552
|
+
command: readWindowsEnvValue(env, "COMSPEC") ?? "cmd.exe",
|
|
2553
|
+
args: [
|
|
2554
|
+
"/d",
|
|
2555
|
+
"/s",
|
|
2556
|
+
"/c",
|
|
2557
|
+
`"${shellCommand}"`
|
|
2558
|
+
],
|
|
2559
|
+
windowsVerbatimArguments: true
|
|
2560
|
+
};
|
|
2561
|
+
}
|
|
2397
2562
|
function buildSpawnCommandOptions(command, options, platform = process.platform, env = process.env) {
|
|
2398
2563
|
if (!shouldUseWindowsBatchShell(command, platform, env)) return options;
|
|
2399
2564
|
return {
|
|
@@ -2468,9 +2633,54 @@ function getAcpxVersion() {
|
|
|
2468
2633
|
cachedVersion = resolveAcpxVersion();
|
|
2469
2634
|
return cachedVersion;
|
|
2470
2635
|
}
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2636
|
+
async function runTimedExecFile(command, args, options = {}) {
|
|
2637
|
+
const timeoutMs = Math.max(1, Math.round(options.timeoutMs ?? 8e3));
|
|
2638
|
+
return await new Promise((resolve, reject) => {
|
|
2639
|
+
let settled = false;
|
|
2640
|
+
let timer;
|
|
2641
|
+
const child = execFile(command, [...args], {
|
|
2642
|
+
encoding: "utf8",
|
|
2643
|
+
maxBuffer: options.maxBufferBytes ?? 33554432,
|
|
2644
|
+
killSignal: "SIGKILL",
|
|
2645
|
+
windowsHide: options.windowsHide
|
|
2646
|
+
}, (error, stdout) => {
|
|
2647
|
+
if (settled) return;
|
|
2648
|
+
settled = true;
|
|
2649
|
+
if (timer) clearTimeout(timer);
|
|
2650
|
+
if (error) {
|
|
2651
|
+
reject(error);
|
|
2652
|
+
return;
|
|
2653
|
+
}
|
|
2654
|
+
resolve(stdout);
|
|
2655
|
+
});
|
|
2656
|
+
timer = setTimeout(() => {
|
|
2657
|
+
if (settled) return;
|
|
2658
|
+
settled = true;
|
|
2659
|
+
const killed = child.kill("SIGKILL");
|
|
2660
|
+
child.stdout?.destroy();
|
|
2661
|
+
child.stderr?.destroy();
|
|
2662
|
+
child.unref();
|
|
2663
|
+
reject(Object.assign(/* @__PURE__ */ new Error(`${command} timed out after ${timeoutMs}ms`), {
|
|
2664
|
+
code: "ETIMEDOUT",
|
|
2665
|
+
killed,
|
|
2666
|
+
signal: "SIGKILL"
|
|
2667
|
+
}));
|
|
2668
|
+
}, timeoutMs);
|
|
2669
|
+
});
|
|
2670
|
+
}
|
|
2671
|
+
function normalizeAgentCommandInput(value) {
|
|
2672
|
+
if (typeof value === "string") return { agentCommand: value };
|
|
2673
|
+
const parts = toCommandParts([...value]);
|
|
2674
|
+
const argv = [parts.command, ...parts.args];
|
|
2675
|
+
return {
|
|
2676
|
+
agentCommand: renderArgvIdentity(argv),
|
|
2677
|
+
agentArgv: argv
|
|
2678
|
+
};
|
|
2679
|
+
}
|
|
2680
|
+
const IDENTITY_SAFE_ARG_RE = /^[A-Za-z0-9_@%+=:,./^~-]+$/u;
|
|
2681
|
+
function renderArgvIdentity(argv) {
|
|
2682
|
+
return argv.map((arg) => IDENTITY_SAFE_ARG_RE.test(arg) ? arg : JSON.stringify(arg)).join(" ");
|
|
2683
|
+
}
|
|
2474
2684
|
function isoNow$1() {
|
|
2475
2685
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2476
2686
|
}
|
|
@@ -2517,6 +2727,18 @@ function waitForChildExit(child, timeoutMs) {
|
|
|
2517
2727
|
child.once("exit", onExitLike);
|
|
2518
2728
|
});
|
|
2519
2729
|
}
|
|
2730
|
+
function resolveAgentCommandParts(value, argv, platform = process.platform) {
|
|
2731
|
+
if (argv) {
|
|
2732
|
+
const parts = toCommandParts([...argv]);
|
|
2733
|
+
assertWindowsLaunchableCommand(parts.command, platform);
|
|
2734
|
+
return parts;
|
|
2735
|
+
}
|
|
2736
|
+
if (platform === "win32") throw new Error("Raw agent command strings are not supported on Windows. Configure the agent with an argv array, for example: \"argv\": [\"agent.exe\", \"--acp\"]. Legacy agents.<name>.args arrays are migrated automatically. Existing sessions without saved argv must be closed and recreated.");
|
|
2737
|
+
return splitCommandLine(value);
|
|
2738
|
+
}
|
|
2739
|
+
function assertWindowsLaunchableCommand(command, platform) {
|
|
2740
|
+
if (platform === "win32" && path.extname(command).toLowerCase() === ".sh") throw new Error(`Windows cannot launch shell script executable "${command}" directly. Configure an explicit interpreter argv, for example: "argv": ["bash", "${command}"]. acpx does not infer interpreters.`);
|
|
2741
|
+
}
|
|
2520
2742
|
function splitCommandLine(value) {
|
|
2521
2743
|
const parts = [];
|
|
2522
2744
|
let current = "";
|
|
@@ -2543,8 +2765,10 @@ function splitCommandLine(value) {
|
|
|
2543
2765
|
}
|
|
2544
2766
|
if (quote) throw new Error("Invalid --agent command: unterminated quote");
|
|
2545
2767
|
if (hasPart) parts.push(current);
|
|
2546
|
-
|
|
2547
|
-
|
|
2768
|
+
return toCommandParts(parts);
|
|
2769
|
+
}
|
|
2770
|
+
function toCommandParts(parts) {
|
|
2771
|
+
if (parts.length === 0 || parts[0] === "") throw new Error("Invalid --agent command: empty command");
|
|
2548
2772
|
return {
|
|
2549
2773
|
command: parts[0],
|
|
2550
2774
|
args: parts.slice(1)
|
|
@@ -2640,8 +2864,7 @@ function isWindowsExecutableCommand(command) {
|
|
|
2640
2864
|
return WINDOWS_EXECUTABLE_EXTENSION_RE.test(normalized);
|
|
2641
2865
|
}
|
|
2642
2866
|
async function runWslpath(cwd) {
|
|
2643
|
-
|
|
2644
|
-
return stdout;
|
|
2867
|
+
return await runTimedExecFile("wslpath", ["-w", cwd]);
|
|
2645
2868
|
}
|
|
2646
2869
|
function basenameToken(value) {
|
|
2647
2870
|
return path.basename(value).toLowerCase().replace(/\.(cmd|exe|bat)$/u, "");
|
|
@@ -3184,6 +3407,7 @@ var TerminalManager = class {
|
|
|
3184
3407
|
usesDefaultConfirmExecute;
|
|
3185
3408
|
confirmExecute;
|
|
3186
3409
|
killGraceMs;
|
|
3410
|
+
processHelperTimeoutMs;
|
|
3187
3411
|
terminals = /* @__PURE__ */ new Map();
|
|
3188
3412
|
constructor(options) {
|
|
3189
3413
|
this.cwd = options.cwd;
|
|
@@ -3193,6 +3417,7 @@ var TerminalManager = class {
|
|
|
3193
3417
|
this.usesDefaultConfirmExecute = options.confirmExecute == null;
|
|
3194
3418
|
this.confirmExecute = options.confirmExecute ?? defaultConfirmExecute;
|
|
3195
3419
|
this.killGraceMs = Math.max(0, Math.round(options.killGraceMs ?? DEFAULT_KILL_GRACE_MS));
|
|
3420
|
+
this.processHelperTimeoutMs = Math.max(1, Math.round(options.processHelperTimeoutMs ?? 8e3));
|
|
3196
3421
|
}
|
|
3197
3422
|
updatePermissionPolicy(permissionMode, nonInteractivePermissions) {
|
|
3198
3423
|
this.permissionMode = permissionMode;
|
|
@@ -3219,6 +3444,7 @@ var TerminalManager = class {
|
|
|
3219
3444
|
process: proc,
|
|
3220
3445
|
killProcessGroup: spawnCommand.killProcessGroup,
|
|
3221
3446
|
descendantPids: /* @__PURE__ */ new Set(),
|
|
3447
|
+
processHelperTimeoutMs: this.processHelperTimeoutMs,
|
|
3222
3448
|
output: Buffer.alloc(0),
|
|
3223
3449
|
truncated: false,
|
|
3224
3450
|
outputByteLimit,
|
|
@@ -3444,7 +3670,7 @@ var TerminalManager = class {
|
|
|
3444
3670
|
}
|
|
3445
3671
|
async captureDescendantPids(terminal, pid) {
|
|
3446
3672
|
if (!this.isRunning(terminal)) await terminal.processGroupSnapshotPromise?.catch(() => {});
|
|
3447
|
-
for (const descendantPid of await listDescendantPids(pid)) terminal.descendantPids.add(descendantPid);
|
|
3673
|
+
for (const descendantPid of await listDescendantPids(pid, terminal.processHelperTimeoutMs)) terminal.descendantPids.add(descendantPid);
|
|
3448
3674
|
}
|
|
3449
3675
|
async waitForCleanupAfterSignal(terminal) {
|
|
3450
3676
|
return await Promise.race([this.waitForTerminalAndTrackedDescendants(terminal).then(() => true), waitMs(this.killGraceMs).then(() => false)]);
|
|
@@ -3497,10 +3723,10 @@ function commandPathExists(command, cwd) {
|
|
|
3497
3723
|
const resolvedPath = path.isAbsolute(command) ? command : path.resolve(cwd, command);
|
|
3498
3724
|
return fs.existsSync(resolvedPath);
|
|
3499
3725
|
}
|
|
3500
|
-
async function listDescendantPids(rootPid) {
|
|
3726
|
+
async function listDescendantPids(rootPid, timeoutMs) {
|
|
3501
3727
|
let output;
|
|
3502
3728
|
try {
|
|
3503
|
-
output = await runProcessListCommand();
|
|
3729
|
+
output = await runProcessListCommand(timeoutMs);
|
|
3504
3730
|
} catch {
|
|
3505
3731
|
return [];
|
|
3506
3732
|
}
|
|
@@ -3533,47 +3759,23 @@ function parseProcessListLine(line) {
|
|
|
3533
3759
|
parentPid
|
|
3534
3760
|
};
|
|
3535
3761
|
}
|
|
3536
|
-
async function runProcessListCommand() {
|
|
3537
|
-
if (process.platform === "win32") return await runWindowsProcessListCommand();
|
|
3538
|
-
return await
|
|
3539
|
-
const child = spawn("ps", ["-eo", "pid=,ppid="], { stdio: [
|
|
3540
|
-
"ignore",
|
|
3541
|
-
"pipe",
|
|
3542
|
-
"pipe"
|
|
3543
|
-
] });
|
|
3544
|
-
let stdout = "";
|
|
3545
|
-
let stderr = "";
|
|
3546
|
-
child.stdout.setEncoding("utf8");
|
|
3547
|
-
child.stderr.setEncoding("utf8");
|
|
3548
|
-
child.stdout.on("data", (chunk) => {
|
|
3549
|
-
stdout += chunk;
|
|
3550
|
-
});
|
|
3551
|
-
child.stderr.on("data", (chunk) => {
|
|
3552
|
-
stderr += chunk;
|
|
3553
|
-
});
|
|
3554
|
-
child.once("error", reject);
|
|
3555
|
-
child.once("close", (code, signal) => {
|
|
3556
|
-
if (code === 0) {
|
|
3557
|
-
resolve(stdout);
|
|
3558
|
-
return;
|
|
3559
|
-
}
|
|
3560
|
-
reject(/* @__PURE__ */ new Error(`ps exited with code ${code ?? "null"} signal ${signal ?? "null"}: ${stderr}`));
|
|
3561
|
-
});
|
|
3562
|
-
});
|
|
3762
|
+
async function runProcessListCommand(timeoutMs) {
|
|
3763
|
+
if (process.platform === "win32") return await runWindowsProcessListCommand(timeoutMs);
|
|
3764
|
+
return await runTimedExecFile("ps", ["-eo", "pid=,ppid="], { timeoutMs });
|
|
3563
3765
|
}
|
|
3564
3766
|
async function rememberProcessGroupPids(terminal) {
|
|
3565
3767
|
const processGroupId = terminal.process.pid;
|
|
3566
3768
|
if (!terminal.killProcessGroup || !processGroupId) return;
|
|
3567
3769
|
if (process.platform === "win32") {
|
|
3568
|
-
for (const pid of await listDescendantPids(processGroupId)) terminal.descendantPids.add(pid);
|
|
3770
|
+
for (const pid of await listDescendantPids(processGroupId, terminal.processHelperTimeoutMs)) terminal.descendantPids.add(pid);
|
|
3569
3771
|
return;
|
|
3570
3772
|
}
|
|
3571
|
-
for (const pid of await listProcessGroupPids(processGroupId)) if (pid !== processGroupId) terminal.descendantPids.add(pid);
|
|
3773
|
+
for (const pid of await listProcessGroupPids(processGroupId, terminal.processHelperTimeoutMs)) if (pid !== processGroupId) terminal.descendantPids.add(pid);
|
|
3572
3774
|
}
|
|
3573
|
-
async function listProcessGroupPids(processGroupId) {
|
|
3775
|
+
async function listProcessGroupPids(processGroupId, timeoutMs) {
|
|
3574
3776
|
let output;
|
|
3575
3777
|
try {
|
|
3576
|
-
output = await runProcessGroupListCommand();
|
|
3778
|
+
output = await runProcessGroupListCommand(timeoutMs);
|
|
3577
3779
|
} catch {
|
|
3578
3780
|
return [];
|
|
3579
3781
|
}
|
|
@@ -3587,66 +3789,18 @@ async function listProcessGroupPids(processGroupId) {
|
|
|
3587
3789
|
}
|
|
3588
3790
|
return pids;
|
|
3589
3791
|
}
|
|
3590
|
-
async function runProcessGroupListCommand() {
|
|
3591
|
-
return await
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
stdout += chunk;
|
|
3603
|
-
});
|
|
3604
|
-
child.stderr.on("data", (chunk) => {
|
|
3605
|
-
stderr += chunk;
|
|
3606
|
-
});
|
|
3607
|
-
child.once("error", reject);
|
|
3608
|
-
child.once("close", (code, signal) => {
|
|
3609
|
-
if (code === 0) {
|
|
3610
|
-
resolve(stdout);
|
|
3611
|
-
return;
|
|
3612
|
-
}
|
|
3613
|
-
reject(/* @__PURE__ */ new Error(`ps exited with code ${code ?? "null"} signal ${signal ?? "null"}: ${stderr}`));
|
|
3614
|
-
});
|
|
3615
|
-
});
|
|
3616
|
-
}
|
|
3617
|
-
async function runWindowsProcessListCommand() {
|
|
3618
|
-
return await new Promise((resolve, reject) => {
|
|
3619
|
-
const child = spawn("powershell.exe", [
|
|
3620
|
-
"-NoProfile",
|
|
3621
|
-
"-NonInteractive",
|
|
3622
|
-
"-Command",
|
|
3623
|
-
["Get-CimInstance Win32_Process |", "ForEach-Object { \"$($_.ProcessId) $($_.ParentProcessId)\" }"].join(" ")
|
|
3624
|
-
], {
|
|
3625
|
-
stdio: [
|
|
3626
|
-
"ignore",
|
|
3627
|
-
"pipe",
|
|
3628
|
-
"pipe"
|
|
3629
|
-
],
|
|
3630
|
-
windowsHide: true
|
|
3631
|
-
});
|
|
3632
|
-
let stdout = "";
|
|
3633
|
-
let stderr = "";
|
|
3634
|
-
child.stdout.setEncoding("utf8");
|
|
3635
|
-
child.stderr.setEncoding("utf8");
|
|
3636
|
-
child.stdout.on("data", (chunk) => {
|
|
3637
|
-
stdout += chunk;
|
|
3638
|
-
});
|
|
3639
|
-
child.stderr.on("data", (chunk) => {
|
|
3640
|
-
stderr += chunk;
|
|
3641
|
-
});
|
|
3642
|
-
child.once("error", reject);
|
|
3643
|
-
child.once("close", (code, signal) => {
|
|
3644
|
-
if (code === 0) {
|
|
3645
|
-
resolve(stdout);
|
|
3646
|
-
return;
|
|
3647
|
-
}
|
|
3648
|
-
reject(/* @__PURE__ */ new Error(`powershell process list exited with code ${code ?? "null"} signal ${signal ?? "null"}: ${stderr}`));
|
|
3649
|
-
});
|
|
3792
|
+
async function runProcessGroupListCommand(timeoutMs) {
|
|
3793
|
+
return await runTimedExecFile("ps", ["-eo", "pid=,pgid="], { timeoutMs });
|
|
3794
|
+
}
|
|
3795
|
+
async function runWindowsProcessListCommand(timeoutMs) {
|
|
3796
|
+
return await runTimedExecFile("powershell.exe", [
|
|
3797
|
+
"-NoProfile",
|
|
3798
|
+
"-NonInteractive",
|
|
3799
|
+
"-Command",
|
|
3800
|
+
["Get-CimInstance Win32_Process |", "ForEach-Object { \"$($_.ProcessId) $($_.ParentProcessId)\" }"].join(" ")
|
|
3801
|
+
], {
|
|
3802
|
+
timeoutMs,
|
|
3803
|
+
windowsHide: true
|
|
3650
3804
|
});
|
|
3651
3805
|
}
|
|
3652
3806
|
async function killWindowsProcessTree(pid, signal) {
|
|
@@ -3706,6 +3860,14 @@ const STARTUP_STDERR_MAX_CHARS = 8192;
|
|
|
3706
3860
|
const DEVIN_COMPATIBILITY_CLIENT_CAPABILITIES_META = Object.freeze({ "cognition.ai/requestDiagnostics": true });
|
|
3707
3861
|
const DEVIN_COMPATIBILITY_CLIENT_NAME = "windsurf";
|
|
3708
3862
|
const DEFAULT_DEVIN_COMPATIBILITY_CLIENT_VERSION = "1.110.1";
|
|
3863
|
+
const ELICITATION_CANCEL_MESSAGES = {
|
|
3864
|
+
inactive: "elicitation owner is no longer active",
|
|
3865
|
+
unavailable: "elicitation handler is unavailable",
|
|
3866
|
+
unsupported: "elicitation mode is not supported",
|
|
3867
|
+
mismatchedSession: "elicitation session is not active",
|
|
3868
|
+
cancelled: "elicitation request was cancelled",
|
|
3869
|
+
requestScoped: "request-scoped elicitation has no owner"
|
|
3870
|
+
};
|
|
3709
3871
|
function resolveClientInfo(devinAcp) {
|
|
3710
3872
|
if (!devinAcp) return {
|
|
3711
3873
|
name: "acpx",
|
|
@@ -3716,13 +3878,88 @@ function resolveClientInfo(devinAcp) {
|
|
|
3716
3878
|
version: process.env.ACPX_DEVIN_WINDSURF_VERSION ?? DEFAULT_DEVIN_COMPATIBILITY_CLIENT_VERSION
|
|
3717
3879
|
};
|
|
3718
3880
|
}
|
|
3881
|
+
function normalizeElicitationModes(modes) {
|
|
3882
|
+
return [...new Set((modes ?? []).filter((mode) => mode === "form" || mode === "url"))];
|
|
3883
|
+
}
|
|
3884
|
+
function cancelledElicitationResponse(message) {
|
|
3885
|
+
return {
|
|
3886
|
+
action: "cancel",
|
|
3887
|
+
_meta: { message }
|
|
3888
|
+
};
|
|
3889
|
+
}
|
|
3890
|
+
function isKnownElicitationResponse(response) {
|
|
3891
|
+
if (!response || typeof response !== "object") return false;
|
|
3892
|
+
const action = response.action;
|
|
3893
|
+
return action === "accept" || action === "decline" || action === "cancel";
|
|
3894
|
+
}
|
|
3895
|
+
function elicitationSessionId(request) {
|
|
3896
|
+
const value = request.sessionId;
|
|
3897
|
+
return typeof value === "string" ? value : void 0;
|
|
3898
|
+
}
|
|
3899
|
+
function elicitationRequestScopeId(request) {
|
|
3900
|
+
const value = request.requestId;
|
|
3901
|
+
return value === null || typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
3902
|
+
}
|
|
3903
|
+
function waitForAbort(signal) {
|
|
3904
|
+
if (signal.aborted) return Promise.resolve({ kind: "aborted" });
|
|
3905
|
+
return new Promise((resolve) => {
|
|
3906
|
+
signal.addEventListener("abort", () => resolve({ kind: "aborted" }), { once: true });
|
|
3907
|
+
});
|
|
3908
|
+
}
|
|
3909
|
+
function isExtensionNotification(message) {
|
|
3910
|
+
if (!("method" in message) || "id" in message || typeof message.method !== "string") return false;
|
|
3911
|
+
return message.method !== methods.client.session.update && message.method !== methods.client.elicitation.complete && message.method !== methods.protocol.cancelRequest;
|
|
3912
|
+
}
|
|
3913
|
+
function elicitationRequestId(message) {
|
|
3914
|
+
if (!("method" in message) || message.method !== methods.client.elicitation.create || !("id" in message)) return;
|
|
3915
|
+
return message.id;
|
|
3916
|
+
}
|
|
3917
|
+
function responseId(message) {
|
|
3918
|
+
if (!("id" in message) || "method" in message) return;
|
|
3919
|
+
return message.id;
|
|
3920
|
+
}
|
|
3921
|
+
function promptRequestOwner(message) {
|
|
3922
|
+
if (!("method" in message) || message.method !== methods.agent.session.prompt || !("id" in message)) return;
|
|
3923
|
+
const sessionId = message.params?.sessionId;
|
|
3924
|
+
return typeof sessionId === "string" ? {
|
|
3925
|
+
requestId: message.id,
|
|
3926
|
+
sessionId
|
|
3927
|
+
} : void 0;
|
|
3928
|
+
}
|
|
3929
|
+
function createAgentConnectionFacade(connection) {
|
|
3930
|
+
const agent = connection.agent;
|
|
3931
|
+
return {
|
|
3932
|
+
signal: connection.signal,
|
|
3933
|
+
close: (error) => connection.close(error),
|
|
3934
|
+
initialize: async (params) => await agent.request(methods.agent.initialize, params),
|
|
3935
|
+
authenticate: async (params) => {
|
|
3936
|
+
await agent.request(methods.agent.authenticate, params);
|
|
3937
|
+
},
|
|
3938
|
+
newSession: async (params) => await agent.request(methods.agent.session.new, params),
|
|
3939
|
+
loadSession: async (params) => await agent.request(methods.agent.session.load, params),
|
|
3940
|
+
resumeSession: async (params) => await agent.request(methods.agent.session.resume, params),
|
|
3941
|
+
prompt: async (params) => await agent.request(methods.agent.session.prompt, params),
|
|
3942
|
+
setSessionMode: async (params) => await agent.request(methods.agent.session.setMode, params),
|
|
3943
|
+
setSessionConfigOption: async (params) => await agent.request(methods.agent.session.setConfigOption, params),
|
|
3944
|
+
extMethod: async (method, params) => await agent.request(method, params),
|
|
3945
|
+
cancel: async (params) => await agent.notify(methods.agent.session.cancel, params),
|
|
3946
|
+
closeSession: async (params) => {
|
|
3947
|
+
await agent.request(methods.agent.session.close, params);
|
|
3948
|
+
},
|
|
3949
|
+
listSessions: async (params) => await agent.request(methods.agent.session.list, params)
|
|
3950
|
+
};
|
|
3951
|
+
}
|
|
3719
3952
|
function resolveClientCapabilities(params) {
|
|
3720
3953
|
const baseCapabilities = {
|
|
3721
3954
|
fs: {
|
|
3722
|
-
readTextFile:
|
|
3723
|
-
writeTextFile:
|
|
3955
|
+
readTextFile: params.fs,
|
|
3956
|
+
writeTextFile: params.fs
|
|
3724
3957
|
},
|
|
3725
|
-
terminal: params.terminal
|
|
3958
|
+
terminal: params.terminal,
|
|
3959
|
+
...params.elicitationModes.length > 0 ? { elicitation: {
|
|
3960
|
+
...params.elicitationModes.includes("form") ? { form: {} } : {},
|
|
3961
|
+
...params.elicitationModes.includes("url") ? { url: {} } : {}
|
|
3962
|
+
} } : {}
|
|
3726
3963
|
};
|
|
3727
3964
|
if (!params.devinAcp) return baseCapabilities;
|
|
3728
3965
|
return {
|
|
@@ -3730,9 +3967,6 @@ function resolveClientCapabilities(params) {
|
|
|
3730
3967
|
_meta: DEVIN_COMPATIBILITY_CLIENT_CAPABILITIES_META
|
|
3731
3968
|
};
|
|
3732
3969
|
}
|
|
3733
|
-
function isDevinRequestDiagnosticsMethod(method) {
|
|
3734
|
-
return method === "_cognition.ai/request_diagnostics";
|
|
3735
|
-
}
|
|
3736
3970
|
function hasResponseField(response, field) {
|
|
3737
3971
|
return !!response && typeof response === "object" && field in response;
|
|
3738
3972
|
}
|
|
@@ -3753,6 +3987,15 @@ function toReconnectedSessionResult(response) {
|
|
|
3753
3987
|
legacyModelMetadataPresent: hasResponseField(response, "models")
|
|
3754
3988
|
};
|
|
3755
3989
|
}
|
|
3990
|
+
function snapshotPermissionPolicy(policy) {
|
|
3991
|
+
if (!policy) return;
|
|
3992
|
+
return {
|
|
3993
|
+
...policy.autoApprove ? { autoApprove: [...policy.autoApprove] } : {},
|
|
3994
|
+
...policy.autoDeny ? { autoDeny: [...policy.autoDeny] } : {},
|
|
3995
|
+
...policy.escalate ? { escalate: [...policy.escalate] } : {},
|
|
3996
|
+
...policy.defaultAction ? { defaultAction: policy.defaultAction } : {}
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3756
3999
|
function childProcessIsRunning(agent) {
|
|
3757
4000
|
if (!agent) return false;
|
|
3758
4001
|
return agent.exitCode == null && agent.signalCode == null && !agent.killed;
|
|
@@ -3845,6 +4088,7 @@ var AcpClient = class {
|
|
|
3845
4088
|
suppressSessionUpdates = false;
|
|
3846
4089
|
suppressReplaySessionUpdateMessages = false;
|
|
3847
4090
|
activePrompt;
|
|
4091
|
+
pendingPromptOwners = [];
|
|
3848
4092
|
cancellingSessionIds = /* @__PURE__ */ new Set();
|
|
3849
4093
|
permissionAbortControllers = /* @__PURE__ */ new Map();
|
|
3850
4094
|
closing = false;
|
|
@@ -3859,7 +4103,9 @@ var AcpClient = class {
|
|
|
3859
4103
|
this.options = {
|
|
3860
4104
|
...options,
|
|
3861
4105
|
cwd: asAbsoluteCwd(options.cwd),
|
|
3862
|
-
authPolicy: options.authPolicy ?? "skip"
|
|
4106
|
+
authPolicy: options.authPolicy ?? "skip",
|
|
4107
|
+
permissionPolicy: snapshotPermissionPolicy(options.permissionPolicy),
|
|
4108
|
+
elicitationModes: normalizeElicitationModes(options.elicitationModes)
|
|
3863
4109
|
};
|
|
3864
4110
|
this.eventHandlers = {
|
|
3865
4111
|
onAcpMessage: this.options.onAcpMessage,
|
|
@@ -3926,12 +4172,16 @@ var AcpClient = class {
|
|
|
3926
4172
|
const shouldRefreshPermissionPolicy = options.permissionMode !== void 0 || options.nonInteractivePermissions !== void 0;
|
|
3927
4173
|
if (options.permissionMode) this.options.permissionMode = options.permissionMode;
|
|
3928
4174
|
if (options.nonInteractivePermissions !== void 0) this.options.nonInteractivePermissions = options.nonInteractivePermissions;
|
|
3929
|
-
if (Object.prototype.hasOwnProperty.call(options, "permissionPolicy")) this.options.permissionPolicy = options.permissionPolicy;
|
|
3930
|
-
|
|
4175
|
+
if (Object.prototype.hasOwnProperty.call(options, "permissionPolicy")) this.options.permissionPolicy = snapshotPermissionPolicy(options.permissionPolicy);
|
|
4176
|
+
this.updateClientCapabilityPreferences(options);
|
|
3931
4177
|
this.refreshRuntimePermissionPolicy(shouldRefreshPermissionPolicy);
|
|
3932
4178
|
if (options.suppressSdkConsoleErrors !== void 0) this.options.suppressSdkConsoleErrors = options.suppressSdkConsoleErrors;
|
|
3933
4179
|
if (options.verbose !== void 0) this.options.verbose = options.verbose;
|
|
3934
4180
|
}
|
|
4181
|
+
updateClientCapabilityPreferences(options) {
|
|
4182
|
+
if (options.fs !== void 0) this.options.fs = options.fs;
|
|
4183
|
+
if (options.terminal !== void 0) this.options.terminal = options.terminal;
|
|
4184
|
+
}
|
|
3935
4185
|
refreshRuntimePermissionPolicy(enabled) {
|
|
3936
4186
|
if (!enabled) return;
|
|
3937
4187
|
this.filesystem.updatePermissionPolicy(this.options.permissionMode, this.options.nonInteractivePermissions);
|
|
@@ -3945,6 +4195,15 @@ var AcpClient = class {
|
|
|
3945
4195
|
if (sessionId == null) return true;
|
|
3946
4196
|
return this.activePrompt.sessionId === sessionId;
|
|
3947
4197
|
}
|
|
4198
|
+
hasUnresolvedPrompt() {
|
|
4199
|
+
return this.activePrompt !== void 0;
|
|
4200
|
+
}
|
|
4201
|
+
endPromptElicitation(sessionId) {
|
|
4202
|
+
const active = this.activePrompt;
|
|
4203
|
+
if (!active || active.sessionId !== sessionId) return;
|
|
4204
|
+
active.elicitationHandler = void 0;
|
|
4205
|
+
active.elicitationController.abort();
|
|
4206
|
+
}
|
|
3948
4207
|
async start() {
|
|
3949
4208
|
if (this.connection && this.agent && isChildProcessRunning(this.agent)) return;
|
|
3950
4209
|
if (this.connection || this.agent) await this.close();
|
|
@@ -3980,7 +4239,7 @@ var AcpClient = class {
|
|
|
3980
4239
|
});
|
|
3981
4240
|
}
|
|
3982
4241
|
async resolveAgentLaunchPlan() {
|
|
3983
|
-
const configuredCommand =
|
|
4242
|
+
const configuredCommand = resolveAgentCommandParts(this.options.agentCommand, this.options.agentArgv);
|
|
3984
4243
|
const resolvedBuiltInLaunch = resolveBuiltInAgentLaunch(this.options.agentCommand);
|
|
3985
4244
|
const spawnCommand = resolvedBuiltInLaunch?.command ?? configuredCommand.command;
|
|
3986
4245
|
let args = resolvedBuiltInLaunch?.args ?? configuredCommand.args;
|
|
@@ -4019,7 +4278,11 @@ var AcpClient = class {
|
|
|
4019
4278
|
}
|
|
4020
4279
|
}
|
|
4021
4280
|
async spawnAgentProcess(plan) {
|
|
4022
|
-
const
|
|
4281
|
+
const spawnCommand = buildAgentSpawnCommand(plan.spawnCommand, plan.args, process.platform, plan.spawnOptions.env);
|
|
4282
|
+
const spawnedChild = spawn(spawnCommand.command, spawnCommand.args, {
|
|
4283
|
+
...plan.spawnOptions,
|
|
4284
|
+
windowsVerbatimArguments: spawnCommand.windowsVerbatimArguments
|
|
4285
|
+
});
|
|
4023
4286
|
try {
|
|
4024
4287
|
await waitForSpawn$1(spawnedChild);
|
|
4025
4288
|
} catch (error) {
|
|
@@ -4028,42 +4291,31 @@ var AcpClient = class {
|
|
|
4028
4291
|
return requireAgentStdio(spawnedChild);
|
|
4029
4292
|
}
|
|
4030
4293
|
createConnection(stream, launch) {
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
waitForTerminalExit: async (params) => {
|
|
4057
|
-
return this.handleWaitForTerminalExit(params);
|
|
4058
|
-
},
|
|
4059
|
-
killTerminal: async (params) => {
|
|
4060
|
-
return this.handleKillTerminal(params);
|
|
4061
|
-
},
|
|
4062
|
-
releaseTerminal: async (params) => {
|
|
4063
|
-
return this.handleReleaseTerminal(params);
|
|
4064
|
-
},
|
|
4065
|
-
extNotification: async () => {}
|
|
4066
|
-
}), stream);
|
|
4294
|
+
const app = client({ name: "acpx" }).onNotification(methods.client.session.update, async ({ params }) => {
|
|
4295
|
+
await this.handleSessionUpdate(params);
|
|
4296
|
+
}).onNotification(methods.client.elicitation.complete, async () => {}).onRequest(methods.client.session.requestPermission, async ({ params }) => {
|
|
4297
|
+
return await this.handlePermissionRequest(params);
|
|
4298
|
+
}).onRequest(methods.client.elicitation.create, async ({ params, requestId, signal }) => {
|
|
4299
|
+
return await this.handleElicitationRequest(params, requestId, signal);
|
|
4300
|
+
}).onRequest(methods.client.fs.readTextFile, async ({ params }) => {
|
|
4301
|
+
return await this.handleReadTextFile(params);
|
|
4302
|
+
}).onRequest(methods.client.fs.writeTextFile, async ({ params }) => {
|
|
4303
|
+
return await this.handleWriteTextFile(params);
|
|
4304
|
+
}).onRequest(methods.client.terminal.create, async ({ params }) => {
|
|
4305
|
+
return await this.handleCreateTerminal(params);
|
|
4306
|
+
}).onRequest(methods.client.terminal.output, async ({ params }) => {
|
|
4307
|
+
return await this.handleTerminalOutput(params);
|
|
4308
|
+
}).onRequest(methods.client.terminal.waitForExit, async ({ params }) => {
|
|
4309
|
+
return await this.handleWaitForTerminalExit(params);
|
|
4310
|
+
}).onRequest(methods.client.terminal.kill, async ({ params }) => {
|
|
4311
|
+
return await this.handleKillTerminal(params);
|
|
4312
|
+
}).onRequest(methods.client.terminal.release, async ({ params }) => {
|
|
4313
|
+
return await this.handleReleaseTerminal(params);
|
|
4314
|
+
});
|
|
4315
|
+
if (launch.devinAcp) app.onRequest("_cognition.ai/request_diagnostics", (params) => {
|
|
4316
|
+
return params && typeof params === "object" && !Array.isArray(params) ? params : {};
|
|
4317
|
+
}, async () => ({}));
|
|
4318
|
+
return createAgentConnectionFacade(app.connect(stream));
|
|
4067
4319
|
}
|
|
4068
4320
|
async initializeAgentConnection(params) {
|
|
4069
4321
|
try {
|
|
@@ -4074,6 +4326,7 @@ var AcpClient = class {
|
|
|
4074
4326
|
this.initResult = initResult;
|
|
4075
4327
|
this.log(`initialized protocol version ${initResult.protocolVersion}`);
|
|
4076
4328
|
} catch (error) {
|
|
4329
|
+
params.connection.close?.(error);
|
|
4077
4330
|
await this.handleInitializeFailure(params, error);
|
|
4078
4331
|
}
|
|
4079
4332
|
}
|
|
@@ -4082,7 +4335,9 @@ var AcpClient = class {
|
|
|
4082
4335
|
protocolVersion: PROTOCOL_VERSION,
|
|
4083
4336
|
clientCapabilities: resolveClientCapabilities({
|
|
4084
4337
|
devinAcp: launch.devinAcp,
|
|
4085
|
-
|
|
4338
|
+
fs: this.options.fs !== false,
|
|
4339
|
+
terminal: this.options.terminal !== false,
|
|
4340
|
+
elicitationModes: this.options.elicitationModes ?? []
|
|
4086
4341
|
}),
|
|
4087
4342
|
clientInfo: resolveClientInfo(launch.devinAcp)
|
|
4088
4343
|
});
|
|
@@ -4105,9 +4360,24 @@ var AcpClient = class {
|
|
|
4105
4360
|
createTappedStream(base) {
|
|
4106
4361
|
const onAcpMessage = () => this.eventHandlers.onAcpMessage;
|
|
4107
4362
|
const onAcpOutputMessage = () => this.eventHandlers.onAcpOutputMessage;
|
|
4363
|
+
const elicitationRequestIds = /* @__PURE__ */ new Set();
|
|
4364
|
+
const bindPromptOwner = (owner) => {
|
|
4365
|
+
this.bindPromptOwner(owner);
|
|
4366
|
+
};
|
|
4108
4367
|
const shouldSuppressInboundReplaySessionUpdate = (message) => {
|
|
4109
4368
|
return this.suppressReplaySessionUpdateMessages && isSessionUpdateNotification(message);
|
|
4110
4369
|
};
|
|
4370
|
+
const observeInbound = (message) => {
|
|
4371
|
+
const requestId = elicitationRequestId(message);
|
|
4372
|
+
if (requestId !== void 0) {
|
|
4373
|
+
elicitationRequestIds.add(requestId);
|
|
4374
|
+
return;
|
|
4375
|
+
}
|
|
4376
|
+
if (!shouldSuppressInboundReplaySessionUpdate(message)) {
|
|
4377
|
+
onAcpOutputMessage()?.("inbound", message);
|
|
4378
|
+
onAcpMessage()?.("inbound", message);
|
|
4379
|
+
}
|
|
4380
|
+
};
|
|
4111
4381
|
return {
|
|
4112
4382
|
readable: new ReadableStream({ async start(controller) {
|
|
4113
4383
|
const reader = base.readable.getReader();
|
|
@@ -4116,10 +4386,8 @@ var AcpClient = class {
|
|
|
4116
4386
|
const { value, done } = await reader.read();
|
|
4117
4387
|
if (done) break;
|
|
4118
4388
|
if (!value) continue;
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
onAcpMessage()?.("inbound", value);
|
|
4122
|
-
}
|
|
4389
|
+
observeInbound(value);
|
|
4390
|
+
if (isExtensionNotification(value)) continue;
|
|
4123
4391
|
controller.enqueue(value);
|
|
4124
4392
|
}
|
|
4125
4393
|
} finally {
|
|
@@ -4128,8 +4396,13 @@ var AcpClient = class {
|
|
|
4128
4396
|
}
|
|
4129
4397
|
} }),
|
|
4130
4398
|
writable: new WritableStream({ async write(message) {
|
|
4131
|
-
|
|
4132
|
-
|
|
4399
|
+
const promptOwner = promptRequestOwner(message);
|
|
4400
|
+
if (promptOwner) bindPromptOwner(promptOwner);
|
|
4401
|
+
const id = responseId(message);
|
|
4402
|
+
if (!(id !== void 0 && elicitationRequestIds.delete(id))) {
|
|
4403
|
+
onAcpOutputMessage()?.("outbound", message);
|
|
4404
|
+
onAcpMessage()?.("outbound", message);
|
|
4405
|
+
}
|
|
4133
4406
|
const writer = base.writable.getWriter();
|
|
4134
4407
|
try {
|
|
4135
4408
|
await writer.write(message);
|
|
@@ -4141,7 +4414,7 @@ var AcpClient = class {
|
|
|
4141
4414
|
}
|
|
4142
4415
|
async createSession(cwd = this.options.cwd) {
|
|
4143
4416
|
const connection = this.getConnection();
|
|
4144
|
-
const { command, args } =
|
|
4417
|
+
const { command, args } = resolveAgentCommandParts(this.options.agentCommand, this.options.agentArgv);
|
|
4145
4418
|
const claudeAcp = isClaudeAcpCommand(command, args);
|
|
4146
4419
|
const sessionCwd = await resolveAgentSessionCwd(cwd, this.options.agentCommand);
|
|
4147
4420
|
let result;
|
|
@@ -4225,24 +4498,23 @@ var AcpClient = class {
|
|
|
4225
4498
|
this.suppressSessionUpdates = previous.suppressSessionUpdates;
|
|
4226
4499
|
this.suppressReplaySessionUpdateMessages = previous.suppressReplaySessionUpdateMessages;
|
|
4227
4500
|
}
|
|
4228
|
-
async prompt(sessionId, prompt) {
|
|
4501
|
+
async prompt(sessionId, prompt, onRequestStarted, onElicitation) {
|
|
4229
4502
|
const connection = this.getConnection();
|
|
4230
4503
|
const normalizedPrompt = this.normalizePromptForAgent(prompt);
|
|
4231
4504
|
const restoreConsoleError = this.options.suppressSdkConsoleErrors ? installSdkConsoleErrorSuppression() : void 0;
|
|
4505
|
+
const activePrompt = this.beginActivePrompt(sessionId, onElicitation);
|
|
4232
4506
|
let promptPromise;
|
|
4233
4507
|
try {
|
|
4234
4508
|
promptPromise = this.runConnectionRequest(() => connection.prompt({
|
|
4235
4509
|
sessionId,
|
|
4236
4510
|
prompt: normalizedPrompt
|
|
4237
|
-
}));
|
|
4511
|
+
}), onRequestStarted, () => !connection.signal?.aborted);
|
|
4238
4512
|
} catch (error) {
|
|
4513
|
+
this.clearActivePrompt(activePrompt);
|
|
4239
4514
|
restoreConsoleError?.();
|
|
4240
4515
|
throw error;
|
|
4241
4516
|
}
|
|
4242
|
-
|
|
4243
|
-
sessionId,
|
|
4244
|
-
promise: promptPromise
|
|
4245
|
-
};
|
|
4517
|
+
activePrompt.promise = promptPromise;
|
|
4246
4518
|
try {
|
|
4247
4519
|
return this.returnPromptResponseOrPermissionFailure(sessionId, await promptPromise);
|
|
4248
4520
|
} catch (error) {
|
|
@@ -4250,12 +4522,37 @@ var AcpClient = class {
|
|
|
4250
4522
|
throw error;
|
|
4251
4523
|
} finally {
|
|
4252
4524
|
restoreConsoleError?.();
|
|
4253
|
-
|
|
4525
|
+
this.clearActivePrompt(activePrompt);
|
|
4254
4526
|
this.cancellingSessionIds.delete(sessionId);
|
|
4255
4527
|
this.abortAndDropPermissionSignal(sessionId);
|
|
4256
4528
|
this.promptPermissionFailures.delete(sessionId);
|
|
4257
4529
|
}
|
|
4258
4530
|
}
|
|
4531
|
+
beginActivePrompt(sessionId, elicitationHandler) {
|
|
4532
|
+
const previous = this.activePrompt;
|
|
4533
|
+
this.cancellingSessionIds.delete(sessionId);
|
|
4534
|
+
const active = {
|
|
4535
|
+
sessionId,
|
|
4536
|
+
elicitationHandler,
|
|
4537
|
+
elicitationController: new AbortController()
|
|
4538
|
+
};
|
|
4539
|
+
this.activePrompt = active;
|
|
4540
|
+
this.pendingPromptOwners.push(active);
|
|
4541
|
+
previous?.elicitationController?.abort();
|
|
4542
|
+
return active;
|
|
4543
|
+
}
|
|
4544
|
+
bindPromptOwner(owner) {
|
|
4545
|
+
const active = this.pendingPromptOwners.find((candidate) => {
|
|
4546
|
+
return candidate.requestId === void 0 && candidate.sessionId === owner.sessionId;
|
|
4547
|
+
});
|
|
4548
|
+
if (active) active.requestId = owner.requestId;
|
|
4549
|
+
}
|
|
4550
|
+
clearActivePrompt(active) {
|
|
4551
|
+
if (this.activePrompt === active) this.activePrompt = void 0;
|
|
4552
|
+
const pendingIndex = this.pendingPromptOwners.indexOf(active);
|
|
4553
|
+
if (pendingIndex >= 0) this.pendingPromptOwners.splice(pendingIndex, 1);
|
|
4554
|
+
active.elicitationController.abort();
|
|
4555
|
+
}
|
|
4259
4556
|
normalizePromptForAgent(prompt) {
|
|
4260
4557
|
const normalizedPrompt = typeof prompt === "string" ? textPrompt(prompt) : prompt;
|
|
4261
4558
|
const unsupportedPromptContent = getUnsupportedPromptContentMessage(normalizedPrompt, this.initResult?.agentCapabilities);
|
|
@@ -4368,12 +4665,18 @@ var AcpClient = class {
|
|
|
4368
4665
|
}
|
|
4369
4666
|
async cancel(sessionId) {
|
|
4370
4667
|
const connection = this.getConnection();
|
|
4371
|
-
this.
|
|
4668
|
+
const active = this.activePrompt;
|
|
4669
|
+
if (active?.sessionId === sessionId) {
|
|
4670
|
+
this.cancellingSessionIds.add(sessionId);
|
|
4671
|
+
active.elicitationController?.abort();
|
|
4672
|
+
} else this.cancellingSessionIds.delete(sessionId);
|
|
4372
4673
|
this.abortAndDropPermissionSignal(sessionId);
|
|
4373
4674
|
await this.runConnectionRequest(() => connection.cancel({ sessionId }));
|
|
4374
4675
|
}
|
|
4375
4676
|
async closeSession(sessionId) {
|
|
4376
4677
|
const connection = this.getConnection();
|
|
4678
|
+
this.cancellingSessionIds.add(sessionId);
|
|
4679
|
+
if (this.activePrompt?.sessionId === sessionId) this.activePrompt.elicitationController?.abort();
|
|
4377
4680
|
await this.runConnectionRequest(() => connection.closeSession({ sessionId }));
|
|
4378
4681
|
if (this.loadedSessionId === sessionId) this.loadedSessionId = void 0;
|
|
4379
4682
|
this.modelConfigIds.delete(sessionId);
|
|
@@ -4399,21 +4702,25 @@ var AcpClient = class {
|
|
|
4399
4702
|
this.log(`failed to send session/cancel: ${message}`);
|
|
4400
4703
|
}
|
|
4401
4704
|
if (waitMs <= 0) return;
|
|
4705
|
+
const activePromise = active.promise;
|
|
4706
|
+
if (!activePromise) return;
|
|
4402
4707
|
let timer;
|
|
4403
4708
|
const timeoutPromise = new Promise((resolve) => {
|
|
4404
4709
|
timer = setTimeout(resolve, waitMs);
|
|
4405
4710
|
});
|
|
4406
4711
|
try {
|
|
4407
|
-
return await Promise.race([
|
|
4712
|
+
return await Promise.race([activePromise.then((response) => response, () => void 0), timeoutPromise]);
|
|
4408
4713
|
} finally {
|
|
4409
4714
|
if (timer) clearTimeout(timer);
|
|
4410
4715
|
}
|
|
4411
4716
|
}
|
|
4412
4717
|
async close() {
|
|
4413
4718
|
this.closing = true;
|
|
4719
|
+
this.abortActiveElicitation();
|
|
4414
4720
|
await this.terminalManager.shutdown();
|
|
4415
4721
|
const agent = this.agent;
|
|
4416
4722
|
if (agent) await this.terminateAgentProcess(agent);
|
|
4723
|
+
this.closeConnection();
|
|
4417
4724
|
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) }));
|
|
4418
4725
|
this.sessionUpdateChain = Promise.resolve();
|
|
4419
4726
|
this.observedSessionUpdates = 0;
|
|
@@ -4421,6 +4728,7 @@ var AcpClient = class {
|
|
|
4421
4728
|
this.suppressSessionUpdates = false;
|
|
4422
4729
|
this.suppressReplaySessionUpdateMessages = false;
|
|
4423
4730
|
this.activePrompt = void 0;
|
|
4731
|
+
this.pendingPromptOwners.length = 0;
|
|
4424
4732
|
this.cancellingSessionIds.clear();
|
|
4425
4733
|
for (const controller of this.permissionAbortControllers.values()) controller.abort();
|
|
4426
4734
|
this.permissionAbortControllers.clear();
|
|
@@ -4432,6 +4740,12 @@ var AcpClient = class {
|
|
|
4432
4740
|
this.connection = void 0;
|
|
4433
4741
|
this.agent = void 0;
|
|
4434
4742
|
}
|
|
4743
|
+
abortActiveElicitation() {
|
|
4744
|
+
this.activePrompt?.elicitationController?.abort();
|
|
4745
|
+
}
|
|
4746
|
+
closeConnection() {
|
|
4747
|
+
this.connection?.close?.();
|
|
4748
|
+
}
|
|
4435
4749
|
async terminateAgentProcess(child) {
|
|
4436
4750
|
const stdinCloseGraceMs = resolveAgentCloseAfterStdinEndMs(this.options.agentCommand);
|
|
4437
4751
|
this.endAgentStdin(child);
|
|
@@ -4587,15 +4901,15 @@ var AcpClient = class {
|
|
|
4587
4901
|
};
|
|
4588
4902
|
}
|
|
4589
4903
|
isGrokBuildAcpCommand() {
|
|
4590
|
-
const { command, args } =
|
|
4904
|
+
const { command, args } = resolveAgentCommandParts(this.options.agentCommand, this.options.agentArgv);
|
|
4591
4905
|
return command.replace(/\\/g, "/").split("/").pop()?.replace(/\.(cmd|exe|ps1)$/iu, "").toLowerCase() === "grok" && args[0] === "agent" && args[1] === "stdio";
|
|
4592
4906
|
}
|
|
4593
|
-
async authenticateIfRequired(connection,
|
|
4594
|
-
if (
|
|
4595
|
-
const selected = this.selectAuthMethod(
|
|
4907
|
+
async authenticateIfRequired(connection, authMethods) {
|
|
4908
|
+
if (authMethods.length === 0) return;
|
|
4909
|
+
const selected = this.selectAuthMethod(authMethods);
|
|
4596
4910
|
if (!selected) {
|
|
4597
|
-
if (this.options.authPolicy === "fail") throw new AuthPolicyError(`agent advertised auth methods [${
|
|
4598
|
-
this.log(`agent advertised auth methods [${
|
|
4911
|
+
if (this.options.authPolicy === "fail") throw new AuthPolicyError(`agent advertised auth methods [${authMethods.map((m) => m.id).join(", ")}] but no matching credentials found`);
|
|
4912
|
+
this.log(`agent advertised auth methods [${authMethods.map((m) => m.id).join(", ")}] but no matching credentials found — skipping (agent may handle auth internally)`);
|
|
4599
4913
|
return;
|
|
4600
4914
|
}
|
|
4601
4915
|
await connection.authenticate({ methodId: selected.methodId });
|
|
@@ -4612,6 +4926,50 @@ var AcpClient = class {
|
|
|
4612
4926
|
}
|
|
4613
4927
|
return response;
|
|
4614
4928
|
}
|
|
4929
|
+
async handleElicitationRequest(request, requestId, requestSignal) {
|
|
4930
|
+
const resolved = this.resolveElicitationOwner(request);
|
|
4931
|
+
if ("response" in resolved) return resolved.response;
|
|
4932
|
+
const { active, handler } = resolved.owner;
|
|
4933
|
+
const signal = AbortSignal.any([requestSignal, active.elicitationController.signal]);
|
|
4934
|
+
const handlerAttempt = Promise.resolve().then(async () => await handler(request, {
|
|
4935
|
+
requestId,
|
|
4936
|
+
signal
|
|
4937
|
+
})).then((response) => ({
|
|
4938
|
+
kind: "response",
|
|
4939
|
+
response
|
|
4940
|
+
}), (error) => ({
|
|
4941
|
+
kind: "error",
|
|
4942
|
+
error
|
|
4943
|
+
}));
|
|
4944
|
+
const outcome = await Promise.race([handlerAttempt, waitForAbort(signal)]);
|
|
4945
|
+
if (this.activePrompt !== active) return cancelledElicitationResponse(ELICITATION_CANCEL_MESSAGES.inactive);
|
|
4946
|
+
if (outcome.kind === "aborted" || signal.aborted) return cancelledElicitationResponse(ELICITATION_CANCEL_MESSAGES.cancelled);
|
|
4947
|
+
if (outcome.kind === "error" || !isKnownElicitationResponse(outcome.response)) return cancelledElicitationResponse(ELICITATION_CANCEL_MESSAGES.unavailable);
|
|
4948
|
+
return outcome.response;
|
|
4949
|
+
}
|
|
4950
|
+
resolveElicitationOwner(request) {
|
|
4951
|
+
if (!this.options.elicitationModes?.includes(request.mode)) return { response: cancelledElicitationResponse(ELICITATION_CANCEL_MESSAGES.unsupported) };
|
|
4952
|
+
const active = this.activePrompt;
|
|
4953
|
+
if (!active) return { response: cancelledElicitationResponse(ELICITATION_CANCEL_MESSAGES.inactive) };
|
|
4954
|
+
const scope = this.resolveElicitationScope(request, active);
|
|
4955
|
+
if ("response" in scope) return scope;
|
|
4956
|
+
if (this.isElicitationSessionCancelling(scope.sessionId)) return { response: cancelledElicitationResponse(ELICITATION_CANCEL_MESSAGES.cancelled) };
|
|
4957
|
+
if (!active.elicitationHandler) return { response: cancelledElicitationResponse(ELICITATION_CANCEL_MESSAGES.unavailable) };
|
|
4958
|
+
return { owner: {
|
|
4959
|
+
active,
|
|
4960
|
+
handler: active.elicitationHandler
|
|
4961
|
+
} };
|
|
4962
|
+
}
|
|
4963
|
+
resolveElicitationScope(request, active) {
|
|
4964
|
+
const sessionId = elicitationSessionId(request);
|
|
4965
|
+
if (sessionId) return sessionId === active.sessionId ? { sessionId } : { response: cancelledElicitationResponse(ELICITATION_CANCEL_MESSAGES.mismatchedSession) };
|
|
4966
|
+
const requestScopeId = elicitationRequestScopeId(request);
|
|
4967
|
+
if (requestScopeId === void 0 || requestScopeId !== active.requestId) return { response: cancelledElicitationResponse(ELICITATION_CANCEL_MESSAGES.requestScoped) };
|
|
4968
|
+
return { sessionId: active.sessionId };
|
|
4969
|
+
}
|
|
4970
|
+
isElicitationSessionCancelling(sessionId) {
|
|
4971
|
+
return this.closing || this.cancellingSessionIds.has(sessionId);
|
|
4972
|
+
}
|
|
4615
4973
|
async tryHandlePermissionRequestWithHost(params) {
|
|
4616
4974
|
if (!this.options.onPermissionRequest) return;
|
|
4617
4975
|
const signal = this.cancellationSignalForSession(params.sessionId);
|
|
@@ -4697,7 +5055,7 @@ var AcpClient = class {
|
|
|
4697
5055
|
if (error) this.promptPermissionFailures.delete(sessionId);
|
|
4698
5056
|
return error;
|
|
4699
5057
|
}
|
|
4700
|
-
async runConnectionRequest(run) {
|
|
5058
|
+
async runConnectionRequest(run, onRequestStarted, canStartRequest = () => true) {
|
|
4701
5059
|
return await new Promise((resolve, reject) => {
|
|
4702
5060
|
const pending = {
|
|
4703
5061
|
settled: false,
|
|
@@ -4710,7 +5068,20 @@ var AcpClient = class {
|
|
|
4710
5068
|
cb();
|
|
4711
5069
|
};
|
|
4712
5070
|
this.pendingConnectionRequests.add(pending);
|
|
4713
|
-
Promise.resolve().then(
|
|
5071
|
+
Promise.resolve().then(async () => {
|
|
5072
|
+
if (pending.settled) return { started: false };
|
|
5073
|
+
const requestCanStart = canStartRequest();
|
|
5074
|
+
const request = run();
|
|
5075
|
+
if (requestCanStart) try {
|
|
5076
|
+
Promise.resolve(onRequestStarted?.()).catch(() => {});
|
|
5077
|
+
} catch {}
|
|
5078
|
+
return {
|
|
5079
|
+
started: true,
|
|
5080
|
+
value: await request
|
|
5081
|
+
};
|
|
5082
|
+
}).then((outcome) => {
|
|
5083
|
+
if (outcome.started) finish(() => resolve(outcome.value));
|
|
5084
|
+
}, (error) => finish(() => reject(error)));
|
|
4714
5085
|
});
|
|
4715
5086
|
}
|
|
4716
5087
|
rejectPendingConnectionRequests(error) {
|
|
@@ -5977,31 +6348,24 @@ function createActiveSessionController(params) {
|
|
|
5977
6348
|
}
|
|
5978
6349
|
async function withConnectedSession(options) {
|
|
5979
6350
|
const record = await options.loadRecord(options.sessionRecordId);
|
|
5980
|
-
const
|
|
6351
|
+
const clientOptions = {
|
|
5981
6352
|
agentCommand: record.agentCommand,
|
|
6353
|
+
agentArgv: record.agentArgv,
|
|
5982
6354
|
cwd: absolutePath(record.cwd),
|
|
5983
6355
|
mcpServers: options.mcpServers,
|
|
5984
6356
|
permissionMode: options.permissionMode ?? "approve-reads",
|
|
5985
6357
|
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
6358
|
+
permissionPolicy: options.permissionPolicy,
|
|
5986
6359
|
onPermissionRequest: options.onPermissionRequest,
|
|
5987
6360
|
authCredentials: options.authCredentials,
|
|
5988
6361
|
authPolicy: options.authPolicy,
|
|
6362
|
+
fs: options.fs,
|
|
5989
6363
|
terminal: options.terminal,
|
|
6364
|
+
elicitationModes: options.elicitationModes,
|
|
5990
6365
|
verbose: options.verbose,
|
|
5991
6366
|
sessionOptions: sessionOptionsFromRecord(record)
|
|
5992
|
-
}
|
|
5993
|
-
|
|
5994
|
-
cwd: absolutePath(record.cwd),
|
|
5995
|
-
mcpServers: options.mcpServers,
|
|
5996
|
-
permissionMode: options.permissionMode ?? "approve-reads",
|
|
5997
|
-
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
5998
|
-
onPermissionRequest: options.onPermissionRequest,
|
|
5999
|
-
authCredentials: options.authCredentials,
|
|
6000
|
-
authPolicy: options.authPolicy,
|
|
6001
|
-
terminal: options.terminal,
|
|
6002
|
-
verbose: options.verbose,
|
|
6003
|
-
sessionOptions: sessionOptionsFromRecord(record)
|
|
6004
|
-
});
|
|
6367
|
+
};
|
|
6368
|
+
const client = options.createClient?.(clientOptions) ?? new AcpClient(clientOptions);
|
|
6005
6369
|
let activeSessionIdForControl = record.acpSessionId;
|
|
6006
6370
|
let notifiedClientAvailable = false;
|
|
6007
6371
|
const activeController = createActiveSessionController({
|
|
@@ -6073,7 +6437,7 @@ const SESSION_REPLY_IDLE_MS = 1e3;
|
|
|
6073
6437
|
const SESSION_REPLY_DRAIN_TIMEOUT_MS = 5e3;
|
|
6074
6438
|
async function runPromptTurn(params) {
|
|
6075
6439
|
try {
|
|
6076
|
-
const promptPromise = params.client.prompt(params.sessionId, params.prompt);
|
|
6440
|
+
const promptPromise = params.client.prompt(params.sessionId, params.prompt, params.onPromptRequestStarted, params.onElicitation);
|
|
6077
6441
|
await params.onPromptStarted?.();
|
|
6078
6442
|
const response = await withTimeout(promptPromise, params.timeoutMs);
|
|
6079
6443
|
await params.client.waitForSessionUpdatesIdle?.({
|
|
@@ -6152,6 +6516,6 @@ var LiveSessionCheckpoint = class {
|
|
|
6152
6516
|
}
|
|
6153
6517
|
};
|
|
6154
6518
|
//#endregion
|
|
6155
|
-
export {
|
|
6519
|
+
export { writeSessionRecord as $, PERMISSION_POLICY_ACTIONS as $t, REQUESTED_MODEL_UNSUPPORTED_ERROR_CODE as A, TimeoutError as At, getAcpxVersion as B, formatErrorMessage as Bt, mergeSessionOptions as C, PromptInputValidationError as Ct, applyLifecycleSnapshotToRecord as D, promptToDisplayText as Dt, applyConversation as E, parsePromptSource as Et, modelStateFromConfigOptions as F, normalizeAgentName$1 as Ft, findSession as G, toAcpErrorPayload as Gt, DEFAULT_HISTORY_LIMIT as H, normalizeOutputError as Ht, normalizeAgentCommandInput as I, resolveAgentArgv as It, listSessions as J, NON_INTERACTIVE_PERMISSION_POLICIES as Jt, findSessionByDirectoryWalk as K, AUTH_POLICIES as Kt, renderArgvIdentity as L, resolveAgentCommand as Lt, RequestedModelUnsupportedError as M, withTimeout as Mt, assertRequestedModelSupported as N, DEFAULT_AGENT_NAME as Nt, reconcileAgentSessionId as O, textPrompt as Ot, isRequestedModelUnsupportedError as P, listBuiltInAgents as Pt, resolveSessionRecord as Q, PERMISSION_MODES as Qt, runTimedExecFile as R, resolveCanonicalAgentName as Rt, advertisedModelState as S, parsePromptStopReason as St, sessionOptionsFromRecord as T, mergePromptSourceWithText as Tt, absolutePath as U, extractAcpError as Ut, permissionModeSatisfies as V, isRetryablePromptError as Vt, findGitRepositoryRoot as W, isAcpResourceNotFoundError as Wt, normalizeName as X, OUTPUT_ERROR_ORIGINS as Xt, listSessionsForAgent as Y, OUTPUT_ERROR_CODES as Yt, pruneSessions as Z, OUTPUT_FORMATS as Zt, createSessionConversation as _, sessionEventLockPath as _t, applyRequestedModelIfAdvertised as a, measurePerf as at, recordSessionUpdate as b, isAcpJsonRpcMessage as bt, setCurrentModelId as c, setPerfGauge as ct, setDesiredModelId as d, serializeSessionRecordForDisk as dt, SESSION_RECORD_SCHEMA as en, createAtomicWriteTempPath as et, syncAdvertisedModelState as f, normalizeRuntimeSessionId as ft, cloneSessionConversation as g, sessionEventActivePath as gt, cloneSessionAcpxState as h, sessionBaseDir$1 as ht, connectAndLoadSession as i, QueueProtocolError as in, incrementPerfCounter as it, REQUESTED_MODEL_UNSUPPORTED_REASONS as j, withInterrupt as jt, AcpClient as k, InterruptedError as kt, setDesiredConfigOption as l, startPerfTimer as lt, applyConfigOptionsToState as m, defaultSessionEventLog as mt, runPromptTurn as n, AgentSpawnError as nn, formatPerfMetric as nt, currentModelIdFromSetModelResponse as o, recordPerfDuration as ot, applyConfigOptionsToRecord as p, DEFAULT_EVENT_SEGMENT_MAX_BYTES as pt, isoNow$2 as q, EXIT_CODES as qt, withConnectedSession as r, QueueConnectionError as rn, getPerfMetricsSnapshot as rt, clearDesiredConfigOption as s, resetPerfMetrics as st, LiveSessionCheckpoint as t, AcpxOperationalError as tn, assertPersistedKeyPolicy as tt, setDesiredModeId as u, parseSessionRecord as ut, recordClientOperation as v, sessionEventSegmentPath as vt, persistSessionOptions as w, isPromptInput as wt, trimConversationForRuntime as x, parseJsonRpcErrorMessage as xt, recordPromptSubmission as y, extractSessionUpdateNotification as yt, splitCommandLine as z, exitCodeForOutputErrorCode as zt };
|
|
6156
6520
|
|
|
6157
|
-
//# sourceMappingURL=live-checkpoint-
|
|
6521
|
+
//# sourceMappingURL=live-checkpoint-BSIrfgVo.js.map
|