@moxt-ai/mobius 0.0.28 → 0.0.29
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.
- package/dist/agent-catalog/acp-readiness-probe.d.ts.map +1 -1
- package/dist/agent-catalog/acp-readiness-probe.js +2 -2
- package/dist/agent-catalog/acp-readiness-probe.js.map +1 -1
- package/dist/agent-catalog/agent-specification.d.ts +3 -0
- package/dist/agent-catalog/agent-specification.d.ts.map +1 -1
- package/dist/agent-catalog/agent-specification.js +3 -0
- package/dist/agent-catalog/agent-specification.js.map +1 -1
- package/dist/agent-catalog/agents/copilot-cli-agent.d.ts +18 -0
- package/dist/agent-catalog/agents/copilot-cli-agent.d.ts.map +1 -0
- package/dist/agent-catalog/agents/copilot-cli-agent.js +29 -0
- package/dist/agent-catalog/agents/copilot-cli-agent.js.map +1 -0
- package/dist/agent-catalog/agents/gemini-cli-agent.d.ts +14 -0
- package/dist/agent-catalog/agents/gemini-cli-agent.d.ts.map +1 -0
- package/dist/agent-catalog/agents/gemini-cli-agent.js +30 -0
- package/dist/agent-catalog/agents/gemini-cli-agent.js.map +1 -0
- package/dist/agent-catalog/agents/hermes-agent.d.ts +18 -0
- package/dist/agent-catalog/agents/hermes-agent.d.ts.map +1 -0
- package/dist/agent-catalog/agents/hermes-agent.js +32 -0
- package/dist/agent-catalog/agents/hermes-agent.js.map +1 -0
- package/dist/agent-catalog/agents/resolve-user-local-executable.d.ts +4 -0
- package/dist/agent-catalog/agents/resolve-user-local-executable.d.ts.map +1 -0
- package/dist/agent-catalog/agents/resolve-user-local-executable.js +14 -0
- package/dist/agent-catalog/agents/resolve-user-local-executable.js.map +1 -0
- package/dist/agent-catalog/agents/supported-agent-specifications.d.ts.map +1 -1
- package/dist/agent-catalog/agents/supported-agent-specifications.js +6 -0
- package/dist/agent-catalog/agents/supported-agent-specifications.js.map +1 -1
- package/dist/agent-catalog/discover-agent.d.ts.map +1 -1
- package/dist/agent-catalog/discover-agent.js +2 -2
- package/dist/agent-catalog/discover-agent.js.map +1 -1
- package/dist/agent-catalog/discover-local-agents.d.ts +3 -0
- package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
- package/dist/agent-catalog/discover-local-agents.js +3 -0
- package/dist/agent-catalog/discover-local-agents.js.map +1 -1
- package/dist/agent-catalog/executable-discovery.d.ts +1 -2
- package/dist/agent-catalog/executable-discovery.d.ts.map +1 -1
- package/dist/agent-catalog/executable-discovery.js +4 -6
- package/dist/agent-catalog/executable-discovery.js.map +1 -1
- package/dist/agent-catalog/version-output.d.ts +2 -0
- package/dist/agent-catalog/version-output.d.ts.map +1 -0
- package/dist/agent-catalog/version-output.js +4 -0
- package/dist/agent-catalog/version-output.js.map +1 -0
- package/dist/cli.js +372 -233
- package/dist/cli.js.map +4 -4
- package/dist/index.js +361 -224
- package/dist/index.js.map +4 -4
- package/dist/runtime.js +373 -234
- package/dist/runtime.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { mkdir as mkdir5 } from "node:fs/promises";
|
|
|
11
11
|
// package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "@moxt-ai/mobius",
|
|
14
|
-
version: "0.0.
|
|
14
|
+
version: "0.0.29",
|
|
15
15
|
description: "Mobius CLI for pairing and running local AI agent services.",
|
|
16
16
|
type: "module",
|
|
17
17
|
bin: {
|
|
@@ -1158,6 +1158,13 @@ var ManagedNpmPackageInstaller = class {
|
|
|
1158
1158
|
|
|
1159
1159
|
// src/agent-catalog/agent-specification.ts
|
|
1160
1160
|
import { join as join3 } from "node:path";
|
|
1161
|
+
|
|
1162
|
+
// src/agent-catalog/version-output.ts
|
|
1163
|
+
function normalizeVersionOutput(output2) {
|
|
1164
|
+
return output2.trim().split(/\r?\n/, 1)[0]?.trim().slice(0, 128) ?? "";
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// src/agent-catalog/agent-specification.ts
|
|
1161
1168
|
var VERSION_PROBE_TIMEOUT_MILLISECONDS = 3e3;
|
|
1162
1169
|
var ACP_PROBE_TIMEOUT_MILLISECONDS = 5e3;
|
|
1163
1170
|
var DEFAULT_PROMPT_TIMEOUT_MILLISECONDS = 30 * 60 * 1e3;
|
|
@@ -1166,6 +1173,8 @@ var LocalAgentSpecification = class {
|
|
|
1166
1173
|
authenticationCommand = () => "";
|
|
1167
1174
|
adapterVersionArguments = ["--version"];
|
|
1168
1175
|
agentVersionArguments = ["--version"];
|
|
1176
|
+
normalizeAdapterVersion = normalizeVersionOutput;
|
|
1177
|
+
normalizeAgentVersion = normalizeVersionOutput;
|
|
1169
1178
|
promptTimeoutMilliseconds = DEFAULT_PROMPT_TIMEOUT_MILLISECONDS;
|
|
1170
1179
|
versionProbeTimeoutMilliseconds = VERSION_PROBE_TIMEOUT_MILLISECONDS;
|
|
1171
1180
|
resolveManagedAgent = async (stateDirectory, platform, signal) => {
|
|
@@ -1277,6 +1286,20 @@ var AgentProbeError = class extends Error {
|
|
|
1277
1286
|
}
|
|
1278
1287
|
};
|
|
1279
1288
|
|
|
1289
|
+
// src/agent-catalog/agents/resolve-user-local-executable.ts
|
|
1290
|
+
import { isAbsolute as isAbsolute2, join as join4 } from "node:path";
|
|
1291
|
+
async function resolveUserLocalExecutable(executableName, context) {
|
|
1292
|
+
context.signal.throwIfAborted();
|
|
1293
|
+
const platform = context.platform ?? process.platform;
|
|
1294
|
+
const homeDirectory = context.environment["HOME"];
|
|
1295
|
+
if (platform === "win32" || homeDirectory === void 0 || !isAbsolute2(homeDirectory)) {
|
|
1296
|
+
return [];
|
|
1297
|
+
}
|
|
1298
|
+
const executable = await resolveExecutablePath(join4(homeDirectory, ".local", "bin", executableName), platform);
|
|
1299
|
+
context.signal.throwIfAborted();
|
|
1300
|
+
return executable === null ? [] : [executable];
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1280
1303
|
// src/agent-catalog/agents/verify-session-creation.ts
|
|
1281
1304
|
import { methods } from "@agentclientprotocol/sdk";
|
|
1282
1305
|
async function verifySessionCreation(connection, capabilities, defaultWorkspace, signal, label) {
|
|
@@ -1301,6 +1324,37 @@ async function verifySessionCreation(connection, capabilities, defaultWorkspace,
|
|
|
1301
1324
|
}
|
|
1302
1325
|
}
|
|
1303
1326
|
|
|
1327
|
+
// src/agent-catalog/agents/copilot-cli-agent.ts
|
|
1328
|
+
var COPILOT_CLI_TESTED_VERSION = "1.0.83";
|
|
1329
|
+
var CopilotCliAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
1330
|
+
acpProbeTimeoutMilliseconds = 2e4;
|
|
1331
|
+
adapterVersion = COPILOT_CLI_TESTED_VERSION;
|
|
1332
|
+
authenticationCommand = () => "copilot login";
|
|
1333
|
+
agentExecutable = "copilot";
|
|
1334
|
+
id = "github-copilot-cli";
|
|
1335
|
+
label = "GitHub Copilot CLI";
|
|
1336
|
+
versionProbeTimeoutMilliseconds = 1e4;
|
|
1337
|
+
constructor() {
|
|
1338
|
+
super(
|
|
1339
|
+
"MOBIUS_COPILOT_PATH",
|
|
1340
|
+
["--no-auto-update", "--acp", "--stdio"],
|
|
1341
|
+
["agents", "github-copilot-cli", COPILOT_CLI_TESTED_VERSION, "bin", "copilot"]
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
createLaunchEnvironment = async (_agent, _context) => Object.freeze({ COPILOT_AUTO_UPDATE: "false" });
|
|
1345
|
+
resolveInstalledAgentExecutables = async (context) => await resolveUserLocalExecutable(this.agentExecutable, context);
|
|
1346
|
+
verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
|
|
1347
|
+
const capabilities = initialized.agentCapabilities ?? {};
|
|
1348
|
+
if (capabilities.loadSession !== true || capabilities.sessionCapabilities?.list == null || (initialized.authMethods ?? []).length === 0) {
|
|
1349
|
+
throw new AgentProbeError(
|
|
1350
|
+
"acp_incompatible",
|
|
1351
|
+
"GitHub Copilot CLI reported an unsupported ACP capability set"
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1354
|
+
await verifySessionCreation(connection, capabilities, defaultWorkspace, signal, this.label);
|
|
1355
|
+
};
|
|
1356
|
+
};
|
|
1357
|
+
|
|
1304
1358
|
// src/agent-catalog/agents/cursor-cli-agent.ts
|
|
1305
1359
|
var CURSOR_CLI_TESTED_VERSION = "2026.09.02-c22c1a3";
|
|
1306
1360
|
var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
@@ -1327,7 +1381,7 @@ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1327
1381
|
|
|
1328
1382
|
// src/agent-catalog/agents/deepseek-harness-agent.ts
|
|
1329
1383
|
import { realpath as realpath3, stat as stat3 } from "node:fs/promises";
|
|
1330
|
-
import { isAbsolute as
|
|
1384
|
+
import { isAbsolute as isAbsolute3, join as join6, normalize } from "node:path";
|
|
1331
1385
|
|
|
1332
1386
|
// src/agent-installation/deepseek-managed-package.ts
|
|
1333
1387
|
var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
|
|
@@ -1345,18 +1399,18 @@ var DEEPSEEK_HARNESS_PACKAGE = new DeepSeekHarnessManagedPackage(
|
|
|
1345
1399
|
|
|
1346
1400
|
// src/storage/state-directory.ts
|
|
1347
1401
|
import { homedir } from "node:os";
|
|
1348
|
-
import { join as
|
|
1402
|
+
import { join as join5, resolve as resolve2 } from "node:path";
|
|
1349
1403
|
function readStateDirectory(environment = process.env) {
|
|
1350
1404
|
const configured = environment["MOBIUS_STATE_DIRECTORY"]?.trim();
|
|
1351
1405
|
if (configured !== void 0 && configured.length > 0) {
|
|
1352
1406
|
return resolve2(configured);
|
|
1353
1407
|
}
|
|
1354
|
-
return
|
|
1408
|
+
return join5(homedir(), ".mobius");
|
|
1355
1409
|
}
|
|
1356
1410
|
|
|
1357
1411
|
// src/agent-catalog/agents/deepseek-harness-agent.ts
|
|
1358
1412
|
async function validateAgentHome(path2) {
|
|
1359
|
-
if (!
|
|
1413
|
+
if (!isAbsolute3(path2) || normalize(path2) !== path2) {
|
|
1360
1414
|
throw new AgentProbeError("agent_environment_invalid", "The configured Agent home is invalid");
|
|
1361
1415
|
}
|
|
1362
1416
|
try {
|
|
@@ -1406,7 +1460,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1406
1460
|
context.signal
|
|
1407
1461
|
);
|
|
1408
1462
|
if (managed.path === agent.path) {
|
|
1409
|
-
selectedHome =
|
|
1463
|
+
selectedHome = join6(readStateDirectory(context.environment), "agents", this.id, "home");
|
|
1410
1464
|
}
|
|
1411
1465
|
} catch {
|
|
1412
1466
|
context.signal.throwIfAborted();
|
|
@@ -1422,7 +1476,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1422
1476
|
resolveManagedAgent = async (stateDirectory, _platform, signal) => {
|
|
1423
1477
|
signal.throwIfAborted();
|
|
1424
1478
|
const executable = await validateManagedNpmPackage(
|
|
1425
|
-
|
|
1479
|
+
join6(stateDirectory, "agents", this.id, DEEPSEEK_HARNESS_PACKAGE.version),
|
|
1426
1480
|
DEEPSEEK_HARNESS_PACKAGE
|
|
1427
1481
|
);
|
|
1428
1482
|
signal.throwIfAborted();
|
|
@@ -1442,9 +1496,41 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1442
1496
|
};
|
|
1443
1497
|
};
|
|
1444
1498
|
|
|
1499
|
+
// src/agent-catalog/agents/gemini-cli-agent.ts
|
|
1500
|
+
var GEMINI_CLI_TESTED_VERSION = "0.59.0";
|
|
1501
|
+
var GeminiCliAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
1502
|
+
acpProbeTimeoutMilliseconds = 2e4;
|
|
1503
|
+
adapterVersion = GEMINI_CLI_TESTED_VERSION;
|
|
1504
|
+
authenticationCommand = () => "gemini";
|
|
1505
|
+
agentExecutable = "gemini";
|
|
1506
|
+
id = "gemini-cli";
|
|
1507
|
+
label = "Gemini CLI";
|
|
1508
|
+
versionProbeTimeoutMilliseconds = 1e4;
|
|
1509
|
+
constructor() {
|
|
1510
|
+
super(
|
|
1511
|
+
"MOBIUS_GEMINI_PATH",
|
|
1512
|
+
["--acp"],
|
|
1513
|
+
[
|
|
1514
|
+
"agents",
|
|
1515
|
+
"gemini-cli",
|
|
1516
|
+
GEMINI_CLI_TESTED_VERSION,
|
|
1517
|
+
"bin",
|
|
1518
|
+
process.platform === "win32" ? "gemini.cmd" : "gemini"
|
|
1519
|
+
]
|
|
1520
|
+
);
|
|
1521
|
+
}
|
|
1522
|
+
verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
|
|
1523
|
+
const capabilities = initialized.agentCapabilities ?? {};
|
|
1524
|
+
if (capabilities.loadSession !== true || (initialized.authMethods ?? []).length === 0) {
|
|
1525
|
+
throw new AgentProbeError("acp_incompatible", "Gemini CLI reported an unsupported ACP capability set");
|
|
1526
|
+
}
|
|
1527
|
+
await verifySessionCreation(connection, capabilities, defaultWorkspace, signal, this.label);
|
|
1528
|
+
};
|
|
1529
|
+
};
|
|
1530
|
+
|
|
1445
1531
|
// src/agent-catalog/agents/grok-build-agent.ts
|
|
1446
1532
|
import { realpath as realpath4 } from "node:fs/promises";
|
|
1447
|
-
import { isAbsolute as
|
|
1533
|
+
import { isAbsolute as isAbsolute4, join as join7, relative as relative2, sep as sep2 } from "node:path";
|
|
1448
1534
|
|
|
1449
1535
|
// src/agent-installation/grok-managed-package.ts
|
|
1450
1536
|
var GROK_BUILD_MANAGED_VERSION = "1.0.21";
|
|
@@ -1507,7 +1593,7 @@ function grokBuildManagedPackage(platform, architecture) {
|
|
|
1507
1593
|
// src/agent-catalog/agents/grok-build-agent.ts
|
|
1508
1594
|
function isContainedPath2(root, candidate) {
|
|
1509
1595
|
const difference = relative2(root, candidate);
|
|
1510
|
-
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !
|
|
1596
|
+
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute4(difference);
|
|
1511
1597
|
}
|
|
1512
1598
|
var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
1513
1599
|
adapterVersion = GROK_BUILD_MANAGED_VERSION;
|
|
@@ -1535,7 +1621,7 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1535
1621
|
if (managed.path === agent.path) {
|
|
1536
1622
|
return Object.freeze({
|
|
1537
1623
|
GROK_HOME: await realpath4(
|
|
1538
|
-
|
|
1624
|
+
join7(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION, "home")
|
|
1539
1625
|
)
|
|
1540
1626
|
});
|
|
1541
1627
|
}
|
|
@@ -1546,9 +1632,9 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1546
1632
|
};
|
|
1547
1633
|
resolveManagedAgent = async (stateDirectory, platform, signal) => {
|
|
1548
1634
|
signal.throwIfAborted();
|
|
1549
|
-
const versionRoot = await realpath4(
|
|
1550
|
-
await validateManagedNpmPackage(
|
|
1551
|
-
const executable = await resolveExecutablePath(
|
|
1635
|
+
const versionRoot = await realpath4(join7(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION));
|
|
1636
|
+
await validateManagedNpmPackage(join7(versionRoot, "package"), grokBuildManagedPackage(platform, process.arch));
|
|
1637
|
+
const executable = await resolveExecutablePath(join7(versionRoot, "home", "bin", "grok"), platform);
|
|
1552
1638
|
signal.throwIfAborted();
|
|
1553
1639
|
if (executable === null || !isContainedPath2(versionRoot, executable.path)) {
|
|
1554
1640
|
throw new AgentProbeError("managed_agent_invalid", "The managed Grok Build executable is invalid");
|
|
@@ -1565,14 +1651,39 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1565
1651
|
};
|
|
1566
1652
|
};
|
|
1567
1653
|
|
|
1654
|
+
// src/agent-catalog/agents/hermes-agent.ts
|
|
1655
|
+
var HERMES_TESTED_VERSION = "0.21.1";
|
|
1656
|
+
var HermesAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
1657
|
+
acpProbeTimeoutMilliseconds = 2e4;
|
|
1658
|
+
adapterVersion = HERMES_TESTED_VERSION;
|
|
1659
|
+
adapterVersionArguments = ["acp", "--version"];
|
|
1660
|
+
authenticationCommand = () => "hermes acp --setup";
|
|
1661
|
+
agentExecutable = "hermes";
|
|
1662
|
+
agentVersionArguments = ["acp", "--version"];
|
|
1663
|
+
id = "hermes";
|
|
1664
|
+
label = "Hermes Agent";
|
|
1665
|
+
constructor() {
|
|
1666
|
+
super("MOBIUS_HERMES_PATH", ["acp"], ["agents", "hermes", HERMES_TESTED_VERSION, "bin", "hermes"]);
|
|
1667
|
+
}
|
|
1668
|
+
resolveInstalledAgentExecutables = async (context) => await resolveUserLocalExecutable(this.agentExecutable, context);
|
|
1669
|
+
verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
|
|
1670
|
+
const capabilities = initialized.agentCapabilities ?? {};
|
|
1671
|
+
const session = capabilities.sessionCapabilities;
|
|
1672
|
+
if (capabilities.loadSession !== true || session?.fork == null || session.list == null || session.resume == null || (initialized.authMethods ?? []).length === 0) {
|
|
1673
|
+
throw new AgentProbeError("acp_incompatible", "Hermes Agent reported an unsupported ACP capability set");
|
|
1674
|
+
}
|
|
1675
|
+
await verifySessionCreation(connection, capabilities, defaultWorkspace, signal, this.label);
|
|
1676
|
+
};
|
|
1677
|
+
};
|
|
1678
|
+
|
|
1568
1679
|
// src/agent-catalog/agents/opencode-agent.ts
|
|
1569
|
-
import { join as
|
|
1680
|
+
import { join as join9 } from "node:path";
|
|
1570
1681
|
|
|
1571
1682
|
// src/agent-installation/managed-agent-archive.ts
|
|
1572
1683
|
import { createHash } from "node:crypto";
|
|
1573
1684
|
import { createReadStream } from "node:fs";
|
|
1574
1685
|
import { chmod, copyFile, mkdir as mkdir2, mkdtemp as mkdtemp2, open as open2, realpath as realpath5, rename as rename2, rm as rm2, stat as stat4, writeFile } from "node:fs/promises";
|
|
1575
|
-
import { dirname as dirname2, isAbsolute as
|
|
1686
|
+
import { dirname as dirname2, isAbsolute as isAbsolute5, join as join8, relative as relative3, sep as sep3 } from "node:path";
|
|
1576
1687
|
|
|
1577
1688
|
// src/agent-installation/verified-download.ts
|
|
1578
1689
|
import { fetch } from "undici";
|
|
@@ -1678,7 +1789,7 @@ function isRecord3(value) {
|
|
|
1678
1789
|
}
|
|
1679
1790
|
function isContainedPath3(root, candidate) {
|
|
1680
1791
|
const difference = relative3(root, candidate);
|
|
1681
|
-
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !
|
|
1792
|
+
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute5(difference);
|
|
1682
1793
|
}
|
|
1683
1794
|
async function hashFile(path2, signal) {
|
|
1684
1795
|
signal.throwIfAborted();
|
|
@@ -1757,11 +1868,11 @@ async function validateManagedAgentArchive(root, definition, signal) {
|
|
|
1757
1868
|
if (!rootMetadata.isDirectory() || typeof process.getuid === "function" && rootMetadata.uid !== process.getuid()) {
|
|
1758
1869
|
throw new Error("Managed Agent root is not user-owned");
|
|
1759
1870
|
}
|
|
1760
|
-
const manifest = await readManifest(
|
|
1871
|
+
const manifest = await readManifest(join8(rootPath, "archive.json"));
|
|
1761
1872
|
if (manifest["archiveSha256"] !== definition.archiveSha256 || manifest["archiveUrl"] !== definition.archiveUrl.toString() || manifest["version"] !== definition.version || typeof manifest["executableSha256"] !== "string") {
|
|
1762
1873
|
throw new Error("Managed Agent archive identity is invalid");
|
|
1763
1874
|
}
|
|
1764
|
-
const executable = await resolveExecutablePath(
|
|
1875
|
+
const executable = await resolveExecutablePath(join8(rootPath, "bin", definition.executableName));
|
|
1765
1876
|
if (executable === null || !isContainedPath3(rootPath, executable.path) || await hashFile(executable.path, signal) !== manifest["executableSha256"]) {
|
|
1766
1877
|
throw new Error("Managed Agent executable is invalid");
|
|
1767
1878
|
}
|
|
@@ -1853,7 +1964,7 @@ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1853
1964
|
}
|
|
1854
1965
|
createLaunchEnvironment = async (_agent, _context) => Object.freeze({ OPENCODE_DISABLE_AUTOUPDATE: "1" });
|
|
1855
1966
|
resolveManagedAgent = async (stateDirectory, platform, signal) => await validateManagedAgentArchive(
|
|
1856
|
-
|
|
1967
|
+
join9(stateDirectory, "agents", this.id, OPENCODE_MANAGED_VERSION),
|
|
1857
1968
|
openCodeManagedArchive(platform, process.arch),
|
|
1858
1969
|
signal
|
|
1859
1970
|
);
|
|
@@ -1871,7 +1982,7 @@ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1871
1982
|
};
|
|
1872
1983
|
|
|
1873
1984
|
// src/agent-catalog/agents/pi-agent.ts
|
|
1874
|
-
import { join as
|
|
1985
|
+
import { join as join10 } from "node:path";
|
|
1875
1986
|
import {
|
|
1876
1987
|
methods as methods2
|
|
1877
1988
|
} from "@agentclientprotocol/sdk";
|
|
@@ -1930,7 +2041,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
|
|
|
1930
2041
|
resolveManagedAgent = async (stateDirectory, _platform, signal) => {
|
|
1931
2042
|
signal.throwIfAborted();
|
|
1932
2043
|
const executable = await validateManagedNpmPackage(
|
|
1933
|
-
|
|
2044
|
+
join10(stateDirectory, "agents", this.id, PI_AGENT_PACKAGE.version),
|
|
1934
2045
|
PI_AGENT_PACKAGE
|
|
1935
2046
|
);
|
|
1936
2047
|
signal.throwIfAborted();
|
|
@@ -1968,7 +2079,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
|
|
|
1968
2079
|
};
|
|
1969
2080
|
|
|
1970
2081
|
// src/agent-catalog/agents/workbuddy-agent.ts
|
|
1971
|
-
import { isAbsolute as
|
|
2082
|
+
import { isAbsolute as isAbsolute6, join as join11 } from "node:path";
|
|
1972
2083
|
|
|
1973
2084
|
// src/agent-installation/workbuddy-managed-package.ts
|
|
1974
2085
|
var WORKBUDDY_MANAGED_VERSION = "2.146.0";
|
|
@@ -2021,7 +2132,7 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
2021
2132
|
resolveManagedAgent = async (stateDirectory, _platform, signal) => {
|
|
2022
2133
|
signal.throwIfAborted();
|
|
2023
2134
|
const executable = await validateManagedNpmPackage(
|
|
2024
|
-
|
|
2135
|
+
join11(stateDirectory, "agents", this.id, WORKBUDDY_MANAGED_VERSION),
|
|
2025
2136
|
WORKBUDDY_MANAGED_PACKAGE
|
|
2026
2137
|
);
|
|
2027
2138
|
signal.throwIfAborted();
|
|
@@ -2032,10 +2143,10 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
2032
2143
|
if ((context.platform ?? process.platform) !== "darwin") {
|
|
2033
2144
|
return [];
|
|
2034
2145
|
}
|
|
2035
|
-
const requestedPaths = [
|
|
2146
|
+
const requestedPaths = [join11("/Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH)];
|
|
2036
2147
|
const homeDirectory = context.environment["HOME"];
|
|
2037
|
-
if (homeDirectory !== void 0 &&
|
|
2038
|
-
requestedPaths.unshift(
|
|
2148
|
+
if (homeDirectory !== void 0 && isAbsolute6(homeDirectory)) {
|
|
2149
|
+
requestedPaths.unshift(join11(homeDirectory, "Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH));
|
|
2039
2150
|
}
|
|
2040
2151
|
const executables = [];
|
|
2041
2152
|
for (const requestedPath of requestedPaths) {
|
|
@@ -2061,12 +2172,15 @@ function supportedLocalAgentSpecifications() {
|
|
|
2061
2172
|
return Object.freeze([
|
|
2062
2173
|
new CodexAgentSpecification(),
|
|
2063
2174
|
new ClaudeCodeAgentSpecification(),
|
|
2175
|
+
new CopilotCliAgentSpecification(),
|
|
2064
2176
|
new PiAgentSpecification(),
|
|
2065
2177
|
new DeepSeekHarnessAgentSpecification(),
|
|
2178
|
+
new HermesAgentSpecification(),
|
|
2066
2179
|
new OpenCodeAgentSpecification(),
|
|
2067
2180
|
new CursorCliAgentSpecification(),
|
|
2068
2181
|
new GrokBuildAgentSpecification(),
|
|
2069
|
-
new WorkBuddyAgentSpecification()
|
|
2182
|
+
new WorkBuddyAgentSpecification(),
|
|
2183
|
+
new GeminiCliAgentSpecification()
|
|
2070
2184
|
]);
|
|
2071
2185
|
}
|
|
2072
2186
|
|
|
@@ -2106,11 +2220,173 @@ var createAcpClient = (handler) => client({ name: "mobius" }).onRequest(
|
|
|
2106
2220
|
outcome: { outcome: "cancelled" }
|
|
2107
2221
|
})).onNotification("cursor/update_todos", discardExtensionParams, async () => Promise.resolve()).onNotification("cursor/task", discardExtensionParams, async () => Promise.resolve()).onNotification("cursor/generate_image", discardExtensionParams, async () => Promise.resolve());
|
|
2108
2222
|
|
|
2223
|
+
// src/agent-catalog/acp-readiness-probe.ts
|
|
2224
|
+
var ACP_OUTPUT_LIMIT_BYTES = 1024 * 1024;
|
|
2225
|
+
var VerifiedAcpReadiness = class {
|
|
2226
|
+
adapterVersion;
|
|
2227
|
+
capabilities;
|
|
2228
|
+
constructor(adapterVersion, capabilities) {
|
|
2229
|
+
this.adapterVersion = adapterVersion;
|
|
2230
|
+
this.capabilities = capabilities;
|
|
2231
|
+
}
|
|
2232
|
+
};
|
|
2233
|
+
var DiscoveryAcpHandler = class {
|
|
2234
|
+
onElicitation = (_request, _signal) => Promise.reject(new Error("ACP probe does not accept elicitations"));
|
|
2235
|
+
onElicitationComplete = (_notification) => Promise.resolve();
|
|
2236
|
+
onPermission = (_request, _signal) => Promise.reject(new Error("ACP probe does not grant permissions"));
|
|
2237
|
+
onUpdate = (_notification) => Promise.resolve();
|
|
2238
|
+
};
|
|
2239
|
+
function readableAcpStream(input2) {
|
|
2240
|
+
let byteLength = 0;
|
|
2241
|
+
let open5 = true;
|
|
2242
|
+
return new ReadableStream({
|
|
2243
|
+
start(controller) {
|
|
2244
|
+
input2.on("data", (chunk) => {
|
|
2245
|
+
if (!open5) {
|
|
2246
|
+
return;
|
|
2247
|
+
}
|
|
2248
|
+
if (!(chunk instanceof Uint8Array)) {
|
|
2249
|
+
open5 = false;
|
|
2250
|
+
controller.error(new Error("ACP adapter produced invalid output"));
|
|
2251
|
+
return;
|
|
2252
|
+
}
|
|
2253
|
+
byteLength += chunk.byteLength;
|
|
2254
|
+
if (byteLength > ACP_OUTPUT_LIMIT_BYTES) {
|
|
2255
|
+
open5 = false;
|
|
2256
|
+
controller.error(new Error("ACP adapter output limit exceeded"));
|
|
2257
|
+
return;
|
|
2258
|
+
}
|
|
2259
|
+
controller.enqueue(new Uint8Array(chunk));
|
|
2260
|
+
});
|
|
2261
|
+
input2.once("end", () => {
|
|
2262
|
+
if (open5) {
|
|
2263
|
+
open5 = false;
|
|
2264
|
+
controller.close();
|
|
2265
|
+
}
|
|
2266
|
+
});
|
|
2267
|
+
input2.once("error", (error61) => {
|
|
2268
|
+
if (open5) {
|
|
2269
|
+
open5 = false;
|
|
2270
|
+
controller.error(error61);
|
|
2271
|
+
}
|
|
2272
|
+
});
|
|
2273
|
+
},
|
|
2274
|
+
cancel() {
|
|
2275
|
+
open5 = false;
|
|
2276
|
+
}
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
2279
|
+
function writableAcpStream(output2) {
|
|
2280
|
+
return new WritableStream({
|
|
2281
|
+
write(chunk) {
|
|
2282
|
+
return new Promise((resolveWrite, rejectWrite) => {
|
|
2283
|
+
output2.write(chunk, (error61) => {
|
|
2284
|
+
if (error61) {
|
|
2285
|
+
rejectWrite(error61);
|
|
2286
|
+
return;
|
|
2287
|
+
}
|
|
2288
|
+
resolveWrite();
|
|
2289
|
+
});
|
|
2290
|
+
});
|
|
2291
|
+
}
|
|
2292
|
+
});
|
|
2293
|
+
}
|
|
2294
|
+
async function probeAcpReadiness(specification, agent, environment, defaultWorkspace, signal) {
|
|
2295
|
+
signal.throwIfAborted();
|
|
2296
|
+
const controller = new AbortController();
|
|
2297
|
+
let timedOut = false;
|
|
2298
|
+
const timeout = setTimeout(() => {
|
|
2299
|
+
timedOut = true;
|
|
2300
|
+
controller.abort(new Error("ACP probe timed out"));
|
|
2301
|
+
}, specification.acpProbeTimeoutMilliseconds);
|
|
2302
|
+
const abort = () => controller.abort(signal.reason);
|
|
2303
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
2304
|
+
if (signal.aborted) {
|
|
2305
|
+
abort();
|
|
2306
|
+
}
|
|
2307
|
+
const child = spawn2(agent.adapterPath, [...agent.arguments], {
|
|
2308
|
+
cwd: defaultWorkspace,
|
|
2309
|
+
detached: process.platform !== "win32",
|
|
2310
|
+
env: { ...environment, ...agent.environment },
|
|
2311
|
+
shell: false,
|
|
2312
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2313
|
+
});
|
|
2314
|
+
const processExit = new Promise((_resolve, reject) => {
|
|
2315
|
+
const rejectExit = () => reject(new Error("ACP adapter exited during initialization"));
|
|
2316
|
+
child.once("error", reject);
|
|
2317
|
+
child.once("exit", rejectExit);
|
|
2318
|
+
if (child.exitCode !== null || child.signalCode !== null) {
|
|
2319
|
+
rejectExit();
|
|
2320
|
+
}
|
|
2321
|
+
});
|
|
2322
|
+
const stdin = child.stdin;
|
|
2323
|
+
const stdout = child.stdout;
|
|
2324
|
+
const stderr = child.stderr;
|
|
2325
|
+
if (stdin === null || stdout === null || stderr === null) {
|
|
2326
|
+
await stopProcessTree(child);
|
|
2327
|
+
throw new AgentProbeError("acp_incompatible", "ACP adapter streams are unavailable");
|
|
2328
|
+
}
|
|
2329
|
+
let stderrBytes = 0;
|
|
2330
|
+
const consumeStderr = (chunk) => {
|
|
2331
|
+
stderrBytes += chunk.byteLength;
|
|
2332
|
+
if (stderrBytes > ACP_OUTPUT_LIMIT_BYTES) {
|
|
2333
|
+
controller.abort(new Error("ACP adapter output limit exceeded"));
|
|
2334
|
+
}
|
|
2335
|
+
};
|
|
2336
|
+
stderr.on("data", consumeStderr);
|
|
2337
|
+
const connection = createAcpClient(new DiscoveryAcpHandler()).connect(
|
|
2338
|
+
ndJsonStream(writableAcpStream(stdin), readableAcpStream(stdout))
|
|
2339
|
+
);
|
|
2340
|
+
try {
|
|
2341
|
+
const initialized = await Promise.race([
|
|
2342
|
+
connection.agent.request(
|
|
2343
|
+
methods4.agent.initialize,
|
|
2344
|
+
{
|
|
2345
|
+
clientCapabilities: {},
|
|
2346
|
+
clientInfo: { name: "mobius", version: "0.0.3" },
|
|
2347
|
+
protocolVersion: PROTOCOL_VERSION
|
|
2348
|
+
},
|
|
2349
|
+
{ cancellationSignal: controller.signal }
|
|
2350
|
+
),
|
|
2351
|
+
processExit
|
|
2352
|
+
]);
|
|
2353
|
+
if (initialized.protocolVersion !== PROTOCOL_VERSION) {
|
|
2354
|
+
throw new AgentProbeError("acp_incompatible", "ACP adapter selected an unsupported protocol version");
|
|
2355
|
+
}
|
|
2356
|
+
await specification.verifyAcp(connection, initialized, defaultWorkspace, controller.signal);
|
|
2357
|
+
return new VerifiedAcpReadiness(
|
|
2358
|
+
normalizeVersionOutput(initialized.agentInfo?.version ?? ""),
|
|
2359
|
+
normalizeAcpCapabilities(initialized)
|
|
2360
|
+
);
|
|
2361
|
+
} catch (error61) {
|
|
2362
|
+
if (signal.aborted) {
|
|
2363
|
+
signal.throwIfAborted();
|
|
2364
|
+
}
|
|
2365
|
+
if (timedOut) {
|
|
2366
|
+
throw new AgentProbeError("adapter_probe_timeout", "ACP adapter probe timed out", { cause: error61 });
|
|
2367
|
+
}
|
|
2368
|
+
if (error61 instanceof AgentProbeError) {
|
|
2369
|
+
throw error61;
|
|
2370
|
+
}
|
|
2371
|
+
if (error61 instanceof RequestError && error61.code === -32e3 && specification.authenticationCommand().length > 0) {
|
|
2372
|
+
throw new AgentProbeError("authentication_required", "Agent authentication is required", { cause: error61 });
|
|
2373
|
+
}
|
|
2374
|
+
throw new AgentProbeError("acp_incompatible", "ACP adapter initialization failed", { cause: error61 });
|
|
2375
|
+
} finally {
|
|
2376
|
+
clearTimeout(timeout);
|
|
2377
|
+
signal.removeEventListener("abort", abort);
|
|
2378
|
+
connection.close();
|
|
2379
|
+
stdin.end();
|
|
2380
|
+
stderr.removeListener("data", consumeStderr);
|
|
2381
|
+
await stopProcessTree(child);
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
|
|
2109
2385
|
// src/agent-catalog/executable-discovery.ts
|
|
2110
|
-
import { isAbsolute as
|
|
2386
|
+
import { isAbsolute as isAbsolute7, join as join13 } from "node:path";
|
|
2111
2387
|
|
|
2112
2388
|
// src/agent-installation/managed-adapter-installer.ts
|
|
2113
|
-
import { join as
|
|
2389
|
+
import { join as join12 } from "node:path";
|
|
2114
2390
|
var ManagedAdapterInstallError = class extends Error {
|
|
2115
2391
|
code;
|
|
2116
2392
|
constructor(code, message, options = {}) {
|
|
@@ -2167,7 +2443,7 @@ var ManagedAdapterInstaller = class {
|
|
|
2167
2443
|
this.#stateDirectory = options.stateDirectory;
|
|
2168
2444
|
}
|
|
2169
2445
|
install = async (specification, signal) => {
|
|
2170
|
-
const root =
|
|
2446
|
+
const root = join12(this.#stateDirectory, "adapters", specification.id, specification.adapterVersion);
|
|
2171
2447
|
try {
|
|
2172
2448
|
return await this.#npmInstaller.install(
|
|
2173
2449
|
root,
|
|
@@ -2201,7 +2477,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
|
|
|
2201
2477
|
let managed;
|
|
2202
2478
|
try {
|
|
2203
2479
|
managed = await validateManagedAdapter(
|
|
2204
|
-
|
|
2480
|
+
join13(readStateDirectory(context.environment), "adapters", specification.id, specification.adapterVersion),
|
|
2205
2481
|
specification
|
|
2206
2482
|
);
|
|
2207
2483
|
} catch {
|
|
@@ -2212,7 +2488,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
|
|
|
2212
2488
|
async function resolveSpecificationExecutables(executableName, overrideVariable, resolveInstalled, resolveManaged, context) {
|
|
2213
2489
|
const override = context.environment[overrideVariable];
|
|
2214
2490
|
if (override !== void 0) {
|
|
2215
|
-
if (override.length === 0 || !
|
|
2491
|
+
if (override.length === 0 || !isAbsolute7(override)) {
|
|
2216
2492
|
return [];
|
|
2217
2493
|
}
|
|
2218
2494
|
const executable = await resolveExecutablePath(override, context.platform);
|
|
@@ -2266,10 +2542,7 @@ async function resolveAdapterExecutable(specification, context) {
|
|
|
2266
2542
|
const executables = await resolveAdapterExecutables(specification, context);
|
|
2267
2543
|
return executables[0] ?? null;
|
|
2268
2544
|
}
|
|
2269
|
-
function
|
|
2270
|
-
return output2.trim().split(/\r?\n/, 1)[0]?.trim().slice(0, 128) ?? "";
|
|
2271
|
-
}
|
|
2272
|
-
async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal, timeoutMilliseconds) {
|
|
2545
|
+
async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal, timeoutMilliseconds, normalize4 = normalizeVersionOutput) {
|
|
2273
2546
|
const result = await runBoundedProcess({
|
|
2274
2547
|
arguments: arguments_,
|
|
2275
2548
|
command: executable.path,
|
|
@@ -2278,7 +2551,7 @@ async function probeVersion(executable, arguments_, environment, defaultWorkspac
|
|
|
2278
2551
|
signal,
|
|
2279
2552
|
timeoutMilliseconds
|
|
2280
2553
|
});
|
|
2281
|
-
const version2 =
|
|
2554
|
+
const version2 = normalize4(result.stdout || result.stderr);
|
|
2282
2555
|
if (version2.length === 0) {
|
|
2283
2556
|
throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version");
|
|
2284
2557
|
}
|
|
@@ -2302,7 +2575,8 @@ async function findVerifiedAgentExecutable(specification, context) {
|
|
|
2302
2575
|
context.environment,
|
|
2303
2576
|
context.defaultWorkspace,
|
|
2304
2577
|
context.signal,
|
|
2305
|
-
specification.versionProbeTimeoutMilliseconds
|
|
2578
|
+
specification.versionProbeTimeoutMilliseconds,
|
|
2579
|
+
specification.normalizeAgentVersion
|
|
2306
2580
|
);
|
|
2307
2581
|
return new VerifiedAgentExecutable(executable, version2);
|
|
2308
2582
|
} catch {
|
|
@@ -2314,168 +2588,6 @@ async function findVerifiedAgentExecutable(specification, context) {
|
|
|
2314
2588
|
return null;
|
|
2315
2589
|
}
|
|
2316
2590
|
|
|
2317
|
-
// src/agent-catalog/acp-readiness-probe.ts
|
|
2318
|
-
var ACP_OUTPUT_LIMIT_BYTES = 1024 * 1024;
|
|
2319
|
-
var VerifiedAcpReadiness = class {
|
|
2320
|
-
adapterVersion;
|
|
2321
|
-
capabilities;
|
|
2322
|
-
constructor(adapterVersion, capabilities) {
|
|
2323
|
-
this.adapterVersion = adapterVersion;
|
|
2324
|
-
this.capabilities = capabilities;
|
|
2325
|
-
}
|
|
2326
|
-
};
|
|
2327
|
-
var DiscoveryAcpHandler = class {
|
|
2328
|
-
onElicitation = (_request, _signal) => Promise.reject(new Error("ACP probe does not accept elicitations"));
|
|
2329
|
-
onElicitationComplete = (_notification) => Promise.resolve();
|
|
2330
|
-
onPermission = (_request, _signal) => Promise.reject(new Error("ACP probe does not grant permissions"));
|
|
2331
|
-
onUpdate = (_notification) => Promise.resolve();
|
|
2332
|
-
};
|
|
2333
|
-
function readableAcpStream(input2) {
|
|
2334
|
-
let byteLength = 0;
|
|
2335
|
-
let open5 = true;
|
|
2336
|
-
return new ReadableStream({
|
|
2337
|
-
start(controller) {
|
|
2338
|
-
input2.on("data", (chunk) => {
|
|
2339
|
-
if (!open5) {
|
|
2340
|
-
return;
|
|
2341
|
-
}
|
|
2342
|
-
if (!(chunk instanceof Uint8Array)) {
|
|
2343
|
-
open5 = false;
|
|
2344
|
-
controller.error(new Error("ACP adapter produced invalid output"));
|
|
2345
|
-
return;
|
|
2346
|
-
}
|
|
2347
|
-
byteLength += chunk.byteLength;
|
|
2348
|
-
if (byteLength > ACP_OUTPUT_LIMIT_BYTES) {
|
|
2349
|
-
open5 = false;
|
|
2350
|
-
controller.error(new Error("ACP adapter output limit exceeded"));
|
|
2351
|
-
return;
|
|
2352
|
-
}
|
|
2353
|
-
controller.enqueue(new Uint8Array(chunk));
|
|
2354
|
-
});
|
|
2355
|
-
input2.once("end", () => {
|
|
2356
|
-
if (open5) {
|
|
2357
|
-
open5 = false;
|
|
2358
|
-
controller.close();
|
|
2359
|
-
}
|
|
2360
|
-
});
|
|
2361
|
-
input2.once("error", (error61) => {
|
|
2362
|
-
if (open5) {
|
|
2363
|
-
open5 = false;
|
|
2364
|
-
controller.error(error61);
|
|
2365
|
-
}
|
|
2366
|
-
});
|
|
2367
|
-
},
|
|
2368
|
-
cancel() {
|
|
2369
|
-
open5 = false;
|
|
2370
|
-
}
|
|
2371
|
-
});
|
|
2372
|
-
}
|
|
2373
|
-
function writableAcpStream(output2) {
|
|
2374
|
-
return new WritableStream({
|
|
2375
|
-
write(chunk) {
|
|
2376
|
-
return new Promise((resolveWrite, rejectWrite) => {
|
|
2377
|
-
output2.write(chunk, (error61) => {
|
|
2378
|
-
if (error61) {
|
|
2379
|
-
rejectWrite(error61);
|
|
2380
|
-
return;
|
|
2381
|
-
}
|
|
2382
|
-
resolveWrite();
|
|
2383
|
-
});
|
|
2384
|
-
});
|
|
2385
|
-
}
|
|
2386
|
-
});
|
|
2387
|
-
}
|
|
2388
|
-
async function probeAcpReadiness(specification, agent, environment, defaultWorkspace, signal) {
|
|
2389
|
-
signal.throwIfAborted();
|
|
2390
|
-
const controller = new AbortController();
|
|
2391
|
-
let timedOut = false;
|
|
2392
|
-
const timeout = setTimeout(() => {
|
|
2393
|
-
timedOut = true;
|
|
2394
|
-
controller.abort(new Error("ACP probe timed out"));
|
|
2395
|
-
}, specification.acpProbeTimeoutMilliseconds);
|
|
2396
|
-
const abort = () => controller.abort(signal.reason);
|
|
2397
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
2398
|
-
if (signal.aborted) {
|
|
2399
|
-
abort();
|
|
2400
|
-
}
|
|
2401
|
-
const child = spawn2(agent.adapterPath, [...agent.arguments], {
|
|
2402
|
-
cwd: defaultWorkspace,
|
|
2403
|
-
detached: process.platform !== "win32",
|
|
2404
|
-
env: { ...environment, ...agent.environment },
|
|
2405
|
-
shell: false,
|
|
2406
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
2407
|
-
});
|
|
2408
|
-
const processExit = new Promise((_resolve, reject) => {
|
|
2409
|
-
const rejectExit = () => reject(new Error("ACP adapter exited during initialization"));
|
|
2410
|
-
child.once("error", reject);
|
|
2411
|
-
child.once("exit", rejectExit);
|
|
2412
|
-
if (child.exitCode !== null || child.signalCode !== null) {
|
|
2413
|
-
rejectExit();
|
|
2414
|
-
}
|
|
2415
|
-
});
|
|
2416
|
-
const stdin = child.stdin;
|
|
2417
|
-
const stdout = child.stdout;
|
|
2418
|
-
const stderr = child.stderr;
|
|
2419
|
-
if (stdin === null || stdout === null || stderr === null) {
|
|
2420
|
-
await stopProcessTree(child);
|
|
2421
|
-
throw new AgentProbeError("acp_incompatible", "ACP adapter streams are unavailable");
|
|
2422
|
-
}
|
|
2423
|
-
let stderrBytes = 0;
|
|
2424
|
-
const consumeStderr = (chunk) => {
|
|
2425
|
-
stderrBytes += chunk.byteLength;
|
|
2426
|
-
if (stderrBytes > ACP_OUTPUT_LIMIT_BYTES) {
|
|
2427
|
-
controller.abort(new Error("ACP adapter output limit exceeded"));
|
|
2428
|
-
}
|
|
2429
|
-
};
|
|
2430
|
-
stderr.on("data", consumeStderr);
|
|
2431
|
-
const connection = createAcpClient(new DiscoveryAcpHandler()).connect(
|
|
2432
|
-
ndJsonStream(writableAcpStream(stdin), readableAcpStream(stdout))
|
|
2433
|
-
);
|
|
2434
|
-
try {
|
|
2435
|
-
const initialized = await Promise.race([
|
|
2436
|
-
connection.agent.request(
|
|
2437
|
-
methods4.agent.initialize,
|
|
2438
|
-
{
|
|
2439
|
-
clientCapabilities: {},
|
|
2440
|
-
clientInfo: { name: "mobius", version: "0.0.3" },
|
|
2441
|
-
protocolVersion: PROTOCOL_VERSION
|
|
2442
|
-
},
|
|
2443
|
-
{ cancellationSignal: controller.signal }
|
|
2444
|
-
),
|
|
2445
|
-
processExit
|
|
2446
|
-
]);
|
|
2447
|
-
if (initialized.protocolVersion !== PROTOCOL_VERSION) {
|
|
2448
|
-
throw new AgentProbeError("acp_incompatible", "ACP adapter selected an unsupported protocol version");
|
|
2449
|
-
}
|
|
2450
|
-
await specification.verifyAcp(connection, initialized, defaultWorkspace, controller.signal);
|
|
2451
|
-
return new VerifiedAcpReadiness(
|
|
2452
|
-
normalizedVersion(initialized.agentInfo?.version ?? ""),
|
|
2453
|
-
normalizeAcpCapabilities(initialized)
|
|
2454
|
-
);
|
|
2455
|
-
} catch (error61) {
|
|
2456
|
-
if (signal.aborted) {
|
|
2457
|
-
signal.throwIfAborted();
|
|
2458
|
-
}
|
|
2459
|
-
if (timedOut) {
|
|
2460
|
-
throw new AgentProbeError("adapter_probe_timeout", "ACP adapter probe timed out", { cause: error61 });
|
|
2461
|
-
}
|
|
2462
|
-
if (error61 instanceof AgentProbeError) {
|
|
2463
|
-
throw error61;
|
|
2464
|
-
}
|
|
2465
|
-
if (error61 instanceof RequestError && error61.code === -32e3 && specification.authenticationCommand().length > 0) {
|
|
2466
|
-
throw new AgentProbeError("authentication_required", "Agent authentication is required", { cause: error61 });
|
|
2467
|
-
}
|
|
2468
|
-
throw new AgentProbeError("acp_incompatible", "ACP adapter initialization failed", { cause: error61 });
|
|
2469
|
-
} finally {
|
|
2470
|
-
clearTimeout(timeout);
|
|
2471
|
-
signal.removeEventListener("abort", abort);
|
|
2472
|
-
connection.close();
|
|
2473
|
-
stdin.end();
|
|
2474
|
-
stderr.removeListener("data", consumeStderr);
|
|
2475
|
-
await stopProcessTree(child);
|
|
2476
|
-
}
|
|
2477
|
-
}
|
|
2478
|
-
|
|
2479
2591
|
// src/agent-catalog/discover-agent.ts
|
|
2480
2592
|
function agentProbeFailure(specification, error61) {
|
|
2481
2593
|
if (error61 instanceof AgentProbeError) {
|
|
@@ -2519,7 +2631,8 @@ async function discoverAgent(specification, context) {
|
|
|
2519
2631
|
context.environment,
|
|
2520
2632
|
context.defaultWorkspace,
|
|
2521
2633
|
context.signal,
|
|
2522
|
-
specification.versionProbeTimeoutMilliseconds
|
|
2634
|
+
specification.versionProbeTimeoutMilliseconds,
|
|
2635
|
+
specification.normalizeAgentVersion
|
|
2523
2636
|
);
|
|
2524
2637
|
} catch (error61) {
|
|
2525
2638
|
if (context.signal.aborted) {
|
|
@@ -2555,7 +2668,8 @@ async function discoverAgent(specification, context) {
|
|
|
2555
2668
|
},
|
|
2556
2669
|
context.defaultWorkspace,
|
|
2557
2670
|
context.signal,
|
|
2558
|
-
specification.versionProbeTimeoutMilliseconds
|
|
2671
|
+
specification.versionProbeTimeoutMilliseconds,
|
|
2672
|
+
specification.normalizeAdapterVersion
|
|
2559
2673
|
);
|
|
2560
2674
|
}
|
|
2561
2675
|
} catch (error61) {
|
|
@@ -2788,7 +2902,7 @@ async function executeBotMessageCommand(arguments_, environment, signal) {
|
|
|
2788
2902
|
}
|
|
2789
2903
|
|
|
2790
2904
|
// src/config.ts
|
|
2791
|
-
import { join as
|
|
2905
|
+
import { join as join14 } from "node:path";
|
|
2792
2906
|
|
|
2793
2907
|
// ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/external.js
|
|
2794
2908
|
var external_exports = {};
|
|
@@ -21658,6 +21772,28 @@ function date4(params) {
|
|
|
21658
21772
|
|
|
21659
21773
|
// ../protocol/src/prompt-usage.ts
|
|
21660
21774
|
var TOKEN_COUNT = external_exports.number().int().nonnegative();
|
|
21775
|
+
function normalizeQuotaTokenCount(value) {
|
|
21776
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
21777
|
+
return value;
|
|
21778
|
+
}
|
|
21779
|
+
if (Reflect.has(value, "inputTokens") || Reflect.has(value, "outputTokens") || Reflect.has(value, "totalTokens")) {
|
|
21780
|
+
return value;
|
|
21781
|
+
}
|
|
21782
|
+
if (!Reflect.has(value, "input_tokens") && !Reflect.has(value, "output_tokens")) {
|
|
21783
|
+
return value;
|
|
21784
|
+
}
|
|
21785
|
+
const inputTokens = Reflect.get(value, "input_tokens");
|
|
21786
|
+
const outputTokens = Reflect.get(value, "output_tokens");
|
|
21787
|
+
const reportedTotal = Reflect.get(value, "total_tokens");
|
|
21788
|
+
return {
|
|
21789
|
+
cachedInputTokens: Reflect.get(value, "cached_input_tokens"),
|
|
21790
|
+
cachedWriteTokens: Reflect.get(value, "cached_write_tokens"),
|
|
21791
|
+
inputTokens,
|
|
21792
|
+
outputTokens,
|
|
21793
|
+
reasoningOutputTokens: Reflect.get(value, "reasoning_output_tokens"),
|
|
21794
|
+
totalTokens: reportedTotal === void 0 && typeof inputTokens === "number" && typeof outputTokens === "number" ? inputTokens + outputTokens : reportedTotal
|
|
21795
|
+
};
|
|
21796
|
+
}
|
|
21661
21797
|
var promptUsageSchema = external_exports.object({
|
|
21662
21798
|
cachedReadTokens: TOKEN_COUNT.nullish(),
|
|
21663
21799
|
cachedWriteTokens: TOKEN_COUNT.nullish(),
|
|
@@ -21666,14 +21802,17 @@ var promptUsageSchema = external_exports.object({
|
|
|
21666
21802
|
thoughtTokens: TOKEN_COUNT.nullish(),
|
|
21667
21803
|
totalTokens: TOKEN_COUNT
|
|
21668
21804
|
}).readonly();
|
|
21669
|
-
var quotaTokenCountSchema = external_exports.
|
|
21670
|
-
|
|
21671
|
-
|
|
21672
|
-
|
|
21673
|
-
|
|
21674
|
-
|
|
21675
|
-
|
|
21676
|
-
|
|
21805
|
+
var quotaTokenCountSchema = external_exports.preprocess(
|
|
21806
|
+
normalizeQuotaTokenCount,
|
|
21807
|
+
external_exports.object({
|
|
21808
|
+
cachedInputTokens: TOKEN_COUNT.optional(),
|
|
21809
|
+
cachedWriteTokens: TOKEN_COUNT.optional(),
|
|
21810
|
+
inputTokens: TOKEN_COUNT,
|
|
21811
|
+
outputTokens: TOKEN_COUNT,
|
|
21812
|
+
reasoningOutputTokens: TOKEN_COUNT.optional(),
|
|
21813
|
+
totalTokens: TOKEN_COUNT
|
|
21814
|
+
}).readonly()
|
|
21815
|
+
);
|
|
21677
21816
|
var promptMetadataSchema = external_exports.object({
|
|
21678
21817
|
quota: external_exports.object({
|
|
21679
21818
|
model_usage: external_exports.array(
|
|
@@ -23301,7 +23440,7 @@ var decodeSessionEventRejection = (encoded) => decode5(encoded, eventRejectionSc
|
|
|
23301
23440
|
// src/config.ts
|
|
23302
23441
|
function loadDefaultWorkspace(environment = process.env) {
|
|
23303
23442
|
const { MOBIUS_DEFAULT_WORKSPACE: configuredWorkspace } = environment;
|
|
23304
|
-
return configuredWorkspace ??
|
|
23443
|
+
return configuredWorkspace ?? join14(readStateDirectory(environment), "workspace");
|
|
23305
23444
|
}
|
|
23306
23445
|
function createDaemonConfig(connection, agents = [], installableAgents = []) {
|
|
23307
23446
|
return {
|
|
@@ -23320,7 +23459,7 @@ function createDaemonConfig(connection, agents = [], installableAgents = []) {
|
|
|
23320
23459
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23321
23460
|
import { mkdir as mkdir3, open as open4, realpath as realpath6, rename as rename3, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
|
|
23322
23461
|
import { hostname as hostname3 } from "node:os";
|
|
23323
|
-
import { basename, join as
|
|
23462
|
+
import { basename, join as join15, resolve as resolve3 } from "node:path";
|
|
23324
23463
|
import { fetch as fetch2 } from "undici";
|
|
23325
23464
|
var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
|
|
23326
23465
|
var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
|
|
@@ -23520,10 +23659,10 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
|
|
|
23520
23659
|
return options.pairingId.length > 0 ? decodePairingResponse(value, "runtimeCredential", REDEEM_RESPONSE_KEYS) : decodePairingResponse(value, "daemonToken", CLAIM_RESPONSE_KEYS);
|
|
23521
23660
|
}
|
|
23522
23661
|
async function persistConnection(channelId, relayOrigin, runtimeCredential2, defaultWorkspace, environment) {
|
|
23523
|
-
const connectionsDirectory =
|
|
23662
|
+
const connectionsDirectory = join15(readStateDirectory(environment), "connections");
|
|
23524
23663
|
await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
|
|
23525
|
-
const connectionPath =
|
|
23526
|
-
const temporaryPath =
|
|
23664
|
+
const connectionPath = join15(connectionsDirectory, `${channelId}.json`);
|
|
23665
|
+
const temporaryPath = join15(connectionsDirectory, `.${channelId}.${randomUUID2()}.tmp`);
|
|
23527
23666
|
await writeFile2(
|
|
23528
23667
|
temporaryPath,
|
|
23529
23668
|
`${JSON.stringify(
|
|
@@ -23561,7 +23700,7 @@ function decodeSavedConnection(value, expectedChannelId) {
|
|
|
23561
23700
|
};
|
|
23562
23701
|
}
|
|
23563
23702
|
async function readSavedConnection(channelId, environment) {
|
|
23564
|
-
const connectionPath =
|
|
23703
|
+
const connectionPath = join15(readStateDirectory(environment), "connections", `${channelId}.json`);
|
|
23565
23704
|
let encoded = "";
|
|
23566
23705
|
const handle = await open4(connectionPath, "r");
|
|
23567
23706
|
try {
|
|
@@ -23597,7 +23736,7 @@ function buildPairedDaemon(connection, connectionPath, inventory, environment) {
|
|
|
23597
23736
|
const relayUrl = mobiusApiUrl(connection.relayOrigin, "/v1/runtimes/connect");
|
|
23598
23737
|
relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
23599
23738
|
relayUrl.searchParams.set("token", connection.runtimeCredential);
|
|
23600
|
-
const auditDatabasePath =
|
|
23739
|
+
const auditDatabasePath = join15(readStateDirectory(environment), "audit", `${connection.channelId}.sqlite`);
|
|
23601
23740
|
return {
|
|
23602
23741
|
channelUrl: new URL(`/channels/${encodeURIComponent(connection.channelId)}`, connection.relayOrigin).toString(),
|
|
23603
23742
|
config: createDaemonConfig(
|
|
@@ -23647,7 +23786,7 @@ async function pairLocalMachine(arguments_, signal = new AbortController().signa
|
|
|
23647
23786
|
}
|
|
23648
23787
|
async function resumeMobiusRuntime(channelId, signal, environment = process.env) {
|
|
23649
23788
|
const normalizedChannelId = validatePairingId(channelId);
|
|
23650
|
-
const connectionPath =
|
|
23789
|
+
const connectionPath = join15(readStateDirectory(environment), "connections", `${normalizedChannelId}.json`);
|
|
23651
23790
|
const connection = await readSavedConnection(normalizedChannelId, environment);
|
|
23652
23791
|
const inventory = await discoverLocalAgentInventory({
|
|
23653
23792
|
defaultWorkspace: connection.defaultWorkspace,
|
|
@@ -23710,7 +23849,7 @@ var AuditStore = class {
|
|
|
23710
23849
|
|
|
23711
23850
|
// src/run-daemon.ts
|
|
23712
23851
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
23713
|
-
import { basename as basename5, join as
|
|
23852
|
+
import { basename as basename5, join as join17 } from "node:path";
|
|
23714
23853
|
import { styleText } from "node:util";
|
|
23715
23854
|
import { fetch as fetch7, WebSocket as WebSocket2 } from "undici";
|
|
23716
23855
|
|
|
@@ -23725,7 +23864,7 @@ import {
|
|
|
23725
23864
|
|
|
23726
23865
|
// src/authorization/local-raster.ts
|
|
23727
23866
|
import { readFile, realpath as realpath7, stat as stat6 } from "node:fs/promises";
|
|
23728
|
-
import { basename as basename2, isAbsolute as
|
|
23867
|
+
import { basename as basename2, isAbsolute as isAbsolute8, normalize as normalize2, relative as relative4, sep as sep4 } from "node:path";
|
|
23729
23868
|
import { fileURLToPath } from "node:url";
|
|
23730
23869
|
var MAX_LOCAL_RASTER_BYTES = 3e6;
|
|
23731
23870
|
var PNG_SIGNATURE = Uint8Array.of(137, 80, 78, 71);
|
|
@@ -23768,17 +23907,17 @@ function sniffRasterMime(bytes) {
|
|
|
23768
23907
|
}
|
|
23769
23908
|
function isInsideRoot(root, target) {
|
|
23770
23909
|
const relation = relative4(root, target);
|
|
23771
|
-
return relation !== ".." && !relation.startsWith(`..${sep4}`) && !
|
|
23910
|
+
return relation !== ".." && !relation.startsWith(`..${sep4}`) && !isAbsolute8(relation);
|
|
23772
23911
|
}
|
|
23773
23912
|
async function resolveCanonicalPath(requested, signal) {
|
|
23774
23913
|
signal.throwIfAborted();
|
|
23775
|
-
if (!
|
|
23914
|
+
if (!isAbsolute8(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
|
|
23776
23915
|
return null;
|
|
23777
23916
|
}
|
|
23778
23917
|
try {
|
|
23779
23918
|
const target = await realpath7(requested);
|
|
23780
23919
|
signal.throwIfAborted();
|
|
23781
|
-
if (!
|
|
23920
|
+
if (!isAbsolute8(target) || normalize2(target) !== target) {
|
|
23782
23921
|
return null;
|
|
23783
23922
|
}
|
|
23784
23923
|
return target;
|
|
@@ -28308,7 +28447,7 @@ var LocalAuthorizationError = class extends Error {
|
|
|
28308
28447
|
// src/authorization/workspace-directory.ts
|
|
28309
28448
|
import { readdir, realpath as realpath8, stat as stat7 } from "node:fs/promises";
|
|
28310
28449
|
import { homedir as homedir2 } from "node:os";
|
|
28311
|
-
import { basename as basename3, dirname as dirname5, isAbsolute as
|
|
28450
|
+
import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute9, join as join16, normalize as normalize3, relative as relative5 } from "node:path";
|
|
28312
28451
|
var WorkspaceDirectoryListing = class {
|
|
28313
28452
|
directoryId;
|
|
28314
28453
|
directoryLabel;
|
|
@@ -28360,7 +28499,7 @@ var WorkspaceDirectoryService = class {
|
|
|
28360
28499
|
}
|
|
28361
28500
|
if (id.startsWith("path-")) {
|
|
28362
28501
|
const path2 = decodePath(id, "path-");
|
|
28363
|
-
if (
|
|
28502
|
+
if (isAbsolute9(path2)) {
|
|
28364
28503
|
return path2;
|
|
28365
28504
|
}
|
|
28366
28505
|
}
|
|
@@ -28368,7 +28507,7 @@ var WorkspaceDirectoryService = class {
|
|
|
28368
28507
|
};
|
|
28369
28508
|
resolvePath = async (requested, signal) => {
|
|
28370
28509
|
signal.throwIfAborted();
|
|
28371
|
-
if (!
|
|
28510
|
+
if (!isAbsolute9(requested) || requested.includes("\0") || normalize3(requested) !== requested) {
|
|
28372
28511
|
throw new LocalAuthorizationError("The local directory path is invalid");
|
|
28373
28512
|
}
|
|
28374
28513
|
try {
|
|
@@ -28376,7 +28515,7 @@ var WorkspaceDirectoryService = class {
|
|
|
28376
28515
|
signal.throwIfAborted();
|
|
28377
28516
|
const metadata = await stat7(target);
|
|
28378
28517
|
signal.throwIfAborted();
|
|
28379
|
-
if (!
|
|
28518
|
+
if (!isAbsolute9(target) || normalize3(target) !== target || !metadata.isDirectory()) {
|
|
28380
28519
|
throw new LocalAuthorizationError("The selected location is not a directory");
|
|
28381
28520
|
}
|
|
28382
28521
|
return target;
|
|
@@ -28392,7 +28531,7 @@ var WorkspaceDirectoryService = class {
|
|
|
28392
28531
|
};
|
|
28393
28532
|
label = (path2) => {
|
|
28394
28533
|
const suffix = relative5(homedir2(), path2);
|
|
28395
|
-
return suffix === "" ? "~" : !
|
|
28534
|
+
return suffix === "" ? "~" : !isAbsolute9(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
|
|
28396
28535
|
};
|
|
28397
28536
|
identify = async (bindingId, requestedPath, signal) => {
|
|
28398
28537
|
this.authorizeMachine(bindingId);
|
|
@@ -28422,7 +28561,7 @@ var WorkspaceDirectoryService = class {
|
|
|
28422
28561
|
continue;
|
|
28423
28562
|
}
|
|
28424
28563
|
try {
|
|
28425
|
-
const path2 = await this.resolvePath(
|
|
28564
|
+
const path2 = await this.resolvePath(join16(target, child.name), signal);
|
|
28426
28565
|
entries.push({ directoryId: encodePath(path2), name: child.name });
|
|
28427
28566
|
} catch (cause) {
|
|
28428
28567
|
signal.throwIfAborted();
|
|
@@ -28933,7 +29072,7 @@ var BotExecutionContextRegistry = class {
|
|
|
28933
29072
|
// src/bots/bot-outbound-ipc.ts
|
|
28934
29073
|
import { chmod as chmod2, mkdir as mkdir4, unlink } from "node:fs/promises";
|
|
28935
29074
|
import { createServer } from "node:net";
|
|
28936
|
-
import { dirname as dirname6, isAbsolute as
|
|
29075
|
+
import { dirname as dirname6, isAbsolute as isAbsolute10 } from "node:path";
|
|
28937
29076
|
import { fetch as fetch5 } from "undici";
|
|
28938
29077
|
var BOT_IPC_REQUEST_LIMIT = 32 * 1024;
|
|
28939
29078
|
var BOT_IPC_TIMEOUT_MILLISECONDS2 = 2e4;
|
|
@@ -29031,7 +29170,7 @@ var BotOutboundIpcServer = class {
|
|
|
29031
29170
|
#usesFilesystemSocket;
|
|
29032
29171
|
constructor(socketPath, relayUrl, registry2) {
|
|
29033
29172
|
const usesFilesystemSocket = !socketPath.startsWith(WINDOWS_NAMED_PIPE_PREFIX);
|
|
29034
|
-
if (usesFilesystemSocket && !
|
|
29173
|
+
if (usesFilesystemSocket && !isAbsolute10(socketPath)) {
|
|
29035
29174
|
throw new Error("The Bot IPC path must be absolute");
|
|
29036
29175
|
}
|
|
29037
29176
|
this.#registry = registry2;
|
|
@@ -30971,7 +31110,7 @@ function botIpcSocketPath() {
|
|
|
30971
31110
|
if (process.platform === "win32") {
|
|
30972
31111
|
return `\\\\.\\pipe\\mobius-bot-${randomUUID6()}`;
|
|
30973
31112
|
}
|
|
30974
|
-
return
|
|
31113
|
+
return join17("/tmp", `mobius-bot-${randomUUID6()}.sock`);
|
|
30975
31114
|
}
|
|
30976
31115
|
var DaemonAcpObserver = class {
|
|
30977
31116
|
#config;
|