acpx 0.14.0 → 0.15.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 +3 -3
- package/dist/{cli-DSwJ-0g-.js → cli-BHAT_D3V.js} +4 -4
- package/dist/{cli-DSwJ-0g-.js.map → cli-BHAT_D3V.js.map} +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +8 -7
- package/dist/cli.js.map +1 -1
- package/dist/{client-IfFkZz0S.d.ts → client-Cvz6msGc.d.ts} +6 -2
- package/dist/client-Cvz6msGc.d.ts.map +1 -0
- package/dist/{flags-ftdtbXWd.js → flags-BHcZWTov.js} +3 -3
- package/dist/{flags-ftdtbXWd.js.map → flags-BHcZWTov.js.map} +1 -1
- package/dist/{flows-DEook1GU.js → flows-BOI1XkMp.js} +52 -11
- package/dist/flows-BOI1XkMp.js.map +1 -0
- package/dist/flows.d.ts +4 -2
- package/dist/flows.d.ts.map +1 -1
- package/dist/flows.js +1 -1
- package/dist/{live-checkpoint-BW9JivEG.js → live-checkpoint-sB7dFOYR.js} +272 -86
- package/dist/live-checkpoint-sB7dFOYR.js.map +1 -0
- package/dist/{output-jb0298L8.js → output-8-D6Gd4Z.js} +41 -9
- package/dist/output-8-D6Gd4Z.js.map +1 -0
- package/dist/runtime.d.ts +10 -3
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +45 -7
- package/dist/runtime.js.map +1 -1
- package/dist/{session-options-DwRDODlr.d.ts → session-options-DyIGRNfu.d.ts} +48 -2
- package/dist/session-options-DyIGRNfu.d.ts.map +1 -0
- package/package.json +2 -2
- package/skills/acpx/SKILL.md +2 -0
- package/dist/client-IfFkZz0S.d.ts.map +0 -1
- package/dist/flows-DEook1GU.js.map +0 -1
- package/dist/live-checkpoint-BW9JivEG.js.map +0 -1
- package/dist/output-jb0298L8.js.map +0 -1
- package/dist/session-options-DwRDODlr.d.ts.map +0 -1
|
@@ -454,6 +454,7 @@ const AGENT_REGISTRY = {
|
|
|
454
454
|
kilocode: "npx -y @kilocode/cli acp",
|
|
455
455
|
kimi: "kimi acp",
|
|
456
456
|
kiro: "kiro-cli-chat acp",
|
|
457
|
+
mcode: "mcode acp",
|
|
457
458
|
mux: `npx -y mux@${ACP_ADAPTER_PACKAGE_RANGES.mux} acp`,
|
|
458
459
|
opencode: "npx -y opencode-ai acp",
|
|
459
460
|
pool: "pool acp",
|
|
@@ -507,6 +508,7 @@ const AGENT_ARGV_REGISTRY = {
|
|
|
507
508
|
],
|
|
508
509
|
kimi: ["kimi", "acp"],
|
|
509
510
|
kiro: ["kiro-cli-chat", "acp"],
|
|
511
|
+
mcode: ["mcode", "acp"],
|
|
510
512
|
mux: [
|
|
511
513
|
"npx",
|
|
512
514
|
"-y",
|
|
@@ -3145,14 +3147,18 @@ function promotePrefixedAuthEnvironment(env) {
|
|
|
3145
3147
|
}
|
|
3146
3148
|
return protectedKeys;
|
|
3147
3149
|
}
|
|
3148
|
-
function
|
|
3150
|
+
function validateAgentProcessEnv(agentProcessEnv) {
|
|
3151
|
+
for (const [key, value] of Object.entries(agentProcessEnv ?? {})) if (typeof value !== "string" || key.includes("=") || key.includes("\0") || value.includes("\0")) throw new Error("Invalid agentProcessEnv: environment entries cannot contain NUL or names with '='");
|
|
3152
|
+
}
|
|
3153
|
+
function buildAgentEnvironment(authCredentials, sessionEnv, agentProcessEnv) {
|
|
3154
|
+
validateAgentProcessEnv(agentProcessEnv);
|
|
3149
3155
|
const env = { ...process.env };
|
|
3150
3156
|
const protectedAuthEnvKeys = promotePrefixedAuthEnvironment(env);
|
|
3151
3157
|
if (authCredentials) for (const [methodId, credential] of Object.entries(authCredentials)) {
|
|
3152
3158
|
addAuthCredentialEnvKeys(protectedAuthEnvKeys, methodId, credential);
|
|
3153
3159
|
assignAuthCredentialEnv(env, methodId, credential);
|
|
3154
3160
|
}
|
|
3155
|
-
|
|
3161
|
+
for (const overlay of [sessionEnv, agentProcessEnv]) for (const [key, value] of Object.entries(overlay ?? {})) {
|
|
3156
3162
|
if (typeof value !== "string" || protectedAuthEnvKeys.has(protectedEnvKey(key))) continue;
|
|
3157
3163
|
assignSessionEnv(env, key, value);
|
|
3158
3164
|
}
|
|
@@ -3188,10 +3194,10 @@ function resolveConfiguredAuthCredential(methodId, authCredentials) {
|
|
|
3188
3194
|
const configCredentials = authCredentials ?? {};
|
|
3189
3195
|
return configCredentials[methodId] ?? configCredentials[toEnvToken(methodId)];
|
|
3190
3196
|
}
|
|
3191
|
-
function buildAgentSpawnOptions(cwd, authCredentials, sessionEnv) {
|
|
3197
|
+
function buildAgentSpawnOptions(cwd, authCredentials, sessionEnv, agentProcessEnv) {
|
|
3192
3198
|
return {
|
|
3193
3199
|
cwd,
|
|
3194
|
-
env: buildAgentEnvironment(authCredentials, sessionEnv),
|
|
3200
|
+
env: buildAgentEnvironment(authCredentials, sessionEnv, agentProcessEnv),
|
|
3195
3201
|
stdio: [
|
|
3196
3202
|
"pipe",
|
|
3197
3203
|
"pipe",
|
|
@@ -3320,6 +3326,94 @@ function assertRequestedModelSupported(params) {
|
|
|
3320
3326
|
}
|
|
3321
3327
|
}
|
|
3322
3328
|
//#endregion
|
|
3329
|
+
//#region src/acp/ndjson-stream.ts
|
|
3330
|
+
const DEFAULT_MAX_ACP_MESSAGE_BYTES = 67108864;
|
|
3331
|
+
var AcpMessageLimitError = class extends AcpxOperationalError {
|
|
3332
|
+
constructor(limit) {
|
|
3333
|
+
super(`ACP message exceeded ACPX_MAX_ACP_MESSAGE_BYTES (${limit} bytes). Increase the limit or set it to 0 for unlimited input.`, {
|
|
3334
|
+
outputCode: "RUNTIME",
|
|
3335
|
+
detailCode: "ACP_MESSAGE_TOO_LARGE",
|
|
3336
|
+
origin: "acp",
|
|
3337
|
+
retryable: false
|
|
3338
|
+
});
|
|
3339
|
+
}
|
|
3340
|
+
};
|
|
3341
|
+
function readMaxAcpMessageBytes(raw = process.env.ACPX_MAX_ACP_MESSAGE_BYTES) {
|
|
3342
|
+
const value = raw?.trim();
|
|
3343
|
+
if (!value) return DEFAULT_MAX_ACP_MESSAGE_BYTES;
|
|
3344
|
+
const bytes = Number(value);
|
|
3345
|
+
if (!/^\d+$/.test(value) || !Number.isSafeInteger(bytes)) throw new Error("ACPX_MAX_ACP_MESSAGE_BYTES must be a non-negative safe integer; zero is unlimited");
|
|
3346
|
+
return bytes === 0 ? void 0 : bytes;
|
|
3347
|
+
}
|
|
3348
|
+
function countLineBytes(chunk, retained, limit) {
|
|
3349
|
+
let start = 0;
|
|
3350
|
+
while (start < chunk.length) {
|
|
3351
|
+
const newline = chunk.indexOf(10, start);
|
|
3352
|
+
const end = newline < 0 ? chunk.length : newline;
|
|
3353
|
+
retained += end - start;
|
|
3354
|
+
if (retained > limit) throw new AcpMessageLimitError(limit);
|
|
3355
|
+
if (newline < 0) return retained;
|
|
3356
|
+
retained = 0;
|
|
3357
|
+
start = end + 1;
|
|
3358
|
+
}
|
|
3359
|
+
return retained;
|
|
3360
|
+
}
|
|
3361
|
+
function parseAcpJsonMessageLine(line) {
|
|
3362
|
+
const message = JSON.parse(line);
|
|
3363
|
+
return isAcpMessageObject(message) ? message : void 0;
|
|
3364
|
+
}
|
|
3365
|
+
function enqueueNdJsonLine(agentCommand, line, controller) {
|
|
3366
|
+
const trimmedLine = line.trim();
|
|
3367
|
+
if (!trimmedLine || shouldIgnoreNonJsonAgentOutputLine(agentCommand, trimmedLine)) return;
|
|
3368
|
+
try {
|
|
3369
|
+
const message = parseAcpJsonMessageLine(trimmedLine);
|
|
3370
|
+
if (message) controller.enqueue(message);
|
|
3371
|
+
} catch (err) {
|
|
3372
|
+
console.error("Failed to parse JSON message:", trimmedLine, err);
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
function enqueueNdJsonLines(agentCommand, lines, controller) {
|
|
3376
|
+
for (const line of lines) enqueueNdJsonLine(agentCommand, line, controller);
|
|
3377
|
+
}
|
|
3378
|
+
function createNdJsonMessageStream(agentCommand, output, input, maxMessageBytes, onReadError) {
|
|
3379
|
+
const textEncoder = new TextEncoder();
|
|
3380
|
+
const textDecoder = new TextDecoder();
|
|
3381
|
+
return {
|
|
3382
|
+
readable: new ReadableStream({ async start(controller) {
|
|
3383
|
+
let content = "";
|
|
3384
|
+
let retainedBytes = 0;
|
|
3385
|
+
const reader = input.getReader();
|
|
3386
|
+
try {
|
|
3387
|
+
while (true) {
|
|
3388
|
+
const { value, done } = await reader.read();
|
|
3389
|
+
if (done) break;
|
|
3390
|
+
if (maxMessageBytes !== void 0) retainedBytes = countLineBytes(value, retainedBytes, maxMessageBytes);
|
|
3391
|
+
content += textDecoder.decode(value, { stream: true });
|
|
3392
|
+
const lines = content.split("\n");
|
|
3393
|
+
content = lines.pop() || "";
|
|
3394
|
+
enqueueNdJsonLines(agentCommand, lines, controller);
|
|
3395
|
+
}
|
|
3396
|
+
controller.close();
|
|
3397
|
+
} catch (err) {
|
|
3398
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
3399
|
+
controller.error(error);
|
|
3400
|
+
onReadError?.(error);
|
|
3401
|
+
} finally {
|
|
3402
|
+
reader.releaseLock();
|
|
3403
|
+
}
|
|
3404
|
+
} }),
|
|
3405
|
+
writable: new WritableStream({ async write(message) {
|
|
3406
|
+
const content = JSON.stringify(message) + "\n";
|
|
3407
|
+
const writer = output.getWriter();
|
|
3408
|
+
try {
|
|
3409
|
+
await writer.write(textEncoder.encode(content));
|
|
3410
|
+
} finally {
|
|
3411
|
+
writer.releaseLock();
|
|
3412
|
+
}
|
|
3413
|
+
} })
|
|
3414
|
+
};
|
|
3415
|
+
}
|
|
3416
|
+
//#endregion
|
|
3323
3417
|
//#region src/acp/session-control-errors.ts
|
|
3324
3418
|
const SESSION_CONTROL_UNSUPPORTED_ACP_CODES = /* @__PURE__ */ new Set([-32601, -32602]);
|
|
3325
3419
|
function asRecord$1(value) {
|
|
@@ -3376,6 +3470,13 @@ function buildTerminalSpawnOptions(command, cwd, env, platform = process.platfor
|
|
|
3376
3470
|
windowsHide: true
|
|
3377
3471
|
}, platform, resolvedEnv ?? process.env);
|
|
3378
3472
|
}
|
|
3473
|
+
function readTerminalOutputCeiling() {
|
|
3474
|
+
const raw = process.env.ACPX_TERMINAL_MAX_OUTPUT_BYTES?.trim();
|
|
3475
|
+
if (!raw) return;
|
|
3476
|
+
const bytes = Number(raw);
|
|
3477
|
+
if (!/^\d+$/.test(raw) || !Number.isSafeInteger(bytes)) throw new Error("ACPX_TERMINAL_MAX_OUTPUT_BYTES must be a non-negative safe integer; zero disables the host ceiling");
|
|
3478
|
+
return bytes === 0 ? void 0 : bytes;
|
|
3479
|
+
}
|
|
3379
3480
|
function trimToUtf8Boundary(buffer, limit) {
|
|
3380
3481
|
if (limit <= 0) return Buffer.alloc(0);
|
|
3381
3482
|
if (buffer.length <= limit) return buffer;
|
|
@@ -3419,8 +3520,10 @@ var TerminalManager = class {
|
|
|
3419
3520
|
confirmExecute;
|
|
3420
3521
|
killGraceMs;
|
|
3421
3522
|
processHelperTimeoutMs;
|
|
3523
|
+
outputCeilingBytes;
|
|
3422
3524
|
terminals = /* @__PURE__ */ new Map();
|
|
3423
3525
|
constructor(options) {
|
|
3526
|
+
this.outputCeilingBytes = readTerminalOutputCeiling();
|
|
3424
3527
|
this.cwd = options.cwd;
|
|
3425
3528
|
this.permissionMode = options.permissionMode;
|
|
3426
3529
|
this.nonInteractivePermissions = options.nonInteractivePermissions ?? "deny";
|
|
@@ -3445,7 +3548,8 @@ var TerminalManager = class {
|
|
|
3445
3548
|
});
|
|
3446
3549
|
try {
|
|
3447
3550
|
if (!await this.isExecuteApproved(commandLine)) throw new PermissionDeniedError("Permission denied for terminal/create");
|
|
3448
|
-
const
|
|
3551
|
+
const requestedLimit = Math.max(0, Math.round(params.outputByteLimit ?? DEFAULT_TERMINAL_OUTPUT_LIMIT_BYTES));
|
|
3552
|
+
const outputByteLimit = Math.min(requestedLimit, this.outputCeilingBytes ?? Number.POSITIVE_INFINITY);
|
|
3449
3553
|
const { proc, spawnCommand } = await spawnTerminalProcess(params, this.cwd);
|
|
3450
3554
|
let resolveExit = () => {};
|
|
3451
3555
|
const exitPromise = new Promise((resolve) => {
|
|
@@ -4006,6 +4110,17 @@ function snapshotPermissionPolicy(policy) {
|
|
|
4006
4110
|
...policy.defaultAction ? { defaultAction: policy.defaultAction } : {}
|
|
4007
4111
|
};
|
|
4008
4112
|
}
|
|
4113
|
+
function snapshotProcessLaunchScope(scope) {
|
|
4114
|
+
if (!scope || scope.kind === "client") return Object.freeze({ kind: "client" });
|
|
4115
|
+
if (scope.kind === "runtime-session") return Object.freeze({
|
|
4116
|
+
kind: "runtime-session",
|
|
4117
|
+
sessionKey: scope.sessionKey
|
|
4118
|
+
});
|
|
4119
|
+
return Object.freeze({
|
|
4120
|
+
kind: "runtime-probe",
|
|
4121
|
+
agent: scope.agent
|
|
4122
|
+
});
|
|
4123
|
+
}
|
|
4009
4124
|
function childProcessIsRunning(agent) {
|
|
4010
4125
|
if (!agent) return false;
|
|
4011
4126
|
return agent.exitCode == null && agent.signalCode == null && !agent.killed;
|
|
@@ -4027,56 +4142,6 @@ function installSdkConsoleErrorSuppression() {
|
|
|
4027
4142
|
console.error = originalConsoleError;
|
|
4028
4143
|
};
|
|
4029
4144
|
}
|
|
4030
|
-
function enqueueNdJsonLine(agentCommand, line, controller) {
|
|
4031
|
-
const trimmedLine = line.trim();
|
|
4032
|
-
if (!trimmedLine || shouldIgnoreNonJsonAgentOutputLine(agentCommand, trimmedLine)) return;
|
|
4033
|
-
try {
|
|
4034
|
-
const message = parseAcpJsonMessageLine(trimmedLine);
|
|
4035
|
-
if (message) controller.enqueue(message);
|
|
4036
|
-
} catch (err) {
|
|
4037
|
-
console.error("Failed to parse JSON message:", trimmedLine, err);
|
|
4038
|
-
}
|
|
4039
|
-
}
|
|
4040
|
-
function parseAcpJsonMessageLine(line) {
|
|
4041
|
-
const message = JSON.parse(line);
|
|
4042
|
-
return isAcpMessageObject(message) ? message : void 0;
|
|
4043
|
-
}
|
|
4044
|
-
function enqueueNdJsonLines(agentCommand, lines, controller) {
|
|
4045
|
-
for (const line of lines) enqueueNdJsonLine(agentCommand, line, controller);
|
|
4046
|
-
}
|
|
4047
|
-
function createNdJsonMessageStream(agentCommand, output, input) {
|
|
4048
|
-
const textEncoder = new TextEncoder();
|
|
4049
|
-
const textDecoder = new TextDecoder();
|
|
4050
|
-
return {
|
|
4051
|
-
readable: new ReadableStream({ async start(controller) {
|
|
4052
|
-
let content = "";
|
|
4053
|
-
const reader = input.getReader();
|
|
4054
|
-
try {
|
|
4055
|
-
while (true) {
|
|
4056
|
-
const { value, done } = await reader.read();
|
|
4057
|
-
if (done) break;
|
|
4058
|
-
if (!value) continue;
|
|
4059
|
-
content += textDecoder.decode(value, { stream: true });
|
|
4060
|
-
const lines = content.split("\n");
|
|
4061
|
-
content = lines.pop() || "";
|
|
4062
|
-
enqueueNdJsonLines(agentCommand, lines, controller);
|
|
4063
|
-
}
|
|
4064
|
-
} finally {
|
|
4065
|
-
reader.releaseLock();
|
|
4066
|
-
controller.close();
|
|
4067
|
-
}
|
|
4068
|
-
} }),
|
|
4069
|
-
writable: new WritableStream({ async write(message) {
|
|
4070
|
-
const content = JSON.stringify(message) + "\n";
|
|
4071
|
-
const writer = output.getWriter();
|
|
4072
|
-
try {
|
|
4073
|
-
await writer.write(textEncoder.encode(content));
|
|
4074
|
-
} finally {
|
|
4075
|
-
writer.releaseLock();
|
|
4076
|
-
}
|
|
4077
|
-
} })
|
|
4078
|
-
};
|
|
4079
|
-
}
|
|
4080
4145
|
var AcpClient = class {
|
|
4081
4146
|
options;
|
|
4082
4147
|
connection;
|
|
@@ -4113,6 +4178,7 @@ var AcpClient = class {
|
|
|
4113
4178
|
this.options = {
|
|
4114
4179
|
...options,
|
|
4115
4180
|
cwd: asAbsoluteCwd(options.cwd),
|
|
4181
|
+
agentProcessEnv: options.agentProcessEnv ? { ...options.agentProcessEnv } : void 0,
|
|
4116
4182
|
authPolicy: options.authPolicy ?? "skip",
|
|
4117
4183
|
permissionPolicy: snapshotPermissionPolicy(options.permissionPolicy),
|
|
4118
4184
|
elicitationModes: normalizeElicitationModes(options.elicitationModes)
|
|
@@ -4217,29 +4283,41 @@ var AcpClient = class {
|
|
|
4217
4283
|
async start() {
|
|
4218
4284
|
if (this.connection && this.agent && isChildProcessRunning(this.agent)) return;
|
|
4219
4285
|
if (this.connection || this.agent) await this.close();
|
|
4286
|
+
const maxMessageBytes = readMaxAcpMessageBytes();
|
|
4220
4287
|
const launch = await this.resolveAgentLaunchPlan();
|
|
4221
4288
|
this.logAgentLaunch(launch);
|
|
4222
4289
|
await this.ensureLaunchSupport(launch);
|
|
4223
|
-
const child = await this.spawnAgentProcess(launch);
|
|
4290
|
+
const { child, process: startedProcess } = await this.spawnAgentProcess(launch);
|
|
4224
4291
|
this.closing = false;
|
|
4225
|
-
this.agentStartedAt =
|
|
4292
|
+
this.agentStartedAt = startedProcess.startedAt;
|
|
4226
4293
|
this.lastAgentExit = void 0;
|
|
4227
|
-
this.lastKnownPid =
|
|
4228
|
-
this.attachAgentLifecycleObservers(child);
|
|
4294
|
+
this.lastKnownPid = startedProcess.pid;
|
|
4229
4295
|
const startupStderr = [];
|
|
4230
4296
|
child.stderr.on("data", (chunk) => {
|
|
4231
4297
|
this.captureStartupStderr(startupStderr, chunk);
|
|
4232
4298
|
if (!this.options.verbose) return;
|
|
4233
4299
|
process.stderr.write(chunk);
|
|
4234
4300
|
});
|
|
4301
|
+
const startupFailure = this.createStartupFailureWatcher(child, startupStderr);
|
|
4302
|
+
try {
|
|
4303
|
+
await this.admitAndObserveSpawnedProcess(child, startedProcess);
|
|
4304
|
+
const admissionExit = startupFailure.getError();
|
|
4305
|
+
if (admissionExit) throw admissionExit;
|
|
4306
|
+
} catch (error) {
|
|
4307
|
+
startupFailure.dispose();
|
|
4308
|
+
throw error;
|
|
4309
|
+
}
|
|
4235
4310
|
const input = Writable.toWeb(child.stdin);
|
|
4236
4311
|
const output = Readable.toWeb(child.stdout);
|
|
4237
|
-
|
|
4238
|
-
const
|
|
4312
|
+
let connection;
|
|
4313
|
+
const stream = this.createTappedStream(createNdJsonMessageStream(this.options.agentCommand, input, output, maxMessageBytes, (error) => {
|
|
4314
|
+
this.rejectPendingConnectionRequests(error);
|
|
4315
|
+
connection?.close?.(error);
|
|
4316
|
+
}));
|
|
4317
|
+
connection = this.createConnection(stream, launch);
|
|
4239
4318
|
connection.signal.addEventListener("abort", () => {
|
|
4240
4319
|
this.recordAgentExit("connection_close", child.exitCode ?? null, child.signalCode ?? null);
|
|
4241
4320
|
}, { once: true });
|
|
4242
|
-
const startupFailure = this.createStartupFailureWatcher(child, startupStderr);
|
|
4243
4321
|
await this.initializeAgentConnection({
|
|
4244
4322
|
child,
|
|
4245
4323
|
connection,
|
|
@@ -4263,7 +4341,7 @@ var AcpClient = class {
|
|
|
4263
4341
|
geminiAcp: isGeminiAcpCommand(spawnCommand, args),
|
|
4264
4342
|
copilotAcp: isCopilotAcpCommand(spawnCommand, args),
|
|
4265
4343
|
claudeAcp: isClaudeAcpCommand(spawnCommand, args),
|
|
4266
|
-
spawnOptions: buildAgentSpawnOptions(this.options.cwd, this.options.authCredentials, this.options.sessionOptions?.env)
|
|
4344
|
+
spawnOptions: buildAgentSpawnOptions(this.options.cwd, this.options.authCredentials, this.options.sessionOptions?.env, this.options.agentProcessEnv)
|
|
4267
4345
|
};
|
|
4268
4346
|
}
|
|
4269
4347
|
logAgentLaunch(plan) {
|
|
@@ -4289,16 +4367,57 @@ var AcpClient = class {
|
|
|
4289
4367
|
}
|
|
4290
4368
|
async spawnAgentProcess(plan) {
|
|
4291
4369
|
const spawnCommand = buildAgentSpawnCommand(plan.spawnCommand, plan.args, process.platform, plan.spawnOptions.env);
|
|
4292
|
-
const
|
|
4293
|
-
|
|
4294
|
-
|
|
4370
|
+
const launch = Object.freeze({
|
|
4371
|
+
launchId: randomUUID(),
|
|
4372
|
+
scope: snapshotProcessLaunchScope(this.options.processLaunchScope),
|
|
4373
|
+
command: spawnCommand.command,
|
|
4374
|
+
args: Object.freeze([...spawnCommand.args]),
|
|
4375
|
+
cwd: this.options.cwd
|
|
4295
4376
|
});
|
|
4377
|
+
await this.options.processLifecycle?.onBeforeSpawn?.(launch);
|
|
4378
|
+
let spawnedChild;
|
|
4296
4379
|
try {
|
|
4380
|
+
spawnedChild = spawn(spawnCommand.command, spawnCommand.args, {
|
|
4381
|
+
...plan.spawnOptions,
|
|
4382
|
+
windowsVerbatimArguments: spawnCommand.windowsVerbatimArguments
|
|
4383
|
+
});
|
|
4297
4384
|
await waitForSpawn$1(spawnedChild);
|
|
4298
4385
|
} catch (error) {
|
|
4299
|
-
|
|
4386
|
+
const spawnError = new AgentSpawnError(this.options.agentCommand, error);
|
|
4387
|
+
this.notifyProcessSpawnFailure(launch, spawnError);
|
|
4388
|
+
throw spawnError;
|
|
4389
|
+
}
|
|
4390
|
+
const child = requireAgentStdio(spawnedChild);
|
|
4391
|
+
const pid = child.pid;
|
|
4392
|
+
if (pid === void 0) {
|
|
4393
|
+
const spawnError = new AgentSpawnError(this.options.agentCommand, /* @__PURE__ */ new Error("spawned agent process did not expose a PID"));
|
|
4394
|
+
this.notifyProcessSpawnFailure(launch, spawnError);
|
|
4395
|
+
await this.terminateAgentProcess(child);
|
|
4396
|
+
throw spawnError;
|
|
4397
|
+
}
|
|
4398
|
+
return {
|
|
4399
|
+
child,
|
|
4400
|
+
process: Object.freeze({
|
|
4401
|
+
...launch,
|
|
4402
|
+
pid,
|
|
4403
|
+
startedAt: isoNow$1()
|
|
4404
|
+
})
|
|
4405
|
+
};
|
|
4406
|
+
}
|
|
4407
|
+
async admitAndObserveSpawnedProcess(child, process) {
|
|
4408
|
+
let releaseExitNotification = () => {};
|
|
4409
|
+
const exitNotificationBarrier = new Promise((resolve) => {
|
|
4410
|
+
releaseExitNotification = resolve;
|
|
4411
|
+
});
|
|
4412
|
+
this.attachAgentLifecycleObservers(child, process, exitNotificationBarrier);
|
|
4413
|
+
try {
|
|
4414
|
+
await this.options.processLifecycle?.onSpawned?.(process);
|
|
4415
|
+
} catch (error) {
|
|
4416
|
+
await this.terminateAgentProcess(child);
|
|
4417
|
+
throw error;
|
|
4418
|
+
} finally {
|
|
4419
|
+
releaseExitNotification();
|
|
4300
4420
|
}
|
|
4301
|
-
return requireAgentStdio(spawnedChild);
|
|
4302
4421
|
}
|
|
4303
4422
|
createConnection(stream, launch) {
|
|
4304
4423
|
const app = client({ name: "acpx" }).onNotification(methods.client.session.update, async ({ params }) => {
|
|
@@ -4357,7 +4476,7 @@ var AcpClient = class {
|
|
|
4357
4476
|
}
|
|
4358
4477
|
async handleInitializeFailure(params, error) {
|
|
4359
4478
|
params.startupFailure.dispose();
|
|
4360
|
-
const normalizedError = await this.normalizeInitializeError(error, params.child, params.startupStderr);
|
|
4479
|
+
const normalizedError = error instanceof AcpMessageLimitError ? error : await this.normalizeInitializeError(error, params.child, params.startupStderr);
|
|
4361
4480
|
try {
|
|
4362
4481
|
params.child.kill();
|
|
4363
4482
|
} catch {}
|
|
@@ -4822,6 +4941,7 @@ var AcpClient = class {
|
|
|
4822
4941
|
}
|
|
4823
4942
|
createStartupFailureWatcher(child, startupStderr) {
|
|
4824
4943
|
let settled = false;
|
|
4944
|
+
let failure;
|
|
4825
4945
|
let rejectPromise;
|
|
4826
4946
|
const cleanup = () => {
|
|
4827
4947
|
child.off("error", onError);
|
|
@@ -4832,7 +4952,10 @@ var AcpClient = class {
|
|
|
4832
4952
|
if (settled) return;
|
|
4833
4953
|
settled = true;
|
|
4834
4954
|
cleanup();
|
|
4835
|
-
if (error)
|
|
4955
|
+
if (error) {
|
|
4956
|
+
failure = error;
|
|
4957
|
+
rejectPromise(error);
|
|
4958
|
+
}
|
|
4836
4959
|
};
|
|
4837
4960
|
const createError = (params) => new AgentStartupError({
|
|
4838
4961
|
agentCommand: this.options.agentCommand,
|
|
@@ -4856,14 +4979,18 @@ var AcpClient = class {
|
|
|
4856
4979
|
signal
|
|
4857
4980
|
}));
|
|
4858
4981
|
};
|
|
4982
|
+
const promise = new Promise((_resolve, reject) => {
|
|
4983
|
+
rejectPromise = reject;
|
|
4984
|
+
child.once("error", onError);
|
|
4985
|
+
child.once("exit", onExit);
|
|
4986
|
+
child.once("close", onClose);
|
|
4987
|
+
if (child.exitCode !== null || child.signalCode !== null) onExit(child.exitCode, child.signalCode);
|
|
4988
|
+
});
|
|
4989
|
+
promise.catch(() => {});
|
|
4859
4990
|
return {
|
|
4860
|
-
promise
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
child.once("exit", onExit);
|
|
4864
|
-
child.once("close", onClose);
|
|
4865
|
-
}),
|
|
4866
|
-
dispose: () => finish()
|
|
4991
|
+
promise,
|
|
4992
|
+
dispose: () => finish(),
|
|
4993
|
+
getError: () => failure
|
|
4867
4994
|
};
|
|
4868
4995
|
}
|
|
4869
4996
|
async normalizeInitializeError(error, child, startupStderr) {
|
|
@@ -5043,10 +5170,19 @@ var AcpClient = class {
|
|
|
5043
5170
|
recorded: true
|
|
5044
5171
|
};
|
|
5045
5172
|
}
|
|
5046
|
-
attachAgentLifecycleObservers(child) {
|
|
5047
|
-
|
|
5173
|
+
attachAgentLifecycleObservers(child, startedProcess, exitNotificationBarrier) {
|
|
5174
|
+
const onExit = (exitCode, signal) => {
|
|
5175
|
+
const exitedAt = isoNow$1();
|
|
5048
5176
|
this.recordAgentExit("process_exit", exitCode, signal);
|
|
5049
|
-
|
|
5177
|
+
exitNotificationBarrier.then(() => {
|
|
5178
|
+
this.notifyProcessExit(startedProcess, exitCode, signal, exitedAt);
|
|
5179
|
+
});
|
|
5180
|
+
};
|
|
5181
|
+
child.once("exit", onExit);
|
|
5182
|
+
if (child.exitCode !== null || child.signalCode !== null) {
|
|
5183
|
+
child.off("exit", onExit);
|
|
5184
|
+
onExit(child.exitCode, child.signalCode);
|
|
5185
|
+
}
|
|
5050
5186
|
child.once("close", (exitCode, signal) => {
|
|
5051
5187
|
this.recordAgentExit("process_close", exitCode, signal);
|
|
5052
5188
|
});
|
|
@@ -5054,6 +5190,43 @@ var AcpClient = class {
|
|
|
5054
5190
|
this.recordAgentExit("pipe_close", child.exitCode ?? null, child.signalCode ?? null);
|
|
5055
5191
|
});
|
|
5056
5192
|
}
|
|
5193
|
+
notifyProcessSpawnFailure(launch, error) {
|
|
5194
|
+
const handler = this.options.processLifecycle?.onSpawnFailed;
|
|
5195
|
+
if (!handler) return;
|
|
5196
|
+
const event = Object.freeze({
|
|
5197
|
+
...launch,
|
|
5198
|
+
error,
|
|
5199
|
+
failedAt: isoNow$1()
|
|
5200
|
+
});
|
|
5201
|
+
try {
|
|
5202
|
+
Promise.resolve(handler(event)).catch((observerError) => {
|
|
5203
|
+
this.logProcessLifecycleError("onSpawnFailed", observerError);
|
|
5204
|
+
});
|
|
5205
|
+
} catch (observerError) {
|
|
5206
|
+
this.logProcessLifecycleError("onSpawnFailed", observerError);
|
|
5207
|
+
}
|
|
5208
|
+
}
|
|
5209
|
+
notifyProcessExit(startedProcess, exitCode, signal, exitedAt) {
|
|
5210
|
+
const handler = this.options.processLifecycle?.onExit;
|
|
5211
|
+
if (!handler) return;
|
|
5212
|
+
const event = Object.freeze({
|
|
5213
|
+
...startedProcess,
|
|
5214
|
+
exitCode,
|
|
5215
|
+
signal,
|
|
5216
|
+
exitedAt
|
|
5217
|
+
});
|
|
5218
|
+
try {
|
|
5219
|
+
Promise.resolve(handler(event)).catch((error) => {
|
|
5220
|
+
this.logProcessLifecycleError("onExit", error);
|
|
5221
|
+
});
|
|
5222
|
+
} catch (error) {
|
|
5223
|
+
this.logProcessLifecycleError("onExit", error);
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
logProcessLifecycleError(hook, error) {
|
|
5227
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5228
|
+
this.log(`process lifecycle ${hook} hook failed: ${message}`);
|
|
5229
|
+
}
|
|
5057
5230
|
recordAgentExit(reason, exitCode, signal) {
|
|
5058
5231
|
if (this.lastAgentExit) return;
|
|
5059
5232
|
this.lastAgentExit = {
|
|
@@ -6482,9 +6655,24 @@ async function withConnectedSession(options) {
|
|
|
6482
6655
|
//#region src/runtime/engine/prompt-turn.ts
|
|
6483
6656
|
const SESSION_REPLY_IDLE_MS = 1e3;
|
|
6484
6657
|
const SESSION_REPLY_DRAIN_TIMEOUT_MS = 5e3;
|
|
6658
|
+
function responseMetaField(meta) {
|
|
6659
|
+
return meta === void 0 ? {} : { _meta: meta };
|
|
6660
|
+
}
|
|
6661
|
+
function recoveredSessionResult(response, conversation, promptMessageId) {
|
|
6662
|
+
recordPromptResponseUsage(conversation, response?.usage, promptMessageId);
|
|
6663
|
+
return {
|
|
6664
|
+
stopReason: "end_turn",
|
|
6665
|
+
source: "session",
|
|
6666
|
+
...responseMetaField(response?._meta)
|
|
6667
|
+
};
|
|
6668
|
+
}
|
|
6485
6669
|
async function runPromptTurn(params) {
|
|
6670
|
+
let settledResponse;
|
|
6486
6671
|
try {
|
|
6487
6672
|
const promptPromise = params.client.prompt(params.sessionId, params.prompt, params.onPromptRequestWritten, params.onElicitation);
|
|
6673
|
+
promptPromise.then((response) => {
|
|
6674
|
+
settledResponse = response;
|
|
6675
|
+
}, () => {});
|
|
6488
6676
|
await params.onPromptStarted?.();
|
|
6489
6677
|
const response = await withTimeout(promptPromise, params.timeoutMs);
|
|
6490
6678
|
await params.client.waitForSessionUpdatesIdle?.({
|
|
@@ -6494,7 +6682,8 @@ async function runPromptTurn(params) {
|
|
|
6494
6682
|
recordPromptResponseUsage(params.conversation, response.usage, params.promptMessageId);
|
|
6495
6683
|
return {
|
|
6496
6684
|
stopReason: response.stopReason,
|
|
6497
|
-
source: "rpc"
|
|
6685
|
+
source: "rpc",
|
|
6686
|
+
...responseMetaField(response._meta)
|
|
6498
6687
|
};
|
|
6499
6688
|
} catch (error) {
|
|
6500
6689
|
if (!(error instanceof TimeoutError) || !params.promptMessageId) throw error;
|
|
@@ -6502,10 +6691,7 @@ async function runPromptTurn(params) {
|
|
|
6502
6691
|
idleMs: SESSION_REPLY_IDLE_MS,
|
|
6503
6692
|
timeoutMs: SESSION_REPLY_DRAIN_TIMEOUT_MS
|
|
6504
6693
|
}).catch(() => {});
|
|
6505
|
-
if (hasAgentReplyAfterPrompt(params.conversation, params.promptMessageId)) return
|
|
6506
|
-
stopReason: "end_turn",
|
|
6507
|
-
source: "session"
|
|
6508
|
-
};
|
|
6694
|
+
if (hasAgentReplyAfterPrompt(params.conversation, params.promptMessageId)) return recoveredSessionResult(settledResponse, params.conversation, params.promptMessageId);
|
|
6509
6695
|
throw error;
|
|
6510
6696
|
}
|
|
6511
6697
|
}
|
|
@@ -6565,4 +6751,4 @@ var LiveSessionCheckpoint = class {
|
|
|
6565
6751
|
//#endregion
|
|
6566
6752
|
export { formatPerfMetric as $, AgentSpawnError as $t, RequestedModelUnsupportedError as A, DEFAULT_AGENT_NAME as At, absolutePath as B, extractAcpError as Bt, sessionOptionsFromRecord as C, parsePromptSource as Ct, AcpClient as D, TimeoutError as Dt, reconcileAgentSessionId as E, InterruptedError as Et, runTimedExecFile as F, resolveCanonicalAgentName as Ft, listSessions as G, NON_INTERACTIVE_PERMISSION_POLICIES as Gt, findSession as H, toAcpErrorPayload as Ht, splitCommandLine as I, exitCodeForOutputErrorCode as It, pruneSessions as J, OUTPUT_FORMATS as Jt, listSessionsForAgent as K, OUTPUT_ERROR_CODES as Kt, getAcpxVersion as L, formatErrorMessage as Lt, modelStateFromConfigOptions as M, normalizeAgentName$1 as Mt, normalizeAgentCommandInput as N, resolveAgentArgv as Nt, REQUESTED_MODEL_UNSUPPORTED_ERROR_CODE as O, withInterrupt as Ot, renderArgvIdentity as P, resolveAgentCommand as Pt, assertPersistedKeyPolicy as Q, AcpxOperationalError as Qt, permissionModeSatisfies as R, isRetryablePromptError as Rt, persistSessionOptions as S, mergePromptSourceWithText as St, applyLifecycleSnapshotToRecord as T, textPrompt as Tt, findSessionByDirectoryWalk as U, AUTH_POLICIES as Ut, findGitRepositoryRoot as V, isAcpResourceNotFoundError as Vt, isoNow$2 as W, EXIT_CODES as Wt, writeSessionRecord as X, PERMISSION_POLICY_ACTIONS as Xt, resolveSessionRecord as Y, PERMISSION_MODES as Yt, createAtomicWriteTempPath as Z, SESSION_RECORD_SCHEMA as Zt, recordPromptSubmission as _, isAcpJsonRpcMessage as _t, applyConfigOptionSelection as a, setPerfGauge as at, advertisedModelState as b, PromptInputValidationError as bt, applyRequestedModelIfAdvertised as c, serializeSessionRecordForDisk as ct, setDesiredModeId as d, defaultSessionEventLog as dt, QueueConnectionError as en, getPerfMetricsSnapshot as et, syncAdvertisedModelState as f, sessionBaseDir$1 as ft, recordClientOperation as g, extractSessionUpdateNotification as gt, createSessionConversation as h, sessionEventSegmentPath as ht, connectAndLoadSession as i, resetPerfMetrics as it, isRequestedModelUnsupportedError as j, listBuiltInAgents as jt, REQUESTED_MODEL_UNSUPPORTED_REASONS as k, withTimeout as kt, currentModelIdFromSetModelResponse as l, normalizeRuntimeSessionId as lt, cloneSessionConversation as m, sessionEventLockPath as mt, runPromptTurn as n, measurePerf as nt, applyConfigOptionsToRecord as o, startPerfTimer as ot, cloneSessionAcpxState as p, sessionEventActivePath as pt, normalizeName as q, OUTPUT_ERROR_ORIGINS as qt, withConnectedSession as r, recordPerfDuration as rt, applyModelSelection as s, parseSessionRecord as st, LiveSessionCheckpoint as t, QueueProtocolError as tn, incrementPerfCounter as tt, setCurrentModelId as u, DEFAULT_EVENT_SEGMENT_MAX_BYTES as ut, recordSessionUpdate as v, parseJsonRpcErrorMessage as vt, applyConversation as w, promptToDisplayText as wt, mergeSessionOptions as x, isPromptInput as xt, trimConversationForRuntime as y, parsePromptStopReason as yt, DEFAULT_HISTORY_LIMIT as z, normalizeOutputError as zt };
|
|
6567
6753
|
|
|
6568
|
-
//# sourceMappingURL=live-checkpoint-
|
|
6754
|
+
//# sourceMappingURL=live-checkpoint-sB7dFOYR.js.map
|