@moxt-ai/mobius 0.0.13 → 0.0.15

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 (91) hide show
  1. package/dist/acp/create-client.d.ts.map +1 -1
  2. package/dist/acp/create-client.js +16 -1
  3. package/dist/acp/create-client.js.map +1 -1
  4. package/dist/agent-catalog/agent-discovery.d.ts +1 -1
  5. package/dist/agent-catalog/agent-discovery.d.ts.map +1 -1
  6. package/dist/agent-catalog/agent-discovery.js +2 -2
  7. package/dist/agent-catalog/agent-discovery.js.map +1 -1
  8. package/dist/agent-catalog/agents/cursor-cli-agent.d.ts +13 -0
  9. package/dist/agent-catalog/agents/cursor-cli-agent.d.ts.map +1 -0
  10. package/dist/agent-catalog/agents/cursor-cli-agent.js +25 -0
  11. package/dist/agent-catalog/agents/cursor-cli-agent.js.map +1 -0
  12. package/dist/agent-catalog/agents/grok-build-agent.d.ts +18 -0
  13. package/dist/agent-catalog/agents/grok-build-agent.d.ts.map +1 -0
  14. package/dist/agent-catalog/agents/grok-build-agent.js +75 -0
  15. package/dist/agent-catalog/agents/grok-build-agent.js.map +1 -0
  16. package/dist/agent-catalog/agents/supported-agent-specifications.d.ts.map +1 -1
  17. package/dist/agent-catalog/agents/supported-agent-specifications.js +6 -0
  18. package/dist/agent-catalog/agents/supported-agent-specifications.js.map +1 -1
  19. package/dist/agent-catalog/agents/verify-session-creation.d.ts +3 -0
  20. package/dist/agent-catalog/agents/verify-session-creation.d.ts.map +1 -0
  21. package/dist/agent-catalog/agents/verify-session-creation.js +16 -0
  22. package/dist/agent-catalog/agents/verify-session-creation.js.map +1 -0
  23. package/dist/agent-catalog/agents/workbuddy-agent.d.ts +15 -0
  24. package/dist/agent-catalog/agents/workbuddy-agent.d.ts.map +1 -0
  25. package/dist/agent-catalog/agents/workbuddy-agent.js +41 -0
  26. package/dist/agent-catalog/agents/workbuddy-agent.js.map +1 -0
  27. package/dist/agent-catalog/discover-local-agents.d.ts +3 -0
  28. package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
  29. package/dist/agent-catalog/discover-local-agents.js +4 -10
  30. package/dist/agent-catalog/discover-local-agents.js.map +1 -1
  31. package/dist/agent-catalog/local-agent.d.ts +1 -2
  32. package/dist/agent-catalog/local-agent.d.ts.map +1 -1
  33. package/dist/agent-catalog/local-agent.js +1 -3
  34. package/dist/agent-catalog/local-agent.js.map +1 -1
  35. package/dist/agent-catalog/publish-agent-catalog.d.ts.map +1 -1
  36. package/dist/agent-catalog/publish-agent-catalog.js +0 -1
  37. package/dist/agent-catalog/publish-agent-catalog.js.map +1 -1
  38. package/dist/agent-installation/agent-installation-manager.d.ts +1 -8
  39. package/dist/agent-installation/agent-installation-manager.d.ts.map +1 -1
  40. package/dist/agent-installation/agent-installation-manager.js +7 -24
  41. package/dist/agent-installation/agent-installation-manager.js.map +1 -1
  42. package/dist/agent-installation/fixed-agent-install-recipe.d.ts +20 -0
  43. package/dist/agent-installation/fixed-agent-install-recipe.d.ts.map +1 -0
  44. package/dist/agent-installation/fixed-agent-install-recipe.js +18 -0
  45. package/dist/agent-installation/fixed-agent-install-recipe.js.map +1 -0
  46. package/dist/agent-installation/fixed-agent-install-recipes.d.ts +5 -18
  47. package/dist/agent-installation/fixed-agent-install-recipes.d.ts.map +1 -1
  48. package/dist/agent-installation/fixed-agent-install-recipes.js +9 -16
  49. package/dist/agent-installation/fixed-agent-install-recipes.js.map +1 -1
  50. package/dist/agent-installation/grok-build-install-recipe.d.ts +12 -0
  51. package/dist/agent-installation/grok-build-install-recipe.d.ts.map +1 -0
  52. package/dist/agent-installation/grok-build-install-recipe.js +102 -0
  53. package/dist/agent-installation/grok-build-install-recipe.js.map +1 -0
  54. package/dist/agent-installation/grok-managed-package.d.ts +4 -0
  55. package/dist/agent-installation/grok-managed-package.d.ts.map +1 -0
  56. package/dist/agent-installation/grok-managed-package.js +34 -0
  57. package/dist/agent-installation/grok-managed-package.js.map +1 -0
  58. package/dist/agent-installation/managed-npm-package.d.ts +8 -0
  59. package/dist/agent-installation/managed-npm-package.d.ts.map +1 -1
  60. package/dist/agent-installation/managed-npm-package.js +32 -3
  61. package/dist/agent-installation/managed-npm-package.js.map +1 -1
  62. package/dist/agent-installation/workbuddy-install-recipe.d.ts +12 -0
  63. package/dist/agent-installation/workbuddy-install-recipe.d.ts.map +1 -0
  64. package/dist/agent-installation/workbuddy-install-recipe.js +51 -0
  65. package/dist/agent-installation/workbuddy-install-recipe.js.map +1 -0
  66. package/dist/agent-installation/workbuddy-managed-package.d.ts +10 -0
  67. package/dist/agent-installation/workbuddy-managed-package.d.ts.map +1 -0
  68. package/dist/agent-installation/workbuddy-managed-package.js +11 -0
  69. package/dist/agent-installation/workbuddy-managed-package.js.map +1 -0
  70. package/dist/cli.js +1289 -837
  71. package/dist/cli.js.map +4 -4
  72. package/dist/config.d.ts.map +1 -1
  73. package/dist/config.js +2 -1
  74. package/dist/config.js.map +1 -1
  75. package/dist/index.js +1411 -959
  76. package/dist/index.js.map +4 -4
  77. package/dist/pairing/pair-local-machine.d.ts.map +1 -1
  78. package/dist/pairing/pair-local-machine.js +3 -3
  79. package/dist/pairing/pair-local-machine.js.map +1 -1
  80. package/dist/run-daemon.d.ts.map +1 -1
  81. package/dist/run-daemon.js +3 -12
  82. package/dist/run-daemon.js.map +1 -1
  83. package/package.json +2 -2
  84. package/dist/agent-installation/installation-grants.d.ts +0 -2
  85. package/dist/agent-installation/installation-grants.d.ts.map +0 -1
  86. package/dist/agent-installation/installation-grants.js +0 -51
  87. package/dist/agent-installation/installation-grants.js.map +0 -1
  88. package/dist/agent-installation/local-installation-authorizer.d.ts +0 -7
  89. package/dist/agent-installation/local-installation-authorizer.d.ts.map +0 -1
  90. package/dist/agent-installation/local-installation-authorizer.js +0 -32
  91. package/dist/agent-installation/local-installation-authorizer.js.map +0 -1
package/dist/index.js CHANGED
@@ -9,6 +9,9 @@ import {
9
9
  client,
10
10
  methods
11
11
  } from "@agentclientprotocol/sdk";
12
+ function discardExtensionParams(_params) {
13
+ return Object.freeze({});
14
+ }
12
15
  var createAcpClient = (handler) => client({ name: "mobius" }).onRequest(
13
16
  methods.client.session.requestPermission,
14
17
  async (context) => await handler.onPermission(context.params, context.signal)
@@ -19,652 +22,31 @@ var createAcpClient = (handler) => client({ name: "mobius" }).onRequest(
19
22
  await handler.onUpdate(context.params);
20
23
  }).onNotification(methods.client.elicitation.complete, async (context) => {
21
24
  await handler.onElicitationComplete(context.params);
22
- });
25
+ }).onRequest("cursor/ask_question", discardExtensionParams, async () => ({
26
+ outcome: {
27
+ outcome: "skipped",
28
+ reason: "Mobius does not expose Cursor question extensions"
29
+ }
30
+ })).onRequest("cursor/create_plan", discardExtensionParams, async () => ({
31
+ outcome: { outcome: "cancelled" }
32
+ })).onNotification(
33
+ "cursor/update_todos",
34
+ discardExtensionParams,
35
+ async () => Promise.resolve()
36
+ ).onNotification(
37
+ "cursor/task",
38
+ discardExtensionParams,
39
+ async () => Promise.resolve()
40
+ ).onNotification(
41
+ "cursor/generate_image",
42
+ discardExtensionParams,
43
+ async () => Promise.resolve()
44
+ );
23
45
 
24
46
  // src/config.ts
25
47
  import { join as join3 } from "node:path";
26
48
  import { fileURLToPath } from "node:url";
27
49
 
28
- // src/agent-catalog/local-agent.ts
29
- import { realpathSync, statSync } from "node:fs";
30
-
31
- // src/process/executable.ts
32
- import { execFile, spawn } from "node:child_process";
33
- import { constants } from "node:fs";
34
- import { access, realpath, stat } from "node:fs/promises";
35
- import { join, resolve } from "node:path";
36
- var DEFAULT_OUTPUT_LIMIT_BYTES = 16 * 1024;
37
- var PROCESS_GRACEFUL_STOP_TIMEOUT_MILLISECONDS = 1e3;
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;
44
- var ExecutableIdentity = class {
45
- changedAtMilliseconds;
46
- device;
47
- inode;
48
- realPath;
49
- requestedPath;
50
- size;
51
- constructor(requestedPath, realPath_, device, inode, size, changedAtMilliseconds) {
52
- this.changedAtMilliseconds = changedAtMilliseconds;
53
- this.device = device;
54
- this.inode = inode;
55
- this.realPath = realPath_;
56
- this.requestedPath = requestedPath;
57
- this.size = size;
58
- }
59
- matches = (candidate) => this.requestedPath === candidate.requestedPath && this.realPath === candidate.realPath && this.device === candidate.device && this.inode === candidate.inode && this.size === candidate.size && this.changedAtMilliseconds === candidate.changedAtMilliseconds;
60
- };
61
- var ResolvedExecutable = class {
62
- identity;
63
- path;
64
- constructor(identity2) {
65
- this.identity = identity2;
66
- this.path = identity2.realPath;
67
- }
68
- };
69
- var ProcessExecutionError = class extends Error {
70
- code;
71
- constructor(code, message, options = {}) {
72
- super(message, options);
73
- this.code = code;
74
- this.name = "ProcessExecutionError";
75
- }
76
- };
77
- var ProcessResult = class {
78
- stderr;
79
- stdout;
80
- constructor(stdout, stderr) {
81
- this.stderr = stderr;
82
- this.stdout = stdout;
83
- }
84
- };
85
- function executableExtensions(executableName, environment, platform) {
86
- if (platform !== "win32") {
87
- return [""];
88
- }
89
- if (/\.[a-zA-Z0-9]+$/.test(executableName)) {
90
- return [""];
91
- }
92
- const configured = environment["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD";
93
- const extensions = configured.split(";").map((extension) => extension.trim()).filter((extension) => extension.length > 0).map(
94
- (extension) => extension.startsWith(".") ? extension : `.${extension}`
95
- );
96
- return extensions.length > 0 ? extensions : [".EXE"];
97
- }
98
- async function resolveExecutablePath(requestedPath, platform = process.platform) {
99
- const absoluteRequestedPath = resolve(requestedPath);
100
- try {
101
- const resolvedPath = await realpath(absoluteRequestedPath);
102
- const metadata = await stat(resolvedPath);
103
- if (!metadata.isFile()) {
104
- return null;
105
- }
106
- if (platform !== "win32") {
107
- await access(resolvedPath, constants.X_OK);
108
- }
109
- return new ResolvedExecutable(
110
- new ExecutableIdentity(
111
- absoluteRequestedPath,
112
- resolvedPath,
113
- metadata.dev,
114
- metadata.ino,
115
- metadata.size,
116
- metadata.ctimeMs
117
- )
118
- );
119
- } catch {
120
- return null;
121
- }
122
- }
123
- async function findExecutableOnPath(executableName, environment, platform = process.platform) {
124
- const encodedPath = environment["PATH"] ?? "";
125
- const separator = platform === "win32" ? ";" : ":";
126
- const extensions = executableExtensions(
127
- executableName,
128
- environment,
129
- platform
130
- );
131
- for (const entry of encodedPath.split(separator)) {
132
- if (entry.length === 0) {
133
- continue;
134
- }
135
- for (const extension of extensions) {
136
- const requestedPath = resolve(
137
- join(entry, `${executableName}${extension}`)
138
- );
139
- const executable = await resolveExecutablePath(requestedPath, platform);
140
- if (executable !== null) {
141
- return executable;
142
- }
143
- }
144
- }
145
- return null;
146
- }
147
- async function revalidateExecutable(identity2, platform = process.platform) {
148
- const current = await resolveExecutablePath(identity2.requestedPath, platform);
149
- return current !== null && identity2.matches(current.identity);
150
- }
151
- function appendBounded(chunks, chunk, currentBytes, limitBytes) {
152
- const nextBytes = currentBytes + chunk.byteLength;
153
- if (nextBytes > limitBytes) {
154
- throw new ProcessExecutionError(
155
- "process_output_limit",
156
- "The executable produced too much output"
157
- );
158
- }
159
- chunks.push(chunk);
160
- return nextBytes;
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
- }
275
- function terminateProcess(child) {
276
- if (child.exitCode !== null || child.signalCode !== null || child.pid === void 0) {
277
- return;
278
- }
279
- if (process.platform !== "win32") {
280
- try {
281
- process.kill(-child.pid, "SIGTERM");
282
- return;
283
- } catch {
284
- }
285
- }
286
- child.kill("SIGTERM");
287
- }
288
- function forceTerminateProcess(child) {
289
- if (child.exitCode !== null || child.signalCode !== null || child.pid === void 0) {
290
- return;
291
- }
292
- if (process.platform !== "win32") {
293
- try {
294
- process.kill(-child.pid, "SIGKILL");
295
- return;
296
- } catch {
297
- }
298
- }
299
- child.kill("SIGKILL");
300
- }
301
- async function stopProcessTree(child, capturedProcesses = []) {
302
- const childProcessId = child.pid;
303
- if (childProcessId === void 0) {
304
- return;
305
- }
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)
313
- );
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) {
321
- return;
322
- }
323
- signalDetachedProcessGroups(processes, childProcessId, FORCED_STOP_SIGNAL);
324
- forceTerminateProcess(child);
325
- const [exitedAfterForce, descendantsExitedAfterForce] = await Promise.all([
326
- waitForProcessExit(child, PROCESS_FORCED_STOP_TIMEOUT_MILLISECONDS),
327
- waitForCapturedProcessesExit(processes, childProcessId)
328
- ]);
329
- if (!exitedAfterForce || !descendantsExitedAfterForce) {
330
- throw new ProcessExecutionError(
331
- "process_termination_timeout",
332
- "The executable process could not be stopped"
333
- );
334
- }
335
- }
336
- function waitForProcessExit(child, timeoutMilliseconds) {
337
- if (child.exitCode !== null || child.signalCode !== null) {
338
- return Promise.resolve(true);
339
- }
340
- return new Promise((resolveExit) => {
341
- let settled = false;
342
- const finish = (exited) => {
343
- if (settled) {
344
- return;
345
- }
346
- settled = true;
347
- clearTimeout(timeout);
348
- child.removeListener("exit", handleExit);
349
- resolveExit(exited);
350
- };
351
- const handleExit = () => finish(true);
352
- const timeout = setTimeout(() => finish(false), timeoutMilliseconds);
353
- child.once("exit", handleExit);
354
- if (child.exitCode !== null || child.signalCode !== null) {
355
- finish(true);
356
- }
357
- });
358
- }
359
- async function runBoundedProcess(options) {
360
- options.signal.throwIfAborted();
361
- const outputLimitBytes = options.outputLimitBytes ?? DEFAULT_OUTPUT_LIMIT_BYTES;
362
- const child = spawn(options.command, [...options.arguments], {
363
- cwd: options.cwd,
364
- detached: process.platform !== "win32",
365
- env: { ...options.environment },
366
- shell: false,
367
- stdio: ["ignore", "pipe", "pipe"]
368
- });
369
- const stdout = [];
370
- const stderr = [];
371
- let stdoutBytes = 0;
372
- let stderrBytes = 0;
373
- let interruptionFailure = null;
374
- let interruptionCleanupFailure = null;
375
- let stopping = false;
376
- const interrupted = Promise.withResolvers();
377
- const interrupt = (failure) => {
378
- if (stopping) {
379
- return;
380
- }
381
- stopping = true;
382
- interruptionFailure = failure;
383
- const stop = async () => {
384
- try {
385
- await stopProcessTree(child);
386
- } catch (error61) {
387
- interruptionCleanupFailure = error61 instanceof ProcessExecutionError ? error61 : new ProcessExecutionError(
388
- "process_termination_failed",
389
- "The executable process could not be stopped",
390
- { cause: error61 }
391
- );
392
- } finally {
393
- interrupted.resolve();
394
- }
395
- };
396
- void stop();
397
- };
398
- const collectStdout = (chunk) => {
399
- if (interruptionFailure !== null) {
400
- return;
401
- }
402
- try {
403
- stdoutBytes = appendBounded(stdout, chunk, stdoutBytes, outputLimitBytes);
404
- } catch (error61) {
405
- const failure = error61 instanceof ProcessExecutionError ? error61 : new ProcessExecutionError(
406
- "process_output_limit",
407
- "The executable produced too much output",
408
- { cause: error61 }
409
- );
410
- interrupt(failure);
411
- }
412
- };
413
- const collectStderr = (chunk) => {
414
- if (interruptionFailure !== null) {
415
- return;
416
- }
417
- try {
418
- stderrBytes = appendBounded(stderr, chunk, stderrBytes, outputLimitBytes);
419
- } catch (error61) {
420
- const failure = error61 instanceof ProcessExecutionError ? error61 : new ProcessExecutionError(
421
- "process_output_limit",
422
- "The executable produced too much output",
423
- { cause: error61 }
424
- );
425
- interrupt(failure);
426
- }
427
- };
428
- child.stdout?.on("data", collectStdout);
429
- child.stderr?.on("data", collectStderr);
430
- const timeout = setTimeout(() => {
431
- interrupt(
432
- new ProcessExecutionError(
433
- "process_timeout",
434
- "The executable probe timed out"
435
- )
436
- );
437
- }, options.timeoutMilliseconds);
438
- const abort = () => interrupt(
439
- new ProcessExecutionError(
440
- "process_cancelled",
441
- "The executable probe was cancelled",
442
- { cause: options.signal.reason }
443
- )
444
- );
445
- options.signal.addEventListener("abort", abort, { once: true });
446
- if (options.signal.aborted) {
447
- abort();
448
- }
449
- try {
450
- const exit = new Promise((resolveExit, rejectExit) => {
451
- child.once("error", rejectExit);
452
- child.once("exit", (code) => resolveExit(code ?? 1));
453
- });
454
- const exitCode = await Promise.race([
455
- exit,
456
- interrupted.promise.then(() => -1)
457
- ]);
458
- if (interruptionCleanupFailure !== null) {
459
- throw interruptionCleanupFailure;
460
- }
461
- if (interruptionFailure !== null) {
462
- throw interruptionFailure;
463
- }
464
- if (exitCode !== 0) {
465
- throw new ProcessExecutionError(
466
- "process_exit_failed",
467
- "The executable probe failed"
468
- );
469
- }
470
- return new ProcessResult(
471
- Buffer.concat(stdout).toString("utf8"),
472
- Buffer.concat(stderr).toString("utf8")
473
- );
474
- } catch (error61) {
475
- if (error61 instanceof ProcessExecutionError) {
476
- throw error61;
477
- }
478
- throw new ProcessExecutionError(
479
- "process_spawn_failed",
480
- "The executable could not be started",
481
- { cause: error61 }
482
- );
483
- } finally {
484
- clearTimeout(timeout);
485
- options.signal.removeEventListener("abort", abort);
486
- child.stdout?.removeListener("data", collectStdout);
487
- child.stderr?.removeListener("data", collectStderr);
488
- if (stopping) {
489
- await interrupted.promise;
490
- } else {
491
- await stopProcessTree(child);
492
- }
493
- }
494
- }
495
-
496
- // src/agent-catalog/local-agent.ts
497
- function readTrustedIdentity(path2) {
498
- const resolvedPath = realpathSync(path2);
499
- const metadata = statSync(resolvedPath);
500
- return new ExecutableIdentity(
501
- resolvedPath,
502
- resolvedPath,
503
- metadata.dev,
504
- metadata.ino,
505
- metadata.size,
506
- metadata.ctimeMs
507
- );
508
- }
509
- var LocalAgentDefinition = class {
510
- adapterIdentity;
511
- adapterPath;
512
- adapterVersion;
513
- agentIdentity;
514
- agentVersion;
515
- arguments;
516
- command;
517
- environment;
518
- id;
519
- label;
520
- promptTimeoutMilliseconds;
521
- constructor(id, label, command, arguments_, environment = {}, adapterVersion = "", agentVersion = "", adapterIdentity = readTrustedIdentity(command), agentIdentity = adapterIdentity, promptTimeoutMilliseconds = 30 * 60 * 1e3) {
522
- if (!Number.isSafeInteger(promptTimeoutMilliseconds) || promptTimeoutMilliseconds < 1) {
523
- throw new Error("The local Agent prompt deadline is invalid");
524
- }
525
- this.adapterIdentity = adapterIdentity;
526
- this.adapterPath = adapterIdentity.realPath;
527
- this.adapterVersion = adapterVersion;
528
- this.agentIdentity = agentIdentity;
529
- this.agentVersion = agentVersion;
530
- this.id = id;
531
- this.label = label;
532
- this.promptTimeoutMilliseconds = promptTimeoutMilliseconds;
533
- this.command = adapterIdentity.realPath;
534
- this.arguments = Object.freeze([...arguments_]);
535
- this.environment = Object.freeze({ ...environment });
536
- }
537
- };
538
- var InstallableAgentDefinition = class {
539
- id;
540
- label;
541
- requiresLocalApproval;
542
- constructor(id, label, requiresLocalApproval = true) {
543
- this.id = id;
544
- this.label = label;
545
- this.requiresLocalApproval = requiresLocalApproval;
546
- }
547
- };
548
- var LocalAgentCatalogSnapshot = class {
549
- agents;
550
- installableAgents;
551
- constructor(agents, installableAgents) {
552
- this.agents = Object.freeze([...agents]);
553
- this.installableAgents = Object.freeze([...installableAgents]);
554
- }
555
- };
556
- var LocalAgentCatalogError = class extends Error {
557
- code = "agent_not_ready";
558
- constructor() {
559
- super("The requested local Agent is not ready");
560
- this.name = "LocalAgentCatalogError";
561
- }
562
- };
563
- var LocalAgentCatalog = class {
564
- #snapshot;
565
- constructor(agents, installableAgents) {
566
- this.#snapshot = this.validate(agents, installableAgents);
567
- }
568
- find = (agentId) => {
569
- for (const agent of this.#snapshot.agents) {
570
- if (agent.id === agentId) {
571
- return agent;
572
- }
573
- }
574
- throw new LocalAgentCatalogError();
575
- };
576
- read = () => this.#snapshot;
577
- transition = (agents, installableAgents) => {
578
- const next = this.validate(agents, installableAgents);
579
- this.#snapshot = next;
580
- return next;
581
- };
582
- validate = (agents, installableAgents) => {
583
- const identifiers = /* @__PURE__ */ new Set();
584
- for (const agent of agents) {
585
- if (identifiers.has(agent.id)) {
586
- throw new Error("The local Agent catalog contains duplicate entries");
587
- }
588
- identifiers.add(agent.id);
589
- }
590
- for (const agent of installableAgents) {
591
- if (identifiers.has(agent.id)) {
592
- throw new Error("A local Agent cannot be ready and installable");
593
- }
594
- identifiers.add(agent.id);
595
- }
596
- return new LocalAgentCatalogSnapshot(agents, installableAgents);
597
- };
598
- };
599
-
600
- // src/storage/state-directory.ts
601
- import { homedir } from "node:os";
602
- import { join as join2, resolve as resolve2 } from "node:path";
603
- function readStateDirectory(environment = process.env) {
604
- const configured = environment["MOBIUS_STATE_DIRECTORY"]?.trim();
605
- if (configured !== void 0 && configured.length > 0) {
606
- return resolve2(configured);
607
- }
608
- return join2(homedir(), ".mobius");
609
- }
610
-
611
- // src/config.ts
612
- function loadDefaultWorkspace() {
613
- const { MOBIUS_DEFAULT_WORKSPACE: configuredWorkspace } = process.env;
614
- return configuredWorkspace ?? join3(readStateDirectory(), "workspace");
615
- }
616
- function createDaemonConfig(connection, agents = [], installableAgents = []) {
617
- return {
618
- agents,
619
- defaultWorkspace: connection.defaultWorkspace,
620
- auditDatabasePath: connection.auditDatabasePath,
621
- bindingId: "workspace",
622
- catalog: new LocalAgentCatalog(agents, installableAgents),
623
- channelId: connection.channelId,
624
- installableAgents,
625
- relayUrl: connection.relayUrl
626
- };
627
- }
628
- function loadDaemonConfig() {
629
- const relayUrl = new URL(
630
- // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
631
- process.env["MOBIUS_RELAY_URL"] ?? "ws://127.0.0.1:8787/mobius/api/channels/local/daemon"
632
- );
633
- relayUrl.searchParams.set(
634
- "token",
635
- // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
636
- process.env["MOBIUS_RELAY_TOKEN"] ?? "local-development-token"
637
- );
638
- if (relayUrl.protocol !== "ws:" && relayUrl.protocol !== "wss:") {
639
- throw new Error("MOBIUS_RELAY_URL must use ws or wss");
640
- }
641
- return createDaemonConfig(
642
- {
643
- defaultWorkspace: loadDefaultWorkspace(),
644
- auditDatabasePath: (
645
- // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
646
- process.env["MOBIUS_AUDIT_DATABASE"] ?? fileURLToPath(
647
- new URL("../../../.mobius/daemon.sqlite", import.meta.url)
648
- )
649
- ),
650
- // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
651
- channelId: process.env["MOBIUS_CHANNEL_ID"] ?? "local",
652
- relayUrl
653
- },
654
- [],
655
- []
656
- );
657
- }
658
-
659
- // src/acp/session-manager.ts
660
- import { spawn as spawn2 } from "node:child_process";
661
- import {
662
- methods as methods2,
663
- ndJsonStream,
664
- PROTOCOL_VERSION,
665
- RequestError
666
- } from "@agentclientprotocol/sdk";
667
-
668
50
  // ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/external.js
669
51
  var external_exports = {};
670
52
  __export(external_exports, {
@@ -2625,8 +2007,8 @@ function emoji() {
2625
2007
  }
2626
2008
  var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
2627
2009
  var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
2628
- var mac = (delimiter2) => {
2629
- const escapedDelim = escapeRegex(delimiter2 ?? ":");
2010
+ var mac = (delimiter3) => {
2011
+ const escapedDelim = escapeRegex(delimiter3 ?? ":");
2630
2012
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
2631
2013
  };
2632
2014
  var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
@@ -19601,7 +18983,6 @@ var SESSION_OPERATION_FAILED_KIND = "session.operation.failed";
19601
18983
  var AGENT_CONTENT_KIND = "agent.content";
19602
18984
  var AGENT_INSTALL_REQUEST_KIND = "agent.install.request";
19603
18985
  var AGENT_INSTALL_CANCEL_KIND = "agent.install.cancel";
19604
- var AGENT_INSTALL_AWAITING_APPROVAL_KIND = "agent.install.awaiting_approval";
19605
18986
  var AGENT_INSTALL_STARTED_KIND = "agent.install.started";
19606
18987
  var AGENT_INSTALL_PROGRESS_KIND = "agent.install.progress";
19607
18988
  var AGENT_INSTALL_COMPLETED_KIND = "agent.install.completed";
@@ -19907,10 +19288,6 @@ var agentInstallCancelCommandSchema = external_exports.strictObject({
19907
19288
  kind: external_exports.literal(AGENT_INSTALL_CANCEL_KIND),
19908
19289
  requestId: IDENTIFIER
19909
19290
  }).readonly();
19910
- var agentInstallAwaitingApprovalEventSchema = external_exports.strictObject({
19911
- ...agentInstallIdentityFields,
19912
- kind: external_exports.literal(AGENT_INSTALL_AWAITING_APPROVAL_KIND)
19913
- }).readonly();
19914
19291
  var agentInstallStartedEventSchema = external_exports.strictObject({
19915
19292
  ...agentInstallIdentityFields,
19916
19293
  kind: external_exports.literal(AGENT_INSTALL_STARTED_KIND)
@@ -19993,7 +19370,6 @@ var encodeSessionOperationFailedEvent = (message) => encode3(message, sessionOpe
19993
19370
  var encodeAgentContentEvent = (message) => encode3(message, agentContentEventSchema);
19994
19371
  var decodeAgentInstallRequestCommand = (encoded) => decode3(encoded, agentInstallRequestCommandSchema);
19995
19372
  var decodeAgentInstallCancelCommand = (encoded) => decode3(encoded, agentInstallCancelCommandSchema);
19996
- var encodeAgentInstallAwaitingApprovalEvent = (message) => encode3(message, agentInstallAwaitingApprovalEventSchema);
19997
19373
  var encodeAgentInstallStartedEvent = (message) => encode3(message, agentInstallStartedEventSchema);
19998
19374
  var encodeAgentInstallProgressEvent = (message) => encode3(message, agentInstallProgressEventSchema);
19999
19375
  var encodeAgentInstallCompletedEvent = (message) => encode3(message, agentInstallCompletedEventSchema);
@@ -20393,6 +19769,29 @@ function encodeSessionFailedEvent(message) {
20393
19769
  return JSON.stringify(decodeSessionFailedEvent(JSON.stringify(message)));
20394
19770
  }
20395
19771
 
19772
+ // ../protocol/src/mobius-api.ts
19773
+ var MOBIUS_API_PREFIX = "/mobius/api";
19774
+ var API_PREFIX_PATTERN = /^\/[a-zA-Z0-9._~-]+(?:\/[a-zA-Z0-9._~-]+)*$/;
19775
+ var MobiusApiConfigurationError = class extends Error {
19776
+ code = "invalid_api_prefix";
19777
+ constructor() {
19778
+ super("The Mobius API prefix must be an absolute path without parameters");
19779
+ this.name = "MobiusApiConfigurationError";
19780
+ }
19781
+ };
19782
+ function parseMobiusApiPrefix(value) {
19783
+ if (typeof value !== "string" || !API_PREFIX_PATTERN.test(value)) {
19784
+ throw new MobiusApiConfigurationError();
19785
+ }
19786
+ return value;
19787
+ }
19788
+ function mobiusApiPath(resourcePath, apiPrefix = MOBIUS_API_PREFIX) {
19789
+ return `${parseMobiusApiPrefix(apiPrefix)}${resourcePath}`;
19790
+ }
19791
+ function mobiusApiUrl(origin, resourcePath, apiPrefix = MOBIUS_API_PREFIX) {
19792
+ return new URL(mobiusApiPath(resourcePath, apiPrefix), origin);
19793
+ }
19794
+
20396
19795
  // ../protocol/src/session-history.ts
20397
19796
  var SESSION_HISTORY_CHARACTER_LIMIT = 256e3;
20398
19797
  var SESSION_HISTORY_MESSAGE_LIMIT = 1e3;
@@ -21084,29 +20483,667 @@ var eventAcknowledgementSchema = external_exports.strictObject({
21084
20483
  function decode5(encoded, schema) {
21085
20484
  let value;
21086
20485
  try {
21087
- value = JSON.parse(encoded);
21088
- } catch (cause) {
21089
- throw new ProtocolMessageError("Message is not valid JSON", { cause });
20486
+ value = JSON.parse(encoded);
20487
+ } catch (cause) {
20488
+ throw new ProtocolMessageError("Message is not valid JSON", { cause });
20489
+ }
20490
+ const decoded = schema.safeParse(value);
20491
+ if (!decoded.success) {
20492
+ throw new ProtocolMessageError("Message does not match its schema", {
20493
+ cause: decoded.error
20494
+ });
20495
+ }
20496
+ return decoded.data;
20497
+ }
20498
+ var encode4 = (message, schema) => {
20499
+ const decoded = schema.safeParse(message);
20500
+ if (!decoded.success) {
20501
+ throw new ProtocolMessageError("Message does not match its schema", {
20502
+ cause: decoded.error
20503
+ });
20504
+ }
20505
+ return JSON.stringify(decoded.data);
20506
+ };
20507
+ var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
20508
+ var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
20509
+
20510
+ // src/agent-catalog/local-agent.ts
20511
+ import { realpathSync, statSync } from "node:fs";
20512
+
20513
+ // src/process/executable.ts
20514
+ import { execFile, spawn } from "node:child_process";
20515
+ import { constants } from "node:fs";
20516
+ import { access, realpath, stat } from "node:fs/promises";
20517
+ import { join, resolve } from "node:path";
20518
+ var DEFAULT_OUTPUT_LIMIT_BYTES = 16 * 1024;
20519
+ var PROCESS_GRACEFUL_STOP_TIMEOUT_MILLISECONDS = 1e3;
20520
+ var PROCESS_FORCED_STOP_TIMEOUT_MILLISECONDS = 5e3;
20521
+ var PROCESS_TABLE_TIMEOUT_MILLISECONDS = 1e3;
20522
+ var PROCESS_TABLE_OUTPUT_LIMIT_BYTES = 1024 * 1024;
20523
+ var PROCESS_EXIT_CHECK_ATTEMPTS = 8;
20524
+ var GRACEFUL_STOP_SIGNAL = 15;
20525
+ var FORCED_STOP_SIGNAL = 9;
20526
+ var ExecutableIdentity = class {
20527
+ changedAtMilliseconds;
20528
+ device;
20529
+ inode;
20530
+ realPath;
20531
+ requestedPath;
20532
+ size;
20533
+ constructor(requestedPath, realPath_, device, inode, size, changedAtMilliseconds) {
20534
+ this.changedAtMilliseconds = changedAtMilliseconds;
20535
+ this.device = device;
20536
+ this.inode = inode;
20537
+ this.realPath = realPath_;
20538
+ this.requestedPath = requestedPath;
20539
+ this.size = size;
20540
+ }
20541
+ matches = (candidate) => this.requestedPath === candidate.requestedPath && this.realPath === candidate.realPath && this.device === candidate.device && this.inode === candidate.inode && this.size === candidate.size && this.changedAtMilliseconds === candidate.changedAtMilliseconds;
20542
+ };
20543
+ var ResolvedExecutable = class {
20544
+ identity;
20545
+ path;
20546
+ constructor(identity2) {
20547
+ this.identity = identity2;
20548
+ this.path = identity2.realPath;
20549
+ }
20550
+ };
20551
+ var ProcessExecutionError = class extends Error {
20552
+ code;
20553
+ constructor(code, message, options = {}) {
20554
+ super(message, options);
20555
+ this.code = code;
20556
+ this.name = "ProcessExecutionError";
20557
+ }
20558
+ };
20559
+ var ProcessResult = class {
20560
+ stderr;
20561
+ stdout;
20562
+ constructor(stdout, stderr) {
20563
+ this.stderr = stderr;
20564
+ this.stdout = stdout;
20565
+ }
20566
+ };
20567
+ function executableExtensions(executableName, environment, platform) {
20568
+ if (platform !== "win32") {
20569
+ return [""];
20570
+ }
20571
+ if (/\.[a-zA-Z0-9]+$/.test(executableName)) {
20572
+ return [""];
20573
+ }
20574
+ const configured = environment["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD";
20575
+ const extensions = configured.split(";").map((extension) => extension.trim()).filter((extension) => extension.length > 0).map(
20576
+ (extension) => extension.startsWith(".") ? extension : `.${extension}`
20577
+ );
20578
+ return extensions.length > 0 ? extensions : [".EXE"];
20579
+ }
20580
+ async function resolveExecutablePath(requestedPath, platform = process.platform) {
20581
+ const absoluteRequestedPath = resolve(requestedPath);
20582
+ try {
20583
+ const resolvedPath = await realpath(absoluteRequestedPath);
20584
+ const metadata = await stat(resolvedPath);
20585
+ if (!metadata.isFile()) {
20586
+ return null;
20587
+ }
20588
+ if (platform !== "win32") {
20589
+ await access(resolvedPath, constants.X_OK);
20590
+ }
20591
+ return new ResolvedExecutable(
20592
+ new ExecutableIdentity(
20593
+ absoluteRequestedPath,
20594
+ resolvedPath,
20595
+ metadata.dev,
20596
+ metadata.ino,
20597
+ metadata.size,
20598
+ metadata.ctimeMs
20599
+ )
20600
+ );
20601
+ } catch {
20602
+ return null;
20603
+ }
20604
+ }
20605
+ async function findExecutableOnPath(executableName, environment, platform = process.platform) {
20606
+ const encodedPath = environment["PATH"] ?? "";
20607
+ const separator = platform === "win32" ? ";" : ":";
20608
+ const extensions = executableExtensions(
20609
+ executableName,
20610
+ environment,
20611
+ platform
20612
+ );
20613
+ for (const entry of encodedPath.split(separator)) {
20614
+ if (entry.length === 0) {
20615
+ continue;
20616
+ }
20617
+ for (const extension of extensions) {
20618
+ const requestedPath = resolve(
20619
+ join(entry, `${executableName}${extension}`)
20620
+ );
20621
+ const executable = await resolveExecutablePath(requestedPath, platform);
20622
+ if (executable !== null) {
20623
+ return executable;
20624
+ }
20625
+ }
20626
+ }
20627
+ return null;
20628
+ }
20629
+ async function revalidateExecutable(identity2, platform = process.platform) {
20630
+ const current = await resolveExecutablePath(identity2.requestedPath, platform);
20631
+ return current !== null && identity2.matches(current.identity);
20632
+ }
20633
+ function appendBounded(chunks, chunk, currentBytes, limitBytes) {
20634
+ const nextBytes = currentBytes + chunk.byteLength;
20635
+ if (nextBytes > limitBytes) {
20636
+ throw new ProcessExecutionError(
20637
+ "process_output_limit",
20638
+ "The executable produced too much output"
20639
+ );
20640
+ }
20641
+ chunks.push(chunk);
20642
+ return nextBytes;
20643
+ }
20644
+ function parseProcessTable(output2) {
20645
+ const entries = [];
20646
+ for (const line of output2.split("\n")) {
20647
+ const groups = /^\s*(?<pid>\d+)\s+(?<ppid>\d+)\s+(?<pgid>\d+)\s*$/.exec(
20648
+ line
20649
+ )?.groups;
20650
+ if (groups === void 0) {
20651
+ continue;
20652
+ }
20653
+ const processId = Number(groups["pid"]);
20654
+ const parentProcessId = Number(groups["ppid"]);
20655
+ const processGroupId = Number(groups["pgid"]);
20656
+ if (!Number.isSafeInteger(processId) || processId <= 0 || !Number.isSafeInteger(parentProcessId) || parentProcessId < 0 || !Number.isSafeInteger(processGroupId) || processGroupId <= 0) {
20657
+ continue;
20658
+ }
20659
+ entries.push({ parentProcessId, processGroupId, processId });
20660
+ }
20661
+ return entries;
20662
+ }
20663
+ function readProcessTable() {
20664
+ if (process.platform === "win32") {
20665
+ return Promise.resolve([]);
20666
+ }
20667
+ const executable = process.platform === "darwin" ? "/bin/ps" : "/usr/bin/ps";
20668
+ return new Promise((resolveTable) => {
20669
+ execFile(
20670
+ executable,
20671
+ ["-axo", "pid=,ppid=,pgid="],
20672
+ {
20673
+ encoding: "utf8",
20674
+ maxBuffer: PROCESS_TABLE_OUTPUT_LIMIT_BYTES,
20675
+ signal: AbortSignal.timeout(PROCESS_TABLE_TIMEOUT_MILLISECONDS),
20676
+ timeout: PROCESS_TABLE_TIMEOUT_MILLISECONDS
20677
+ },
20678
+ (error61, stdout) => {
20679
+ resolveTable(error61 === null ? parseProcessTable(stdout) : []);
20680
+ }
20681
+ );
20682
+ });
20683
+ }
20684
+ function selectProcessTree(entries, rootProcessId) {
20685
+ const processIds = /* @__PURE__ */ new Set([rootProcessId]);
20686
+ let previousSize = 0;
20687
+ while (previousSize !== processIds.size) {
20688
+ previousSize = processIds.size;
20689
+ for (const entry of entries) {
20690
+ if (processIds.has(entry.parentProcessId)) {
20691
+ processIds.add(entry.processId);
20692
+ }
20693
+ }
20694
+ }
20695
+ return entries.filter((entry) => processIds.has(entry.processId)).map((entry) => ({
20696
+ processGroupId: entry.processGroupId,
20697
+ processId: entry.processId
20698
+ }));
20699
+ }
20700
+ function mergeProcessTrees(captured, current) {
20701
+ const processes = /* @__PURE__ */ new Map();
20702
+ for (const identity2 of captured) {
20703
+ processes.set(identity2.processId, identity2);
20704
+ }
20705
+ for (const identity2 of current) {
20706
+ processes.set(identity2.processId, identity2);
20707
+ }
20708
+ return [...processes.values()];
20709
+ }
20710
+ async function captureProcessTree(child) {
20711
+ if (process.platform === "win32" || child.pid === void 0) {
20712
+ return [];
20713
+ }
20714
+ return selectProcessTree(await readProcessTable(), child.pid);
20715
+ }
20716
+ function signalDetachedProcessGroups(processes, rootProcessId, signal) {
20717
+ const processIds = new Set(processes.map((identity2) => identity2.processId));
20718
+ const signalledGroups = /* @__PURE__ */ new Set();
20719
+ for (const identity2 of processes) {
20720
+ if (identity2.processGroupId === rootProcessId || !processIds.has(identity2.processGroupId) || signalledGroups.has(identity2.processGroupId)) {
20721
+ continue;
20722
+ }
20723
+ try {
20724
+ process.kill(-identity2.processGroupId, signal);
20725
+ signalledGroups.add(identity2.processGroupId);
20726
+ } catch {
20727
+ }
20728
+ }
20729
+ for (const identity2 of processes) {
20730
+ if (identity2.processId === rootProcessId || identity2.processGroupId === rootProcessId || signalledGroups.has(identity2.processGroupId)) {
20731
+ continue;
20732
+ }
20733
+ try {
20734
+ process.kill(identity2.processId, signal);
20735
+ } catch {
20736
+ }
20737
+ }
20738
+ }
20739
+ function processExists(processId) {
20740
+ try {
20741
+ process.kill(processId, 0);
20742
+ return true;
20743
+ } catch {
20744
+ return false;
20745
+ }
20746
+ }
20747
+ async function waitForCapturedProcessesExit(processes, rootProcessId) {
20748
+ const processIds = processes.map((identity2) => identity2.processId).filter((processId) => processId !== rootProcessId);
20749
+ for (let attempt = 0; attempt < PROCESS_EXIT_CHECK_ATTEMPTS; attempt += 1) {
20750
+ if (processIds.every((processId) => !processExists(processId))) {
20751
+ return true;
20752
+ }
20753
+ await readProcessTable();
20754
+ }
20755
+ return processIds.every((processId) => !processExists(processId));
20756
+ }
20757
+ function terminateProcess(child) {
20758
+ if (child.exitCode !== null || child.signalCode !== null || child.pid === void 0) {
20759
+ return;
20760
+ }
20761
+ if (process.platform !== "win32") {
20762
+ try {
20763
+ process.kill(-child.pid, "SIGTERM");
20764
+ return;
20765
+ } catch {
20766
+ }
20767
+ }
20768
+ child.kill("SIGTERM");
20769
+ }
20770
+ function forceTerminateProcess(child) {
20771
+ if (child.exitCode !== null || child.signalCode !== null || child.pid === void 0) {
20772
+ return;
20773
+ }
20774
+ if (process.platform !== "win32") {
20775
+ try {
20776
+ process.kill(-child.pid, "SIGKILL");
20777
+ return;
20778
+ } catch {
20779
+ }
20780
+ }
20781
+ child.kill("SIGKILL");
20782
+ }
20783
+ async function stopProcessTree(child, capturedProcesses = []) {
20784
+ const childProcessId = child.pid;
20785
+ if (childProcessId === void 0) {
20786
+ return;
20787
+ }
20788
+ const childExited = child.exitCode !== null || child.signalCode !== null;
20789
+ if (childExited && capturedProcesses.length === 0) {
20790
+ return;
20791
+ }
20792
+ const processes = mergeProcessTrees(
20793
+ capturedProcesses,
20794
+ childExited ? [] : await captureProcessTree(child)
20795
+ );
20796
+ signalDetachedProcessGroups(processes, childProcessId, GRACEFUL_STOP_SIGNAL);
20797
+ terminateProcess(child);
20798
+ const [exitedAfterTermination, descendantsExitedAfterTermination] = await Promise.all([
20799
+ waitForProcessExit(child, PROCESS_GRACEFUL_STOP_TIMEOUT_MILLISECONDS),
20800
+ waitForCapturedProcessesExit(processes, childProcessId)
20801
+ ]);
20802
+ if (exitedAfterTermination && descendantsExitedAfterTermination) {
20803
+ return;
20804
+ }
20805
+ signalDetachedProcessGroups(processes, childProcessId, FORCED_STOP_SIGNAL);
20806
+ forceTerminateProcess(child);
20807
+ const [exitedAfterForce, descendantsExitedAfterForce] = await Promise.all([
20808
+ waitForProcessExit(child, PROCESS_FORCED_STOP_TIMEOUT_MILLISECONDS),
20809
+ waitForCapturedProcessesExit(processes, childProcessId)
20810
+ ]);
20811
+ if (!exitedAfterForce || !descendantsExitedAfterForce) {
20812
+ throw new ProcessExecutionError(
20813
+ "process_termination_timeout",
20814
+ "The executable process could not be stopped"
20815
+ );
20816
+ }
20817
+ }
20818
+ function waitForProcessExit(child, timeoutMilliseconds) {
20819
+ if (child.exitCode !== null || child.signalCode !== null) {
20820
+ return Promise.resolve(true);
20821
+ }
20822
+ return new Promise((resolveExit) => {
20823
+ let settled = false;
20824
+ const finish = (exited) => {
20825
+ if (settled) {
20826
+ return;
20827
+ }
20828
+ settled = true;
20829
+ clearTimeout(timeout);
20830
+ child.removeListener("exit", handleExit);
20831
+ resolveExit(exited);
20832
+ };
20833
+ const handleExit = () => finish(true);
20834
+ const timeout = setTimeout(() => finish(false), timeoutMilliseconds);
20835
+ child.once("exit", handleExit);
20836
+ if (child.exitCode !== null || child.signalCode !== null) {
20837
+ finish(true);
20838
+ }
20839
+ });
20840
+ }
20841
+ async function runBoundedProcess(options) {
20842
+ options.signal.throwIfAborted();
20843
+ const outputLimitBytes = options.outputLimitBytes ?? DEFAULT_OUTPUT_LIMIT_BYTES;
20844
+ const child = spawn(options.command, [...options.arguments], {
20845
+ cwd: options.cwd,
20846
+ detached: process.platform !== "win32",
20847
+ env: { ...options.environment },
20848
+ shell: false,
20849
+ stdio: ["ignore", "pipe", "pipe"]
20850
+ });
20851
+ const stdout = [];
20852
+ const stderr = [];
20853
+ let stdoutBytes = 0;
20854
+ let stderrBytes = 0;
20855
+ let interruptionFailure = null;
20856
+ let interruptionCleanupFailure = null;
20857
+ let stopping = false;
20858
+ const interrupted = Promise.withResolvers();
20859
+ const interrupt = (failure) => {
20860
+ if (stopping) {
20861
+ return;
20862
+ }
20863
+ stopping = true;
20864
+ interruptionFailure = failure;
20865
+ const stop = async () => {
20866
+ try {
20867
+ await stopProcessTree(child);
20868
+ } catch (error61) {
20869
+ interruptionCleanupFailure = error61 instanceof ProcessExecutionError ? error61 : new ProcessExecutionError(
20870
+ "process_termination_failed",
20871
+ "The executable process could not be stopped",
20872
+ { cause: error61 }
20873
+ );
20874
+ } finally {
20875
+ interrupted.resolve();
20876
+ }
20877
+ };
20878
+ void stop();
20879
+ };
20880
+ const collectStdout = (chunk) => {
20881
+ if (interruptionFailure !== null) {
20882
+ return;
20883
+ }
20884
+ try {
20885
+ stdoutBytes = appendBounded(stdout, chunk, stdoutBytes, outputLimitBytes);
20886
+ } catch (error61) {
20887
+ const failure = error61 instanceof ProcessExecutionError ? error61 : new ProcessExecutionError(
20888
+ "process_output_limit",
20889
+ "The executable produced too much output",
20890
+ { cause: error61 }
20891
+ );
20892
+ interrupt(failure);
20893
+ }
20894
+ };
20895
+ const collectStderr = (chunk) => {
20896
+ if (interruptionFailure !== null) {
20897
+ return;
20898
+ }
20899
+ try {
20900
+ stderrBytes = appendBounded(stderr, chunk, stderrBytes, outputLimitBytes);
20901
+ } catch (error61) {
20902
+ const failure = error61 instanceof ProcessExecutionError ? error61 : new ProcessExecutionError(
20903
+ "process_output_limit",
20904
+ "The executable produced too much output",
20905
+ { cause: error61 }
20906
+ );
20907
+ interrupt(failure);
20908
+ }
20909
+ };
20910
+ child.stdout?.on("data", collectStdout);
20911
+ child.stderr?.on("data", collectStderr);
20912
+ const timeout = setTimeout(() => {
20913
+ interrupt(
20914
+ new ProcessExecutionError(
20915
+ "process_timeout",
20916
+ "The executable probe timed out"
20917
+ )
20918
+ );
20919
+ }, options.timeoutMilliseconds);
20920
+ const abort = () => interrupt(
20921
+ new ProcessExecutionError(
20922
+ "process_cancelled",
20923
+ "The executable probe was cancelled",
20924
+ { cause: options.signal.reason }
20925
+ )
20926
+ );
20927
+ options.signal.addEventListener("abort", abort, { once: true });
20928
+ if (options.signal.aborted) {
20929
+ abort();
21090
20930
  }
21091
- const decoded = schema.safeParse(value);
21092
- if (!decoded.success) {
21093
- throw new ProtocolMessageError("Message does not match its schema", {
21094
- cause: decoded.error
20931
+ try {
20932
+ const exit = new Promise((resolveExit, rejectExit) => {
20933
+ child.once("error", rejectExit);
20934
+ child.once("exit", (code) => resolveExit(code ?? 1));
21095
20935
  });
20936
+ const exitCode = await Promise.race([
20937
+ exit,
20938
+ interrupted.promise.then(() => -1)
20939
+ ]);
20940
+ if (interruptionCleanupFailure !== null) {
20941
+ throw interruptionCleanupFailure;
20942
+ }
20943
+ if (interruptionFailure !== null) {
20944
+ throw interruptionFailure;
20945
+ }
20946
+ if (exitCode !== 0) {
20947
+ throw new ProcessExecutionError(
20948
+ "process_exit_failed",
20949
+ "The executable probe failed"
20950
+ );
20951
+ }
20952
+ return new ProcessResult(
20953
+ Buffer.concat(stdout).toString("utf8"),
20954
+ Buffer.concat(stderr).toString("utf8")
20955
+ );
20956
+ } catch (error61) {
20957
+ if (error61 instanceof ProcessExecutionError) {
20958
+ throw error61;
20959
+ }
20960
+ throw new ProcessExecutionError(
20961
+ "process_spawn_failed",
20962
+ "The executable could not be started",
20963
+ { cause: error61 }
20964
+ );
20965
+ } finally {
20966
+ clearTimeout(timeout);
20967
+ options.signal.removeEventListener("abort", abort);
20968
+ child.stdout?.removeListener("data", collectStdout);
20969
+ child.stderr?.removeListener("data", collectStderr);
20970
+ if (stopping) {
20971
+ await interrupted.promise;
20972
+ } else {
20973
+ await stopProcessTree(child);
20974
+ }
20975
+ }
20976
+ }
20977
+
20978
+ // src/agent-catalog/local-agent.ts
20979
+ function readTrustedIdentity(path2) {
20980
+ const resolvedPath = realpathSync(path2);
20981
+ const metadata = statSync(resolvedPath);
20982
+ return new ExecutableIdentity(
20983
+ resolvedPath,
20984
+ resolvedPath,
20985
+ metadata.dev,
20986
+ metadata.ino,
20987
+ metadata.size,
20988
+ metadata.ctimeMs
20989
+ );
20990
+ }
20991
+ var LocalAgentDefinition = class {
20992
+ adapterIdentity;
20993
+ adapterPath;
20994
+ adapterVersion;
20995
+ agentIdentity;
20996
+ agentVersion;
20997
+ arguments;
20998
+ command;
20999
+ environment;
21000
+ id;
21001
+ label;
21002
+ promptTimeoutMilliseconds;
21003
+ constructor(id, label, command, arguments_, environment = {}, adapterVersion = "", agentVersion = "", adapterIdentity = readTrustedIdentity(command), agentIdentity = adapterIdentity, promptTimeoutMilliseconds = 30 * 60 * 1e3) {
21004
+ if (!Number.isSafeInteger(promptTimeoutMilliseconds) || promptTimeoutMilliseconds < 1) {
21005
+ throw new Error("The local Agent prompt deadline is invalid");
21006
+ }
21007
+ this.adapterIdentity = adapterIdentity;
21008
+ this.adapterPath = adapterIdentity.realPath;
21009
+ this.adapterVersion = adapterVersion;
21010
+ this.agentIdentity = agentIdentity;
21011
+ this.agentVersion = agentVersion;
21012
+ this.id = id;
21013
+ this.label = label;
21014
+ this.promptTimeoutMilliseconds = promptTimeoutMilliseconds;
21015
+ this.command = adapterIdentity.realPath;
21016
+ this.arguments = Object.freeze([...arguments_]);
21017
+ this.environment = Object.freeze({ ...environment });
21018
+ }
21019
+ };
21020
+ var InstallableAgentDefinition = class {
21021
+ id;
21022
+ label;
21023
+ constructor(id, label) {
21024
+ this.id = id;
21025
+ this.label = label;
21026
+ }
21027
+ };
21028
+ var LocalAgentCatalogSnapshot = class {
21029
+ agents;
21030
+ installableAgents;
21031
+ constructor(agents, installableAgents) {
21032
+ this.agents = Object.freeze([...agents]);
21033
+ this.installableAgents = Object.freeze([...installableAgents]);
21034
+ }
21035
+ };
21036
+ var LocalAgentCatalogError = class extends Error {
21037
+ code = "agent_not_ready";
21038
+ constructor() {
21039
+ super("The requested local Agent is not ready");
21040
+ this.name = "LocalAgentCatalogError";
21041
+ }
21042
+ };
21043
+ var LocalAgentCatalog = class {
21044
+ #snapshot;
21045
+ constructor(agents, installableAgents) {
21046
+ this.#snapshot = this.validate(agents, installableAgents);
21047
+ }
21048
+ find = (agentId) => {
21049
+ for (const agent of this.#snapshot.agents) {
21050
+ if (agent.id === agentId) {
21051
+ return agent;
21052
+ }
21053
+ }
21054
+ throw new LocalAgentCatalogError();
21055
+ };
21056
+ read = () => this.#snapshot;
21057
+ transition = (agents, installableAgents) => {
21058
+ const next = this.validate(agents, installableAgents);
21059
+ this.#snapshot = next;
21060
+ return next;
21061
+ };
21062
+ validate = (agents, installableAgents) => {
21063
+ const identifiers = /* @__PURE__ */ new Set();
21064
+ for (const agent of agents) {
21065
+ if (identifiers.has(agent.id)) {
21066
+ throw new Error("The local Agent catalog contains duplicate entries");
21067
+ }
21068
+ identifiers.add(agent.id);
21069
+ }
21070
+ for (const agent of installableAgents) {
21071
+ if (identifiers.has(agent.id)) {
21072
+ throw new Error("A local Agent cannot be ready and installable");
21073
+ }
21074
+ identifiers.add(agent.id);
21075
+ }
21076
+ return new LocalAgentCatalogSnapshot(agents, installableAgents);
21077
+ };
21078
+ };
21079
+
21080
+ // src/storage/state-directory.ts
21081
+ import { homedir } from "node:os";
21082
+ import { join as join2, resolve as resolve2 } from "node:path";
21083
+ function readStateDirectory(environment = process.env) {
21084
+ const configured = environment["MOBIUS_STATE_DIRECTORY"]?.trim();
21085
+ if (configured !== void 0 && configured.length > 0) {
21086
+ return resolve2(configured);
21096
21087
  }
21097
- return decoded.data;
21088
+ return join2(homedir(), ".mobius");
21098
21089
  }
21099
- var encode4 = (message, schema) => {
21100
- const decoded = schema.safeParse(message);
21101
- if (!decoded.success) {
21102
- throw new ProtocolMessageError("Message does not match its schema", {
21103
- cause: decoded.error
21104
- });
21090
+
21091
+ // src/config.ts
21092
+ function loadDefaultWorkspace() {
21093
+ const { MOBIUS_DEFAULT_WORKSPACE: configuredWorkspace } = process.env;
21094
+ return configuredWorkspace ?? join3(readStateDirectory(), "workspace");
21095
+ }
21096
+ function createDaemonConfig(connection, agents = [], installableAgents = []) {
21097
+ return {
21098
+ agents,
21099
+ defaultWorkspace: connection.defaultWorkspace,
21100
+ auditDatabasePath: connection.auditDatabasePath,
21101
+ bindingId: "workspace",
21102
+ catalog: new LocalAgentCatalog(agents, installableAgents),
21103
+ channelId: connection.channelId,
21104
+ installableAgents,
21105
+ relayUrl: connection.relayUrl
21106
+ };
21107
+ }
21108
+ function loadDaemonConfig() {
21109
+ const relayUrl = new URL(
21110
+ // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
21111
+ process.env["MOBIUS_RELAY_URL"] ?? `ws://127.0.0.1:8787${mobiusApiPath("/channels/local/daemon")}`
21112
+ );
21113
+ relayUrl.searchParams.set(
21114
+ "token",
21115
+ // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
21116
+ process.env["MOBIUS_RELAY_TOKEN"] ?? "local-development-token"
21117
+ );
21118
+ if (relayUrl.protocol !== "ws:" && relayUrl.protocol !== "wss:") {
21119
+ throw new Error("MOBIUS_RELAY_URL must use ws or wss");
21105
21120
  }
21106
- return JSON.stringify(decoded.data);
21107
- };
21108
- var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
21109
- var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
21121
+ return createDaemonConfig(
21122
+ {
21123
+ defaultWorkspace: loadDefaultWorkspace(),
21124
+ auditDatabasePath: (
21125
+ // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
21126
+ process.env["MOBIUS_AUDIT_DATABASE"] ?? fileURLToPath(
21127
+ new URL("../../../.mobius/daemon.sqlite", import.meta.url)
21128
+ )
21129
+ ),
21130
+ // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
21131
+ channelId: process.env["MOBIUS_CHANNEL_ID"] ?? "local",
21132
+ relayUrl
21133
+ },
21134
+ [],
21135
+ []
21136
+ );
21137
+ }
21138
+
21139
+ // src/acp/session-manager.ts
21140
+ import { spawn as spawn2 } from "node:child_process";
21141
+ import {
21142
+ methods as methods2,
21143
+ ndJsonStream,
21144
+ PROTOCOL_VERSION,
21145
+ RequestError
21146
+ } from "@agentclientprotocol/sdk";
21110
21147
 
21111
21148
  // src/acp/activity.ts
21112
21149
  var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
@@ -24147,58 +24184,16 @@ var LocalAuthorizationError = class extends Error {
24147
24184
  import { randomUUID } from "node:crypto";
24148
24185
  import {
24149
24186
  mkdir as mkdir3,
24150
- open as open6,
24151
- realpath as realpath5,
24187
+ open as open5,
24188
+ realpath as realpath6,
24152
24189
  rename as rename3,
24153
24190
  stat as stat5,
24154
24191
  writeFile as writeFile2
24155
24192
  } from "node:fs/promises";
24156
24193
  import { hostname as hostname3 } from "node:os";
24157
- import { basename, join as join13, resolve as resolve3 } from "node:path";
24194
+ import { basename, join as join14, resolve as resolve3 } from "node:path";
24158
24195
  import { fetch as fetch2 } from "undici";
24159
24196
 
24160
- // src/agent-installation/installation-grants.ts
24161
- import { open as open2 } from "node:fs/promises";
24162
- import { join as join4 } from "node:path";
24163
- var MAX_GRANT_FILE_LENGTH = 16 * 1024;
24164
- var AGENT_ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
24165
- function isRecord4(value) {
24166
- return typeof value === "object" && value !== null && !Array.isArray(value);
24167
- }
24168
- async function readGrantedAgents(stateDirectory) {
24169
- const path2 = join4(stateDirectory, "installation-grants.json");
24170
- let handle;
24171
- try {
24172
- handle = await open2(path2, "r");
24173
- } catch (error61) {
24174
- if (error61 instanceof Error && "code" in error61 && error61.code === "ENOENT") {
24175
- return /* @__PURE__ */ new Set();
24176
- }
24177
- throw error61;
24178
- }
24179
- try {
24180
- const metadata = await handle.stat();
24181
- if (!metadata.isFile() || metadata.size > MAX_GRANT_FILE_LENGTH || typeof process.getuid === "function" && metadata.uid !== process.getuid() || process.platform !== "win32" && (metadata.mode & 63) !== 0) {
24182
- throw new Error("The local installation grant file is not private");
24183
- }
24184
- const encoded = await handle.readFile({ encoding: "utf8" });
24185
- const value = JSON.parse(encoded);
24186
- if (!isRecord4(value) || Object.keys(value).length !== 1 || !Array.isArray(value["agents"])) {
24187
- throw new Error("The local installation grant file is invalid");
24188
- }
24189
- const agents = /* @__PURE__ */ new Set();
24190
- for (const candidate of value["agents"]) {
24191
- if (typeof candidate !== "string" || !AGENT_ID_PATTERN.test(candidate) || agents.has(candidate)) {
24192
- throw new Error("The local installation grant file is invalid");
24193
- }
24194
- agents.add(candidate);
24195
- }
24196
- return agents;
24197
- } finally {
24198
- await handle.close();
24199
- }
24200
- }
24201
-
24202
24197
  // src/agent-catalog/agent-discovery.ts
24203
24198
  var AgentDiscovery = class {
24204
24199
  specification;
@@ -24263,7 +24258,7 @@ var LocalAgentInventory = class {
24263
24258
  discoveries;
24264
24259
  installable;
24265
24260
  unavailable;
24266
- constructor(discoveries, grantedAgents = /* @__PURE__ */ new Set(), platform = process.platform, architecture = process.arch) {
24261
+ constructor(discoveries, platform = process.platform, architecture = process.arch) {
24267
24262
  const available = [];
24268
24263
  const unavailable = [];
24269
24264
  for (const discovery of discoveries) {
@@ -24286,8 +24281,7 @@ var LocalAgentInventory = class {
24286
24281
  ).map(
24287
24282
  (discovery) => new InstallableAgentDefinition(
24288
24283
  discovery.specification.id,
24289
- discovery.specification.label,
24290
- !grantedAgents.has(discovery.specification.id)
24284
+ discovery.specification.label
24291
24285
  )
24292
24286
  )
24293
24287
  );
@@ -24300,13 +24294,13 @@ var LocalAgentInventory = class {
24300
24294
  import {
24301
24295
  mkdir,
24302
24296
  mkdtemp,
24303
- open as open3,
24297
+ open as open2,
24304
24298
  realpath as realpath2,
24305
24299
  rename,
24306
24300
  rm,
24307
24301
  stat as stat2
24308
24302
  } from "node:fs/promises";
24309
- import { delimiter, dirname as dirname3, isAbsolute, join as join5, relative, sep } from "node:path";
24303
+ import { delimiter, dirname as dirname3, isAbsolute, join as join4, relative, sep } from "node:path";
24310
24304
  var INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
24311
24305
  var PACKAGE_METADATA_LIMIT_BYTES = 64 * 1024;
24312
24306
  var PACKAGE_LOCK_LIMIT_BYTES = 8 * 1024 * 1024;
@@ -24325,6 +24319,7 @@ var ManagedNpmPackageDefinition = class {
24325
24319
  };
24326
24320
  var SriManagedNpmPackageDefinition = class extends ManagedNpmPackageDefinition {
24327
24321
  integrity;
24322
+ requiredDependencies = Object.freeze([]);
24328
24323
  tarballUrl;
24329
24324
  constructor(packageName, version2, executableName, integrity, tarballUrl) {
24330
24325
  super(packageName, version2, executableName);
@@ -24332,6 +24327,18 @@ var SriManagedNpmPackageDefinition = class extends ManagedNpmPackageDefinition {
24332
24327
  this.tarballUrl = tarballUrl;
24333
24328
  }
24334
24329
  };
24330
+ var SriManagedNpmDependencyDefinition = class {
24331
+ integrity;
24332
+ packageName;
24333
+ tarballUrl;
24334
+ version;
24335
+ constructor(packageName, version2, integrity, tarballUrl) {
24336
+ this.integrity = integrity;
24337
+ this.packageName = packageName;
24338
+ this.tarballUrl = tarballUrl;
24339
+ this.version = version2;
24340
+ }
24341
+ };
24335
24342
  var ManagedNpmPackageError = class extends Error {
24336
24343
  code;
24337
24344
  constructor(code, message, options = {}) {
@@ -24340,11 +24347,11 @@ var ManagedNpmPackageError = class extends Error {
24340
24347
  this.name = "ManagedNpmPackageError";
24341
24348
  }
24342
24349
  };
24343
- function isRecord5(value) {
24350
+ function isRecord4(value) {
24344
24351
  return typeof value === "object" && value !== null && !Array.isArray(value);
24345
24352
  }
24346
24353
  function packagePath(root, packageName) {
24347
- return join5(root, "node_modules", ...packageName.split("/"));
24354
+ return join4(root, "node_modules", ...packageName.split("/"));
24348
24355
  }
24349
24356
  function isContainedPath(root, candidate) {
24350
24357
  const difference = relative(root, candidate);
@@ -24352,7 +24359,7 @@ function isContainedPath(root, candidate) {
24352
24359
  }
24353
24360
  async function readJsonRecord(path2, maximumBytes) {
24354
24361
  try {
24355
- const handle = await open3(path2, "r");
24362
+ const handle = await open2(path2, "r");
24356
24363
  try {
24357
24364
  const metadata = await handle.stat();
24358
24365
  if (!metadata.isFile() || metadata.size > maximumBytes) {
@@ -24364,7 +24371,7 @@ async function readJsonRecord(path2, maximumBytes) {
24364
24371
  const value = JSON.parse(
24365
24372
  await handle.readFile({ encoding: "utf8" })
24366
24373
  );
24367
- if (!isRecord5(value)) {
24374
+ if (!isRecord4(value)) {
24368
24375
  throw new ManagedNpmPackageError(
24369
24376
  "managed_package_verification_failed",
24370
24377
  "The managed npm package metadata is invalid"
@@ -24390,7 +24397,7 @@ function readBinPath(packageMetadata, executableName) {
24390
24397
  if (typeof bin === "string") {
24391
24398
  return bin;
24392
24399
  }
24393
- if (isRecord5(bin) && typeof bin[executableName] === "string") {
24400
+ if (isRecord4(bin) && typeof bin[executableName] === "string") {
24394
24401
  return bin[executableName];
24395
24402
  }
24396
24403
  throw new ManagedNpmPackageError(
@@ -24398,7 +24405,7 @@ function readBinPath(packageMetadata, executableName) {
24398
24405
  "The managed npm package executable declaration is invalid"
24399
24406
  );
24400
24407
  }
24401
- function verifyPackageLock(lock, definition) {
24408
+ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
24402
24409
  if (lock["lockfileVersion"] !== 3) {
24403
24410
  throw new ManagedNpmPackageError(
24404
24411
  "managed_package_verification_failed",
@@ -24406,7 +24413,7 @@ function verifyPackageLock(lock, definition) {
24406
24413
  );
24407
24414
  }
24408
24415
  const packages = lock["packages"];
24409
- if (!isRecord5(packages)) {
24416
+ if (!isRecord4(packages)) {
24410
24417
  throw new ManagedNpmPackageError(
24411
24418
  "managed_package_verification_failed",
24412
24419
  "The managed npm package lockfile is invalid"
@@ -24417,10 +24424,10 @@ function verifyPackageLock(lock, definition) {
24417
24424
  let matches = 0;
24418
24425
  for (const [key, candidate] of Object.entries(packages)) {
24419
24426
  const normalizedKey = key.replaceAll("\\", "/");
24420
- if (definition.verifyDependencyClosure && normalizedKey.length > 0) {
24427
+ if (verifyDependencyClosure && normalizedKey.length > 0) {
24421
24428
  let resolved;
24422
24429
  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") {
24430
+ if (!normalizedKey.split("/").includes("node_modules") || !isRecord4(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
24431
  throw new Error("Invalid locked dependency");
24425
24432
  }
24426
24433
  resolved = new URL(candidate["resolved"]);
@@ -24443,13 +24450,35 @@ function verifyPackageLock(lock, definition) {
24443
24450
  matches += 1;
24444
24451
  }
24445
24452
  }
24446
- if (matches !== 1 || !isRecord5(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
24453
+ if (matches !== 1 || !isRecord4(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
24447
24454
  throw new ManagedNpmPackageError(
24448
24455
  "managed_package_verification_failed",
24449
24456
  "The managed npm package lockfile does not match the pinned artifact"
24450
24457
  );
24451
24458
  }
24452
24459
  }
24460
+ async function verifyRequiredDependency(rootPath, lock, definition) {
24461
+ const dependencyRoot = await realpath2(
24462
+ packagePath(rootPath, definition.packageName)
24463
+ );
24464
+ if (!isContainedPath(rootPath, dependencyRoot)) {
24465
+ throw new ManagedNpmPackageError(
24466
+ "managed_package_verification_failed",
24467
+ "The required managed npm dependency escaped its private cache"
24468
+ );
24469
+ }
24470
+ const metadata = await readJsonRecord(
24471
+ join4(dependencyRoot, "package.json"),
24472
+ PACKAGE_METADATA_LIMIT_BYTES
24473
+ );
24474
+ if (metadata["name"] !== definition.packageName || metadata["version"] !== definition.version) {
24475
+ throw new ManagedNpmPackageError(
24476
+ "managed_package_verification_failed",
24477
+ "The required managed npm dependency identity is invalid"
24478
+ );
24479
+ }
24480
+ verifyPackageLockEntry(lock, definition, false);
24481
+ }
24453
24482
  async function validateManagedNpmPackage(root, definition) {
24454
24483
  try {
24455
24484
  return await validateManagedNpmPackageContents(root, definition);
@@ -24476,7 +24505,7 @@ async function validateManagedNpmPackageContents(root, definition) {
24476
24505
  );
24477
24506
  }
24478
24507
  const metadata = await readJsonRecord(
24479
- join5(packageRoot, "package.json"),
24508
+ join4(packageRoot, "package.json"),
24480
24509
  PACKAGE_METADATA_LIMIT_BYTES
24481
24510
  );
24482
24511
  if (metadata["name"] !== definition.packageName || metadata["version"] !== definition.version) {
@@ -24486,17 +24515,22 @@ async function validateManagedNpmPackageContents(root, definition) {
24486
24515
  );
24487
24516
  }
24488
24517
  if (definition instanceof SriManagedNpmPackageDefinition) {
24489
- verifyPackageLock(
24490
- await readJsonRecord(
24491
- join5(rootPath, "package-lock.json"),
24492
- PACKAGE_LOCK_LIMIT_BYTES
24493
- ),
24494
- definition
24518
+ const lock = await readJsonRecord(
24519
+ join4(rootPath, "package-lock.json"),
24520
+ PACKAGE_LOCK_LIMIT_BYTES
24495
24521
  );
24522
+ verifyPackageLockEntry(
24523
+ lock,
24524
+ definition,
24525
+ definition.verifyDependencyClosure
24526
+ );
24527
+ for (const dependency of definition.requiredDependencies) {
24528
+ await verifyRequiredDependency(rootPath, lock, dependency);
24529
+ }
24496
24530
  }
24497
24531
  const declaredBin = readBinPath(metadata, definition.executableName);
24498
24532
  const executable = await resolveExecutablePath(
24499
- join5(packageRoot, declaredBin)
24533
+ join4(packageRoot, declaredBin)
24500
24534
  );
24501
24535
  if (executable === null || !isContainedPath(rootPath, executable.path)) {
24502
24536
  throw new ManagedNpmPackageError(
@@ -24522,7 +24556,7 @@ var ManagedNpmPackageInstaller = class {
24522
24556
  const parent = dirname3(root);
24523
24557
  await mkdir(parent, { mode: 448, recursive: true });
24524
24558
  const staging = await mkdtemp(
24525
- join5(parent, `.${definition.version}.staging-`)
24559
+ join4(parent, `.${definition.version}.staging-`)
24526
24560
  );
24527
24561
  try {
24528
24562
  const npm = await findExecutableOnPath(
@@ -24552,9 +24586,9 @@ var ManagedNpmPackageInstaller = class {
24552
24586
  `${definition.packageName}@${definition.version}`
24553
24587
  );
24554
24588
  const installEnvironment = {
24555
- HOME: join5(staging, "home"),
24589
+ HOME: join4(staging, "home"),
24556
24590
  NPM_CONFIG_AUDIT: "false",
24557
- NPM_CONFIG_CACHE: join5(staging, ".npm-cache"),
24591
+ NPM_CONFIG_CACHE: join4(staging, ".npm-cache"),
24558
24592
  NPM_CONFIG_FUND: "false",
24559
24593
  NPM_CONFIG_IGNORE_SCRIPTS: "true",
24560
24594
  NPM_CONFIG_PACKAGE_LOCK: "true",
@@ -24576,8 +24610,8 @@ var ManagedNpmPackageInstaller = class {
24576
24610
  timeoutMilliseconds: INSTALL_TIMEOUT_MILLISECONDS
24577
24611
  });
24578
24612
  await Promise.all([
24579
- rm(join5(staging, ".npm-cache"), { force: true, recursive: true }),
24580
- rm(join5(staging, "home"), { force: true, recursive: true })
24613
+ rm(join4(staging, ".npm-cache"), { force: true, recursive: true }),
24614
+ rm(join4(staging, "home"), { force: true, recursive: true })
24581
24615
  ]);
24582
24616
  await validateManagedNpmPackage(staging, definition);
24583
24617
  try {
@@ -24613,7 +24647,7 @@ var ManagedNpmPackageInstaller = class {
24613
24647
  };
24614
24648
 
24615
24649
  // src/agent-catalog/agent-specification.ts
24616
- import { join as join6 } from "node:path";
24650
+ import { join as join5 } from "node:path";
24617
24651
  var VERSION_PROBE_TIMEOUT_MILLISECONDS = 3e3;
24618
24652
  var ACP_PROBE_TIMEOUT_MILLISECONDS = 5e3;
24619
24653
  var DEFAULT_PROMPT_TIMEOUT_MILLISECONDS = 30 * 60 * 1e3;
@@ -24627,7 +24661,7 @@ var LocalAgentSpecification = class {
24627
24661
  resolveManagedAgent = async (stateDirectory, platform, signal) => {
24628
24662
  signal.throwIfAborted();
24629
24663
  const executable = await resolveExecutablePath(
24630
- join6(stateDirectory, ...this.managedAgentExecutablePath),
24664
+ join5(stateDirectory, ...this.managedAgentExecutablePath),
24631
24665
  platform
24632
24666
  );
24633
24667
  signal.throwIfAborted();
@@ -24732,9 +24766,84 @@ var CodexAgentSpecification = class extends BridgedAcpAgentDefinition {
24732
24766
  managedAgentExecutablePath = ["agents", "codex", "bin", "codex"];
24733
24767
  };
24734
24768
 
24769
+ // src/agent-catalog/agent-probe-error.ts
24770
+ var AgentProbeError = class extends Error {
24771
+ code;
24772
+ constructor(code, message, options = {}) {
24773
+ super(message, options);
24774
+ this.code = code;
24775
+ this.name = "AgentProbeError";
24776
+ }
24777
+ };
24778
+
24779
+ // src/agent-catalog/agents/verify-session-creation.ts
24780
+ import {
24781
+ methods as methods3
24782
+ } from "@agentclientprotocol/sdk";
24783
+ async function verifySessionCreation(connection, capabilities, defaultWorkspace, signal, label) {
24784
+ const session = await connection.agent.request(
24785
+ methods3.agent.session.new,
24786
+ {
24787
+ additionalDirectories: [],
24788
+ cwd: defaultWorkspace,
24789
+ mcpServers: []
24790
+ },
24791
+ { cancellationSignal: signal }
24792
+ );
24793
+ if (session.sessionId.length === 0) {
24794
+ throw new AgentProbeError(
24795
+ "acp_incompatible",
24796
+ `${label} returned an invalid ACP session`
24797
+ );
24798
+ }
24799
+ if (capabilities.sessionCapabilities?.close != null) {
24800
+ await connection.agent.request(
24801
+ methods3.agent.session.close,
24802
+ { sessionId: session.sessionId },
24803
+ { cancellationSignal: signal }
24804
+ );
24805
+ }
24806
+ }
24807
+
24808
+ // src/agent-catalog/agents/cursor-cli-agent.ts
24809
+ var CURSOR_CLI_TESTED_VERSION = "2026.09.02-c22c1a3";
24810
+ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
24811
+ adapterVersion = CURSOR_CLI_TESTED_VERSION;
24812
+ authenticationCommand = () => "cursor-agent login";
24813
+ agentExecutable = "cursor-agent";
24814
+ id = "cursor";
24815
+ label = "Cursor CLI";
24816
+ constructor() {
24817
+ super(
24818
+ "MOBIUS_CURSOR_PATH",
24819
+ ["--disable-auto-update", "acp"],
24820
+ ["agents", "cursor", CURSOR_CLI_TESTED_VERSION, "bin", "cursor-agent"]
24821
+ );
24822
+ }
24823
+ supportsInstallation = (_platform, _architecture) => false;
24824
+ verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
24825
+ const capabilities = initialized.agentCapabilities ?? {};
24826
+ if (capabilities.loadSession !== true || capabilities.sessionCapabilities?.list == null || !(initialized.authMethods ?? []).some(
24827
+ (method) => method.id === "cursor_login"
24828
+ )) {
24829
+ throw new AgentProbeError(
24830
+ "acp_incompatible",
24831
+ "Cursor CLI reported an unsupported ACP capability set"
24832
+ );
24833
+ }
24834
+ await verifySessionCreation(
24835
+ connection,
24836
+ capabilities,
24837
+ defaultWorkspace,
24838
+ signal,
24839
+ this.label
24840
+ );
24841
+ };
24842
+ };
24843
+
24735
24844
  // src/agent-catalog/agents/deepseek-harness-agent.ts
24736
24845
  import { realpath as realpath3, stat as stat3 } from "node:fs/promises";
24737
- import { isAbsolute as isAbsolute2, join as join7, normalize } from "node:path";
24846
+ import { isAbsolute as isAbsolute2, join as join6, normalize } from "node:path";
24738
24847
 
24739
24848
  // src/agent-installation/deepseek-managed-package.ts
24740
24849
  var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
@@ -24752,16 +24861,6 @@ var DEEPSEEK_HARNESS_PACKAGE = new DeepSeekHarnessManagedPackage(
24752
24861
  "https://registry.npmjs.org/@deepseek-ai/dsh/-/dsh-0.1.2-rc.1.tgz"
24753
24862
  );
24754
24863
 
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
24864
  // src/agent-catalog/agents/deepseek-harness-agent.ts
24766
24865
  async function validateAgentHome(path2) {
24767
24866
  if (!isAbsolute2(path2) || normalize(path2) !== path2) {
@@ -24819,7 +24918,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
24819
24918
  context.signal
24820
24919
  );
24821
24920
  if (managed.path === agent.path) {
24822
- selectedHome = join7(
24921
+ selectedHome = join6(
24823
24922
  readStateDirectory(context.environment),
24824
24923
  "agents",
24825
24924
  this.id,
@@ -24840,7 +24939,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
24840
24939
  resolveManagedAgent = async (stateDirectory, _platform, signal) => {
24841
24940
  signal.throwIfAborted();
24842
24941
  const executable = await validateManagedNpmPackage(
24843
- join7(stateDirectory, "agents", this.id, DEEPSEEK_HARNESS_PACKAGE.version),
24942
+ join6(stateDirectory, "agents", this.id, DEEPSEEK_HARNESS_PACKAGE.version),
24844
24943
  DEEPSEEK_HARNESS_PACKAGE
24845
24944
  );
24846
24945
  signal.throwIfAborted();
@@ -24860,6 +24959,166 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
24860
24959
  };
24861
24960
  };
24862
24961
 
24962
+ // src/agent-catalog/agents/grok-build-agent.ts
24963
+ import { realpath as realpath4 } from "node:fs/promises";
24964
+ import { isAbsolute as isAbsolute3, join as join7, relative as relative2, sep as sep2 } from "node:path";
24965
+
24966
+ // src/agent-installation/grok-managed-package.ts
24967
+ var GROK_BUILD_MANAGED_VERSION = "1.0.21";
24968
+ var GrokBuildManagedPackage = class extends SriManagedNpmPackageDefinition {
24969
+ dependencyResolutionArguments = Object.freeze([
24970
+ "--before=2026-09-04T19:51:47.325Z"
24971
+ ]);
24972
+ includeOptionalDependencies = true;
24973
+ requiredDependencies;
24974
+ verifyDependencyClosure = true;
24975
+ constructor(requiredDependency) {
24976
+ super(
24977
+ "@xai-official/grok",
24978
+ GROK_BUILD_MANAGED_VERSION,
24979
+ "grok",
24980
+ "sha512-6yQqC+h1o+ObaqCxImK23dhkrOX1DEBMOKaH6fCK+B4gX0/8XIKZp0n7iKyBdK8KZa5vhMn7pS45kjX49Tps5g==",
24981
+ "https://registry.npmjs.org/@xai-official/grok/-/grok-1.0.21.tgz"
24982
+ );
24983
+ this.requiredDependencies = Object.freeze([requiredDependency]);
24984
+ }
24985
+ };
24986
+ var GROK_DARWIN_ARM64_PACKAGE = new SriManagedNpmDependencyDefinition(
24987
+ "@xai-official/grok-darwin-arm64",
24988
+ GROK_BUILD_MANAGED_VERSION,
24989
+ "sha512-I4pKZGnR6Mv4MJOJsB9B/i2o0ODF4eZtp4jHN5feoTqKIeAUVg38OzBtE8aN/wZa7Xg+qhnf6Jd1tcAFvMoFtQ==",
24990
+ "https://registry.npmjs.org/@xai-official/grok-darwin-arm64/-/grok-darwin-arm64-1.0.21.tgz"
24991
+ );
24992
+ var GROK_DARWIN_X64_PACKAGE = new SriManagedNpmDependencyDefinition(
24993
+ "@xai-official/grok-darwin-x64",
24994
+ GROK_BUILD_MANAGED_VERSION,
24995
+ "sha512-h0nFj3NZ9Kz8w6fQ6UDxxeSIhC1WjwwoRE92iNbG//tZy6YGkppR3s7oRVtt4Xl0CJANKUt0EusyIYnnAvKLzw==",
24996
+ "https://registry.npmjs.org/@xai-official/grok-darwin-x64/-/grok-darwin-x64-1.0.21.tgz"
24997
+ );
24998
+ var GROK_LINUX_ARM64_PACKAGE = new SriManagedNpmDependencyDefinition(
24999
+ "@xai-official/grok-linux-arm64",
25000
+ GROK_BUILD_MANAGED_VERSION,
25001
+ "sha512-Jlwz9XtZPNKz/V/ydifC8OVu3hIZz7pmoStt8c4KCqkSWjWiZ/PBIC0iJiq8rvByhx5Z0EdSyq8ZXVwtocceGA==",
25002
+ "https://registry.npmjs.org/@xai-official/grok-linux-arm64/-/grok-linux-arm64-1.0.21.tgz"
25003
+ );
25004
+ var GROK_LINUX_X64_PACKAGE = new SriManagedNpmDependencyDefinition(
25005
+ "@xai-official/grok-linux-x64",
25006
+ GROK_BUILD_MANAGED_VERSION,
25007
+ "sha512-AjDV5ifEz5LFG2Jt5IlhAeEkJati/wOvCchVbR4eIj2ogjvmXoXlzBrYRXuAJpXBy5q0se/Yuez5FxDU9Ju81w==",
25008
+ "https://registry.npmjs.org/@xai-official/grok-linux-x64/-/grok-linux-x64-1.0.21.tgz"
25009
+ );
25010
+ function grokBuildManagedPackage(platform, architecture) {
25011
+ if (platform === "darwin" && architecture === "arm64") {
25012
+ return new GrokBuildManagedPackage(GROK_DARWIN_ARM64_PACKAGE);
25013
+ }
25014
+ if (platform === "darwin" && architecture === "x64") {
25015
+ return new GrokBuildManagedPackage(GROK_DARWIN_X64_PACKAGE);
25016
+ }
25017
+ if (platform === "linux" && architecture === "arm64") {
25018
+ return new GrokBuildManagedPackage(GROK_LINUX_ARM64_PACKAGE);
25019
+ }
25020
+ if (platform === "linux" && architecture === "x64") {
25021
+ return new GrokBuildManagedPackage(GROK_LINUX_X64_PACKAGE);
25022
+ }
25023
+ throw new Error("Grok Build does not publish a package for this platform");
25024
+ }
25025
+
25026
+ // src/agent-catalog/agents/grok-build-agent.ts
25027
+ function isContainedPath2(root, candidate) {
25028
+ const difference = relative2(root, candidate);
25029
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute3(difference);
25030
+ }
25031
+ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
25032
+ adapterVersion = GROK_BUILD_MANAGED_VERSION;
25033
+ authenticationCommand = () => "grok login";
25034
+ agentExecutable = "grok";
25035
+ agentVersionArguments = ["version"];
25036
+ adapterVersionArguments = ["version"];
25037
+ id = "grok-build";
25038
+ label = "Grok Build";
25039
+ constructor() {
25040
+ super(
25041
+ "MOBIUS_GROK_BUILD_PATH",
25042
+ ["--no-auto-update", "agent", "stdio"],
25043
+ [
25044
+ "agents",
25045
+ "grok-build",
25046
+ GROK_BUILD_MANAGED_VERSION,
25047
+ "home",
25048
+ "bin",
25049
+ "grok"
25050
+ ]
25051
+ );
25052
+ }
25053
+ createLaunchEnvironment = async (agent, context) => {
25054
+ const stateDirectory = readStateDirectory(context.environment);
25055
+ try {
25056
+ const managed = await this.resolveManagedAgent(
25057
+ stateDirectory,
25058
+ context.platform ?? process.platform,
25059
+ context.signal
25060
+ );
25061
+ if (managed.path === agent.path) {
25062
+ return Object.freeze({
25063
+ GROK_HOME: await realpath4(
25064
+ join7(
25065
+ stateDirectory,
25066
+ "agents",
25067
+ this.id,
25068
+ GROK_BUILD_MANAGED_VERSION,
25069
+ "home"
25070
+ )
25071
+ )
25072
+ });
25073
+ }
25074
+ } catch {
25075
+ context.signal.throwIfAborted();
25076
+ }
25077
+ return Object.freeze({});
25078
+ };
25079
+ resolveManagedAgent = async (stateDirectory, platform, signal) => {
25080
+ signal.throwIfAborted();
25081
+ const versionRoot = await realpath4(
25082
+ join7(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION)
25083
+ );
25084
+ await validateManagedNpmPackage(
25085
+ join7(versionRoot, "package"),
25086
+ grokBuildManagedPackage(platform, process.arch)
25087
+ );
25088
+ const executable = await resolveExecutablePath(
25089
+ join7(versionRoot, "home", "bin", "grok"),
25090
+ platform
25091
+ );
25092
+ signal.throwIfAborted();
25093
+ if (executable === null || !isContainedPath2(versionRoot, executable.path)) {
25094
+ throw new AgentProbeError(
25095
+ "managed_agent_invalid",
25096
+ "The managed Grok Build executable is invalid"
25097
+ );
25098
+ }
25099
+ return executable;
25100
+ };
25101
+ verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
25102
+ const capabilities = initialized.agentCapabilities ?? {};
25103
+ const session = capabilities.sessionCapabilities;
25104
+ if (capabilities.loadSession !== true || session?.close == null || session.list == null || session.resume == null || !(initialized.authMethods ?? []).some(
25105
+ (method) => method.id === "xai.api_key" || method.id === "grok.com"
25106
+ )) {
25107
+ throw new AgentProbeError(
25108
+ "acp_incompatible",
25109
+ "Grok Build reported an unsupported ACP capability set"
25110
+ );
25111
+ }
25112
+ await verifySessionCreation(
25113
+ connection,
25114
+ capabilities,
25115
+ defaultWorkspace,
25116
+ signal,
25117
+ this.label
25118
+ );
25119
+ };
25120
+ };
25121
+
24863
25122
  // src/agent-catalog/agents/opencode-agent.ts
24864
25123
  import { join as join9 } from "node:path";
24865
25124
 
@@ -24871,18 +25130,18 @@ import {
24871
25130
  copyFile,
24872
25131
  mkdir as mkdir2,
24873
25132
  mkdtemp as mkdtemp2,
24874
- open as open5,
24875
- realpath as realpath4,
25133
+ open as open4,
25134
+ realpath as realpath5,
24876
25135
  rename as rename2,
24877
25136
  rm as rm2,
24878
25137
  stat as stat4,
24879
25138
  writeFile
24880
25139
  } from "node:fs/promises";
24881
- import { dirname as dirname4, isAbsolute as isAbsolute3, join as join8, relative as relative2, sep as sep2 } from "node:path";
25140
+ import { dirname as dirname4, isAbsolute as isAbsolute4, join as join8, relative as relative3, sep as sep3 } from "node:path";
24882
25141
 
24883
25142
  // src/agent-installation/verified-download.ts
24884
25143
  import { createHash } from "node:crypto";
24885
- import { open as open4, unlink } from "node:fs/promises";
25144
+ import { open as open3, unlink } from "node:fs/promises";
24886
25145
  import { fetch } from "undici";
24887
25146
 
24888
25147
  // src/network/environment-proxy.ts
@@ -25014,7 +25273,7 @@ async function downloadVerifiedFile(options, transport = new UndiciInstallerDown
25014
25273
  );
25015
25274
  }
25016
25275
  }
25017
- handle = await open4(options.destination, "wx", 384);
25276
+ handle = await open3(options.destination, "wx", 384);
25018
25277
  const digest = createHash("sha256");
25019
25278
  const reader = fetched.response.body.getReader();
25020
25279
  let bytes = 0;
@@ -25124,12 +25383,12 @@ var ManagedAgentArchiveError = class extends Error {
25124
25383
  var ManagedAgentArchiveDownloader = class {
25125
25384
  download = async (options) => await downloadVerifiedFile(options);
25126
25385
  };
25127
- function isRecord6(value) {
25386
+ function isRecord5(value) {
25128
25387
  return typeof value === "object" && value !== null && !Array.isArray(value);
25129
25388
  }
25130
- function isContainedPath2(root, candidate) {
25131
- const difference = relative2(root, candidate);
25132
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute3(difference);
25389
+ function isContainedPath3(root, candidate) {
25390
+ const difference = relative3(root, candidate);
25391
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute4(difference);
25133
25392
  }
25134
25393
  async function hashFile(path2, signal) {
25135
25394
  signal.throwIfAborted();
@@ -25164,7 +25423,7 @@ async function hashFile(path2, signal) {
25164
25423
  async function readManifest(path2) {
25165
25424
  let handle;
25166
25425
  try {
25167
- handle = await open5(path2, "r");
25426
+ handle = await open4(path2, "r");
25168
25427
  } catch (error61) {
25169
25428
  throw new ManagedAgentArchiveError(
25170
25429
  "managed_archive_verification_failed",
@@ -25183,7 +25442,7 @@ async function readManifest(path2) {
25183
25442
  const parsed = JSON.parse(
25184
25443
  await handle.readFile({ encoding: "utf8" })
25185
25444
  );
25186
- if (!isRecord6(parsed)) {
25445
+ if (!isRecord5(parsed)) {
25187
25446
  throw new ManagedAgentArchiveError(
25188
25447
  "managed_archive_verification_failed",
25189
25448
  "The managed Agent archive manifest is invalid"
@@ -25205,7 +25464,7 @@ async function readManifest(path2) {
25205
25464
  }
25206
25465
  async function validateManagedAgentArchive(root, definition, signal) {
25207
25466
  try {
25208
- const rootPath = await realpath4(root);
25467
+ const rootPath = await realpath5(root);
25209
25468
  const rootMetadata = await stat4(rootPath);
25210
25469
  if (!rootMetadata.isDirectory() || typeof process.getuid === "function" && rootMetadata.uid !== process.getuid()) {
25211
25470
  throw new Error("Managed Agent root is not user-owned");
@@ -25217,7 +25476,7 @@ async function validateManagedAgentArchive(root, definition, signal) {
25217
25476
  const executable = await resolveExecutablePath(
25218
25477
  join8(rootPath, "bin", definition.executableName)
25219
25478
  );
25220
- if (executable === null || !isContainedPath2(rootPath, executable.path) || await hashFile(executable.path, signal) !== manifest["executableSha256"]) {
25479
+ if (executable === null || !isContainedPath3(rootPath, executable.path) || await hashFile(executable.path, signal) !== manifest["executableSha256"]) {
25221
25480
  throw new Error("Managed Agent executable is invalid");
25222
25481
  }
25223
25482
  return executable;
@@ -25273,7 +25532,7 @@ var ManagedAgentArchiveInstaller = class {
25273
25532
  const archivePath = join8(working, definition.archiveName);
25274
25533
  const extractionRoot = join8(working, "extracted");
25275
25534
  await mkdir2(extractionRoot, { mode: 448 });
25276
- const canonicalExtractionRoot = await realpath4(extractionRoot);
25535
+ const canonicalExtractionRoot = await realpath5(extractionRoot);
25277
25536
  const download = await this.#downloader.download({
25278
25537
  allowedHosts: /* @__PURE__ */ new Set([
25279
25538
  "github.com",
@@ -25311,11 +25570,11 @@ var ManagedAgentArchiveInstaller = class {
25311
25570
  signal,
25312
25571
  timeoutMilliseconds: ARCHIVE_EXTRACTION_TIMEOUT_MILLISECONDS
25313
25572
  });
25314
- const extracted = await realpath4(
25573
+ const extracted = await realpath5(
25315
25574
  join8(canonicalExtractionRoot, definition.executableName)
25316
25575
  );
25317
25576
  const extractedMetadata = await stat4(extracted);
25318
- if (!isContainedPath2(canonicalExtractionRoot, extracted) || !extractedMetadata.isFile()) {
25577
+ if (!isContainedPath3(canonicalExtractionRoot, extracted) || !extractedMetadata.isFile()) {
25319
25578
  throw new ManagedAgentArchiveError(
25320
25579
  "managed_archive_verification_failed",
25321
25580
  "The managed Agent archive executable is invalid"
@@ -25470,7 +25729,7 @@ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
25470
25729
  // src/agent-catalog/agents/pi-agent.ts
25471
25730
  import { join as join10 } from "node:path";
25472
25731
  import {
25473
- methods as methods3
25732
+ methods as methods4
25474
25733
  } from "@agentclientprotocol/sdk";
25475
25734
 
25476
25735
  // src/agent-installation/pi-managed-packages.ts
@@ -25542,7 +25801,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
25542
25801
  );
25543
25802
  }
25544
25803
  const session = await connection.agent.request(
25545
- methods3.agent.session.new,
25804
+ methods4.agent.session.new,
25546
25805
  {
25547
25806
  additionalDirectories: [],
25548
25807
  cwd: defaultWorkspace,
@@ -25557,7 +25816,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
25557
25816
  );
25558
25817
  }
25559
25818
  const prompt = await connection.agent.request(
25560
- methods3.agent.session.prompt,
25819
+ methods4.agent.session.prompt,
25561
25820
  {
25562
25821
  prompt: [{ text: "/session", type: "text" }],
25563
25822
  sessionId: session.sessionId
@@ -25573,6 +25832,77 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
25573
25832
  };
25574
25833
  };
25575
25834
 
25835
+ // src/agent-catalog/agents/workbuddy-agent.ts
25836
+ import { join as join11 } from "node:path";
25837
+
25838
+ // src/agent-installation/workbuddy-managed-package.ts
25839
+ var WORKBUDDY_MANAGED_VERSION = "2.146.0";
25840
+ var WorkBuddyManagedPackage = class extends SriManagedNpmPackageDefinition {
25841
+ dependencyResolutionArguments = Object.freeze([
25842
+ "--before=2026-09-05T12:39:25.295Z"
25843
+ ]);
25844
+ includeOptionalDependencies = true;
25845
+ verifyDependencyClosure = true;
25846
+ };
25847
+ var WORKBUDDY_MANAGED_PACKAGE = new WorkBuddyManagedPackage(
25848
+ "@tencent-ai/codebuddy-code",
25849
+ WORKBUDDY_MANAGED_VERSION,
25850
+ "codebuddy",
25851
+ "sha512-81V+8rzYJY8PezHZMs4VZN2nvoijrsRWIuCERTr6hELotcxaZaAcqbQQSbHJcN8eTlFE5TRPlzMI4oEkLCat4A==",
25852
+ "https://registry.npmjs.org/@tencent-ai/codebuddy-code/-/codebuddy-code-2.146.0.tgz"
25853
+ );
25854
+
25855
+ // src/agent-catalog/agents/workbuddy-agent.ts
25856
+ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
25857
+ adapterVersion = WORKBUDDY_MANAGED_VERSION;
25858
+ authenticationCommand = () => "codebuddy";
25859
+ agentExecutable = "codebuddy";
25860
+ id = "workbuddy";
25861
+ label = "WorkBuddy";
25862
+ constructor() {
25863
+ super(
25864
+ "MOBIUS_WORKBUDDY_PATH",
25865
+ ["--acp"],
25866
+ [
25867
+ "agents",
25868
+ "workbuddy",
25869
+ WORKBUDDY_MANAGED_VERSION,
25870
+ "node_modules",
25871
+ "@tencent-ai",
25872
+ "codebuddy-code",
25873
+ "bin",
25874
+ "codebuddy"
25875
+ ]
25876
+ );
25877
+ }
25878
+ createLaunchEnvironment = () => Promise.resolve(Object.freeze({ DISABLE_AUTOUPDATER: "1" }));
25879
+ resolveManagedAgent = async (stateDirectory, _platform, signal) => {
25880
+ signal.throwIfAborted();
25881
+ const executable = await validateManagedNpmPackage(
25882
+ join11(stateDirectory, "agents", this.id, WORKBUDDY_MANAGED_VERSION),
25883
+ WORKBUDDY_MANAGED_PACKAGE
25884
+ );
25885
+ signal.throwIfAborted();
25886
+ return executable;
25887
+ };
25888
+ verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
25889
+ const capabilities = initialized.agentCapabilities ?? {};
25890
+ if (capabilities.loadSession !== true || (initialized.authMethods ?? []).length === 0) {
25891
+ throw new AgentProbeError(
25892
+ "acp_incompatible",
25893
+ "WorkBuddy reported an unsupported ACP capability set"
25894
+ );
25895
+ }
25896
+ await verifySessionCreation(
25897
+ connection,
25898
+ capabilities,
25899
+ defaultWorkspace,
25900
+ signal,
25901
+ this.label
25902
+ );
25903
+ };
25904
+ };
25905
+
25576
25906
  // src/agent-catalog/agents/supported-agent-specifications.ts
25577
25907
  function supportedLocalAgentSpecifications() {
25578
25908
  return Object.freeze([
@@ -25580,24 +25910,27 @@ function supportedLocalAgentSpecifications() {
25580
25910
  new ClaudeCodeAgentSpecification(),
25581
25911
  new PiAgentSpecification(),
25582
25912
  new DeepSeekHarnessAgentSpecification(),
25583
- new OpenCodeAgentSpecification()
25913
+ new OpenCodeAgentSpecification(),
25914
+ new CursorCliAgentSpecification(),
25915
+ new GrokBuildAgentSpecification(),
25916
+ new WorkBuddyAgentSpecification()
25584
25917
  ]);
25585
25918
  }
25586
25919
 
25587
25920
  // src/agent-catalog/acp-readiness-probe.ts
25588
25921
  import { spawn as spawn3 } from "node:child_process";
25589
25922
  import {
25590
- methods as methods4,
25923
+ methods as methods5,
25591
25924
  ndJsonStream as ndJsonStream2,
25592
25925
  PROTOCOL_VERSION as PROTOCOL_VERSION2,
25593
25926
  RequestError as RequestError2
25594
25927
  } from "@agentclientprotocol/sdk";
25595
25928
 
25596
25929
  // src/agent-catalog/executable-discovery.ts
25597
- import { isAbsolute as isAbsolute4, join as join12 } from "node:path";
25930
+ import { isAbsolute as isAbsolute5, join as join13 } from "node:path";
25598
25931
 
25599
25932
  // src/agent-installation/managed-adapter-installer.ts
25600
- import { join as join11 } from "node:path";
25933
+ import { join as join12 } from "node:path";
25601
25934
  var ManagedAdapterInstallError = class extends Error {
25602
25935
  code;
25603
25936
  constructor(code, message, options = {}) {
@@ -25659,7 +25992,7 @@ var ManagedAdapterInstaller = class {
25659
25992
  this.#stateDirectory = options.stateDirectory;
25660
25993
  }
25661
25994
  install = async (specification, signal) => {
25662
- const root = join11(
25995
+ const root = join12(
25663
25996
  this.#stateDirectory,
25664
25997
  "adapters",
25665
25998
  specification.id,
@@ -25698,7 +26031,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
25698
26031
  let managed;
25699
26032
  try {
25700
26033
  managed = await validateManagedAdapter(
25701
- join12(
26034
+ join13(
25702
26035
  readStateDirectory(context.environment),
25703
26036
  "adapters",
25704
26037
  specification.id,
@@ -25714,7 +26047,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
25714
26047
  async function resolveSpecificationExecutables(executableName, overrideVariable, resolveManaged, context) {
25715
26048
  const override = context.environment[overrideVariable];
25716
26049
  if (override !== void 0) {
25717
- if (override.length === 0 || !isAbsolute4(override)) {
26050
+ if (override.length === 0 || !isAbsolute5(override)) {
25718
26051
  return [];
25719
26052
  }
25720
26053
  const executable = await resolveExecutablePath(override, context.platform);
@@ -25825,41 +26158,41 @@ var DiscoveryAcpHandler = class {
25825
26158
  };
25826
26159
  function readableAcpStream(input2) {
25827
26160
  let byteLength = 0;
25828
- let open7 = true;
26161
+ let open6 = true;
25829
26162
  return new ReadableStream({
25830
26163
  start(controller) {
25831
26164
  input2.on("data", (chunk) => {
25832
- if (!open7) {
26165
+ if (!open6) {
25833
26166
  return;
25834
26167
  }
25835
26168
  if (!(chunk instanceof Uint8Array)) {
25836
- open7 = false;
26169
+ open6 = false;
25837
26170
  controller.error(new Error("ACP adapter produced invalid output"));
25838
26171
  return;
25839
26172
  }
25840
26173
  byteLength += chunk.byteLength;
25841
26174
  if (byteLength > ACP_OUTPUT_LIMIT_BYTES) {
25842
- open7 = false;
26175
+ open6 = false;
25843
26176
  controller.error(new Error("ACP adapter output limit exceeded"));
25844
26177
  return;
25845
26178
  }
25846
26179
  controller.enqueue(new Uint8Array(chunk));
25847
26180
  });
25848
26181
  input2.once("end", () => {
25849
- if (open7) {
25850
- open7 = false;
26182
+ if (open6) {
26183
+ open6 = false;
25851
26184
  controller.close();
25852
26185
  }
25853
26186
  });
25854
26187
  input2.once("error", (error61) => {
25855
- if (open7) {
25856
- open7 = false;
26188
+ if (open6) {
26189
+ open6 = false;
25857
26190
  controller.error(error61);
25858
26191
  }
25859
26192
  });
25860
26193
  },
25861
26194
  cancel() {
25862
- open7 = false;
26195
+ open6 = false;
25863
26196
  }
25864
26197
  });
25865
26198
  }
@@ -25928,7 +26261,7 @@ async function probeAcpReadiness(specification, agent, environment, defaultWorks
25928
26261
  try {
25929
26262
  const initialized = await Promise.race([
25930
26263
  connection.agent.request(
25931
- methods4.agent.initialize,
26264
+ methods5.agent.initialize,
25932
26265
  {
25933
26266
  clientCapabilities: {},
25934
26267
  clientInfo: { name: "mobius", version: "0.0.3" },
@@ -26139,16 +26472,8 @@ async function discoverLocalAgentInventory(options) {
26139
26472
  async (specification) => await discoverAgent(specification, options)
26140
26473
  )
26141
26474
  );
26142
- let grantedAgents = /* @__PURE__ */ new Set();
26143
- try {
26144
- grantedAgents = await readGrantedAgents(
26145
- readStateDirectory(options.environment)
26146
- );
26147
- } catch {
26148
- }
26149
26475
  return new LocalAgentInventory(
26150
26476
  discoveries,
26151
- grantedAgents,
26152
26477
  options.platform,
26153
26478
  options.architecture
26154
26479
  );
@@ -26179,7 +26504,7 @@ var PairingClientError = class extends Error {
26179
26504
  this.name = "PairingClientError";
26180
26505
  }
26181
26506
  };
26182
- function isRecord7(value) {
26507
+ function isRecord6(value) {
26183
26508
  return typeof value === "object" && value !== null && !Array.isArray(value);
26184
26509
  }
26185
26510
  function hasExactKeys(value, expectedKeys) {
@@ -26293,7 +26618,7 @@ async function resolveDefaultWorkspace(path2) {
26293
26618
  const requestedWorkspace = resolve3(path2);
26294
26619
  try {
26295
26620
  await mkdir3(requestedWorkspace, { recursive: true, mode: 448 });
26296
- const defaultWorkspace = await realpath5(requestedWorkspace);
26621
+ const defaultWorkspace = await realpath6(requestedWorkspace);
26297
26622
  const metadata = await stat5(defaultWorkspace);
26298
26623
  if (!metadata.isDirectory()) {
26299
26624
  throw new PairingClientError(
@@ -26332,9 +26657,9 @@ async function readJsonResponse(response) {
26332
26657
  }
26333
26658
  }
26334
26659
  function readRelayError(value) {
26335
- if (isRecord7(value)) {
26660
+ if (isRecord6(value)) {
26336
26661
  const error61 = value["error"];
26337
- if (isRecord7(error61)) {
26662
+ if (isRecord6(error61)) {
26338
26663
  const code = error61["code"];
26339
26664
  const message = error61["message"];
26340
26665
  if (typeof code === "string" && typeof message === "string") {
@@ -26348,7 +26673,7 @@ function readRelayError(value) {
26348
26673
  );
26349
26674
  }
26350
26675
  function decodeClaimResponse(value) {
26351
- if (!isRecord7(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
26676
+ if (!isRecord6(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
26352
26677
  throw new PairingClientError(
26353
26678
  "invalid_relay_response",
26354
26679
  "The relay returned an invalid pairing response"
@@ -26370,7 +26695,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
26370
26695
  id: agent.id,
26371
26696
  label: agent.label
26372
26697
  }));
26373
- const endpoint = new URL("/mobius/api/pairings/claim", options.relayOrigin);
26698
+ const endpoint = mobiusApiUrl(options.relayOrigin, "/pairings/claim");
26374
26699
  let response;
26375
26700
  try {
26376
26701
  response = await fetch2(endpoint, {
@@ -26378,8 +26703,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
26378
26703
  agents,
26379
26704
  installableAgents: installableAgents.map((agent) => ({
26380
26705
  id: agent.id,
26381
- label: agent.label,
26382
- requiresLocalApproval: agent.requiresLocalApproval
26706
+ label: agent.label
26383
26707
  })),
26384
26708
  machineName: hostname3(),
26385
26709
  pairingCode: options.code,
@@ -26407,10 +26731,10 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
26407
26731
  return decodeClaimResponse(value);
26408
26732
  }
26409
26733
  async function persistConnection(channelId, relayOrigin, daemonToken, defaultWorkspace) {
26410
- const connectionsDirectory = join13(readStateDirectory(), "connections");
26734
+ const connectionsDirectory = join14(readStateDirectory(), "connections");
26411
26735
  await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
26412
- const connectionPath = join13(connectionsDirectory, `${channelId}.json`);
26413
- const temporaryPath = join13(
26736
+ const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
26737
+ const temporaryPath = join14(
26414
26738
  connectionsDirectory,
26415
26739
  `.${channelId}.${randomUUID()}.tmp`
26416
26740
  );
@@ -26433,7 +26757,7 @@ async function persistConnection(channelId, relayOrigin, daemonToken, defaultWor
26433
26757
  return connectionPath;
26434
26758
  }
26435
26759
  function decodeSavedConnection(value, expectedChannelId) {
26436
- if (!isRecord7(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
26760
+ if (!isRecord6(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
26437
26761
  throw new PairingClientError(
26438
26762
  "invalid_connection",
26439
26763
  "The saved connection is invalid"
@@ -26457,13 +26781,13 @@ function decodeSavedConnection(value, expectedChannelId) {
26457
26781
  };
26458
26782
  }
26459
26783
  async function readSavedConnection(channelId) {
26460
- const connectionPath = join13(
26784
+ const connectionPath = join14(
26461
26785
  readStateDirectory(),
26462
26786
  "connections",
26463
26787
  `${channelId}.json`
26464
26788
  );
26465
26789
  let encoded = "";
26466
- const handle = await open6(connectionPath, "r");
26790
+ const handle = await open5(connectionPath, "r");
26467
26791
  try {
26468
26792
  const metadata = await handle.stat();
26469
26793
  if (!metadata.isFile() || metadata.size > MAX_CONNECTION_FILE_LENGTH) {
@@ -26506,13 +26830,13 @@ function assertInventoryUsable(inventory) {
26506
26830
  }
26507
26831
  function buildPairedDaemon(connection, connectionPath, inventory) {
26508
26832
  assertInventoryUsable(inventory);
26509
- const relayUrl = new URL(
26510
- `/mobius/api/channels/${encodeURIComponent(connection.channelId)}/daemon`,
26511
- connection.relayOrigin
26833
+ const relayUrl = mobiusApiUrl(
26834
+ connection.relayOrigin,
26835
+ `/channels/${encodeURIComponent(connection.channelId)}/daemon`
26512
26836
  );
26513
26837
  relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
26514
26838
  relayUrl.searchParams.set("token", connection.daemonToken);
26515
- const auditDatabasePath = join13(
26839
+ const auditDatabasePath = join14(
26516
26840
  readStateDirectory(),
26517
26841
  "audit",
26518
26842
  `${connection.channelId}.sqlite`
@@ -26571,7 +26895,7 @@ async function pairLocalMachine(arguments_, signal = new AbortController().signa
26571
26895
  }
26572
26896
  async function resumeLocalMachine(arguments_, signal = new AbortController().signal) {
26573
26897
  const channelId = parseChannelArgument(arguments_);
26574
- const connectionPath = join13(
26898
+ const connectionPath = join14(
26575
26899
  readStateDirectory(),
26576
26900
  "connections",
26577
26901
  `${channelId}.json`
@@ -26626,8 +26950,7 @@ async function publishAgentCatalog(config2, signal) {
26626
26950
  })),
26627
26951
  installableAgents: catalog.installableAgents.map((agent) => ({
26628
26952
  id: agent.id,
26629
- label: agent.label,
26630
- requiresLocalApproval: agent.requiresLocalApproval
26953
+ label: agent.label
26631
26954
  }))
26632
26955
  }),
26633
26956
  dispatcher: environmentProxyDispatcher,
@@ -26668,12 +26991,6 @@ var RequestedInstallation = class extends AgentInstallation {
26668
26991
  super(requestId, agentId);
26669
26992
  }
26670
26993
  };
26671
- var AwaitingLocalApproval = class extends AgentInstallation {
26672
- status = "awaiting_local_approval";
26673
- constructor(requestId, agentId) {
26674
- super(requestId, agentId);
26675
- }
26676
- };
26677
26994
  var RunningInstallation = class extends AgentInstallation {
26678
26995
  stage;
26679
26996
  status = "running";
@@ -26728,9 +27045,9 @@ var InstallationJob = class {
26728
27045
  this.state = new RequestedInstallation(requestId, agentId);
26729
27046
  }
26730
27047
  };
26731
- function specificationFor(specifications, agentId) {
27048
+ function authorizedSpecificationFor(specifications, agentId) {
26732
27049
  for (const specification of specifications) {
26733
- if (specification.id === agentId) {
27050
+ if (specification.id === agentId && specification.supportsInstallation(process.platform, process.arch)) {
26734
27051
  return specification;
26735
27052
  }
26736
27053
  }
@@ -26749,14 +27066,12 @@ function executionFailure(error61) {
26749
27066
  var AgentInstallationManager = class {
26750
27067
  #activeAgents = /* @__PURE__ */ new Map();
26751
27068
  #audit;
26752
- #authorizer;
26753
27069
  #executor;
26754
27070
  #jobs = /* @__PURE__ */ new Map();
26755
27071
  #observer;
26756
27072
  #specifications;
26757
- constructor(specifications, authorizer, executor, observer, audit = new NullInstallationAudit()) {
27073
+ constructor(specifications, executor, observer, audit = new NullInstallationAudit()) {
26758
27074
  this.#audit = audit;
26759
- this.#authorizer = authorizer;
26760
27075
  this.#executor = executor;
26761
27076
  this.#observer = observer;
26762
27077
  this.#specifications = Object.freeze([...specifications]);
@@ -26787,7 +27102,7 @@ var AgentInstallationManager = class {
26787
27102
  command.requestId,
26788
27103
  command.agentId
26789
27104
  );
26790
- const specification = specificationFor(
27105
+ const specification = authorizedSpecificationFor(
26791
27106
  this.#specifications,
26792
27107
  command.agentId
26793
27108
  );
@@ -26890,45 +27205,14 @@ var AgentInstallationManager = class {
26890
27205
  }, INSTALLATION_DEADLINE_MILLISECONDS);
26891
27206
  const signal = job.controller.signal;
26892
27207
  try {
26893
- await this.#transition(
26894
- job,
26895
- new AwaitingLocalApproval(job.requestId, job.agentId)
26896
- );
26897
- this.#audit.record(
26898
- "agent_installation_awaiting_approval",
26899
- job.requestId,
26900
- job.agentId
26901
- );
26902
- const approved = await this.#authorizer.authorize(
26903
- specification.id,
26904
- specification.label,
26905
- job.requestId,
26906
- signal
26907
- );
26908
27208
  signal.throwIfAborted();
26909
- if (!approved) {
26910
- const denied = new FailedInstallation(
26911
- job.requestId,
26912
- job.agentId,
26913
- "installation_not_authorized",
26914
- "Installation was not approved on the local machine"
26915
- );
26916
- await this.#transition(job, denied);
26917
- this.#audit.record(
26918
- "agent_installation_denied",
26919
- job.requestId,
26920
- job.agentId
26921
- );
26922
- job.completion.resolve(denied);
26923
- return;
26924
- }
26925
27209
  this.#audit.record(
26926
27210
  "agent_installation_authorized",
26927
27211
  job.requestId,
26928
- job.agentId
27212
+ specification.id
26929
27213
  );
26930
27214
  await this.#executor.execute(
26931
- job.agentId,
27215
+ specification.id,
26932
27216
  job.requestId,
26933
27217
  async (stage) => {
26934
27218
  signal.throwIfAborted();
@@ -27198,12 +27482,10 @@ import { realpathSync as realpathSync2, statSync as statSync2 } from "node:fs";
27198
27482
  import { resolve as resolve4 } from "node:path";
27199
27483
 
27200
27484
  // src/agent-installation/fixed-agent-install-recipes.ts
27201
- import { mkdir as mkdir4, mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
27202
- import { join as join14 } from "node:path";
27203
- var INSTALLER_DOWNLOAD_LIMIT_BYTES = 1024 * 1024;
27204
- var INSTALLER_DOWNLOAD_TIMEOUT_MILLISECONDS = 6e4;
27205
- var AGENT_INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
27206
- var MINIMAL_PATH2 = "/usr/bin:/bin";
27485
+ import { mkdir as mkdir5, mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
27486
+ import { join as join17 } from "node:path";
27487
+
27488
+ // src/agent-installation/fixed-agent-install-recipe.ts
27207
27489
  var FixedAgentInstallRecipe = class {
27208
27490
  assertSupportedPlatform = () => {
27209
27491
  if (process.platform !== "darwin" && process.platform !== "linux" || process.arch !== "arm64" && process.arch !== "x64") {
@@ -27224,28 +27506,243 @@ var FixedAgentInstallRecipe = class {
27224
27506
  return executable;
27225
27507
  };
27226
27508
  };
27509
+
27510
+ // src/agent-installation/grok-build-install-recipe.ts
27511
+ import { mkdir as mkdir4, realpath as realpath7, stat as stat6 } from "node:fs/promises";
27512
+ import { delimiter as delimiter2, dirname as dirname5, isAbsolute as isAbsolute6, join as join15, relative as relative4, sep as sep4 } from "node:path";
27513
+ var INSTALL_TIMEOUT_MILLISECONDS2 = 5 * 60 * 1e3;
27514
+ function isContainedPath4(root, candidate) {
27515
+ const difference = relative4(root, candidate);
27516
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep4}`) && !isAbsolute6(difference);
27517
+ }
27518
+ async function resolveLifecycleScript(packageRoot) {
27519
+ try {
27520
+ const canonicalPackageRoot = await realpath7(packageRoot);
27521
+ const script = await realpath7(
27522
+ join15(canonicalPackageRoot, "bin", "postinstall.js")
27523
+ );
27524
+ const metadata = await stat6(script);
27525
+ if (!metadata.isFile() || !isContainedPath4(canonicalPackageRoot, script)) {
27526
+ throw new Error("Invalid Grok Build lifecycle script");
27527
+ }
27528
+ return script;
27529
+ } catch (error61) {
27530
+ throw new InstallationManagerError(
27531
+ "agent_verification_failed",
27532
+ "The managed Grok Build lifecycle script is invalid",
27533
+ { cause: error61 }
27534
+ );
27535
+ }
27536
+ }
27537
+ var GrokBuildInstallRecipe = class extends FixedAgentInstallRecipe {
27538
+ #npmInstaller;
27539
+ id = "grok-build";
27540
+ label = "Grok Build";
27541
+ releaseChannel = GROK_BUILD_MANAGED_VERSION;
27542
+ constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
27543
+ super();
27544
+ this.#npmInstaller = npmInstaller;
27545
+ }
27546
+ install = async (options) => {
27547
+ this.assertSupportedPlatform();
27548
+ const definition = grokBuildManagedPackage(process.platform, process.arch);
27549
+ const versionRoot = join15(
27550
+ options.stateDirectory,
27551
+ "agents",
27552
+ this.id,
27553
+ GROK_BUILD_MANAGED_VERSION
27554
+ );
27555
+ const packageRoot = join15(versionRoot, "package");
27556
+ const managedHome = join15(versionRoot, "home");
27557
+ try {
27558
+ await mkdir4(managedHome, { mode: 448, recursive: true });
27559
+ const canonicalHome = await realpath7(managedHome);
27560
+ await options.report("downloading");
27561
+ await options.report("verifying");
27562
+ await options.report("installing_agent");
27563
+ await this.#npmInstaller.install(
27564
+ packageRoot,
27565
+ definition,
27566
+ options.environment,
27567
+ options.signal
27568
+ );
27569
+ options.audit.record(
27570
+ "agent_npm_package_verified",
27571
+ options.requestId,
27572
+ this.id,
27573
+ {
27574
+ integrity: definition.integrity,
27575
+ package: definition.packageName,
27576
+ version: definition.version
27577
+ }
27578
+ );
27579
+ const script = await resolveLifecycleScript(
27580
+ join15(packageRoot, "node_modules", "@xai-official", "grok")
27581
+ );
27582
+ await runBoundedProcess({
27583
+ arguments: [script],
27584
+ command: process.execPath,
27585
+ cwd: dirname5(script),
27586
+ environment: {
27587
+ GROK_HOME: canonicalHome,
27588
+ GROK_INSTALL_COMPLETIONS: "0",
27589
+ GROK_NPM_REGISTRY: "https://registry.npmjs.org/",
27590
+ HOME: canonicalHome,
27591
+ PATH: `${dirname5(process.execPath)}${delimiter2}/usr/bin${delimiter2}/bin`
27592
+ },
27593
+ outputLimitBytes: 64 * 1024,
27594
+ signal: options.signal,
27595
+ timeoutMilliseconds: INSTALL_TIMEOUT_MILLISECONDS2
27596
+ });
27597
+ options.audit.record(
27598
+ "agent_lifecycle_step_completed",
27599
+ options.requestId,
27600
+ this.id,
27601
+ {
27602
+ lifecycle: "postinstall",
27603
+ package: definition.packageName,
27604
+ version: definition.version
27605
+ }
27606
+ );
27607
+ return await this.requireInstalledExecutable(
27608
+ join15(canonicalHome, "bin", "grok")
27609
+ );
27610
+ } catch (error61) {
27611
+ if (options.signal.aborted) {
27612
+ options.signal.throwIfAborted();
27613
+ }
27614
+ if (error61 instanceof ManagedNpmPackageError) {
27615
+ if (error61.code === "managed_package_verification_failed") {
27616
+ throw new InstallationManagerError(
27617
+ "agent_verification_failed",
27618
+ "The managed Grok Build packages did not match their pinned artifacts",
27619
+ { cause: error61 }
27620
+ );
27621
+ }
27622
+ if (error61.code === "managed_package_publish_failed") {
27623
+ throw new InstallationManagerError(
27624
+ "agent_publish_failed",
27625
+ "The managed Grok Build package could not be published",
27626
+ { cause: error61 }
27627
+ );
27628
+ }
27629
+ throw new InstallationManagerError(error61.code, error61.message, {
27630
+ cause: error61
27631
+ });
27632
+ }
27633
+ if (error61 instanceof InstallationManagerError) {
27634
+ throw error61;
27635
+ }
27636
+ throw new InstallationManagerError(
27637
+ "agent_install_failed",
27638
+ "The fixed Grok Build installation recipe failed",
27639
+ { cause: error61 }
27640
+ );
27641
+ }
27642
+ };
27643
+ };
27644
+
27645
+ // src/agent-installation/workbuddy-install-recipe.ts
27646
+ import { join as join16 } from "node:path";
27647
+ var WorkBuddyInstallRecipe = class extends FixedAgentInstallRecipe {
27648
+ #npmInstaller;
27649
+ id = "workbuddy";
27650
+ label = "WorkBuddy";
27651
+ releaseChannel = WORKBUDDY_MANAGED_VERSION;
27652
+ constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
27653
+ super();
27654
+ this.#npmInstaller = npmInstaller;
27655
+ }
27656
+ install = async (options) => {
27657
+ this.assertSupportedPlatform();
27658
+ try {
27659
+ await options.report("downloading");
27660
+ await options.report("verifying");
27661
+ await options.report("installing_agent");
27662
+ const executable = await this.#npmInstaller.install(
27663
+ join16(
27664
+ options.stateDirectory,
27665
+ "agents",
27666
+ this.id,
27667
+ WORKBUDDY_MANAGED_VERSION
27668
+ ),
27669
+ WORKBUDDY_MANAGED_PACKAGE,
27670
+ options.environment,
27671
+ options.signal
27672
+ );
27673
+ options.audit.record(
27674
+ "agent_npm_package_verified",
27675
+ options.requestId,
27676
+ this.id,
27677
+ {
27678
+ integrity: WORKBUDDY_MANAGED_PACKAGE.integrity,
27679
+ package: WORKBUDDY_MANAGED_PACKAGE.packageName,
27680
+ version: WORKBUDDY_MANAGED_PACKAGE.version
27681
+ }
27682
+ );
27683
+ return executable;
27684
+ } catch (error61) {
27685
+ if (options.signal.aborted) {
27686
+ options.signal.throwIfAborted();
27687
+ }
27688
+ if (error61 instanceof ManagedNpmPackageError) {
27689
+ if (error61.code === "managed_package_verification_failed") {
27690
+ throw new InstallationManagerError(
27691
+ "agent_verification_failed",
27692
+ "The managed WorkBuddy package did not match its pinned artifact",
27693
+ { cause: error61 }
27694
+ );
27695
+ }
27696
+ if (error61.code === "managed_package_publish_failed") {
27697
+ throw new InstallationManagerError(
27698
+ "agent_publish_failed",
27699
+ "The managed WorkBuddy package could not be published",
27700
+ { cause: error61 }
27701
+ );
27702
+ }
27703
+ throw new InstallationManagerError(error61.code, error61.message, {
27704
+ cause: error61
27705
+ });
27706
+ }
27707
+ if (error61 instanceof InstallationManagerError) {
27708
+ throw error61;
27709
+ }
27710
+ throw new InstallationManagerError(
27711
+ "agent_install_failed",
27712
+ "The fixed WorkBuddy installation recipe failed",
27713
+ { cause: error61 }
27714
+ );
27715
+ }
27716
+ };
27717
+ };
27718
+
27719
+ // src/agent-installation/fixed-agent-install-recipes.ts
27720
+ var INSTALLER_DOWNLOAD_LIMIT_BYTES = 1024 * 1024;
27721
+ var INSTALLER_DOWNLOAD_TIMEOUT_MILLISECONDS = 6e4;
27722
+ var AGENT_INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
27723
+ var MINIMAL_PATH2 = "/usr/bin:/bin";
27227
27724
  var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
27228
27725
  id = "codex";
27229
27726
  label = "Codex";
27230
27727
  releaseChannel = "latest";
27231
27728
  install = async (options) => {
27232
27729
  this.assertSupportedPlatform();
27233
- const root = join14(options.stateDirectory, "agents", this.id);
27234
- const temporaryRoot = join14(options.stateDirectory, "temporary");
27730
+ const root = join17(options.stateDirectory, "agents", this.id);
27731
+ const temporaryRoot = join17(options.stateDirectory, "temporary");
27235
27732
  await Promise.all([
27236
- mkdir4(root, { mode: 448, recursive: true }),
27237
- mkdir4(temporaryRoot, { mode: 448, recursive: true })
27733
+ mkdir5(root, { mode: 448, recursive: true }),
27734
+ mkdir5(temporaryRoot, { mode: 448, recursive: true })
27238
27735
  ]);
27239
27736
  const temporaryDirectory = await mkdtemp3(
27240
- join14(temporaryRoot, ".codex-install-")
27737
+ join17(temporaryRoot, ".codex-install-")
27241
27738
  );
27242
- const installerPath = join14(temporaryDirectory, "install.sh");
27243
- const installDirectory = join14(root, "bin");
27244
- const codexHome = join14(root, "home");
27739
+ const installerPath = join17(temporaryDirectory, "install.sh");
27740
+ const installDirectory = join17(root, "bin");
27741
+ const codexHome = join17(root, "home");
27245
27742
  try {
27246
27743
  await Promise.all([
27247
- mkdir4(installDirectory, { mode: 448, recursive: true }),
27248
- mkdir4(codexHome, { mode: 448, recursive: true })
27744
+ mkdir5(installDirectory, { mode: 448, recursive: true }),
27745
+ mkdir5(codexHome, { mode: 448, recursive: true })
27249
27746
  ]);
27250
27747
  await options.report("downloading");
27251
27748
  const download = await downloadVerifiedFile({
@@ -27285,7 +27782,7 @@ var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
27285
27782
  timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
27286
27783
  });
27287
27784
  return await this.requireInstalledExecutable(
27288
- join14(installDirectory, "codex")
27785
+ join17(installDirectory, "codex")
27289
27786
  );
27290
27787
  } catch (error61) {
27291
27788
  if (options.signal.aborted) {
@@ -27309,17 +27806,17 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
27309
27806
  releaseChannel = "stable";
27310
27807
  install = async (options) => {
27311
27808
  this.assertSupportedPlatform();
27312
- const root = join14(options.stateDirectory, "agents", this.id);
27313
- const managedHome = join14(root, "home");
27314
- const temporaryRoot = join14(options.stateDirectory, "temporary");
27809
+ const root = join17(options.stateDirectory, "agents", this.id);
27810
+ const managedHome = join17(root, "home");
27811
+ const temporaryRoot = join17(options.stateDirectory, "temporary");
27315
27812
  await Promise.all([
27316
- mkdir4(managedHome, { mode: 448, recursive: true }),
27317
- mkdir4(temporaryRoot, { mode: 448, recursive: true })
27813
+ mkdir5(managedHome, { mode: 448, recursive: true }),
27814
+ mkdir5(temporaryRoot, { mode: 448, recursive: true })
27318
27815
  ]);
27319
27816
  const temporaryDirectory = await mkdtemp3(
27320
- join14(temporaryRoot, ".claude-install-")
27817
+ join17(temporaryRoot, ".claude-install-")
27321
27818
  );
27322
- const installerPath = join14(temporaryDirectory, "install.sh");
27819
+ const installerPath = join17(temporaryDirectory, "install.sh");
27323
27820
  try {
27324
27821
  await options.report("downloading");
27325
27822
  const download = await downloadVerifiedFile({
@@ -27356,7 +27853,7 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
27356
27853
  timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
27357
27854
  });
27358
27855
  return await this.requireInstalledExecutable(
27359
- join14(managedHome, ".local", "bin", "claude")
27856
+ join17(managedHome, ".local", "bin", "claude")
27360
27857
  );
27361
27858
  } catch (error61) {
27362
27859
  if (options.signal.aborted) {
@@ -27390,7 +27887,7 @@ var PiInstallRecipe = class extends FixedAgentInstallRecipe {
27390
27887
  await options.report("verifying");
27391
27888
  await options.report("installing_agent");
27392
27889
  const executable = await this.#npmInstaller.install(
27393
- join14(
27890
+ join17(
27394
27891
  options.stateDirectory,
27395
27892
  "agents",
27396
27893
  this.id,
@@ -27457,18 +27954,18 @@ var DeepSeekHarnessInstallRecipe = class extends FixedAgentInstallRecipe {
27457
27954
  install = async (options) => {
27458
27955
  this.assertSupportedPlatform();
27459
27956
  try {
27460
- const managedHome = join14(
27957
+ const managedHome = join17(
27461
27958
  options.stateDirectory,
27462
27959
  "agents",
27463
27960
  this.id,
27464
27961
  "home"
27465
27962
  );
27466
- await mkdir4(managedHome, { mode: 448, recursive: true });
27963
+ await mkdir5(managedHome, { mode: 448, recursive: true });
27467
27964
  await options.report("downloading");
27468
27965
  await options.report("verifying");
27469
27966
  await options.report("installing_agent");
27470
27967
  const executable = await this.#npmInstaller.install(
27471
- join14(
27968
+ join17(
27472
27969
  options.stateDirectory,
27473
27970
  "agents",
27474
27971
  this.id,
@@ -27540,7 +28037,7 @@ var OpenCodeInstallRecipe = class extends FixedAgentInstallRecipe {
27540
28037
  await options.report("verifying");
27541
28038
  await options.report("installing_agent");
27542
28039
  const executable = await this.#archiveInstaller.install(
27543
- join14(
28040
+ join17(
27544
28041
  options.stateDirectory,
27545
28042
  "agents",
27546
28043
  this.id,
@@ -27599,7 +28096,9 @@ function fixedAgentInstallRecipes() {
27599
28096
  new ClaudeCodeInstallRecipe(),
27600
28097
  new PiInstallRecipe(),
27601
28098
  new DeepSeekHarnessInstallRecipe(),
27602
- new OpenCodeInstallRecipe()
28099
+ new OpenCodeInstallRecipe(),
28100
+ new GrokBuildInstallRecipe(),
28101
+ new WorkBuddyInstallRecipe()
27603
28102
  ]);
27604
28103
  }
27605
28104
 
@@ -27840,51 +28339,16 @@ var FixedInstallationExecutor = class {
27840
28339
  };
27841
28340
  };
27842
28341
 
27843
- // src/agent-installation/local-installation-authorizer.ts
27844
- import { createInterface } from "node:readline/promises";
27845
- var ConsoleInstallationAuthorizer = class {
27846
- #stateDirectory;
27847
- constructor(stateDirectory) {
27848
- this.#stateDirectory = stateDirectory;
27849
- }
27850
- authorize = async (agentId, label, requestId, signal) => {
27851
- signal.throwIfAborted();
27852
- const grants = await readGrantedAgents(this.#stateDirectory);
27853
- signal.throwIfAborted();
27854
- if (grants.has(agentId)) {
27855
- return true;
27856
- }
27857
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
27858
- return false;
27859
- }
27860
- const prompt = createInterface({
27861
- input: process.stdin,
27862
- output: process.stdout
27863
- });
27864
- try {
27865
- const answer = await prompt.question(
27866
- `
27867
- Mobius Web requested installation of ${label} (${requestId}). Allow this fixed user-level recipe? [y/N] `,
27868
- { signal }
27869
- );
27870
- const normalized = answer.trim().toLowerCase();
27871
- return normalized === "y" || normalized === "yes";
27872
- } finally {
27873
- prompt.close();
27874
- }
27875
- };
27876
- };
27877
-
27878
28342
  // src/authorization/workspace-directory.ts
27879
- import { readdir, realpath as realpath6, stat as stat6 } from "node:fs/promises";
28343
+ import { readdir, realpath as realpath8, stat as stat7 } from "node:fs/promises";
27880
28344
  import { homedir as homedir2 } from "node:os";
27881
28345
  import {
27882
28346
  basename as basename2,
27883
- dirname as dirname5,
27884
- isAbsolute as isAbsolute5,
27885
- join as join15,
28347
+ dirname as dirname6,
28348
+ isAbsolute as isAbsolute7,
28349
+ join as join18,
27886
28350
  normalize as normalize2,
27887
- relative as relative3
28351
+ relative as relative5
27888
28352
  } from "node:path";
27889
28353
  var WorkspaceDirectoryListing = class {
27890
28354
  directoryId;
@@ -27934,20 +28398,20 @@ var WorkspaceDirectoryService = class {
27934
28398
  if (id === "home") return homedir2();
27935
28399
  if (id.startsWith("path-")) {
27936
28400
  const path2 = decodePath(id, "path-");
27937
- if (isAbsolute5(path2)) return path2;
28401
+ if (isAbsolute7(path2)) return path2;
27938
28402
  }
27939
28403
  throw new LocalAuthorizationError("The directory identifier is invalid");
27940
28404
  };
27941
28405
  resolvePath = async (requested, signal) => {
27942
28406
  signal.throwIfAborted();
27943
- if (!isAbsolute5(requested) || requested.includes("\0") || normalize2(requested) !== requested)
28407
+ if (!isAbsolute7(requested) || requested.includes("\0") || normalize2(requested) !== requested)
27944
28408
  throw new LocalAuthorizationError("The local directory path is invalid");
27945
28409
  try {
27946
- const target = await realpath6(requested);
28410
+ const target = await realpath8(requested);
27947
28411
  signal.throwIfAborted();
27948
- const metadata = await stat6(target);
28412
+ const metadata = await stat7(target);
27949
28413
  signal.throwIfAborted();
27950
- if (!isAbsolute5(target) || normalize2(target) !== target || !metadata.isDirectory())
28414
+ if (!isAbsolute7(target) || normalize2(target) !== target || !metadata.isDirectory())
27951
28415
  throw new LocalAuthorizationError(
27952
28416
  "The selected location is not a directory"
27953
28417
  );
@@ -27962,8 +28426,8 @@ var WorkspaceDirectoryService = class {
27962
28426
  }
27963
28427
  };
27964
28428
  label = (path2) => {
27965
- const suffix = relative3(homedir2(), path2);
27966
- return suffix === "" ? "~" : !isAbsolute5(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
28429
+ const suffix = relative5(homedir2(), path2);
28430
+ return suffix === "" ? "~" : !isAbsolute7(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
27967
28431
  };
27968
28432
  identify = async (bindingId, requestedPath, signal) => {
27969
28433
  this.authorizeMachine(bindingId);
@@ -27991,7 +28455,7 @@ var WorkspaceDirectoryService = class {
27991
28455
  continue;
27992
28456
  }
27993
28457
  try {
27994
- const path2 = await this.resolvePath(join15(target, child.name), signal);
28458
+ const path2 = await this.resolvePath(join18(target, child.name), signal);
27995
28459
  entries.push({ directoryId: encodePath(path2), name: child.name });
27996
28460
  } catch (cause) {
27997
28461
  signal.throwIfAborted();
@@ -27999,7 +28463,7 @@ var WorkspaceDirectoryService = class {
27999
28463
  }
28000
28464
  }
28001
28465
  entries.sort((a, b) => a.name.localeCompare(b.name));
28002
- const parent = dirname5(target);
28466
+ const parent = dirname6(target);
28003
28467
  return new WorkspaceDirectoryListing(
28004
28468
  id,
28005
28469
  this.label(target),
@@ -28792,7 +29256,7 @@ var RelayConnectionLiveness = class {
28792
29256
 
28793
29257
  // src/relay-connection/session-event-outbox.ts
28794
29258
  import { mkdirSync as mkdirSync3 } from "node:fs";
28795
- import { dirname as dirname6 } from "node:path";
29259
+ import { dirname as dirname7 } from "node:path";
28796
29260
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
28797
29261
  function readPendingEnvelope(row) {
28798
29262
  if (typeof row !== "object" || row === null || Array.isArray(row)) {
@@ -28807,7 +29271,7 @@ function readPendingEnvelope(row) {
28807
29271
  var SessionEventOutbox = class {
28808
29272
  #database;
28809
29273
  constructor(path2) {
28810
- mkdirSync3(dirname6(path2), { recursive: true });
29274
+ mkdirSync3(dirname7(path2), { recursive: true });
28811
29275
  this.#database = new DatabaseSync3(path2);
28812
29276
  this.#database.exec(`
28813
29277
  CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
@@ -29099,17 +29563,6 @@ var DaemonInstallationObserver = class {
29099
29563
  if (state instanceof RequestedInstallation) {
29100
29564
  return Promise.resolve();
29101
29565
  }
29102
- if (state instanceof AwaitingLocalApproval) {
29103
- this.#send(
29104
- socket,
29105
- encodeAgentInstallAwaitingApprovalEvent({
29106
- agentId: state.agentId,
29107
- kind: AGENT_INSTALL_AWAITING_APPROVAL_KIND,
29108
- requestId: state.requestId
29109
- })
29110
- );
29111
- return Promise.resolve();
29112
- }
29113
29566
  if (state instanceof RunningInstallation) {
29114
29567
  if (!this.#started.has(state.requestId)) {
29115
29568
  this.#started.add(state.requestId);
@@ -30006,7 +30459,6 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
30006
30459
  );
30007
30460
  const installations = new AgentInstallationManager(
30008
30461
  specifications,
30009
- new ConsoleInstallationAuthorizer(stateDirectory),
30010
30462
  installationExecutor,
30011
30463
  installationObserver,
30012
30464
  installationAudit