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.
Files changed (34) hide show
  1. package/README.md +25 -19
  2. package/dist/{cli-8dP_TqBp.js → cli-D4XUKXcD.js} +5 -5
  3. package/dist/{cli-8dP_TqBp.js.map → cli-D4XUKXcD.js.map} +1 -1
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +429 -88
  7. package/dist/cli.js.map +1 -1
  8. package/dist/{client-C4iJBO0j.d.ts → client-DIlpCkHw.d.ts} +38 -5
  9. package/dist/client-DIlpCkHw.d.ts.map +1 -0
  10. package/dist/{flags--2oX_ubW.js → flags-Dvgmpq_l.js} +5 -5
  11. package/dist/flags-Dvgmpq_l.js.map +1 -0
  12. package/dist/{flows-e4umXVbY.js → flows-Cvsc-_AW.js} +4 -3
  13. package/dist/flows-Cvsc-_AW.js.map +1 -0
  14. package/dist/flows.d.ts +1 -1
  15. package/dist/flows.d.ts.map +1 -1
  16. package/dist/flows.js +1 -1
  17. package/dist/{live-checkpoint-CuFft_Nd.js → live-checkpoint-BWkYxMeS.js} +848 -207
  18. package/dist/live-checkpoint-BWkYxMeS.js.map +1 -0
  19. package/dist/{output-Di77Yugq.js → output-BEv_BB7T.js} +359 -141
  20. package/dist/output-BEv_BB7T.js.map +1 -0
  21. package/dist/runtime.d.ts +71 -5
  22. package/dist/runtime.d.ts.map +1 -1
  23. package/dist/runtime.js +192 -35
  24. package/dist/runtime.js.map +1 -1
  25. package/dist/{session-options-Bh1bIqQ2.d.ts → session-options-jkYbBxGE.d.ts} +27 -2
  26. package/dist/session-options-jkYbBxGE.d.ts.map +1 -0
  27. package/package.json +21 -20
  28. package/skills/acpx/SKILL.md +58 -3
  29. package/dist/client-C4iJBO0j.d.ts.map +0 -1
  30. package/dist/flags--2oX_ubW.js.map +0 -1
  31. package/dist/flows-e4umXVbY.js.map +0 -1
  32. package/dist/live-checkpoint-CuFft_Nd.js.map +0 -1
  33. package/dist/output-Di77Yugq.js.map +0 -1
  34. package/dist/session-options-Bh1bIqQ2.d.ts.map +0 -1
@@ -1,10 +1,11 @@
1
- import { $ as defaultSessionEventLog, A as findGitRepositoryRoot, Bt as QueueConnectionError, C as applyConversation, Ct as formatErrorMessage, E as AcpClient, F as listSessionsForAgent, G as recordPerfDuration, H as getPerfMetricsSnapshot, I as normalizeName, J as startPerfTimer, K as resetPerfMetrics, L as pruneSessions, M as findSessionByDirectoryWalk, Mt as OUTPUT_ERROR_CODES, N as isoNow, Nt as OUTPUT_ERROR_ORIGINS, Ot as toAcpErrorPayload, P as listSessions, R as resolveSessionRecord, S as sessionOptionsFromRecord, Tt as normalizeOutputError, U as incrementPerfCounter, V as formatPerfMetric, Vt as QueueProtocolError, W as measurePerf, Z as normalizeRuntimeSessionId, _ as recordPromptSubmission, _t as withTimeout, a as applyRequestedModelIfAdvertised, at as isAcpJsonRpcMessage, b as mergeSessionOptions, c as setDesiredConfigOption, d as syncAdvertisedModelState, et as sessionBaseDir, f as applyConfigOptionsToRecord, ft as promptToDisplayText, g as recordClientOperation, gt as withInterrupt, h as createSessionConversation, ht as TimeoutError, i as connectAndLoadSession, it as extractSessionUpdateNotification, j as findSession, k as absolutePath, l as setDesiredModeId, lt as isPromptInput, m as cloneSessionConversation, mt as InterruptedError, n as runPromptTurn, nt as sessionEventLockPath, o as assertRequestedModelSupported, ot as parseJsonRpcErrorMessage, p as cloneSessionAcpxState, pt as textPrompt, q as setPerfGauge, r as withConnectedSession, rt as sessionEventSegmentPath, s as setCurrentModelId, st as parsePromptStopReason, t as LiveSessionCheckpoint, tt as sessionEventActivePath, u as setDesiredModelId, v as recordSessionUpdate, w as applyLifecycleSnapshotToRecord, wt as isRetryablePromptError, x as persistSessionOptions, y as trimConversationForRuntime, z as writeSessionRecord } from "./live-checkpoint-CuFft_Nd.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-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
- 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;
@@ -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: (message, context) => parseStringResultOwnerMessage(message, context, "set_model_result", "modelId"),
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
- 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 }));
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
- if (task.waitForCompletion) task.send({
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 true;
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
- if (await submitSetModelToQueueOwner(owner, modelId, timeoutMs)) {
1457
- if (verbose) process.stderr.write(`[acpx] requested session/set_model on owner pid ${owner.pid} for session ${sessionId}\n`);
1458
- return true;
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
- return toSessionMutationResult(await withConnectedSession(buildDirectConnectedSessionOptions(options, async ({ client, sessionId, record }) => {
1518
- await withTimeout(client.setSessionModel(sessionId, options.modelId), options.timeoutMs);
1519
- setDesiredModelId(record, options.modelId);
1520
- setCurrentModelId(record, options.modelId);
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
- if (options.configId === "mode") setDesiredModeId(record, options.value);
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
- if (await trySetModelOnRunningOwner(options.sessionId, options.modelId, options.timeoutMs, options.verbose)) {
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
- setDesiredModelId(record, options.modelId);
1572
- setCurrentModelId(record, options.modelId);
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
- if (options.configId === "mode") setDesiredModeId(record, options.value);
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
- const trimmed = command.trim();
1619
- if (!trimmed) return;
1620
- const token = trimmed.split(/\s+/, 1)[0];
1621
- return token.length > 0 ? token : void 0;
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 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) {
1627
1735
  try {
1628
- const argv = (await fs$1.readFile(procCmdline, "utf8")).split("\0").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
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 true;
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
- let sessionId;
1654
- let agentSessionId;
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
- applyConfigOptionsToRecord(record, sessionResult);
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: await applyRequestedModelIfAdvertised({
1724
- client,
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
- await this.options.withTimeout(async () => await activeController.setSessionModel(modelId), timeoutMs);
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 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];
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 payload = JSON.stringify(options);
2134
- spawn(process.execPath, resolveQueueOwnerSpawnArgs(), buildQueueOwnerSpawnOptions(payload)).unref();
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 advertisedModelsForRecord(record) {
2383
- const availableModels = record.acpx?.available_models;
2384
- if (!Array.isArray(availableModels)) return;
2385
- return {
2386
- currentModelId: record.acpx?.current_model_id ?? "",
2387
- availableModels: availableModels.map((modelId) => ({
2388
- modelId,
2389
- name: modelId
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 = advertisedModelsForRecord(params.record);
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
- setDesiredModelId(params.record, requestedModel);
2410
- setCurrentModelId(params.record, requestedModel);
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
- if (!hasError && !Object.hasOwn(candidate, "result")) return;
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
- await client.setSessionModel(activeSessionIdForControl, modelId);
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
- return await client.setSessionConfigOption(activeSessionIdForControl, configId, value);
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 || !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;
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-Di77Yugq.js.map
4364
+ //# sourceMappingURL=output-BEv_BB7T.js.map