@rivet-dev/agentos-core 0.2.5-rc.3 → 0.2.5-rc.4
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/README.md +4 -4
- package/dist/agent-os.d.ts +25 -28
- package/dist/agent-os.js +129 -403
- package/dist/agentos-package.d.ts +3 -3
- package/dist/agentos-package.js +7 -1
- package/dist/cron/types.d.ts +1 -1
- package/dist/default-software.d.ts +6 -46
- package/dist/default-software.js +7 -90
- package/dist/generated/AcpLimitsConfig.d.ts +4 -0
- package/dist/generated/AcpLimitsConfig.js +2 -0
- package/dist/generated/CreateVmConfig.d.ts +26 -0
- package/dist/generated/CreateVmConfig.js +1 -0
- package/dist/generated/FsPermissionRule.d.ts +6 -0
- package/dist/generated/FsPermissionRule.js +1 -0
- package/dist/generated/FsPermissionRuleSet.d.ts +6 -0
- package/dist/generated/FsPermissionRuleSet.js +1 -0
- package/dist/generated/FsPermissionScope.d.ts +3 -0
- package/dist/generated/FsPermissionScope.js +1 -0
- package/dist/generated/HttpLimitsConfig.d.ts +3 -0
- package/dist/generated/HttpLimitsConfig.js +2 -0
- package/dist/generated/JsModuleResolution.d.ts +1 -0
- package/dist/generated/JsModuleResolution.js +2 -0
- package/dist/generated/JsRuntimeConfig.d.ts +31 -0
- package/dist/generated/JsRuntimeConfig.js +1 -0
- package/dist/generated/JsRuntimeLimitsConfig.d.ts +11 -0
- package/dist/generated/JsRuntimeLimitsConfig.js +2 -0
- package/dist/generated/JsRuntimePlatform.d.ts +1 -0
- package/dist/generated/JsRuntimePlatform.js +2 -0
- package/dist/generated/MountPluginDescriptor.d.ts +4 -0
- package/dist/generated/MountPluginDescriptor.js +2 -0
- package/dist/generated/NativeRootFilesystemConfig.d.ts +5 -0
- package/dist/generated/NativeRootFilesystemConfig.js +1 -0
- package/dist/generated/PatternPermissionRule.d.ts +6 -0
- package/dist/generated/PatternPermissionRule.js +1 -0
- package/dist/generated/PatternPermissionRuleSet.d.ts +6 -0
- package/dist/generated/PatternPermissionRuleSet.js +1 -0
- package/dist/generated/PatternPermissionScope.d.ts +3 -0
- package/dist/generated/PatternPermissionScope.js +1 -0
- package/dist/generated/PermissionMode.d.ts +1 -0
- package/dist/generated/PermissionMode.js +2 -0
- package/dist/generated/PermissionsPolicy.d.ts +10 -0
- package/dist/generated/PermissionsPolicy.js +1 -0
- package/dist/generated/PluginLimitsConfig.d.ts +4 -0
- package/dist/generated/PluginLimitsConfig.js +2 -0
- package/dist/generated/PythonLimitsConfig.d.ts +6 -0
- package/dist/generated/PythonLimitsConfig.js +2 -0
- package/dist/generated/ResourceLimitsConfig.d.ts +24 -0
- package/dist/generated/ResourceLimitsConfig.js +2 -0
- package/dist/generated/RootFilesystemConfig.d.ts +9 -0
- package/dist/generated/RootFilesystemConfig.js +1 -0
- package/dist/generated/RootFilesystemEntry.d.ts +13 -0
- package/dist/generated/RootFilesystemEntry.js +1 -0
- package/dist/generated/RootFilesystemEntryEncoding.d.ts +1 -0
- package/dist/generated/RootFilesystemEntryEncoding.js +2 -0
- package/dist/generated/RootFilesystemEntryKind.d.ts +1 -0
- package/dist/generated/RootFilesystemEntryKind.js +2 -0
- package/dist/generated/RootFilesystemLowerDescriptor.d.ts +7 -0
- package/dist/generated/RootFilesystemLowerDescriptor.js +1 -0
- package/dist/generated/RootFilesystemMode.d.ts +1 -0
- package/dist/generated/RootFilesystemMode.js +2 -0
- package/dist/generated/ToolLimitsConfig.d.ts +10 -0
- package/dist/generated/ToolLimitsConfig.js +2 -0
- package/dist/generated/VmDnsConfig.d.ts +6 -0
- package/dist/generated/VmDnsConfig.js +2 -0
- package/dist/generated/VmLimitsConfig.d.ts +18 -0
- package/dist/generated/VmLimitsConfig.js +1 -0
- package/dist/generated/VmListenPolicyConfig.d.ts +5 -0
- package/dist/generated/VmListenPolicyConfig.js +2 -0
- package/dist/generated/WasmLimitsConfig.d.ts +7 -0
- package/dist/generated/WasmLimitsConfig.js +2 -0
- package/dist/host-dir-mount.d.ts +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/options-schema.d.ts +14 -1
- package/dist/options-schema.js +27 -21
- package/dist/packages.d.ts +2 -2
- package/dist/packages.js +20 -6
- package/dist/runtime-compat.d.ts +17 -4
- package/dist/runtime-compat.js +51 -88
- package/dist/runtime.d.ts +27 -0
- package/dist/sandbox.d.ts +112 -0
- package/dist/sandbox.js +264 -0
- package/dist/sidecar/agentos-protocol.d.ts +27 -1
- package/dist/sidecar/agentos-protocol.js +77 -20
- package/dist/sidecar/native-process-client.d.ts +5 -4
- package/dist/sidecar/native-process-client.js +4 -4
- package/dist/sidecar/permissions.d.ts +1 -1
- package/dist/sidecar/rpc-client.d.ts +21 -2
- package/dist/sidecar/rpc-client.js +113 -41
- package/dist/types.d.ts +7 -1
- package/package.json +34 -35
- package/dist/agents.d.ts +0 -79
- package/dist/agents.js +0 -48
package/dist/agent-os.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { existsSync,
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
3
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
5
4
|
import { join, posix as posixPath, resolve as resolveHostPath, } from "node:path";
|
|
6
5
|
import { fileURLToPath } from "node:url";
|
|
7
6
|
import { validateToolkits } from "./host-tools.js";
|
|
@@ -13,14 +12,6 @@ export { isAcpTimeoutErrorData } from "./json-rpc.js";
|
|
|
13
12
|
const ACP_PROTOCOL_VERSION = 1;
|
|
14
13
|
const ACP_EXTENSION_NAMESPACE = "dev.rivet.agent-os.acp";
|
|
15
14
|
const SHELL_DISPOSE_TIMEOUT_MS = 5_000;
|
|
16
|
-
/**
|
|
17
|
-
* Reserved `env` key on `AcpResumeSessionRequest` carrying the resolved adapter
|
|
18
|
-
* bin entrypoint. The resume wire request omits a dedicated `adapterEntrypoint`
|
|
19
|
-
* field; the sidecar reads the entrypoint from this key and strips it before
|
|
20
|
-
* launching the adapter. Must stay in sync with the sidecar constant of the same
|
|
21
|
-
* name in `crates/agentos-sidecar/src/acp_extension.rs`.
|
|
22
|
-
*/
|
|
23
|
-
const RESUME_ADAPTER_ENTRYPOINT_ENV = "AGENT_OS_RESUME_ADAPTER_ENTRYPOINT";
|
|
24
15
|
function defaultAcpClientCapabilities() {
|
|
25
16
|
return {
|
|
26
17
|
fs: {
|
|
@@ -45,12 +36,10 @@ import { getBaseEnvironment } from "./base-filesystem.js";
|
|
|
45
36
|
import { CronManager } from "./cron/cron-manager.js";
|
|
46
37
|
import { TimerScheduleDriver } from "./cron/timer-driver.js";
|
|
47
38
|
import { snapshotVirtualFilesystem, sortFilesystemEntries, } from "./filesystem-snapshot.js";
|
|
48
|
-
import { createHostDirBackend } from "./host-dir-mount.js";
|
|
49
39
|
import { serializeMountConfigForSidecar, } from "./js-bridge.js";
|
|
50
40
|
import { createSnapshotExport, } from "./layers.js";
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import { resolveDefaultSoftware, resolveDependencyAgents, } from "./default-software.js";
|
|
41
|
+
import { OPT_AGENTOS_ROOT, } from "./agentos-package.js";
|
|
42
|
+
import { resolveDefaultSoftware } from "./default-software.js";
|
|
54
43
|
import { allowAll } from "./runtime-compat.js";
|
|
55
44
|
import { AcpRuntimeKind, decodeAcpCallback, decodeAcpEvent, decodeAcpResponse, encodeAcpCallbackResponse, encodeAcpRequest, } from "./sidecar/agentos-protocol.js";
|
|
56
45
|
import { serializePermissionsForSidecar } from "./sidecar/permissions.js";
|
|
@@ -114,52 +103,27 @@ function toRecord(value) {
|
|
|
114
103
|
: {};
|
|
115
104
|
}
|
|
116
105
|
function normalizePackageRef(value) {
|
|
106
|
+
// The single package reference is `packagePath`: the packed `.aospkg` file
|
|
107
|
+
// (registry-built packages export `{ packagePath }`), or a package dir for
|
|
108
|
+
// local transition fixtures. A raw string is shorthand for the same path.
|
|
117
109
|
if (typeof value === "string") {
|
|
118
|
-
return {
|
|
110
|
+
return { path: value };
|
|
119
111
|
}
|
|
120
112
|
const record = toRecord(value);
|
|
121
|
-
if (typeof record.
|
|
122
|
-
return {
|
|
123
|
-
dir: record.packageDir,
|
|
124
|
-
legacyManifest: legacyPackageManifest(record),
|
|
125
|
-
};
|
|
113
|
+
if (typeof record.packagePath === "string") {
|
|
114
|
+
return { path: record.packagePath };
|
|
126
115
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
116
|
+
// Recognizably-legacy shapes fail loudly: silently dropping a software
|
|
117
|
+
// entry boots a VM with missing packages and no diagnostic.
|
|
118
|
+
for (const legacy of ["packageTar", "packageDir", "dir"]) {
|
|
119
|
+
if (typeof record[legacy] === "string") {
|
|
120
|
+
throw new Error(`agentOS package ref uses removed field "${legacy}" (value: ${JSON.stringify(record[legacy])}); ` +
|
|
121
|
+
"packages are referenced by a single `packagePath` — update the package " +
|
|
122
|
+
"(rebuild @agentos-software/* dependencies) or pass { packagePath }");
|
|
123
|
+
}
|
|
132
124
|
}
|
|
133
125
|
return undefined;
|
|
134
126
|
}
|
|
135
|
-
function legacyPackageManifest(record) {
|
|
136
|
-
if (typeof record.name !== "string") {
|
|
137
|
-
return undefined;
|
|
138
|
-
}
|
|
139
|
-
const manifest = { name: record.name };
|
|
140
|
-
const agent = toRecord(record.agent);
|
|
141
|
-
if (typeof agent.acpEntrypoint === "string") {
|
|
142
|
-
manifest.agent = {
|
|
143
|
-
acpEntrypoint: agent.acpEntrypoint,
|
|
144
|
-
...(isStringRecord(agent.env) ? { env: agent.env } : {}),
|
|
145
|
-
...(Array.isArray(agent.launchArgs) &&
|
|
146
|
-
agent.launchArgs.every((arg) => typeof arg === "string")
|
|
147
|
-
? { launchArgs: agent.launchArgs }
|
|
148
|
-
: {}),
|
|
149
|
-
...(typeof agent.snapshot === "boolean" ? { snapshot: agent.snapshot } : {}),
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
return manifest;
|
|
153
|
-
}
|
|
154
|
-
function readPackageManifestForClient(ref) {
|
|
155
|
-
return tryReadAgentosPackageManifest(ref.dir) ?? ref.legacyManifest;
|
|
156
|
-
}
|
|
157
|
-
function isStringRecord(value) {
|
|
158
|
-
return (value !== null &&
|
|
159
|
-
typeof value === "object" &&
|
|
160
|
-
!Array.isArray(value) &&
|
|
161
|
-
Object.values(value).every((entry) => typeof entry === "string"));
|
|
162
|
-
}
|
|
163
127
|
function parseAcpJson(value, context) {
|
|
164
128
|
if (value === null) {
|
|
165
129
|
return undefined;
|
|
@@ -475,7 +439,6 @@ const RUNTIME_BOOTSTRAP_COMMANDS = [
|
|
|
475
439
|
"python",
|
|
476
440
|
"python3",
|
|
477
441
|
];
|
|
478
|
-
const KERNEL_COMMAND_STUB = "#!/bin/sh\n# kernel command stub\n";
|
|
479
442
|
const REPO_ROOT = fileURLToPath(new URL("../../..", import.meta.url));
|
|
480
443
|
const SIDECAR_BINARY = join(REPO_ROOT, "target/debug/agentos-sidecar");
|
|
481
444
|
const SIDECAR_BUILD_INPUTS = [
|
|
@@ -515,7 +478,7 @@ function findBootstrapSeedEntry(config, path) {
|
|
|
515
478
|
const meta = KERNEL_POSIX_BOOTSTRAP_DIR_METADATA[path];
|
|
516
479
|
return meta ? { path, type: "directory", ...meta } : undefined;
|
|
517
480
|
}
|
|
518
|
-
function createKernelBootstrapLower(config,
|
|
481
|
+
function createKernelBootstrapLower(config, extraEntries = []) {
|
|
519
482
|
const includesBundledBaseLayer = !(config?.disableDefaultBaseLayer ?? false);
|
|
520
483
|
const existingPaths = collectConfiguredLowerPaths(config);
|
|
521
484
|
const entries = [
|
|
@@ -557,22 +520,6 @@ function createKernelBootstrapLower(config, commandNames, extraEntries = []) {
|
|
|
557
520
|
encoding: "base64",
|
|
558
521
|
});
|
|
559
522
|
}
|
|
560
|
-
const uniqueCommands = [...new Set(commandNames)].sort((a, b) => a.localeCompare(b));
|
|
561
|
-
for (const command of uniqueCommands) {
|
|
562
|
-
const stubPath = `/bin/${command}`;
|
|
563
|
-
if (existingPaths.has(stubPath)) {
|
|
564
|
-
continue;
|
|
565
|
-
}
|
|
566
|
-
entries.push({
|
|
567
|
-
path: stubPath,
|
|
568
|
-
type: "file",
|
|
569
|
-
mode: "755",
|
|
570
|
-
uid: 0,
|
|
571
|
-
gid: 0,
|
|
572
|
-
content: KERNEL_COMMAND_STUB,
|
|
573
|
-
encoding: "utf8",
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
523
|
for (const entry of sortFilesystemEntries(extraEntries)) {
|
|
577
524
|
if (existingPaths.has(entry.path)) {
|
|
578
525
|
continue;
|
|
@@ -769,28 +716,10 @@ function collectSidecarMountPlan(options) {
|
|
|
769
716
|
}
|
|
770
717
|
pushMount(mount);
|
|
771
718
|
}
|
|
772
|
-
if (options.shimDir) {
|
|
773
|
-
pushMount({
|
|
774
|
-
path: "/usr/local/bin",
|
|
775
|
-
plugin: createHostDirBackend({
|
|
776
|
-
hostPath: options.shimDir,
|
|
777
|
-
readOnly: true,
|
|
778
|
-
}),
|
|
779
|
-
readOnly: true,
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
719
|
hostMounts.sort((left, right) => right.vmPath.length - left.vmPath.length);
|
|
783
720
|
hostPathMappings.sort((left, right) => right.vmPath.length - left.vmPath.length);
|
|
784
721
|
return { sidecarMounts, hostMounts, hostPathMappings };
|
|
785
722
|
}
|
|
786
|
-
function materializeToolShimDir(toolKits) {
|
|
787
|
-
const shimDir = mkdtempSync(join(tmpdir(), "agentos-host-tools-shims-"));
|
|
788
|
-
writeFileSync(join(shimDir, "agentos"), KERNEL_COMMAND_STUB, { mode: 0o755 });
|
|
789
|
-
for (const toolKit of toolKits) {
|
|
790
|
-
writeFileSync(join(shimDir, `agentos-${toolKit.name}`), KERNEL_COMMAND_STUB, { mode: 0o755 });
|
|
791
|
-
}
|
|
792
|
-
return shimDir;
|
|
793
|
-
}
|
|
794
723
|
function collectToolkitBootstrapCommands(toolKits) {
|
|
795
724
|
if (toolKits.length === 0) {
|
|
796
725
|
return [];
|
|
@@ -1465,12 +1394,9 @@ export class AgentOs {
|
|
|
1465
1394
|
_closedShellIds = new BoundedSet(CLOSED_SHELL_ID_RETENTION_LIMIT);
|
|
1466
1395
|
_pendingShellExitPromises = new Set();
|
|
1467
1396
|
_shellCounter = 0;
|
|
1468
|
-
/** Command names linked into `/opt/agentos/bin` at runtime (via the sidecar). */
|
|
1469
|
-
_linkedCommands = new Set();
|
|
1470
1397
|
_acpTerminals = new Map();
|
|
1471
1398
|
_acpTerminalCounter = 0;
|
|
1472
1399
|
_softwareRoots;
|
|
1473
|
-
_softwareAgentConfigs;
|
|
1474
1400
|
_cronManager;
|
|
1475
1401
|
_toolKits = [];
|
|
1476
1402
|
_toolReference = "";
|
|
@@ -1487,11 +1413,10 @@ export class AgentOs {
|
|
|
1487
1413
|
_agentStderrHandler;
|
|
1488
1414
|
_agentExitHandler;
|
|
1489
1415
|
_limitWarningHandler;
|
|
1490
|
-
constructor(kernel, sidecar, softwareRoots,
|
|
1416
|
+
constructor(kernel, sidecar, softwareRoots, hostMounts, env, rootFilesystem, sidecarClient, sidecarSession, sidecarVm, additionalInstructions, agentStderrHandler, agentExitHandler, limitWarningHandler) {
|
|
1491
1417
|
this.#kernel = kernel;
|
|
1492
1418
|
this.sidecar = sidecar;
|
|
1493
1419
|
this._softwareRoots = softwareRoots;
|
|
1494
|
-
this._softwareAgentConfigs = softwareAgentConfigs;
|
|
1495
1420
|
this._hostMounts = hostMounts;
|
|
1496
1421
|
this._env = env;
|
|
1497
1422
|
this._rootFilesystem = rootFilesystem;
|
|
@@ -1527,38 +1452,32 @@ export class AgentOs {
|
|
|
1527
1452
|
// VM on first use, so agent closures (and pi's V8 snapshot bundle) only
|
|
1528
1453
|
// enter VMs that run them. Unbuilt packages throw with build
|
|
1529
1454
|
// instructions; opt out via defaultSoftware: false.
|
|
1530
|
-
const defaultSoftware = options?.defaultSoftware === false ? [] :
|
|
1455
|
+
const defaultSoftware = options?.defaultSoftware === false ? [] : resolveDefaultSoftware();
|
|
1531
1456
|
const software = options?.defaultSoftware === false
|
|
1532
1457
|
? (options.software ?? [])
|
|
1533
1458
|
: [...defaultSoftware, ...(options?.software ?? [])];
|
|
1534
|
-
//
|
|
1535
|
-
// `
|
|
1536
|
-
//
|
|
1459
|
+
// Packages are projected by the SIDECAR: the client forwards only the
|
|
1460
|
+
// package `path` over `configureVm` and the sidecar reads metadata from
|
|
1461
|
+
// the packed vbare manifest (chunk1 of the `.aospkg`).
|
|
1537
1462
|
const flatSoftware = software.flat();
|
|
1538
|
-
|
|
1463
|
+
// Honor the AgentOsOptions.defaultSoftware contract ("entries already present
|
|
1464
|
+
// in `software` are not duplicated"): the default bundle and an explicitly
|
|
1465
|
+
// passed one resolve to the same package paths, so dedup by path. Without
|
|
1466
|
+
// this the sidecar rejects the second projection with a duplicate-command
|
|
1467
|
+
// error (e.g. coreutils' `[`).
|
|
1468
|
+
const seenPackagePaths = new Set();
|
|
1469
|
+
const sidecarPackages = flatSoftware.flatMap((entry) => {
|
|
1539
1470
|
const ref = normalizePackageRef(entry);
|
|
1540
|
-
|
|
1471
|
+
if (!ref || seenPackagePaths.has(ref.path)) {
|
|
1472
|
+
return [];
|
|
1473
|
+
}
|
|
1474
|
+
seenPackagePaths.add(ref.path);
|
|
1475
|
+
return [{ path: ref.path }];
|
|
1541
1476
|
});
|
|
1542
|
-
const sidecarPackages = packageRefs.map((ref) => ({ dir: ref.dir }));
|
|
1543
1477
|
// All package software is projected into `/opt/agentos` by the sidecar. The
|
|
1544
|
-
// client stages nothing host-side
|
|
1545
|
-
|
|
1546
|
-
//
|
|
1547
|
-
// launches via `/opt/agentos/bin/<acpEntrypoint>`. The wire no longer
|
|
1548
|
-
// carries agent metadata; read it from the package manifest.
|
|
1549
|
-
for (const ref of packageRefs) {
|
|
1550
|
-
const manifest = readPackageManifestForClient(ref);
|
|
1551
|
-
if (!manifest?.agent)
|
|
1552
|
-
continue;
|
|
1553
|
-
agentConfigs.set(manifest.name, {
|
|
1554
|
-
adapterEntrypoint: `${OPT_AGENTOS_BIN}/${manifest.agent.acpEntrypoint}`,
|
|
1555
|
-
launchArgs: manifest.agent.launchArgs,
|
|
1556
|
-
defaultEnv: manifest.agent.env,
|
|
1557
|
-
});
|
|
1558
|
-
}
|
|
1559
|
-
// Agent-SDK snapshot bundle (loaded once per sidecar into the V8 startup
|
|
1560
|
-
// snapshot, reused across sessions) for any snapshot-enabled agent.
|
|
1561
|
-
const snapshotUserlandCode = resolveAgentSnapshotBundle(packageRefs.map((ref) => ({ packageDir: ref.dir })));
|
|
1478
|
+
// client stages nothing host-side and parses NO package manifests: the
|
|
1479
|
+
// sidecar owns agent resolution, agent enumeration, and agent snapshot
|
|
1480
|
+
// bundle loading from the projected package dirs.
|
|
1562
1481
|
const localMounts = await resolveCompatLocalMounts(options?.mounts);
|
|
1563
1482
|
const toolKits = options?.toolKits;
|
|
1564
1483
|
if (toolKits && toolKits.length > 0) {
|
|
@@ -1573,81 +1492,32 @@ export class AgentOs {
|
|
|
1573
1492
|
// runtime `linkSoftware` appends to that live dir). The client no longer
|
|
1574
1493
|
// stages packages host-side.
|
|
1575
1494
|
const toolBootstrapCommands = collectToolkitBootstrapCommands(toolKits ?? []);
|
|
1576
|
-
const
|
|
1495
|
+
const bootstrapCommands = [
|
|
1496
|
+
...RUNTIME_BOOTSTRAP_COMMANDS,
|
|
1497
|
+
...toolBootstrapCommands,
|
|
1498
|
+
];
|
|
1499
|
+
const bootstrapLower = createKernelBootstrapLower(options?.rootFilesystem);
|
|
1577
1500
|
let toolReference = "";
|
|
1578
1501
|
let rootBridge = null;
|
|
1579
1502
|
let kernel = null;
|
|
1580
1503
|
let client = null;
|
|
1581
1504
|
let createdNativeVm = null;
|
|
1582
1505
|
let nativeSession = null;
|
|
1583
|
-
let toolShimDir = null;
|
|
1584
1506
|
let cleanedUp = false;
|
|
1585
1507
|
const cleanup = async () => {
|
|
1586
1508
|
if (cleanedUp) {
|
|
1587
1509
|
return;
|
|
1588
1510
|
}
|
|
1589
1511
|
cleanedUp = true;
|
|
1590
|
-
if (toolShimDir) {
|
|
1591
|
-
rmSync(toolShimDir, { recursive: true, force: true });
|
|
1592
|
-
toolShimDir = null;
|
|
1593
|
-
}
|
|
1594
1512
|
};
|
|
1595
1513
|
try {
|
|
1596
1514
|
const env = getBaseEnvironment();
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
// Guest command paths. The sidecar owns the `/opt/agentos` projection,
|
|
1601
|
-
// but the client's command map (rpc-client) still needs to KNOW the
|
|
1602
|
-
// projected command names so its shell-exec guard (`this.commands.has("sh")`)
|
|
1603
|
-
// and wasmvm routing work. Seed each projected package's commands from its
|
|
1604
|
-
// `bin` map (mirroring the sidecar projection's command derivation), mapped
|
|
1605
|
-
// to their projected `/opt/agentos/bin/<cmd>` path. Tool-shim commands are
|
|
1606
|
-
// added below.
|
|
1515
|
+
// Guest command paths. The sidecar owns the `/opt/agentos` projection and
|
|
1516
|
+
// reports the exact projected package commands after `configureVm`.
|
|
1517
|
+
// Tool-shim commands are added below.
|
|
1607
1518
|
const commandGuestPaths = new Map();
|
|
1608
|
-
const deriveProjectedCommandNames = (dir) => {
|
|
1609
|
-
try {
|
|
1610
|
-
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
1611
|
-
if (pkg.bin && typeof pkg.bin === "object") {
|
|
1612
|
-
return Object.keys(pkg.bin);
|
|
1613
|
-
}
|
|
1614
|
-
if (typeof pkg.bin === "string") {
|
|
1615
|
-
const base = pkg.name?.split("/").pop();
|
|
1616
|
-
if (base)
|
|
1617
|
-
return [base];
|
|
1618
|
-
}
|
|
1619
|
-
}
|
|
1620
|
-
catch {
|
|
1621
|
-
// no/invalid package.json — fall through to the bin/ scan
|
|
1622
|
-
}
|
|
1623
|
-
try {
|
|
1624
|
-
return readdirSync(join(dir, "bin"));
|
|
1625
|
-
}
|
|
1626
|
-
catch {
|
|
1627
|
-
return [];
|
|
1628
|
-
}
|
|
1629
|
-
};
|
|
1630
|
-
for (const ref of packageRefs) {
|
|
1631
|
-
for (const cmd of deriveProjectedCommandNames(ref.dir)) {
|
|
1632
|
-
commandGuestPaths.set(cmd, `/opt/agentos/bin/${cmd}`);
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
const requestedMounts = options?.moduleAccessCwd
|
|
1636
|
-
? [
|
|
1637
|
-
...(options.mounts ?? []),
|
|
1638
|
-
{
|
|
1639
|
-
path: "/root/node_modules",
|
|
1640
|
-
plugin: createHostDirBackend({
|
|
1641
|
-
hostPath: join(options.moduleAccessCwd, "node_modules"),
|
|
1642
|
-
readOnly: true,
|
|
1643
|
-
}),
|
|
1644
|
-
readOnly: true,
|
|
1645
|
-
},
|
|
1646
|
-
]
|
|
1647
|
-
: options?.mounts;
|
|
1648
1519
|
const { sidecarMounts, hostMounts, hostPathMappings } = collectSidecarMountPlan({
|
|
1649
|
-
mounts:
|
|
1650
|
-
shimDir: toolShimDir,
|
|
1520
|
+
mounts: options?.mounts,
|
|
1651
1521
|
});
|
|
1652
1522
|
// Reuse the sidecar handle's single shared native process; this VM
|
|
1653
1523
|
// becomes another tenant of it rather than spawning its own process.
|
|
@@ -1666,6 +1536,7 @@ export class AgentOs {
|
|
|
1666
1536
|
permissions: sidecarPermissions,
|
|
1667
1537
|
limits: options?.limits,
|
|
1668
1538
|
loopbackExemptPorts: options?.loopbackExemptPorts ?? [],
|
|
1539
|
+
bootstrapCommands,
|
|
1669
1540
|
// 0.3: the Node builtin allow-list moved from configureVm to
|
|
1670
1541
|
// VM creation. `undefined` => engine default allow-list;
|
|
1671
1542
|
// `[]` => deny all; `[..]` => exactly those. Platform and
|
|
@@ -1673,8 +1544,7 @@ export class AgentOs {
|
|
|
1673
1544
|
// emulation), matching the prior behavior where Agent OS only
|
|
1674
1545
|
// constrained the builtin allow-list.
|
|
1675
1546
|
...(options?.allowedNodeBuiltins !== undefined ||
|
|
1676
|
-
options?.highResolutionTime !== undefined
|
|
1677
|
-
snapshotUserlandCode !== undefined
|
|
1547
|
+
options?.highResolutionTime !== undefined
|
|
1678
1548
|
? {
|
|
1679
1549
|
jsRuntime: {
|
|
1680
1550
|
platform: "node",
|
|
@@ -1685,9 +1555,6 @@ export class AgentOs {
|
|
|
1685
1555
|
...(options?.highResolutionTime !== undefined
|
|
1686
1556
|
? { highResolutionTime: options.highResolutionTime }
|
|
1687
1557
|
: {}),
|
|
1688
|
-
...(snapshotUserlandCode !== undefined
|
|
1689
|
-
? { snapshotUserlandCode }
|
|
1690
|
-
: {}),
|
|
1691
1558
|
},
|
|
1692
1559
|
}
|
|
1693
1560
|
: {}),
|
|
@@ -1703,14 +1570,18 @@ export class AgentOs {
|
|
|
1703
1570
|
event.payload.state === "ready" &&
|
|
1704
1571
|
event.ownership.scope === "vm" &&
|
|
1705
1572
|
event.ownership.vm_id === nativeVm.vmId, 10_000);
|
|
1706
|
-
await client.configureVm(session, nativeVm, {
|
|
1573
|
+
const configuredVm = await client.configureVm(session, nativeVm, {
|
|
1707
1574
|
mounts: sidecarMounts,
|
|
1708
1575
|
permissions: sidecarPermissions,
|
|
1709
1576
|
commandPermissions: {},
|
|
1710
1577
|
loopbackExemptPorts: options?.loopbackExemptPorts,
|
|
1711
1578
|
packages: sidecarPackages,
|
|
1712
1579
|
packagesMountAt: OPT_AGENTOS_ROOT,
|
|
1580
|
+
toolShimCommands: toolBootstrapCommands,
|
|
1713
1581
|
});
|
|
1582
|
+
for (const command of configuredVm.projectedCommands) {
|
|
1583
|
+
commandGuestPaths.set(command.name, command.guestPath);
|
|
1584
|
+
}
|
|
1714
1585
|
if (toolKits && toolKits.length > 0) {
|
|
1715
1586
|
toolReference = await registerToolkitsOnSidecar(client, session, nativeVm, toolKits);
|
|
1716
1587
|
commandGuestPaths.set("agentos", "/bin/agentos");
|
|
@@ -1796,7 +1667,7 @@ export class AgentOs {
|
|
|
1796
1667
|
createVm: async () => createVmAdmin(),
|
|
1797
1668
|
});
|
|
1798
1669
|
const vmAdmin = sidecarLease.admin;
|
|
1799
|
-
const vm = new AgentOs(vmAdmin.kernel, sidecar, [],
|
|
1670
|
+
const vm = new AgentOs(vmAdmin.kernel, sidecar, [], vmAdmin.hostMounts, vmAdmin.env, vmAdmin.rootView, vmAdmin.sidecarClient, vmAdmin.sidecarSession, vmAdmin.sidecarVm, options?.additionalInstructions, options?.onAgentStderr ?? defaultAgentStderrHandler, options?.onAgentExit ?? defaultAgentExitHandler, options?.onLimitWarning);
|
|
1800
1671
|
vm._sidecarLease = sidecarLease;
|
|
1801
1672
|
vm._toolKits = vmAdmin.toolKits;
|
|
1802
1673
|
vm._toolReference = vmAdmin.toolReference;
|
|
@@ -1933,35 +1804,6 @@ export class AgentOs {
|
|
|
1933
1804
|
_vfs() {
|
|
1934
1805
|
return this.#kernel.vfs;
|
|
1935
1806
|
}
|
|
1936
|
-
async _copyPath(from, to) {
|
|
1937
|
-
const stat = await this._vfs().lstat(from);
|
|
1938
|
-
if (stat.isSymbolicLink) {
|
|
1939
|
-
const target = await this._vfs().readlink(from);
|
|
1940
|
-
await this._vfs().symlink(target, to);
|
|
1941
|
-
return;
|
|
1942
|
-
}
|
|
1943
|
-
if (stat.isDirectory) {
|
|
1944
|
-
await this._mkdirp(posixPath.dirname(to));
|
|
1945
|
-
if (!(await this.#kernel.exists(to))) {
|
|
1946
|
-
await this.#kernel.mkdir(to);
|
|
1947
|
-
}
|
|
1948
|
-
await this._vfs().chmod(to, stat.mode);
|
|
1949
|
-
await this._vfs().chown(to, stat.uid, stat.gid);
|
|
1950
|
-
const entries = await this.#kernel.readdir(from);
|
|
1951
|
-
for (const entry of entries) {
|
|
1952
|
-
if (entry === "." || entry === "..")
|
|
1953
|
-
continue;
|
|
1954
|
-
const fromPath = from === "/" ? `/${entry}` : `${from}/${entry}`;
|
|
1955
|
-
const toPath = to === "/" ? `/${entry}` : `${to}/${entry}`;
|
|
1956
|
-
await this._copyPath(fromPath, toPath);
|
|
1957
|
-
}
|
|
1958
|
-
return;
|
|
1959
|
-
}
|
|
1960
|
-
const content = await this.#kernel.readFile(from);
|
|
1961
|
-
await this.writeFile(to, content);
|
|
1962
|
-
await this._vfs().chmod(to, stat.mode);
|
|
1963
|
-
await this._vfs().chown(to, stat.uid, stat.gid);
|
|
1964
|
-
}
|
|
1965
1807
|
async readFile(path) {
|
|
1966
1808
|
this._assertSafeAbsolutePath(path);
|
|
1967
1809
|
return this.#kernel.readFile(path);
|
|
@@ -2035,49 +1877,31 @@ export class AgentOs {
|
|
|
2035
1877
|
}
|
|
2036
1878
|
async readdirRecursive(path, options) {
|
|
2037
1879
|
this._assertSafeAbsolutePath(path);
|
|
2038
|
-
const maxDepth = options?.maxDepth;
|
|
2039
1880
|
const exclude = options?.exclude ? new Set(options.exclude) : undefined;
|
|
1881
|
+
const entries = await this.#kernel.readdirRecursive(path, {
|
|
1882
|
+
maxDepth: options?.maxDepth,
|
|
1883
|
+
});
|
|
1884
|
+
const excludedPrefixes = [];
|
|
2040
1885
|
const results = [];
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
if (
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
const entries = await this.#kernel.readdir(dirPath);
|
|
2049
|
-
for (const name of entries) {
|
|
2050
|
-
if (name === "." || name === "..")
|
|
2051
|
-
continue;
|
|
2052
|
-
if (exclude?.has(name))
|
|
2053
|
-
continue;
|
|
2054
|
-
const fullPath = dirPath === "/" ? `/${name}` : `${dirPath}/${name}`;
|
|
2055
|
-
const s = await this.#kernel.stat(fullPath);
|
|
2056
|
-
if (s.isSymbolicLink) {
|
|
2057
|
-
results.push({
|
|
2058
|
-
path: fullPath,
|
|
2059
|
-
type: "symlink",
|
|
2060
|
-
size: s.size,
|
|
2061
|
-
});
|
|
2062
|
-
}
|
|
2063
|
-
else if (s.isDirectory) {
|
|
2064
|
-
results.push({
|
|
2065
|
-
path: fullPath,
|
|
2066
|
-
type: "directory",
|
|
2067
|
-
size: s.size,
|
|
2068
|
-
});
|
|
2069
|
-
if (maxDepth === undefined || depth < maxDepth) {
|
|
2070
|
-
queue.push([fullPath, depth + 1]);
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
|
-
else {
|
|
2074
|
-
results.push({
|
|
2075
|
-
path: fullPath,
|
|
2076
|
-
type: "file",
|
|
2077
|
-
size: s.size,
|
|
2078
|
-
});
|
|
1886
|
+
for (const entry of entries) {
|
|
1887
|
+
if (excludedPrefixes.some((prefix) => entry.path === prefix || entry.path.startsWith(`${prefix}/`))) {
|
|
1888
|
+
continue;
|
|
1889
|
+
}
|
|
1890
|
+
if (exclude?.has(entry.name)) {
|
|
1891
|
+
if (entry.isDirectory && !entry.isSymbolicLink) {
|
|
1892
|
+
excludedPrefixes.push(entry.path);
|
|
2079
1893
|
}
|
|
1894
|
+
continue;
|
|
2080
1895
|
}
|
|
1896
|
+
results.push({
|
|
1897
|
+
path: entry.path,
|
|
1898
|
+
type: entry.isSymbolicLink
|
|
1899
|
+
? "symlink"
|
|
1900
|
+
: entry.isDirectory
|
|
1901
|
+
? "directory"
|
|
1902
|
+
: "file",
|
|
1903
|
+
size: entry.size,
|
|
1904
|
+
});
|
|
2081
1905
|
}
|
|
2082
1906
|
return results;
|
|
2083
1907
|
}
|
|
@@ -2105,30 +1929,15 @@ export class AgentOs {
|
|
|
2105
1929
|
this.#kernel.unmountFs(path);
|
|
2106
1930
|
}
|
|
2107
1931
|
async move(from, to) {
|
|
2108
|
-
this.
|
|
2109
|
-
this.
|
|
2110
|
-
|
|
2111
|
-
if (!sourceStat.isDirectory || sourceStat.isSymbolicLink) {
|
|
2112
|
-
return this.#kernel.rename(from, to);
|
|
2113
|
-
}
|
|
2114
|
-
await this._copyPath(from, to);
|
|
2115
|
-
await this.delete(from, { recursive: true });
|
|
1932
|
+
this._assertWritableAbsolutePath(from);
|
|
1933
|
+
this._assertWritableAbsolutePath(to);
|
|
1934
|
+
await this.#kernel.movePath(from, to);
|
|
2116
1935
|
}
|
|
2117
1936
|
async delete(path, options) {
|
|
2118
|
-
this.
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
const entries = await this.#kernel.readdir(path);
|
|
2123
|
-
for (const entry of entries) {
|
|
2124
|
-
if (entry === "." || entry === "..")
|
|
2125
|
-
continue;
|
|
2126
|
-
await this.delete(`${path}/${entry}`, { recursive: true });
|
|
2127
|
-
}
|
|
2128
|
-
}
|
|
2129
|
-
return this.#kernel.removeDir(path);
|
|
2130
|
-
}
|
|
2131
|
-
return this.#kernel.removeFile(path);
|
|
1937
|
+
this._assertWritableAbsolutePath(path);
|
|
1938
|
+
await this.#kernel.removePath(path, {
|
|
1939
|
+
recursive: options?.recursive ?? false,
|
|
1940
|
+
});
|
|
2132
1941
|
}
|
|
2133
1942
|
async fetch(port, request) {
|
|
2134
1943
|
const url = new URL(request.url);
|
|
@@ -2359,78 +2168,39 @@ export class AgentOs {
|
|
|
2359
2168
|
// appends the package to its live host-backed staging dir; the commands
|
|
2360
2169
|
// appear under `/opt/agentos/bin` immediately. The sidecar rejects a
|
|
2361
2170
|
// duplicate command, surfaced here as a thrown error.
|
|
2362
|
-
const commands = await this._sidecarClient.linkPackage(this._sidecarSession, this._sidecarVm, {
|
|
2363
|
-
|
|
2364
|
-
this.
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
this._softwareAgentConfigs.set(manifest.name, {
|
|
2369
|
-
adapterEntrypoint: `${OPT_AGENTOS_BIN}/${manifest.agent.acpEntrypoint}`,
|
|
2370
|
-
launchArgs: manifest.agent.launchArgs,
|
|
2371
|
-
defaultEnv: manifest.agent.env,
|
|
2372
|
-
});
|
|
2171
|
+
const commands = await this._sidecarClient.linkPackage(this._sidecarSession, this._sidecarVm, { path: ref.path });
|
|
2172
|
+
if (this.#kernel instanceof NativeSidecarKernelProxy) {
|
|
2173
|
+
this.#kernel.registerCommandGuestPaths(new Map(commands.projectedCommands.map((command) => [
|
|
2174
|
+
command.name,
|
|
2175
|
+
command.guestPath,
|
|
2176
|
+
])));
|
|
2373
2177
|
}
|
|
2178
|
+
// The client parses no manifests: an `agent` block in the linked package is
|
|
2179
|
+
// picked up by the sidecar (it owns the projected `/opt/agentos` and answers
|
|
2180
|
+
// createSession/listAgents from it). Nothing to record client-side.
|
|
2374
2181
|
}
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
// An `/opt/agentos` agent package is materialized into the VM at
|
|
2398
|
-
// boot, so it is always "installed" — its adapter is a real command.
|
|
2399
|
-
if (config.adapterEntrypoint || !config.acpAdapter) {
|
|
2400
|
-
return {
|
|
2401
|
-
id,
|
|
2402
|
-
adapterEntrypoint: config.adapterEntrypoint,
|
|
2403
|
-
installed: true,
|
|
2404
|
-
};
|
|
2405
|
-
}
|
|
2406
|
-
let installed = false;
|
|
2407
|
-
try {
|
|
2408
|
-
// Check the software roots that provide this adapter package.
|
|
2409
|
-
const vmPrefix = `/root/node_modules/${config.acpAdapter}`;
|
|
2410
|
-
let hostPkgJsonPath = null;
|
|
2411
|
-
for (const root of this._softwareRoots) {
|
|
2412
|
-
if (root.vmPath === vmPrefix) {
|
|
2413
|
-
hostPkgJsonPath = join(root.hostPath, "package.json");
|
|
2414
|
-
break;
|
|
2415
|
-
}
|
|
2416
|
-
}
|
|
2417
|
-
if (!hostPkgJsonPath) {
|
|
2418
|
-
throw new Error("no package source");
|
|
2419
|
-
}
|
|
2420
|
-
readFileSync(hostPkgJsonPath);
|
|
2421
|
-
installed = true;
|
|
2422
|
-
}
|
|
2423
|
-
catch {
|
|
2424
|
-
// Package not installed
|
|
2425
|
-
}
|
|
2426
|
-
return {
|
|
2427
|
-
id,
|
|
2428
|
-
acpAdapter: config.acpAdapter,
|
|
2429
|
-
agentPackage: config.agentPackage,
|
|
2430
|
-
installed,
|
|
2431
|
-
};
|
|
2432
|
-
})
|
|
2433
|
-
.filter((entry) => entry !== null);
|
|
2182
|
+
async providedCommands() {
|
|
2183
|
+
return this._sidecarClient.providedCommands(this._sidecarSession, this._sidecarVm);
|
|
2184
|
+
}
|
|
2185
|
+
/**
|
|
2186
|
+
* Returns all registered agents with their installation status. Thin forwarder:
|
|
2187
|
+
* sends `AcpListAgentsRequest` and maps the response. The sidecar enumerates the
|
|
2188
|
+
* projected `/opt/agentos` packages (the client parses no manifests). Every such
|
|
2189
|
+
* agent is a package materialized into the VM, so `installed` is always `true`.
|
|
2190
|
+
*/
|
|
2191
|
+
async listAgents() {
|
|
2192
|
+
const response = await this._sendAcpRequest({
|
|
2193
|
+
tag: "AcpListAgentsRequest",
|
|
2194
|
+
val: { reserved: false },
|
|
2195
|
+
});
|
|
2196
|
+
if (response.tag !== "AcpListAgentsResponse") {
|
|
2197
|
+
throw new Error(`unexpected list_agents response: ${response.tag}`);
|
|
2198
|
+
}
|
|
2199
|
+
return response.val.agents.map((agent) => ({
|
|
2200
|
+
id: agent.id,
|
|
2201
|
+
installed: agent.installed,
|
|
2202
|
+
adapterEntrypoint: agent.adapterEntrypoint,
|
|
2203
|
+
}));
|
|
2434
2204
|
}
|
|
2435
2205
|
_syncSessionState(session, state) {
|
|
2436
2206
|
session.processId = state.processId;
|
|
@@ -2913,42 +2683,21 @@ export class AgentOs {
|
|
|
2913
2683
|
this._syncSessionState(session, state);
|
|
2914
2684
|
}
|
|
2915
2685
|
async createSession(agentType, options) {
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
if (dependencyAgent) {
|
|
2925
|
-
await this.linkSoftware({ packageDir: dependencyAgent.packageDir });
|
|
2926
|
-
config = this._resolveAgentConfig(agentType);
|
|
2927
|
-
}
|
|
2928
|
-
}
|
|
2929
|
-
if (!config) {
|
|
2930
|
-
throw new Error(`Unknown agent type: ${agentType}`);
|
|
2931
|
-
}
|
|
2932
|
-
// System-prompt assembly and injection (launch args / OPENCODE_CONTEXTPATHS) are owned by
|
|
2933
|
-
// the sidecar at AcpCreateSessionRequest. The host only forwards additionalInstructions /
|
|
2934
|
-
// skipOsInstructions plus the agent's static launch args and env.
|
|
2935
|
-
const launchArgs = [...(config.launchArgs ?? [])];
|
|
2936
|
-
const launchEnv = { ...config.defaultEnv, ...options?.env };
|
|
2686
|
+
// The client is npm-agnostic: it sends only the agent NAME. The sidecar
|
|
2687
|
+
// resolves the name -> package -> entrypoint/env/launchArgs from the
|
|
2688
|
+
// projected `/opt/agentos/<name>/current/agentos-package.json` and spawns
|
|
2689
|
+
// (including the agent's static launch args and manifest env defaults).
|
|
2690
|
+
// System-prompt assembly/injection (launch args / OPENCODE_CONTEXTPATHS) is
|
|
2691
|
+
// owned by the sidecar; the host only forwards additionalInstructions /
|
|
2692
|
+
// skipOsInstructions plus the caller's env.
|
|
2693
|
+
const launchEnv = { ...options?.env };
|
|
2937
2694
|
const sessionCwd = options?.cwd ?? "/workspace";
|
|
2938
|
-
// Every agent is an `/opt/agentos` package now: the config carries a
|
|
2939
|
-
// pre-resolved guest command path (`adapterEntrypoint`) that the sidecar
|
|
2940
|
-
// spawns directly. There is no npm adapter resolution.
|
|
2941
|
-
const adapterEntrypoint = config.adapterEntrypoint;
|
|
2942
|
-
if (!adapterEntrypoint) {
|
|
2943
|
-
throw new Error(`agent "${String(agentType)}" config has no adapterEntrypoint`);
|
|
2944
|
-
}
|
|
2945
2695
|
const response = await this._sendAcpRequest({
|
|
2946
2696
|
tag: "AcpCreateSessionRequest",
|
|
2947
2697
|
val: {
|
|
2948
2698
|
agentType: String(agentType),
|
|
2949
2699
|
runtime: AcpRuntimeKind.JavaScript,
|
|
2950
|
-
|
|
2951
|
-
args: launchArgs,
|
|
2700
|
+
args: [],
|
|
2952
2701
|
env: new Map(Object.entries(launchEnv)),
|
|
2953
2702
|
cwd: sessionCwd,
|
|
2954
2703
|
mcpServers: JSON.stringify(options?.mcpServers ?? []),
|
|
@@ -3008,26 +2757,11 @@ export class AgentOs {
|
|
|
3008
2757
|
* there is no surviving store and the fallback tier always runs.
|
|
3009
2758
|
*/
|
|
3010
2759
|
async resumeSession(sessionId, agentType, options) {
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
}
|
|
3015
|
-
// Every agent is an `/opt/agentos` package now: the config carries a
|
|
3016
|
-
// pre-resolved guest command path (`adapterEntrypoint`). There is no npm
|
|
3017
|
-
// adapter resolution.
|
|
3018
|
-
const adapterEntrypoint = config.adapterEntrypoint;
|
|
3019
|
-
if (!adapterEntrypoint) {
|
|
3020
|
-
throw new Error(`agent "${String(agentType)}" config has no adapterEntrypoint`);
|
|
3021
|
-
}
|
|
2760
|
+
// The client is npm-agnostic: it sends only the agent NAME. The sidecar
|
|
2761
|
+
// resolves the name -> package -> entrypoint/env/launchArgs from the
|
|
2762
|
+
// projected manifest, exactly as createSession does.
|
|
3022
2763
|
const sessionCwd = options?.cwd ?? "/workspace";
|
|
3023
|
-
|
|
3024
|
-
// the resolved entrypoint through env under the sidecar's reserved key. The
|
|
3025
|
-
// sidecar reads it and strips it before launching the adapter.
|
|
3026
|
-
const launchEnv = {
|
|
3027
|
-
...config.defaultEnv,
|
|
3028
|
-
...options?.env,
|
|
3029
|
-
[RESUME_ADAPTER_ENTRYPOINT_ENV]: adapterEntrypoint,
|
|
3030
|
-
};
|
|
2764
|
+
const launchEnv = { ...options?.env };
|
|
3031
2765
|
const response = await this._sendAcpRequest({
|
|
3032
2766
|
tag: "AcpResumeSessionRequest",
|
|
3033
2767
|
val: {
|
|
@@ -3578,14 +3312,6 @@ export class AgentOs {
|
|
|
3578
3312
|
return "reject";
|
|
3579
3313
|
}
|
|
3580
3314
|
}
|
|
3581
|
-
/**
|
|
3582
|
-
* Resolve an agent config by ID. Agents are /opt/agentos packages
|
|
3583
|
-
* registered from their manifests (explicit software at create, or lazily
|
|
3584
|
-
* linked dependency agents) — there is no hardcoded fallback config.
|
|
3585
|
-
*/
|
|
3586
|
-
_resolveAgentConfig(agentType) {
|
|
3587
|
-
return this._softwareAgentConfigs.get(agentType);
|
|
3588
|
-
}
|
|
3589
3315
|
/**
|
|
3590
3316
|
* Gracefully destroy a session: cancel any pending work, close the client,
|
|
3591
3317
|
* and remove from tracking. Unlike close() which is abrupt, this attempts
|
|
@@ -3902,13 +3628,13 @@ function ensureSharedSidecarNativeProcess(sidecar) {
|
|
|
3902
3628
|
// the spawned child is untracked, unreapable, and pins the loop).
|
|
3903
3629
|
state.sharedChild = sidecarChildHandle(client);
|
|
3904
3630
|
if (!state.sharedChild) {
|
|
3905
|
-
// We reached into @
|
|
3631
|
+
// We reached into @rivet-dev/agentos-runtime-core internals to get the child for
|
|
3906
3632
|
// idle-unref. If that shape ever changes this returns undefined and
|
|
3907
3633
|
// the optimization silently stops working (one-shot scripts would
|
|
3908
3634
|
// hang again). Make it loud rather than a silent regression.
|
|
3909
3635
|
console.warn("[agentos] could not resolve the shared sidecar child handle; " +
|
|
3910
3636
|
"standalone scripts may not exit cleanly after dispose(). " +
|
|
3911
|
-
"This usually means @
|
|
3637
|
+
"This usually means @rivet-dev/agentos-runtime-core internals changed.");
|
|
3912
3638
|
}
|
|
3913
3639
|
// Apply the current hold state to the just-spawned child.
|
|
3914
3640
|
applySharedSidecarHold(state);
|