acpx 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
- import { $ as setPerfGauge, A as assertRequestedModelSupported, At as isRetryablePromptError, B as listSessions, C as mergeSessionOptions, Ct as withTimeout, D as applyLifecycleSnapshotToRecord, E as applyConversation, F as absolutePath, G as writeSessionRecord, H as normalizeName, I as findGitRepositoryRoot, J as getPerfMetricsSnapshot, Kt as QueueConnectionError, L as findSession, Pt as toAcpErrorPayload, Q as resetPerfMetrics, R as findSessionByDirectoryWalk, Rt as OUTPUT_ERROR_CODES, S as advertisedModelState, St as withInterrupt, T as sessionOptionsFromRecord, U as pruneSessions, V as listSessionsForAgent, W as resolveSessionRecord, X as measurePerf, Y as incrementPerfCounter, Z as recordPerfDuration, _ as createSessionConversation, a as applyRequestedModelIfAdvertised, at as defaultSessionEventLog, b as recordSessionUpdate, bt as InterruptedError, c as setCurrentModelId, ct as sessionEventLockPath, d as setDesiredModelId, dt as isAcpJsonRpcMessage, et as startPerfTimer, f as syncAdvertisedModelState, ft as parseJsonRpcErrorMessage, g as cloneSessionConversation, h as cloneSessionAcpxState, ht as isPromptInput, i as connectAndLoadSession, j as modelStateFromConfigOptions, jt as normalizeOutputError, k as AcpClient, kt as formatErrorMessage, l as setDesiredConfigOption, lt as sessionEventSegmentPath, m as applyConfigOptionsToState, n as runPromptTurn, o as currentModelIdFromSetModelResponse, ot as sessionBaseDir, p as applyConfigOptionsToRecord, pt as parsePromptStopReason, q as formatPerfMetric, qt as QueueProtocolError, r as withConnectedSession, rt as normalizeRuntimeSessionId, s as clearDesiredConfigOption, st as sessionEventActivePath, t as LiveSessionCheckpoint, u as setDesiredModeId, ut as extractSessionUpdateNotification, v as recordClientOperation, vt as promptToDisplayText, w as persistSessionOptions, x as trimConversationForRuntime, xt as TimeoutError, y as recordPromptSubmission, yt as textPrompt, z as isoNow, zt as OUTPUT_ERROR_ORIGINS } from "./live-checkpoint-BZrk9Mjz.js";
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-mdAaF3qJ.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
- if (alive) await terminateProcess(owner.pid).catch(() => {});
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 = nowIsoFactory();
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
- if (error.code !== "EEXIST") throw error;
218
- const owner = await readQueueOwnerRecord(sessionId);
219
- if (!owner) {
220
- await cleanupStaleQueueOwner(sessionId, owner);
221
- return;
222
- }
223
- if (!isProcessAlive(owner.pid) || isQueueOwnerHeartbeatStale(owner)) {
224
- if (isProcessAlive(owner.pid)) await terminateProcess(owner.pid).catch(() => {});
225
- await cleanupStaleQueueOwner(sessionId, owner);
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;
@@ -818,25 +866,26 @@ var SessionQueueOwner = class SessionQueueOwner {
818
866
  }
819
867
  enqueue(task) {
820
868
  if (this.closed) {
821
- if (task.waitForCompletion) task.send(makeQueueOwnerError(task.requestId, "Queue owner is shutting down", "QUEUE_OWNER_SHUTTING_DOWN", { retryable: true }));
869
+ task.send(makeQueueOwnerError(task.requestId, "Queue owner is shutting down", "QUEUE_OWNER_SHUTTING_DOWN", { retryable: true }));
822
870
  task.close();
823
- return;
871
+ return false;
824
872
  }
825
873
  const waiter = this.waiters.shift();
826
874
  if (waiter) {
827
875
  waiter(task);
828
- return;
876
+ return true;
829
877
  }
830
878
  if (this.pending.length >= this.maxQueueDepth) {
831
- if (task.waitForCompletion) task.send({
879
+ task.send({
832
880
  ...makeQueueOwnerError(task.requestId, `Queue owner is overloaded (${this.pending.length}/${this.maxQueueDepth} queued)`, "QUEUE_OWNER_OVERLOADED", { retryable: true }),
833
881
  ownerGeneration: this.ownerGeneration
834
882
  });
835
883
  task.close();
836
- return;
884
+ return false;
837
885
  }
838
886
  this.pending.push(task);
839
887
  this.emitQueueDepth();
888
+ return true;
840
889
  }
841
890
  handleControlRequest(options) {
842
891
  writeQueueMessage(options.socket, {
@@ -980,13 +1029,13 @@ var SessionQueueOwner = class SessionQueueOwner {
980
1029
  if (!socket.destroyed) socket.end();
981
1030
  }
982
1031
  };
1032
+ if (!this.enqueue(task)) return;
983
1033
  writeQueueMessage(socket, {
984
1034
  type: "accepted",
985
1035
  requestId: request.requestId,
986
1036
  ownerGeneration: this.ownerGeneration
987
1037
  });
988
1038
  if (!request.waitForCompletion) task.close();
989
- this.enqueue(task);
990
1039
  }
991
1040
  handleConnection(socket) {
992
1041
  socket.setEncoding("utf8");
@@ -1025,7 +1074,7 @@ var SessionQueueOwner = class SessionQueueOwner {
1025
1074
  //#endregion
1026
1075
  //#region src/cli/queue/ipc.ts
1027
1076
  const MAX_MESSAGE_BUFFER_SIZE = 10 * 1024 * 1024;
1028
- 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"]);
1029
1078
  async function maybeRecoverStaleOwnerAfterProtocolMismatch(params) {
1030
1079
  if (!(params.error instanceof QueueProtocolError)) return false;
1031
1080
  const detailCode = params.error.detailCode;
@@ -1392,9 +1441,22 @@ async function submitCloseSessionToQueueOwner(owner, timeoutMs) {
1392
1441
  });
1393
1442
  return response.closed;
1394
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
+ }
1395
1455
  async function trySubmitToRunningOwner(options) {
1396
1456
  const owner = await readQueueOwnerRecord(options.sessionId);
1397
1457
  if (!owner) return;
1458
+ if (!await ensureOwnerIsUsable(options.sessionId, owner)) return;
1459
+ assertQueueOwnerMcpConfigMatches(owner, options);
1398
1460
  let submitted;
1399
1461
  try {
1400
1462
  submitted = await submitToQueueOwner(owner, options);
@@ -1561,6 +1623,7 @@ async function runSessionSetConfigOptionDirect(options) {
1561
1623
  }
1562
1624
  //#endregion
1563
1625
  //#region src/cli/session/session-control.ts
1626
+ const execFileAsync = promisify(execFile);
1564
1627
  async function cancelSessionPrompt(options) {
1565
1628
  const cancelled = await tryCancelOnRunningOwner(options);
1566
1629
  return {
@@ -1648,25 +1711,72 @@ async function setSessionConfigOption(options) {
1648
1711
  });
1649
1712
  }
1650
1713
  function firstAgentCommandToken(command) {
1651
- const trimmed = command.trim();
1652
- if (!trimmed) return;
1653
- const token = trimmed.split(/\s+/, 1)[0];
1654
- return token.length > 0 ? token : void 0;
1714
+ try {
1715
+ return splitCommandLine(command).command || void 0;
1716
+ } catch {
1717
+ return;
1718
+ }
1655
1719
  }
1656
1720
  async function isLikelyMatchingProcess(pid, agentCommand) {
1657
1721
  const expectedToken = firstAgentCommandToken(agentCommand);
1658
1722
  if (!expectedToken) return false;
1659
- const procCmdline = `/proc/${pid}/cmdline`;
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) {
1660
1735
  try {
1661
- const argv = (await fs$1.readFile(procCmdline, "utf8")).split("\0").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
1662
- if (argv.length === 0) return false;
1663
- const executableBase = path.basename(argv[0]);
1664
- const expectedBase = path.basename(expectedToken);
1665
- 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);
1666
1737
  } catch {
1667
- return true;
1738
+ return;
1668
1739
  }
1669
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
+ };
1670
1780
  async function closeSession(sessionId) {
1671
1781
  const record = await resolveSessionRecord(sessionId);
1672
1782
  await tryCloseSessionOnRunningOwner({ sessionId: record.acpxRecordId }).catch(() => {});
@@ -2062,22 +2172,24 @@ var QueueOwnerTurnController = class {
2062
2172
  };
2063
2173
  //#endregion
2064
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";
2065
2177
  function isNonEmptyStringArray(value) {
2066
2178
  return Array.isArray(value) && value.length > 0 && value.every((entry) => typeof entry === "string" && entry.length > 0);
2067
2179
  }
2068
- const NODE_TEST_FLAGS = new Set([
2180
+ const NODE_TEST_FLAGS = /* @__PURE__ */ new Set([
2069
2181
  "--experimental-test-coverage",
2070
2182
  "--test",
2071
2183
  "--test-name-pattern",
2072
2184
  "--test-reporter",
2073
2185
  "--test-reporter-destination"
2074
2186
  ]);
2075
- const NODE_TEST_FLAGS_WITH_VALUE = new Set([
2187
+ const NODE_TEST_FLAGS_WITH_VALUE = /* @__PURE__ */ new Set([
2076
2188
  "--test-name-pattern",
2077
2189
  "--test-reporter",
2078
2190
  "--test-reporter-destination"
2079
2191
  ]);
2080
- const INSPECTOR_FLAGS_WITH_VALUE = new Set([
2192
+ const INSPECTOR_FLAGS_WITH_VALUE = /* @__PURE__ */ new Set([
2081
2193
  "--inspect",
2082
2194
  "--inspect-brk",
2083
2195
  "--inspect-port",
@@ -2137,6 +2249,8 @@ function queueOwnerRuntimeOptionsFromSend(options) {
2137
2249
  return {
2138
2250
  sessionId: options.sessionId,
2139
2251
  mcpServers: options.mcpServers,
2252
+ ...options.mcpConfigPath ? { mcpConfigPath: options.mcpConfigPath } : {},
2253
+ ...options.mcpConfigFingerprint ? { mcpConfigFingerprint: options.mcpConfigFingerprint } : {},
2140
2254
  permissionMode: options.permissionMode,
2141
2255
  nonInteractivePermissions: options.nonInteractivePermissions,
2142
2256
  authCredentials: options.authCredentials,
@@ -2150,20 +2264,32 @@ function queueOwnerRuntimeOptionsFromSend(options) {
2150
2264
  sessionOptions: options.sessionOptions
2151
2265
  };
2152
2266
  }
2153
- function buildQueueOwnerSpawnOptions(payload) {
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];
2154
2283
  return {
2155
2284
  detached: true,
2156
2285
  stdio: "ignore",
2157
- env: {
2158
- ...process.env,
2159
- ACPX_QUEUE_OWNER_PAYLOAD: payload
2160
- },
2286
+ env,
2161
2287
  windowsHide: true
2162
2288
  };
2163
2289
  }
2164
2290
  function spawnQueueOwnerProcess(options) {
2165
- const payload = JSON.stringify(options);
2166
- spawn(process.execPath, resolveQueueOwnerSpawnArgs(), buildQueueOwnerSpawnOptions(payload)).unref();
2291
+ const payloadPath = writeQueueOwnerPayloadFile(JSON.stringify(options));
2292
+ spawn(process.execPath, resolveQueueOwnerSpawnArgs(), buildQueueOwnerSpawnOptions(payloadPath)).unref();
2167
2293
  }
2168
2294
  //#endregion
2169
2295
  //#region src/session/events.ts
@@ -2479,13 +2605,14 @@ function extractJsonRpcResponseInfo(message) {
2479
2605
  const idKey = jsonRpcIdKey$1(candidate.id);
2480
2606
  if (!idKey) return;
2481
2607
  const hasError = Object.hasOwn(candidate, "error");
2482
- if (!hasError && !Object.hasOwn(candidate, "result")) return;
2608
+ const hasResult = Object.hasOwn(candidate, "result");
2609
+ if (!hasError && !hasResult) return;
2483
2610
  return {
2484
2611
  idKey,
2485
2612
  hasError
2486
2613
  };
2487
2614
  }
2488
- const SESSION_RECONNECT_METHODS = new Set(["session/load", "session/resume"]);
2615
+ const SESSION_RECONNECT_METHODS = /* @__PURE__ */ new Set(["session/load", "session/resume"]);
2489
2616
  function filterRecoverableLoadFallbackOutput(messages) {
2490
2617
  const requestMethodById = /* @__PURE__ */ new Map();
2491
2618
  const failedLoadRequestIds = /* @__PURE__ */ new Set();
@@ -3039,6 +3166,8 @@ async function submitToRunningOwner(options, waitForCompletion) {
3039
3166
  sessionId: options.sessionId,
3040
3167
  message: promptToDisplayText(options.prompt),
3041
3168
  prompt: options.prompt,
3169
+ mcpConfigPath: options.mcpConfigPath,
3170
+ mcpConfigFingerprint: options.mcpConfigFingerprint,
3042
3171
  permissionMode: options.permissionMode,
3043
3172
  nonInteractivePermissions: options.nonInteractivePermissions,
3044
3173
  permissionPolicy: options.permissionPolicy,
@@ -3137,7 +3266,10 @@ async function writeQueueOwnerLifecycleSnapshot(sessionId, sharedClient) {
3137
3266
  } catch {}
3138
3267
  }
3139
3268
  async function runSessionQueueOwner(options) {
3140
- const lease = await tryAcquireQueueOwnerLease(options.sessionId);
3269
+ const lease = await tryAcquireQueueOwnerLease(options.sessionId, {
3270
+ path: options.mcpConfigPath,
3271
+ fingerprint: options.mcpConfigFingerprint
3272
+ });
3141
3273
  if (!lease) return;
3142
3274
  const sessionRecord = await resolveSessionRecord(options.sessionId);
3143
3275
  let owner;
@@ -3290,6 +3422,7 @@ var session_exports = /* @__PURE__ */ __exportAll({
3290
3422
  runSessionQueueOwner: () => runSessionQueueOwner,
3291
3423
  sendSession: () => sendSession,
3292
3424
  sendSessionDirect: () => sendSessionDirect,
3425
+ sessionControlTestInternals: () => sessionControlTestInternals,
3293
3426
  setSessionConfigOption: () => setSessionConfigOption,
3294
3427
  setSessionMode: () => setSessionMode,
3295
3428
  setSessionModel: () => setSessionModel
@@ -3463,10 +3596,13 @@ var JsonOutputFormatter = class {
3463
3596
  sanitizeReadResponse(message) {
3464
3597
  const candidate = message;
3465
3598
  const idKey = jsonRpcIdKey(candidate.id);
3466
- if (!idKey || !Object.hasOwn(candidate, "result")) return message;
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;
3467
3603
  const method = this.requestMethodById.get(idKey);
3468
3604
  this.requestMethodById.delete(idKey);
3469
- if (method !== "fs/read_text_file") return message;
3605
+ if (method !== "fs/read_text_file" || !hasResult) return message;
3470
3606
  const root = asRecord$1(message);
3471
3607
  if (!root) return message;
3472
3608
  return {
@@ -4225,4 +4361,4 @@ function createOutputFormatter(format, options = {}) {
4225
4361
  //#endregion
4226
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 };
4227
4363
 
4228
- //# sourceMappingURL=output-D_BGt1YI.js.map
4364
+ //# sourceMappingURL=output-Smw6kFL_.js.map