@moxt-ai/mobius 0.0.27 → 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/acp/activity.d.ts +1 -0
- package/dist/acp/activity.d.ts.map +1 -1
- package/dist/acp/activity.js +14 -1
- package/dist/acp/activity.js.map +1 -1
- package/dist/acp/session-history.d.ts.map +1 -1
- package/dist/acp/session-history.js +10 -16
- package/dist/acp/session-history.js.map +1 -1
- package/dist/acp/session-manager.d.ts +7 -0
- package/dist/acp/session-manager.d.ts.map +1 -1
- package/dist/acp/session-manager.js +65 -11
- package/dist/acp/session-manager.js.map +1 -1
- 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/artifacts/runtime-artifact-uploader.d.ts +12 -0
- package/dist/artifacts/runtime-artifact-uploader.d.ts.map +1 -0
- package/dist/artifacts/runtime-artifact-uploader.js +157 -0
- package/dist/artifacts/runtime-artifact-uploader.js.map +1 -0
- package/dist/authorization/local-raster.d.ts +10 -0
- package/dist/authorization/local-raster.d.ts.map +1 -0
- package/dist/authorization/local-raster.js +134 -0
- package/dist/authorization/local-raster.js.map +1 -0
- package/dist/cli.js +1185 -333
- package/dist/cli.js.map +4 -4
- package/dist/index.js +1245 -396
- package/dist/index.js.map +4 -4
- package/dist/native-sessions/codex-history.d.ts.map +1 -1
- package/dist/native-sessions/codex-history.js +11 -11
- package/dist/native-sessions/codex-history.js.map +1 -1
- package/dist/native-sessions/history-images.d.ts +3 -0
- package/dist/native-sessions/history-images.d.ts.map +1 -0
- package/dist/native-sessions/history-images.js +74 -0
- package/dist/native-sessions/history-images.js.map +1 -0
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +30 -7
- package/dist/run-daemon.js.map +1 -1
- package/dist/runtime.js +1205 -354
- package/dist/runtime.js.map +4 -4
- package/package.json +2 -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: {
|
|
@@ -55,6 +55,7 @@ var package_default = {
|
|
|
55
55
|
},
|
|
56
56
|
devDependencies: {
|
|
57
57
|
"@moxt-ai/mobius-protocol": "workspace:*",
|
|
58
|
+
"@moxt-ai/mobius-sdk": "workspace:*",
|
|
58
59
|
"@types/node": "^24.13.3",
|
|
59
60
|
esbuild: "0.28.2"
|
|
60
61
|
},
|
|
@@ -1157,6 +1158,13 @@ var ManagedNpmPackageInstaller = class {
|
|
|
1157
1158
|
|
|
1158
1159
|
// src/agent-catalog/agent-specification.ts
|
|
1159
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
|
|
1160
1168
|
var VERSION_PROBE_TIMEOUT_MILLISECONDS = 3e3;
|
|
1161
1169
|
var ACP_PROBE_TIMEOUT_MILLISECONDS = 5e3;
|
|
1162
1170
|
var DEFAULT_PROMPT_TIMEOUT_MILLISECONDS = 30 * 60 * 1e3;
|
|
@@ -1165,6 +1173,8 @@ var LocalAgentSpecification = class {
|
|
|
1165
1173
|
authenticationCommand = () => "";
|
|
1166
1174
|
adapterVersionArguments = ["--version"];
|
|
1167
1175
|
agentVersionArguments = ["--version"];
|
|
1176
|
+
normalizeAdapterVersion = normalizeVersionOutput;
|
|
1177
|
+
normalizeAgentVersion = normalizeVersionOutput;
|
|
1168
1178
|
promptTimeoutMilliseconds = DEFAULT_PROMPT_TIMEOUT_MILLISECONDS;
|
|
1169
1179
|
versionProbeTimeoutMilliseconds = VERSION_PROBE_TIMEOUT_MILLISECONDS;
|
|
1170
1180
|
resolveManagedAgent = async (stateDirectory, platform, signal) => {
|
|
@@ -1276,6 +1286,20 @@ var AgentProbeError = class extends Error {
|
|
|
1276
1286
|
}
|
|
1277
1287
|
};
|
|
1278
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
|
+
|
|
1279
1303
|
// src/agent-catalog/agents/verify-session-creation.ts
|
|
1280
1304
|
import { methods } from "@agentclientprotocol/sdk";
|
|
1281
1305
|
async function verifySessionCreation(connection, capabilities, defaultWorkspace, signal, label) {
|
|
@@ -1300,6 +1324,37 @@ async function verifySessionCreation(connection, capabilities, defaultWorkspace,
|
|
|
1300
1324
|
}
|
|
1301
1325
|
}
|
|
1302
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
|
+
|
|
1303
1358
|
// src/agent-catalog/agents/cursor-cli-agent.ts
|
|
1304
1359
|
var CURSOR_CLI_TESTED_VERSION = "2026.09.02-c22c1a3";
|
|
1305
1360
|
var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
@@ -1326,7 +1381,7 @@ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1326
1381
|
|
|
1327
1382
|
// src/agent-catalog/agents/deepseek-harness-agent.ts
|
|
1328
1383
|
import { realpath as realpath3, stat as stat3 } from "node:fs/promises";
|
|
1329
|
-
import { isAbsolute as
|
|
1384
|
+
import { isAbsolute as isAbsolute3, join as join6, normalize } from "node:path";
|
|
1330
1385
|
|
|
1331
1386
|
// src/agent-installation/deepseek-managed-package.ts
|
|
1332
1387
|
var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
|
|
@@ -1344,18 +1399,18 @@ var DEEPSEEK_HARNESS_PACKAGE = new DeepSeekHarnessManagedPackage(
|
|
|
1344
1399
|
|
|
1345
1400
|
// src/storage/state-directory.ts
|
|
1346
1401
|
import { homedir } from "node:os";
|
|
1347
|
-
import { join as
|
|
1402
|
+
import { join as join5, resolve as resolve2 } from "node:path";
|
|
1348
1403
|
function readStateDirectory(environment = process.env) {
|
|
1349
1404
|
const configured = environment["MOBIUS_STATE_DIRECTORY"]?.trim();
|
|
1350
1405
|
if (configured !== void 0 && configured.length > 0) {
|
|
1351
1406
|
return resolve2(configured);
|
|
1352
1407
|
}
|
|
1353
|
-
return
|
|
1408
|
+
return join5(homedir(), ".mobius");
|
|
1354
1409
|
}
|
|
1355
1410
|
|
|
1356
1411
|
// src/agent-catalog/agents/deepseek-harness-agent.ts
|
|
1357
1412
|
async function validateAgentHome(path2) {
|
|
1358
|
-
if (!
|
|
1413
|
+
if (!isAbsolute3(path2) || normalize(path2) !== path2) {
|
|
1359
1414
|
throw new AgentProbeError("agent_environment_invalid", "The configured Agent home is invalid");
|
|
1360
1415
|
}
|
|
1361
1416
|
try {
|
|
@@ -1405,7 +1460,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1405
1460
|
context.signal
|
|
1406
1461
|
);
|
|
1407
1462
|
if (managed.path === agent.path) {
|
|
1408
|
-
selectedHome =
|
|
1463
|
+
selectedHome = join6(readStateDirectory(context.environment), "agents", this.id, "home");
|
|
1409
1464
|
}
|
|
1410
1465
|
} catch {
|
|
1411
1466
|
context.signal.throwIfAborted();
|
|
@@ -1421,7 +1476,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1421
1476
|
resolveManagedAgent = async (stateDirectory, _platform, signal) => {
|
|
1422
1477
|
signal.throwIfAborted();
|
|
1423
1478
|
const executable = await validateManagedNpmPackage(
|
|
1424
|
-
|
|
1479
|
+
join6(stateDirectory, "agents", this.id, DEEPSEEK_HARNESS_PACKAGE.version),
|
|
1425
1480
|
DEEPSEEK_HARNESS_PACKAGE
|
|
1426
1481
|
);
|
|
1427
1482
|
signal.throwIfAborted();
|
|
@@ -1441,9 +1496,41 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1441
1496
|
};
|
|
1442
1497
|
};
|
|
1443
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
|
+
|
|
1444
1531
|
// src/agent-catalog/agents/grok-build-agent.ts
|
|
1445
1532
|
import { realpath as realpath4 } from "node:fs/promises";
|
|
1446
|
-
import { isAbsolute as
|
|
1533
|
+
import { isAbsolute as isAbsolute4, join as join7, relative as relative2, sep as sep2 } from "node:path";
|
|
1447
1534
|
|
|
1448
1535
|
// src/agent-installation/grok-managed-package.ts
|
|
1449
1536
|
var GROK_BUILD_MANAGED_VERSION = "1.0.21";
|
|
@@ -1506,7 +1593,7 @@ function grokBuildManagedPackage(platform, architecture) {
|
|
|
1506
1593
|
// src/agent-catalog/agents/grok-build-agent.ts
|
|
1507
1594
|
function isContainedPath2(root, candidate) {
|
|
1508
1595
|
const difference = relative2(root, candidate);
|
|
1509
|
-
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !
|
|
1596
|
+
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute4(difference);
|
|
1510
1597
|
}
|
|
1511
1598
|
var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
1512
1599
|
adapterVersion = GROK_BUILD_MANAGED_VERSION;
|
|
@@ -1534,7 +1621,7 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1534
1621
|
if (managed.path === agent.path) {
|
|
1535
1622
|
return Object.freeze({
|
|
1536
1623
|
GROK_HOME: await realpath4(
|
|
1537
|
-
|
|
1624
|
+
join7(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION, "home")
|
|
1538
1625
|
)
|
|
1539
1626
|
});
|
|
1540
1627
|
}
|
|
@@ -1545,9 +1632,9 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1545
1632
|
};
|
|
1546
1633
|
resolveManagedAgent = async (stateDirectory, platform, signal) => {
|
|
1547
1634
|
signal.throwIfAborted();
|
|
1548
|
-
const versionRoot = await realpath4(
|
|
1549
|
-
await validateManagedNpmPackage(
|
|
1550
|
-
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);
|
|
1551
1638
|
signal.throwIfAborted();
|
|
1552
1639
|
if (executable === null || !isContainedPath2(versionRoot, executable.path)) {
|
|
1553
1640
|
throw new AgentProbeError("managed_agent_invalid", "The managed Grok Build executable is invalid");
|
|
@@ -1564,14 +1651,39 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1564
1651
|
};
|
|
1565
1652
|
};
|
|
1566
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
|
+
|
|
1567
1679
|
// src/agent-catalog/agents/opencode-agent.ts
|
|
1568
|
-
import { join as
|
|
1680
|
+
import { join as join9 } from "node:path";
|
|
1569
1681
|
|
|
1570
1682
|
// src/agent-installation/managed-agent-archive.ts
|
|
1571
1683
|
import { createHash } from "node:crypto";
|
|
1572
1684
|
import { createReadStream } from "node:fs";
|
|
1573
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";
|
|
1574
|
-
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";
|
|
1575
1687
|
|
|
1576
1688
|
// src/agent-installation/verified-download.ts
|
|
1577
1689
|
import { fetch } from "undici";
|
|
@@ -1677,7 +1789,7 @@ function isRecord3(value) {
|
|
|
1677
1789
|
}
|
|
1678
1790
|
function isContainedPath3(root, candidate) {
|
|
1679
1791
|
const difference = relative3(root, candidate);
|
|
1680
|
-
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !
|
|
1792
|
+
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute5(difference);
|
|
1681
1793
|
}
|
|
1682
1794
|
async function hashFile(path2, signal) {
|
|
1683
1795
|
signal.throwIfAborted();
|
|
@@ -1756,11 +1868,11 @@ async function validateManagedAgentArchive(root, definition, signal) {
|
|
|
1756
1868
|
if (!rootMetadata.isDirectory() || typeof process.getuid === "function" && rootMetadata.uid !== process.getuid()) {
|
|
1757
1869
|
throw new Error("Managed Agent root is not user-owned");
|
|
1758
1870
|
}
|
|
1759
|
-
const manifest = await readManifest(
|
|
1871
|
+
const manifest = await readManifest(join8(rootPath, "archive.json"));
|
|
1760
1872
|
if (manifest["archiveSha256"] !== definition.archiveSha256 || manifest["archiveUrl"] !== definition.archiveUrl.toString() || manifest["version"] !== definition.version || typeof manifest["executableSha256"] !== "string") {
|
|
1761
1873
|
throw new Error("Managed Agent archive identity is invalid");
|
|
1762
1874
|
}
|
|
1763
|
-
const executable = await resolveExecutablePath(
|
|
1875
|
+
const executable = await resolveExecutablePath(join8(rootPath, "bin", definition.executableName));
|
|
1764
1876
|
if (executable === null || !isContainedPath3(rootPath, executable.path) || await hashFile(executable.path, signal) !== manifest["executableSha256"]) {
|
|
1765
1877
|
throw new Error("Managed Agent executable is invalid");
|
|
1766
1878
|
}
|
|
@@ -1852,7 +1964,7 @@ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1852
1964
|
}
|
|
1853
1965
|
createLaunchEnvironment = async (_agent, _context) => Object.freeze({ OPENCODE_DISABLE_AUTOUPDATE: "1" });
|
|
1854
1966
|
resolveManagedAgent = async (stateDirectory, platform, signal) => await validateManagedAgentArchive(
|
|
1855
|
-
|
|
1967
|
+
join9(stateDirectory, "agents", this.id, OPENCODE_MANAGED_VERSION),
|
|
1856
1968
|
openCodeManagedArchive(platform, process.arch),
|
|
1857
1969
|
signal
|
|
1858
1970
|
);
|
|
@@ -1870,7 +1982,7 @@ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
1870
1982
|
};
|
|
1871
1983
|
|
|
1872
1984
|
// src/agent-catalog/agents/pi-agent.ts
|
|
1873
|
-
import { join as
|
|
1985
|
+
import { join as join10 } from "node:path";
|
|
1874
1986
|
import {
|
|
1875
1987
|
methods as methods2
|
|
1876
1988
|
} from "@agentclientprotocol/sdk";
|
|
@@ -1929,7 +2041,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
|
|
|
1929
2041
|
resolveManagedAgent = async (stateDirectory, _platform, signal) => {
|
|
1930
2042
|
signal.throwIfAborted();
|
|
1931
2043
|
const executable = await validateManagedNpmPackage(
|
|
1932
|
-
|
|
2044
|
+
join10(stateDirectory, "agents", this.id, PI_AGENT_PACKAGE.version),
|
|
1933
2045
|
PI_AGENT_PACKAGE
|
|
1934
2046
|
);
|
|
1935
2047
|
signal.throwIfAborted();
|
|
@@ -1967,7 +2079,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
|
|
|
1967
2079
|
};
|
|
1968
2080
|
|
|
1969
2081
|
// src/agent-catalog/agents/workbuddy-agent.ts
|
|
1970
|
-
import { isAbsolute as
|
|
2082
|
+
import { isAbsolute as isAbsolute6, join as join11 } from "node:path";
|
|
1971
2083
|
|
|
1972
2084
|
// src/agent-installation/workbuddy-managed-package.ts
|
|
1973
2085
|
var WORKBUDDY_MANAGED_VERSION = "2.146.0";
|
|
@@ -2020,7 +2132,7 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
2020
2132
|
resolveManagedAgent = async (stateDirectory, _platform, signal) => {
|
|
2021
2133
|
signal.throwIfAborted();
|
|
2022
2134
|
const executable = await validateManagedNpmPackage(
|
|
2023
|
-
|
|
2135
|
+
join11(stateDirectory, "agents", this.id, WORKBUDDY_MANAGED_VERSION),
|
|
2024
2136
|
WORKBUDDY_MANAGED_PACKAGE
|
|
2025
2137
|
);
|
|
2026
2138
|
signal.throwIfAborted();
|
|
@@ -2031,10 +2143,10 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
2031
2143
|
if ((context.platform ?? process.platform) !== "darwin") {
|
|
2032
2144
|
return [];
|
|
2033
2145
|
}
|
|
2034
|
-
const requestedPaths = [
|
|
2146
|
+
const requestedPaths = [join11("/Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH)];
|
|
2035
2147
|
const homeDirectory = context.environment["HOME"];
|
|
2036
|
-
if (homeDirectory !== void 0 &&
|
|
2037
|
-
requestedPaths.unshift(
|
|
2148
|
+
if (homeDirectory !== void 0 && isAbsolute6(homeDirectory)) {
|
|
2149
|
+
requestedPaths.unshift(join11(homeDirectory, "Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH));
|
|
2038
2150
|
}
|
|
2039
2151
|
const executables = [];
|
|
2040
2152
|
for (const requestedPath of requestedPaths) {
|
|
@@ -2060,12 +2172,15 @@ function supportedLocalAgentSpecifications() {
|
|
|
2060
2172
|
return Object.freeze([
|
|
2061
2173
|
new CodexAgentSpecification(),
|
|
2062
2174
|
new ClaudeCodeAgentSpecification(),
|
|
2175
|
+
new CopilotCliAgentSpecification(),
|
|
2063
2176
|
new PiAgentSpecification(),
|
|
2064
2177
|
new DeepSeekHarnessAgentSpecification(),
|
|
2178
|
+
new HermesAgentSpecification(),
|
|
2065
2179
|
new OpenCodeAgentSpecification(),
|
|
2066
2180
|
new CursorCliAgentSpecification(),
|
|
2067
2181
|
new GrokBuildAgentSpecification(),
|
|
2068
|
-
new WorkBuddyAgentSpecification()
|
|
2182
|
+
new WorkBuddyAgentSpecification(),
|
|
2183
|
+
new GeminiCliAgentSpecification()
|
|
2069
2184
|
]);
|
|
2070
2185
|
}
|
|
2071
2186
|
|
|
@@ -2105,11 +2220,173 @@ var createAcpClient = (handler) => client({ name: "mobius" }).onRequest(
|
|
|
2105
2220
|
outcome: { outcome: "cancelled" }
|
|
2106
2221
|
})).onNotification("cursor/update_todos", discardExtensionParams, async () => Promise.resolve()).onNotification("cursor/task", discardExtensionParams, async () => Promise.resolve()).onNotification("cursor/generate_image", discardExtensionParams, async () => Promise.resolve());
|
|
2107
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
|
+
|
|
2108
2385
|
// src/agent-catalog/executable-discovery.ts
|
|
2109
|
-
import { isAbsolute as
|
|
2386
|
+
import { isAbsolute as isAbsolute7, join as join13 } from "node:path";
|
|
2110
2387
|
|
|
2111
2388
|
// src/agent-installation/managed-adapter-installer.ts
|
|
2112
|
-
import { join as
|
|
2389
|
+
import { join as join12 } from "node:path";
|
|
2113
2390
|
var ManagedAdapterInstallError = class extends Error {
|
|
2114
2391
|
code;
|
|
2115
2392
|
constructor(code, message, options = {}) {
|
|
@@ -2166,7 +2443,7 @@ var ManagedAdapterInstaller = class {
|
|
|
2166
2443
|
this.#stateDirectory = options.stateDirectory;
|
|
2167
2444
|
}
|
|
2168
2445
|
install = async (specification, signal) => {
|
|
2169
|
-
const root =
|
|
2446
|
+
const root = join12(this.#stateDirectory, "adapters", specification.id, specification.adapterVersion);
|
|
2170
2447
|
try {
|
|
2171
2448
|
return await this.#npmInstaller.install(
|
|
2172
2449
|
root,
|
|
@@ -2200,7 +2477,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
|
|
|
2200
2477
|
let managed;
|
|
2201
2478
|
try {
|
|
2202
2479
|
managed = await validateManagedAdapter(
|
|
2203
|
-
|
|
2480
|
+
join13(readStateDirectory(context.environment), "adapters", specification.id, specification.adapterVersion),
|
|
2204
2481
|
specification
|
|
2205
2482
|
);
|
|
2206
2483
|
} catch {
|
|
@@ -2211,7 +2488,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
|
|
|
2211
2488
|
async function resolveSpecificationExecutables(executableName, overrideVariable, resolveInstalled, resolveManaged, context) {
|
|
2212
2489
|
const override = context.environment[overrideVariable];
|
|
2213
2490
|
if (override !== void 0) {
|
|
2214
|
-
if (override.length === 0 || !
|
|
2491
|
+
if (override.length === 0 || !isAbsolute7(override)) {
|
|
2215
2492
|
return [];
|
|
2216
2493
|
}
|
|
2217
2494
|
const executable = await resolveExecutablePath(override, context.platform);
|
|
@@ -2265,10 +2542,7 @@ async function resolveAdapterExecutable(specification, context) {
|
|
|
2265
2542
|
const executables = await resolveAdapterExecutables(specification, context);
|
|
2266
2543
|
return executables[0] ?? null;
|
|
2267
2544
|
}
|
|
2268
|
-
function
|
|
2269
|
-
return output2.trim().split(/\r?\n/, 1)[0]?.trim().slice(0, 128) ?? "";
|
|
2270
|
-
}
|
|
2271
|
-
async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal, timeoutMilliseconds) {
|
|
2545
|
+
async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal, timeoutMilliseconds, normalize4 = normalizeVersionOutput) {
|
|
2272
2546
|
const result = await runBoundedProcess({
|
|
2273
2547
|
arguments: arguments_,
|
|
2274
2548
|
command: executable.path,
|
|
@@ -2277,7 +2551,7 @@ async function probeVersion(executable, arguments_, environment, defaultWorkspac
|
|
|
2277
2551
|
signal,
|
|
2278
2552
|
timeoutMilliseconds
|
|
2279
2553
|
});
|
|
2280
|
-
const version2 =
|
|
2554
|
+
const version2 = normalize4(result.stdout || result.stderr);
|
|
2281
2555
|
if (version2.length === 0) {
|
|
2282
2556
|
throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version");
|
|
2283
2557
|
}
|
|
@@ -2301,7 +2575,8 @@ async function findVerifiedAgentExecutable(specification, context) {
|
|
|
2301
2575
|
context.environment,
|
|
2302
2576
|
context.defaultWorkspace,
|
|
2303
2577
|
context.signal,
|
|
2304
|
-
specification.versionProbeTimeoutMilliseconds
|
|
2578
|
+
specification.versionProbeTimeoutMilliseconds,
|
|
2579
|
+
specification.normalizeAgentVersion
|
|
2305
2580
|
);
|
|
2306
2581
|
return new VerifiedAgentExecutable(executable, version2);
|
|
2307
2582
|
} catch {
|
|
@@ -2313,168 +2588,6 @@ async function findVerifiedAgentExecutable(specification, context) {
|
|
|
2313
2588
|
return null;
|
|
2314
2589
|
}
|
|
2315
2590
|
|
|
2316
|
-
// src/agent-catalog/acp-readiness-probe.ts
|
|
2317
|
-
var ACP_OUTPUT_LIMIT_BYTES = 1024 * 1024;
|
|
2318
|
-
var VerifiedAcpReadiness = class {
|
|
2319
|
-
adapterVersion;
|
|
2320
|
-
capabilities;
|
|
2321
|
-
constructor(adapterVersion, capabilities) {
|
|
2322
|
-
this.adapterVersion = adapterVersion;
|
|
2323
|
-
this.capabilities = capabilities;
|
|
2324
|
-
}
|
|
2325
|
-
};
|
|
2326
|
-
var DiscoveryAcpHandler = class {
|
|
2327
|
-
onElicitation = (_request, _signal) => Promise.reject(new Error("ACP probe does not accept elicitations"));
|
|
2328
|
-
onElicitationComplete = (_notification) => Promise.resolve();
|
|
2329
|
-
onPermission = (_request, _signal) => Promise.reject(new Error("ACP probe does not grant permissions"));
|
|
2330
|
-
onUpdate = (_notification) => Promise.resolve();
|
|
2331
|
-
};
|
|
2332
|
-
function readableAcpStream(input2) {
|
|
2333
|
-
let byteLength = 0;
|
|
2334
|
-
let open5 = true;
|
|
2335
|
-
return new ReadableStream({
|
|
2336
|
-
start(controller) {
|
|
2337
|
-
input2.on("data", (chunk) => {
|
|
2338
|
-
if (!open5) {
|
|
2339
|
-
return;
|
|
2340
|
-
}
|
|
2341
|
-
if (!(chunk instanceof Uint8Array)) {
|
|
2342
|
-
open5 = false;
|
|
2343
|
-
controller.error(new Error("ACP adapter produced invalid output"));
|
|
2344
|
-
return;
|
|
2345
|
-
}
|
|
2346
|
-
byteLength += chunk.byteLength;
|
|
2347
|
-
if (byteLength > ACP_OUTPUT_LIMIT_BYTES) {
|
|
2348
|
-
open5 = false;
|
|
2349
|
-
controller.error(new Error("ACP adapter output limit exceeded"));
|
|
2350
|
-
return;
|
|
2351
|
-
}
|
|
2352
|
-
controller.enqueue(new Uint8Array(chunk));
|
|
2353
|
-
});
|
|
2354
|
-
input2.once("end", () => {
|
|
2355
|
-
if (open5) {
|
|
2356
|
-
open5 = false;
|
|
2357
|
-
controller.close();
|
|
2358
|
-
}
|
|
2359
|
-
});
|
|
2360
|
-
input2.once("error", (error61) => {
|
|
2361
|
-
if (open5) {
|
|
2362
|
-
open5 = false;
|
|
2363
|
-
controller.error(error61);
|
|
2364
|
-
}
|
|
2365
|
-
});
|
|
2366
|
-
},
|
|
2367
|
-
cancel() {
|
|
2368
|
-
open5 = false;
|
|
2369
|
-
}
|
|
2370
|
-
});
|
|
2371
|
-
}
|
|
2372
|
-
function writableAcpStream(output2) {
|
|
2373
|
-
return new WritableStream({
|
|
2374
|
-
write(chunk) {
|
|
2375
|
-
return new Promise((resolveWrite, rejectWrite) => {
|
|
2376
|
-
output2.write(chunk, (error61) => {
|
|
2377
|
-
if (error61) {
|
|
2378
|
-
rejectWrite(error61);
|
|
2379
|
-
return;
|
|
2380
|
-
}
|
|
2381
|
-
resolveWrite();
|
|
2382
|
-
});
|
|
2383
|
-
});
|
|
2384
|
-
}
|
|
2385
|
-
});
|
|
2386
|
-
}
|
|
2387
|
-
async function probeAcpReadiness(specification, agent, environment, defaultWorkspace, signal) {
|
|
2388
|
-
signal.throwIfAborted();
|
|
2389
|
-
const controller = new AbortController();
|
|
2390
|
-
let timedOut = false;
|
|
2391
|
-
const timeout = setTimeout(() => {
|
|
2392
|
-
timedOut = true;
|
|
2393
|
-
controller.abort(new Error("ACP probe timed out"));
|
|
2394
|
-
}, specification.acpProbeTimeoutMilliseconds);
|
|
2395
|
-
const abort = () => controller.abort(signal.reason);
|
|
2396
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
2397
|
-
if (signal.aborted) {
|
|
2398
|
-
abort();
|
|
2399
|
-
}
|
|
2400
|
-
const child = spawn2(agent.adapterPath, [...agent.arguments], {
|
|
2401
|
-
cwd: defaultWorkspace,
|
|
2402
|
-
detached: process.platform !== "win32",
|
|
2403
|
-
env: { ...environment, ...agent.environment },
|
|
2404
|
-
shell: false,
|
|
2405
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
2406
|
-
});
|
|
2407
|
-
const processExit = new Promise((_resolve, reject) => {
|
|
2408
|
-
const rejectExit = () => reject(new Error("ACP adapter exited during initialization"));
|
|
2409
|
-
child.once("error", reject);
|
|
2410
|
-
child.once("exit", rejectExit);
|
|
2411
|
-
if (child.exitCode !== null || child.signalCode !== null) {
|
|
2412
|
-
rejectExit();
|
|
2413
|
-
}
|
|
2414
|
-
});
|
|
2415
|
-
const stdin = child.stdin;
|
|
2416
|
-
const stdout = child.stdout;
|
|
2417
|
-
const stderr = child.stderr;
|
|
2418
|
-
if (stdin === null || stdout === null || stderr === null) {
|
|
2419
|
-
await stopProcessTree(child);
|
|
2420
|
-
throw new AgentProbeError("acp_incompatible", "ACP adapter streams are unavailable");
|
|
2421
|
-
}
|
|
2422
|
-
let stderrBytes = 0;
|
|
2423
|
-
const consumeStderr = (chunk) => {
|
|
2424
|
-
stderrBytes += chunk.byteLength;
|
|
2425
|
-
if (stderrBytes > ACP_OUTPUT_LIMIT_BYTES) {
|
|
2426
|
-
controller.abort(new Error("ACP adapter output limit exceeded"));
|
|
2427
|
-
}
|
|
2428
|
-
};
|
|
2429
|
-
stderr.on("data", consumeStderr);
|
|
2430
|
-
const connection = createAcpClient(new DiscoveryAcpHandler()).connect(
|
|
2431
|
-
ndJsonStream(writableAcpStream(stdin), readableAcpStream(stdout))
|
|
2432
|
-
);
|
|
2433
|
-
try {
|
|
2434
|
-
const initialized = await Promise.race([
|
|
2435
|
-
connection.agent.request(
|
|
2436
|
-
methods4.agent.initialize,
|
|
2437
|
-
{
|
|
2438
|
-
clientCapabilities: {},
|
|
2439
|
-
clientInfo: { name: "mobius", version: "0.0.3" },
|
|
2440
|
-
protocolVersion: PROTOCOL_VERSION
|
|
2441
|
-
},
|
|
2442
|
-
{ cancellationSignal: controller.signal }
|
|
2443
|
-
),
|
|
2444
|
-
processExit
|
|
2445
|
-
]);
|
|
2446
|
-
if (initialized.protocolVersion !== PROTOCOL_VERSION) {
|
|
2447
|
-
throw new AgentProbeError("acp_incompatible", "ACP adapter selected an unsupported protocol version");
|
|
2448
|
-
}
|
|
2449
|
-
await specification.verifyAcp(connection, initialized, defaultWorkspace, controller.signal);
|
|
2450
|
-
return new VerifiedAcpReadiness(
|
|
2451
|
-
normalizedVersion(initialized.agentInfo?.version ?? ""),
|
|
2452
|
-
normalizeAcpCapabilities(initialized)
|
|
2453
|
-
);
|
|
2454
|
-
} catch (error61) {
|
|
2455
|
-
if (signal.aborted) {
|
|
2456
|
-
signal.throwIfAborted();
|
|
2457
|
-
}
|
|
2458
|
-
if (timedOut) {
|
|
2459
|
-
throw new AgentProbeError("adapter_probe_timeout", "ACP adapter probe timed out", { cause: error61 });
|
|
2460
|
-
}
|
|
2461
|
-
if (error61 instanceof AgentProbeError) {
|
|
2462
|
-
throw error61;
|
|
2463
|
-
}
|
|
2464
|
-
if (error61 instanceof RequestError && error61.code === -32e3 && specification.authenticationCommand().length > 0) {
|
|
2465
|
-
throw new AgentProbeError("authentication_required", "Agent authentication is required", { cause: error61 });
|
|
2466
|
-
}
|
|
2467
|
-
throw new AgentProbeError("acp_incompatible", "ACP adapter initialization failed", { cause: error61 });
|
|
2468
|
-
} finally {
|
|
2469
|
-
clearTimeout(timeout);
|
|
2470
|
-
signal.removeEventListener("abort", abort);
|
|
2471
|
-
connection.close();
|
|
2472
|
-
stdin.end();
|
|
2473
|
-
stderr.removeListener("data", consumeStderr);
|
|
2474
|
-
await stopProcessTree(child);
|
|
2475
|
-
}
|
|
2476
|
-
}
|
|
2477
|
-
|
|
2478
2591
|
// src/agent-catalog/discover-agent.ts
|
|
2479
2592
|
function agentProbeFailure(specification, error61) {
|
|
2480
2593
|
if (error61 instanceof AgentProbeError) {
|
|
@@ -2518,7 +2631,8 @@ async function discoverAgent(specification, context) {
|
|
|
2518
2631
|
context.environment,
|
|
2519
2632
|
context.defaultWorkspace,
|
|
2520
2633
|
context.signal,
|
|
2521
|
-
specification.versionProbeTimeoutMilliseconds
|
|
2634
|
+
specification.versionProbeTimeoutMilliseconds,
|
|
2635
|
+
specification.normalizeAgentVersion
|
|
2522
2636
|
);
|
|
2523
2637
|
} catch (error61) {
|
|
2524
2638
|
if (context.signal.aborted) {
|
|
@@ -2554,7 +2668,8 @@ async function discoverAgent(specification, context) {
|
|
|
2554
2668
|
},
|
|
2555
2669
|
context.defaultWorkspace,
|
|
2556
2670
|
context.signal,
|
|
2557
|
-
specification.versionProbeTimeoutMilliseconds
|
|
2671
|
+
specification.versionProbeTimeoutMilliseconds,
|
|
2672
|
+
specification.normalizeAdapterVersion
|
|
2558
2673
|
);
|
|
2559
2674
|
}
|
|
2560
2675
|
} catch (error61) {
|
|
@@ -2787,7 +2902,7 @@ async function executeBotMessageCommand(arguments_, environment, signal) {
|
|
|
2787
2902
|
}
|
|
2788
2903
|
|
|
2789
2904
|
// src/config.ts
|
|
2790
|
-
import { join as
|
|
2905
|
+
import { join as join14 } from "node:path";
|
|
2791
2906
|
|
|
2792
2907
|
// ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/external.js
|
|
2793
2908
|
var external_exports = {};
|
|
@@ -18841,8 +18956,8 @@ function rewriteKeyNames(ctx) {
|
|
|
18841
18956
|
bySchema.set(entry.schema, entry);
|
|
18842
18957
|
}
|
|
18843
18958
|
const rewrites = /* @__PURE__ */ new Map();
|
|
18844
|
-
for (const
|
|
18845
|
-
const seen = ctx.seen.get(
|
|
18959
|
+
for (const record3 of pendingRecords.get(ctx) ?? []) {
|
|
18960
|
+
const seen = ctx.seen.get(record3);
|
|
18846
18961
|
const names = (seen?.def ?? seen?.schema)?.propertyNames;
|
|
18847
18962
|
if (!names || names === true || rewrites.has(names))
|
|
18848
18963
|
continue;
|
|
@@ -21657,6 +21772,28 @@ function date4(params) {
|
|
|
21657
21772
|
|
|
21658
21773
|
// ../protocol/src/prompt-usage.ts
|
|
21659
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
|
+
}
|
|
21660
21797
|
var promptUsageSchema = external_exports.object({
|
|
21661
21798
|
cachedReadTokens: TOKEN_COUNT.nullish(),
|
|
21662
21799
|
cachedWriteTokens: TOKEN_COUNT.nullish(),
|
|
@@ -21665,14 +21802,17 @@ var promptUsageSchema = external_exports.object({
|
|
|
21665
21802
|
thoughtTokens: TOKEN_COUNT.nullish(),
|
|
21666
21803
|
totalTokens: TOKEN_COUNT
|
|
21667
21804
|
}).readonly();
|
|
21668
|
-
var quotaTokenCountSchema = external_exports.
|
|
21669
|
-
|
|
21670
|
-
|
|
21671
|
-
|
|
21672
|
-
|
|
21673
|
-
|
|
21674
|
-
|
|
21675
|
-
|
|
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
|
+
);
|
|
21676
21816
|
var promptMetadataSchema = external_exports.object({
|
|
21677
21817
|
quota: external_exports.object({
|
|
21678
21818
|
model_usage: external_exports.array(
|
|
@@ -21799,6 +21939,7 @@ var elicitationFieldSchema = external_exports.strictObject({
|
|
|
21799
21939
|
type: external_exports.enum(["boolean", "integer", "multiselect", "number", "select", "string"])
|
|
21800
21940
|
}).readonly();
|
|
21801
21941
|
var displayContentSchema = external_exports.strictObject({
|
|
21942
|
+
artifactId: external_exports.string().max(128).default(""),
|
|
21802
21943
|
data: external_exports.string().max(4e6),
|
|
21803
21944
|
mimeType: external_exports.string().max(255),
|
|
21804
21945
|
name: external_exports.string().max(500),
|
|
@@ -21811,6 +21952,7 @@ var displayContentSchema = external_exports.strictObject({
|
|
|
21811
21952
|
uri: external_exports.string().max(4096)
|
|
21812
21953
|
}).readonly();
|
|
21813
21954
|
var recordedDisplayContentSchema = external_exports.strictObject({
|
|
21955
|
+
artifactId: external_exports.string().max(128).default(""),
|
|
21814
21956
|
data: external_exports.string().max(4e6),
|
|
21815
21957
|
mimeType: external_exports.string().max(255),
|
|
21816
21958
|
name: external_exports.string().max(500),
|
|
@@ -23298,7 +23440,7 @@ var decodeSessionEventRejection = (encoded) => decode5(encoded, eventRejectionSc
|
|
|
23298
23440
|
// src/config.ts
|
|
23299
23441
|
function loadDefaultWorkspace(environment = process.env) {
|
|
23300
23442
|
const { MOBIUS_DEFAULT_WORKSPACE: configuredWorkspace } = environment;
|
|
23301
|
-
return configuredWorkspace ??
|
|
23443
|
+
return configuredWorkspace ?? join14(readStateDirectory(environment), "workspace");
|
|
23302
23444
|
}
|
|
23303
23445
|
function createDaemonConfig(connection, agents = [], installableAgents = []) {
|
|
23304
23446
|
return {
|
|
@@ -23317,7 +23459,7 @@ function createDaemonConfig(connection, agents = [], installableAgents = []) {
|
|
|
23317
23459
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23318
23460
|
import { mkdir as mkdir3, open as open4, realpath as realpath6, rename as rename3, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
|
|
23319
23461
|
import { hostname as hostname3 } from "node:os";
|
|
23320
|
-
import { basename, join as
|
|
23462
|
+
import { basename, join as join15, resolve as resolve3 } from "node:path";
|
|
23321
23463
|
import { fetch as fetch2 } from "undici";
|
|
23322
23464
|
var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
|
|
23323
23465
|
var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
|
|
@@ -23517,10 +23659,10 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
|
|
|
23517
23659
|
return options.pairingId.length > 0 ? decodePairingResponse(value, "runtimeCredential", REDEEM_RESPONSE_KEYS) : decodePairingResponse(value, "daemonToken", CLAIM_RESPONSE_KEYS);
|
|
23518
23660
|
}
|
|
23519
23661
|
async function persistConnection(channelId, relayOrigin, runtimeCredential2, defaultWorkspace, environment) {
|
|
23520
|
-
const connectionsDirectory =
|
|
23662
|
+
const connectionsDirectory = join15(readStateDirectory(environment), "connections");
|
|
23521
23663
|
await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
|
|
23522
|
-
const connectionPath =
|
|
23523
|
-
const temporaryPath =
|
|
23664
|
+
const connectionPath = join15(connectionsDirectory, `${channelId}.json`);
|
|
23665
|
+
const temporaryPath = join15(connectionsDirectory, `.${channelId}.${randomUUID2()}.tmp`);
|
|
23524
23666
|
await writeFile2(
|
|
23525
23667
|
temporaryPath,
|
|
23526
23668
|
`${JSON.stringify(
|
|
@@ -23558,7 +23700,7 @@ function decodeSavedConnection(value, expectedChannelId) {
|
|
|
23558
23700
|
};
|
|
23559
23701
|
}
|
|
23560
23702
|
async function readSavedConnection(channelId, environment) {
|
|
23561
|
-
const connectionPath =
|
|
23703
|
+
const connectionPath = join15(readStateDirectory(environment), "connections", `${channelId}.json`);
|
|
23562
23704
|
let encoded = "";
|
|
23563
23705
|
const handle = await open4(connectionPath, "r");
|
|
23564
23706
|
try {
|
|
@@ -23594,7 +23736,7 @@ function buildPairedDaemon(connection, connectionPath, inventory, environment) {
|
|
|
23594
23736
|
const relayUrl = mobiusApiUrl(connection.relayOrigin, "/v1/runtimes/connect");
|
|
23595
23737
|
relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
23596
23738
|
relayUrl.searchParams.set("token", connection.runtimeCredential);
|
|
23597
|
-
const auditDatabasePath =
|
|
23739
|
+
const auditDatabasePath = join15(readStateDirectory(environment), "audit", `${connection.channelId}.sqlite`);
|
|
23598
23740
|
return {
|
|
23599
23741
|
channelUrl: new URL(`/channels/${encodeURIComponent(connection.channelId)}`, connection.relayOrigin).toString(),
|
|
23600
23742
|
config: createDaemonConfig(
|
|
@@ -23644,7 +23786,7 @@ async function pairLocalMachine(arguments_, signal = new AbortController().signa
|
|
|
23644
23786
|
}
|
|
23645
23787
|
async function resumeMobiusRuntime(channelId, signal, environment = process.env) {
|
|
23646
23788
|
const normalizedChannelId = validatePairingId(channelId);
|
|
23647
|
-
const connectionPath =
|
|
23789
|
+
const connectionPath = join15(readStateDirectory(environment), "connections", `${normalizedChannelId}.json`);
|
|
23648
23790
|
const connection = await readSavedConnection(normalizedChannelId, environment);
|
|
23649
23791
|
const inventory = await discoverLocalAgentInventory({
|
|
23650
23792
|
defaultWorkspace: connection.defaultWorkspace,
|
|
@@ -23681,7 +23823,7 @@ var AuditStore = class {
|
|
|
23681
23823
|
this.database.exec("ALTER TABLE audit_events ADD COLUMN details_json TEXT NOT NULL DEFAULT '{}'");
|
|
23682
23824
|
}
|
|
23683
23825
|
}
|
|
23684
|
-
record(
|
|
23826
|
+
record(record3) {
|
|
23685
23827
|
this.database.prepare(
|
|
23686
23828
|
`
|
|
23687
23829
|
INSERT INTO audit_events (
|
|
@@ -23694,10 +23836,10 @@ var AuditStore = class {
|
|
|
23694
23836
|
`
|
|
23695
23837
|
).run(
|
|
23696
23838
|
(/* @__PURE__ */ new Date()).toISOString(),
|
|
23697
|
-
|
|
23698
|
-
|
|
23699
|
-
|
|
23700
|
-
JSON.stringify(
|
|
23839
|
+
record3.event,
|
|
23840
|
+
record3.commandId,
|
|
23841
|
+
record3.sessionId,
|
|
23842
|
+
JSON.stringify(record3.details ?? {})
|
|
23701
23843
|
);
|
|
23702
23844
|
}
|
|
23703
23845
|
close() {
|
|
@@ -23707,9 +23849,9 @@ var AuditStore = class {
|
|
|
23707
23849
|
|
|
23708
23850
|
// src/run-daemon.ts
|
|
23709
23851
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
23710
|
-
import { basename as
|
|
23852
|
+
import { basename as basename5, join as join17 } from "node:path";
|
|
23711
23853
|
import { styleText } from "node:util";
|
|
23712
|
-
import { fetch as
|
|
23854
|
+
import { fetch as fetch7, WebSocket as WebSocket2 } from "undici";
|
|
23713
23855
|
|
|
23714
23856
|
// src/acp/session-manager.ts
|
|
23715
23857
|
import { spawn as spawn3 } from "node:child_process";
|
|
@@ -23720,6 +23862,212 @@ import {
|
|
|
23720
23862
|
RequestError as RequestError2
|
|
23721
23863
|
} from "@agentclientprotocol/sdk";
|
|
23722
23864
|
|
|
23865
|
+
// src/authorization/local-raster.ts
|
|
23866
|
+
import { readFile, realpath as realpath7, stat as stat6 } from "node:fs/promises";
|
|
23867
|
+
import { basename as basename2, isAbsolute as isAbsolute8, normalize as normalize2, relative as relative4, sep as sep4 } from "node:path";
|
|
23868
|
+
import { fileURLToPath } from "node:url";
|
|
23869
|
+
var MAX_LOCAL_RASTER_BYTES = 3e6;
|
|
23870
|
+
var PNG_SIGNATURE = Uint8Array.of(137, 80, 78, 71);
|
|
23871
|
+
var JPEG_SIGNATURE = Uint8Array.of(255, 216, 255);
|
|
23872
|
+
var GIF87_SIGNATURE = new TextEncoder().encode("GIF87a");
|
|
23873
|
+
var GIF89_SIGNATURE = new TextEncoder().encode("GIF89a");
|
|
23874
|
+
var RIFF_SIGNATURE = new TextEncoder().encode("RIFF");
|
|
23875
|
+
var WEBP_SIGNATURE = new TextEncoder().encode("WEBP");
|
|
23876
|
+
var LocalRasterImage = class {
|
|
23877
|
+
bytes;
|
|
23878
|
+
mimeType;
|
|
23879
|
+
name;
|
|
23880
|
+
constructor(name, mimeType, bytes) {
|
|
23881
|
+
this.bytes = bytes;
|
|
23882
|
+
this.mimeType = mimeType;
|
|
23883
|
+
this.name = name;
|
|
23884
|
+
}
|
|
23885
|
+
base64 = () => Buffer.from(this.bytes).toString("base64");
|
|
23886
|
+
};
|
|
23887
|
+
function startsWith(bytes, signature, offset = 0) {
|
|
23888
|
+
if (bytes.byteLength < offset + signature.byteLength) {
|
|
23889
|
+
return false;
|
|
23890
|
+
}
|
|
23891
|
+
return signature.every((value, index) => bytes[offset + index] === value);
|
|
23892
|
+
}
|
|
23893
|
+
function sniffRasterMime(bytes) {
|
|
23894
|
+
if (startsWith(bytes, PNG_SIGNATURE)) {
|
|
23895
|
+
return "image/png";
|
|
23896
|
+
}
|
|
23897
|
+
if (startsWith(bytes, JPEG_SIGNATURE)) {
|
|
23898
|
+
return "image/jpeg";
|
|
23899
|
+
}
|
|
23900
|
+
if (startsWith(bytes, GIF87_SIGNATURE) || startsWith(bytes, GIF89_SIGNATURE)) {
|
|
23901
|
+
return "image/gif";
|
|
23902
|
+
}
|
|
23903
|
+
if (startsWith(bytes, RIFF_SIGNATURE) && startsWith(bytes, WEBP_SIGNATURE, 8)) {
|
|
23904
|
+
return "image/webp";
|
|
23905
|
+
}
|
|
23906
|
+
return null;
|
|
23907
|
+
}
|
|
23908
|
+
function isInsideRoot(root, target) {
|
|
23909
|
+
const relation = relative4(root, target);
|
|
23910
|
+
return relation !== ".." && !relation.startsWith(`..${sep4}`) && !isAbsolute8(relation);
|
|
23911
|
+
}
|
|
23912
|
+
async function resolveCanonicalPath(requested, signal) {
|
|
23913
|
+
signal.throwIfAborted();
|
|
23914
|
+
if (!isAbsolute8(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
|
|
23915
|
+
return null;
|
|
23916
|
+
}
|
|
23917
|
+
try {
|
|
23918
|
+
const target = await realpath7(requested);
|
|
23919
|
+
signal.throwIfAborted();
|
|
23920
|
+
if (!isAbsolute8(target) || normalize2(target) !== target) {
|
|
23921
|
+
return null;
|
|
23922
|
+
}
|
|
23923
|
+
return target;
|
|
23924
|
+
} catch (cause) {
|
|
23925
|
+
signal.throwIfAborted();
|
|
23926
|
+
if (cause instanceof Error && cause.name === "AbortError") {
|
|
23927
|
+
throw cause;
|
|
23928
|
+
}
|
|
23929
|
+
return null;
|
|
23930
|
+
}
|
|
23931
|
+
}
|
|
23932
|
+
function parseLocalImageUri(uri) {
|
|
23933
|
+
const trimmed = uri.trim();
|
|
23934
|
+
if (trimmed.length === 0 || trimmed.length > 2048 || trimmed.includes("\0")) {
|
|
23935
|
+
return null;
|
|
23936
|
+
}
|
|
23937
|
+
if (trimmed.startsWith("data:")) {
|
|
23938
|
+
return null;
|
|
23939
|
+
}
|
|
23940
|
+
if (trimmed.startsWith("file:")) {
|
|
23941
|
+
try {
|
|
23942
|
+
const url2 = new URL(trimmed);
|
|
23943
|
+
if (url2.protocol !== "file:" || url2.host.length > 0) {
|
|
23944
|
+
return null;
|
|
23945
|
+
}
|
|
23946
|
+
return fileURLToPath(url2);
|
|
23947
|
+
} catch {
|
|
23948
|
+
return null;
|
|
23949
|
+
}
|
|
23950
|
+
}
|
|
23951
|
+
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)) {
|
|
23952
|
+
return null;
|
|
23953
|
+
}
|
|
23954
|
+
return trimmed;
|
|
23955
|
+
}
|
|
23956
|
+
async function readAuthorizedRaster(uri, roots, signal) {
|
|
23957
|
+
signal.throwIfAborted();
|
|
23958
|
+
const requested = parseLocalImageUri(uri);
|
|
23959
|
+
if (requested === null) {
|
|
23960
|
+
return null;
|
|
23961
|
+
}
|
|
23962
|
+
const target = await resolveCanonicalPath(requested, signal);
|
|
23963
|
+
if (target === null) {
|
|
23964
|
+
return null;
|
|
23965
|
+
}
|
|
23966
|
+
const targetMetadata = await stat6(target);
|
|
23967
|
+
signal.throwIfAborted();
|
|
23968
|
+
if (!targetMetadata.isFile() || targetMetadata.size < 1 || targetMetadata.size > MAX_LOCAL_RASTER_BYTES) {
|
|
23969
|
+
return null;
|
|
23970
|
+
}
|
|
23971
|
+
const authorizedRoots = [];
|
|
23972
|
+
for (const root of roots) {
|
|
23973
|
+
const directory = await resolveCanonicalPath(root, signal);
|
|
23974
|
+
if (directory === null) {
|
|
23975
|
+
continue;
|
|
23976
|
+
}
|
|
23977
|
+
const metadata = await stat6(directory);
|
|
23978
|
+
signal.throwIfAborted();
|
|
23979
|
+
if (metadata.isDirectory()) {
|
|
23980
|
+
authorizedRoots.push(directory);
|
|
23981
|
+
}
|
|
23982
|
+
}
|
|
23983
|
+
if (!authorizedRoots.some((root) => isInsideRoot(root, target))) {
|
|
23984
|
+
return null;
|
|
23985
|
+
}
|
|
23986
|
+
const bytes = new Uint8Array(await readFile(target));
|
|
23987
|
+
signal.throwIfAborted();
|
|
23988
|
+
if (bytes.byteLength < 1 || bytes.byteLength > MAX_LOCAL_RASTER_BYTES) {
|
|
23989
|
+
return null;
|
|
23990
|
+
}
|
|
23991
|
+
const mimeType = sniffRasterMime(bytes);
|
|
23992
|
+
if (mimeType === null) {
|
|
23993
|
+
return null;
|
|
23994
|
+
}
|
|
23995
|
+
return new LocalRasterImage(basename2(target) || "Image", mimeType, bytes);
|
|
23996
|
+
}
|
|
23997
|
+
|
|
23998
|
+
// src/native-sessions/history-images.ts
|
|
23999
|
+
var IMAGE_MARKER = /\[@image\]\(([^)\r\n]*)(?:\)|$)/g;
|
|
24000
|
+
async function embedLocalHistoryImages(history, roots, signal) {
|
|
24001
|
+
if (history.status !== "available") {
|
|
24002
|
+
return history;
|
|
24003
|
+
}
|
|
24004
|
+
const messages = [];
|
|
24005
|
+
let imageCharacters = 0;
|
|
24006
|
+
for (const message of history.messages) {
|
|
24007
|
+
signal.throwIfAborted();
|
|
24008
|
+
const resolved = await resolveMessageImages(message, roots, imageCharacters, signal);
|
|
24009
|
+
imageCharacters += (resolved.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
24010
|
+
messages.push(resolved);
|
|
24011
|
+
}
|
|
24012
|
+
return {
|
|
24013
|
+
...history,
|
|
24014
|
+
messages
|
|
24015
|
+
};
|
|
24016
|
+
}
|
|
24017
|
+
async function resolveMessageImages(message, roots, usedCharacters, signal) {
|
|
24018
|
+
const images = [...message.images ?? []];
|
|
24019
|
+
let imageCharacters = images.reduce((size, image) => size + image.data.length, 0);
|
|
24020
|
+
const text = await replaceImageMarkers(message.text, async (uri) => {
|
|
24021
|
+
if (images.length >= 8 || usedCharacters + imageCharacters >= SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
24022
|
+
return "[Image unavailable]";
|
|
24023
|
+
}
|
|
24024
|
+
const embedded = parseNativeHistoryText(`[@image](${uri})`).images[0];
|
|
24025
|
+
if (embedded !== void 0) {
|
|
24026
|
+
if (usedCharacters + imageCharacters + embedded.data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
24027
|
+
return "[Image unavailable]";
|
|
24028
|
+
}
|
|
24029
|
+
images.push(embedded);
|
|
24030
|
+
imageCharacters += embedded.data.length;
|
|
24031
|
+
return "";
|
|
24032
|
+
}
|
|
24033
|
+
const local = await readAuthorizedRaster(uri, roots, signal);
|
|
24034
|
+
if (local === null) {
|
|
24035
|
+
return "[Image unavailable]";
|
|
24036
|
+
}
|
|
24037
|
+
const data = local.base64();
|
|
24038
|
+
if (usedCharacters + imageCharacters + data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
24039
|
+
return "[Image unavailable]";
|
|
24040
|
+
}
|
|
24041
|
+
images.push({
|
|
24042
|
+
data,
|
|
24043
|
+
mimeType: local.mimeType,
|
|
24044
|
+
name: local.name
|
|
24045
|
+
});
|
|
24046
|
+
imageCharacters += data.length;
|
|
24047
|
+
return "";
|
|
24048
|
+
});
|
|
24049
|
+
return {
|
|
24050
|
+
...message,
|
|
24051
|
+
text,
|
|
24052
|
+
...images.length > 0 ? { images } : {}
|
|
24053
|
+
};
|
|
24054
|
+
}
|
|
24055
|
+
async function replaceImageMarkers(text, replace) {
|
|
24056
|
+
const matches = [...text.matchAll(IMAGE_MARKER)];
|
|
24057
|
+
if (matches.length === 0) {
|
|
24058
|
+
return text;
|
|
24059
|
+
}
|
|
24060
|
+
let cursor = 0;
|
|
24061
|
+
let rewritten = "";
|
|
24062
|
+
for (const match of matches) {
|
|
24063
|
+
const index = match.index ?? 0;
|
|
24064
|
+
rewritten += text.slice(cursor, index);
|
|
24065
|
+
rewritten += await replace(match[1] ?? "");
|
|
24066
|
+
cursor = index + match[0].length;
|
|
24067
|
+
}
|
|
24068
|
+
return `${rewritten}${text.slice(cursor)}`;
|
|
24069
|
+
}
|
|
24070
|
+
|
|
23723
24071
|
// src/acp/activity.ts
|
|
23724
24072
|
var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
|
|
23725
24073
|
function isRecord8(value) {
|
|
@@ -23817,6 +24165,7 @@ function readContentOutputDetail(content) {
|
|
|
23817
24165
|
function summarizeDisplayContent(content) {
|
|
23818
24166
|
return {
|
|
23819
24167
|
...content,
|
|
24168
|
+
artifactId: truncate(content.artifactId, 128),
|
|
23820
24169
|
data: truncate(content.data, AGENT_ACTIVITY_DETAIL_LIMIT),
|
|
23821
24170
|
mimeType: truncate(content.mimeType, 255),
|
|
23822
24171
|
name: truncate(content.name, 500),
|
|
@@ -23829,7 +24178,7 @@ function summarizeDisplayContent(content) {
|
|
|
23829
24178
|
};
|
|
23830
24179
|
}
|
|
23831
24180
|
function contentFitsRecordingEnvelope(content) {
|
|
23832
|
-
return content.data.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.mimeType.length <= 255 && content.name.length <= 500 && content.newText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.oldText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.path.length <= 2048 && content.terminalId.length <= 255 && content.text.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.uri.length <= 4096;
|
|
24181
|
+
return content.artifactId.length <= 128 && content.data.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.mimeType.length <= 255 && content.name.length <= 500 && content.newText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.oldText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.path.length <= 2048 && content.terminalId.length <= 255 && content.text.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.uri.length <= 4096;
|
|
23833
24182
|
}
|
|
23834
24183
|
function encodedByteLength(value) {
|
|
23835
24184
|
return new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
@@ -23855,6 +24204,7 @@ function recordedDetail(activity) {
|
|
|
23855
24204
|
}
|
|
23856
24205
|
function emptyDisplayContent(type) {
|
|
23857
24206
|
return {
|
|
24207
|
+
artifactId: "",
|
|
23858
24208
|
data: "",
|
|
23859
24209
|
mimeType: "",
|
|
23860
24210
|
name: "",
|
|
@@ -23867,6 +24217,16 @@ function emptyDisplayContent(type) {
|
|
|
23867
24217
|
uri: ""
|
|
23868
24218
|
};
|
|
23869
24219
|
}
|
|
24220
|
+
function imageDisplayContent(mimeType, name, data, artifactId = "", uri = "") {
|
|
24221
|
+
return {
|
|
24222
|
+
...emptyDisplayContent("image"),
|
|
24223
|
+
artifactId,
|
|
24224
|
+
data,
|
|
24225
|
+
mimeType,
|
|
24226
|
+
name,
|
|
24227
|
+
uri
|
|
24228
|
+
};
|
|
24229
|
+
}
|
|
23870
24230
|
function normalizeContentBlock(content) {
|
|
23871
24231
|
if (content.type === "text") {
|
|
23872
24232
|
return { ...emptyDisplayContent("text"), text: content.text };
|
|
@@ -24658,7 +25018,6 @@ var AcpHistoryReplay = class {
|
|
|
24658
25018
|
#messages = [];
|
|
24659
25019
|
#lastMessageId = null;
|
|
24660
25020
|
#characters = 0;
|
|
24661
|
-
#imageCharacters = 0;
|
|
24662
25021
|
#truncated = false;
|
|
24663
25022
|
record = (update) => {
|
|
24664
25023
|
if (update.sessionUpdate !== "user_message_chunk" && update.sessionUpdate !== "agent_message_chunk") {
|
|
@@ -24669,40 +25028,30 @@ var AcpHistoryReplay = class {
|
|
|
24669
25028
|
}
|
|
24670
25029
|
const role = update.sessionUpdate === "user_message_chunk" ? "user" : "assistant";
|
|
24671
25030
|
const content = update.content;
|
|
24672
|
-
const
|
|
24673
|
-
|
|
24674
|
-
);
|
|
24675
|
-
const text = parsed.text;
|
|
24676
|
-
if (text.length === 0 && parsed.images.length === 0) {
|
|
25031
|
+
const text = content.type === "text" ? content.text : content.type === "image" ? content.data.length > 0 ? `[@image](data:${content.mimeType};base64,${content.data})` : content.uri != null && content.uri.length > 0 ? `[@image](${content.uri})` : "[image attachment]" : `[${content.type} attachment]`;
|
|
25032
|
+
if (text.length === 0) {
|
|
24677
25033
|
return;
|
|
24678
25034
|
}
|
|
24679
25035
|
const previous = this.#messages.at(-1);
|
|
24680
25036
|
const id = update.messageId ?? null;
|
|
24681
25037
|
const continuation = previous?.role === role && id === this.#lastMessageId;
|
|
24682
25038
|
const combined = continuation ? `${previous.text}${text}` : text;
|
|
24683
|
-
const allImages = continuation ? [...previous.images ?? [], ...parsed.images] : parsed.images;
|
|
24684
|
-
const images = allImages.slice(0, 8);
|
|
24685
|
-
this.#truncated ||= images.length < allImages.length;
|
|
24686
25039
|
if (continuation) {
|
|
24687
25040
|
this.#messages.pop();
|
|
24688
25041
|
this.#characters -= previous.text.length;
|
|
24689
|
-
this.#imageCharacters -= (previous.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
24690
25042
|
}
|
|
24691
25043
|
const bounded = combined.slice(-SESSION_HISTORY_CHARACTER_LIMIT);
|
|
24692
25044
|
this.#truncated ||= bounded.length < combined.length;
|
|
24693
25045
|
this.#messages.push({
|
|
24694
25046
|
role,
|
|
24695
|
-
text: bounded
|
|
24696
|
-
...images.length > 0 ? { images } : {}
|
|
25047
|
+
text: bounded
|
|
24697
25048
|
});
|
|
24698
25049
|
this.#characters += bounded.length;
|
|
24699
|
-
this.#imageCharacters += images.reduce((size, image) => size + image.data.length, 0);
|
|
24700
25050
|
this.#lastMessageId = id;
|
|
24701
|
-
while (this.#messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || this.#characters > SESSION_HISTORY_CHARACTER_LIMIT
|
|
25051
|
+
while (this.#messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || this.#characters > SESSION_HISTORY_CHARACTER_LIMIT) {
|
|
24702
25052
|
const removed = this.#messages.shift();
|
|
24703
25053
|
if (removed !== void 0) {
|
|
24704
25054
|
this.#characters -= removed.text.length;
|
|
24705
|
-
this.#imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
24706
25055
|
}
|
|
24707
25056
|
this.#truncated = true;
|
|
24708
25057
|
}
|
|
@@ -24925,6 +25274,10 @@ var MAX_PRE_SESSION_UPDATES = 100;
|
|
|
24925
25274
|
var MAX_PRE_SESSION_UPDATE_BYTES = 1024 * 1024;
|
|
24926
25275
|
var SESSION_CONTROL_COMMAND_ID = "session-control";
|
|
24927
25276
|
var NullAcpSessionObserver = class {
|
|
25277
|
+
importLocalImage = (_sessionId, _image, signal) => {
|
|
25278
|
+
signal.throwIfAborted();
|
|
25279
|
+
return Promise.resolve("");
|
|
25280
|
+
};
|
|
24928
25281
|
onCommands = () => Promise.resolve();
|
|
24929
25282
|
onConfig = () => Promise.resolve();
|
|
24930
25283
|
onContent = () => Promise.resolve();
|
|
@@ -25547,11 +25900,75 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25547
25900
|
);
|
|
25548
25901
|
await this.#updateTail;
|
|
25549
25902
|
signal.throwIfAborted();
|
|
25550
|
-
return
|
|
25903
|
+
return await embedLocalHistoryImages(
|
|
25904
|
+
history.snapshot(),
|
|
25905
|
+
[this.#cwd, ...this.#additionalDirectories],
|
|
25906
|
+
signal
|
|
25907
|
+
);
|
|
25551
25908
|
} finally {
|
|
25552
25909
|
this.#replay = { kind: "idle" };
|
|
25553
25910
|
}
|
|
25554
25911
|
};
|
|
25912
|
+
imageRoots = () => [this.#cwd, ...this.#additionalDirectories];
|
|
25913
|
+
emitAgentText = async (text, messageId) => {
|
|
25914
|
+
const signal = AbortSignal.timeout(2e4);
|
|
25915
|
+
const parts = text.split(/(\[@image\]\([^)\r\n]*(?:\)|$))/);
|
|
25916
|
+
let leftover = "";
|
|
25917
|
+
for (const part of parts) {
|
|
25918
|
+
const marker = /^\[@image\]\(([^)\r\n]*)(?:\)|$)/.exec(part);
|
|
25919
|
+
if (marker === null) {
|
|
25920
|
+
leftover += part;
|
|
25921
|
+
continue;
|
|
25922
|
+
}
|
|
25923
|
+
if (leftover.length > 0) {
|
|
25924
|
+
await this.#turn.onText(leftover, messageId);
|
|
25925
|
+
leftover = "";
|
|
25926
|
+
}
|
|
25927
|
+
const raster = await readAuthorizedRaster(marker[1] ?? "", this.imageRoots(), signal);
|
|
25928
|
+
if (raster === null) {
|
|
25929
|
+
leftover += "[Image unavailable]";
|
|
25930
|
+
continue;
|
|
25931
|
+
}
|
|
25932
|
+
await this.emitRaster(raster, messageId, signal);
|
|
25933
|
+
}
|
|
25934
|
+
if (leftover.length > 0) {
|
|
25935
|
+
await this.#turn.onText(leftover, messageId);
|
|
25936
|
+
}
|
|
25937
|
+
};
|
|
25938
|
+
emitAgentContent = async (content, messageId) => {
|
|
25939
|
+
if (content.type === "image" && content.data.length === 0 && content.uri.length > 0) {
|
|
25940
|
+
const signal = AbortSignal.timeout(2e4);
|
|
25941
|
+
const raster = await readAuthorizedRaster(content.uri, this.imageRoots(), signal);
|
|
25942
|
+
if (raster !== null) {
|
|
25943
|
+
await this.emitRaster(raster, messageId, signal);
|
|
25944
|
+
return;
|
|
25945
|
+
}
|
|
25946
|
+
}
|
|
25947
|
+
await this.#getObserver().onContent({
|
|
25948
|
+
commandId: this.#turn.commandId,
|
|
25949
|
+
content,
|
|
25950
|
+
contentId: `content-${crypto.randomUUID()}`,
|
|
25951
|
+
kind: AGENT_CONTENT_KIND,
|
|
25952
|
+
messageId,
|
|
25953
|
+
sessionId: this.#mobiusSessionId
|
|
25954
|
+
});
|
|
25955
|
+
};
|
|
25956
|
+
emitRaster = async (raster, messageId, signal) => {
|
|
25957
|
+
const artifactId = await this.#getObserver().importLocalImage(this.#mobiusSessionId, raster, signal);
|
|
25958
|
+
await this.#getObserver().onContent({
|
|
25959
|
+
commandId: this.#turn.commandId,
|
|
25960
|
+
content: imageDisplayContent(
|
|
25961
|
+
raster.mimeType,
|
|
25962
|
+
raster.name,
|
|
25963
|
+
artifactId.length > 0 ? "" : raster.base64(),
|
|
25964
|
+
artifactId
|
|
25965
|
+
),
|
|
25966
|
+
contentId: `content-${crypto.randomUUID()}`,
|
|
25967
|
+
kind: AGENT_CONTENT_KIND,
|
|
25968
|
+
messageId,
|
|
25969
|
+
sessionId: this.#mobiusSessionId
|
|
25970
|
+
});
|
|
25971
|
+
};
|
|
25555
25972
|
async #initializeAgent(signal) {
|
|
25556
25973
|
const initialized = await this.race(
|
|
25557
25974
|
this.#connection.agent.request(
|
|
@@ -26254,18 +26671,14 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
26254
26671
|
);
|
|
26255
26672
|
} else {
|
|
26256
26673
|
await this.#turn.activities.finishNarrative();
|
|
26257
|
-
await this
|
|
26674
|
+
await this.emitAgentText(update.content.text, truncate3(update.messageId ?? "", 255));
|
|
26258
26675
|
}
|
|
26259
26676
|
} else {
|
|
26260
26677
|
await this.#turn.activities.finishNarrative();
|
|
26261
|
-
await this
|
|
26262
|
-
|
|
26263
|
-
|
|
26264
|
-
|
|
26265
|
-
kind: AGENT_CONTENT_KIND,
|
|
26266
|
-
messageId: truncate3(update.messageId ?? "", 255),
|
|
26267
|
-
sessionId: this.#mobiusSessionId
|
|
26268
|
-
});
|
|
26678
|
+
await this.emitAgentContent(
|
|
26679
|
+
normalizeContentBlock(update.content),
|
|
26680
|
+
truncate3(update.messageId ?? "", 255)
|
|
26681
|
+
);
|
|
26269
26682
|
}
|
|
26270
26683
|
return;
|
|
26271
26684
|
}
|
|
@@ -27626,6 +28039,402 @@ var FixedInstallationExecutor = class {
|
|
|
27626
28039
|
};
|
|
27627
28040
|
};
|
|
27628
28041
|
|
|
28042
|
+
// src/artifacts/runtime-artifact-uploader.ts
|
|
28043
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
28044
|
+
|
|
28045
|
+
// ../mobius-sdk/src/errors.ts
|
|
28046
|
+
var MobiusError = class extends Error {
|
|
28047
|
+
code;
|
|
28048
|
+
constructor(code, message, options = {}) {
|
|
28049
|
+
super(message, options);
|
|
28050
|
+
this.code = code;
|
|
28051
|
+
this.name = "MobiusError";
|
|
28052
|
+
}
|
|
28053
|
+
};
|
|
28054
|
+
var MobiusProtocolError = class extends MobiusError {
|
|
28055
|
+
constructor(message, options = {}) {
|
|
28056
|
+
super("invalid_service_response", message, options);
|
|
28057
|
+
this.name = "MobiusProtocolError";
|
|
28058
|
+
}
|
|
28059
|
+
};
|
|
28060
|
+
var MobiusValidationError = class extends MobiusError {
|
|
28061
|
+
constructor(message, options = {}) {
|
|
28062
|
+
super("invalid_request", message, options);
|
|
28063
|
+
this.name = "MobiusValidationError";
|
|
28064
|
+
}
|
|
28065
|
+
};
|
|
28066
|
+
|
|
28067
|
+
// ../mobius-sdk/src/resources.ts
|
|
28068
|
+
var IDENTIFIER_PATTERN6 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
28069
|
+
function invalidResponse(message) {
|
|
28070
|
+
return new MobiusProtocolError(message);
|
|
28071
|
+
}
|
|
28072
|
+
function isRecord11(value) {
|
|
28073
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28074
|
+
}
|
|
28075
|
+
function record2(value, name) {
|
|
28076
|
+
if (!isRecord11(value)) {
|
|
28077
|
+
throw invalidResponse(`The service returned an invalid ${name}`);
|
|
28078
|
+
}
|
|
28079
|
+
return value;
|
|
28080
|
+
}
|
|
28081
|
+
function stringField(value, field, maximumLength = 85e5) {
|
|
28082
|
+
const candidate = value[field];
|
|
28083
|
+
if (typeof candidate !== "string" || candidate.length > maximumLength) {
|
|
28084
|
+
throw invalidResponse(`The service returned an invalid ${field}`);
|
|
28085
|
+
}
|
|
28086
|
+
return candidate;
|
|
28087
|
+
}
|
|
28088
|
+
function identifierField(value, field) {
|
|
28089
|
+
const candidate = stringField(value, field, 128);
|
|
28090
|
+
if (!IDENTIFIER_PATTERN6.test(candidate)) {
|
|
28091
|
+
throw invalidResponse(`The service returned an invalid ${field}`);
|
|
28092
|
+
}
|
|
28093
|
+
return candidate;
|
|
28094
|
+
}
|
|
28095
|
+
function integerField(value, field) {
|
|
28096
|
+
const candidate = value[field];
|
|
28097
|
+
if (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0) {
|
|
28098
|
+
throw invalidResponse(`The service returned an invalid ${field}`);
|
|
28099
|
+
}
|
|
28100
|
+
return candidate;
|
|
28101
|
+
}
|
|
28102
|
+
function validateTimestamp(value, field) {
|
|
28103
|
+
if (Number.isNaN(Date.parse(value))) {
|
|
28104
|
+
throw invalidResponse(`The service returned an invalid ${field}`);
|
|
28105
|
+
}
|
|
28106
|
+
return value;
|
|
28107
|
+
}
|
|
28108
|
+
var MobiusArtifactUploadRequest = class {
|
|
28109
|
+
byteLength;
|
|
28110
|
+
mediaType;
|
|
28111
|
+
name;
|
|
28112
|
+
sha256;
|
|
28113
|
+
constructor(name, mediaType, byteLength, sha256) {
|
|
28114
|
+
if (name.length < 1 || name.length > 500 || name.includes("\0") || mediaType.length < 1 || mediaType.length > 255 || mediaType.includes("\r") || mediaType.includes("\n") || !Number.isSafeInteger(byteLength) || byteLength < 1 || !/^[a-f0-9]{64}$/.test(sha256)) {
|
|
28115
|
+
throw new MobiusValidationError("The artifact upload request is invalid");
|
|
28116
|
+
}
|
|
28117
|
+
this.byteLength = byteLength;
|
|
28118
|
+
this.mediaType = mediaType;
|
|
28119
|
+
this.name = name;
|
|
28120
|
+
this.sha256 = sha256;
|
|
28121
|
+
}
|
|
28122
|
+
};
|
|
28123
|
+
var MobiusArtifact = class {
|
|
28124
|
+
artifactId;
|
|
28125
|
+
byteLength;
|
|
28126
|
+
createdAt;
|
|
28127
|
+
mediaType;
|
|
28128
|
+
name;
|
|
28129
|
+
sessionId;
|
|
28130
|
+
sha256;
|
|
28131
|
+
constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt) {
|
|
28132
|
+
this.artifactId = artifactId;
|
|
28133
|
+
this.byteLength = byteLength;
|
|
28134
|
+
this.createdAt = createdAt;
|
|
28135
|
+
this.mediaType = mediaType;
|
|
28136
|
+
this.name = name;
|
|
28137
|
+
this.sessionId = sessionId;
|
|
28138
|
+
this.sha256 = sha256;
|
|
28139
|
+
}
|
|
28140
|
+
};
|
|
28141
|
+
var MobiusUploadingArtifact = class extends MobiusArtifact {
|
|
28142
|
+
expiresAt;
|
|
28143
|
+
state = "uploading";
|
|
28144
|
+
constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiresAt) {
|
|
28145
|
+
super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
|
|
28146
|
+
this.expiresAt = expiresAt;
|
|
28147
|
+
}
|
|
28148
|
+
};
|
|
28149
|
+
var MobiusArtifactUpload = class extends MobiusUploadingArtifact {
|
|
28150
|
+
uploadToken;
|
|
28151
|
+
constructor(artifact, uploadToken) {
|
|
28152
|
+
super(
|
|
28153
|
+
artifact.sessionId,
|
|
28154
|
+
artifact.artifactId,
|
|
28155
|
+
artifact.name,
|
|
28156
|
+
artifact.mediaType,
|
|
28157
|
+
artifact.byteLength,
|
|
28158
|
+
artifact.sha256,
|
|
28159
|
+
artifact.createdAt,
|
|
28160
|
+
artifact.expiresAt
|
|
28161
|
+
);
|
|
28162
|
+
this.uploadToken = uploadToken;
|
|
28163
|
+
}
|
|
28164
|
+
};
|
|
28165
|
+
var MobiusAvailableArtifact = class extends MobiusArtifact {
|
|
28166
|
+
availableAt;
|
|
28167
|
+
state = "available";
|
|
28168
|
+
constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, availableAt) {
|
|
28169
|
+
super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
|
|
28170
|
+
this.availableAt = availableAt;
|
|
28171
|
+
}
|
|
28172
|
+
};
|
|
28173
|
+
var MobiusExpiredArtifact = class extends MobiusArtifact {
|
|
28174
|
+
expiredAt;
|
|
28175
|
+
state = "expired";
|
|
28176
|
+
constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiredAt) {
|
|
28177
|
+
super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
|
|
28178
|
+
this.expiredAt = expiredAt;
|
|
28179
|
+
}
|
|
28180
|
+
};
|
|
28181
|
+
function artifactFields(value) {
|
|
28182
|
+
const sha256 = stringField(value, "sha256", 64);
|
|
28183
|
+
if (!/^[a-f0-9]{64}$/.test(sha256)) {
|
|
28184
|
+
throw invalidResponse("The service returned an invalid artifact digest");
|
|
28185
|
+
}
|
|
28186
|
+
return {
|
|
28187
|
+
artifactId: identifierField(value, "artifactId"),
|
|
28188
|
+
byteLength: integerField(value, "byteLength"),
|
|
28189
|
+
createdAt: validateTimestamp(stringField(value, "createdAt", 128), "createdAt"),
|
|
28190
|
+
mediaType: stringField(value, "mediaType", 255),
|
|
28191
|
+
name: stringField(value, "name", 500),
|
|
28192
|
+
sessionId: identifierField(value, "sessionId"),
|
|
28193
|
+
sha256
|
|
28194
|
+
};
|
|
28195
|
+
}
|
|
28196
|
+
function uploadingArtifact(value) {
|
|
28197
|
+
const fields = artifactFields(value);
|
|
28198
|
+
return new MobiusUploadingArtifact(
|
|
28199
|
+
fields.sessionId,
|
|
28200
|
+
fields.artifactId,
|
|
28201
|
+
fields.name,
|
|
28202
|
+
fields.mediaType,
|
|
28203
|
+
fields.byteLength,
|
|
28204
|
+
fields.sha256,
|
|
28205
|
+
fields.createdAt,
|
|
28206
|
+
validateTimestamp(stringField(value, "expiresAt", 128), "expiresAt")
|
|
28207
|
+
);
|
|
28208
|
+
}
|
|
28209
|
+
function decodeMobiusArtifactUpload(value) {
|
|
28210
|
+
const artifact = record2(value, "artifact upload authorization");
|
|
28211
|
+
return new MobiusArtifactUpload(uploadingArtifact(artifact), stringField(artifact, "uploadToken", 256));
|
|
28212
|
+
}
|
|
28213
|
+
function decodeMobiusArtifact(value) {
|
|
28214
|
+
const artifact = record2(value, "artifact");
|
|
28215
|
+
const state = stringField(artifact, "state", 32);
|
|
28216
|
+
if (state === "uploading") {
|
|
28217
|
+
return uploadingArtifact(artifact);
|
|
28218
|
+
}
|
|
28219
|
+
const fields = artifactFields(artifact);
|
|
28220
|
+
if (state === "available") {
|
|
28221
|
+
return new MobiusAvailableArtifact(
|
|
28222
|
+
fields.sessionId,
|
|
28223
|
+
fields.artifactId,
|
|
28224
|
+
fields.name,
|
|
28225
|
+
fields.mediaType,
|
|
28226
|
+
fields.byteLength,
|
|
28227
|
+
fields.sha256,
|
|
28228
|
+
fields.createdAt,
|
|
28229
|
+
validateTimestamp(stringField(artifact, "availableAt", 128), "availableAt")
|
|
28230
|
+
);
|
|
28231
|
+
}
|
|
28232
|
+
if (state === "expired") {
|
|
28233
|
+
return new MobiusExpiredArtifact(
|
|
28234
|
+
fields.sessionId,
|
|
28235
|
+
fields.artifactId,
|
|
28236
|
+
fields.name,
|
|
28237
|
+
fields.mediaType,
|
|
28238
|
+
fields.byteLength,
|
|
28239
|
+
fields.sha256,
|
|
28240
|
+
fields.createdAt,
|
|
28241
|
+
validateTimestamp(stringField(artifact, "expiredAt", 128), "expiredAt")
|
|
28242
|
+
);
|
|
28243
|
+
}
|
|
28244
|
+
throw invalidResponse("The service returned an invalid artifact state");
|
|
28245
|
+
}
|
|
28246
|
+
function decodeMobiusAvailableArtifact(value) {
|
|
28247
|
+
const artifact = decodeMobiusArtifact(value);
|
|
28248
|
+
if (!(artifact instanceof MobiusAvailableArtifact)) {
|
|
28249
|
+
throw invalidResponse("The service did not make the artifact available");
|
|
28250
|
+
}
|
|
28251
|
+
return artifact;
|
|
28252
|
+
}
|
|
28253
|
+
var MobiusRuntimePairingLifecycle = Object.freeze({
|
|
28254
|
+
Expired: "expired",
|
|
28255
|
+
Paired: "paired",
|
|
28256
|
+
Pending: "pending",
|
|
28257
|
+
Revoked: "revoked"
|
|
28258
|
+
});
|
|
28259
|
+
|
|
28260
|
+
// src/artifacts/runtime-artifact-uploader.ts
|
|
28261
|
+
import { fetch as fetch4 } from "undici";
|
|
28262
|
+
var UPLOAD_TIMEOUT_MILLISECONDS = 2e4;
|
|
28263
|
+
var RuntimeArtifactUploadError = class extends Error {
|
|
28264
|
+
code;
|
|
28265
|
+
constructor(code, message, options = {}) {
|
|
28266
|
+
super(message, options);
|
|
28267
|
+
this.code = code;
|
|
28268
|
+
this.name = "RuntimeArtifactUploadError";
|
|
28269
|
+
}
|
|
28270
|
+
};
|
|
28271
|
+
var UploadedRuntimeArtifact = class {
|
|
28272
|
+
artifactId;
|
|
28273
|
+
byteLength;
|
|
28274
|
+
mimeType;
|
|
28275
|
+
name;
|
|
28276
|
+
sha256;
|
|
28277
|
+
constructor(artifactId, name, mimeType, byteLength, sha256) {
|
|
28278
|
+
this.artifactId = artifactId;
|
|
28279
|
+
this.byteLength = byteLength;
|
|
28280
|
+
this.mimeType = mimeType;
|
|
28281
|
+
this.name = name;
|
|
28282
|
+
this.sha256 = sha256;
|
|
28283
|
+
}
|
|
28284
|
+
};
|
|
28285
|
+
function daemonToken(config2) {
|
|
28286
|
+
const token = config2.relayUrl.searchParams.get("token");
|
|
28287
|
+
if (token === null || token.length < 32) {
|
|
28288
|
+
throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay daemon token is missing");
|
|
28289
|
+
}
|
|
28290
|
+
return token;
|
|
28291
|
+
}
|
|
28292
|
+
function channelOrigin(config2) {
|
|
28293
|
+
const url2 = new URL(config2.relayUrl);
|
|
28294
|
+
url2.protocol = url2.protocol === "wss:" ? "https:" : "http:";
|
|
28295
|
+
let channelPath = "";
|
|
28296
|
+
if (url2.pathname.endsWith("/daemon")) {
|
|
28297
|
+
channelPath = url2.pathname.slice(0, -"/daemon".length);
|
|
28298
|
+
} else {
|
|
28299
|
+
const runtimePath = `${MOBIUS_API_PREFIX}/v1/runtimes/connect`;
|
|
28300
|
+
if (!url2.pathname.endsWith("/v1/runtimes/connect") && !url2.pathname.endsWith(runtimePath)) {
|
|
28301
|
+
throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay artifact endpoint is invalid");
|
|
28302
|
+
}
|
|
28303
|
+
channelPath = `${url2.pathname.replace(/\/v1\/runtimes\/connect$/, "")}/channels/${encodeURIComponent(config2.channelId)}`;
|
|
28304
|
+
}
|
|
28305
|
+
url2.pathname = channelPath;
|
|
28306
|
+
url2.search = "";
|
|
28307
|
+
url2.hash = "";
|
|
28308
|
+
return url2;
|
|
28309
|
+
}
|
|
28310
|
+
function uploadError(code, message, cause) {
|
|
28311
|
+
return new RuntimeArtifactUploadError(code, message, cause === void 0 ? {} : { cause });
|
|
28312
|
+
}
|
|
28313
|
+
function translateSdkError(cause) {
|
|
28314
|
+
if (cause instanceof MobiusValidationError) {
|
|
28315
|
+
throw uploadError("artifact_upload_failed", cause.message, cause);
|
|
28316
|
+
}
|
|
28317
|
+
if (cause instanceof MobiusProtocolError) {
|
|
28318
|
+
throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
|
|
28319
|
+
}
|
|
28320
|
+
throw cause;
|
|
28321
|
+
}
|
|
28322
|
+
async function readJson(response) {
|
|
28323
|
+
try {
|
|
28324
|
+
return await response.json();
|
|
28325
|
+
} catch (cause) {
|
|
28326
|
+
throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
|
|
28327
|
+
}
|
|
28328
|
+
}
|
|
28329
|
+
async function readAuthorization(response) {
|
|
28330
|
+
try {
|
|
28331
|
+
return decodeMobiusArtifactUpload(await readJson(response));
|
|
28332
|
+
} catch (cause) {
|
|
28333
|
+
translateSdkError(cause);
|
|
28334
|
+
}
|
|
28335
|
+
}
|
|
28336
|
+
function sessionArtifactUrl(origin, sessionId, resourcePath, token) {
|
|
28337
|
+
const url2 = new URL(`${origin.pathname}/sessions/${encodeURIComponent(sessionId)}/${resourcePath}`, origin);
|
|
28338
|
+
url2.searchParams.set("token", token);
|
|
28339
|
+
return url2;
|
|
28340
|
+
}
|
|
28341
|
+
async function postLease(url2, request, signal) {
|
|
28342
|
+
return await fetch4(url2, {
|
|
28343
|
+
dispatcher: environmentProxyDispatcher,
|
|
28344
|
+
headers: { "content-type": "application/json" },
|
|
28345
|
+
method: "POST",
|
|
28346
|
+
body: JSON.stringify(request),
|
|
28347
|
+
signal
|
|
28348
|
+
});
|
|
28349
|
+
}
|
|
28350
|
+
async function putContent(url2, authorization, bytes, signal) {
|
|
28351
|
+
return await fetch4(url2, {
|
|
28352
|
+
dispatcher: environmentProxyDispatcher,
|
|
28353
|
+
headers: {
|
|
28354
|
+
"content-type": authorization.mediaType,
|
|
28355
|
+
"x-mobius-upload-token": authorization.uploadToken
|
|
28356
|
+
},
|
|
28357
|
+
method: "PUT",
|
|
28358
|
+
body: bytes,
|
|
28359
|
+
signal
|
|
28360
|
+
});
|
|
28361
|
+
}
|
|
28362
|
+
async function uploadRuntimeArtifact(config2, sessionId, image, signal) {
|
|
28363
|
+
signal.throwIfAborted();
|
|
28364
|
+
let request;
|
|
28365
|
+
try {
|
|
28366
|
+
request = new MobiusArtifactUploadRequest(
|
|
28367
|
+
image.name,
|
|
28368
|
+
image.mimeType,
|
|
28369
|
+
image.bytes.byteLength,
|
|
28370
|
+
createHash2("sha256").update(image.bytes).digest("hex")
|
|
28371
|
+
);
|
|
28372
|
+
} catch (cause) {
|
|
28373
|
+
translateSdkError(cause);
|
|
28374
|
+
}
|
|
28375
|
+
const timeoutSignal = AbortSignal.timeout(UPLOAD_TIMEOUT_MILLISECONDS);
|
|
28376
|
+
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
28377
|
+
const origin = channelOrigin(config2);
|
|
28378
|
+
const token = daemonToken(config2);
|
|
28379
|
+
let created;
|
|
28380
|
+
try {
|
|
28381
|
+
created = await postLease(
|
|
28382
|
+
sessionArtifactUrl(origin, sessionId, "artifacts/uploads", token),
|
|
28383
|
+
request,
|
|
28384
|
+
requestSignal
|
|
28385
|
+
);
|
|
28386
|
+
} catch (cause) {
|
|
28387
|
+
signal.throwIfAborted();
|
|
28388
|
+
throw uploadError(
|
|
28389
|
+
timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
|
|
28390
|
+
timeoutSignal.aborted ? "The artifact upload authorization timed out" : "The artifact upload could not start",
|
|
28391
|
+
cause
|
|
28392
|
+
);
|
|
28393
|
+
}
|
|
28394
|
+
if (!created.ok) {
|
|
28395
|
+
await created.body?.cancel();
|
|
28396
|
+
throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact upload");
|
|
28397
|
+
}
|
|
28398
|
+
const authorization = await readAuthorization(created);
|
|
28399
|
+
let uploaded;
|
|
28400
|
+
try {
|
|
28401
|
+
uploaded = await putContent(
|
|
28402
|
+
sessionArtifactUrl(
|
|
28403
|
+
origin,
|
|
28404
|
+
sessionId,
|
|
28405
|
+
`artifacts/${encodeURIComponent(authorization.artifactId)}/content`,
|
|
28406
|
+
token
|
|
28407
|
+
),
|
|
28408
|
+
authorization,
|
|
28409
|
+
image.bytes,
|
|
28410
|
+
requestSignal
|
|
28411
|
+
);
|
|
28412
|
+
} catch (cause) {
|
|
28413
|
+
signal.throwIfAborted();
|
|
28414
|
+
throw uploadError(
|
|
28415
|
+
timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
|
|
28416
|
+
timeoutSignal.aborted ? "The artifact upload timed out" : "The artifact content could not be uploaded",
|
|
28417
|
+
cause
|
|
28418
|
+
);
|
|
28419
|
+
}
|
|
28420
|
+
if (!uploaded.ok) {
|
|
28421
|
+
await uploaded.body?.cancel();
|
|
28422
|
+
throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact content");
|
|
28423
|
+
}
|
|
28424
|
+
try {
|
|
28425
|
+
const available = decodeMobiusAvailableArtifact(await readJson(uploaded));
|
|
28426
|
+
return new UploadedRuntimeArtifact(
|
|
28427
|
+
available.artifactId,
|
|
28428
|
+
available.name,
|
|
28429
|
+
available.mediaType,
|
|
28430
|
+
available.byteLength,
|
|
28431
|
+
available.sha256
|
|
28432
|
+
);
|
|
28433
|
+
} catch (cause) {
|
|
28434
|
+
translateSdkError(cause);
|
|
28435
|
+
}
|
|
28436
|
+
}
|
|
28437
|
+
|
|
27629
28438
|
// src/authorization/local-authorization-error.ts
|
|
27630
28439
|
var LocalAuthorizationError = class extends Error {
|
|
27631
28440
|
code = "local_authorization_failed";
|
|
@@ -27636,9 +28445,9 @@ var LocalAuthorizationError = class extends Error {
|
|
|
27636
28445
|
};
|
|
27637
28446
|
|
|
27638
28447
|
// src/authorization/workspace-directory.ts
|
|
27639
|
-
import { readdir, realpath as
|
|
28448
|
+
import { readdir, realpath as realpath8, stat as stat7 } from "node:fs/promises";
|
|
27640
28449
|
import { homedir as homedir2 } from "node:os";
|
|
27641
|
-
import { basename as
|
|
28450
|
+
import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute9, join as join16, normalize as normalize3, relative as relative5 } from "node:path";
|
|
27642
28451
|
var WorkspaceDirectoryListing = class {
|
|
27643
28452
|
directoryId;
|
|
27644
28453
|
directoryLabel;
|
|
@@ -27664,7 +28473,7 @@ function decodePath(value, prefix) {
|
|
|
27664
28473
|
throw new LocalAuthorizationError("The directory identifier is invalid");
|
|
27665
28474
|
}
|
|
27666
28475
|
const decoded = Buffer.from(encoded, "base64url").toString("utf8");
|
|
27667
|
-
if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") ||
|
|
28476
|
+
if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize3(decoded) !== decoded) {
|
|
27668
28477
|
throw new LocalAuthorizationError("The directory identifier is invalid");
|
|
27669
28478
|
}
|
|
27670
28479
|
return decoded;
|
|
@@ -27690,7 +28499,7 @@ var WorkspaceDirectoryService = class {
|
|
|
27690
28499
|
}
|
|
27691
28500
|
if (id.startsWith("path-")) {
|
|
27692
28501
|
const path2 = decodePath(id, "path-");
|
|
27693
|
-
if (
|
|
28502
|
+
if (isAbsolute9(path2)) {
|
|
27694
28503
|
return path2;
|
|
27695
28504
|
}
|
|
27696
28505
|
}
|
|
@@ -27698,15 +28507,15 @@ var WorkspaceDirectoryService = class {
|
|
|
27698
28507
|
};
|
|
27699
28508
|
resolvePath = async (requested, signal) => {
|
|
27700
28509
|
signal.throwIfAborted();
|
|
27701
|
-
if (!
|
|
28510
|
+
if (!isAbsolute9(requested) || requested.includes("\0") || normalize3(requested) !== requested) {
|
|
27702
28511
|
throw new LocalAuthorizationError("The local directory path is invalid");
|
|
27703
28512
|
}
|
|
27704
28513
|
try {
|
|
27705
|
-
const target = await
|
|
28514
|
+
const target = await realpath8(requested);
|
|
27706
28515
|
signal.throwIfAborted();
|
|
27707
|
-
const metadata = await
|
|
28516
|
+
const metadata = await stat7(target);
|
|
27708
28517
|
signal.throwIfAborted();
|
|
27709
|
-
if (!
|
|
28518
|
+
if (!isAbsolute9(target) || normalize3(target) !== target || !metadata.isDirectory()) {
|
|
27710
28519
|
throw new LocalAuthorizationError("The selected location is not a directory");
|
|
27711
28520
|
}
|
|
27712
28521
|
return target;
|
|
@@ -27721,8 +28530,8 @@ var WorkspaceDirectoryService = class {
|
|
|
27721
28530
|
}
|
|
27722
28531
|
};
|
|
27723
28532
|
label = (path2) => {
|
|
27724
|
-
const suffix =
|
|
27725
|
-
return suffix === "" ? "~" : !
|
|
28533
|
+
const suffix = relative5(homedir2(), path2);
|
|
28534
|
+
return suffix === "" ? "~" : !isAbsolute9(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
|
|
27726
28535
|
};
|
|
27727
28536
|
identify = async (bindingId, requestedPath, signal) => {
|
|
27728
28537
|
this.authorizeMachine(bindingId);
|
|
@@ -27730,7 +28539,7 @@ var WorkspaceDirectoryService = class {
|
|
|
27730
28539
|
return {
|
|
27731
28540
|
path: path2,
|
|
27732
28541
|
directoryId: encodePath(path2),
|
|
27733
|
-
name:
|
|
28542
|
+
name: basename3(path2) || path2,
|
|
27734
28543
|
label: this.label(path2)
|
|
27735
28544
|
};
|
|
27736
28545
|
};
|
|
@@ -27752,7 +28561,7 @@ var WorkspaceDirectoryService = class {
|
|
|
27752
28561
|
continue;
|
|
27753
28562
|
}
|
|
27754
28563
|
try {
|
|
27755
|
-
const path2 = await this.resolvePath(
|
|
28564
|
+
const path2 = await this.resolvePath(join16(target, child.name), signal);
|
|
27756
28565
|
entries.push({ directoryId: encodePath(path2), name: child.name });
|
|
27757
28566
|
} catch (cause) {
|
|
27758
28567
|
signal.throwIfAborted();
|
|
@@ -27787,8 +28596,8 @@ var WorkspaceDirectoryService = class {
|
|
|
27787
28596
|
};
|
|
27788
28597
|
|
|
27789
28598
|
// src/bots/local-bot-grant-store.ts
|
|
27790
|
-
import { createHash as
|
|
27791
|
-
import { stat as
|
|
28599
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
|
|
28600
|
+
import { stat as stat8 } from "node:fs/promises";
|
|
27792
28601
|
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
27793
28602
|
var LOCAL_BOT_GRANT_LIFETIME_MILLISECONDS = 90 * 24 * 60 * 60 * 1e3;
|
|
27794
28603
|
var LocalBotAuthorizationError = class extends Error {
|
|
@@ -27832,7 +28641,7 @@ var LocalBotGrant = class {
|
|
|
27832
28641
|
}
|
|
27833
28642
|
};
|
|
27834
28643
|
function digest(value) {
|
|
27835
|
-
return
|
|
28644
|
+
return createHash3("sha256").update(value, "utf8").digest("hex");
|
|
27836
28645
|
}
|
|
27837
28646
|
function agentDigest(agent) {
|
|
27838
28647
|
return digest(
|
|
@@ -27846,7 +28655,7 @@ function agentDigest(agent) {
|
|
|
27846
28655
|
);
|
|
27847
28656
|
}
|
|
27848
28657
|
async function workspaceDigest(path2) {
|
|
27849
|
-
const metadata = await
|
|
28658
|
+
const metadata = await stat8(path2);
|
|
27850
28659
|
if (!metadata.isDirectory()) {
|
|
27851
28660
|
throw new LocalBotAuthorizationError("binding_incompatible", "The Bot workspace is not a directory");
|
|
27852
28661
|
}
|
|
@@ -28263,12 +29072,12 @@ var BotExecutionContextRegistry = class {
|
|
|
28263
29072
|
// src/bots/bot-outbound-ipc.ts
|
|
28264
29073
|
import { chmod as chmod2, mkdir as mkdir4, unlink } from "node:fs/promises";
|
|
28265
29074
|
import { createServer } from "node:net";
|
|
28266
|
-
import { dirname as dirname6, isAbsolute as
|
|
28267
|
-
import { fetch as
|
|
29075
|
+
import { dirname as dirname6, isAbsolute as isAbsolute10 } from "node:path";
|
|
29076
|
+
import { fetch as fetch5 } from "undici";
|
|
28268
29077
|
var BOT_IPC_REQUEST_LIMIT = 32 * 1024;
|
|
28269
29078
|
var BOT_IPC_TIMEOUT_MILLISECONDS2 = 2e4;
|
|
28270
29079
|
var BOT_RELAY_TIMEOUT_MILLISECONDS = 2e4;
|
|
28271
|
-
var
|
|
29080
|
+
var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
28272
29081
|
var WINDOWS_NAMED_PIPE_PREFIX = "\\\\.\\pipe\\";
|
|
28273
29082
|
var BotOutboundIpcRequest = class {
|
|
28274
29083
|
contextHandle;
|
|
@@ -28282,7 +29091,7 @@ var BotOutboundIpcRequest = class {
|
|
|
28282
29091
|
this.text = text;
|
|
28283
29092
|
}
|
|
28284
29093
|
};
|
|
28285
|
-
function
|
|
29094
|
+
function isRecord12(value) {
|
|
28286
29095
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28287
29096
|
}
|
|
28288
29097
|
function decodeRequest(encoded) {
|
|
@@ -28292,7 +29101,7 @@ function decodeRequest(encoded) {
|
|
|
28292
29101
|
} catch (cause) {
|
|
28293
29102
|
throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid", { cause });
|
|
28294
29103
|
}
|
|
28295
|
-
if (!
|
|
29104
|
+
if (!isRecord12(value)) {
|
|
28296
29105
|
throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
|
|
28297
29106
|
}
|
|
28298
29107
|
const keys = Object.keys(value);
|
|
@@ -28303,7 +29112,7 @@ function decodeRequest(encoded) {
|
|
|
28303
29112
|
const idempotencyKey = value["idempotencyKey"];
|
|
28304
29113
|
const target = value["target"];
|
|
28305
29114
|
const text = value["text"];
|
|
28306
|
-
if (typeof contextHandle !== "string" || !/^ctx_[a-zA-Z0-9_-]{43}$/.test(contextHandle) || typeof idempotencyKey !== "string" || !
|
|
29115
|
+
if (typeof contextHandle !== "string" || !/^ctx_[a-zA-Z0-9_-]{43}$/.test(contextHandle) || typeof idempotencyKey !== "string" || !IDENTIFIER_PATTERN7.test(idempotencyKey) || typeof target !== "string" || !IDENTIFIER_PATTERN7.test(target) || typeof text !== "string" || text.trim().length === 0 || text.length > 1e4) {
|
|
28307
29116
|
throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
|
|
28308
29117
|
}
|
|
28309
29118
|
return new BotOutboundIpcRequest(contextHandle, idempotencyKey, target, text);
|
|
@@ -28325,7 +29134,7 @@ function relayEndpoint(relayUrl, context, target) {
|
|
|
28325
29134
|
endpoint.pathname = `${MOBIUS_API_PREFIX}/v1/bot-executions/${execution}/delivery-targets/${encodeURIComponent(deliveryTargetId)}/messages`;
|
|
28326
29135
|
return endpoint;
|
|
28327
29136
|
}
|
|
28328
|
-
function
|
|
29137
|
+
function daemonToken2(relayUrl) {
|
|
28329
29138
|
const token = relayUrl.searchParams.get("token") ?? "";
|
|
28330
29139
|
if (!/^[a-zA-Z0-9_-]{32,256}$/.test(token)) {
|
|
28331
29140
|
throw new LocalBotAuthorizationError("bot_service_unavailable", "The Runtime credential is unavailable");
|
|
@@ -28342,10 +29151,10 @@ async function decodeRelayResponse(response) {
|
|
|
28342
29151
|
cause
|
|
28343
29152
|
});
|
|
28344
29153
|
}
|
|
28345
|
-
if (response.status === 202 &&
|
|
29154
|
+
if (response.status === 202 && isRecord12(value) && typeof value["outboundMessageId"] === "string") {
|
|
28346
29155
|
return value["outboundMessageId"];
|
|
28347
29156
|
}
|
|
28348
|
-
if (
|
|
29157
|
+
if (isRecord12(value) && isRecord12(value["error"])) {
|
|
28349
29158
|
const error61 = value["error"];
|
|
28350
29159
|
if (typeof error61["code"] === "string" && typeof error61["message"] === "string") {
|
|
28351
29160
|
throw new LocalBotAuthorizationError(error61["code"], error61["message"]);
|
|
@@ -28361,7 +29170,7 @@ var BotOutboundIpcServer = class {
|
|
|
28361
29170
|
#usesFilesystemSocket;
|
|
28362
29171
|
constructor(socketPath, relayUrl, registry2) {
|
|
28363
29172
|
const usesFilesystemSocket = !socketPath.startsWith(WINDOWS_NAMED_PIPE_PREFIX);
|
|
28364
|
-
if (usesFilesystemSocket && !
|
|
29173
|
+
if (usesFilesystemSocket && !isAbsolute10(socketPath)) {
|
|
28365
29174
|
throw new Error("The Bot IPC path must be absolute");
|
|
28366
29175
|
}
|
|
28367
29176
|
this.#registry = registry2;
|
|
@@ -28378,7 +29187,7 @@ var BotOutboundIpcServer = class {
|
|
|
28378
29187
|
if (this.#usesFilesystemSocket) {
|
|
28379
29188
|
await mkdir4(dirname6(this.#socketPath), { mode: 448, recursive: true });
|
|
28380
29189
|
await unlink(this.#socketPath).catch((error61) => {
|
|
28381
|
-
if (!
|
|
29190
|
+
if (!isRecord12(error61) || error61["code"] !== "ENOENT") {
|
|
28382
29191
|
throw error61;
|
|
28383
29192
|
}
|
|
28384
29193
|
});
|
|
@@ -28413,7 +29222,7 @@ var BotOutboundIpcServer = class {
|
|
|
28413
29222
|
}
|
|
28414
29223
|
if (this.#usesFilesystemSocket) {
|
|
28415
29224
|
await unlink(this.#socketPath).catch((error61) => {
|
|
28416
|
-
if (!
|
|
29225
|
+
if (!isRecord12(error61) || error61["code"] !== "ENOENT") {
|
|
28417
29226
|
throw error61;
|
|
28418
29227
|
}
|
|
28419
29228
|
});
|
|
@@ -28477,10 +29286,10 @@ var BotOutboundIpcServer = class {
|
|
|
28477
29286
|
const requestSignal = AbortSignal.any([signal, timeout]);
|
|
28478
29287
|
let response;
|
|
28479
29288
|
try {
|
|
28480
|
-
response = await
|
|
29289
|
+
response = await fetch5(relayEndpoint(this.#relayUrl, context, request.target), {
|
|
28481
29290
|
body: JSON.stringify({ idempotencyKey: request.idempotencyKey, text: request.text }),
|
|
28482
29291
|
headers: {
|
|
28483
|
-
authorization: `Bearer ${
|
|
29292
|
+
authorization: `Bearer ${daemonToken2(this.#relayUrl)}`,
|
|
28484
29293
|
"content-type": "application/json",
|
|
28485
29294
|
"x-mobius-bot-execution-capability": context.command.executionCapabilitySecret
|
|
28486
29295
|
},
|
|
@@ -28501,7 +29310,7 @@ var BotOutboundIpcServer = class {
|
|
|
28501
29310
|
|
|
28502
29311
|
// src/native-sessions/service.ts
|
|
28503
29312
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
28504
|
-
import { basename as
|
|
29313
|
+
import { basename as basename4 } from "node:path";
|
|
28505
29314
|
|
|
28506
29315
|
// src/native-sessions/codex-history.ts
|
|
28507
29316
|
import { spawn as spawn4 } from "node:child_process";
|
|
@@ -28534,7 +29343,6 @@ function decodeHistory(thread, value) {
|
|
|
28534
29343
|
const page = turnsSchema.parse(value);
|
|
28535
29344
|
const messages = [];
|
|
28536
29345
|
let characters = 0;
|
|
28537
|
-
let imageCharacters = 0;
|
|
28538
29346
|
let truncated = page.nextCursor != null;
|
|
28539
29347
|
for (const turn of page.data.toReversed()) {
|
|
28540
29348
|
for (const item of turn.items) {
|
|
@@ -28542,22 +29350,19 @@ function decodeHistory(thread, value) {
|
|
|
28542
29350
|
let message;
|
|
28543
29351
|
if (type === "userMessage") {
|
|
28544
29352
|
const { content } = userMessageSchema.parse(item);
|
|
28545
|
-
const
|
|
28546
|
-
|
|
28547
|
-
|
|
28548
|
-
|
|
28549
|
-
|
|
28550
|
-
|
|
28551
|
-
|
|
28552
|
-
|
|
28553
|
-
|
|
28554
|
-
|
|
28555
|
-
}).join("")
|
|
28556
|
-
);
|
|
29353
|
+
const text2 = content.map((block) => {
|
|
29354
|
+
const { type: type2 } = itemTypeSchema.parse(block);
|
|
29355
|
+
if (type2 === "text") {
|
|
29356
|
+
return textSchema.parse(block).text;
|
|
29357
|
+
}
|
|
29358
|
+
if (type2 === "image") {
|
|
29359
|
+
return `[@image](${imageSchema.parse(block).url})`;
|
|
29360
|
+
}
|
|
29361
|
+
return "[Attachment]";
|
|
29362
|
+
}).join("");
|
|
28557
29363
|
message = {
|
|
28558
29364
|
role: "user",
|
|
28559
|
-
text:
|
|
28560
|
-
...parsed.images.length > 0 ? { images: parsed.images } : {}
|
|
29365
|
+
text: text2
|
|
28561
29366
|
};
|
|
28562
29367
|
} else if (type === "agentMessage") {
|
|
28563
29368
|
const agent = agentMessageSchema.parse(item);
|
|
@@ -28575,12 +29380,10 @@ function decodeHistory(thread, value) {
|
|
|
28575
29380
|
truncated ||= text.length < message.text.length;
|
|
28576
29381
|
messages.push({ ...message, text });
|
|
28577
29382
|
characters += text.length;
|
|
28578
|
-
|
|
28579
|
-
while (messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT || imageCharacters > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
29383
|
+
while (messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT) {
|
|
28580
29384
|
const removed = messages.shift();
|
|
28581
29385
|
if (removed !== void 0) {
|
|
28582
29386
|
characters -= removed.text.length;
|
|
28583
|
-
imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
28584
29387
|
}
|
|
28585
29388
|
truncated = true;
|
|
28586
29389
|
}
|
|
@@ -28738,7 +29541,11 @@ async function readCodexHistory(agent, cwd, nativeSessionId, signal) {
|
|
|
28738
29541
|
params: { clientInfo: { name: "mobius_history", version: "1.0.0" } }
|
|
28739
29542
|
});
|
|
28740
29543
|
}
|
|
28741
|
-
|
|
29544
|
+
const snapshot = await response.promise;
|
|
29545
|
+
return {
|
|
29546
|
+
...snapshot,
|
|
29547
|
+
history: await embedLocalHistoryImages(snapshot.history, [cwd, snapshot.cwd], signal)
|
|
29548
|
+
};
|
|
28742
29549
|
} finally {
|
|
28743
29550
|
clearTimeout(timeout);
|
|
28744
29551
|
signal.removeEventListener("abort", abort);
|
|
@@ -28992,7 +29799,7 @@ var NativeSessionService = class {
|
|
|
28992
29799
|
}
|
|
28993
29800
|
resolvedPaths.add(path2);
|
|
28994
29801
|
additionalDirectories.push(path2);
|
|
28995
|
-
additionalEntries.push({ directoryId: directoryId2, name:
|
|
29802
|
+
additionalEntries.push({ directoryId: directoryId2, name: basename4(path2) });
|
|
28996
29803
|
}
|
|
28997
29804
|
const listing = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
|
|
28998
29805
|
const opened = await this.#sessions.forkSessionAtTurn(
|
|
@@ -29131,13 +29938,13 @@ var NativeSessionService = class {
|
|
|
29131
29938
|
};
|
|
29132
29939
|
|
|
29133
29940
|
// src/prompt-artifact-resolver.ts
|
|
29134
|
-
import { createHash as
|
|
29135
|
-
import { fetch as
|
|
29941
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
29942
|
+
import { fetch as fetch6 } from "undici";
|
|
29136
29943
|
var ARTIFACT_SCHEME = "mobius-artifact:";
|
|
29137
29944
|
var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
|
|
29138
29945
|
var MAX_AGENT_IMAGE_BASE64_LENGTH = 4e6;
|
|
29139
29946
|
var MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
|
|
29140
|
-
var
|
|
29947
|
+
var IDENTIFIER_PATTERN8 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
29141
29948
|
var PromptArtifactError = class extends Error {
|
|
29142
29949
|
code;
|
|
29143
29950
|
constructor(code, message, options = {}) {
|
|
@@ -29180,7 +29987,7 @@ function parseReference(resource) {
|
|
|
29180
29987
|
const encodedByteLength2 = url2.searchParams.get("byteLength") ?? "";
|
|
29181
29988
|
const sha256 = url2.searchParams.get("sha256") ?? "";
|
|
29182
29989
|
const byteLength = Number(encodedByteLength2);
|
|
29183
|
-
if (url2.protocol !== ARTIFACT_SCHEME || url2.hash.length > 0 || resource.type !== "link" || resource.text.length > 0 || !
|
|
29990
|
+
if (url2.protocol !== ARTIFACT_SCHEME || url2.hash.length > 0 || resource.type !== "link" || resource.text.length > 0 || !IDENTIFIER_PATTERN8.test(artifactId) || keys.length !== 2 || keys[0] !== "byteLength" || keys[1] !== "sha256" || !/^[1-9][0-9]*$/.test(encodedByteLength2) || !Number.isSafeInteger(byteLength) || !/^[a-f0-9]{64}$/.test(sha256)) {
|
|
29184
29991
|
throw new PromptArtifactError("artifact_reference_invalid", "The prompt artifact reference is invalid");
|
|
29185
29992
|
}
|
|
29186
29993
|
return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
|
|
@@ -29246,7 +30053,7 @@ async function download(config2, command, reference, signal) {
|
|
|
29246
30053
|
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
29247
30054
|
let response;
|
|
29248
30055
|
try {
|
|
29249
|
-
response = await
|
|
30056
|
+
response = await fetch6(downloadUrl(config2, command, reference), {
|
|
29250
30057
|
dispatcher: environmentProxyDispatcher,
|
|
29251
30058
|
headers: {
|
|
29252
30059
|
accept: reference.resource.mimeType,
|
|
@@ -29270,7 +30077,7 @@ async function download(config2, command, reference, signal) {
|
|
|
29270
30077
|
);
|
|
29271
30078
|
}
|
|
29272
30079
|
const bytes = await responseBytes(response, reference.byteLength, requestSignal);
|
|
29273
|
-
if (
|
|
30080
|
+
if (createHash4("sha256").update(bytes).digest("hex") !== reference.sha256) {
|
|
29274
30081
|
throw new PromptArtifactError(
|
|
29275
30082
|
"artifact_integrity_failed",
|
|
29276
30083
|
"The prompt artifact failed integrity validation"
|
|
@@ -30303,13 +31110,26 @@ function botIpcSocketPath() {
|
|
|
30303
31110
|
if (process.platform === "win32") {
|
|
30304
31111
|
return `\\\\.\\pipe\\mobius-bot-${randomUUID6()}`;
|
|
30305
31112
|
}
|
|
30306
|
-
return
|
|
31113
|
+
return join17("/tmp", `mobius-bot-${randomUUID6()}.sock`);
|
|
30307
31114
|
}
|
|
30308
31115
|
var DaemonAcpObserver = class {
|
|
31116
|
+
#config;
|
|
30309
31117
|
#record;
|
|
30310
|
-
constructor(
|
|
30311
|
-
this.#
|
|
31118
|
+
constructor(config2, record3) {
|
|
31119
|
+
this.#config = config2;
|
|
31120
|
+
this.#record = record3;
|
|
30312
31121
|
}
|
|
31122
|
+
importLocalImage = async (sessionId, image, signal) => {
|
|
31123
|
+
try {
|
|
31124
|
+
return (await uploadRuntimeArtifact(this.#config, sessionId, image, signal)).artifactId;
|
|
31125
|
+
} catch (cause) {
|
|
31126
|
+
signal.throwIfAborted();
|
|
31127
|
+
if (cause instanceof Error && cause.name === "AbortError") {
|
|
31128
|
+
throw cause;
|
|
31129
|
+
}
|
|
31130
|
+
return "";
|
|
31131
|
+
}
|
|
31132
|
+
};
|
|
30313
31133
|
onCommands = (event) => {
|
|
30314
31134
|
this.#record(event.sessionId, encodeSessionCommandsUpdatedEvent(event));
|
|
30315
31135
|
return Promise.resolve();
|
|
@@ -30519,7 +31339,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
|
|
|
30519
31339
|
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
30520
31340
|
let response;
|
|
30521
31341
|
try {
|
|
30522
|
-
response = await
|
|
31342
|
+
response = await fetch7(activeTurnReconciliationEndpoint(config2, turn), {
|
|
30523
31343
|
body: JSON.stringify({ outcome: { kind: "running" } }),
|
|
30524
31344
|
dispatcher: environmentProxyDispatcher,
|
|
30525
31345
|
headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
|
|
@@ -30835,7 +31655,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId2, a
|
|
|
30835
31655
|
additionalDirectories.push(directory);
|
|
30836
31656
|
additionalDirectoryEntries.push({
|
|
30837
31657
|
directoryId: additionalDirectoryId,
|
|
30838
|
-
name:
|
|
31658
|
+
name: basename5(directory)
|
|
30839
31659
|
});
|
|
30840
31660
|
}
|
|
30841
31661
|
return new ResolvedSessionDirectories(cwd, additionalDirectories, additionalDirectoryEntries);
|
|
@@ -31346,8 +32166,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31346
32166
|
rejectConnection(failure);
|
|
31347
32167
|
};
|
|
31348
32168
|
const processingDeliveryIds = /* @__PURE__ */ new Set();
|
|
31349
|
-
const processDeliveredPrompt = async (delivery) => {
|
|
31350
|
-
const command = decodeSessionPromptCommand(delivery.payload);
|
|
32169
|
+
const processDeliveredPrompt = async (delivery, command, trackActiveAttempt, execute) => {
|
|
31351
32170
|
if (command.sessionId !== delivery.sessionId) {
|
|
31352
32171
|
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31353
32172
|
}
|
|
@@ -31375,22 +32194,11 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31375
32194
|
}
|
|
31376
32195
|
const turn = new ActiveDaemonTurn(command, receipt.attemptId);
|
|
31377
32196
|
activeTurns.set(command.commandId, turn);
|
|
31378
|
-
if (
|
|
32197
|
+
if (trackActiveAttempt) {
|
|
31379
32198
|
activeAttemptIds.set(command.sessionId, receipt.attemptId);
|
|
31380
32199
|
}
|
|
31381
32200
|
try {
|
|
31382
|
-
await
|
|
31383
|
-
outbox,
|
|
31384
|
-
publisher,
|
|
31385
|
-
command,
|
|
31386
|
-
config2,
|
|
31387
|
-
directories,
|
|
31388
|
-
audit,
|
|
31389
|
-
sessions,
|
|
31390
|
-
receipt.attemptId,
|
|
31391
|
-
timer,
|
|
31392
|
-
turn.signal
|
|
31393
|
-
);
|
|
32201
|
+
await execute(receipt.attemptId, turn.signal);
|
|
31394
32202
|
} finally {
|
|
31395
32203
|
activeTurns.delete(command.commandId);
|
|
31396
32204
|
if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
|
|
@@ -31469,8 +32277,50 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31469
32277
|
}
|
|
31470
32278
|
return;
|
|
31471
32279
|
}
|
|
32280
|
+
if (kind === BOT_SESSION_PROMPT_KIND) {
|
|
32281
|
+
const command = decodeBotSessionPromptCommand(delivery.payload);
|
|
32282
|
+
await processDeliveredPrompt(
|
|
32283
|
+
delivery,
|
|
32284
|
+
command,
|
|
32285
|
+
true,
|
|
32286
|
+
(attemptId, executionSignal) => executeBotPrompt(
|
|
32287
|
+
outbox,
|
|
32288
|
+
publisher,
|
|
32289
|
+
command,
|
|
32290
|
+
config2,
|
|
32291
|
+
directories,
|
|
32292
|
+
audit,
|
|
32293
|
+
sessions,
|
|
32294
|
+
grants,
|
|
32295
|
+
contexts,
|
|
32296
|
+
applicator,
|
|
32297
|
+
ipc,
|
|
32298
|
+
attemptId,
|
|
32299
|
+
timer,
|
|
32300
|
+
executionSignal
|
|
32301
|
+
)
|
|
32302
|
+
);
|
|
32303
|
+
return;
|
|
32304
|
+
}
|
|
31472
32305
|
if (kind === SESSION_PROMPT_KIND) {
|
|
31473
|
-
|
|
32306
|
+
const command = decodeSessionPromptCommand(delivery.payload);
|
|
32307
|
+
await processDeliveredPrompt(
|
|
32308
|
+
delivery,
|
|
32309
|
+
command,
|
|
32310
|
+
command.disposition !== SessionPromptDisposition.Steer,
|
|
32311
|
+
(attemptId, executionSignal) => executePrompt(
|
|
32312
|
+
outbox,
|
|
32313
|
+
publisher,
|
|
32314
|
+
command,
|
|
32315
|
+
config2,
|
|
32316
|
+
directories,
|
|
32317
|
+
audit,
|
|
32318
|
+
sessions,
|
|
32319
|
+
attemptId,
|
|
32320
|
+
timer,
|
|
32321
|
+
executionSignal
|
|
32322
|
+
)
|
|
32323
|
+
);
|
|
31474
32324
|
return;
|
|
31475
32325
|
}
|
|
31476
32326
|
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
@@ -31508,6 +32358,8 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31508
32358
|
payloadSessionId = decodeSessionElicitationRespondCommand(delivery.payload).sessionId;
|
|
31509
32359
|
} else if (payloadKind === SESSION_PROMPT_KIND) {
|
|
31510
32360
|
payloadSessionId = decodeSessionPromptCommand(delivery.payload).sessionId;
|
|
32361
|
+
} else if (payloadKind === BOT_SESSION_PROMPT_KIND) {
|
|
32362
|
+
payloadSessionId = decodeBotSessionPromptCommand(delivery.payload).sessionId;
|
|
31511
32363
|
} else {
|
|
31512
32364
|
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
31513
32365
|
}
|
|
@@ -32105,7 +32957,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
32105
32957
|
}
|
|
32106
32958
|
publisher.recordAttempt(sessionId, payload, attemptId);
|
|
32107
32959
|
};
|
|
32108
|
-
const sessions = new AcpSessionManager(new DaemonAcpObserver(recordSessionEvent), sessionStore);
|
|
32960
|
+
const sessions = new AcpSessionManager(new DaemonAcpObserver(config2, recordSessionEvent), sessionStore);
|
|
32109
32961
|
const directories = new WorkspaceDirectoryService(config2.bindingId, config2.defaultWorkspace);
|
|
32110
32962
|
const installationObserver = new DaemonInstallationObserver();
|
|
32111
32963
|
const diagnostics = new RelayConnectionDiagnostics(audit, config2.channelId, config2.relayUrl);
|