acpx 0.16.0 → 0.17.0

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 (36) hide show
  1. package/README.md +2 -0
  2. package/dist/{cli-BkYIxj_N.js → cli-CiyfEC7L.js} +5 -4
  3. package/dist/{cli-BkYIxj_N.js.map → cli-CiyfEC7L.js.map} +1 -1
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.js +33 -26
  6. package/dist/cli.js.map +1 -1
  7. package/dist/{client-5levcBIs.d.ts → client-C6NUFqr-.d.ts} +12 -6
  8. package/dist/client-C6NUFqr-.d.ts.map +1 -0
  9. package/dist/{flows-Bxs4udrs.js → flows-CTOdIk-m.js} +6 -5
  10. package/dist/{flows-Bxs4udrs.js.map → flows-CTOdIk-m.js.map} +1 -1
  11. package/dist/flows.d.ts +2 -2
  12. package/dist/flows.js +1 -1
  13. package/dist/{invocation-options-BY4lxkn3.js → invocation-options-DbCcOAzM.js} +4 -3
  14. package/dist/{invocation-options-BY4lxkn3.js.map → invocation-options-DbCcOAzM.js.map} +1 -1
  15. package/dist/ipc-D3akHMEq.js +3350 -0
  16. package/dist/ipc-D3akHMEq.js.map +1 -0
  17. package/dist/output-BPPjvJTI.js +980 -0
  18. package/dist/output-BPPjvJTI.js.map +1 -0
  19. package/dist/{live-checkpoint-BEfxBKCh.js → queue-owner-runtime--IbbndGz.js} +3052 -1852
  20. package/dist/queue-owner-runtime--IbbndGz.js.map +1 -0
  21. package/dist/runtime.d.ts +99 -12
  22. package/dist/runtime.d.ts.map +1 -1
  23. package/dist/runtime.js +308 -69
  24. package/dist/runtime.js.map +1 -1
  25. package/dist/{session-options-t3d-F4dn.d.ts → session-options-Dp6mzNSy.d.ts} +2 -2
  26. package/dist/{session-options-t3d-F4dn.d.ts.map → session-options-Dp6mzNSy.d.ts.map} +1 -1
  27. package/dist/session-watch--UX5dh00.js +76 -0
  28. package/dist/session-watch--UX5dh00.js.map +1 -0
  29. package/dist/watch-BbBxO-kb.js +32 -0
  30. package/dist/watch-BbBxO-kb.js.map +1 -0
  31. package/package.json +1 -1
  32. package/skills/acpx/SKILL.md +5 -2
  33. package/dist/client-5levcBIs.d.ts.map +0 -1
  34. package/dist/live-checkpoint-BEfxBKCh.js.map +0 -1
  35. package/dist/output-uo5a27KB.js +0 -4711
  36. package/dist/output-uo5a27KB.js.map +0 -1
package/dist/runtime.js CHANGED
@@ -1,5 +1,8 @@
1
- import { A as isRequestedModelUnsupportedError, C as recordSessionUpdate, D as REQUESTED_MODEL_UNSUPPORTED_ERROR_CODE, Dt as withTimeout, E as AcpClient, L as textPrompt, Mt as extractAcpError, Nt as isAcpResourceNotFoundError, O as REQUESTED_MODEL_UNSUPPORTED_REASONS, S as recordPromptSubmission, T as advertisedModelState, Z as assertPersistedKeyPolicy, _ as reconcileAgentSessionId, a as applyConfigOptionSelection, c as applyModelSelection, f as persistSessionOptions, g as createInitialSessionRecord, gt as writePrivateJsonFile, h as applyLifecycleSnapshotToRecord, i as connectAndLoadSession, jt as normalizeOutputError, k as RequestedModelUnsupportedError, l as applyRequestedModelIfAdvertised, m as applyConversation, n as runPromptTurn, o as applyConfigOptionsToRecord, ot as parseSessionRecord, p as sessionOptionsFromRecord, r as withConnectedSession, s as applyInitialModelSelection, st as serializeSessionRecordForDisk, t as LiveSessionCheckpoint, u as setDesiredModeId, v as cloneSessionAcpxState, w as trimConversationForRuntime, x as recordClientOperation, y as cloneSessionConversation } from "./live-checkpoint-BEfxBKCh.js";
1
+ import { C as textPrompt, D as findSession, F as resolveSessionRecord, L as assertPersistedKeyPolicy, P as readSessionRecord, R as parseSessionRecord, gt as extractAcpError, mt as writePrivateJsonFile, t as tryCancelOnRunningOwner, vt as isAcpResourceNotFoundError, z as serializeSessionRecordForDisk } from "./ipc-D3akHMEq.js";
2
+ import { A as setDesiredModeId, B as recordClientOperation, C as withConnectedSession, D as applyInitialModelSelection, E as applyConfigOptionsToRecord, F as createInitialSessionRecord, G as AcpClient, H as recordSessionUpdate, I as reconcileAgentSessionId, J as RequestedModelUnsupportedError, K as REQUESTED_MODEL_UNSUPPORTED_ERROR_CODE, L as cloneSessionAcpxState, M as sessionOptionsFromRecord, N as applyConversation, O as applyModelSelection, P as applyLifecycleSnapshotToRecord, R as cloneSessionConversation, T as applyConfigOptionSelection, U as trimConversationForRuntime, V as recordPromptSubmission, W as advertisedModelState, Y as isRequestedModelUnsupportedError, _ as cancelSessionPrompt, c as LiveSessionCheckpoint, ct as normalizeOutputError, h as ensureSession, it as assertControlAuthority, j as persistSessionOptions, k as applyRequestedModelIfAdvertised, l as runPromptTurn, ot as withTimeout, q as REQUESTED_MODEL_UNSUPPORTED_REASONS, r as sendSession, s as DISCARD_OUTPUT_FORMATTER, v as closeSession, w as connectAndLoadSession } from "./queue-owner-runtime--IbbndGz.js";
2
3
  import { D as normalizeAgentCommandInput, a as createAgentRegistry, i as DEFAULT_AGENT_NAME } from "./agent-registry-DU6mhZBL.js";
4
+ import { t as watchSession } from "./watch-BbBxO-kb.js";
5
+ import { fileURLToPath } from "node:url";
3
6
  import path from "node:path";
4
7
  import fs from "node:fs/promises";
5
8
  import { randomUUID } from "node:crypto";
@@ -733,7 +736,7 @@ function commandRecord(value) {
733
736
  return value;
734
737
  }
735
738
  //#endregion
736
- //#region src/runtime/engine/manager.ts
739
+ //#region src/runtime/engine/turn.ts
737
740
  function createDeferred() {
738
741
  let resolve;
739
742
  let reject;
@@ -746,22 +749,6 @@ function createDeferred() {
746
749
  reject
747
750
  };
748
751
  }
749
- async function settleAttempt(run) {
750
- try {
751
- return {
752
- ok: true,
753
- value: await run()
754
- };
755
- } catch (error) {
756
- return {
757
- ok: false,
758
- error
759
- };
760
- }
761
- }
762
- function firstFailedAttempt(attempts) {
763
- return attempts.find((attempt) => !attempt.ok);
764
- }
765
752
  var AsyncEventQueue = class {
766
753
  items = [];
767
754
  waits = [];
@@ -798,17 +785,6 @@ var AsyncEventQueue = class {
798
785
  }
799
786
  }
800
787
  };
801
- function isoNow() {
802
- return (/* @__PURE__ */ new Date()).toISOString();
803
- }
804
- function isUnsupportedSessionCloseError(error) {
805
- const acp = extractAcpError(error);
806
- if (!acp) return false;
807
- if (acp.code === -32601 || acp.code === -32602) return true;
808
- if (acp.code !== -32603 || !acp.data || typeof acp.data !== "object") return false;
809
- const details = acp.data.details;
810
- return typeof details === "string" && details.toLowerCase().includes("invalid params");
811
- }
812
788
  function toPromptInput(text, attachments) {
813
789
  if (!attachments || attachments.length === 0) return text;
814
790
  const blocks = [];
@@ -837,13 +813,6 @@ function toPromptInput(text, attachments) {
837
813
  }
838
814
  return blocks.length > 0 ? blocks : textPrompt(text);
839
815
  }
840
- function createRecordId(sessionKey, mode) {
841
- if (mode === "persistent") return sessionKey;
842
- return `${sessionKey}:oneshot:${randomUUID()}`;
843
- }
844
- function resumePolicyForSessionMode(mode) {
845
- return mode === "persistent" ? "same-session-only" : "allow-new";
846
- }
847
816
  function legacyTerminalEventFromTurnResult(result) {
848
817
  if (result.status === "failed") return {
849
818
  type: "error",
@@ -858,6 +827,42 @@ function legacyTerminalEventFromTurnResult(result) {
858
827
  ...result._meta === void 0 ? {} : { _meta: result._meta }
859
828
  };
860
829
  }
830
+ //#endregion
831
+ //#region src/runtime/engine/manager.ts
832
+ async function settleAttempt(run) {
833
+ try {
834
+ return {
835
+ ok: true,
836
+ value: await run()
837
+ };
838
+ } catch (error) {
839
+ return {
840
+ ok: false,
841
+ error
842
+ };
843
+ }
844
+ }
845
+ function firstFailedAttempt(attempts) {
846
+ return attempts.find((attempt) => !attempt.ok);
847
+ }
848
+ function isoNow() {
849
+ return (/* @__PURE__ */ new Date()).toISOString();
850
+ }
851
+ function isUnsupportedSessionCloseError(error) {
852
+ const acp = extractAcpError(error);
853
+ if (!acp) return false;
854
+ if (acp.code === -32601 || acp.code === -32602) return true;
855
+ if (acp.code !== -32603 || !acp.data || typeof acp.data !== "object") return false;
856
+ const details = acp.data.details;
857
+ return typeof details === "string" && details.toLowerCase().includes("invalid params");
858
+ }
859
+ function createRecordId(sessionKey, mode) {
860
+ if (mode === "persistent") return sessionKey;
861
+ return `${sessionKey}:oneshot:${randomUUID()}`;
862
+ }
863
+ function resumePolicyForSessionMode(mode) {
864
+ return mode === "persistent" ? "same-session-only" : "allow-new";
865
+ }
861
866
  function advertisedConfigOptionIds(record) {
862
867
  const configOptions = record.acpx?.config_options;
863
868
  if (!configOptions) return;
@@ -1179,9 +1184,11 @@ var AcpRuntimeManager = class {
1179
1184
  agentArgv: agentArgv ? [...agentArgv] : void 0
1180
1185
  }) : servers ?? []];
1181
1186
  }
1182
- async withRuntimeControlSession(record, sessionMode, run, replacingConfigOption) {
1187
+ async withRuntimeControlSession(record, sessionMode, run, replacingConfigOption, authority) {
1183
1188
  await this.retrySessionCleanup(record.acpxRecordId);
1189
+ assertControlAuthority(authority);
1184
1190
  const owner = await this.readRetainedSessionOwner(record, { consume: false });
1191
+ assertControlAuthority(authority);
1185
1192
  if (owner) {
1186
1193
  const ownedRecord = owner.projection?.record ?? record;
1187
1194
  try {
@@ -1226,6 +1233,7 @@ var AcpRuntimeManager = class {
1226
1233
  timeoutMs: this.options.timeoutMs,
1227
1234
  resumePolicy: resumePolicyForSessionMode(sessionMode),
1228
1235
  replacingConfigOption,
1236
+ authority,
1229
1237
  run
1230
1238
  });
1231
1239
  return {
@@ -1251,8 +1259,9 @@ var AcpRuntimeManager = class {
1251
1259
  const key = `${input.mode}\0${input.sessionKey}`;
1252
1260
  return await this.withManagerLock(this.ensureSessionLocks, key, run);
1253
1261
  }
1254
- async withManagerLock(locks, key, run) {
1262
+ async withManagerLock(locks, key, run, authority) {
1255
1263
  this.assertOpen();
1264
+ assertControlAuthority(authority);
1256
1265
  const previous = locks.get(key) ?? Promise.resolve();
1257
1266
  let release;
1258
1267
  const gate = new Promise((resolve) => {
@@ -1263,6 +1272,7 @@ var AcpRuntimeManager = class {
1263
1272
  await previous;
1264
1273
  try {
1265
1274
  this.assertOpen();
1275
+ assertControlAuthority(authority);
1266
1276
  return await run();
1267
1277
  } finally {
1268
1278
  release();
@@ -1685,24 +1695,24 @@ var AcpRuntimeManager = class {
1685
1695
  return {
1686
1696
  hasActivePrompt: () => turn.client.hasActivePrompt(),
1687
1697
  requestCancelActivePrompt: async () => await this.requestRuntimeTurnCancel(task, turn),
1688
- setSessionMode: async (modeId) => {
1698
+ setSessionMode: async (modeId, authority) => {
1689
1699
  await this.waitForRuntimeControlSession(task, turn);
1690
- await turn.client.setSessionMode(turn.activeSessionId, modeId);
1700
+ await turn.client.setSessionMode(turn.activeSessionId, modeId, authority);
1691
1701
  const nextState = cloneSessionAcpxState(turn.acpxState) ?? {};
1692
1702
  nextState.desired_mode_id = modeId;
1693
1703
  turn.acpxState = nextState;
1694
1704
  },
1695
- setSessionModel: async (modelId) => {
1705
+ setSessionModel: async (modelId, authority) => {
1696
1706
  await this.waitForRuntimeControlSession(task, turn);
1697
1707
  const models = advertisedModelState(turn.acpxState);
1698
- const response = await turn.client.setSessionModel(turn.activeSessionId, modelId, models);
1708
+ const response = await turn.client.setSessionModel(turn.activeSessionId, modelId, models, authority);
1699
1709
  turn.acpxState = applyModelSelection(turn.acpxState, modelId, response);
1700
1710
  return response;
1701
1711
  },
1702
- setSessionConfigOption: async (configId, value) => {
1703
- return (await task.state.activeController.setResolvedSessionConfigOption(configId, value)).response;
1712
+ setSessionConfigOption: async (configId, value, authority) => {
1713
+ return (await task.state.activeController.setResolvedSessionConfigOption(configId, value, authority)).response;
1704
1714
  },
1705
- setResolvedSessionConfigOption: async (configId, value) => await this.setRuntimeResolvedSessionConfigOption(task, turn, configId, value)
1715
+ setResolvedSessionConfigOption: async (configId, value, authority) => await this.setRuntimeResolvedSessionConfigOption(task, turn, configId, value, authority)
1706
1716
  };
1707
1717
  }
1708
1718
  async waitForRuntimeControlSession(task, turn) {
@@ -1715,14 +1725,14 @@ var AcpRuntimeManager = class {
1715
1725
  task.state.pendingCancel = true;
1716
1726
  return true;
1717
1727
  }
1718
- async setRuntimeResolvedSessionConfigOption(task, turn, configId, value) {
1728
+ async setRuntimeResolvedSessionConfigOption(task, turn, configId, value, authority) {
1719
1729
  await this.waitForRuntimeControlSession(task, turn);
1720
1730
  const resolvedConfigId = resolveSupportedConfigOptionId({
1721
1731
  ...turn.record,
1722
1732
  acpx: turn.acpxState ?? void 0
1723
1733
  }, configId);
1724
1734
  const modelConfigId = advertisedModelState(turn.acpxState)?.configId;
1725
- const response = await turn.client.setSessionConfigOption(turn.activeSessionId, resolvedConfigId, value);
1735
+ const response = await turn.client.setSessionConfigOption(turn.activeSessionId, resolvedConfigId, value, authority);
1726
1736
  turn.acpxState = applyConfigOptionSelection(turn.acpxState, resolvedConfigId, value, response, modelConfigId);
1727
1737
  return {
1728
1738
  configId: resolvedConfigId,
@@ -1879,49 +1889,52 @@ var AcpRuntimeManager = class {
1879
1889
  if (owner) await this.flushSessionOwner(owner);
1880
1890
  return runtimeStatusFromRecord(await this.requireRecord(recordId));
1881
1891
  }
1882
- async setMode(handle, mode, sessionMode = "persistent") {
1892
+ async setMode(handle, mode, sessionMode = "persistent", authority) {
1883
1893
  const recordId = handle.acpxRecordId ?? handle.sessionKey;
1884
- await this.withManagerLock(this.runtimeOperationLocks, recordId, async () => this.setModeWithOwnership(handle, mode, sessionMode));
1894
+ await this.withManagerLock(this.runtimeOperationLocks, recordId, async () => this.setModeWithOwnership(handle, mode, sessionMode, authority), authority);
1885
1895
  }
1886
- async setModeWithOwnership(handle, mode, sessionMode) {
1896
+ async setModeWithOwnership(handle, mode, sessionMode, authority) {
1887
1897
  const record = await this.requireRecord(handle.acpxRecordId ?? handle.sessionKey);
1898
+ assertControlAuthority(authority);
1888
1899
  const controller = this.activeControllers.get(record.acpxRecordId);
1889
1900
  let targetRecord = record;
1890
- if (controller) await controller.setSessionMode(mode);
1901
+ if (controller) await controller.setSessionMode(mode, authority);
1891
1902
  else targetRecord = (await this.withRuntimeControlSession(record, sessionMode, async ({ client, sessionId }) => {
1892
- await client.setSessionMode(sessionId, mode);
1893
- })).record;
1903
+ await client.setSessionMode(sessionId, mode, authority);
1904
+ }, void 0, authority)).record;
1894
1905
  setDesiredModeId(targetRecord, mode);
1895
1906
  await this.options.sessionStore.save(targetRecord);
1896
1907
  }
1897
- async setModel(handle, model, sessionMode = "persistent") {
1908
+ async setModel(handle, model, sessionMode = "persistent", authority) {
1898
1909
  const recordId = handle.acpxRecordId ?? handle.sessionKey;
1899
- await this.withManagerLock(this.runtimeOperationLocks, recordId, async () => this.setModelWithOwnership(handle, model, sessionMode));
1910
+ await this.withManagerLock(this.runtimeOperationLocks, recordId, async () => this.setModelWithOwnership(handle, model, sessionMode, authority), authority);
1900
1911
  }
1901
- async setModelWithOwnership(handle, model, sessionMode) {
1912
+ async setModelWithOwnership(handle, model, sessionMode, authority) {
1902
1913
  const record = await this.requireRecord(handle.acpxRecordId ?? handle.sessionKey);
1914
+ assertControlAuthority(authority);
1903
1915
  const controller = this.activeControllers.get(record.acpxRecordId);
1904
1916
  if (controller) {
1905
- const response = await controller.setSessionModel(model);
1917
+ const response = await controller.setSessionModel(model, authority);
1906
1918
  record.acpx = applyModelSelection(record.acpx, model, response);
1907
1919
  await this.options.sessionStore.save(record);
1908
1920
  return;
1909
1921
  }
1910
1922
  const result = await this.withRuntimeControlSession(record, sessionMode, async ({ client, sessionId, record: connectedRecord }) => {
1911
- const response = await client.setSessionModel(sessionId, model, advertisedModelState(connectedRecord.acpx));
1923
+ const response = await client.setSessionModel(sessionId, model, advertisedModelState(connectedRecord.acpx), authority);
1912
1924
  connectedRecord.acpx = applyModelSelection(connectedRecord.acpx, model, response);
1913
- }, { key: "model" });
1925
+ }, { key: "model" }, authority);
1914
1926
  await this.options.sessionStore.save(result.record);
1915
1927
  }
1916
- async setConfigOption(handle, key, value, sessionMode = "persistent") {
1928
+ async setConfigOption(handle, key, value, sessionMode = "persistent", authority) {
1917
1929
  const recordId = handle.acpxRecordId ?? handle.sessionKey;
1918
- return await this.withManagerLock(this.runtimeOperationLocks, recordId, async () => this.setConfigOptionWithOwnership(handle, key, value, sessionMode));
1930
+ return await this.withManagerLock(this.runtimeOperationLocks, recordId, async () => this.setConfigOptionWithOwnership(handle, key, value, sessionMode, authority), authority);
1919
1931
  }
1920
- async setConfigOptionWithOwnership(handle, key, value, sessionMode) {
1932
+ async setConfigOptionWithOwnership(handle, key, value, sessionMode, authority) {
1921
1933
  const record = await this.requireRecord(handle.acpxRecordId ?? handle.sessionKey);
1934
+ assertControlAuthority(authority);
1922
1935
  const controller = this.activeControllers.get(record.acpxRecordId);
1923
1936
  if (controller) {
1924
- const { configId, response } = await controller.setResolvedSessionConfigOption(key, value);
1937
+ const { configId, response } = await controller.setResolvedSessionConfigOption(key, value, authority);
1925
1938
  record.acpx = applyConfigOptionSelection(record.acpx, configId, value, response);
1926
1939
  await this.options.sessionStore.save(record);
1927
1940
  return response;
@@ -1929,13 +1942,13 @@ var AcpRuntimeManager = class {
1929
1942
  const result = await this.withRuntimeControlSession(record, sessionMode, async ({ client, sessionId, record: connectedRecord }) => {
1930
1943
  const configId = resolveSupportedConfigOptionId(connectedRecord, key);
1931
1944
  const modelConfigId = advertisedModelState(connectedRecord.acpx)?.configId;
1932
- const response = await client.setSessionConfigOption(sessionId, configId, value);
1945
+ const response = await client.setSessionConfigOption(sessionId, configId, value, authority);
1933
1946
  connectedRecord.acpx = applyConfigOptionSelection(connectedRecord.acpx, configId, value, response, modelConfigId);
1934
1947
  return response;
1935
1948
  }, {
1936
1949
  key,
1937
1950
  resolve: (connectedRecord) => resolveSupportedConfigOptionId(connectedRecord, key)
1938
- });
1951
+ }, authority);
1939
1952
  await this.options.sessionStore.save(result.record);
1940
1953
  return result.value;
1941
1954
  }
@@ -2125,6 +2138,232 @@ function writeHandleState(handle, state) {
2125
2138
  handle.agentSessionId = state.agentSessionId;
2126
2139
  }
2127
2140
  //#endregion
2141
+ //#region src/runtime/shared.ts
2142
+ const SHARED_BACKEND = "acpx-shared";
2143
+ function invalidOption(message) {
2144
+ throw new AcpRuntimeError("ACP_INVALID_RUNTIME_OPTION", message);
2145
+ }
2146
+ function sharedHandle(record) {
2147
+ return {
2148
+ backend: SHARED_BACKEND,
2149
+ sessionKey: record.name ?? "",
2150
+ runtimeSessionName: record.acpxRecordId,
2151
+ acpxRecordId: record.acpxRecordId,
2152
+ backendSessionId: record.acpSessionId,
2153
+ agentSessionId: record.agentSessionId,
2154
+ cwd: record.cwd
2155
+ };
2156
+ }
2157
+ function sharedRecordId(handle) {
2158
+ if (handle.backend !== SHARED_BACKEND || !handle.acpxRecordId) return invalidOption("A shared runtime requires a handle from a shared session.");
2159
+ return handle.acpxRecordId;
2160
+ }
2161
+ function turnFailure(error) {
2162
+ const normalized = normalizeOutputError(error, {
2163
+ defaultCode: "RUNTIME",
2164
+ origin: "queue"
2165
+ });
2166
+ if (normalized.detailCode === "QUEUE_REQUEST_CANCELLED") return {
2167
+ status: "cancelled",
2168
+ stopReason: "cancelled"
2169
+ };
2170
+ return {
2171
+ status: "failed",
2172
+ error: {
2173
+ message: normalized.message,
2174
+ code: normalized.code,
2175
+ detailCode: normalized.detailCode,
2176
+ retryable: normalized.retryable
2177
+ }
2178
+ };
2179
+ }
2180
+ /** A client of the CLI's local session owner. Shutdown detaches this client. */
2181
+ var SharedAcpRuntime = class {
2182
+ registry;
2183
+ options;
2184
+ disconnect = new AbortController();
2185
+ pending = /* @__PURE__ */ new Set();
2186
+ constructor(options) {
2187
+ for (const name of [
2188
+ "sessionStore",
2189
+ "agentProcessEnv",
2190
+ "mcpServers",
2191
+ "processLifecycle",
2192
+ "onPermissionRequest",
2193
+ "elicitationModes"
2194
+ ]) if (Object.hasOwn(options, name)) invalidOption(`${name} belongs to the in-process runtime and is not supported by shared sessions.`);
2195
+ this.options = {
2196
+ ...options,
2197
+ cwd: path.resolve(options.cwd),
2198
+ authCredentials: options.authCredentials ? { ...options.authCredentials } : void 0
2199
+ };
2200
+ this.registry = options.agentRegistry ?? createAgentRegistry();
2201
+ }
2202
+ assertOpen() {
2203
+ if (this.disconnect.signal.aborted) throw new AcpRuntimeError("ACP_BACKEND_UNAVAILABLE", "Shared ACP runtime is shut down.");
2204
+ }
2205
+ track(task) {
2206
+ this.pending.add(task);
2207
+ task.then(() => this.pending.delete(task), () => this.pending.delete(task));
2208
+ return task;
2209
+ }
2210
+ sessionOptions(input) {
2211
+ if (!input.agent.trim()) invalidOption("ACP agent id is required.");
2212
+ return {
2213
+ ...normalizeAgentCommandInput(this.registry.resolve(input.agent)),
2214
+ cwd: path.resolve(input.cwd ?? this.options.cwd),
2215
+ name: input.sessionKey.trim() || void 0
2216
+ };
2217
+ }
2218
+ async findSession(input) {
2219
+ this.assertOpen();
2220
+ const record = await findSession(this.sessionOptions(input));
2221
+ return record ? sharedHandle(record) : void 0;
2222
+ }
2223
+ ensureSession(input) {
2224
+ this.assertOpen();
2225
+ if (input.mode !== "persistent") invalidOption("Shared sessions require persistent mode; use the in-process runtime for oneshot sessions.");
2226
+ const session = this.sessionOptions(input);
2227
+ return this.track(ensureSession({
2228
+ ...this.options,
2229
+ ...session,
2230
+ walkBoundary: session.cwd,
2231
+ sessionOptions: input.sessionOptions,
2232
+ resumeSessionId: input.resumeSessionId,
2233
+ handleProcessInterrupts: false,
2234
+ signal: this.disconnect.signal
2235
+ }).then(({ record }) => {
2236
+ this.assertOpen();
2237
+ return sharedHandle(record);
2238
+ }));
2239
+ }
2240
+ startTurn(input) {
2241
+ this.assertOpen();
2242
+ if (input.mode !== "prompt" || input.onPermissionRequest || input.onElicitation) invalidOption("Shared turns support prompt mode and the client's static permission policy; in-process callbacks and steering are unsupported.");
2243
+ if (!input.requestId.trim()) invalidOption("A shared turn requires a requestId.");
2244
+ const sessionId = sharedRecordId(input.handle);
2245
+ const prompt = toPromptInput(input.text, input.attachments);
2246
+ const events = new AsyncEventQueue();
2247
+ const promptStarted = createDeferred();
2248
+ promptStarted.promise.catch(() => {});
2249
+ let accepted = false;
2250
+ let settled = false;
2251
+ let cancelRequested = input.signal?.aborted === true;
2252
+ let cancellation;
2253
+ const cancel = async () => {
2254
+ cancelRequested = true;
2255
+ if (!accepted || settled) return;
2256
+ cancellation ??= tryCancelOnRunningOwner({
2257
+ sessionId,
2258
+ targetRequestId: input.requestId
2259
+ }).then(() => {});
2260
+ await cancellation;
2261
+ };
2262
+ const onAbort = () => {
2263
+ cancel().catch(() => {});
2264
+ };
2265
+ input.signal?.addEventListener("abort", onAbort, { once: true });
2266
+ const run = async () => {
2267
+ if (cancelRequested) return {
2268
+ status: "cancelled",
2269
+ stopReason: "cancelled"
2270
+ };
2271
+ if ((await resolveSessionRecord(sessionId)).closed) throw new AcpRuntimeError("ACP_SESSION_INIT_FAILED", "Shared session is closed; ensure it again before submitting a turn.");
2272
+ if (cancelRequested) return {
2273
+ status: "cancelled",
2274
+ stopReason: "cancelled"
2275
+ };
2276
+ const result = await sendSession({
2277
+ ...this.options,
2278
+ sessionId,
2279
+ requestId: input.requestId,
2280
+ prompt: typeof prompt === "string" ? textPrompt(prompt) : prompt,
2281
+ resumePolicy: "same-session-only",
2282
+ requireSharedRuntime: true,
2283
+ signal: this.disconnect.signal,
2284
+ timeoutMs: input.timeoutMs ?? this.options.timeoutMs,
2285
+ queueOwnerArgs: [fileURLToPath(import.meta.resolve("acpx/dist/cli.js")), "__queue-owner"],
2286
+ onQueueAccepted: () => {
2287
+ accepted = true;
2288
+ if (cancelRequested) cancel().catch(() => {});
2289
+ },
2290
+ onPromptStarted: () => promptStarted.resolve(),
2291
+ outputFormatter: {
2292
+ ...DISCARD_OUTPUT_FORMATTER,
2293
+ onAcpMessage: (message) => {
2294
+ const event = parsePromptEventLine(JSON.stringify(message));
2295
+ if (event) events.push(event);
2296
+ }
2297
+ },
2298
+ errorEmissionPolicy: { queueErrorAlreadyEmitted: false },
2299
+ waitForCompletion: true
2300
+ });
2301
+ if ("queued" in result) throw new AcpRuntimeError("ACP_TURN_FAILED", "Shared turn ended without a completion result.");
2302
+ return {
2303
+ status: result.stopReason === "cancelled" ? "cancelled" : "completed",
2304
+ stopReason: result.stopReason,
2305
+ _meta: result._meta
2306
+ };
2307
+ };
2308
+ const result = this.track(run().catch(turnFailure).finally(() => {
2309
+ settled = true;
2310
+ promptStarted.reject(new AcpRuntimeError("ACP_TURN_FAILED", "Turn settled before its prompt was written."));
2311
+ input.signal?.removeEventListener("abort", onAbort);
2312
+ events.close();
2313
+ }));
2314
+ return {
2315
+ requestId: input.requestId,
2316
+ promptStarted: promptStarted.promise,
2317
+ events: events.iterate(),
2318
+ result,
2319
+ cancel,
2320
+ closeStream: async () => {
2321
+ events.clear();
2322
+ events.close();
2323
+ }
2324
+ };
2325
+ }
2326
+ async *runTurn(input) {
2327
+ const turn = this.startTurn(input);
2328
+ yield* turn.events;
2329
+ yield legacyTerminalEventFromTurnResult(await turn.result);
2330
+ }
2331
+ async getStatus(input) {
2332
+ this.assertOpen();
2333
+ return runtimeStatusFromRecord(await resolveSessionRecord(sharedRecordId(input.handle)));
2334
+ }
2335
+ watchSession(input) {
2336
+ this.assertOpen();
2337
+ const signal = input.signal ? AbortSignal.any([input.signal, this.disconnect.signal]) : this.disconnect.signal;
2338
+ const recordId = sharedRecordId(input.handle);
2339
+ const record = readSessionRecord(recordId).then((value) => {
2340
+ if (!value || value.acpxRecordId !== recordId) throw new AcpRuntimeError("ACP_SESSION_INIT_FAILED", "Shared session record is unavailable.");
2341
+ return value;
2342
+ });
2343
+ record.catch(() => {});
2344
+ return watchSession({
2345
+ record,
2346
+ cursor: input.cursor,
2347
+ signal
2348
+ });
2349
+ }
2350
+ async cancel(input) {
2351
+ this.assertOpen();
2352
+ await this.track(cancelSessionPrompt({ sessionId: sharedRecordId(input.handle) }));
2353
+ }
2354
+ async close(input) {
2355
+ this.assertOpen();
2356
+ await this.track(closeSession(sharedRecordId(input.handle)));
2357
+ }
2358
+ async shutdown() {
2359
+ this.disconnect.abort(new AcpRuntimeError("ACP_BACKEND_UNAVAILABLE", "Shared client detached; submitted work may still be running."));
2360
+ await Promise.allSettled(this.pending);
2361
+ }
2362
+ };
2363
+ function createSharedAcpRuntime(options) {
2364
+ return new SharedAcpRuntime(options);
2365
+ }
2366
+ //#endregion
2128
2367
  //#region src/runtime.ts
2129
2368
  const ACPX_BACKEND_ID = "acpx";
2130
2369
  const ACPX_CAPABILITIES = { controls: [
@@ -2286,15 +2525,15 @@ var AcpxRuntime = class {
2286
2525
  }
2287
2526
  async setMode(input) {
2288
2527
  const { handle, state } = this.resolveManagerHandle(input.handle);
2289
- await (await this.getManager()).setMode(handle, input.mode, state.mode);
2528
+ await (await this.getManager()).setMode(handle, input.mode, state.mode, input);
2290
2529
  }
2291
2530
  async setModel(input) {
2292
2531
  const { handle, state } = this.resolveManagerHandle(input.handle);
2293
- await (await this.getManager()).setModel(handle, input.model, state.mode);
2532
+ await (await this.getManager()).setModel(handle, input.model, state.mode, input);
2294
2533
  }
2295
2534
  async setConfigOption(input) {
2296
2535
  const { handle, state } = this.resolveManagerHandle(input.handle);
2297
- return await (await this.getManager()).setConfigOption(handle, input.key, input.value, state.mode);
2536
+ return await (await this.getManager()).setConfigOption(handle, input.key, input.value, state.mode, input);
2298
2537
  }
2299
2538
  async cancel(input) {
2300
2539
  const { handle } = this.resolveManagerHandle(input.handle);
@@ -2377,6 +2616,6 @@ function createRuntimeStore(options) {
2377
2616
  return createFileSessionStore(options);
2378
2617
  }
2379
2618
  //#endregion
2380
- export { ACPX_BACKEND_ID, AcpRuntimeError, AcpxRuntime, DEFAULT_AGENT_NAME, REQUESTED_MODEL_UNSUPPORTED_ERROR_CODE, REQUESTED_MODEL_UNSUPPORTED_REASONS, RequestedModelUnsupportedError, createAcpRuntime, createAgentRegistry, createFileSessionStore, createRuntimeStore, decodeAcpxRuntimeHandleState, encodeAcpxRuntimeHandleState, isAcpRuntimeError, isRequestedModelUnsupportedError };
2619
+ export { ACPX_BACKEND_ID, AcpRuntimeError, AcpxRuntime, DEFAULT_AGENT_NAME, REQUESTED_MODEL_UNSUPPORTED_ERROR_CODE, REQUESTED_MODEL_UNSUPPORTED_REASONS, RequestedModelUnsupportedError, SharedAcpRuntime, createAcpRuntime, createAgentRegistry, createFileSessionStore, createRuntimeStore, createSharedAcpRuntime, decodeAcpxRuntimeHandleState, encodeAcpxRuntimeHandleState, isAcpRuntimeError, isRequestedModelUnsupportedError };
2381
2620
 
2382
2621
  //# sourceMappingURL=runtime.js.map