@moxt-ai/mobius 0.0.10 → 0.0.11

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 (112) hide show
  1. package/dist/acp/session-history.d.ts.map +1 -1
  2. package/dist/acp/session-history.js +1 -0
  3. package/dist/acp/session-history.js.map +1 -1
  4. package/dist/acp/session-manager.d.ts +4 -1
  5. package/dist/acp/session-manager.d.ts.map +1 -1
  6. package/dist/acp/session-manager.js +99 -24
  7. package/dist/acp/session-manager.js.map +1 -1
  8. package/dist/agent-catalog/acp-readiness-probe.d.ts +4 -0
  9. package/dist/agent-catalog/acp-readiness-probe.d.ts.map +1 -0
  10. package/dist/agent-catalog/acp-readiness-probe.js +153 -0
  11. package/dist/agent-catalog/acp-readiness-probe.js.map +1 -0
  12. package/dist/agent-catalog/agent-diagnostics.d.ts +1 -1
  13. package/dist/agent-catalog/agent-diagnostics.d.ts.map +1 -1
  14. package/dist/agent-catalog/agent-diagnostics.js +1 -1
  15. package/dist/agent-catalog/agent-diagnostics.js.map +1 -1
  16. package/dist/agent-catalog/agent-discovery-context.d.ts +8 -0
  17. package/dist/agent-catalog/agent-discovery-context.d.ts.map +1 -0
  18. package/dist/agent-catalog/agent-discovery-context.js +2 -0
  19. package/dist/agent-catalog/agent-discovery-context.js.map +1 -0
  20. package/dist/agent-catalog/agent-discovery.d.ts +55 -0
  21. package/dist/agent-catalog/agent-discovery.d.ts.map +1 -0
  22. package/dist/agent-catalog/agent-discovery.js +89 -0
  23. package/dist/agent-catalog/agent-discovery.js.map +1 -0
  24. package/dist/agent-catalog/agent-probe-error.d.ts +5 -0
  25. package/dist/agent-catalog/agent-probe-error.d.ts.map +1 -0
  26. package/dist/agent-catalog/agent-probe-error.js +9 -0
  27. package/dist/agent-catalog/agent-probe-error.js.map +1 -0
  28. package/dist/agent-catalog/agent-specification.d.ts +45 -0
  29. package/dist/agent-catalog/agent-specification.d.ts.map +1 -0
  30. package/dist/agent-catalog/agent-specification.js +59 -0
  31. package/dist/agent-catalog/agent-specification.js.map +1 -0
  32. package/dist/agent-catalog/agents/claude-code-agent.d.ts +14 -0
  33. package/dist/agent-catalog/agents/claude-code-agent.d.ts.map +1 -0
  34. package/dist/agent-catalog/agents/claude-code-agent.js +30 -0
  35. package/dist/agent-catalog/agents/claude-code-agent.js.map +1 -0
  36. package/dist/agent-catalog/agents/codex-agent.d.ts +14 -0
  37. package/dist/agent-catalog/agents/codex-agent.d.ts.map +1 -0
  38. package/dist/agent-catalog/agents/codex-agent.js +23 -0
  39. package/dist/agent-catalog/agents/codex-agent.js.map +1 -0
  40. package/dist/agent-catalog/agents/deepseek-harness-agent.d.ts +16 -0
  41. package/dist/agent-catalog/agents/deepseek-harness-agent.d.ts.map +1 -0
  42. package/dist/agent-catalog/agents/deepseek-harness-agent.js +94 -0
  43. package/dist/agent-catalog/agents/deepseek-harness-agent.js.map +1 -0
  44. package/dist/agent-catalog/agents/opencode-agent.d.ts +17 -0
  45. package/dist/agent-catalog/agents/opencode-agent.d.ts.map +1 -0
  46. package/dist/agent-catalog/agents/opencode-agent.js +36 -0
  47. package/dist/agent-catalog/agents/opencode-agent.js.map +1 -0
  48. package/dist/agent-catalog/agents/pi-agent.d.ts +21 -0
  49. package/dist/agent-catalog/agents/pi-agent.d.ts.map +1 -0
  50. package/dist/agent-catalog/agents/pi-agent.js +69 -0
  51. package/dist/agent-catalog/agents/pi-agent.js.map +1 -0
  52. package/dist/agent-catalog/agents/supported-agent-specifications.d.ts +3 -0
  53. package/dist/agent-catalog/agents/supported-agent-specifications.d.ts.map +1 -0
  54. package/dist/agent-catalog/agents/supported-agent-specifications.js +15 -0
  55. package/dist/agent-catalog/agents/supported-agent-specifications.js.map +1 -0
  56. package/dist/agent-catalog/discover-agent.d.ts +5 -0
  57. package/dist/agent-catalog/discover-agent.d.ts.map +1 -0
  58. package/dist/agent-catalog/discover-agent.js +100 -0
  59. package/dist/agent-catalog/discover-agent.js.map +1 -0
  60. package/dist/agent-catalog/discover-local-agents.d.ts +12 -101
  61. package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
  62. package/dist/agent-catalog/discover-local-agents.js +11 -564
  63. package/dist/agent-catalog/discover-local-agents.js.map +1 -1
  64. package/dist/agent-catalog/executable-discovery.d.ts +16 -0
  65. package/dist/agent-catalog/executable-discovery.d.ts.map +1 -0
  66. package/dist/agent-catalog/executable-discovery.js +105 -0
  67. package/dist/agent-catalog/executable-discovery.js.map +1 -0
  68. package/dist/agent-installation/agent-installation-manager.d.ts +1 -1
  69. package/dist/agent-installation/agent-installation-manager.d.ts.map +1 -1
  70. package/dist/agent-installation/automatic-adapter-provisioner.d.ts +2 -1
  71. package/dist/agent-installation/automatic-adapter-provisioner.d.ts.map +1 -1
  72. package/dist/agent-installation/automatic-adapter-provisioner.js +11 -2
  73. package/dist/agent-installation/automatic-adapter-provisioner.js.map +1 -1
  74. package/dist/agent-installation/deepseek-managed-package.d.ts +9 -0
  75. package/dist/agent-installation/deepseek-managed-package.d.ts.map +1 -0
  76. package/dist/agent-installation/deepseek-managed-package.js +10 -0
  77. package/dist/agent-installation/deepseek-managed-package.js.map +1 -0
  78. package/dist/agent-installation/fixed-agent-install-recipes.d.ts +18 -0
  79. package/dist/agent-installation/fixed-agent-install-recipes.d.ts.map +1 -1
  80. package/dist/agent-installation/fixed-agent-install-recipes.js +97 -0
  81. package/dist/agent-installation/fixed-agent-install-recipes.js.map +1 -1
  82. package/dist/agent-installation/fixed-installation-executor.d.ts +1 -1
  83. package/dist/agent-installation/fixed-installation-executor.d.ts.map +1 -1
  84. package/dist/agent-installation/fixed-installation-executor.js +17 -3
  85. package/dist/agent-installation/fixed-installation-executor.js.map +1 -1
  86. package/dist/agent-installation/managed-adapter-installer.d.ts +4 -4
  87. package/dist/agent-installation/managed-adapter-installer.d.ts.map +1 -1
  88. package/dist/agent-installation/managed-adapter-installer.js.map +1 -1
  89. package/dist/agent-installation/managed-agent-archive.d.ts +40 -0
  90. package/dist/agent-installation/managed-agent-archive.d.ts.map +1 -0
  91. package/dist/agent-installation/managed-agent-archive.js +274 -0
  92. package/dist/agent-installation/managed-agent-archive.js.map +1 -0
  93. package/dist/agent-installation/managed-npm-package.d.ts +3 -0
  94. package/dist/agent-installation/managed-npm-package.d.ts.map +1 -1
  95. package/dist/agent-installation/managed-npm-package.js +55 -24
  96. package/dist/agent-installation/managed-npm-package.js.map +1 -1
  97. package/dist/agent-installation/opencode-managed-release.d.ts +4 -0
  98. package/dist/agent-installation/opencode-managed-release.d.ts.map +1 -0
  99. package/dist/agent-installation/opencode-managed-release.js +25 -0
  100. package/dist/agent-installation/opencode-managed-release.js.map +1 -0
  101. package/dist/cli.js +2316 -1298
  102. package/dist/cli.js.map +4 -4
  103. package/dist/index.js +1763 -743
  104. package/dist/index.js.map +4 -4
  105. package/dist/native-sessions/codex-history.d.ts.map +1 -1
  106. package/dist/native-sessions/codex-history.js +1 -0
  107. package/dist/native-sessions/codex-history.js.map +1 -1
  108. package/dist/process/executable.d.ts +6 -1
  109. package/dist/process/executable.d.ts.map +1 -1
  110. package/dist/process/executable.js +150 -7
  111. package/dist/process/executable.js.map +1 -1
  112. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -29,13 +29,18 @@ import { fileURLToPath } from "node:url";
29
29
  import { realpathSync, statSync } from "node:fs";
30
30
 
31
31
  // src/process/executable.ts
32
- import { spawn } from "node:child_process";
32
+ import { execFile, spawn } from "node:child_process";
33
33
  import { constants } from "node:fs";
34
34
  import { access, realpath, stat } from "node:fs/promises";
35
35
  import { join, resolve } from "node:path";
36
36
  var DEFAULT_OUTPUT_LIMIT_BYTES = 16 * 1024;
37
37
  var PROCESS_GRACEFUL_STOP_TIMEOUT_MILLISECONDS = 1e3;
38
38
  var PROCESS_FORCED_STOP_TIMEOUT_MILLISECONDS = 5e3;
39
+ var PROCESS_TABLE_TIMEOUT_MILLISECONDS = 1e3;
40
+ var PROCESS_TABLE_OUTPUT_LIMIT_BYTES = 1024 * 1024;
41
+ var PROCESS_EXIT_CHECK_ATTEMPTS = 8;
42
+ var GRACEFUL_STOP_SIGNAL = 15;
43
+ var FORCED_STOP_SIGNAL = 9;
39
44
  var ExecutableIdentity = class {
40
45
  changedAtMilliseconds;
41
46
  device;
@@ -154,6 +159,119 @@ function appendBounded(chunks, chunk, currentBytes, limitBytes) {
154
159
  chunks.push(chunk);
155
160
  return nextBytes;
156
161
  }
162
+ function parseProcessTable(output2) {
163
+ const entries = [];
164
+ for (const line of output2.split("\n")) {
165
+ const groups = /^\s*(?<pid>\d+)\s+(?<ppid>\d+)\s+(?<pgid>\d+)\s*$/.exec(
166
+ line
167
+ )?.groups;
168
+ if (groups === void 0) {
169
+ continue;
170
+ }
171
+ const processId = Number(groups["pid"]);
172
+ const parentProcessId = Number(groups["ppid"]);
173
+ const processGroupId = Number(groups["pgid"]);
174
+ if (!Number.isSafeInteger(processId) || processId <= 0 || !Number.isSafeInteger(parentProcessId) || parentProcessId < 0 || !Number.isSafeInteger(processGroupId) || processGroupId <= 0) {
175
+ continue;
176
+ }
177
+ entries.push({ parentProcessId, processGroupId, processId });
178
+ }
179
+ return entries;
180
+ }
181
+ function readProcessTable() {
182
+ if (process.platform === "win32") {
183
+ return Promise.resolve([]);
184
+ }
185
+ const executable = process.platform === "darwin" ? "/bin/ps" : "/usr/bin/ps";
186
+ return new Promise((resolveTable) => {
187
+ execFile(
188
+ executable,
189
+ ["-axo", "pid=,ppid=,pgid="],
190
+ {
191
+ encoding: "utf8",
192
+ maxBuffer: PROCESS_TABLE_OUTPUT_LIMIT_BYTES,
193
+ signal: AbortSignal.timeout(PROCESS_TABLE_TIMEOUT_MILLISECONDS),
194
+ timeout: PROCESS_TABLE_TIMEOUT_MILLISECONDS
195
+ },
196
+ (error61, stdout) => {
197
+ resolveTable(error61 === null ? parseProcessTable(stdout) : []);
198
+ }
199
+ );
200
+ });
201
+ }
202
+ function selectProcessTree(entries, rootProcessId) {
203
+ const processIds = /* @__PURE__ */ new Set([rootProcessId]);
204
+ let previousSize = 0;
205
+ while (previousSize !== processIds.size) {
206
+ previousSize = processIds.size;
207
+ for (const entry of entries) {
208
+ if (processIds.has(entry.parentProcessId)) {
209
+ processIds.add(entry.processId);
210
+ }
211
+ }
212
+ }
213
+ return entries.filter((entry) => processIds.has(entry.processId)).map((entry) => ({
214
+ processGroupId: entry.processGroupId,
215
+ processId: entry.processId
216
+ }));
217
+ }
218
+ function mergeProcessTrees(captured, current) {
219
+ const processes = /* @__PURE__ */ new Map();
220
+ for (const identity2 of captured) {
221
+ processes.set(identity2.processId, identity2);
222
+ }
223
+ for (const identity2 of current) {
224
+ processes.set(identity2.processId, identity2);
225
+ }
226
+ return [...processes.values()];
227
+ }
228
+ async function captureProcessTree(child) {
229
+ if (process.platform === "win32" || child.pid === void 0) {
230
+ return [];
231
+ }
232
+ return selectProcessTree(await readProcessTable(), child.pid);
233
+ }
234
+ function signalDetachedProcessGroups(processes, rootProcessId, signal) {
235
+ const processIds = new Set(processes.map((identity2) => identity2.processId));
236
+ const signalledGroups = /* @__PURE__ */ new Set();
237
+ for (const identity2 of processes) {
238
+ if (identity2.processGroupId === rootProcessId || !processIds.has(identity2.processGroupId) || signalledGroups.has(identity2.processGroupId)) {
239
+ continue;
240
+ }
241
+ try {
242
+ process.kill(-identity2.processGroupId, signal);
243
+ signalledGroups.add(identity2.processGroupId);
244
+ } catch {
245
+ }
246
+ }
247
+ for (const identity2 of processes) {
248
+ if (identity2.processId === rootProcessId || identity2.processGroupId === rootProcessId || signalledGroups.has(identity2.processGroupId)) {
249
+ continue;
250
+ }
251
+ try {
252
+ process.kill(identity2.processId, signal);
253
+ } catch {
254
+ }
255
+ }
256
+ }
257
+ function processExists(processId) {
258
+ try {
259
+ process.kill(processId, 0);
260
+ return true;
261
+ } catch {
262
+ return false;
263
+ }
264
+ }
265
+ async function waitForCapturedProcessesExit(processes, rootProcessId) {
266
+ const processIds = processes.map((identity2) => identity2.processId).filter((processId) => processId !== rootProcessId);
267
+ for (let attempt = 0; attempt < PROCESS_EXIT_CHECK_ATTEMPTS; attempt += 1) {
268
+ if (processIds.every((processId) => !processExists(processId))) {
269
+ return true;
270
+ }
271
+ await readProcessTable();
272
+ }
273
+ return processIds.every((processId) => !processExists(processId));
274
+ }
157
275
  function terminateProcess(child) {
158
276
  if (child.exitCode !== null || child.signalCode !== null || child.pid === void 0) {
159
277
  return;
@@ -180,24 +298,35 @@ function forceTerminateProcess(child) {
180
298
  }
181
299
  child.kill("SIGKILL");
182
300
  }
183
- async function stopProcessTree(child) {
184
- if (child.exitCode !== null || child.signalCode !== null) {
301
+ async function stopProcessTree(child, capturedProcesses = []) {
302
+ const childProcessId = child.pid;
303
+ if (childProcessId === void 0) {
185
304
  return;
186
305
  }
187
- terminateProcess(child);
188
- const exitedAfterTermination = await waitForProcessExit(
189
- child,
190
- PROCESS_GRACEFUL_STOP_TIMEOUT_MILLISECONDS
306
+ const childExited = child.exitCode !== null || child.signalCode !== null;
307
+ if (childExited && capturedProcesses.length === 0) {
308
+ return;
309
+ }
310
+ const processes = mergeProcessTrees(
311
+ capturedProcesses,
312
+ childExited ? [] : await captureProcessTree(child)
191
313
  );
192
- if (exitedAfterTermination) {
314
+ signalDetachedProcessGroups(processes, childProcessId, GRACEFUL_STOP_SIGNAL);
315
+ terminateProcess(child);
316
+ const [exitedAfterTermination, descendantsExitedAfterTermination] = await Promise.all([
317
+ waitForProcessExit(child, PROCESS_GRACEFUL_STOP_TIMEOUT_MILLISECONDS),
318
+ waitForCapturedProcessesExit(processes, childProcessId)
319
+ ]);
320
+ if (exitedAfterTermination && descendantsExitedAfterTermination) {
193
321
  return;
194
322
  }
323
+ signalDetachedProcessGroups(processes, childProcessId, FORCED_STOP_SIGNAL);
195
324
  forceTerminateProcess(child);
196
- const exitedAfterForce = await waitForProcessExit(
197
- child,
198
- PROCESS_FORCED_STOP_TIMEOUT_MILLISECONDS
199
- );
200
- if (!exitedAfterForce) {
325
+ const [exitedAfterForce, descendantsExitedAfterForce] = await Promise.all([
326
+ waitForProcessExit(child, PROCESS_FORCED_STOP_TIMEOUT_MILLISECONDS),
327
+ waitForCapturedProcessesExit(processes, childProcessId)
328
+ ]);
329
+ if (!exitedAfterForce || !descendantsExitedAfterForce) {
201
330
  throw new ProcessExecutionError(
202
331
  "process_termination_timeout",
203
332
  "The executable process could not be stopped"
@@ -532,7 +661,8 @@ import { spawn as spawn2 } from "node:child_process";
532
661
  import {
533
662
  methods as methods2,
534
663
  ndJsonStream,
535
- PROTOCOL_VERSION
664
+ PROTOCOL_VERSION,
665
+ RequestError
536
666
  } from "@agentclientprotocol/sdk";
537
667
 
538
668
  // ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/external.js
@@ -20307,7 +20437,10 @@ var sessionHistorySchema = external_exports.discriminatedUnion("status", [
20307
20437
  status: external_exports.literal("available"),
20308
20438
  messages: external_exports.array(historyMessage).max(SESSION_HISTORY_MESSAGE_LIMIT).readonly(),
20309
20439
  truncated: external_exports.boolean(),
20310
- coveredCommandIds: external_exports.array(external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/)).max(1e4).readonly()
20440
+ coveredCommandIds: external_exports.array(external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/)).max(1e4).readonly(),
20441
+ coveredMessageIds: external_exports.array(
20442
+ external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}:(?:user|agent)$/)
20443
+ ).max(2e4).readonly().default([])
20311
20444
  }).readonly(),
20312
20445
  external_exports.strictObject({ status: external_exports.literal("unavailable") }).readonly()
20313
20446
  ]).refine(
@@ -21546,7 +21679,8 @@ var AcpHistoryReplay = class {
21546
21679
  status: "available",
21547
21680
  messages: [...this.#messages],
21548
21681
  truncated: this.#truncated,
21549
- coveredCommandIds: []
21682
+ coveredCommandIds: [],
21683
+ coveredMessageIds: []
21550
21684
  });
21551
21685
  };
21552
21686
 
@@ -21762,6 +21896,8 @@ var SqliteAcpSessionStore = class {
21762
21896
 
21763
21897
  // src/acp/session-manager.ts
21764
21898
  var PROCESS_STOP_TIMEOUT_MILLISECONDS = 1e3;
21899
+ var MAX_PRE_SESSION_UPDATES = 100;
21900
+ var MAX_PRE_SESSION_UPDATE_BYTES = 1024 * 1024;
21765
21901
  var SESSION_CONTROL_COMMAND_ID = "session-control";
21766
21902
  var NullAcpSessionObserver = class {
21767
21903
  onCommands = () => Promise.resolve();
@@ -22370,8 +22506,11 @@ var AcpProcessSession = class _AcpProcessSession {
22370
22506
  #mobiusSessionId;
22371
22507
  #pendingElicitations = /* @__PURE__ */ new Map();
22372
22508
  #pendingPermissions = /* @__PURE__ */ new Map();
22509
+ #preSessionUpdates = [];
22373
22510
  #processExit;
22374
22511
  #store;
22512
+ #verifiedAgentVersion;
22513
+ #preSessionUpdateBytes = 0;
22375
22514
  #agentName = "";
22376
22515
  #agentVersion = "";
22377
22516
  #capabilities = {
@@ -22405,6 +22544,7 @@ var AcpProcessSession = class _AcpProcessSession {
22405
22544
  this.#getObserver = getObserver;
22406
22545
  this.#mobiusSessionId = mobiusSessionId;
22407
22546
  this.#store = store;
22547
+ this.#verifiedAgentVersion = agent.agentVersion;
22408
22548
  this.#child = spawn2(agent.adapterPath, [...agent.arguments], {
22409
22549
  cwd,
22410
22550
  detached: process.platform !== "win32",
@@ -22560,7 +22700,10 @@ var AcpProcessSession = class _AcpProcessSession {
22560
22700
  initialized.agentInfo?.title ?? initialized.agentInfo?.name ?? this.#agentId,
22561
22701
  255
22562
22702
  );
22563
- this.#agentVersion = truncate2(initialized.agentInfo?.version ?? "", 128);
22703
+ this.#agentVersion = truncate2(
22704
+ this.#verifiedAgentVersion.length > 0 ? this.#verifiedAgentVersion : initialized.agentInfo?.version ?? "",
22705
+ 128
22706
+ );
22564
22707
  }
22565
22708
  initialize = async (signal, origin) => {
22566
22709
  await this.#initializeAgent(signal);
@@ -22606,7 +22749,7 @@ var AcpProcessSession = class _AcpProcessSession {
22606
22749
  "ACP agent exited while forking a session",
22607
22750
  signal
22608
22751
  );
22609
- this.#nativeSessionId = nativeSessionIdSchema.parse(forked.sessionId);
22752
+ this.selectNativeSession(forked.sessionId);
22610
22753
  if (this.#nativeSessionId === origin.nativeSessionId || this.#store.findNative(this.#agentId, this.#nativeSessionId).length > 0) {
22611
22754
  throw new AcpExecutionError(
22612
22755
  "The Agent did not create an independent fork",
@@ -22621,7 +22764,7 @@ var AcpProcessSession = class _AcpProcessSession {
22621
22764
  stored.session.additionalDirectories,
22622
22765
  this.#additionalDirectories
22623
22766
  )) {
22624
- this.#nativeSessionId = stored.session.nativeSessionId;
22767
+ this.selectNativeSession(stored.session.nativeSessionId);
22625
22768
  this.#prompted = stored.session.prompted;
22626
22769
  this.#restored = true;
22627
22770
  if (this.#capabilities.resumeSession) {
@@ -22691,7 +22834,7 @@ var AcpProcessSession = class _AcpProcessSession {
22691
22834
  "ACP agent exited while starting a session",
22692
22835
  signal
22693
22836
  );
22694
- this.#nativeSessionId = created.sessionId;
22837
+ this.selectNativeSession(created.sessionId);
22695
22838
  lifecycleResponse = created;
22696
22839
  }
22697
22840
  const lifecycleRecord = isRecord3(lifecycleResponse) ? lifecycleResponse : {};
@@ -22953,13 +23096,17 @@ var AcpProcessSession = class _AcpProcessSession {
22953
23096
  }
22954
23097
  };
22955
23098
  cancel = async () => {
22956
- await this.cancelPendingInteractions();
22957
- if (!this.#turn.running) {
22958
- return;
23099
+ const capturedProcesses = await captureProcessTree(this.#child);
23100
+ try {
23101
+ await this.cancelPendingInteractions();
23102
+ if (this.#turn.running) {
23103
+ await this.#connection.agent.notify(methods2.agent.session.cancel, {
23104
+ sessionId: this.#nativeSessionId
23105
+ });
23106
+ }
23107
+ } finally {
23108
+ await this.closeProcess(capturedProcesses);
22959
23109
  }
22960
- await this.#connection.agent.notify(methods2.agent.session.cancel, {
22961
- sessionId: this.#nativeSessionId
22962
- });
22963
23110
  };
22964
23111
  respondPermission = async (options) => {
22965
23112
  const pending = this.#pendingPermissions.get(options.interactionId);
@@ -23146,11 +23293,45 @@ var AcpProcessSession = class _AcpProcessSession {
23146
23293
  });
23147
23294
  };
23148
23295
  onUpdate = (notification) => {
23296
+ if (this.#nativeSessionId.length === 0) {
23297
+ const notificationBytes = Buffer.byteLength(JSON.stringify(notification));
23298
+ if (this.#preSessionUpdates.length >= MAX_PRE_SESSION_UPDATES || this.#preSessionUpdateBytes + notificationBytes > MAX_PRE_SESSION_UPDATE_BYTES) {
23299
+ return Promise.reject(
23300
+ new AcpExecutionError(
23301
+ "ACP agent sent too many updates before creating its session",
23302
+ {},
23303
+ "agent_update_limit"
23304
+ )
23305
+ );
23306
+ }
23307
+ this.#preSessionUpdates.push(notification);
23308
+ this.#preSessionUpdateBytes += notificationBytes;
23309
+ return Promise.resolve();
23310
+ }
23311
+ return this.enqueueUpdate(notification);
23312
+ };
23313
+ enqueueUpdate = (notification) => {
23149
23314
  this.#updateTail = this.#updateTail.then(
23150
23315
  async () => await this.processUpdate(notification)
23151
23316
  );
23152
23317
  return this.#updateTail;
23153
23318
  };
23319
+ selectNativeSession = (sessionId) => {
23320
+ const selected = nativeSessionIdSchema.parse(sessionId);
23321
+ if (this.#nativeSessionId.length > 0 && this.#nativeSessionId !== selected) {
23322
+ throw new AcpExecutionError(
23323
+ "ACP agent attempted to replace the selected session",
23324
+ {},
23325
+ "invalid_agent_session"
23326
+ );
23327
+ }
23328
+ this.#nativeSessionId = selected;
23329
+ const pending = this.#preSessionUpdates.splice(0);
23330
+ this.#preSessionUpdateBytes = 0;
23331
+ for (const notification of pending) {
23332
+ void this.enqueueUpdate(notification);
23333
+ }
23334
+ };
23154
23335
  processUpdate = async (notification) => {
23155
23336
  this.assertNativeSession(notification.sessionId);
23156
23337
  const update = notification.update;
@@ -23288,9 +23469,12 @@ var AcpProcessSession = class _AcpProcessSession {
23288
23469
  }
23289
23470
  await this.closeProcess();
23290
23471
  };
23291
- closeProcess = async () => {
23292
- this.#connection.close();
23293
- await stopProcessTree(this.#child);
23472
+ closeProcess = async (capturedProcesses = []) => {
23473
+ try {
23474
+ await stopProcessTree(this.#child, capturedProcesses);
23475
+ } finally {
23476
+ this.#connection.close();
23477
+ }
23294
23478
  };
23295
23479
  race = async (operation, exitMessage, signal) => {
23296
23480
  signal.throwIfAborted();
@@ -23306,13 +23490,25 @@ var AcpProcessSession = class _AcpProcessSession {
23306
23490
  };
23307
23491
  });
23308
23492
  try {
23309
- return await Promise.race([
23310
- operation,
23311
- this.#processExit.then(() => {
23312
- throw new AcpExecutionError(exitMessage);
23313
- }),
23314
- aborted2
23315
- ]);
23493
+ try {
23494
+ return await Promise.race([
23495
+ operation,
23496
+ this.#processExit.then(() => {
23497
+ throw new AcpExecutionError(exitMessage);
23498
+ }),
23499
+ aborted2
23500
+ ]);
23501
+ } catch (error61) {
23502
+ signal.throwIfAborted();
23503
+ if (error61 instanceof RequestError && error61.code === -32e3) {
23504
+ throw new AcpExecutionError(
23505
+ "Agent authentication is required",
23506
+ { cause: error61 },
23507
+ "authentication_required"
23508
+ );
23509
+ }
23510
+ throw error61;
23511
+ }
23316
23512
  } finally {
23317
23513
  removeAbortListener();
23318
23514
  }
@@ -23571,7 +23767,13 @@ var AcpSessionManager = class {
23571
23767
  this.#cancellationRequests.add(sessionId);
23572
23768
  const runtime = this.#sessions.get(sessionId);
23573
23769
  if (runtime !== void 0) {
23574
- await runtime.cancel();
23770
+ try {
23771
+ await runtime.cancel();
23772
+ } finally {
23773
+ if (this.#sessions.get(sessionId) === runtime) {
23774
+ this.#sessions.delete(sessionId);
23775
+ }
23776
+ }
23575
23777
  }
23576
23778
  };
23577
23779
  runPrompt = async (options) => {
@@ -23624,7 +23826,19 @@ var AcpSessionManager = class {
23624
23826
  if (this.#cancellationRequests.has(options.sessionId)) {
23625
23827
  return { stopReason: "cancelled" };
23626
23828
  }
23627
- return await runtime.prompt(boundedOptions);
23829
+ try {
23830
+ const result = await runtime.prompt(boundedOptions);
23831
+ return this.#cancellationRequests.has(options.sessionId) ? { stopReason: "cancelled" } : result;
23832
+ } catch (error61) {
23833
+ if (this.#cancellationRequests.has(options.sessionId)) {
23834
+ if (this.#sessions.get(options.sessionId) === runtime) {
23835
+ this.#sessions.delete(options.sessionId);
23836
+ }
23837
+ await runtime.closeProcess();
23838
+ return { stopReason: "cancelled" };
23839
+ }
23840
+ throw error61;
23841
+ }
23628
23842
  } catch (error61) {
23629
23843
  const failedRuntime = this.#sessions.get(options.sessionId);
23630
23844
  if (failedRuntime !== void 0) {
@@ -23932,26 +24146,16 @@ var LocalAuthorizationError = class extends Error {
23932
24146
  // src/pairing/pair-local-machine.ts
23933
24147
  import { randomUUID } from "node:crypto";
23934
24148
  import {
23935
- mkdir as mkdir2,
23936
- open as open4,
23937
- realpath as realpath3,
23938
- rename as rename2,
23939
- stat as stat3,
23940
- writeFile
24149
+ mkdir as mkdir3,
24150
+ open as open6,
24151
+ realpath as realpath5,
24152
+ rename as rename3,
24153
+ stat as stat5,
24154
+ writeFile as writeFile2
23941
24155
  } from "node:fs/promises";
23942
24156
  import { hostname as hostname3 } from "node:os";
23943
- import { basename, join as join8, resolve as resolve3 } from "node:path";
23944
- import { fetch } from "undici";
23945
-
23946
- // src/agent-catalog/discover-local-agents.ts
23947
- import { spawn as spawn3 } from "node:child_process";
23948
- import { isAbsolute as isAbsolute2, join as join7 } from "node:path";
23949
- import {
23950
- methods as methods3,
23951
- ndJsonStream as ndJsonStream2,
23952
- PROTOCOL_VERSION as PROTOCOL_VERSION2,
23953
- RequestError
23954
- } from "@agentclientprotocol/sdk";
24157
+ import { basename, join as join13, resolve as resolve3 } from "node:path";
24158
+ import { fetch as fetch2 } from "undici";
23955
24159
 
23956
24160
  // src/agent-installation/installation-grants.ts
23957
24161
  import { open as open2 } from "node:fs/promises";
@@ -23995,8 +24199,102 @@ async function readGrantedAgents(stateDirectory) {
23995
24199
  }
23996
24200
  }
23997
24201
 
23998
- // src/agent-installation/managed-adapter-installer.ts
23999
- import { join as join6 } from "node:path";
24202
+ // src/agent-catalog/agent-discovery.ts
24203
+ var AgentDiscovery = class {
24204
+ specification;
24205
+ constructor(specification) {
24206
+ this.specification = specification;
24207
+ }
24208
+ };
24209
+ var AvailableAgent = class extends AgentDiscovery {
24210
+ agent;
24211
+ status = "ready";
24212
+ constructor(specification, agent) {
24213
+ super(specification);
24214
+ this.agent = agent;
24215
+ }
24216
+ };
24217
+ var UnavailableAgent = class extends AgentDiscovery {
24218
+ };
24219
+ var MissingAdapter = class extends UnavailableAgent {
24220
+ code = "adapter_not_found";
24221
+ message = "ACP adapter not found";
24222
+ status = "missing_adapter";
24223
+ constructor(specification) {
24224
+ super(specification);
24225
+ }
24226
+ };
24227
+ var MissingAgent = class extends UnavailableAgent {
24228
+ code = "agent_not_found";
24229
+ message = "Agent executable not found";
24230
+ status = "missing_agent";
24231
+ constructor(specification) {
24232
+ super(specification);
24233
+ }
24234
+ };
24235
+ var ProbeFailed = class extends UnavailableAgent {
24236
+ code;
24237
+ message;
24238
+ status = "probe_failed";
24239
+ constructor(specification, code, message) {
24240
+ super(specification);
24241
+ this.code = code;
24242
+ this.message = message;
24243
+ }
24244
+ };
24245
+ var IncompatibleAdapter = class extends UnavailableAgent {
24246
+ code = "acp_incompatible";
24247
+ message = "ACP adapter is incompatible";
24248
+ status = "incompatible_adapter";
24249
+ constructor(specification) {
24250
+ super(specification);
24251
+ }
24252
+ };
24253
+ var AuthenticationRequiredAgent = class extends UnavailableAgent {
24254
+ code = "authentication_required";
24255
+ message = "Agent authentication is required";
24256
+ status = "authentication_required";
24257
+ constructor(specification) {
24258
+ super(specification);
24259
+ }
24260
+ };
24261
+ var LocalAgentInventory = class {
24262
+ available;
24263
+ discoveries;
24264
+ installable;
24265
+ unavailable;
24266
+ constructor(discoveries, grantedAgents = /* @__PURE__ */ new Set(), platform = process.platform, architecture = process.arch) {
24267
+ const available = [];
24268
+ const unavailable = [];
24269
+ for (const discovery of discoveries) {
24270
+ if (discovery instanceof AvailableAgent) {
24271
+ available.push(discovery);
24272
+ } else if (discovery instanceof UnavailableAgent) {
24273
+ unavailable.push(discovery);
24274
+ } else {
24275
+ throw new Error("Unsupported Agent discovery outcome");
24276
+ }
24277
+ }
24278
+ this.available = Object.freeze(available);
24279
+ this.discoveries = Object.freeze([...discoveries]);
24280
+ this.installable = Object.freeze(
24281
+ unavailable.filter(
24282
+ (discovery) => !(discovery instanceof AuthenticationRequiredAgent) && discovery.specification.supportsInstallation(
24283
+ platform,
24284
+ architecture
24285
+ )
24286
+ ).map(
24287
+ (discovery) => new InstallableAgentDefinition(
24288
+ discovery.specification.id,
24289
+ discovery.specification.label,
24290
+ !grantedAgents.has(discovery.specification.id)
24291
+ )
24292
+ )
24293
+ );
24294
+ this.unavailable = Object.freeze(unavailable);
24295
+ }
24296
+ readyAgents = () => this.available.map((discovery) => discovery.agent);
24297
+ };
24000
24298
 
24001
24299
  // src/agent-installation/managed-npm-package.ts
24002
24300
  import {
@@ -24013,9 +24311,12 @@ var INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
24013
24311
  var PACKAGE_METADATA_LIMIT_BYTES = 64 * 1024;
24014
24312
  var PACKAGE_LOCK_LIMIT_BYTES = 8 * 1024 * 1024;
24015
24313
  var ManagedNpmPackageDefinition = class {
24314
+ dependencyResolutionArguments = Object.freeze([]);
24016
24315
  executableName;
24316
+ includeOptionalDependencies = false;
24017
24317
  packageName;
24018
24318
  version;
24319
+ verifyDependencyClosure = false;
24019
24320
  constructor(packageName, version2, executableName) {
24020
24321
  this.executableName = executableName;
24021
24322
  this.packageName = packageName;
@@ -24116,6 +24417,27 @@ function verifyPackageLock(lock, definition) {
24116
24417
  let matches = 0;
24117
24418
  for (const [key, candidate] of Object.entries(packages)) {
24118
24419
  const normalizedKey = key.replaceAll("\\", "/");
24420
+ if (definition.verifyDependencyClosure && normalizedKey.length > 0) {
24421
+ let resolved;
24422
+ try {
24423
+ if (!normalizedKey.split("/").includes("node_modules") || !isRecord5(candidate) || typeof candidate["version"] !== "string" || candidate["version"].length === 0 || typeof candidate["integrity"] !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(candidate["integrity"]) || typeof candidate["resolved"] !== "string") {
24424
+ throw new Error("Invalid locked dependency");
24425
+ }
24426
+ resolved = new URL(candidate["resolved"]);
24427
+ } catch (error61) {
24428
+ throw new ManagedNpmPackageError(
24429
+ "managed_package_verification_failed",
24430
+ "The managed npm dependency closure is invalid",
24431
+ { cause: error61 }
24432
+ );
24433
+ }
24434
+ if (resolved.protocol !== "https:" || resolved.hostname !== "registry.npmjs.org" || resolved.port.length > 0 || resolved.username.length > 0 || resolved.password.length > 0) {
24435
+ throw new ManagedNpmPackageError(
24436
+ "managed_package_verification_failed",
24437
+ "The managed npm dependency closure is invalid"
24438
+ );
24439
+ }
24440
+ }
24119
24441
  if (normalizedKey === suffix || normalizedKey.endsWith(`/${suffix}`)) {
24120
24442
  entry = candidate;
24121
24443
  matches += 1;
@@ -24213,33 +24535,42 @@ var ManagedNpmPackageInstaller = class {
24213
24535
  "A supported npm executable is required to install the managed package"
24214
24536
  );
24215
24537
  }
24538
+ const installArguments = ["install", "--prefix", staging];
24539
+ installArguments.push(...definition.dependencyResolutionArguments);
24540
+ if (definition.includeOptionalDependencies) {
24541
+ installArguments.push("--include=optional");
24542
+ } else {
24543
+ installArguments.push("--omit=optional");
24544
+ }
24545
+ installArguments.push(
24546
+ "--ignore-scripts",
24547
+ "--no-audit",
24548
+ "--no-fund",
24549
+ "--package-lock=true",
24550
+ "--save-exact",
24551
+ "--registry=https://registry.npmjs.org/",
24552
+ `${definition.packageName}@${definition.version}`
24553
+ );
24554
+ const installEnvironment = {
24555
+ HOME: join5(staging, "home"),
24556
+ NPM_CONFIG_AUDIT: "false",
24557
+ NPM_CONFIG_CACHE: join5(staging, ".npm-cache"),
24558
+ NPM_CONFIG_FUND: "false",
24559
+ NPM_CONFIG_IGNORE_SCRIPTS: "true",
24560
+ NPM_CONFIG_PACKAGE_LOCK: "true",
24561
+ NPM_CONFIG_REGISTRY: "https://registry.npmjs.org/",
24562
+ PATH: `${dirname3(process.execPath)}${delimiter}/usr/bin${delimiter}/bin`
24563
+ };
24564
+ if (definition.includeOptionalDependencies) {
24565
+ installEnvironment["NPM_CONFIG_INCLUDE"] = "optional";
24566
+ } else {
24567
+ installEnvironment["NPM_CONFIG_OMIT"] = "optional";
24568
+ }
24216
24569
  await runBoundedProcess({
24217
- arguments: [
24218
- "install",
24219
- "--prefix",
24220
- staging,
24221
- "--omit=optional",
24222
- "--ignore-scripts",
24223
- "--no-audit",
24224
- "--no-fund",
24225
- "--package-lock=true",
24226
- "--save-exact",
24227
- "--registry=https://registry.npmjs.org/",
24228
- `${definition.packageName}@${definition.version}`
24229
- ],
24570
+ arguments: installArguments,
24230
24571
  command: npm.path,
24231
24572
  cwd: staging,
24232
- environment: {
24233
- HOME: join5(staging, "home"),
24234
- NPM_CONFIG_AUDIT: "false",
24235
- NPM_CONFIG_CACHE: join5(staging, ".npm-cache"),
24236
- NPM_CONFIG_FUND: "false",
24237
- NPM_CONFIG_IGNORE_SCRIPTS: "true",
24238
- NPM_CONFIG_OMIT: "optional",
24239
- NPM_CONFIG_PACKAGE_LOCK: "true",
24240
- NPM_CONFIG_REGISTRY: "https://registry.npmjs.org/",
24241
- PATH: `${dirname3(process.execPath)}${delimiter}/usr/bin${delimiter}/bin`
24242
- },
24573
+ environment: installEnvironment,
24243
24574
  outputLimitBytes: 64 * 1024,
24244
24575
  signal,
24245
24576
  timeoutMilliseconds: INSTALL_TIMEOUT_MILLISECONDS
@@ -24281,90 +24612,867 @@ var ManagedNpmPackageInstaller = class {
24281
24612
  };
24282
24613
  };
24283
24614
 
24284
- // src/agent-installation/managed-adapter-installer.ts
24285
- var ManagedAdapterInstallError = class extends Error {
24286
- code;
24287
- constructor(code, message, options = {}) {
24288
- super(message, options);
24289
- this.code = code;
24290
- this.name = "ManagedAdapterInstallError";
24291
- }
24292
- };
24293
- function translateError(error61) {
24294
- if (error61 instanceof ManagedAdapterInstallError) {
24295
- return error61;
24296
- }
24297
- if (error61 instanceof ManagedNpmPackageError) {
24298
- if (error61.code === "package_manager_not_found") {
24299
- return new ManagedAdapterInstallError(
24300
- error61.code,
24301
- "A supported npm executable is required to install the ACP adapter",
24302
- { cause: error61 }
24303
- );
24304
- }
24305
- if (error61.code === "managed_package_verification_failed") {
24306
- return new ManagedAdapterInstallError(
24307
- "adapter_verification_failed",
24308
- "The managed adapter did not match its pinned artifact",
24615
+ // src/agent-catalog/agent-specification.ts
24616
+ import { join as join6 } from "node:path";
24617
+ var VERSION_PROBE_TIMEOUT_MILLISECONDS = 3e3;
24618
+ var ACP_PROBE_TIMEOUT_MILLISECONDS = 5e3;
24619
+ var DEFAULT_PROMPT_TIMEOUT_MILLISECONDS = 30 * 60 * 1e3;
24620
+ var LocalAgentSpecification = class {
24621
+ acpProbeTimeoutMilliseconds = ACP_PROBE_TIMEOUT_MILLISECONDS;
24622
+ authenticationCommand = () => "";
24623
+ adapterVersionArguments = ["--version"];
24624
+ agentVersionArguments = ["--version"];
24625
+ promptTimeoutMilliseconds = DEFAULT_PROMPT_TIMEOUT_MILLISECONDS;
24626
+ versionProbeTimeoutMilliseconds = VERSION_PROBE_TIMEOUT_MILLISECONDS;
24627
+ resolveManagedAgent = async (stateDirectory, platform, signal) => {
24628
+ signal.throwIfAborted();
24629
+ const executable = await resolveExecutablePath(
24630
+ join6(stateDirectory, ...this.managedAgentExecutablePath),
24631
+ platform
24632
+ );
24633
+ signal.throwIfAborted();
24634
+ if (executable === null) {
24635
+ throw new Error("The managed Agent executable is unavailable");
24636
+ }
24637
+ return executable;
24638
+ };
24639
+ createLaunchEnvironment = async (_agent, _context) => Object.freeze({});
24640
+ recoveryCommand = () => "";
24641
+ supportsInstallation = (platform, architecture) => (platform === "darwin" || platform === "linux") && (architecture === "arm64" || architecture === "x64");
24642
+ verifyAcp = (_connection, _initialized, _defaultWorkspace, _signal) => Promise.resolve();
24643
+ };
24644
+ var DirectAcpAgentDefinition = class extends LocalAgentSpecification {
24645
+ adapterOverrideVariable;
24646
+ agentOverrideVariable;
24647
+ launchArguments;
24648
+ managedAdapterExecutablePath;
24649
+ managedAgentExecutablePath;
24650
+ constructor(executableOverrideVariable, launchArguments, managedExecutablePath) {
24651
+ super();
24652
+ this.adapterOverrideVariable = executableOverrideVariable;
24653
+ this.agentOverrideVariable = executableOverrideVariable;
24654
+ this.launchArguments = Object.freeze([...launchArguments]);
24655
+ this.managedAdapterExecutablePath = Object.freeze([
24656
+ ...managedExecutablePath
24657
+ ]);
24658
+ this.managedAgentExecutablePath = this.managedAdapterExecutablePath;
24659
+ }
24660
+ };
24661
+ var BridgedAcpAgentDefinition = class extends LocalAgentSpecification {
24662
+ launchArguments = Object.freeze([]);
24663
+ get adapterExecutable() {
24664
+ return this.adapterPackageDefinition.executableName;
24665
+ }
24666
+ get adapterPackage() {
24667
+ return this.adapterPackageDefinition.packageName;
24668
+ }
24669
+ get adapterVersion() {
24670
+ return this.adapterPackageDefinition.version;
24671
+ }
24672
+ createLaunchEnvironment = async (agent, _context) => Object.freeze({ [this.adapterEnvironmentVariable]: agent.path });
24673
+ recoveryCommand = () => `npm install -g --omit=optional ${this.adapterPackage}@${this.adapterVersion}`;
24674
+ };
24675
+
24676
+ // src/agent-catalog/agents/claude-code-agent.ts
24677
+ var ClaudeCodeAgentSpecification = class extends BridgedAcpAgentDefinition {
24678
+ adapterEnvironmentVariable = "CLAUDE_CODE_EXECUTABLE";
24679
+ adapterOverrideVariable = "MOBIUS_CLAUDE_ACP_PATH";
24680
+ adapterPackageDefinition = new ManagedNpmPackageDefinition(
24681
+ "@agentclientprotocol/claude-agent-acp",
24682
+ "0.73.0",
24683
+ "claude-agent-acp"
24684
+ );
24685
+ agentExecutable = "claude";
24686
+ agentOverrideVariable = "MOBIUS_CLAUDE_PATH";
24687
+ id = "claude";
24688
+ label = "Claude Code";
24689
+ managedAdapterExecutablePath = [
24690
+ "adapters",
24691
+ "claude",
24692
+ "0.73.0",
24693
+ "node_modules",
24694
+ "@agentclientprotocol",
24695
+ "claude-agent-acp",
24696
+ "dist",
24697
+ "index.js"
24698
+ ];
24699
+ managedAgentExecutablePath = [
24700
+ "agents",
24701
+ "claude",
24702
+ "home",
24703
+ ".local",
24704
+ "bin",
24705
+ "claude"
24706
+ ];
24707
+ };
24708
+
24709
+ // src/agent-catalog/agents/codex-agent.ts
24710
+ var CodexAgentSpecification = class extends BridgedAcpAgentDefinition {
24711
+ adapterEnvironmentVariable = "CODEX_PATH";
24712
+ adapterOverrideVariable = "MOBIUS_CODEX_ACP_PATH";
24713
+ adapterPackageDefinition = new ManagedNpmPackageDefinition(
24714
+ "@agentclientprotocol/codex-acp",
24715
+ "1.8.0",
24716
+ "codex-acp"
24717
+ );
24718
+ agentExecutable = "codex";
24719
+ agentOverrideVariable = "MOBIUS_CODEX_PATH";
24720
+ id = "codex";
24721
+ label = "Codex";
24722
+ managedAdapterExecutablePath = [
24723
+ "adapters",
24724
+ "codex",
24725
+ "1.8.0",
24726
+ "node_modules",
24727
+ "@agentclientprotocol",
24728
+ "codex-acp",
24729
+ "dist",
24730
+ "index.js"
24731
+ ];
24732
+ managedAgentExecutablePath = ["agents", "codex", "bin", "codex"];
24733
+ };
24734
+
24735
+ // src/agent-catalog/agents/deepseek-harness-agent.ts
24736
+ import { realpath as realpath3, stat as stat3 } from "node:fs/promises";
24737
+ import { isAbsolute as isAbsolute2, join as join7, normalize } from "node:path";
24738
+
24739
+ // src/agent-installation/deepseek-managed-package.ts
24740
+ var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
24741
+ dependencyResolutionArguments = Object.freeze([
24742
+ "--before=2026-09-03T06:31:52.107Z"
24743
+ ]);
24744
+ includeOptionalDependencies = true;
24745
+ verifyDependencyClosure = true;
24746
+ };
24747
+ var DEEPSEEK_HARNESS_PACKAGE = new DeepSeekHarnessManagedPackage(
24748
+ "@deepseek-ai/dsh",
24749
+ "0.1.2-rc.1",
24750
+ "dsh",
24751
+ "sha512-RPq48TzxvwpdT9/7W1tbhZDBMmeK+bxDrX9cqQC27Wx/LqtgJF8PSa3b3xriU8oxtvhwYmk21w2cej3uMQrnVA==",
24752
+ "https://registry.npmjs.org/@deepseek-ai/dsh/-/dsh-0.1.2-rc.1.tgz"
24753
+ );
24754
+
24755
+ // src/agent-catalog/agent-probe-error.ts
24756
+ var AgentProbeError = class extends Error {
24757
+ code;
24758
+ constructor(code, message, options = {}) {
24759
+ super(message, options);
24760
+ this.code = code;
24761
+ this.name = "AgentProbeError";
24762
+ }
24763
+ };
24764
+
24765
+ // src/agent-catalog/agents/deepseek-harness-agent.ts
24766
+ async function validateAgentHome(path2) {
24767
+ if (!isAbsolute2(path2) || normalize(path2) !== path2) {
24768
+ throw new AgentProbeError(
24769
+ "agent_environment_invalid",
24770
+ "The configured Agent home is invalid"
24771
+ );
24772
+ }
24773
+ try {
24774
+ const resolved = await realpath3(path2);
24775
+ const metadata = await stat3(resolved);
24776
+ if (!metadata.isDirectory() || typeof process.getuid === "function" && metadata.uid !== process.getuid()) {
24777
+ throw new Error("Agent home is not a user-owned directory");
24778
+ }
24779
+ return resolved;
24780
+ } catch (error61) {
24781
+ if (error61 instanceof AgentProbeError) {
24782
+ throw error61;
24783
+ }
24784
+ throw new AgentProbeError(
24785
+ "agent_environment_invalid",
24786
+ "The configured Agent home is invalid",
24787
+ { cause: error61 }
24788
+ );
24789
+ }
24790
+ }
24791
+ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
24792
+ adapterVersion = DEEPSEEK_HARNESS_PACKAGE.version;
24793
+ authenticationCommand = () => "dsh web";
24794
+ agentExecutable = "dsh";
24795
+ id = "deepseek-harness";
24796
+ label = "DeepSeek Harness";
24797
+ constructor() {
24798
+ super(
24799
+ "MOBIUS_DEEPSEEK_HARNESS_PATH",
24800
+ ["--profile", "acp"],
24801
+ [
24802
+ "agents",
24803
+ "deepseek-harness",
24804
+ DEEPSEEK_HARNESS_PACKAGE.version,
24805
+ "node_modules",
24806
+ "@deepseek-ai",
24807
+ "dsh",
24808
+ "lib",
24809
+ "bin.js"
24810
+ ]
24811
+ );
24812
+ }
24813
+ createLaunchEnvironment = async (agent, context) => {
24814
+ let selectedHome = context.environment["DSH_HOME"];
24815
+ try {
24816
+ const managed = await this.resolveManagedAgent(
24817
+ readStateDirectory(context.environment),
24818
+ context.platform ?? process.platform,
24819
+ context.signal
24820
+ );
24821
+ if (managed.path === agent.path) {
24822
+ selectedHome = join7(
24823
+ readStateDirectory(context.environment),
24824
+ "agents",
24825
+ this.id,
24826
+ "home"
24827
+ );
24828
+ }
24829
+ } catch {
24830
+ context.signal.throwIfAborted();
24831
+ }
24832
+ if (selectedHome === void 0 || selectedHome.length === 0) {
24833
+ return Object.freeze({ DSH_PERMISSION_MODE: "workspace-write" });
24834
+ }
24835
+ return Object.freeze({
24836
+ DSH_HOME: await validateAgentHome(selectedHome),
24837
+ DSH_PERMISSION_MODE: "workspace-write"
24838
+ });
24839
+ };
24840
+ resolveManagedAgent = async (stateDirectory, _platform, signal) => {
24841
+ signal.throwIfAborted();
24842
+ const executable = await validateManagedNpmPackage(
24843
+ join7(stateDirectory, "agents", this.id, DEEPSEEK_HARNESS_PACKAGE.version),
24844
+ DEEPSEEK_HARNESS_PACKAGE
24845
+ );
24846
+ signal.throwIfAborted();
24847
+ return executable;
24848
+ };
24849
+ verifyAcp = (_connection, initialized, _defaultWorkspace, _signal) => {
24850
+ const capabilities = initialized.agentCapabilities ?? {};
24851
+ const session = capabilities.sessionCapabilities;
24852
+ const prompt = capabilities.promptCapabilities;
24853
+ if ((initialized.authMethods ?? []).length !== 0 || capabilities.loadSession === true || capabilities.mcpCapabilities?.http !== true || session?.close == null || session.list == null || session.resume == null || session.additionalDirectories != null || session.delete != null || session.fork != null || prompt?.audio === true || prompt?.embeddedContext === true || prompt?.image === true) {
24854
+ throw new AgentProbeError(
24855
+ "acp_incompatible",
24856
+ "DeepSeek Harness reported an unsupported ACP capability set"
24857
+ );
24858
+ }
24859
+ return Promise.resolve();
24860
+ };
24861
+ };
24862
+
24863
+ // src/agent-catalog/agents/opencode-agent.ts
24864
+ import { join as join9 } from "node:path";
24865
+
24866
+ // src/agent-installation/managed-agent-archive.ts
24867
+ import { createHash as createHash2 } from "node:crypto";
24868
+ import { createReadStream } from "node:fs";
24869
+ import {
24870
+ chmod,
24871
+ copyFile,
24872
+ mkdir as mkdir2,
24873
+ mkdtemp as mkdtemp2,
24874
+ open as open5,
24875
+ realpath as realpath4,
24876
+ rename as rename2,
24877
+ rm as rm2,
24878
+ stat as stat4,
24879
+ writeFile
24880
+ } from "node:fs/promises";
24881
+ import { dirname as dirname4, isAbsolute as isAbsolute3, join as join8, relative as relative2, sep as sep2 } from "node:path";
24882
+
24883
+ // src/agent-installation/verified-download.ts
24884
+ import { createHash } from "node:crypto";
24885
+ import { open as open4, unlink } from "node:fs/promises";
24886
+ import { fetch } from "undici";
24887
+
24888
+ // src/network/environment-proxy.ts
24889
+ import { EnvHttpProxyAgent } from "undici";
24890
+ var environmentProxyDispatcher = new EnvHttpProxyAgent();
24891
+
24892
+ // src/agent-installation/verified-download.ts
24893
+ var MAX_REDIRECTS = 4;
24894
+ var REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
24895
+ var InstallerDownloadError = class extends Error {
24896
+ code;
24897
+ constructor(code, message, options = {}) {
24898
+ super(message, options);
24899
+ this.code = code;
24900
+ this.name = "InstallerDownloadError";
24901
+ }
24902
+ };
24903
+ var VerifiedDownload = class {
24904
+ bytes;
24905
+ sha256;
24906
+ url;
24907
+ constructor(url2, bytes, sha256) {
24908
+ this.bytes = bytes;
24909
+ this.sha256 = sha256;
24910
+ this.url = url2;
24911
+ }
24912
+ };
24913
+ var UndiciInstallerDownloadTransport = class {
24914
+ get = async (url2, signal) => await fetch(url2, {
24915
+ dispatcher: environmentProxyDispatcher,
24916
+ headers: {
24917
+ accept: "text/plain, application/octet-stream;q=0.9",
24918
+ "user-agent": "Mobius-Agent-Installer/0.0.3"
24919
+ },
24920
+ method: "GET",
24921
+ redirect: "manual",
24922
+ signal
24923
+ });
24924
+ };
24925
+ function validateUrl(url2, allowedHosts) {
24926
+ if (url2.protocol !== "https:" || url2.username.length > 0 || url2.password.length > 0 || url2.port.length > 0 || !allowedHosts.has(url2.hostname)) {
24927
+ throw new InstallerDownloadError(
24928
+ "installer_host_not_allowed",
24929
+ "The installer download target is not allowed"
24930
+ );
24931
+ }
24932
+ }
24933
+ async function fetchInstaller(options, signal, transport) {
24934
+ let url2 = new URL(options.url);
24935
+ for (let redirectCount = 0; redirectCount <= MAX_REDIRECTS; redirectCount += 1) {
24936
+ validateUrl(url2, options.allowedHosts);
24937
+ const response = await transport.get(url2, signal);
24938
+ if (!REDIRECT_STATUSES.has(response.status)) {
24939
+ return { response, url: url2 };
24940
+ }
24941
+ await response.body?.cancel();
24942
+ const location = response.headers.get("location");
24943
+ if (location === null || redirectCount === MAX_REDIRECTS) {
24944
+ throw new InstallerDownloadError(
24945
+ "installer_redirect_invalid",
24946
+ "The installer returned an invalid redirect"
24947
+ );
24948
+ }
24949
+ let redirected;
24950
+ try {
24951
+ redirected = new URL(location, url2);
24952
+ } catch (error61) {
24953
+ throw new InstallerDownloadError(
24954
+ "installer_redirect_invalid",
24955
+ "The installer returned an invalid redirect",
24309
24956
  { cause: error61 }
24310
24957
  );
24311
24958
  }
24312
- if (error61.code === "managed_package_publish_failed") {
24313
- return new ManagedAdapterInstallError(
24314
- "adapter_publish_failed",
24315
- "The managed adapter could not be published",
24959
+ try {
24960
+ validateUrl(redirected, options.allowedHosts);
24961
+ } catch (error61) {
24962
+ throw new InstallerDownloadError(
24963
+ "installer_redirect_not_allowed",
24964
+ "The installer redirect left the approved host allowlist",
24316
24965
  { cause: error61 }
24317
24966
  );
24318
24967
  }
24968
+ url2 = redirected;
24319
24969
  }
24320
- return new ManagedAdapterInstallError(
24321
- "adapter_install_failed",
24322
- "The pinned ACP adapter could not be installed",
24323
- { cause: error61 }
24970
+ throw new InstallerDownloadError(
24971
+ "installer_redirect_invalid",
24972
+ "The installer returned too many redirects"
24324
24973
  );
24325
24974
  }
24326
- async function validateManagedAdapter(root, specification) {
24975
+ async function writeCompleteChunk(handle, chunk) {
24976
+ let offset = 0;
24977
+ while (offset < chunk.byteLength) {
24978
+ const written = await handle.write(
24979
+ chunk,
24980
+ offset,
24981
+ chunk.byteLength - offset
24982
+ );
24983
+ if (written.bytesWritten < 1) {
24984
+ throw new InstallerDownloadError(
24985
+ "installer_write_failed",
24986
+ "The verified installer could not be stored"
24987
+ );
24988
+ }
24989
+ offset += written.bytesWritten;
24990
+ }
24991
+ }
24992
+ async function downloadVerifiedFile(options, transport = new UndiciInstallerDownloadTransport()) {
24993
+ options.signal.throwIfAborted();
24994
+ const timeoutSignal = AbortSignal.timeout(options.timeoutMilliseconds);
24995
+ const signal = AbortSignal.any([options.signal, timeoutSignal]);
24996
+ let handle = null;
24997
+ let responseBody = null;
24327
24998
  try {
24328
- return await validateManagedNpmPackage(
24329
- root,
24330
- specification.adapterPackageDefinition
24999
+ const fetched = await fetchInstaller(options, signal, transport);
25000
+ responseBody = fetched.response.body;
25001
+ if (!fetched.response.ok || fetched.response.body === null) {
25002
+ throw new InstallerDownloadError(
25003
+ "installer_download_failed",
25004
+ "The approved installer could not be downloaded"
25005
+ );
25006
+ }
25007
+ const contentLength = fetched.response.headers.get("content-length");
25008
+ if (contentLength !== null) {
25009
+ const declaredLength = Number(contentLength);
25010
+ if (!Number.isSafeInteger(declaredLength) || declaredLength < 1 || declaredLength > options.maximumBytes) {
25011
+ throw new InstallerDownloadError(
25012
+ "installer_size_invalid",
25013
+ "The installer size is outside the approved limit"
25014
+ );
25015
+ }
25016
+ }
25017
+ handle = await open4(options.destination, "wx", 384);
25018
+ const digest = createHash("sha256");
25019
+ const reader = fetched.response.body.getReader();
25020
+ let bytes = 0;
25021
+ try {
25022
+ while (true) {
25023
+ signal.throwIfAborted();
25024
+ const chunk = await reader.read();
25025
+ if (chunk.done) {
25026
+ break;
25027
+ }
25028
+ bytes += chunk.value.byteLength;
25029
+ if (bytes > options.maximumBytes) {
25030
+ throw new InstallerDownloadError(
25031
+ "installer_size_invalid",
25032
+ "The installer exceeded the approved size limit"
25033
+ );
25034
+ }
25035
+ digest.update(chunk.value);
25036
+ await writeCompleteChunk(handle, chunk.value);
25037
+ }
25038
+ } finally {
25039
+ await reader.cancel().catch(() => void 0);
25040
+ reader.releaseLock();
25041
+ }
25042
+ if (bytes === 0) {
25043
+ throw new InstallerDownloadError(
25044
+ "installer_verification_failed",
25045
+ "The downloaded installer is empty"
25046
+ );
25047
+ }
25048
+ await handle.sync();
25049
+ await handle.close();
25050
+ handle = null;
25051
+ return new VerifiedDownload(fetched.url, bytes, digest.digest("hex"));
25052
+ } catch (error61) {
25053
+ if (handle !== null) {
25054
+ await handle.close().catch(() => void 0);
25055
+ }
25056
+ await unlink(options.destination).catch(() => void 0);
25057
+ if (options.signal.aborted) {
25058
+ options.signal.throwIfAborted();
25059
+ }
25060
+ if (timeoutSignal.aborted) {
25061
+ throw new InstallerDownloadError(
25062
+ "installer_download_timeout",
25063
+ "The installer download timed out",
25064
+ { cause: error61 }
25065
+ );
25066
+ }
25067
+ if (error61 instanceof InstallerDownloadError) {
25068
+ throw error61;
25069
+ }
25070
+ throw new InstallerDownloadError(
25071
+ "installer_download_failed",
25072
+ "The approved installer could not be downloaded",
25073
+ { cause: error61 }
24331
25074
  );
25075
+ } finally {
25076
+ await responseBody?.cancel().catch(() => void 0);
25077
+ }
25078
+ }
25079
+
25080
+ // src/agent-installation/managed-agent-archive.ts
25081
+ var ARCHIVE_DOWNLOAD_LIMIT_BYTES = 128 * 1024 * 1024;
25082
+ var ARCHIVE_DOWNLOAD_TIMEOUT_MILLISECONDS = 2 * 60 * 1e3;
25083
+ var ARCHIVE_EXTRACTION_TIMEOUT_MILLISECONDS = 6e4;
25084
+ var MANIFEST_LIMIT_BYTES = 16 * 1024;
25085
+ var MINIMAL_PATH = "/usr/bin:/bin";
25086
+ var ManagedAgentArchiveDefinition = class {
25087
+ archiveName;
25088
+ archiveSha256;
25089
+ archiveUrl;
25090
+ executableName;
25091
+ version;
25092
+ constructor(version2, archiveName, archiveUrl, archiveSha256, executableName) {
25093
+ this.archiveName = archiveName;
25094
+ this.archiveSha256 = archiveSha256;
25095
+ this.archiveUrl = new URL(archiveUrl);
25096
+ this.executableName = executableName;
25097
+ this.version = version2;
25098
+ }
25099
+ };
25100
+ var ZipManagedAgentArchiveDefinition = class extends ManagedAgentArchiveDefinition {
25101
+ extractor = "/usr/bin/unzip";
25102
+ extractArguments = (archivePath, destination) => ["-q", archivePath, "-d", destination];
25103
+ listArguments = (archivePath) => [
25104
+ "-Z1",
25105
+ archivePath
25106
+ ];
25107
+ };
25108
+ var TarGzipManagedAgentArchiveDefinition = class extends ManagedAgentArchiveDefinition {
25109
+ extractor = "/usr/bin/tar";
25110
+ extractArguments = (archivePath, destination) => ["-xzf", archivePath, "-C", destination];
25111
+ listArguments = (archivePath) => [
25112
+ "-tzf",
25113
+ archivePath
25114
+ ];
25115
+ };
25116
+ var ManagedAgentArchiveError = class extends Error {
25117
+ code;
25118
+ constructor(code, message, options = {}) {
25119
+ super(message, options);
25120
+ this.code = code;
25121
+ this.name = "ManagedAgentArchiveError";
25122
+ }
25123
+ };
25124
+ var ManagedAgentArchiveDownloader = class {
25125
+ download = async (options) => await downloadVerifiedFile(options);
25126
+ };
25127
+ function isRecord6(value) {
25128
+ return typeof value === "object" && value !== null && !Array.isArray(value);
25129
+ }
25130
+ function isContainedPath2(root, candidate) {
25131
+ const difference = relative2(root, candidate);
25132
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute3(difference);
25133
+ }
25134
+ async function hashFile(path2, signal) {
25135
+ signal.throwIfAborted();
25136
+ const digest = createHash2("sha256");
25137
+ const stream = createReadStream(path2, { signal });
25138
+ try {
25139
+ for await (const chunk of stream) {
25140
+ signal.throwIfAborted();
25141
+ if (!(chunk instanceof Uint8Array)) {
25142
+ throw new ManagedAgentArchiveError(
25143
+ "managed_archive_verification_failed",
25144
+ "The managed Agent archive produced invalid bytes"
25145
+ );
25146
+ }
25147
+ digest.update(chunk);
25148
+ }
25149
+ return digest.digest("hex");
24332
25150
  } catch (error61) {
24333
- throw translateError(error61);
25151
+ if (signal.aborted) {
25152
+ signal.throwIfAborted();
25153
+ }
25154
+ if (error61 instanceof ManagedAgentArchiveError) {
25155
+ throw error61;
25156
+ }
25157
+ throw new ManagedAgentArchiveError(
25158
+ "managed_archive_verification_failed",
25159
+ "The managed Agent artifact could not be verified",
25160
+ { cause: error61 }
25161
+ );
24334
25162
  }
24335
25163
  }
24336
- var ManagedAdapterInstaller = class {
24337
- #environment;
24338
- #npmInstaller;
24339
- #stateDirectory;
24340
- constructor(options, npmInstaller = new ManagedNpmPackageInstaller()) {
24341
- this.#environment = options.environment;
24342
- this.#npmInstaller = npmInstaller;
24343
- this.#stateDirectory = options.stateDirectory;
25164
+ async function readManifest(path2) {
25165
+ let handle;
25166
+ try {
25167
+ handle = await open5(path2, "r");
25168
+ } catch (error61) {
25169
+ throw new ManagedAgentArchiveError(
25170
+ "managed_archive_verification_failed",
25171
+ "The managed Agent archive manifest is invalid",
25172
+ { cause: error61 }
25173
+ );
25174
+ }
25175
+ try {
25176
+ const metadata = await handle.stat();
25177
+ if (!metadata.isFile() || metadata.size > MANIFEST_LIMIT_BYTES) {
25178
+ throw new ManagedAgentArchiveError(
25179
+ "managed_archive_verification_failed",
25180
+ "The managed Agent archive manifest is invalid"
25181
+ );
25182
+ }
25183
+ const parsed = JSON.parse(
25184
+ await handle.readFile({ encoding: "utf8" })
25185
+ );
25186
+ if (!isRecord6(parsed)) {
25187
+ throw new ManagedAgentArchiveError(
25188
+ "managed_archive_verification_failed",
25189
+ "The managed Agent archive manifest is invalid"
25190
+ );
25191
+ }
25192
+ return parsed;
25193
+ } catch (error61) {
25194
+ if (error61 instanceof ManagedAgentArchiveError) {
25195
+ throw error61;
25196
+ }
25197
+ throw new ManagedAgentArchiveError(
25198
+ "managed_archive_verification_failed",
25199
+ "The managed Agent archive manifest is invalid",
25200
+ { cause: error61 }
25201
+ );
25202
+ } finally {
25203
+ await handle.close();
25204
+ }
25205
+ }
25206
+ async function validateManagedAgentArchive(root, definition, signal) {
25207
+ try {
25208
+ const rootPath = await realpath4(root);
25209
+ const rootMetadata = await stat4(rootPath);
25210
+ if (!rootMetadata.isDirectory() || typeof process.getuid === "function" && rootMetadata.uid !== process.getuid()) {
25211
+ throw new Error("Managed Agent root is not user-owned");
25212
+ }
25213
+ const manifest = await readManifest(join8(rootPath, "archive.json"));
25214
+ if (manifest["archiveSha256"] !== definition.archiveSha256 || manifest["archiveUrl"] !== definition.archiveUrl.toString() || manifest["version"] !== definition.version || typeof manifest["executableSha256"] !== "string") {
25215
+ throw new Error("Managed Agent archive identity is invalid");
25216
+ }
25217
+ const executable = await resolveExecutablePath(
25218
+ join8(rootPath, "bin", definition.executableName)
25219
+ );
25220
+ if (executable === null || !isContainedPath2(rootPath, executable.path) || await hashFile(executable.path, signal) !== manifest["executableSha256"]) {
25221
+ throw new Error("Managed Agent executable is invalid");
25222
+ }
25223
+ return executable;
25224
+ } catch (error61) {
25225
+ if (signal.aborted) {
25226
+ signal.throwIfAborted();
25227
+ }
25228
+ if (error61 instanceof ManagedAgentArchiveError) {
25229
+ throw error61;
25230
+ }
25231
+ throw new ManagedAgentArchiveError(
25232
+ "managed_archive_verification_failed",
25233
+ "The managed Agent archive did not match its pinned artifact",
25234
+ { cause: error61 }
25235
+ );
25236
+ }
25237
+ }
25238
+ function validateArchiveEntries(output2, definition) {
25239
+ const entries = output2.split(/\r?\n/).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
25240
+ if (entries.length !== 1 || entries[0] !== definition.executableName && entries[0] !== `./${definition.executableName}`) {
25241
+ throw new ManagedAgentArchiveError(
25242
+ "managed_archive_verification_failed",
25243
+ "The managed Agent archive contains unexpected entries"
25244
+ );
25245
+ }
25246
+ }
25247
+ var ManagedAgentArchiveInstaller = class {
25248
+ #downloader;
25249
+ constructor(downloader = new ManagedAgentArchiveDownloader()) {
25250
+ this.#downloader = downloader;
25251
+ }
25252
+ install = async (root, definition, signal) => {
25253
+ signal.throwIfAborted();
25254
+ try {
25255
+ const metadata = await stat4(root);
25256
+ if (metadata.isDirectory()) {
25257
+ return await validateManagedAgentArchive(root, definition, signal);
25258
+ }
25259
+ } catch (error61) {
25260
+ if (error61 instanceof ManagedAgentArchiveError || !(error61 instanceof Error) || !("code" in error61) || error61.code !== "ENOENT") {
25261
+ throw error61;
25262
+ }
25263
+ }
25264
+ const parent = dirname4(root);
25265
+ await mkdir2(parent, { mode: 448, recursive: true });
25266
+ const working = await mkdtemp2(
25267
+ join8(parent, `.${definition.version}.archive-`)
25268
+ );
25269
+ const staging = await mkdtemp2(
25270
+ join8(parent, `.${definition.version}.staging-`)
25271
+ );
25272
+ try {
25273
+ const archivePath = join8(working, definition.archiveName);
25274
+ const extractionRoot = join8(working, "extracted");
25275
+ await mkdir2(extractionRoot, { mode: 448 });
25276
+ const canonicalExtractionRoot = await realpath4(extractionRoot);
25277
+ const download = await this.#downloader.download({
25278
+ allowedHosts: /* @__PURE__ */ new Set([
25279
+ "github.com",
25280
+ "objects.githubusercontent.com",
25281
+ "release-assets.githubusercontent.com"
25282
+ ]),
25283
+ destination: archivePath,
25284
+ maximumBytes: ARCHIVE_DOWNLOAD_LIMIT_BYTES,
25285
+ signal,
25286
+ timeoutMilliseconds: ARCHIVE_DOWNLOAD_TIMEOUT_MILLISECONDS,
25287
+ url: definition.archiveUrl
25288
+ });
25289
+ if (download.sha256 !== definition.archiveSha256) {
25290
+ throw new ManagedAgentArchiveError(
25291
+ "managed_archive_verification_failed",
25292
+ "The managed Agent archive checksum is invalid"
25293
+ );
25294
+ }
25295
+ const list = await runBoundedProcess({
25296
+ arguments: definition.listArguments(archivePath),
25297
+ command: definition.extractor,
25298
+ cwd: working,
25299
+ environment: { PATH: MINIMAL_PATH },
25300
+ outputLimitBytes: 64 * 1024,
25301
+ signal,
25302
+ timeoutMilliseconds: ARCHIVE_EXTRACTION_TIMEOUT_MILLISECONDS
25303
+ });
25304
+ validateArchiveEntries(list.stdout, definition);
25305
+ await runBoundedProcess({
25306
+ arguments: definition.extractArguments(archivePath, extractionRoot),
25307
+ command: definition.extractor,
25308
+ cwd: working,
25309
+ environment: { PATH: MINIMAL_PATH },
25310
+ outputLimitBytes: 64 * 1024,
25311
+ signal,
25312
+ timeoutMilliseconds: ARCHIVE_EXTRACTION_TIMEOUT_MILLISECONDS
25313
+ });
25314
+ const extracted = await realpath4(
25315
+ join8(canonicalExtractionRoot, definition.executableName)
25316
+ );
25317
+ const extractedMetadata = await stat4(extracted);
25318
+ if (!isContainedPath2(canonicalExtractionRoot, extracted) || !extractedMetadata.isFile()) {
25319
+ throw new ManagedAgentArchiveError(
25320
+ "managed_archive_verification_failed",
25321
+ "The managed Agent archive executable is invalid"
25322
+ );
25323
+ }
25324
+ const binDirectory = join8(staging, "bin");
25325
+ const executablePath = join8(binDirectory, definition.executableName);
25326
+ await mkdir2(binDirectory, { mode: 448 });
25327
+ await copyFile(extracted, executablePath);
25328
+ await chmod(executablePath, 448);
25329
+ const executableSha256 = await hashFile(executablePath, signal);
25330
+ await writeFile(
25331
+ join8(staging, "archive.json"),
25332
+ `${JSON.stringify({
25333
+ archiveSha256: definition.archiveSha256,
25334
+ archiveUrl: definition.archiveUrl.toString(),
25335
+ executableSha256,
25336
+ version: definition.version
25337
+ })}
25338
+ `,
25339
+ { mode: 384 }
25340
+ );
25341
+ await validateManagedAgentArchive(staging, definition, signal);
25342
+ try {
25343
+ await rename2(staging, root);
25344
+ } catch (error61) {
25345
+ try {
25346
+ return await validateManagedAgentArchive(root, definition, signal);
25347
+ } catch {
25348
+ throw new ManagedAgentArchiveError(
25349
+ "managed_archive_publish_failed",
25350
+ "The managed Agent archive could not be published",
25351
+ { cause: error61 }
25352
+ );
25353
+ }
25354
+ }
25355
+ return await validateManagedAgentArchive(root, definition, signal);
25356
+ } catch (error61) {
25357
+ if (signal.aborted) {
25358
+ signal.throwIfAborted();
25359
+ }
25360
+ if (error61 instanceof ManagedAgentArchiveError) {
25361
+ throw error61;
25362
+ }
25363
+ throw new ManagedAgentArchiveError(
25364
+ "managed_archive_install_failed",
25365
+ "The pinned Agent archive could not be installed",
25366
+ { cause: error61 }
25367
+ );
25368
+ } finally {
25369
+ await Promise.all([
25370
+ rm2(working, { force: true, recursive: true }),
25371
+ rm2(staging, { force: true, recursive: true })
25372
+ ]);
25373
+ }
25374
+ };
25375
+ };
25376
+
25377
+ // src/agent-installation/opencode-managed-release.ts
25378
+ var OPENCODE_MANAGED_VERSION = "1.18.29";
25379
+ function releaseUrl(asset) {
25380
+ return new URL(
25381
+ `https://github.com/anomalyco/opencode/releases/download/v${OPENCODE_MANAGED_VERSION}/${asset}`
25382
+ );
25383
+ }
25384
+ function openCodeManagedArchive(platform, architecture) {
25385
+ if (platform === "darwin" && architecture === "arm64") {
25386
+ const asset = "opencode-darwin-arm64.zip";
25387
+ return new ZipManagedAgentArchiveDefinition(
25388
+ OPENCODE_MANAGED_VERSION,
25389
+ asset,
25390
+ releaseUrl(asset),
25391
+ "fe764f7f360c584a83e18dd5f23fb1a6b2725f5ee8854b0252fe558f7798e946",
25392
+ "opencode"
25393
+ );
25394
+ }
25395
+ if (platform === "darwin" && architecture === "x64") {
25396
+ const asset = "opencode-darwin-x64.zip";
25397
+ return new ZipManagedAgentArchiveDefinition(
25398
+ OPENCODE_MANAGED_VERSION,
25399
+ asset,
25400
+ releaseUrl(asset),
25401
+ "9858853e7bacdbbd22c2d70c377e009dc4b354dd04f5588705411e7afb89fd2d",
25402
+ "opencode"
25403
+ );
24344
25404
  }
24345
- install = async (specification, signal) => {
24346
- const root = join6(
24347
- this.#stateDirectory,
24348
- "adapters",
24349
- specification.id,
24350
- specification.adapterVersion
25405
+ if (platform === "linux" && architecture === "arm64") {
25406
+ const asset = "opencode-linux-arm64.tar.gz";
25407
+ return new TarGzipManagedAgentArchiveDefinition(
25408
+ OPENCODE_MANAGED_VERSION,
25409
+ asset,
25410
+ releaseUrl(asset),
25411
+ "70baf769395ca4e7a68924026530c390eace194f3b7e4919d4efcb2aa2eed3c0",
25412
+ "opencode"
24351
25413
  );
24352
- try {
24353
- return await this.#npmInstaller.install(
24354
- root,
24355
- specification.adapterPackageDefinition,
24356
- this.#environment,
24357
- signal
25414
+ }
25415
+ if (platform === "linux" && architecture === "x64") {
25416
+ const asset = "opencode-linux-x64.tar.gz";
25417
+ return new TarGzipManagedAgentArchiveDefinition(
25418
+ OPENCODE_MANAGED_VERSION,
25419
+ asset,
25420
+ releaseUrl(asset),
25421
+ "ea800b7ff56226b70952126c9fc1e2517ca4c4b5682fd9d3f9e87449697a1194",
25422
+ "opencode"
25423
+ );
25424
+ }
25425
+ throw new Error(
25426
+ "OpenCode does not publish an approved archive for this platform"
25427
+ );
25428
+ }
25429
+
25430
+ // src/agent-catalog/agents/opencode-agent.ts
25431
+ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
25432
+ versionProbeTimeoutMilliseconds = 15e3;
25433
+ adapterVersion = OPENCODE_MANAGED_VERSION;
25434
+ authenticationCommand = () => "opencode auth login";
25435
+ agentExecutable = "opencode";
25436
+ id = "opencode";
25437
+ label = "OpenCode";
25438
+ constructor() {
25439
+ super(
25440
+ "MOBIUS_OPENCODE_PATH",
25441
+ ["acp"],
25442
+ [
25443
+ "agents",
25444
+ "opencode",
25445
+ OPENCODE_MANAGED_VERSION,
25446
+ "bin",
25447
+ process.platform === "win32" ? "opencode.exe" : "opencode"
25448
+ ]
25449
+ );
25450
+ }
25451
+ createLaunchEnvironment = async (_agent, _context) => Object.freeze({ OPENCODE_DISABLE_AUTOUPDATE: "1" });
25452
+ resolveManagedAgent = async (stateDirectory, platform, signal) => await validateManagedAgentArchive(
25453
+ join9(stateDirectory, "agents", this.id, OPENCODE_MANAGED_VERSION),
25454
+ openCodeManagedArchive(platform, process.arch),
25455
+ signal
25456
+ );
25457
+ verifyAcp = (_connection, initialized, _defaultWorkspace, _signal) => {
25458
+ const capabilities = initialized.agentCapabilities ?? {};
25459
+ const session = capabilities.sessionCapabilities;
25460
+ if (capabilities.loadSession !== true || session?.close == null || session.list == null || session.resume == null) {
25461
+ throw new AgentProbeError(
25462
+ "acp_incompatible",
25463
+ "OpenCode does not support the required ACP session lifecycle"
24358
25464
  );
24359
- } catch (error61) {
24360
- if (signal.aborted) {
24361
- signal.throwIfAborted();
24362
- }
24363
- throw translateError(error61);
24364
25465
  }
25466
+ return Promise.resolve();
24365
25467
  };
24366
25468
  };
24367
25469
 
25470
+ // src/agent-catalog/agents/pi-agent.ts
25471
+ import { join as join10 } from "node:path";
25472
+ import {
25473
+ methods as methods3
25474
+ } from "@agentclientprotocol/sdk";
25475
+
24368
25476
  // src/agent-installation/pi-managed-packages.ts
24369
25477
  var PI_ACP_PACKAGE = new SriManagedNpmPackageDefinition(
24370
25478
  "pi-acp",
@@ -24381,101 +25489,11 @@ var PI_AGENT_PACKAGE = new SriManagedNpmPackageDefinition(
24381
25489
  "https://registry.npmjs.org/@earendil-works/pi-coding-agent/-/pi-coding-agent-0.85.0.tgz"
24382
25490
  );
24383
25491
 
24384
- // src/agent-catalog/discover-local-agents.ts
24385
- var VERSION_PROBE_TIMEOUT_MILLISECONDS = 3e3;
24386
- var ACP_PROBE_TIMEOUT_MILLISECONDS = 5e3;
24387
- var ACP_OUTPUT_LIMIT_BYTES = 1024 * 1024;
24388
- var DEFAULT_PROMPT_TIMEOUT_MILLISECONDS = 30 * 60 * 1e3;
24389
- var PI_ACP_PROBE_TIMEOUT_MILLISECONDS = 3e4;
24390
- var PI_PROMPT_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
24391
- var LocalAgentSpecification = class {
24392
- acpProbeTimeoutMilliseconds = ACP_PROBE_TIMEOUT_MILLISECONDS;
24393
- authenticationCommand = () => "";
24394
- adapterVersionArguments = ["--version"];
24395
- agentVersionArguments = ["--version"];
24396
- promptTimeoutMilliseconds = DEFAULT_PROMPT_TIMEOUT_MILLISECONDS;
24397
- get adapterExecutable() {
24398
- return this.adapterPackageDefinition.executableName;
24399
- }
24400
- get adapterPackage() {
24401
- return this.adapterPackageDefinition.packageName;
24402
- }
24403
- get adapterVersion() {
24404
- return this.adapterPackageDefinition.version;
24405
- }
24406
- resolveManagedAgent = async (stateDirectory, platform) => {
24407
- const executable = await resolveExecutablePath(
24408
- join7(stateDirectory, ...this.managedAgentExecutablePath),
24409
- platform
24410
- );
24411
- if (executable === null) {
24412
- throw new Error("The managed Agent executable is unavailable");
24413
- }
24414
- return executable;
24415
- };
24416
- recoveryCommand = () => `npm install -g --omit=optional ${this.adapterPackage}@${this.adapterVersion}`;
24417
- supportsInstallation = (platform, architecture) => (platform === "darwin" || platform === "linux") && (architecture === "arm64" || architecture === "x64");
24418
- verifyAcp = (_connection, _initialized, _defaultWorkspace, _signal) => Promise.resolve();
24419
- };
24420
- var BridgedAcpAgentDefinition = class extends LocalAgentSpecification {
24421
- };
24422
- var CodexAgentSpecification = class extends BridgedAcpAgentDefinition {
24423
- adapterEnvironmentVariable = "CODEX_PATH";
24424
- adapterOverrideVariable = "MOBIUS_CODEX_ACP_PATH";
24425
- adapterPackageDefinition = new ManagedNpmPackageDefinition(
24426
- "@agentclientprotocol/codex-acp",
24427
- "1.8.0",
24428
- "codex-acp"
24429
- );
24430
- agentExecutable = "codex";
24431
- agentOverrideVariable = "MOBIUS_CODEX_PATH";
24432
- id = "codex";
24433
- label = "Codex";
24434
- managedAdapterExecutablePath = [
24435
- "adapters",
24436
- "codex",
24437
- "1.8.0",
24438
- "node_modules",
24439
- "@agentclientprotocol",
24440
- "codex-acp",
24441
- "dist",
24442
- "index.js"
24443
- ];
24444
- managedAgentExecutablePath = ["agents", "codex", "bin", "codex"];
24445
- };
24446
- var ClaudeCodeAgentSpecification = class extends BridgedAcpAgentDefinition {
24447
- adapterEnvironmentVariable = "CLAUDE_CODE_EXECUTABLE";
24448
- adapterOverrideVariable = "MOBIUS_CLAUDE_ACP_PATH";
24449
- adapterPackageDefinition = new ManagedNpmPackageDefinition(
24450
- "@agentclientprotocol/claude-agent-acp",
24451
- "0.73.0",
24452
- "claude-agent-acp"
24453
- );
24454
- agentExecutable = "claude";
24455
- agentOverrideVariable = "MOBIUS_CLAUDE_PATH";
24456
- id = "claude";
24457
- label = "Claude Code";
24458
- managedAdapterExecutablePath = [
24459
- "adapters",
24460
- "claude",
24461
- "0.73.0",
24462
- "node_modules",
24463
- "@agentclientprotocol",
24464
- "claude-agent-acp",
24465
- "dist",
24466
- "index.js"
24467
- ];
24468
- managedAgentExecutablePath = [
24469
- "agents",
24470
- "claude",
24471
- "home",
24472
- ".local",
24473
- "bin",
24474
- "claude"
24475
- ];
24476
- };
25492
+ // src/agent-catalog/agents/pi-agent.ts
25493
+ var ACP_PROBE_TIMEOUT_MILLISECONDS2 = 3e4;
25494
+ var PROMPT_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
24477
25495
  var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
24478
- acpProbeTimeoutMilliseconds = PI_ACP_PROBE_TIMEOUT_MILLISECONDS;
25496
+ acpProbeTimeoutMilliseconds = ACP_PROBE_TIMEOUT_MILLISECONDS2;
24479
25497
  adapterEnvironmentVariable = "PI_ACP_PI_COMMAND";
24480
25498
  adapterOverrideVariable = "MOBIUS_PI_ACP_PATH";
24481
25499
  adapterPackageDefinition = PI_ACP_PACKAGE;
@@ -24505,11 +25523,16 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
24505
25523
  "bundle",
24506
25524
  "cli.js"
24507
25525
  ];
24508
- promptTimeoutMilliseconds = PI_PROMPT_TIMEOUT_MILLISECONDS;
24509
- resolveManagedAgent = async (stateDirectory, _platform) => await validateManagedNpmPackage(
24510
- join7(stateDirectory, "agents", this.id, PI_AGENT_PACKAGE.version),
24511
- PI_AGENT_PACKAGE
24512
- );
25526
+ promptTimeoutMilliseconds = PROMPT_TIMEOUT_MILLISECONDS;
25527
+ resolveManagedAgent = async (stateDirectory, _platform, signal) => {
25528
+ signal.throwIfAborted();
25529
+ const executable = await validateManagedNpmPackage(
25530
+ join10(stateDirectory, "agents", this.id, PI_AGENT_PACKAGE.version),
25531
+ PI_AGENT_PACKAGE
25532
+ );
25533
+ signal.throwIfAborted();
25534
+ return executable;
25535
+ };
24513
25536
  verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
24514
25537
  const capabilities = initialized.agentCapabilities ?? {};
24515
25538
  if (capabilities.loadSession !== true) {
@@ -24549,138 +25572,134 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
24549
25572
  }
24550
25573
  };
24551
25574
  };
25575
+
25576
+ // src/agent-catalog/agents/supported-agent-specifications.ts
24552
25577
  function supportedLocalAgentSpecifications() {
24553
25578
  return Object.freeze([
24554
25579
  new CodexAgentSpecification(),
24555
25580
  new ClaudeCodeAgentSpecification(),
24556
- new PiAgentSpecification()
25581
+ new PiAgentSpecification(),
25582
+ new DeepSeekHarnessAgentSpecification(),
25583
+ new OpenCodeAgentSpecification()
24557
25584
  ]);
24558
25585
  }
24559
- var AgentDiscovery = class {
24560
- specification;
24561
- constructor(specification) {
24562
- this.specification = specification;
24563
- }
24564
- };
24565
- var AvailableAgent = class extends AgentDiscovery {
24566
- agent;
24567
- status = "ready";
24568
- constructor(specification, agent) {
24569
- super(specification);
24570
- this.agent = agent;
24571
- }
24572
- };
24573
- var UnavailableAgent = class extends AgentDiscovery {
24574
- };
24575
- var MissingAdapter = class extends UnavailableAgent {
24576
- code = "adapter_not_found";
24577
- message = "ACP adapter not found";
24578
- status = "missing_adapter";
24579
- constructor(specification) {
24580
- super(specification);
24581
- }
24582
- };
24583
- var MissingAgent = class extends UnavailableAgent {
24584
- code = "agent_not_found";
24585
- message = "Agent executable not found";
24586
- status = "missing_agent";
24587
- constructor(specification) {
24588
- super(specification);
24589
- }
24590
- };
24591
- var ProbeFailed = class extends UnavailableAgent {
25586
+
25587
+ // src/agent-catalog/acp-readiness-probe.ts
25588
+ import { spawn as spawn3 } from "node:child_process";
25589
+ import {
25590
+ methods as methods4,
25591
+ ndJsonStream as ndJsonStream2,
25592
+ PROTOCOL_VERSION as PROTOCOL_VERSION2,
25593
+ RequestError as RequestError2
25594
+ } from "@agentclientprotocol/sdk";
25595
+
25596
+ // src/agent-catalog/executable-discovery.ts
25597
+ import { isAbsolute as isAbsolute4, join as join12 } from "node:path";
25598
+
25599
+ // src/agent-installation/managed-adapter-installer.ts
25600
+ import { join as join11 } from "node:path";
25601
+ var ManagedAdapterInstallError = class extends Error {
24592
25602
  code;
24593
- message;
24594
- status = "probe_failed";
24595
- constructor(specification, code, message) {
24596
- super(specification);
25603
+ constructor(code, message, options = {}) {
25604
+ super(message, options);
24597
25605
  this.code = code;
24598
- this.message = message;
24599
- }
24600
- };
24601
- var IncompatibleAdapter = class extends UnavailableAgent {
24602
- code = "acp_incompatible";
24603
- message = "ACP adapter is incompatible";
24604
- status = "incompatible_adapter";
24605
- constructor(specification) {
24606
- super(specification);
25606
+ this.name = "ManagedAdapterInstallError";
24607
25607
  }
24608
25608
  };
24609
- var AuthenticationRequiredAgent = class extends UnavailableAgent {
24610
- code = "authentication_required";
24611
- message = "Agent authentication is required";
24612
- status = "authentication_required";
24613
- constructor(specification) {
24614
- super(specification);
25609
+ function translateError(error61) {
25610
+ if (error61 instanceof ManagedAdapterInstallError) {
25611
+ return error61;
24615
25612
  }
24616
- };
24617
- var LocalAgentInventory = class {
24618
- available;
24619
- discoveries;
24620
- installable;
24621
- unavailable;
24622
- constructor(discoveries, grantedAgents = /* @__PURE__ */ new Set(), platform = process.platform, architecture = process.arch) {
24623
- const available = [];
24624
- const unavailable = [];
24625
- for (const discovery of discoveries) {
24626
- if (discovery instanceof AvailableAgent) {
24627
- available.push(discovery);
24628
- } else if (discovery instanceof UnavailableAgent) {
24629
- unavailable.push(discovery);
24630
- } else {
24631
- throw new Error("Unsupported Agent discovery outcome");
24632
- }
25613
+ if (error61 instanceof ManagedNpmPackageError) {
25614
+ if (error61.code === "package_manager_not_found") {
25615
+ return new ManagedAdapterInstallError(
25616
+ error61.code,
25617
+ "A supported npm executable is required to install the ACP adapter",
25618
+ { cause: error61 }
25619
+ );
24633
25620
  }
24634
- this.available = Object.freeze(available);
24635
- this.discoveries = Object.freeze([...discoveries]);
24636
- this.installable = Object.freeze(
24637
- unavailable.filter(
24638
- (discovery) => !(discovery instanceof AuthenticationRequiredAgent) && discovery.specification.supportsInstallation(
24639
- platform,
24640
- architecture
24641
- )
24642
- ).map(
24643
- (discovery) => new InstallableAgentDefinition(
24644
- discovery.specification.id,
24645
- discovery.specification.label,
24646
- !grantedAgents.has(discovery.specification.id)
24647
- )
24648
- )
25621
+ if (error61.code === "managed_package_verification_failed") {
25622
+ return new ManagedAdapterInstallError(
25623
+ "adapter_verification_failed",
25624
+ "The managed adapter did not match its pinned artifact",
25625
+ { cause: error61 }
25626
+ );
25627
+ }
25628
+ if (error61.code === "managed_package_publish_failed") {
25629
+ return new ManagedAdapterInstallError(
25630
+ "adapter_publish_failed",
25631
+ "The managed adapter could not be published",
25632
+ { cause: error61 }
25633
+ );
25634
+ }
25635
+ }
25636
+ return new ManagedAdapterInstallError(
25637
+ "adapter_install_failed",
25638
+ "The pinned ACP adapter could not be installed",
25639
+ { cause: error61 }
25640
+ );
25641
+ }
25642
+ async function validateManagedAdapter(root, specification) {
25643
+ try {
25644
+ return await validateManagedNpmPackage(
25645
+ root,
25646
+ specification.adapterPackageDefinition
24649
25647
  );
24650
- this.unavailable = Object.freeze(unavailable);
25648
+ } catch (error61) {
25649
+ throw translateError(error61);
24651
25650
  }
24652
- readyAgents = () => this.available.map((discovery) => discovery.agent);
24653
- };
24654
- var AgentProbeError = class extends Error {
24655
- code;
24656
- constructor(code, message, options = {}) {
24657
- super(message, options);
24658
- this.code = code;
24659
- this.name = "AgentProbeError";
25651
+ }
25652
+ var ManagedAdapterInstaller = class {
25653
+ #environment;
25654
+ #npmInstaller;
25655
+ #stateDirectory;
25656
+ constructor(options, npmInstaller = new ManagedNpmPackageInstaller()) {
25657
+ this.#environment = options.environment;
25658
+ this.#npmInstaller = npmInstaller;
25659
+ this.#stateDirectory = options.stateDirectory;
24660
25660
  }
25661
+ install = async (specification, signal) => {
25662
+ const root = join11(
25663
+ this.#stateDirectory,
25664
+ "adapters",
25665
+ specification.id,
25666
+ specification.adapterVersion
25667
+ );
25668
+ try {
25669
+ return await this.#npmInstaller.install(
25670
+ root,
25671
+ specification.adapterPackageDefinition,
25672
+ this.#environment,
25673
+ signal
25674
+ );
25675
+ } catch (error61) {
25676
+ if (signal.aborted) {
25677
+ signal.throwIfAborted();
25678
+ }
25679
+ throw translateError(error61);
25680
+ }
25681
+ };
24661
25682
  };
24662
- var DiscoveryAcpHandler = class {
24663
- onElicitation = (_request, _signal) => Promise.reject(new Error("ACP probe does not accept elicitations"));
24664
- onElicitationComplete = (_notification) => Promise.resolve();
24665
- onPermission = (_request, _signal) => Promise.reject(new Error("ACP probe does not grant permissions"));
24666
- onUpdate = (_notification) => Promise.resolve();
24667
- };
24668
- async function resolveManagedExecutable(specification, options) {
25683
+
25684
+ // src/agent-catalog/executable-discovery.ts
25685
+ async function resolveManagedExecutable(specification, context) {
24669
25686
  try {
24670
25687
  return await specification.resolveManagedAgent(
24671
- readStateDirectory(options.environment),
24672
- options.platform ?? process.platform
25688
+ readStateDirectory(context.environment),
25689
+ context.platform ?? process.platform,
25690
+ context.signal
24673
25691
  );
24674
25692
  } catch {
25693
+ context.signal.throwIfAborted();
24675
25694
  return null;
24676
25695
  }
24677
25696
  }
24678
- async function resolveManagedAdapterExecutable(specification, options) {
25697
+ async function resolveManagedAdapterExecutable(specification, context) {
24679
25698
  let managed;
24680
25699
  try {
24681
25700
  managed = await validateManagedAdapter(
24682
- join7(
24683
- readStateDirectory(options.environment),
25701
+ join12(
25702
+ readStateDirectory(context.environment),
24684
25703
  "adapters",
24685
25704
  specification.id,
24686
25705
  specification.adapterVersion
@@ -24692,19 +25711,19 @@ async function resolveManagedAdapterExecutable(specification, options) {
24692
25711
  }
24693
25712
  return managed;
24694
25713
  }
24695
- async function resolveSpecificationExecutables(executableName, overrideVariable, resolveManaged, options) {
24696
- const override = options.environment[overrideVariable];
25714
+ async function resolveSpecificationExecutables(executableName, overrideVariable, resolveManaged, context) {
25715
+ const override = context.environment[overrideVariable];
24697
25716
  if (override !== void 0) {
24698
- if (override.length === 0 || !isAbsolute2(override)) {
25717
+ if (override.length === 0 || !isAbsolute4(override)) {
24699
25718
  return [];
24700
25719
  }
24701
- const executable = await resolveExecutablePath(override, options.platform);
25720
+ const executable = await resolveExecutablePath(override, context.platform);
24702
25721
  return executable === null ? [] : [executable];
24703
25722
  }
24704
25723
  const external = await findExecutableOnPath(
24705
25724
  executableName,
24706
- options.environment,
24707
- options.platform
25725
+ context.environment,
25726
+ context.platform
24708
25727
  );
24709
25728
  const managed = await resolveManaged();
24710
25729
  if (external === null) {
@@ -24715,41 +25734,47 @@ async function resolveSpecificationExecutables(executableName, overrideVariable,
24715
25734
  }
24716
25735
  return [external, managed];
24717
25736
  }
24718
- async function resolveAgentExecutables(specification, options) {
25737
+ async function resolveAgentExecutables(specification, context) {
24719
25738
  return await resolveSpecificationExecutables(
24720
25739
  specification.agentExecutable,
24721
25740
  specification.agentOverrideVariable,
24722
- async () => await resolveManagedExecutable(specification, options),
24723
- options
25741
+ async () => await resolveManagedExecutable(specification, context),
25742
+ context
24724
25743
  );
24725
25744
  }
24726
- async function resolveAdapterExecutables(specification, options) {
25745
+ async function resolveAdapterExecutables(specification, context) {
25746
+ if (specification instanceof DirectAcpAgentDefinition) {
25747
+ return await resolveAgentExecutables(specification, context);
25748
+ }
25749
+ if (!(specification instanceof BridgedAcpAgentDefinition)) {
25750
+ throw new Error("Unsupported local Agent execution topology");
25751
+ }
24727
25752
  return await resolveSpecificationExecutables(
24728
25753
  specification.adapterExecutable,
24729
25754
  specification.adapterOverrideVariable,
24730
- async () => await resolveManagedAdapterExecutable(specification, options),
24731
- options
25755
+ async () => await resolveManagedAdapterExecutable(specification, context),
25756
+ context
24732
25757
  );
24733
25758
  }
24734
- async function resolveAgentExecutable(specification, options) {
24735
- const executables = await resolveAgentExecutables(specification, options);
25759
+ async function resolveAgentExecutable(specification, context) {
25760
+ const executables = await resolveAgentExecutables(specification, context);
24736
25761
  return executables[0] ?? null;
24737
25762
  }
24738
- async function resolveAdapterExecutable(specification, options) {
24739
- const executables = await resolveAdapterExecutables(specification, options);
25763
+ async function resolveAdapterExecutable(specification, context) {
25764
+ const executables = await resolveAdapterExecutables(specification, context);
24740
25765
  return executables[0] ?? null;
24741
25766
  }
24742
25767
  function normalizedVersion(output2) {
24743
25768
  return output2.trim().split(/\r?\n/, 1)[0]?.trim().slice(0, 128) ?? "";
24744
25769
  }
24745
- async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal) {
25770
+ async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal, timeoutMilliseconds) {
24746
25771
  const result = await runBoundedProcess({
24747
25772
  arguments: arguments_,
24748
25773
  command: executable.path,
24749
25774
  cwd: defaultWorkspace,
24750
25775
  environment,
24751
25776
  signal,
24752
- timeoutMilliseconds: VERSION_PROBE_TIMEOUT_MILLISECONDS
25777
+ timeoutMilliseconds
24753
25778
  });
24754
25779
  const version2 = normalizedVersion(result.stdout || result.stderr);
24755
25780
  if (version2.length === 0) {
@@ -24768,63 +25793,73 @@ var VerifiedAgentExecutable = class {
24768
25793
  this.version = version2;
24769
25794
  }
24770
25795
  };
24771
- async function findVerifiedAgentExecutable(specification, options) {
24772
- const executables = await resolveAgentExecutables(specification, options);
25796
+ async function findVerifiedAgentExecutable(specification, context) {
25797
+ const executables = await resolveAgentExecutables(specification, context);
24773
25798
  for (const executable of executables) {
24774
25799
  try {
24775
25800
  const version2 = await probeVersion(
24776
25801
  executable,
24777
25802
  specification.agentVersionArguments,
24778
- options.environment,
24779
- options.defaultWorkspace,
24780
- options.signal
25803
+ context.environment,
25804
+ context.defaultWorkspace,
25805
+ context.signal,
25806
+ specification.versionProbeTimeoutMilliseconds
24781
25807
  );
24782
25808
  return new VerifiedAgentExecutable(executable, version2);
24783
25809
  } catch {
24784
- if (options.signal.aborted) {
24785
- options.signal.throwIfAborted();
25810
+ if (context.signal.aborted) {
25811
+ context.signal.throwIfAborted();
24786
25812
  }
24787
25813
  }
24788
25814
  }
24789
25815
  return null;
24790
25816
  }
25817
+
25818
+ // src/agent-catalog/acp-readiness-probe.ts
25819
+ var ACP_OUTPUT_LIMIT_BYTES = 1024 * 1024;
25820
+ var DiscoveryAcpHandler = class {
25821
+ onElicitation = (_request, _signal) => Promise.reject(new Error("ACP probe does not accept elicitations"));
25822
+ onElicitationComplete = (_notification) => Promise.resolve();
25823
+ onPermission = (_request, _signal) => Promise.reject(new Error("ACP probe does not grant permissions"));
25824
+ onUpdate = (_notification) => Promise.resolve();
25825
+ };
24791
25826
  function readableAcpStream(input2) {
24792
25827
  let byteLength = 0;
24793
- let open6 = true;
25828
+ let open7 = true;
24794
25829
  return new ReadableStream({
24795
25830
  start(controller) {
24796
25831
  input2.on("data", (chunk) => {
24797
- if (!open6) {
25832
+ if (!open7) {
24798
25833
  return;
24799
25834
  }
24800
25835
  if (!(chunk instanceof Uint8Array)) {
24801
- open6 = false;
25836
+ open7 = false;
24802
25837
  controller.error(new Error("ACP adapter produced invalid output"));
24803
25838
  return;
24804
25839
  }
24805
25840
  byteLength += chunk.byteLength;
24806
25841
  if (byteLength > ACP_OUTPUT_LIMIT_BYTES) {
24807
- open6 = false;
25842
+ open7 = false;
24808
25843
  controller.error(new Error("ACP adapter output limit exceeded"));
24809
25844
  return;
24810
25845
  }
24811
25846
  controller.enqueue(new Uint8Array(chunk));
24812
25847
  });
24813
25848
  input2.once("end", () => {
24814
- if (open6) {
24815
- open6 = false;
25849
+ if (open7) {
25850
+ open7 = false;
24816
25851
  controller.close();
24817
25852
  }
24818
25853
  });
24819
25854
  input2.once("error", (error61) => {
24820
- if (open6) {
24821
- open6 = false;
25855
+ if (open7) {
25856
+ open7 = false;
24822
25857
  controller.error(error61);
24823
25858
  }
24824
25859
  });
24825
25860
  },
24826
25861
  cancel() {
24827
- open6 = false;
25862
+ open7 = false;
24828
25863
  }
24829
25864
  });
24830
25865
  }
@@ -24843,7 +25878,7 @@ function writableAcpStream(output2) {
24843
25878
  }
24844
25879
  });
24845
25880
  }
24846
- async function probeAcp(specification, agent, environment, defaultWorkspace, signal) {
25881
+ async function probeAcpReadiness(specification, agent, environment, defaultWorkspace, signal) {
24847
25882
  signal.throwIfAborted();
24848
25883
  const controller = new AbortController();
24849
25884
  let timedOut = false;
@@ -24887,13 +25922,13 @@ async function probeAcp(specification, agent, environment, defaultWorkspace, sig
24887
25922
  }
24888
25923
  };
24889
25924
  stderr.on("data", consumeStderr);
24890
- const connection = createAcpClient(new DiscoveryAcpHandler()).connect(
24891
- ndJsonStream2(writableAcpStream(stdin), readableAcpStream(stdout))
24892
- );
25925
+ const connection = createAcpClient(
25926
+ new DiscoveryAcpHandler()
25927
+ ).connect(ndJsonStream2(writableAcpStream(stdin), readableAcpStream(stdout)));
24893
25928
  try {
24894
25929
  const initialized = await Promise.race([
24895
25930
  connection.agent.request(
24896
- methods3.agent.initialize,
25931
+ methods4.agent.initialize,
24897
25932
  {
24898
25933
  clientCapabilities: {},
24899
25934
  clientInfo: { name: "mobius", version: "0.0.3" },
@@ -24930,7 +25965,7 @@ async function probeAcp(specification, agent, environment, defaultWorkspace, sig
24930
25965
  if (error61 instanceof AgentProbeError) {
24931
25966
  throw error61;
24932
25967
  }
24933
- if (error61 instanceof RequestError && error61.code === -32e3 && specification.authenticationCommand().length > 0) {
25968
+ if (error61 instanceof RequestError2 && error61.code === -32e3 && specification.authenticationCommand().length > 0) {
24934
25969
  throw new AgentProbeError(
24935
25970
  "authentication_required",
24936
25971
  "Agent authentication is required",
@@ -24951,6 +25986,8 @@ async function probeAcp(specification, agent, environment, defaultWorkspace, sig
24951
25986
  await stopProcessTree(child);
24952
25987
  }
24953
25988
  }
25989
+
25990
+ // src/agent-catalog/discover-agent.ts
24954
25991
  function probeFailure(specification, executableKind, error61) {
24955
25992
  if (error61 instanceof AgentProbeError) {
24956
25993
  if (error61.code === "authentication_required") {
@@ -24972,12 +26009,15 @@ function probeFailure(specification, executableKind, error61) {
24972
26009
  `${executableKind === "agent" ? "Agent" : "Adapter"} probe failed`
24973
26010
  );
24974
26011
  }
24975
- async function discoverSpecification(specification, options) {
24976
- options.signal.throwIfAborted();
26012
+ async function discoverAgent(specification, context) {
26013
+ context.signal.throwIfAborted();
24977
26014
  const [adapters, agents] = await Promise.all([
24978
- resolveAdapterExecutables(specification, options),
24979
- resolveAgentExecutables(specification, options)
26015
+ resolveAdapterExecutables(specification, context),
26016
+ resolveAgentExecutables(specification, context)
24980
26017
  ]);
26018
+ if (specification instanceof DirectAcpAgentDefinition && agents.length === 0) {
26019
+ return new MissingAgent(specification);
26020
+ }
24981
26021
  if (adapters.length === 0) {
24982
26022
  return new MissingAdapter(specification);
24983
26023
  }
@@ -24991,35 +26031,45 @@ async function discoverSpecification(specification, options) {
24991
26031
  agentVersion = await probeVersion(
24992
26032
  agent,
24993
26033
  specification.agentVersionArguments,
24994
- options.environment,
24995
- options.defaultWorkspace,
24996
- options.signal
26034
+ context.environment,
26035
+ context.defaultWorkspace,
26036
+ context.signal,
26037
+ specification.versionProbeTimeoutMilliseconds
24997
26038
  );
24998
26039
  } catch (error61) {
24999
- if (options.signal.aborted) {
25000
- options.signal.throwIfAborted();
26040
+ if (context.signal.aborted) {
26041
+ context.signal.throwIfAborted();
25001
26042
  }
25002
26043
  lastFailure = probeFailure(specification, "agent", error61);
25003
26044
  continue;
25004
26045
  }
25005
26046
  for (const adapter of adapters) {
26047
+ if (specification instanceof DirectAcpAgentDefinition && adapter.path !== agent.path) {
26048
+ continue;
26049
+ }
25006
26050
  let adapterVersion = "";
26051
+ let launchEnvironment;
25007
26052
  try {
26053
+ launchEnvironment = await specification.createLaunchEnvironment(
26054
+ agent,
26055
+ context
26056
+ );
25008
26057
  if (specification.adapterVersionArguments.length > 0) {
25009
26058
  adapterVersion = await probeVersion(
25010
26059
  adapter,
25011
26060
  specification.adapterVersionArguments,
25012
26061
  {
25013
- ...options.environment,
25014
- [specification.adapterEnvironmentVariable]: agent.path
26062
+ ...context.environment,
26063
+ ...launchEnvironment
25015
26064
  },
25016
- options.defaultWorkspace,
25017
- options.signal
26065
+ context.defaultWorkspace,
26066
+ context.signal,
26067
+ specification.versionProbeTimeoutMilliseconds
25018
26068
  );
25019
26069
  }
25020
26070
  } catch (error61) {
25021
- if (options.signal.aborted) {
25022
- options.signal.throwIfAborted();
26071
+ if (context.signal.aborted) {
26072
+ context.signal.throwIfAborted();
25023
26073
  }
25024
26074
  lastFailure = probeFailure(specification, "adapter", error61);
25025
26075
  continue;
@@ -25028,8 +26078,8 @@ async function discoverSpecification(specification, options) {
25028
26078
  specification.id,
25029
26079
  specification.label,
25030
26080
  adapter.path,
25031
- [],
25032
- { [specification.adapterEnvironmentVariable]: agent.path },
26081
+ specification.launchArguments,
26082
+ launchEnvironment,
25033
26083
  adapterVersion,
25034
26084
  agentVersion,
25035
26085
  adapter.identity,
@@ -25037,12 +26087,12 @@ async function discoverSpecification(specification, options) {
25037
26087
  specification.promptTimeoutMilliseconds
25038
26088
  );
25039
26089
  try {
25040
- const acpVersion = await probeAcp(
26090
+ const acpVersion = await probeAcpReadiness(
25041
26091
  specification,
25042
26092
  definition,
25043
- options.environment,
25044
- options.defaultWorkspace,
25045
- options.signal
26093
+ context.environment,
26094
+ context.defaultWorkspace,
26095
+ context.signal
25046
26096
  );
25047
26097
  const verifiedAdapterVersion = adapterVersion.length > 0 ? adapterVersion : acpVersion;
25048
26098
  if (verifiedAdapterVersion.length === 0) {
@@ -25057,8 +26107,8 @@ async function discoverSpecification(specification, options) {
25057
26107
  specification.id,
25058
26108
  specification.label,
25059
26109
  adapter.path,
25060
- [],
25061
- { [specification.adapterEnvironmentVariable]: agent.path },
26110
+ specification.launchArguments,
26111
+ launchEnvironment,
25062
26112
  verifiedAdapterVersion,
25063
26113
  agentVersion,
25064
26114
  adapter.identity,
@@ -25067,20 +26117,26 @@ async function discoverSpecification(specification, options) {
25067
26117
  )
25068
26118
  );
25069
26119
  } catch (error61) {
25070
- if (options.signal.aborted) {
25071
- options.signal.throwIfAborted();
26120
+ if (context.signal.aborted) {
26121
+ context.signal.throwIfAborted();
25072
26122
  }
25073
- lastFailure = probeFailure(specification, "adapter", error61);
26123
+ const failure = probeFailure(specification, "adapter", error61);
26124
+ if (failure instanceof AuthenticationRequiredAgent) {
26125
+ return failure;
26126
+ }
26127
+ lastFailure = failure;
25074
26128
  }
25075
26129
  }
25076
26130
  }
25077
26131
  return lastFailure ?? new IncompatibleAdapter(specification);
25078
26132
  }
26133
+
26134
+ // src/agent-catalog/discover-local-agents.ts
25079
26135
  async function discoverLocalAgentInventory(options) {
25080
26136
  const specifications = options.specifications ?? supportedLocalAgentSpecifications();
25081
26137
  const discoveries = await Promise.all(
25082
26138
  specifications.map(
25083
- async (specification) => await discoverSpecification(specification, options)
26139
+ async (specification) => await discoverAgent(specification, options)
25084
26140
  )
25085
26141
  );
25086
26142
  let grantedAgents = /* @__PURE__ */ new Set();
@@ -25098,10 +26154,6 @@ async function discoverLocalAgentInventory(options) {
25098
26154
  );
25099
26155
  }
25100
26156
 
25101
- // src/network/environment-proxy.ts
25102
- import { EnvHttpProxyAgent } from "undici";
25103
- var environmentProxyDispatcher = new EnvHttpProxyAgent();
25104
-
25105
26157
  // src/pairing/pair-local-machine.ts
25106
26158
  var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
25107
26159
  var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
@@ -25127,7 +26179,7 @@ var PairingClientError = class extends Error {
25127
26179
  this.name = "PairingClientError";
25128
26180
  }
25129
26181
  };
25130
- function isRecord6(value) {
26182
+ function isRecord7(value) {
25131
26183
  return typeof value === "object" && value !== null && !Array.isArray(value);
25132
26184
  }
25133
26185
  function hasExactKeys(value, expectedKeys) {
@@ -25240,9 +26292,9 @@ function parseChannelArgument(arguments_) {
25240
26292
  async function resolveDefaultWorkspace(path2) {
25241
26293
  const requestedWorkspace = resolve3(path2);
25242
26294
  try {
25243
- await mkdir2(requestedWorkspace, { recursive: true, mode: 448 });
25244
- const defaultWorkspace = await realpath3(requestedWorkspace);
25245
- const metadata = await stat3(defaultWorkspace);
26295
+ await mkdir3(requestedWorkspace, { recursive: true, mode: 448 });
26296
+ const defaultWorkspace = await realpath5(requestedWorkspace);
26297
+ const metadata = await stat5(defaultWorkspace);
25246
26298
  if (!metadata.isDirectory()) {
25247
26299
  throw new PairingClientError(
25248
26300
  "invalid_workspace",
@@ -25280,9 +26332,9 @@ async function readJsonResponse(response) {
25280
26332
  }
25281
26333
  }
25282
26334
  function readRelayError(value) {
25283
- if (isRecord6(value)) {
26335
+ if (isRecord7(value)) {
25284
26336
  const error61 = value["error"];
25285
- if (isRecord6(error61)) {
26337
+ if (isRecord7(error61)) {
25286
26338
  const code = error61["code"];
25287
26339
  const message = error61["message"];
25288
26340
  if (typeof code === "string" && typeof message === "string") {
@@ -25296,7 +26348,7 @@ function readRelayError(value) {
25296
26348
  );
25297
26349
  }
25298
26350
  function decodeClaimResponse(value) {
25299
- if (!isRecord6(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
26351
+ if (!isRecord7(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
25300
26352
  throw new PairingClientError(
25301
26353
  "invalid_relay_response",
25302
26354
  "The relay returned an invalid pairing response"
@@ -25321,7 +26373,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
25321
26373
  const endpoint = new URL("/api/pairings/claim", options.relayOrigin);
25322
26374
  let response;
25323
26375
  try {
25324
- response = await fetch(endpoint, {
26376
+ response = await fetch2(endpoint, {
25325
26377
  body: JSON.stringify({
25326
26378
  agents,
25327
26379
  installableAgents: installableAgents.map((agent) => ({
@@ -25355,14 +26407,14 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
25355
26407
  return decodeClaimResponse(value);
25356
26408
  }
25357
26409
  async function persistConnection(channelId, relayOrigin, daemonToken, defaultWorkspace) {
25358
- const connectionsDirectory = join8(readStateDirectory(), "connections");
25359
- await mkdir2(connectionsDirectory, { mode: 448, recursive: true });
25360
- const connectionPath = join8(connectionsDirectory, `${channelId}.json`);
25361
- const temporaryPath = join8(
26410
+ const connectionsDirectory = join13(readStateDirectory(), "connections");
26411
+ await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
26412
+ const connectionPath = join13(connectionsDirectory, `${channelId}.json`);
26413
+ const temporaryPath = join13(
25362
26414
  connectionsDirectory,
25363
26415
  `.${channelId}.${randomUUID()}.tmp`
25364
26416
  );
25365
- await writeFile(
26417
+ await writeFile2(
25366
26418
  temporaryPath,
25367
26419
  `${JSON.stringify(
25368
26420
  {
@@ -25377,11 +26429,11 @@ async function persistConnection(channelId, relayOrigin, daemonToken, defaultWor
25377
26429
  `,
25378
26430
  { flag: "wx", mode: 384 }
25379
26431
  );
25380
- await rename2(temporaryPath, connectionPath);
26432
+ await rename3(temporaryPath, connectionPath);
25381
26433
  return connectionPath;
25382
26434
  }
25383
26435
  function decodeSavedConnection(value, expectedChannelId) {
25384
- if (!isRecord6(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
26436
+ if (!isRecord7(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
25385
26437
  throw new PairingClientError(
25386
26438
  "invalid_connection",
25387
26439
  "The saved connection is invalid"
@@ -25405,13 +26457,13 @@ function decodeSavedConnection(value, expectedChannelId) {
25405
26457
  };
25406
26458
  }
25407
26459
  async function readSavedConnection(channelId) {
25408
- const connectionPath = join8(
26460
+ const connectionPath = join13(
25409
26461
  readStateDirectory(),
25410
26462
  "connections",
25411
26463
  `${channelId}.json`
25412
26464
  );
25413
26465
  let encoded = "";
25414
- const handle = await open4(connectionPath, "r");
26466
+ const handle = await open6(connectionPath, "r");
25415
26467
  try {
25416
26468
  const metadata = await handle.stat();
25417
26469
  if (!metadata.isFile() || metadata.size > MAX_CONNECTION_FILE_LENGTH) {
@@ -25460,7 +26512,7 @@ function buildPairedDaemon(connection, connectionPath, inventory) {
25460
26512
  );
25461
26513
  relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
25462
26514
  relayUrl.searchParams.set("token", connection.daemonToken);
25463
- const auditDatabasePath = join8(
26515
+ const auditDatabasePath = join13(
25464
26516
  readStateDirectory(),
25465
26517
  "audit",
25466
26518
  `${connection.channelId}.sqlite`
@@ -25519,7 +26571,7 @@ async function pairLocalMachine(arguments_, signal = new AbortController().signa
25519
26571
  }
25520
26572
  async function resumeLocalMachine(arguments_, signal = new AbortController().signal) {
25521
26573
  const channelId = parseChannelArgument(arguments_);
25522
- const connectionPath = join8(
26574
+ const connectionPath = join13(
25523
26575
  readStateDirectory(),
25524
26576
  "connections",
25525
26577
  `${channelId}.json`
@@ -25538,7 +26590,7 @@ import { basename as basename3 } from "node:path";
25538
26590
  import { WebSocket as WebSocket2 } from "undici";
25539
26591
 
25540
26592
  // src/agent-catalog/publish-agent-catalog.ts
25541
- import { fetch as fetch2 } from "undici";
26593
+ import { fetch as fetch3 } from "undici";
25542
26594
  var CATALOG_UPDATE_TIMEOUT_MILLISECONDS = 2e4;
25543
26595
  var AgentCatalogPublishError = class extends Error {
25544
26596
  code = "agent_catalog_update_failed";
@@ -25565,7 +26617,7 @@ async function publishAgentCatalog(config2, signal) {
25565
26617
  let response;
25566
26618
  const catalog = config2.catalog.read();
25567
26619
  try {
25568
- response = await fetch2(catalogEndpoint(config2.relayUrl), {
26620
+ response = await fetch3(catalogEndpoint(config2.relayUrl), {
25569
26621
  body: JSON.stringify({
25570
26622
  agents: catalog.agents.map((agent) => ({
25571
26623
  id: agent.id,
@@ -25971,7 +27023,7 @@ var InstalledAutomaticAdapter = class {
25971
27023
  }
25972
27024
  };
25973
27025
  function shouldProvisionAdapter(unavailable, options) {
25974
- return AUTOMATIC_ADAPTER_FAILURE_CODES.has(unavailable.code) && options.environment[unavailable.specification.adapterOverrideVariable] === void 0 && unavailable.specification.supportsInstallation(
27026
+ return unavailable.specification instanceof BridgedAcpAgentDefinition && AUTOMATIC_ADAPTER_FAILURE_CODES.has(unavailable.code) && options.environment[unavailable.specification.adapterOverrideVariable] === void 0 && unavailable.specification.supportsInstallation(
25975
27027
  options.platform ?? process.platform,
25976
27028
  options.architecture ?? process.arch
25977
27029
  );
@@ -26015,6 +27067,10 @@ var AutomaticAdapterProvisioner = class {
26015
27067
  for (const unavailable of candidates) {
26016
27068
  signal.throwIfAborted();
26017
27069
  const specification = unavailable.specification;
27070
+ if (!(specification instanceof BridgedAcpAgentDefinition)) {
27071
+ attempts.push(null);
27072
+ continue;
27073
+ }
26018
27074
  const verifiedAgent = await findVerifiedAgentExecutable(
26019
27075
  specification,
26020
27076
  discoveryOptions(
@@ -26076,270 +27132,77 @@ var AutomaticAdapterProvisioner = class {
26076
27132
  `
26077
27133
  );
26078
27134
  attempts.push(null);
26079
- }
26080
- }
26081
- signal.throwIfAborted();
26082
- const installed = attempts.filter(
26083
- (attempt) => attempt !== null
26084
- );
26085
- if (installed.length > 0) {
26086
- const verificationEnvironment = {
26087
- ...this.#options.environment
26088
- };
26089
- for (const attempt of installed) {
26090
- verificationEnvironment[attempt.specification.adapterOverrideVariable] = attempt.executable.path;
26091
- }
26092
- inventory = await discoverLocalAgentInventory(
26093
- discoveryOptions(
26094
- this.#options,
26095
- verificationEnvironment,
26096
- signal,
26097
- this.#specifications
26098
- )
26099
- );
26100
- }
26101
- this.#options.catalog.transition(
26102
- inventory.readyAgents(),
26103
- inventory.installable
26104
- );
26105
- for (const attempt of installed) {
26106
- const available = inventory.available.find(
26107
- (candidate) => candidate instanceof AvailableAgent && candidate.specification.id === attempt.specification.id
26108
- );
26109
- if (available === void 0) {
26110
- const unavailable = inventory.unavailable.find(
26111
- (candidate) => candidate.specification.id === attempt.specification.id
26112
- );
26113
- this.#options.audit.record(
26114
- "agent_adapter_auto_install_verification_failed",
26115
- attempt.requestId,
26116
- attempt.specification.id,
26117
- { code: unavailable?.code ?? "agent_verification_failed" }
26118
- );
26119
- continue;
26120
- }
26121
- this.#options.audit.record(
26122
- "agent_adapter_auto_install_verified",
26123
- attempt.requestId,
26124
- attempt.specification.id,
26125
- {
26126
- adapterVersion: available.agent.adapterVersion,
26127
- agentVersion: available.agent.agentVersion
26128
- }
26129
- );
26130
- process.stdout.write(
26131
- `${attempt.specification.label} ACP integration is ready.
26132
- `
26133
- );
26134
- }
26135
- return inventory;
26136
- };
26137
- };
26138
-
26139
- // src/agent-installation/fixed-installation-executor.ts
26140
- import { realpathSync as realpathSync2, statSync as statSync2 } from "node:fs";
26141
- import { resolve as resolve4 } from "node:path";
26142
-
26143
- // src/agent-installation/fixed-agent-install-recipes.ts
26144
- import { mkdir as mkdir3, mkdtemp as mkdtemp2, rm as rm2 } from "node:fs/promises";
26145
- import { join as join9 } from "node:path";
26146
-
26147
- // src/agent-installation/verified-download.ts
26148
- import { createHash } from "node:crypto";
26149
- import { open as open5, unlink } from "node:fs/promises";
26150
- import { fetch as fetch3 } from "undici";
26151
- var MAX_REDIRECTS = 4;
26152
- var REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
26153
- var InstallerDownloadError = class extends Error {
26154
- code;
26155
- constructor(code, message, options = {}) {
26156
- super(message, options);
26157
- this.code = code;
26158
- this.name = "InstallerDownloadError";
26159
- }
26160
- };
26161
- var VerifiedDownload = class {
26162
- bytes;
26163
- sha256;
26164
- url;
26165
- constructor(url2, bytes, sha256) {
26166
- this.bytes = bytes;
26167
- this.sha256 = sha256;
26168
- this.url = url2;
26169
- }
26170
- };
26171
- var UndiciInstallerDownloadTransport = class {
26172
- get = async (url2, signal) => await fetch3(url2, {
26173
- dispatcher: environmentProxyDispatcher,
26174
- headers: {
26175
- accept: "text/plain, application/octet-stream;q=0.9",
26176
- "user-agent": "Mobius-Agent-Installer/0.0.3"
26177
- },
26178
- method: "GET",
26179
- redirect: "manual",
26180
- signal
26181
- });
26182
- };
26183
- function validateUrl(url2, allowedHosts) {
26184
- if (url2.protocol !== "https:" || url2.username.length > 0 || url2.password.length > 0 || url2.port.length > 0 || !allowedHosts.has(url2.hostname)) {
26185
- throw new InstallerDownloadError(
26186
- "installer_host_not_allowed",
26187
- "The installer download target is not allowed"
26188
- );
26189
- }
26190
- }
26191
- async function fetchInstaller(options, signal, transport) {
26192
- let url2 = new URL(options.url);
26193
- for (let redirectCount = 0; redirectCount <= MAX_REDIRECTS; redirectCount += 1) {
26194
- validateUrl(url2, options.allowedHosts);
26195
- const response = await transport.get(url2, signal);
26196
- if (!REDIRECT_STATUSES.has(response.status)) {
26197
- return { response, url: url2 };
26198
- }
26199
- await response.body?.cancel();
26200
- const location = response.headers.get("location");
26201
- if (location === null || redirectCount === MAX_REDIRECTS) {
26202
- throw new InstallerDownloadError(
26203
- "installer_redirect_invalid",
26204
- "The installer returned an invalid redirect"
26205
- );
26206
- }
26207
- let redirected;
26208
- try {
26209
- redirected = new URL(location, url2);
26210
- } catch (error61) {
26211
- throw new InstallerDownloadError(
26212
- "installer_redirect_invalid",
26213
- "The installer returned an invalid redirect",
26214
- { cause: error61 }
26215
- );
26216
- }
26217
- try {
26218
- validateUrl(redirected, options.allowedHosts);
26219
- } catch (error61) {
26220
- throw new InstallerDownloadError(
26221
- "installer_redirect_not_allowed",
26222
- "The installer redirect left the approved host allowlist",
26223
- { cause: error61 }
26224
- );
26225
- }
26226
- url2 = redirected;
26227
- }
26228
- throw new InstallerDownloadError(
26229
- "installer_redirect_invalid",
26230
- "The installer returned too many redirects"
26231
- );
26232
- }
26233
- async function writeCompleteChunk(handle, chunk) {
26234
- let offset = 0;
26235
- while (offset < chunk.byteLength) {
26236
- const written = await handle.write(
26237
- chunk,
26238
- offset,
26239
- chunk.byteLength - offset
27135
+ }
27136
+ }
27137
+ signal.throwIfAborted();
27138
+ const installed = attempts.filter(
27139
+ (attempt) => attempt !== null
26240
27140
  );
26241
- if (written.bytesWritten < 1) {
26242
- throw new InstallerDownloadError(
26243
- "installer_write_failed",
26244
- "The verified installer could not be stored"
27141
+ if (installed.length > 0) {
27142
+ const verificationEnvironment = {
27143
+ ...this.#options.environment
27144
+ };
27145
+ for (const attempt of installed) {
27146
+ verificationEnvironment[attempt.specification.adapterOverrideVariable] = attempt.executable.path;
27147
+ }
27148
+ inventory = await discoverLocalAgentInventory(
27149
+ discoveryOptions(
27150
+ this.#options,
27151
+ verificationEnvironment,
27152
+ signal,
27153
+ this.#specifications
27154
+ )
26245
27155
  );
26246
27156
  }
26247
- offset += written.bytesWritten;
26248
- }
26249
- }
26250
- async function downloadVerifiedFile(options, transport = new UndiciInstallerDownloadTransport()) {
26251
- options.signal.throwIfAborted();
26252
- const timeoutSignal = AbortSignal.timeout(options.timeoutMilliseconds);
26253
- const signal = AbortSignal.any([options.signal, timeoutSignal]);
26254
- let handle = null;
26255
- let responseBody = null;
26256
- try {
26257
- const fetched = await fetchInstaller(options, signal, transport);
26258
- responseBody = fetched.response.body;
26259
- if (!fetched.response.ok || fetched.response.body === null) {
26260
- throw new InstallerDownloadError(
26261
- "installer_download_failed",
26262
- "The approved installer could not be downloaded"
27157
+ this.#options.catalog.transition(
27158
+ inventory.readyAgents(),
27159
+ inventory.installable
27160
+ );
27161
+ for (const attempt of installed) {
27162
+ const available = inventory.available.find(
27163
+ (candidate) => candidate instanceof AvailableAgent && candidate.specification.id === attempt.specification.id
26263
27164
  );
26264
- }
26265
- const contentLength = fetched.response.headers.get("content-length");
26266
- if (contentLength !== null) {
26267
- const declaredLength = Number(contentLength);
26268
- if (!Number.isSafeInteger(declaredLength) || declaredLength < 1 || declaredLength > options.maximumBytes) {
26269
- throw new InstallerDownloadError(
26270
- "installer_size_invalid",
26271
- "The installer size is outside the approved limit"
27165
+ if (available === void 0) {
27166
+ const unavailable = inventory.unavailable.find(
27167
+ (candidate) => candidate.specification.id === attempt.specification.id
27168
+ );
27169
+ this.#options.audit.record(
27170
+ "agent_adapter_auto_install_verification_failed",
27171
+ attempt.requestId,
27172
+ attempt.specification.id,
27173
+ { code: unavailable?.code ?? "agent_verification_failed" }
26272
27174
  );
27175
+ continue;
26273
27176
  }
26274
- }
26275
- handle = await open5(options.destination, "wx", 384);
26276
- const digest = createHash("sha256");
26277
- const reader = fetched.response.body.getReader();
26278
- let bytes = 0;
26279
- try {
26280
- while (true) {
26281
- signal.throwIfAborted();
26282
- const chunk = await reader.read();
26283
- if (chunk.done) {
26284
- break;
26285
- }
26286
- bytes += chunk.value.byteLength;
26287
- if (bytes > options.maximumBytes) {
26288
- throw new InstallerDownloadError(
26289
- "installer_size_invalid",
26290
- "The installer exceeded the approved size limit"
26291
- );
27177
+ this.#options.audit.record(
27178
+ "agent_adapter_auto_install_verified",
27179
+ attempt.requestId,
27180
+ attempt.specification.id,
27181
+ {
27182
+ adapterVersion: available.agent.adapterVersion,
27183
+ agentVersion: available.agent.agentVersion
26292
27184
  }
26293
- digest.update(chunk.value);
26294
- await writeCompleteChunk(handle, chunk.value);
26295
- }
26296
- } finally {
26297
- await reader.cancel().catch(() => void 0);
26298
- reader.releaseLock();
26299
- }
26300
- if (bytes === 0) {
26301
- throw new InstallerDownloadError(
26302
- "installer_verification_failed",
26303
- "The downloaded installer is empty"
26304
27185
  );
26305
- }
26306
- await handle.sync();
26307
- await handle.close();
26308
- handle = null;
26309
- return new VerifiedDownload(fetched.url, bytes, digest.digest("hex"));
26310
- } catch (error61) {
26311
- if (handle !== null) {
26312
- await handle.close().catch(() => void 0);
26313
- }
26314
- await unlink(options.destination).catch(() => void 0);
26315
- if (options.signal.aborted) {
26316
- options.signal.throwIfAborted();
26317
- }
26318
- if (timeoutSignal.aborted) {
26319
- throw new InstallerDownloadError(
26320
- "installer_download_timeout",
26321
- "The installer download timed out",
26322
- { cause: error61 }
27186
+ process.stdout.write(
27187
+ `${attempt.specification.label} ACP integration is ready.
27188
+ `
26323
27189
  );
26324
27190
  }
26325
- if (error61 instanceof InstallerDownloadError) {
26326
- throw error61;
26327
- }
26328
- throw new InstallerDownloadError(
26329
- "installer_download_failed",
26330
- "The approved installer could not be downloaded",
26331
- { cause: error61 }
26332
- );
26333
- } finally {
26334
- await responseBody?.cancel().catch(() => void 0);
26335
- }
26336
- }
27191
+ return inventory;
27192
+ };
27193
+ };
27194
+
27195
+ // src/agent-installation/fixed-installation-executor.ts
27196
+ import { realpathSync as realpathSync2, statSync as statSync2 } from "node:fs";
27197
+ import { resolve as resolve4 } from "node:path";
26337
27198
 
26338
27199
  // src/agent-installation/fixed-agent-install-recipes.ts
27200
+ import { mkdir as mkdir4, mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
27201
+ import { join as join14 } from "node:path";
26339
27202
  var INSTALLER_DOWNLOAD_LIMIT_BYTES = 1024 * 1024;
26340
27203
  var INSTALLER_DOWNLOAD_TIMEOUT_MILLISECONDS = 6e4;
26341
27204
  var AGENT_INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
26342
- var MINIMAL_PATH = "/usr/bin:/bin";
27205
+ var MINIMAL_PATH2 = "/usr/bin:/bin";
26343
27206
  var FixedAgentInstallRecipe = class {
26344
27207
  assertSupportedPlatform = () => {
26345
27208
  if (process.platform !== "darwin" && process.platform !== "linux" || process.arch !== "arm64" && process.arch !== "x64") {
@@ -26366,22 +27229,22 @@ var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
26366
27229
  releaseChannel = "latest";
26367
27230
  install = async (options) => {
26368
27231
  this.assertSupportedPlatform();
26369
- const root = join9(options.stateDirectory, "agents", this.id);
26370
- const temporaryRoot = join9(options.stateDirectory, "temporary");
27232
+ const root = join14(options.stateDirectory, "agents", this.id);
27233
+ const temporaryRoot = join14(options.stateDirectory, "temporary");
26371
27234
  await Promise.all([
26372
- mkdir3(root, { mode: 448, recursive: true }),
26373
- mkdir3(temporaryRoot, { mode: 448, recursive: true })
27235
+ mkdir4(root, { mode: 448, recursive: true }),
27236
+ mkdir4(temporaryRoot, { mode: 448, recursive: true })
26374
27237
  ]);
26375
- const temporaryDirectory = await mkdtemp2(
26376
- join9(temporaryRoot, ".codex-install-")
27238
+ const temporaryDirectory = await mkdtemp3(
27239
+ join14(temporaryRoot, ".codex-install-")
26377
27240
  );
26378
- const installerPath = join9(temporaryDirectory, "install.sh");
26379
- const installDirectory = join9(root, "bin");
26380
- const codexHome = join9(root, "home");
27241
+ const installerPath = join14(temporaryDirectory, "install.sh");
27242
+ const installDirectory = join14(root, "bin");
27243
+ const codexHome = join14(root, "home");
26381
27244
  try {
26382
27245
  await Promise.all([
26383
- mkdir3(installDirectory, { mode: 448, recursive: true }),
26384
- mkdir3(codexHome, { mode: 448, recursive: true })
27246
+ mkdir4(installDirectory, { mode: 448, recursive: true }),
27247
+ mkdir4(codexHome, { mode: 448, recursive: true })
26385
27248
  ]);
26386
27249
  await options.report("downloading");
26387
27250
  const download = await downloadVerifiedFile({
@@ -26414,14 +27277,14 @@ var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
26414
27277
  CODEX_NON_INTERACTIVE: "1",
26415
27278
  CODEX_RELEASE: this.releaseChannel,
26416
27279
  HOME: codexHome,
26417
- PATH: MINIMAL_PATH
27280
+ PATH: MINIMAL_PATH2
26418
27281
  },
26419
27282
  outputLimitBytes: 64 * 1024,
26420
27283
  signal: options.signal,
26421
27284
  timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
26422
27285
  });
26423
27286
  return await this.requireInstalledExecutable(
26424
- join9(installDirectory, "codex")
27287
+ join14(installDirectory, "codex")
26425
27288
  );
26426
27289
  } catch (error61) {
26427
27290
  if (options.signal.aborted) {
@@ -26435,7 +27298,7 @@ var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
26435
27298
  "The fixed Codex installation recipe failed"
26436
27299
  );
26437
27300
  } finally {
26438
- await rm2(temporaryDirectory, { force: true, recursive: true });
27301
+ await rm3(temporaryDirectory, { force: true, recursive: true });
26439
27302
  }
26440
27303
  };
26441
27304
  };
@@ -26445,17 +27308,17 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
26445
27308
  releaseChannel = "stable";
26446
27309
  install = async (options) => {
26447
27310
  this.assertSupportedPlatform();
26448
- const root = join9(options.stateDirectory, "agents", this.id);
26449
- const managedHome = join9(root, "home");
26450
- const temporaryRoot = join9(options.stateDirectory, "temporary");
27311
+ const root = join14(options.stateDirectory, "agents", this.id);
27312
+ const managedHome = join14(root, "home");
27313
+ const temporaryRoot = join14(options.stateDirectory, "temporary");
26451
27314
  await Promise.all([
26452
- mkdir3(managedHome, { mode: 448, recursive: true }),
26453
- mkdir3(temporaryRoot, { mode: 448, recursive: true })
27315
+ mkdir4(managedHome, { mode: 448, recursive: true }),
27316
+ mkdir4(temporaryRoot, { mode: 448, recursive: true })
26454
27317
  ]);
26455
- const temporaryDirectory = await mkdtemp2(
26456
- join9(temporaryRoot, ".claude-install-")
27318
+ const temporaryDirectory = await mkdtemp3(
27319
+ join14(temporaryRoot, ".claude-install-")
26457
27320
  );
26458
- const installerPath = join9(temporaryDirectory, "install.sh");
27321
+ const installerPath = join14(temporaryDirectory, "install.sh");
26459
27322
  try {
26460
27323
  await options.report("downloading");
26461
27324
  const download = await downloadVerifiedFile({
@@ -26484,7 +27347,7 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
26484
27347
  cwd: temporaryDirectory,
26485
27348
  environment: {
26486
27349
  HOME: managedHome,
26487
- PATH: MINIMAL_PATH,
27350
+ PATH: MINIMAL_PATH2,
26488
27351
  SHELL: "/bin/bash"
26489
27352
  },
26490
27353
  outputLimitBytes: 64 * 1024,
@@ -26492,7 +27355,7 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
26492
27355
  timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
26493
27356
  });
26494
27357
  return await this.requireInstalledExecutable(
26495
- join9(managedHome, ".local", "bin", "claude")
27358
+ join14(managedHome, ".local", "bin", "claude")
26496
27359
  );
26497
27360
  } catch (error61) {
26498
27361
  if (options.signal.aborted) {
@@ -26506,7 +27369,7 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
26506
27369
  "The fixed Claude Code installation recipe failed"
26507
27370
  );
26508
27371
  } finally {
26509
- await rm2(temporaryDirectory, { force: true, recursive: true });
27372
+ await rm3(temporaryDirectory, { force: true, recursive: true });
26510
27373
  }
26511
27374
  };
26512
27375
  };
@@ -26526,7 +27389,7 @@ var PiInstallRecipe = class extends FixedAgentInstallRecipe {
26526
27389
  await options.report("verifying");
26527
27390
  await options.report("installing_agent");
26528
27391
  const executable = await this.#npmInstaller.install(
26529
- join9(
27392
+ join14(
26530
27393
  options.stateDirectory,
26531
27394
  "agents",
26532
27395
  this.id,
@@ -26581,11 +27444,161 @@ var PiInstallRecipe = class extends FixedAgentInstallRecipe {
26581
27444
  }
26582
27445
  };
26583
27446
  };
27447
+ var DeepSeekHarnessInstallRecipe = class extends FixedAgentInstallRecipe {
27448
+ #npmInstaller;
27449
+ id = "deepseek-harness";
27450
+ label = "DeepSeek Harness";
27451
+ releaseChannel = DEEPSEEK_HARNESS_PACKAGE.version;
27452
+ constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
27453
+ super();
27454
+ this.#npmInstaller = npmInstaller;
27455
+ }
27456
+ install = async (options) => {
27457
+ this.assertSupportedPlatform();
27458
+ try {
27459
+ const managedHome = join14(
27460
+ options.stateDirectory,
27461
+ "agents",
27462
+ this.id,
27463
+ "home"
27464
+ );
27465
+ await mkdir4(managedHome, { mode: 448, recursive: true });
27466
+ await options.report("downloading");
27467
+ await options.report("verifying");
27468
+ await options.report("installing_agent");
27469
+ const executable = await this.#npmInstaller.install(
27470
+ join14(
27471
+ options.stateDirectory,
27472
+ "agents",
27473
+ this.id,
27474
+ DEEPSEEK_HARNESS_PACKAGE.version
27475
+ ),
27476
+ DEEPSEEK_HARNESS_PACKAGE,
27477
+ options.environment,
27478
+ options.signal
27479
+ );
27480
+ options.audit.record(
27481
+ "agent_npm_package_verified",
27482
+ options.requestId,
27483
+ this.id,
27484
+ {
27485
+ integrity: DEEPSEEK_HARNESS_PACKAGE.integrity,
27486
+ package: DEEPSEEK_HARNESS_PACKAGE.packageName,
27487
+ version: DEEPSEEK_HARNESS_PACKAGE.version
27488
+ }
27489
+ );
27490
+ return executable;
27491
+ } catch (error61) {
27492
+ if (options.signal.aborted) {
27493
+ options.signal.throwIfAborted();
27494
+ }
27495
+ if (error61 instanceof ManagedNpmPackageError) {
27496
+ if (error61.code === "managed_package_verification_failed") {
27497
+ throw new InstallationManagerError(
27498
+ "agent_verification_failed",
27499
+ "The managed DeepSeek Harness package did not match its pinned artifact",
27500
+ { cause: error61 }
27501
+ );
27502
+ }
27503
+ if (error61.code === "managed_package_publish_failed") {
27504
+ throw new InstallationManagerError(
27505
+ "agent_publish_failed",
27506
+ "The managed DeepSeek Harness package could not be published",
27507
+ { cause: error61 }
27508
+ );
27509
+ }
27510
+ throw new InstallationManagerError(error61.code, error61.message, {
27511
+ cause: error61
27512
+ });
27513
+ }
27514
+ if (error61 instanceof InstallationManagerError) {
27515
+ throw error61;
27516
+ }
27517
+ throw new InstallationManagerError(
27518
+ "agent_install_failed",
27519
+ "The fixed DeepSeek Harness installation recipe failed",
27520
+ { cause: error61 }
27521
+ );
27522
+ }
27523
+ };
27524
+ };
27525
+ var OpenCodeInstallRecipe = class extends FixedAgentInstallRecipe {
27526
+ #archiveInstaller;
27527
+ id = "opencode";
27528
+ label = "OpenCode";
27529
+ releaseChannel = OPENCODE_MANAGED_VERSION;
27530
+ constructor(archiveInstaller = new ManagedAgentArchiveInstaller()) {
27531
+ super();
27532
+ this.#archiveInstaller = archiveInstaller;
27533
+ }
27534
+ install = async (options) => {
27535
+ this.assertSupportedPlatform();
27536
+ const definition = openCodeManagedArchive(process.platform, process.arch);
27537
+ try {
27538
+ await options.report("downloading");
27539
+ await options.report("verifying");
27540
+ await options.report("installing_agent");
27541
+ const executable = await this.#archiveInstaller.install(
27542
+ join14(
27543
+ options.stateDirectory,
27544
+ "agents",
27545
+ this.id,
27546
+ OPENCODE_MANAGED_VERSION
27547
+ ),
27548
+ definition,
27549
+ options.signal
27550
+ );
27551
+ options.audit.record(
27552
+ "agent_archive_verified",
27553
+ options.requestId,
27554
+ this.id,
27555
+ {
27556
+ sha256: definition.archiveSha256,
27557
+ version: definition.version
27558
+ }
27559
+ );
27560
+ return executable;
27561
+ } catch (error61) {
27562
+ if (options.signal.aborted) {
27563
+ options.signal.throwIfAborted();
27564
+ }
27565
+ if (error61 instanceof ManagedAgentArchiveError) {
27566
+ if (error61.code === "managed_archive_verification_failed") {
27567
+ throw new InstallationManagerError(
27568
+ "agent_verification_failed",
27569
+ "The managed OpenCode archive did not match its pinned artifact",
27570
+ { cause: error61 }
27571
+ );
27572
+ }
27573
+ if (error61.code === "managed_archive_publish_failed") {
27574
+ throw new InstallationManagerError(
27575
+ "agent_publish_failed",
27576
+ "The managed OpenCode archive could not be published",
27577
+ { cause: error61 }
27578
+ );
27579
+ }
27580
+ throw new InstallationManagerError(error61.code, error61.message, {
27581
+ cause: error61
27582
+ });
27583
+ }
27584
+ if (error61 instanceof InstallationManagerError) {
27585
+ throw error61;
27586
+ }
27587
+ throw new InstallationManagerError(
27588
+ "agent_install_failed",
27589
+ "The fixed OpenCode installation recipe failed",
27590
+ { cause: error61 }
27591
+ );
27592
+ }
27593
+ };
27594
+ };
26584
27595
  function fixedAgentInstallRecipes() {
26585
27596
  return Object.freeze([
26586
27597
  new CodexInstallRecipe(),
26587
27598
  new ClaudeCodeInstallRecipe(),
26588
- new PiInstallRecipe()
27599
+ new PiInstallRecipe(),
27600
+ new DeepSeekHarnessInstallRecipe(),
27601
+ new OpenCodeInstallRecipe()
26589
27602
  ]);
26590
27603
  }
26591
27604
 
@@ -26723,12 +27736,15 @@ var FixedInstallationExecutor = class {
26723
27736
  });
26724
27737
  installedAgent = true;
26725
27738
  }
26726
- let adapter = await resolveAdapterExecutable(
26727
- specification,
26728
- discoveryOptions2
26729
- );
27739
+ let adapter = specification instanceof DirectAcpAgentDefinition ? agent : await resolveAdapterExecutable(specification, discoveryOptions2);
26730
27740
  let installedAdapter = false;
26731
27741
  if (adapter === null) {
27742
+ if (!(specification instanceof BridgedAcpAgentDefinition)) {
27743
+ throw new InstallationManagerError(
27744
+ "agent_verification_failed",
27745
+ "The direct Agent executable is unavailable"
27746
+ );
27747
+ }
26732
27748
  await report("installing_adapter");
26733
27749
  adapter = await this.#adapterInstaller.install(specification, signal);
26734
27750
  installedAdapter = true;
@@ -26785,7 +27801,7 @@ var FixedInstallationExecutor = class {
26785
27801
  "The complete Agent ACP path did not pass verification"
26786
27802
  );
26787
27803
  }
26788
- if (!installedAdapter && requiresAdapterReplacement(unavailable.code)) {
27804
+ if (!installedAdapter && specification instanceof BridgedAcpAgentDefinition && requiresAdapterReplacement(unavailable.code)) {
26789
27805
  await report("installing_adapter");
26790
27806
  adapter = await this.#adapterInstaller.install(specification, signal);
26791
27807
  installedAdapter = true;
@@ -26804,6 +27820,9 @@ var FixedInstallationExecutor = class {
26804
27820
  stateDirectory: this.#stateDirectory
26805
27821
  });
26806
27822
  installedAgent = true;
27823
+ if (specification instanceof DirectAcpAgentDefinition) {
27824
+ adapter = agent;
27825
+ }
26807
27826
  continue;
26808
27827
  }
26809
27828
  throw new InstallationManagerError(
@@ -26856,15 +27875,15 @@ Mobius Web requested installation of ${label} (${requestId}). Allow this fixed u
26856
27875
  };
26857
27876
 
26858
27877
  // src/authorization/workspace-directory.ts
26859
- import { readdir, realpath as realpath4, stat as stat4 } from "node:fs/promises";
27878
+ import { readdir, realpath as realpath6, stat as stat6 } from "node:fs/promises";
26860
27879
  import { homedir as homedir2 } from "node:os";
26861
27880
  import {
26862
27881
  basename as basename2,
26863
- dirname as dirname4,
26864
- isAbsolute as isAbsolute3,
26865
- join as join10,
26866
- normalize,
26867
- relative as relative2
27882
+ dirname as dirname5,
27883
+ isAbsolute as isAbsolute5,
27884
+ join as join15,
27885
+ normalize as normalize2,
27886
+ relative as relative3
26868
27887
  } from "node:path";
26869
27888
  var WorkspaceDirectoryListing = class {
26870
27889
  directoryId;
@@ -26892,7 +27911,7 @@ function decodePath(value, prefix) {
26892
27911
  if (encoded.length === 0 || encoded.length > 2e3 || !/^[a-zA-Z0-9_-]+$/.test(encoded))
26893
27912
  throw new LocalAuthorizationError("The directory identifier is invalid");
26894
27913
  const decoded = Buffer.from(encoded, "base64url").toString("utf8");
26895
- if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize(decoded) !== decoded)
27914
+ if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize2(decoded) !== decoded)
26896
27915
  throw new LocalAuthorizationError("The directory identifier is invalid");
26897
27916
  return decoded;
26898
27917
  }
@@ -26914,20 +27933,20 @@ var WorkspaceDirectoryService = class {
26914
27933
  if (id === "home") return homedir2();
26915
27934
  if (id.startsWith("path-")) {
26916
27935
  const path2 = decodePath(id, "path-");
26917
- if (isAbsolute3(path2)) return path2;
27936
+ if (isAbsolute5(path2)) return path2;
26918
27937
  }
26919
27938
  throw new LocalAuthorizationError("The directory identifier is invalid");
26920
27939
  };
26921
27940
  resolvePath = async (requested, signal) => {
26922
27941
  signal.throwIfAborted();
26923
- if (!isAbsolute3(requested) || requested.includes("\0") || normalize(requested) !== requested)
27942
+ if (!isAbsolute5(requested) || requested.includes("\0") || normalize2(requested) !== requested)
26924
27943
  throw new LocalAuthorizationError("The local directory path is invalid");
26925
27944
  try {
26926
- const target = await realpath4(requested);
27945
+ const target = await realpath6(requested);
26927
27946
  signal.throwIfAborted();
26928
- const metadata = await stat4(target);
27947
+ const metadata = await stat6(target);
26929
27948
  signal.throwIfAborted();
26930
- if (!isAbsolute3(target) || normalize(target) !== target || !metadata.isDirectory())
27949
+ if (!isAbsolute5(target) || normalize2(target) !== target || !metadata.isDirectory())
26931
27950
  throw new LocalAuthorizationError(
26932
27951
  "The selected location is not a directory"
26933
27952
  );
@@ -26942,8 +27961,8 @@ var WorkspaceDirectoryService = class {
26942
27961
  }
26943
27962
  };
26944
27963
  label = (path2) => {
26945
- const suffix = relative2(homedir2(), path2);
26946
- return suffix === "" ? "~" : !isAbsolute3(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
27964
+ const suffix = relative3(homedir2(), path2);
27965
+ return suffix === "" ? "~" : !isAbsolute5(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
26947
27966
  };
26948
27967
  identify = async (bindingId, requestedPath, signal) => {
26949
27968
  this.authorizeMachine(bindingId);
@@ -26971,7 +27990,7 @@ var WorkspaceDirectoryService = class {
26971
27990
  continue;
26972
27991
  }
26973
27992
  try {
26974
- const path2 = await this.resolvePath(join10(target, child.name), signal);
27993
+ const path2 = await this.resolvePath(join15(target, child.name), signal);
26975
27994
  entries.push({ directoryId: encodePath(path2), name: child.name });
26976
27995
  } catch (cause) {
26977
27996
  signal.throwIfAborted();
@@ -26979,7 +27998,7 @@ var WorkspaceDirectoryService = class {
26979
27998
  }
26980
27999
  }
26981
28000
  entries.sort((a, b) => a.name.localeCompare(b.name));
26982
- const parent = dirname4(target);
28001
+ const parent = dirname5(target);
26983
28002
  return new WorkspaceDirectoryListing(
26984
28003
  id,
26985
28004
  this.label(target),
@@ -27094,7 +28113,8 @@ function decodeHistory(thread, value) {
27094
28113
  status: "available",
27095
28114
  messages,
27096
28115
  truncated,
27097
- coveredCommandIds: []
28116
+ coveredCommandIds: [],
28117
+ coveredMessageIds: []
27098
28118
  }
27099
28119
  };
27100
28120
  }
@@ -27771,7 +28791,7 @@ var RelayConnectionLiveness = class {
27771
28791
 
27772
28792
  // src/relay-connection/session-event-outbox.ts
27773
28793
  import { mkdirSync as mkdirSync3 } from "node:fs";
27774
- import { dirname as dirname5 } from "node:path";
28794
+ import { dirname as dirname6 } from "node:path";
27775
28795
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
27776
28796
  function readPendingEnvelope(row) {
27777
28797
  if (typeof row !== "object" || row === null || Array.isArray(row)) {
@@ -27786,7 +28806,7 @@ function readPendingEnvelope(row) {
27786
28806
  var SessionEventOutbox = class {
27787
28807
  #database;
27788
28808
  constructor(path2) {
27789
- mkdirSync3(dirname5(path2), { recursive: true });
28809
+ mkdirSync3(dirname6(path2), { recursive: true });
27790
28810
  this.#database = new DatabaseSync3(path2);
27791
28811
  this.#database.exec(`
27792
28812
  CREATE TABLE IF NOT EXISTS relay_session_event_outbox (