acpx 0.10.0 → 0.11.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 +25 -19
- package/dist/{cli-8dP_TqBp.js → cli-D4XUKXcD.js} +5 -5
- package/dist/{cli-8dP_TqBp.js.map → cli-D4XUKXcD.js.map} +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +429 -88
- package/dist/cli.js.map +1 -1
- package/dist/{client-C4iJBO0j.d.ts → client-DIlpCkHw.d.ts} +38 -5
- package/dist/client-DIlpCkHw.d.ts.map +1 -0
- package/dist/{flags--2oX_ubW.js → flags-Dvgmpq_l.js} +5 -5
- package/dist/flags-Dvgmpq_l.js.map +1 -0
- package/dist/{flows-e4umXVbY.js → flows-Cvsc-_AW.js} +4 -3
- package/dist/flows-Cvsc-_AW.js.map +1 -0
- package/dist/flows.d.ts +1 -1
- package/dist/flows.d.ts.map +1 -1
- package/dist/flows.js +1 -1
- package/dist/{live-checkpoint-CuFft_Nd.js → live-checkpoint-BWkYxMeS.js} +848 -207
- package/dist/live-checkpoint-BWkYxMeS.js.map +1 -0
- package/dist/{output-Di77Yugq.js → output-BEv_BB7T.js} +359 -141
- package/dist/output-BEv_BB7T.js.map +1 -0
- package/dist/runtime.d.ts +71 -5
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +192 -35
- package/dist/runtime.js.map +1 -1
- package/dist/{session-options-Bh1bIqQ2.d.ts → session-options-jkYbBxGE.d.ts} +27 -2
- package/dist/session-options-jkYbBxGE.d.ts.map +1 -0
- package/package.json +21 -20
- package/skills/acpx/SKILL.md +58 -3
- package/dist/client-C4iJBO0j.d.ts.map +0 -1
- package/dist/flags--2oX_ubW.js.map +0 -1
- package/dist/flows-e4umXVbY.js.map +0 -1
- package/dist/live-checkpoint-CuFft_Nd.js.map +0 -1
- package/dist/output-Di77Yugq.js.map +0 -1
- package/dist/session-options-Bh1bIqQ2.d.ts.map +0 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import fs, { realpathSync } from "node:fs";
|
|
1
|
+
import { $ as getPerfMetricsSnapshot, B as absolutePath, C as mergeSessionOptions, Ct as promptToDisplayText, D as applyLifecycleSnapshotToRecord, Dt as withInterrupt, E as applyConversation, Et as TimeoutError, F as modelStateFromConfigOptions, Ft as isRetryablePromptError, G as listSessions, H as findSession, I as splitCommandLine, It as normalizeOutputError, J as pruneSessions, K as listSessionsForAgent, N as assertRequestedModelSupported, Ot as withTimeout, Pt as formatErrorMessage, Q as formatPerfMetric, Qt as QueueProtocolError, S as advertisedModelState, T as sessionOptionsFromRecord, Tt as InterruptedError, U as findSessionByDirectoryWalk, Ut as OUTPUT_ERROR_CODES, V as findGitRepositoryRoot, W as isoNow, Wt as OUTPUT_ERROR_ORIGINS, X as writeSessionRecord, Y as resolveSessionRecord, Zt as QueueConnectionError, _ as createSessionConversation, _t as parseJsonRpcErrorMessage, a as applyRequestedModelIfAdvertised, at as startPerfTimer, b as recordSessionUpdate, bt as isPromptInput, c as setCurrentModelId, ct as normalizeRuntimeSessionId, d as setDesiredModelId, dt as sessionBaseDir, et as incrementPerfCounter, f as syncAdvertisedModelState, ft as sessionEventActivePath, g as cloneSessionConversation, gt as isAcpJsonRpcMessage, h as cloneSessionAcpxState, ht as extractSessionUpdateNotification, i as connectAndLoadSession, it as setPerfGauge, k as AcpClient, l as setDesiredConfigOption, m as applyConfigOptionsToState, mt as sessionEventSegmentPath, n as runPromptTurn, nt as recordPerfDuration, o as currentModelIdFromSetModelResponse, p as applyConfigOptionsToRecord, pt as sessionEventLockPath, q as normalizeName, r as withConnectedSession, rt as resetPerfMetrics, s as clearDesiredConfigOption, t as LiveSessionCheckpoint, tt as measurePerf, u as setDesiredModeId, ut as defaultSessionEventLog, v as recordClientOperation, vt as parsePromptStopReason, w as persistSessionOptions, wt as textPrompt, x as trimConversationForRuntime, y as recordPromptSubmission, zt as toAcpErrorPayload } from "./live-checkpoint-BWkYxMeS.js";
|
|
2
|
+
import fs, { mkdtempSync, realpathSync, writeFileSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import fs$1 from "node:fs/promises";
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import { createHash, randomInt, randomUUID } from "node:crypto";
|
|
7
|
-
import { spawn } from "node:child_process";
|
|
7
|
+
import { execFile, spawn } from "node:child_process";
|
|
8
|
+
import { promisify } from "node:util";
|
|
8
9
|
import net from "node:net";
|
|
9
10
|
//#region \0rolldown/runtime.js
|
|
10
11
|
var __defProp = Object.defineProperty;
|
|
@@ -75,7 +76,9 @@ function parseQueueOwnerRecord(raw) {
|
|
|
75
76
|
createdAt: record.createdAt,
|
|
76
77
|
heartbeatAt: record.heartbeatAt,
|
|
77
78
|
ownerGeneration: record.ownerGeneration,
|
|
78
|
-
queueDepth: record.queueDepth
|
|
79
|
+
queueDepth: record.queueDepth,
|
|
80
|
+
...typeof record.mcpConfigPath === "string" ? { mcpConfigPath: record.mcpConfigPath } : {},
|
|
81
|
+
...typeof record.mcpConfigFingerprint === "string" ? { mcpConfigFingerprint: record.mcpConfigFingerprint } : {}
|
|
79
82
|
};
|
|
80
83
|
}
|
|
81
84
|
function hasValidQueueOwnerRecordFields(record) {
|
|
@@ -137,6 +140,10 @@ async function cleanupStaleQueueOwner(sessionId, owner) {
|
|
|
137
140
|
if (error.code !== "ENOENT") throw error;
|
|
138
141
|
});
|
|
139
142
|
}
|
|
143
|
+
async function retireStaleQueueOwner(sessionId, owner) {
|
|
144
|
+
if (owner && isProcessAlive(owner.pid)) await terminateProcess(owner.pid);
|
|
145
|
+
await cleanupStaleQueueOwner(sessionId, owner);
|
|
146
|
+
}
|
|
140
147
|
async function readQueueOwnerRecord(sessionId) {
|
|
141
148
|
const lockPath = queueLockFilePath(sessionId);
|
|
142
149
|
try {
|
|
@@ -166,8 +173,7 @@ async function ensureOwnerIsUsable(sessionId, owner) {
|
|
|
166
173
|
const alive = isProcessAlive(owner.pid);
|
|
167
174
|
const stale = isQueueOwnerHeartbeatStale(owner);
|
|
168
175
|
if (alive && !stale) return true;
|
|
169
|
-
|
|
170
|
-
await cleanupStaleQueueOwner(sessionId, owner);
|
|
176
|
+
await retireStaleQueueOwner(sessionId, owner);
|
|
171
177
|
return false;
|
|
172
178
|
}
|
|
173
179
|
async function readQueueOwnerStatus(sessionId) {
|
|
@@ -185,11 +191,13 @@ async function readQueueOwnerStatus(sessionId) {
|
|
|
185
191
|
stale: isQueueOwnerHeartbeatStale(owner)
|
|
186
192
|
};
|
|
187
193
|
}
|
|
188
|
-
async function tryAcquireQueueOwnerLease(sessionId, nowIsoFactory = nowIso) {
|
|
194
|
+
async function tryAcquireQueueOwnerLease(sessionId, mcpConfigOrNowIsoFactory, nowIsoFactory = nowIso) {
|
|
195
|
+
const { mcpConfigPath, clock } = resolveLeaseArguments(mcpConfigOrNowIsoFactory, nowIsoFactory);
|
|
196
|
+
const mcpConfigMetadata = createMcpConfigMetadata(mcpConfigPath, readMcpConfigFingerprint(mcpConfigOrNowIsoFactory));
|
|
189
197
|
await ensureQueueDir();
|
|
190
198
|
const lockPath = queueLockFilePath(sessionId);
|
|
191
199
|
const socketPath = queueSocketPath(sessionId);
|
|
192
|
-
const createdAt =
|
|
200
|
+
const createdAt = clock();
|
|
193
201
|
const ownerGeneration = createOwnerGeneration();
|
|
194
202
|
const payload = JSON.stringify({
|
|
195
203
|
pid: process.pid,
|
|
@@ -198,7 +206,8 @@ async function tryAcquireQueueOwnerLease(sessionId, nowIsoFactory = nowIso) {
|
|
|
198
206
|
createdAt,
|
|
199
207
|
heartbeatAt: createdAt,
|
|
200
208
|
ownerGeneration,
|
|
201
|
-
queueDepth: 0
|
|
209
|
+
queueDepth: 0,
|
|
210
|
+
...mcpConfigMetadata
|
|
202
211
|
}, null, 2);
|
|
203
212
|
try {
|
|
204
213
|
await fs$1.writeFile(lockPath, `${payload}\n`, {
|
|
@@ -211,21 +220,48 @@ async function tryAcquireQueueOwnerLease(sessionId, nowIsoFactory = nowIso) {
|
|
|
211
220
|
lockPath,
|
|
212
221
|
socketPath,
|
|
213
222
|
createdAt,
|
|
214
|
-
ownerGeneration
|
|
223
|
+
ownerGeneration,
|
|
224
|
+
...mcpConfigMetadata
|
|
215
225
|
};
|
|
216
226
|
} catch (error) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
+
return await handleLeaseCollision(sessionId, error);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function readMcpConfigFingerprint(mcpConfigOrNowIsoFactory) {
|
|
231
|
+
return typeof mcpConfigOrNowIsoFactory === "object" ? mcpConfigOrNowIsoFactory?.fingerprint : void 0;
|
|
232
|
+
}
|
|
233
|
+
function createMcpConfigMetadata(mcpConfigPath, mcpConfigFingerprint) {
|
|
234
|
+
return {
|
|
235
|
+
...mcpConfigPath ? { mcpConfigPath } : {},
|
|
236
|
+
...mcpConfigFingerprint ? { mcpConfigFingerprint } : {}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
async function handleLeaseCollision(sessionId, error) {
|
|
240
|
+
if (error.code !== "EEXIST") throw error;
|
|
241
|
+
const owner = await readQueueOwnerRecord(sessionId);
|
|
242
|
+
if (!owner) {
|
|
243
|
+
await cleanupStaleQueueOwner(sessionId, owner);
|
|
227
244
|
return;
|
|
228
245
|
}
|
|
246
|
+
if (!isProcessAlive(owner.pid) || isQueueOwnerHeartbeatStale(owner)) await retireStaleQueueOwner(sessionId, owner);
|
|
247
|
+
}
|
|
248
|
+
function resolveLeaseArguments(mcpConfigOrNowIsoFactory, nowIsoFactory) {
|
|
249
|
+
if (typeof mcpConfigOrNowIsoFactory === "string") return {
|
|
250
|
+
mcpConfigPath: mcpConfigOrNowIsoFactory,
|
|
251
|
+
clock: nowIsoFactory
|
|
252
|
+
};
|
|
253
|
+
if (typeof mcpConfigOrNowIsoFactory === "function") return {
|
|
254
|
+
mcpConfigPath: void 0,
|
|
255
|
+
clock: mcpConfigOrNowIsoFactory
|
|
256
|
+
};
|
|
257
|
+
if (mcpConfigOrNowIsoFactory) return {
|
|
258
|
+
mcpConfigPath: mcpConfigOrNowIsoFactory.path,
|
|
259
|
+
clock: nowIsoFactory
|
|
260
|
+
};
|
|
261
|
+
return {
|
|
262
|
+
mcpConfigPath: void 0,
|
|
263
|
+
clock: nowIsoFactory
|
|
264
|
+
};
|
|
229
265
|
}
|
|
230
266
|
async function refreshQueueOwnerLease(lease, options, nowIsoFactory = nowIso) {
|
|
231
267
|
const payload = JSON.stringify({
|
|
@@ -235,7 +271,9 @@ async function refreshQueueOwnerLease(lease, options, nowIsoFactory = nowIso) {
|
|
|
235
271
|
createdAt: lease.createdAt,
|
|
236
272
|
heartbeatAt: nowIsoFactory(),
|
|
237
273
|
ownerGeneration: lease.ownerGeneration,
|
|
238
|
-
queueDepth: Math.max(0, Math.round(options.queueDepth))
|
|
274
|
+
queueDepth: Math.max(0, Math.round(options.queueDepth)),
|
|
275
|
+
...lease.mcpConfigPath ? { mcpConfigPath: lease.mcpConfigPath } : {},
|
|
276
|
+
...lease.mcpConfigFingerprint ? { mcpConfigFingerprint: lease.mcpConfigFingerprint } : {}
|
|
239
277
|
}, null, 2);
|
|
240
278
|
await fs$1.writeFile(lease.lockPath, `${payload}\n`, { encoding: "utf8" });
|
|
241
279
|
}
|
|
@@ -409,6 +447,7 @@ function parseSessionOptions(value) {
|
|
|
409
447
|
if (!assignSessionAllowedTools(sessionOptions, record.allowedTools)) return null;
|
|
410
448
|
if (!assignSessionMaxTurns(sessionOptions, record.maxTurns)) return null;
|
|
411
449
|
if (!assignSessionSystemPrompt(sessionOptions, record.systemPrompt)) return null;
|
|
450
|
+
if (!assignSessionEnv(sessionOptions, record.env)) return null;
|
|
412
451
|
return sessionOptions;
|
|
413
452
|
}
|
|
414
453
|
function assignSessionModel(options, value) {
|
|
@@ -440,6 +479,15 @@ function assignSessionSystemPrompt(options, value) {
|
|
|
440
479
|
options.systemPrompt = { append: systemPrompt.append };
|
|
441
480
|
return true;
|
|
442
481
|
}
|
|
482
|
+
function assignSessionEnv(options, value) {
|
|
483
|
+
if (value == null) return true;
|
|
484
|
+
const env = asRecord$2(value);
|
|
485
|
+
if (!env) return false;
|
|
486
|
+
const entries = Object.entries(env);
|
|
487
|
+
if (entries.some(([, entryValue]) => typeof entryValue !== "string")) return false;
|
|
488
|
+
options.env = Object.fromEntries(entries);
|
|
489
|
+
return true;
|
|
490
|
+
}
|
|
443
491
|
function parseOwnerGeneration(value) {
|
|
444
492
|
if (value == null) return;
|
|
445
493
|
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) return null;
|
|
@@ -617,7 +665,7 @@ const QUEUE_OWNER_MESSAGE_PARSERS = {
|
|
|
617
665
|
cancel_result: (message, context) => parseBooleanResultOwnerMessage(message, context, "cancel_result", "cancelled"),
|
|
618
666
|
close_session_result: (message, context) => parseBooleanResultOwnerMessage(message, context, "close_session_result", "closed"),
|
|
619
667
|
set_mode_result: (message, context) => parseStringResultOwnerMessage(message, context, "set_mode_result", "modeId"),
|
|
620
|
-
set_model_result:
|
|
668
|
+
set_model_result: parseSetModelOwnerMessage,
|
|
621
669
|
set_config_option_result: parseSetConfigOptionOwnerMessage,
|
|
622
670
|
error: parseErrorOwnerMessage
|
|
623
671
|
};
|
|
@@ -665,6 +713,17 @@ function parseStringResultOwnerMessage(message, context, type, field) {
|
|
|
665
713
|
[field]: message[field]
|
|
666
714
|
};
|
|
667
715
|
}
|
|
716
|
+
function parseSetModelOwnerMessage(message, context) {
|
|
717
|
+
if (typeof message.modelId !== "string") return null;
|
|
718
|
+
const response = asRecord$2(message.response);
|
|
719
|
+
if (message.response !== void 0 && (!response || !Array.isArray(response.configOptions))) return null;
|
|
720
|
+
return {
|
|
721
|
+
type: "set_model_result",
|
|
722
|
+
...context,
|
|
723
|
+
modelId: message.modelId,
|
|
724
|
+
...response ? { response } : {}
|
|
725
|
+
};
|
|
726
|
+
}
|
|
668
727
|
function parseSetConfigOptionOwnerMessage(message, context) {
|
|
669
728
|
const response = asRecord$2(message.response);
|
|
670
729
|
if (!response || !Array.isArray(response.configOptions)) return null;
|
|
@@ -807,25 +866,26 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
807
866
|
}
|
|
808
867
|
enqueue(task) {
|
|
809
868
|
if (this.closed) {
|
|
810
|
-
|
|
869
|
+
task.send(makeQueueOwnerError(task.requestId, "Queue owner is shutting down", "QUEUE_OWNER_SHUTTING_DOWN", { retryable: true }));
|
|
811
870
|
task.close();
|
|
812
|
-
return;
|
|
871
|
+
return false;
|
|
813
872
|
}
|
|
814
873
|
const waiter = this.waiters.shift();
|
|
815
874
|
if (waiter) {
|
|
816
875
|
waiter(task);
|
|
817
|
-
return;
|
|
876
|
+
return true;
|
|
818
877
|
}
|
|
819
878
|
if (this.pending.length >= this.maxQueueDepth) {
|
|
820
|
-
|
|
879
|
+
task.send({
|
|
821
880
|
...makeQueueOwnerError(task.requestId, `Queue owner is overloaded (${this.pending.length}/${this.maxQueueDepth} queued)`, "QUEUE_OWNER_OVERLOADED", { retryable: true }),
|
|
822
881
|
ownerGeneration: this.ownerGeneration
|
|
823
882
|
});
|
|
824
883
|
task.close();
|
|
825
|
-
return;
|
|
884
|
+
return false;
|
|
826
885
|
}
|
|
827
886
|
this.pending.push(task);
|
|
828
887
|
this.emitQueueDepth();
|
|
888
|
+
return true;
|
|
829
889
|
}
|
|
830
890
|
handleControlRequest(options) {
|
|
831
891
|
writeQueueMessage(options.socket, {
|
|
@@ -919,11 +979,12 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
919
979
|
socket,
|
|
920
980
|
requestId: request.requestId,
|
|
921
981
|
run: async () => {
|
|
922
|
-
await this.controlHandlers.setSessionModel(request.modelId, request.timeoutMs);
|
|
982
|
+
const response = await this.controlHandlers.setSessionModel(request.modelId, request.timeoutMs);
|
|
923
983
|
return {
|
|
924
984
|
type: "set_model_result",
|
|
925
985
|
requestId: request.requestId,
|
|
926
|
-
modelId: request.modelId
|
|
986
|
+
modelId: request.modelId,
|
|
987
|
+
response
|
|
927
988
|
};
|
|
928
989
|
}
|
|
929
990
|
});
|
|
@@ -968,13 +1029,13 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
968
1029
|
if (!socket.destroyed) socket.end();
|
|
969
1030
|
}
|
|
970
1031
|
};
|
|
1032
|
+
if (!this.enqueue(task)) return;
|
|
971
1033
|
writeQueueMessage(socket, {
|
|
972
1034
|
type: "accepted",
|
|
973
1035
|
requestId: request.requestId,
|
|
974
1036
|
ownerGeneration: this.ownerGeneration
|
|
975
1037
|
});
|
|
976
1038
|
if (!request.waitForCompletion) task.close();
|
|
977
|
-
this.enqueue(task);
|
|
978
1039
|
}
|
|
979
1040
|
handleConnection(socket) {
|
|
980
1041
|
socket.setEncoding("utf8");
|
|
@@ -1013,7 +1074,7 @@ var SessionQueueOwner = class SessionQueueOwner {
|
|
|
1013
1074
|
//#endregion
|
|
1014
1075
|
//#region src/cli/queue/ipc.ts
|
|
1015
1076
|
const MAX_MESSAGE_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
1016
|
-
const STALE_OWNER_PROTOCOL_DETAIL_CODES = new Set(["QUEUE_PROTOCOL_MALFORMED_MESSAGE", "QUEUE_PROTOCOL_UNEXPECTED_RESPONSE"]);
|
|
1077
|
+
const STALE_OWNER_PROTOCOL_DETAIL_CODES = /* @__PURE__ */ new Set(["QUEUE_PROTOCOL_MALFORMED_MESSAGE", "QUEUE_PROTOCOL_UNEXPECTED_RESPONSE"]);
|
|
1017
1078
|
async function maybeRecoverStaleOwnerAfterProtocolMismatch(params) {
|
|
1018
1079
|
if (!(params.error instanceof QueueProtocolError)) return false;
|
|
1019
1080
|
const detailCode = params.error.detailCode;
|
|
@@ -1344,7 +1405,7 @@ async function submitSetModelToQueueOwner(owner, modelId, timeoutMs) {
|
|
|
1344
1405
|
origin: "queue",
|
|
1345
1406
|
retryable: true
|
|
1346
1407
|
});
|
|
1347
|
-
return
|
|
1408
|
+
return response;
|
|
1348
1409
|
}
|
|
1349
1410
|
async function submitSetConfigOptionToQueueOwner(owner, configId, value, timeoutMs) {
|
|
1350
1411
|
const request = {
|
|
@@ -1380,9 +1441,22 @@ async function submitCloseSessionToQueueOwner(owner, timeoutMs) {
|
|
|
1380
1441
|
});
|
|
1381
1442
|
return response.closed;
|
|
1382
1443
|
}
|
|
1444
|
+
function queueOwnerMcpConfigMatches(owner, options) {
|
|
1445
|
+
return owner.mcpConfigPath === options.mcpConfigPath && owner.mcpConfigFingerprint === options.mcpConfigFingerprint;
|
|
1446
|
+
}
|
|
1447
|
+
function assertQueueOwnerMcpConfigMatches(owner, options) {
|
|
1448
|
+
if (queueOwnerMcpConfigMatches(owner, options)) return;
|
|
1449
|
+
throw new QueueConnectionError("Session queue owner uses a different MCP config; close the session before retrying", {
|
|
1450
|
+
detailCode: "QUEUE_MCP_CONFIG_CONFLICT",
|
|
1451
|
+
origin: "queue",
|
|
1452
|
+
retryable: false
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1383
1455
|
async function trySubmitToRunningOwner(options) {
|
|
1384
1456
|
const owner = await readQueueOwnerRecord(options.sessionId);
|
|
1385
1457
|
if (!owner) return;
|
|
1458
|
+
if (!await ensureOwnerIsUsable(options.sessionId, owner)) return;
|
|
1459
|
+
assertQueueOwnerMcpConfigMatches(owner, options);
|
|
1386
1460
|
let submitted;
|
|
1387
1461
|
try {
|
|
1388
1462
|
submitted = await submitToQueueOwner(owner, options);
|
|
@@ -1453,9 +1527,10 @@ async function trySetModeOnRunningOwner(sessionId, modeId, timeoutMs, verbose) {
|
|
|
1453
1527
|
async function trySetModelOnRunningOwner(sessionId, modelId, timeoutMs, verbose) {
|
|
1454
1528
|
const owner = await readQueueOwnerRecord(sessionId);
|
|
1455
1529
|
if (!owner) return;
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1530
|
+
const submitted = await submitSetModelToQueueOwner(owner, modelId, timeoutMs);
|
|
1531
|
+
if (submitted) {
|
|
1532
|
+
if (verbose) process.stderr.write(`[acpx] requested a model config update on owner pid ${owner.pid} for session ${sessionId}\n`);
|
|
1533
|
+
return submitted;
|
|
1459
1534
|
}
|
|
1460
1535
|
if (!(await probeQueueOwnerHealth(sessionId)).hasLease) return;
|
|
1461
1536
|
throw new QueueConnectionError("Session queue owner is running but not accepting set_model requests", {
|
|
@@ -1514,16 +1589,28 @@ async function runSessionSetModeDirect(options) {
|
|
|
1514
1589
|
})));
|
|
1515
1590
|
}
|
|
1516
1591
|
async function runSessionSetModelDirect(options) {
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1592
|
+
const result = await withConnectedSession(buildDirectConnectedSessionOptions(options, async ({ client, sessionId, record }) => {
|
|
1593
|
+
const models = advertisedModelState(record.acpx);
|
|
1594
|
+
const response = await withTimeout(client.setSessionModel(sessionId, options.modelId, models), options.timeoutMs);
|
|
1595
|
+
applyConfigOptionsToRecord(record, response);
|
|
1596
|
+
setDesiredModelId(record, options.modelId, models?.configId);
|
|
1597
|
+
setCurrentModelId(record, currentModelIdFromSetModelResponse(response, options.modelId));
|
|
1598
|
+
return response;
|
|
1599
|
+
}));
|
|
1600
|
+
return {
|
|
1601
|
+
...toSessionMutationResult(result),
|
|
1602
|
+
response: result.value
|
|
1603
|
+
};
|
|
1522
1604
|
}
|
|
1523
1605
|
async function runSessionSetConfigOptionDirect(options) {
|
|
1524
1606
|
const result = await withConnectedSession(buildDirectConnectedSessionOptions(options, async ({ client, sessionId, record }) => {
|
|
1607
|
+
const modelConfigId = advertisedModelState(record.acpx)?.configId;
|
|
1525
1608
|
const response = await withTimeout(client.setSessionConfigOption(sessionId, options.configId, options.value), options.timeoutMs);
|
|
1526
|
-
|
|
1609
|
+
applyConfigOptionsToRecord(record, response);
|
|
1610
|
+
if (options.configId === modelConfigId) {
|
|
1611
|
+
setDesiredModelId(record, options.value, options.configId);
|
|
1612
|
+
setCurrentModelId(record, currentModelIdFromSetModelResponse(response, options.value));
|
|
1613
|
+
} else if (options.configId === "mode") setDesiredModeId(record, options.value);
|
|
1527
1614
|
else setDesiredConfigOption(record, options.configId, options.value);
|
|
1528
1615
|
return response;
|
|
1529
1616
|
}));
|
|
@@ -1536,6 +1623,7 @@ async function runSessionSetConfigOptionDirect(options) {
|
|
|
1536
1623
|
}
|
|
1537
1624
|
//#endregion
|
|
1538
1625
|
//#region src/cli/session/session-control.ts
|
|
1626
|
+
const execFileAsync = promisify(execFile);
|
|
1539
1627
|
async function cancelSessionPrompt(options) {
|
|
1540
1628
|
const cancelled = await tryCancelOnRunningOwner(options);
|
|
1541
1629
|
return {
|
|
@@ -1566,13 +1654,16 @@ async function setSessionMode(options) {
|
|
|
1566
1654
|
});
|
|
1567
1655
|
}
|
|
1568
1656
|
async function setSessionModel(options) {
|
|
1569
|
-
|
|
1657
|
+
const submittedToOwner = await trySetModelOnRunningOwner(options.sessionId, options.modelId, options.timeoutMs, options.verbose);
|
|
1658
|
+
if (submittedToOwner) {
|
|
1570
1659
|
const record = await resolveSessionRecord(options.sessionId);
|
|
1571
|
-
|
|
1572
|
-
|
|
1660
|
+
applyConfigOptionsToRecord(record, submittedToOwner.response);
|
|
1661
|
+
setDesiredModelId(record, options.modelId, advertisedModelState(record.acpx)?.configId);
|
|
1662
|
+
setCurrentModelId(record, currentModelIdFromSetModelResponse(submittedToOwner.response, options.modelId));
|
|
1573
1663
|
await writeSessionRecord(record);
|
|
1574
1664
|
return {
|
|
1575
1665
|
record,
|
|
1666
|
+
response: submittedToOwner.response,
|
|
1576
1667
|
resumed: false
|
|
1577
1668
|
};
|
|
1578
1669
|
}
|
|
@@ -1592,7 +1683,12 @@ async function setSessionConfigOption(options) {
|
|
|
1592
1683
|
const ownerResponse = await trySetConfigOptionOnRunningOwner(options.sessionId, options.configId, options.value, options.timeoutMs, options.verbose);
|
|
1593
1684
|
if (ownerResponse) {
|
|
1594
1685
|
const record = await resolveSessionRecord(options.sessionId);
|
|
1595
|
-
|
|
1686
|
+
const modelConfigId = advertisedModelState(record.acpx)?.configId;
|
|
1687
|
+
applyConfigOptionsToRecord(record, ownerResponse);
|
|
1688
|
+
if (options.configId === modelConfigId) {
|
|
1689
|
+
setDesiredModelId(record, options.value, options.configId);
|
|
1690
|
+
setCurrentModelId(record, currentModelIdFromSetModelResponse(ownerResponse, options.value));
|
|
1691
|
+
} else if (options.configId === "mode") setDesiredModeId(record, options.value);
|
|
1596
1692
|
else setDesiredConfigOption(record, options.configId, options.value);
|
|
1597
1693
|
await writeSessionRecord(record);
|
|
1598
1694
|
return {
|
|
@@ -1615,25 +1711,72 @@ async function setSessionConfigOption(options) {
|
|
|
1615
1711
|
});
|
|
1616
1712
|
}
|
|
1617
1713
|
function firstAgentCommandToken(command) {
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1714
|
+
try {
|
|
1715
|
+
return splitCommandLine(command).command || void 0;
|
|
1716
|
+
} catch {
|
|
1717
|
+
return;
|
|
1718
|
+
}
|
|
1622
1719
|
}
|
|
1623
1720
|
async function isLikelyMatchingProcess(pid, agentCommand) {
|
|
1624
1721
|
const expectedToken = firstAgentCommandToken(agentCommand);
|
|
1625
1722
|
if (!expectedToken) return false;
|
|
1626
|
-
const
|
|
1723
|
+
const argv = await readProcessArgv(pid);
|
|
1724
|
+
if (argv.length === 0) return false;
|
|
1725
|
+
const executableBase = path.basename(argv[0]);
|
|
1726
|
+
const expectedBase = path.basename(expectedToken);
|
|
1727
|
+
return executableBase === expectedBase || argv.some((entry) => path.basename(entry) === expectedBase);
|
|
1728
|
+
}
|
|
1729
|
+
async function readProcessArgv(pid) {
|
|
1730
|
+
const procArgv = await readProcCmdline(pid);
|
|
1731
|
+
if (procArgv) return procArgv;
|
|
1732
|
+
return splitCommandLineLike(process.platform === "win32" ? await readWindowsCommandLine(pid) : await readPosixCommandLine(pid));
|
|
1733
|
+
}
|
|
1734
|
+
async function readProcCmdline(pid) {
|
|
1627
1735
|
try {
|
|
1628
|
-
|
|
1629
|
-
if (argv.length === 0) return false;
|
|
1630
|
-
const executableBase = path.basename(argv[0]);
|
|
1631
|
-
const expectedBase = path.basename(expectedToken);
|
|
1632
|
-
return executableBase === expectedBase || argv.some((entry) => path.basename(entry) === expectedBase);
|
|
1736
|
+
return (await fs$1.readFile(`/proc/${pid}/cmdline`, "utf8")).split("\0").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
1633
1737
|
} catch {
|
|
1634
|
-
return
|
|
1738
|
+
return;
|
|
1635
1739
|
}
|
|
1636
1740
|
}
|
|
1741
|
+
async function readPosixCommandLine(pid) {
|
|
1742
|
+
try {
|
|
1743
|
+
const { stdout } = await execFileAsync("ps", [
|
|
1744
|
+
"-p",
|
|
1745
|
+
String(pid),
|
|
1746
|
+
"-o",
|
|
1747
|
+
"command="
|
|
1748
|
+
]);
|
|
1749
|
+
return stdout.trim() || void 0;
|
|
1750
|
+
} catch {
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
async function readWindowsCommandLine(pid) {
|
|
1755
|
+
try {
|
|
1756
|
+
const { stdout } = await execFileAsync("powershell.exe", [
|
|
1757
|
+
"-NoProfile",
|
|
1758
|
+
"-NonInteractive",
|
|
1759
|
+
"-Command",
|
|
1760
|
+
`(Get-CimInstance Win32_Process -Filter "ProcessId = ${pid}").CommandLine`
|
|
1761
|
+
], { windowsHide: true });
|
|
1762
|
+
return stdout.trim() || void 0;
|
|
1763
|
+
} catch {
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
function splitCommandLineLike(commandLine) {
|
|
1768
|
+
if (!commandLine) return [];
|
|
1769
|
+
try {
|
|
1770
|
+
const parsed = splitCommandLine(commandLine);
|
|
1771
|
+
return [parsed.command, ...parsed.args];
|
|
1772
|
+
} catch {
|
|
1773
|
+
return commandLine.split(/\s+/u).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
const sessionControlTestInternals = {
|
|
1777
|
+
firstAgentCommandToken,
|
|
1778
|
+
splitCommandLineLike
|
|
1779
|
+
};
|
|
1637
1780
|
async function closeSession(sessionId) {
|
|
1638
1781
|
const record = await resolveSessionRecord(sessionId);
|
|
1639
1782
|
await tryCloseSessionOnRunningOwner({ sessionId: record.acpxRecordId }).catch(() => {});
|
|
@@ -1650,33 +1793,8 @@ async function closeSession(sessionId) {
|
|
|
1650
1793
|
async function createSessionRecordWithClient(client, options) {
|
|
1651
1794
|
const cwd = absolutePath(options.cwd);
|
|
1652
1795
|
await withTimeout(client.start(), options.timeoutMs);
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
let sessionResult;
|
|
1656
|
-
let sessionModels;
|
|
1657
|
-
let requestedModelApplied = false;
|
|
1658
|
-
if (options.resumeSessionId) {
|
|
1659
|
-
const resumed = await resumeSessionRecordWithClient(client, options, cwd);
|
|
1660
|
-
sessionId = resumed.sessionId;
|
|
1661
|
-
agentSessionId = resumed.agentSessionId;
|
|
1662
|
-
sessionResult = resumed.sessionResult;
|
|
1663
|
-
sessionModels = resumed.sessionModels;
|
|
1664
|
-
requestedModelApplied = resumed.requestedModelApplied;
|
|
1665
|
-
} else {
|
|
1666
|
-
const createdSession = await withTimeout(client.createSession(cwd), options.timeoutMs);
|
|
1667
|
-
sessionId = createdSession.sessionId;
|
|
1668
|
-
agentSessionId = normalizeRuntimeSessionId(createdSession.agentSessionId);
|
|
1669
|
-
sessionResult = createdSession;
|
|
1670
|
-
sessionModels = createdSession.models;
|
|
1671
|
-
requestedModelApplied = await applyRequestedModelIfAdvertised({
|
|
1672
|
-
client,
|
|
1673
|
-
sessionId,
|
|
1674
|
-
requestedModel: options.sessionOptions?.model,
|
|
1675
|
-
models: sessionModels,
|
|
1676
|
-
agentCommand: options.agentCommand,
|
|
1677
|
-
timeoutMs: options.timeoutMs
|
|
1678
|
-
});
|
|
1679
|
-
}
|
|
1796
|
+
const createdState = options.resumeSessionId ? await resumeSessionRecordWithClient(client, options, cwd) : await createFreshSessionState(client, options, cwd);
|
|
1797
|
+
const { sessionId, agentSessionId } = createdState;
|
|
1680
1798
|
const lifecycle = client.getAgentLifecycleSnapshot();
|
|
1681
1799
|
const now = isoNow();
|
|
1682
1800
|
const record = {
|
|
@@ -1702,12 +1820,36 @@ async function createSessionRecordWithClient(client, options) {
|
|
|
1702
1820
|
acpx: {}
|
|
1703
1821
|
};
|
|
1704
1822
|
persistSessionOptions(record, options.sessionOptions);
|
|
1705
|
-
|
|
1706
|
-
syncAdvertisedModelState(record, sessionModels);
|
|
1707
|
-
if (requestedModelApplied) setCurrentModelId(record, options.sessionOptions?.model);
|
|
1823
|
+
applyCreatedSessionModelState(record, createdState, options.sessionOptions?.model);
|
|
1708
1824
|
await writeSessionRecord(record);
|
|
1709
1825
|
return record;
|
|
1710
1826
|
}
|
|
1827
|
+
function applyCreatedSessionModelState(record, state, requestedModel) {
|
|
1828
|
+
applyConfigOptionsToRecord(record, state.sessionResult);
|
|
1829
|
+
applyConfigOptionsToRecord(record, state.requestedModelResponse);
|
|
1830
|
+
syncAdvertisedModelState(record, state.requestedModelResponse ? modelStateFromConfigOptions(state.requestedModelResponse.configOptions) : state.sessionModels);
|
|
1831
|
+
if (state.requestedModelApplied) setCurrentModelId(record, currentModelIdFromSetModelResponse(state.requestedModelResponse, requestedModel));
|
|
1832
|
+
}
|
|
1833
|
+
async function createFreshSessionState(client, options, cwd) {
|
|
1834
|
+
const createdSession = await withTimeout(client.createSession(cwd), options.timeoutMs);
|
|
1835
|
+
const modelApplication = await applyRequestedModelIfAdvertised({
|
|
1836
|
+
client,
|
|
1837
|
+
sessionId: createdSession.sessionId,
|
|
1838
|
+
requestedModel: options.sessionOptions?.model,
|
|
1839
|
+
models: createdSession.models,
|
|
1840
|
+
agentCommand: options.agentCommand,
|
|
1841
|
+
timeoutMs: options.timeoutMs,
|
|
1842
|
+
onWarning: options.onModelWarning
|
|
1843
|
+
});
|
|
1844
|
+
return {
|
|
1845
|
+
sessionId: createdSession.sessionId,
|
|
1846
|
+
agentSessionId: normalizeRuntimeSessionId(createdSession.agentSessionId),
|
|
1847
|
+
sessionResult: createdSession,
|
|
1848
|
+
sessionModels: createdSession.models,
|
|
1849
|
+
requestedModelApplied: modelApplication.applied,
|
|
1850
|
+
requestedModelResponse: modelApplication.response
|
|
1851
|
+
};
|
|
1852
|
+
}
|
|
1711
1853
|
async function resumeSessionRecordWithClient(client, options, cwd) {
|
|
1712
1854
|
if (!options.resumeSessionId) throw new Error("resumeSessionId is required");
|
|
1713
1855
|
const resumeMethod = client.supportsResumeSession() ? "session/resume" : client.supportsLoadSession() ? "session/load" : void 0;
|
|
@@ -1715,19 +1857,22 @@ async function resumeSessionRecordWithClient(client, options, cwd) {
|
|
|
1715
1857
|
try {
|
|
1716
1858
|
const resumedSession = await withTimeout(resumeMethod === "session/resume" ? client.resumeSession(options.resumeSessionId, cwd) : client.loadSession(options.resumeSessionId, cwd), options.timeoutMs);
|
|
1717
1859
|
const sessionModels = resumedSession.models;
|
|
1860
|
+
const modelApplication = await applyRequestedModelIfAdvertised({
|
|
1861
|
+
client,
|
|
1862
|
+
sessionId: options.resumeSessionId,
|
|
1863
|
+
requestedModel: options.sessionOptions?.model,
|
|
1864
|
+
models: sessionModels,
|
|
1865
|
+
agentCommand: options.agentCommand,
|
|
1866
|
+
timeoutMs: options.timeoutMs,
|
|
1867
|
+
onWarning: options.onModelWarning
|
|
1868
|
+
});
|
|
1718
1869
|
return {
|
|
1719
1870
|
sessionId: options.resumeSessionId,
|
|
1720
1871
|
agentSessionId: normalizeRuntimeSessionId(resumedSession.agentSessionId),
|
|
1721
1872
|
sessionResult: resumedSession,
|
|
1722
1873
|
sessionModels,
|
|
1723
|
-
requestedModelApplied:
|
|
1724
|
-
|
|
1725
|
-
sessionId: options.resumeSessionId,
|
|
1726
|
-
requestedModel: options.sessionOptions?.model,
|
|
1727
|
-
models: sessionModels,
|
|
1728
|
-
agentCommand: options.agentCommand,
|
|
1729
|
-
timeoutMs: options.timeoutMs
|
|
1730
|
-
})
|
|
1874
|
+
requestedModelApplied: modelApplication.applied,
|
|
1875
|
+
requestedModelResponse: modelApplication.response
|
|
1731
1876
|
};
|
|
1732
1877
|
} catch (error) {
|
|
1733
1878
|
throw new Error(`Failed to resume ACP session ${options.resumeSessionId}: ${formatErrorMessage(error)}`, { cause: error });
|
|
@@ -2015,11 +2160,8 @@ var QueueOwnerTurnController = class {
|
|
|
2015
2160
|
async setSessionModel(modelId, timeoutMs) {
|
|
2016
2161
|
this.assertCanHandleControlRequest();
|
|
2017
2162
|
const activeController = this.activeController;
|
|
2018
|
-
if (activeController)
|
|
2019
|
-
|
|
2020
|
-
return;
|
|
2021
|
-
}
|
|
2022
|
-
await this.options.setSessionModelFallback(modelId, timeoutMs);
|
|
2163
|
+
if (activeController) return await this.options.withTimeout(async () => await activeController.setSessionModel(modelId), timeoutMs);
|
|
2164
|
+
return await this.options.setSessionModelFallback(modelId, timeoutMs);
|
|
2023
2165
|
}
|
|
2024
2166
|
async setSessionConfigOption(configId, value, timeoutMs) {
|
|
2025
2167
|
this.assertCanHandleControlRequest();
|
|
@@ -2030,22 +2172,24 @@ var QueueOwnerTurnController = class {
|
|
|
2030
2172
|
};
|
|
2031
2173
|
//#endregion
|
|
2032
2174
|
//#region src/cli/session/queue-owner-process.ts
|
|
2175
|
+
const QUEUE_OWNER_PAYLOAD_FILE_ENV = "ACPX_QUEUE_OWNER_PAYLOAD_FILE";
|
|
2176
|
+
const QUEUE_OWNER_PAYLOAD_ENV = "ACPX_QUEUE_OWNER_PAYLOAD";
|
|
2033
2177
|
function isNonEmptyStringArray(value) {
|
|
2034
2178
|
return Array.isArray(value) && value.length > 0 && value.every((entry) => typeof entry === "string" && entry.length > 0);
|
|
2035
2179
|
}
|
|
2036
|
-
const NODE_TEST_FLAGS = new Set([
|
|
2180
|
+
const NODE_TEST_FLAGS = /* @__PURE__ */ new Set([
|
|
2037
2181
|
"--experimental-test-coverage",
|
|
2038
2182
|
"--test",
|
|
2039
2183
|
"--test-name-pattern",
|
|
2040
2184
|
"--test-reporter",
|
|
2041
2185
|
"--test-reporter-destination"
|
|
2042
2186
|
]);
|
|
2043
|
-
const NODE_TEST_FLAGS_WITH_VALUE = new Set([
|
|
2187
|
+
const NODE_TEST_FLAGS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
2044
2188
|
"--test-name-pattern",
|
|
2045
2189
|
"--test-reporter",
|
|
2046
2190
|
"--test-reporter-destination"
|
|
2047
2191
|
]);
|
|
2048
|
-
const INSPECTOR_FLAGS_WITH_VALUE = new Set([
|
|
2192
|
+
const INSPECTOR_FLAGS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
2049
2193
|
"--inspect",
|
|
2050
2194
|
"--inspect-brk",
|
|
2051
2195
|
"--inspect-port",
|
|
@@ -2105,6 +2249,8 @@ function queueOwnerRuntimeOptionsFromSend(options) {
|
|
|
2105
2249
|
return {
|
|
2106
2250
|
sessionId: options.sessionId,
|
|
2107
2251
|
mcpServers: options.mcpServers,
|
|
2252
|
+
...options.mcpConfigPath ? { mcpConfigPath: options.mcpConfigPath } : {},
|
|
2253
|
+
...options.mcpConfigFingerprint ? { mcpConfigFingerprint: options.mcpConfigFingerprint } : {},
|
|
2108
2254
|
permissionMode: options.permissionMode,
|
|
2109
2255
|
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
2110
2256
|
authCredentials: options.authCredentials,
|
|
@@ -2118,20 +2264,32 @@ function queueOwnerRuntimeOptionsFromSend(options) {
|
|
|
2118
2264
|
sessionOptions: options.sessionOptions
|
|
2119
2265
|
};
|
|
2120
2266
|
}
|
|
2121
|
-
function
|
|
2267
|
+
function writeQueueOwnerPayloadFile(payload) {
|
|
2268
|
+
const dir = mkdtempSync(path.join(os.tmpdir(), "acpx-queue-owner-"));
|
|
2269
|
+
const payloadPath = path.join(dir, "payload.json");
|
|
2270
|
+
writeFileSync(payloadPath, payload, {
|
|
2271
|
+
encoding: "utf8",
|
|
2272
|
+
flag: "wx",
|
|
2273
|
+
mode: 384
|
|
2274
|
+
});
|
|
2275
|
+
return payloadPath;
|
|
2276
|
+
}
|
|
2277
|
+
function buildQueueOwnerSpawnOptions(payloadFilePath) {
|
|
2278
|
+
const env = {
|
|
2279
|
+
...process.env,
|
|
2280
|
+
[QUEUE_OWNER_PAYLOAD_FILE_ENV]: payloadFilePath
|
|
2281
|
+
};
|
|
2282
|
+
delete env[QUEUE_OWNER_PAYLOAD_ENV];
|
|
2122
2283
|
return {
|
|
2123
2284
|
detached: true,
|
|
2124
2285
|
stdio: "ignore",
|
|
2125
|
-
env
|
|
2126
|
-
...process.env,
|
|
2127
|
-
ACPX_QUEUE_OWNER_PAYLOAD: payload
|
|
2128
|
-
},
|
|
2286
|
+
env,
|
|
2129
2287
|
windowsHide: true
|
|
2130
2288
|
};
|
|
2131
2289
|
}
|
|
2132
2290
|
function spawnQueueOwnerProcess(options) {
|
|
2133
|
-
const
|
|
2134
|
-
spawn(process.execPath, resolveQueueOwnerSpawnArgs(), buildQueueOwnerSpawnOptions(
|
|
2291
|
+
const payloadPath = writeQueueOwnerPayloadFile(JSON.stringify(options));
|
|
2292
|
+
spawn(process.execPath, resolveQueueOwnerSpawnArgs(), buildQueueOwnerSpawnOptions(payloadPath)).unref();
|
|
2135
2293
|
}
|
|
2136
2294
|
//#endregion
|
|
2137
2295
|
//#region src/session/events.ts
|
|
@@ -2379,35 +2537,54 @@ function toPromptResult(stopReason, sessionId, client) {
|
|
|
2379
2537
|
function requestedModelId(value) {
|
|
2380
2538
|
return typeof value === "string" ? value.trim() : "";
|
|
2381
2539
|
}
|
|
2382
|
-
function
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2540
|
+
function applyConfigOptionResponseToState(state, response) {
|
|
2541
|
+
if (!response?.configOptions) return state;
|
|
2542
|
+
return applyConfigOptionsToState(state, response.configOptions);
|
|
2543
|
+
}
|
|
2544
|
+
function mergeConnectedModelState(state, connectedState) {
|
|
2545
|
+
if (!connectedState) return state;
|
|
2546
|
+
const nextState = cloneSessionAcpxState(state) ?? {};
|
|
2547
|
+
mergeConnectedAdvertisedModelState(nextState, connectedState);
|
|
2548
|
+
mergeConnectedModelPreferences(nextState, connectedState);
|
|
2549
|
+
return nextState;
|
|
2550
|
+
}
|
|
2551
|
+
function mergeConnectedAdvertisedModelState(nextState, connectedState) {
|
|
2552
|
+
if (connectedState.config_options !== void 0) nextState.config_options = structuredClone(connectedState.config_options);
|
|
2553
|
+
else delete nextState.config_options;
|
|
2554
|
+
if (connectedState.current_model_id !== void 0) nextState.current_model_id = connectedState.current_model_id;
|
|
2555
|
+
else delete nextState.current_model_id;
|
|
2556
|
+
if (connectedState.available_models) nextState.available_models = [...connectedState.available_models];
|
|
2557
|
+
else delete nextState.available_models;
|
|
2558
|
+
if (connectedState.model_control) nextState.model_control = connectedState.model_control;
|
|
2559
|
+
else delete nextState.model_control;
|
|
2560
|
+
}
|
|
2561
|
+
function mergeConnectedModelPreferences(nextState, connectedState) {
|
|
2562
|
+
if (connectedState.session_options) nextState.session_options = cloneSessionAcpxState(connectedState)?.session_options;
|
|
2563
|
+
if (connectedState.desired_mode_id !== void 0) nextState.desired_mode_id = connectedState.desired_mode_id;
|
|
2564
|
+
if (connectedState.desired_config_options) nextState.desired_config_options = { ...connectedState.desired_config_options };
|
|
2392
2565
|
}
|
|
2393
2566
|
async function applyPromptModelIfAdvertised(params) {
|
|
2394
2567
|
const requestedModel = requestedModelId(params.requestedModel);
|
|
2395
2568
|
if (!requestedModel) return;
|
|
2396
|
-
const models =
|
|
2397
|
-
assertRequestedModelSupported({
|
|
2569
|
+
const models = advertisedModelState(params.record.acpx);
|
|
2570
|
+
emitModelSupportWarning(assertRequestedModelSupported({
|
|
2398
2571
|
requestedModel,
|
|
2399
2572
|
models,
|
|
2400
2573
|
agentCommand: params.record.agentCommand,
|
|
2401
2574
|
context: "apply"
|
|
2402
|
-
});
|
|
2575
|
+
}), params.suppressWarnings);
|
|
2403
2576
|
if (!models) return;
|
|
2404
2577
|
if (params.record.acpx?.current_model_id === requestedModel) {
|
|
2405
|
-
setDesiredModelId(params.record, requestedModel);
|
|
2578
|
+
setDesiredModelId(params.record, requestedModel, models.configId);
|
|
2406
2579
|
return;
|
|
2407
2580
|
}
|
|
2408
|
-
await withTimeout(params.client.setSessionModel(params.sessionId, requestedModel), params.timeoutMs);
|
|
2409
|
-
|
|
2410
|
-
|
|
2581
|
+
const response = await withTimeout(params.client.setSessionModel(params.sessionId, requestedModel, models), params.timeoutMs);
|
|
2582
|
+
applyConfigOptionsToRecord(params.record, response);
|
|
2583
|
+
setDesiredModelId(params.record, requestedModel, models.configId);
|
|
2584
|
+
setCurrentModelId(params.record, currentModelIdFromSetModelResponse(response, requestedModel));
|
|
2585
|
+
}
|
|
2586
|
+
function emitModelSupportWarning(warning, suppressWarnings) {
|
|
2587
|
+
if (warning && !suppressWarnings) process.stderr.write(`[acpx] warning: ${warning}\n`);
|
|
2411
2588
|
}
|
|
2412
2589
|
function jsonRpcIdKey$1(value) {
|
|
2413
2590
|
if (typeof value === "string") return `s:${value}`;
|
|
@@ -2428,13 +2605,14 @@ function extractJsonRpcResponseInfo(message) {
|
|
|
2428
2605
|
const idKey = jsonRpcIdKey$1(candidate.id);
|
|
2429
2606
|
if (!idKey) return;
|
|
2430
2607
|
const hasError = Object.hasOwn(candidate, "error");
|
|
2431
|
-
|
|
2608
|
+
const hasResult = Object.hasOwn(candidate, "result");
|
|
2609
|
+
if (!hasError && !hasResult) return;
|
|
2432
2610
|
return {
|
|
2433
2611
|
idKey,
|
|
2434
2612
|
hasError
|
|
2435
2613
|
};
|
|
2436
2614
|
}
|
|
2437
|
-
const SESSION_RECONNECT_METHODS = new Set(["session/load", "session/resume"]);
|
|
2615
|
+
const SESSION_RECONNECT_METHODS = /* @__PURE__ */ new Set(["session/load", "session/resume"]);
|
|
2438
2616
|
function filterRecoverableLoadFallbackOutput(messages) {
|
|
2439
2617
|
const requestMethodById = /* @__PURE__ */ new Map();
|
|
2440
2618
|
const failedLoadRequestIds = /* @__PURE__ */ new Set();
|
|
@@ -2685,10 +2863,37 @@ async function runSessionPrompt(options) {
|
|
|
2685
2863
|
await client.setSessionMode(activeSessionIdForControl, modeId);
|
|
2686
2864
|
},
|
|
2687
2865
|
setSessionModel: async (modelId) => {
|
|
2688
|
-
|
|
2866
|
+
const models = advertisedModelState(acpxState);
|
|
2867
|
+
const response = await client.setSessionModel(activeSessionIdForControl, modelId, models);
|
|
2868
|
+
acpxState = applyConfigOptionResponseToState(acpxState, response);
|
|
2869
|
+
const nextState = cloneSessionAcpxState(acpxState) ?? {};
|
|
2870
|
+
nextState.session_options = {
|
|
2871
|
+
...nextState.session_options,
|
|
2872
|
+
model: modelId
|
|
2873
|
+
};
|
|
2874
|
+
nextState.current_model_id = currentModelIdFromSetModelResponse(response, modelId);
|
|
2875
|
+
clearDesiredConfigOption(nextState, models?.configId);
|
|
2876
|
+
acpxState = nextState;
|
|
2877
|
+
return response;
|
|
2689
2878
|
},
|
|
2690
2879
|
setSessionConfigOption: async (configId, value) => {
|
|
2691
|
-
|
|
2880
|
+
const response = await client.setSessionConfigOption(activeSessionIdForControl, configId, value);
|
|
2881
|
+
acpxState = applyConfigOptionResponseToState(acpxState, response);
|
|
2882
|
+
const nextState = cloneSessionAcpxState(acpxState) ?? {};
|
|
2883
|
+
if (configId === modelStateFromConfigOptions(nextState.config_options)?.configId) {
|
|
2884
|
+
nextState.session_options = {
|
|
2885
|
+
...nextState.session_options,
|
|
2886
|
+
model: value
|
|
2887
|
+
};
|
|
2888
|
+
nextState.current_model_id = currentModelIdFromSetModelResponse(response, value);
|
|
2889
|
+
clearDesiredConfigOption(nextState, configId);
|
|
2890
|
+
} else if (configId === "mode") nextState.desired_mode_id = value;
|
|
2891
|
+
else nextState.desired_config_options = {
|
|
2892
|
+
...nextState.desired_config_options,
|
|
2893
|
+
[configId]: value
|
|
2894
|
+
};
|
|
2895
|
+
acpxState = nextState;
|
|
2896
|
+
return response;
|
|
2692
2897
|
}
|
|
2693
2898
|
};
|
|
2694
2899
|
const flushConnectOutput = (loadError) => {
|
|
@@ -2707,6 +2912,7 @@ async function runSessionPrompt(options) {
|
|
|
2707
2912
|
resumePolicy: options.resumePolicy,
|
|
2708
2913
|
timeoutMs: options.timeoutMs,
|
|
2709
2914
|
verbose: options.verbose,
|
|
2915
|
+
suppressWarnings: options.suppressSdkConsoleErrors,
|
|
2710
2916
|
activeController,
|
|
2711
2917
|
onClientAvailable: (controller) => {
|
|
2712
2918
|
options.onClientAvailable?.(controller);
|
|
@@ -2720,6 +2926,7 @@ async function runSessionPrompt(options) {
|
|
|
2720
2926
|
}
|
|
2721
2927
|
});
|
|
2722
2928
|
});
|
|
2929
|
+
acpxState = mergeConnectedModelState(acpxState, record.acpx);
|
|
2723
2930
|
flushConnectOutput(connected.loadError);
|
|
2724
2931
|
emitConnectPerfMetric(connectStartedAt, options.verbose);
|
|
2725
2932
|
return connected;
|
|
@@ -2807,8 +3014,10 @@ async function runSessionPrompt(options) {
|
|
|
2807
3014
|
sessionId: activeSessionId,
|
|
2808
3015
|
requestedModel: sessionOptions?.model,
|
|
2809
3016
|
record,
|
|
2810
|
-
timeoutMs: options.timeoutMs
|
|
3017
|
+
timeoutMs: options.timeoutMs,
|
|
3018
|
+
suppressWarnings: options.suppressSdkConsoleErrors
|
|
2811
3019
|
});
|
|
3020
|
+
acpxState = cloneSessionAcpxState(record.acpx);
|
|
2812
3021
|
output.setContext({ sessionId: record.acpxRecordId });
|
|
2813
3022
|
await liveCheckpoint.checkpoint();
|
|
2814
3023
|
const response = await savePromptSuccess(await runPromptWithRetries(activeSessionId));
|
|
@@ -2909,7 +3118,8 @@ async function runOnce(options) {
|
|
|
2909
3118
|
requestedModel: options.sessionOptions?.model,
|
|
2910
3119
|
models: createdSession.models,
|
|
2911
3120
|
agentCommand: options.agentCommand,
|
|
2912
|
-
timeoutMs: options.timeoutMs
|
|
3121
|
+
timeoutMs: options.timeoutMs,
|
|
3122
|
+
onWarning: options.suppressSdkConsoleErrors ? void 0 : (message) => process.stderr.write(`[acpx] warning: ${message}\n`)
|
|
2913
3123
|
});
|
|
2914
3124
|
output.setContext({ sessionId });
|
|
2915
3125
|
const response = await runExecPromptWithRetries(sessionId);
|
|
@@ -2956,6 +3166,8 @@ async function submitToRunningOwner(options, waitForCompletion) {
|
|
|
2956
3166
|
sessionId: options.sessionId,
|
|
2957
3167
|
message: promptToDisplayText(options.prompt),
|
|
2958
3168
|
prompt: options.prompt,
|
|
3169
|
+
mcpConfigPath: options.mcpConfigPath,
|
|
3170
|
+
mcpConfigFingerprint: options.mcpConfigFingerprint,
|
|
2959
3171
|
permissionMode: options.permissionMode,
|
|
2960
3172
|
nonInteractivePermissions: options.nonInteractivePermissions,
|
|
2961
3173
|
permissionPolicy: options.permissionPolicy,
|
|
@@ -3001,7 +3213,7 @@ function createQueueOwnerTurnController(options) {
|
|
|
3001
3213
|
});
|
|
3002
3214
|
},
|
|
3003
3215
|
setSessionModelFallback: async (modelId, timeoutMs) => {
|
|
3004
|
-
await runSessionSetModelDirect({
|
|
3216
|
+
return (await runSessionSetModelDirect({
|
|
3005
3217
|
sessionRecordId: options.sessionId,
|
|
3006
3218
|
modelId,
|
|
3007
3219
|
mcpServers: options.mcpServers,
|
|
@@ -3011,7 +3223,7 @@ function createQueueOwnerTurnController(options) {
|
|
|
3011
3223
|
terminal: options.terminal,
|
|
3012
3224
|
timeoutMs,
|
|
3013
3225
|
verbose: options.verbose
|
|
3014
|
-
});
|
|
3226
|
+
})).response;
|
|
3015
3227
|
},
|
|
3016
3228
|
setSessionConfigOptionFallback: async (configId, value, timeoutMs) => {
|
|
3017
3229
|
return (await runSessionSetConfigOptionDirect({
|
|
@@ -3054,7 +3266,10 @@ async function writeQueueOwnerLifecycleSnapshot(sessionId, sharedClient) {
|
|
|
3054
3266
|
} catch {}
|
|
3055
3267
|
}
|
|
3056
3268
|
async function runSessionQueueOwner(options) {
|
|
3057
|
-
const lease = await tryAcquireQueueOwnerLease(options.sessionId
|
|
3269
|
+
const lease = await tryAcquireQueueOwnerLease(options.sessionId, {
|
|
3270
|
+
path: options.mcpConfigPath,
|
|
3271
|
+
fingerprint: options.mcpConfigFingerprint
|
|
3272
|
+
});
|
|
3058
3273
|
if (!lease) return;
|
|
3059
3274
|
const sessionRecord = await resolveSessionRecord(options.sessionId);
|
|
3060
3275
|
let owner;
|
|
@@ -3105,9 +3320,7 @@ async function runSessionQueueOwner(options) {
|
|
|
3105
3320
|
setSessionMode: async (modeId, timeoutMs) => {
|
|
3106
3321
|
await turnController.setSessionMode(modeId, timeoutMs);
|
|
3107
3322
|
},
|
|
3108
|
-
setSessionModel: async (modelId, timeoutMs) =>
|
|
3109
|
-
await turnController.setSessionModel(modelId, timeoutMs);
|
|
3110
|
-
},
|
|
3323
|
+
setSessionModel: async (modelId, timeoutMs) => await turnController.setSessionModel(modelId, timeoutMs),
|
|
3111
3324
|
setSessionConfigOption: async (configId, value, timeoutMs) => {
|
|
3112
3325
|
return await turnController.setSessionConfigOption(configId, value, timeoutMs);
|
|
3113
3326
|
}
|
|
@@ -3201,6 +3414,7 @@ var session_exports = /* @__PURE__ */ __exportAll({
|
|
|
3201
3414
|
listAgentSessions: () => listAgentSessions,
|
|
3202
3415
|
listSessions: () => listSessions,
|
|
3203
3416
|
listSessionsForAgent: () => listSessionsForAgent,
|
|
3417
|
+
mergeConnectedModelState: () => mergeConnectedModelState,
|
|
3204
3418
|
normalizeQueueOwnerTtlMs: () => normalizeQueueOwnerTtlMs,
|
|
3205
3419
|
pruneSessions: () => pruneSessions,
|
|
3206
3420
|
runOnce: () => runOnce,
|
|
@@ -3208,6 +3422,7 @@ var session_exports = /* @__PURE__ */ __exportAll({
|
|
|
3208
3422
|
runSessionQueueOwner: () => runSessionQueueOwner,
|
|
3209
3423
|
sendSession: () => sendSession,
|
|
3210
3424
|
sendSessionDirect: () => sendSessionDirect,
|
|
3425
|
+
sessionControlTestInternals: () => sessionControlTestInternals,
|
|
3211
3426
|
setSessionConfigOption: () => setSessionConfigOption,
|
|
3212
3427
|
setSessionMode: () => setSessionMode,
|
|
3213
3428
|
setSessionModel: () => setSessionModel
|
|
@@ -3381,10 +3596,13 @@ var JsonOutputFormatter = class {
|
|
|
3381
3596
|
sanitizeReadResponse(message) {
|
|
3382
3597
|
const candidate = message;
|
|
3383
3598
|
const idKey = jsonRpcIdKey(candidate.id);
|
|
3384
|
-
if (!idKey
|
|
3599
|
+
if (!idKey) return message;
|
|
3600
|
+
const hasResult = Object.hasOwn(candidate, "result");
|
|
3601
|
+
const hasError = Object.hasOwn(candidate, "error");
|
|
3602
|
+
if (!hasResult && !hasError) return message;
|
|
3385
3603
|
const method = this.requestMethodById.get(idKey);
|
|
3386
3604
|
this.requestMethodById.delete(idKey);
|
|
3387
|
-
if (method !== "fs/read_text_file") return message;
|
|
3605
|
+
if (method !== "fs/read_text_file" || !hasResult) return message;
|
|
3388
3606
|
const root = asRecord$1(message);
|
|
3389
3607
|
if (!root) return message;
|
|
3390
3608
|
return {
|
|
@@ -4143,4 +4361,4 @@ function createOutputFormatter(format, options = {}) {
|
|
|
4143
4361
|
//#endregion
|
|
4144
4362
|
export { runSessionQueueOwner as a, buildQueueOwnerArgOverride as c, createSessionWithClient as d, cancelSessionPrompt as f, __exportAll as g, isProcessAlive as h, session_exports as i, flushPerfMetricsCapture as l, DEFAULT_QUEUE_OWNER_TTL_MS as m, getTextErrorRemediationHints as n, runOnce as o, probeQueueOwnerHealth as p, output_exports as r, sendSessionDirect as s, createOutputFormatter as t, installPerfMetricsCapture as u };
|
|
4145
4363
|
|
|
4146
|
-
//# sourceMappingURL=output-
|
|
4364
|
+
//# sourceMappingURL=output-BEv_BB7T.js.map
|