@rivet-dev/agentos-runtime-core 0.2.8-rc.2 → 0.2.8-rc.3
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 +1 -1
- package/commands/[ +0 -0
- package/commands/_stubs +0 -0
- package/commands/acl_tools +0 -0
- package/commands/arch +0 -0
- package/commands/attr +0 -0
- package/commands/awk +0 -0
- package/commands/b2sum +0 -0
- package/commands/base32 +0 -0
- package/commands/base64 +0 -0
- package/commands/basename +0 -0
- package/commands/basenc +0 -0
- package/commands/bash +0 -0
- package/commands/bc +0 -0
- package/commands/cat +0 -0
- package/commands/chacl +0 -0
- package/commands/chcon +0 -0
- package/commands/chgrp +0 -0
- package/commands/chmod +0 -0
- package/commands/chown +0 -0
- package/commands/chroot +0 -0
- package/commands/cksum +0 -0
- package/commands/cmp +0 -0
- package/commands/column +0 -0
- package/commands/comm +0 -0
- package/commands/cp +0 -0
- package/commands/curl +0 -0
- package/commands/cut +0 -0
- package/commands/date +0 -0
- package/commands/dd +0 -0
- package/commands/df +0 -0
- package/commands/diff +0 -0
- package/commands/dir +0 -0
- package/commands/dircolors +0 -0
- package/commands/dirname +0 -0
- package/commands/du +0 -0
- package/commands/echo +0 -0
- package/commands/egrep +0 -0
- package/commands/env +0 -0
- package/commands/envsubst +0 -0
- package/commands/expand +0 -0
- package/commands/expr +0 -0
- package/commands/factor +0 -0
- package/commands/false +0 -0
- package/commands/fd +0 -0
- package/commands/fgrep +0 -0
- package/commands/file +0 -0
- package/commands/find +0 -0
- package/commands/findmnt +0 -0
- package/commands/fmt +0 -0
- package/commands/fold +0 -0
- package/commands/getent +0 -0
- package/commands/getfacl +0 -0
- package/commands/getfattr +0 -0
- package/commands/git +0 -0
- package/commands/git-receive-pack +0 -0
- package/commands/git-remote-http +0 -0
- package/commands/git-remote-https +0 -0
- package/commands/git-upload-archive +0 -0
- package/commands/git-upload-pack +0 -0
- package/commands/grep +0 -0
- package/commands/groups +0 -0
- package/commands/gunzip +0 -0
- package/commands/gzip +0 -0
- package/commands/head +0 -0
- package/commands/hostid +0 -0
- package/commands/hostname +0 -0
- package/commands/http-test +0 -0
- package/commands/id +0 -0
- package/commands/install +0 -0
- package/commands/join +0 -0
- package/commands/jq +0 -0
- package/commands/kill +0 -0
- package/commands/link +0 -0
- package/commands/ln +0 -0
- package/commands/logname +0 -0
- package/commands/ls +0 -0
- package/commands/md5sum +0 -0
- package/commands/mkdir +0 -0
- package/commands/mkfifo +0 -0
- package/commands/mknod +0 -0
- package/commands/mktemp +0 -0
- package/commands/more +0 -0
- package/commands/mount +0 -0
- package/commands/mv +0 -0
- package/commands/nice +0 -0
- package/commands/nl +0 -0
- package/commands/nohup +0 -0
- package/commands/nproc +0 -0
- package/commands/numfmt +0 -0
- package/commands/od +0 -0
- package/commands/paste +0 -0
- package/commands/pathchk +0 -0
- package/commands/pinky +0 -0
- package/commands/printenv +0 -0
- package/commands/printf +0 -0
- package/commands/ptx +0 -0
- package/commands/pwd +0 -0
- package/commands/readlink +0 -0
- package/commands/realpath +0 -0
- package/commands/rev +0 -0
- package/commands/rg +0 -0
- package/commands/rm +0 -0
- package/commands/rmdir +0 -0
- package/commands/runas +0 -0
- package/commands/runcon +0 -0
- package/commands/sed +0 -0
- package/commands/seq +0 -0
- package/commands/setfacl +0 -0
- package/commands/setfattr +0 -0
- package/commands/sh +0 -0
- package/commands/sha1sum +0 -0
- package/commands/sha224sum +0 -0
- package/commands/sha256sum +0 -0
- package/commands/sha384sum +0 -0
- package/commands/sha512sum +0 -0
- package/commands/shred +0 -0
- package/commands/shuf +0 -0
- package/commands/sleep +0 -0
- package/commands/sort +0 -0
- package/commands/spawn-test-host +0 -0
- package/commands/split +0 -0
- package/commands/sqlite3 +0 -0
- package/commands/ssh +0 -0
- package/commands/ssh-keysign +0 -0
- package/commands/ssh-sk-helper +0 -0
- package/commands/stat +0 -0
- package/commands/stdbuf +0 -0
- package/commands/strings +0 -0
- package/commands/stty +0 -0
- package/commands/su +0 -0
- package/commands/sum +0 -0
- package/commands/sync +0 -0
- package/commands/tac +0 -0
- package/commands/tail +0 -0
- package/commands/tar +0 -0
- package/commands/tee +0 -0
- package/commands/test +0 -0
- package/commands/timeout +0 -0
- package/commands/touch +0 -0
- package/commands/tr +0 -0
- package/commands/tree +0 -0
- package/commands/true +0 -0
- package/commands/truncate +0 -0
- package/commands/tsort +0 -0
- package/commands/tty +0 -0
- package/commands/uname +0 -0
- package/commands/unexpand +0 -0
- package/commands/uniq +0 -0
- package/commands/unlink +0 -0
- package/commands/unzip +0 -0
- package/commands/uptime +0 -0
- package/commands/users +0 -0
- package/commands/vdir +0 -0
- package/commands/wc +0 -0
- package/commands/wget +0 -0
- package/commands/which +0 -0
- package/commands/who +0 -0
- package/commands/whoami +0 -0
- package/commands/xargs +0 -0
- package/commands/xattr_tools +0 -0
- package/commands/xfs_io +0 -0
- package/commands/xu +0 -0
- package/commands/yes +0 -0
- package/commands/yq +0 -0
- package/commands/zcat +0 -0
- package/commands/zip +0 -0
- package/dist/binary.js +4 -3
- package/dist/descriptors.d.ts +2 -12
- package/dist/descriptors.js +10 -6
- package/dist/frame-stream.d.ts +33 -0
- package/dist/frame-stream.js +113 -0
- package/dist/generated/AcpLimitsConfig.d.ts +16 -0
- package/dist/generated/BindingLimitsConfig.d.ts +10 -0
- package/dist/generated/CreateVmConfig.d.ts +4 -0
- package/dist/generated/Http2LimitsConfig.d.ts +12 -0
- package/dist/generated/Http2LimitsConfig.js +2 -0
- package/dist/generated/JsRuntimeLimitsConfig.d.ts +1 -0
- package/dist/generated/MountPluginDescriptor.d.ts +1 -1
- package/dist/generated/ProcessLimitsConfig.d.ts +7 -0
- package/dist/generated/ProcessLimitsConfig.js +2 -0
- package/dist/generated/ReactorLimitsConfig.d.ts +23 -0
- package/dist/generated/ReactorLimitsConfig.js +2 -0
- package/dist/generated/SqliteLimitsConfig.d.ts +3 -0
- package/dist/generated/SqliteLimitsConfig.js +2 -0
- package/dist/generated/TlsLimitsConfig.d.ts +3 -0
- package/dist/generated/TlsLimitsConfig.js +2 -0
- package/dist/generated/UdpLimitsConfig.d.ts +4 -0
- package/dist/generated/UdpLimitsConfig.js +2 -0
- package/dist/generated/VmGroupConfig.d.ts +5 -0
- package/dist/generated/VmGroupConfig.js +2 -0
- package/dist/generated/VmLimitsConfig.d.ts +14 -2
- package/dist/generated/VmSqliteDescriptor.d.ts +10 -0
- package/dist/generated/VmSqliteDescriptor.js +2 -0
- package/dist/generated/VmUserAccountConfig.d.ts +9 -0
- package/dist/generated/VmUserAccountConfig.js +2 -0
- package/dist/generated/VmUserConfig.d.ts +19 -0
- package/dist/generated/VmUserConfig.js +1 -0
- package/dist/generated/WasmLimitsConfig.d.ts +1 -0
- package/dist/generated-protocol.d.ts +60 -2
- package/dist/generated-protocol.js +166 -31
- package/dist/kernel-proxy.d.ts +4 -0
- package/dist/kernel-proxy.js +53 -20
- package/dist/native-client.d.ts +3 -3
- package/dist/native-client.js +43 -8
- package/dist/node-runtime-options-schema.d.ts +1 -1
- package/dist/node-runtime-options-schema.js +43 -1
- package/dist/node-runtime.d.ts +12 -3
- package/dist/node-runtime.js +8 -7
- package/dist/process.d.ts +5 -1
- package/dist/process.js +35 -8
- package/dist/protocol-client.d.ts +9 -2
- package/dist/protocol-client.js +127 -7
- package/dist/protocol-frames.d.ts +14 -3
- package/dist/protocol-frames.js +26 -1
- package/dist/protocol-schema.d.ts +1 -1
- package/dist/protocol-schema.js +1 -1
- package/dist/request-payloads.d.ts +4 -1
- package/dist/request-payloads.js +7 -2
- package/dist/response-payloads.d.ts +22 -1
- package/dist/response-payloads.js +33 -1
- package/dist/sidecar-errors.d.ts +22 -0
- package/dist/sidecar-errors.js +10 -0
- package/dist/sidecar-process.d.ts +12 -2
- package/dist/sidecar-process.js +77 -12
- package/dist/test-runtime.d.ts +19 -7
- package/dist/test-runtime.js +213 -66
- package/dist/vm-config.d.ts +5 -1
- package/package.json +11 -6
- package/commands/codex +0 -0
- package/commands/codex-exec +0 -0
- package/commands/http_get +0 -0
- package/dist/generated/ToolLimitsConfig.d.ts +0 -10
- /package/dist/generated/{ToolLimitsConfig.js → BindingLimitsConfig.js} +0 -0
package/dist/test-runtime.js
CHANGED
|
@@ -5,9 +5,9 @@ import * as path from "node:path";
|
|
|
5
5
|
import * as posixPath from "node:path/posix";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import "./native-client.js";
|
|
8
|
-
import { NativeSidecarKernelProxy, SidecarProcess, serializeMountConfigForSidecar, } from "./kernel-proxy.js";
|
|
9
8
|
import { resolvePublishedSidecarBinary } from "./binary.js";
|
|
10
9
|
import { findCargoBinary, resolveCargoBinary } from "./cargo.js";
|
|
10
|
+
import { NativeSidecarKernelProxy, SidecarProcess, serializeMountConfigForSidecar, } from "./kernel-proxy.js";
|
|
11
11
|
export const AF_INET = 2;
|
|
12
12
|
export const AF_UNIX = 1;
|
|
13
13
|
export const SOCK_STREAM = 1;
|
|
@@ -33,6 +33,8 @@ const KERNEL_POSIX_BOOTSTRAP_DIRS = [
|
|
|
33
33
|
"/srv",
|
|
34
34
|
"/sys",
|
|
35
35
|
"/opt",
|
|
36
|
+
"/opt/agentos",
|
|
37
|
+
"/opt/agentos/bin",
|
|
36
38
|
"/mnt",
|
|
37
39
|
"/media",
|
|
38
40
|
"/home",
|
|
@@ -66,9 +68,21 @@ const SIDECAR_BUILD_INPUTS = [
|
|
|
66
68
|
path.join(REPO_ROOT, "Cargo.toml"),
|
|
67
69
|
path.join(REPO_ROOT, "Cargo.lock"),
|
|
68
70
|
path.join(REPO_ROOT, "crates/bridge"),
|
|
71
|
+
path.join(REPO_ROOT, "crates/build-support"),
|
|
69
72
|
path.join(REPO_ROOT, "crates/execution"),
|
|
70
73
|
path.join(REPO_ROOT, "crates/kernel"),
|
|
71
|
-
path.join(REPO_ROOT, "crates/sidecar"),
|
|
74
|
+
path.join(REPO_ROOT, "crates/native-sidecar"),
|
|
75
|
+
path.join(REPO_ROOT, "crates/native-sidecar-core"),
|
|
76
|
+
path.join(REPO_ROOT, "crates/sidecar-protocol"),
|
|
77
|
+
path.join(REPO_ROOT, "crates/v8-runtime"),
|
|
78
|
+
path.join(REPO_ROOT, "crates/vfs"),
|
|
79
|
+
path.join(REPO_ROOT, "crates/vm-config"),
|
|
80
|
+
path.join(REPO_ROOT, "packages/build-tools/bridge-src"),
|
|
81
|
+
path.join(REPO_ROOT, "packages/build-tools/package.json"),
|
|
82
|
+
path.join(REPO_ROOT, "packages/build-tools/scripts/build-v8-bridge.mjs"),
|
|
83
|
+
path.join(REPO_ROOT, "packages/core/fixtures/base-filesystem.json"),
|
|
84
|
+
path.join(REPO_ROOT, "packages/runtime-core/fixtures/base-filesystem.json"),
|
|
85
|
+
path.join(REPO_ROOT, "pnpm-lock.yaml"),
|
|
72
86
|
];
|
|
73
87
|
let ensuredSidecarBinary = null;
|
|
74
88
|
export class KernelError extends Error {
|
|
@@ -325,8 +339,10 @@ export class InMemoryFileSystem {
|
|
|
325
339
|
typeBits === 0 ? (entry.mode & 0o170000) | (mode & 0o7777) : mode;
|
|
326
340
|
entry.ctimeMs = Date.now();
|
|
327
341
|
}
|
|
328
|
-
async chown(targetPath, uid, gid) {
|
|
329
|
-
const entry =
|
|
342
|
+
async chown(targetPath, uid, gid, options) {
|
|
343
|
+
const entry = options?.followSymlinks === false
|
|
344
|
+
? this.entries.get(normalizePath(targetPath))
|
|
345
|
+
: this.resolveEntry(targetPath);
|
|
330
346
|
if (!entry)
|
|
331
347
|
throw errnoError("ENOENT", `chown '${targetPath}'`);
|
|
332
348
|
entry.uid = uid;
|
|
@@ -548,8 +564,14 @@ export class NodeFileSystem {
|
|
|
548
564
|
async chmod(targetPath, mode) {
|
|
549
565
|
await fs.chmod(this.normalizeTarget(targetPath), mode);
|
|
550
566
|
}
|
|
551
|
-
async chown(targetPath, uid, gid) {
|
|
552
|
-
|
|
567
|
+
async chown(targetPath, uid, gid, options) {
|
|
568
|
+
const normalized = this.normalizeTarget(targetPath);
|
|
569
|
+
if (options?.followSymlinks === false) {
|
|
570
|
+
await fs.lchown(normalized, uid, gid);
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
await fs.chown(normalized, uid, gid);
|
|
574
|
+
}
|
|
553
575
|
}
|
|
554
576
|
async utimes(targetPath, atime, mtime) {
|
|
555
577
|
await fs.utimes(this.normalizeTarget(targetPath), atime / 1000, mtime / 1000);
|
|
@@ -569,7 +591,7 @@ export class NodeFileSystem {
|
|
|
569
591
|
}
|
|
570
592
|
}
|
|
571
593
|
async pwrite(targetPath, offset, data) {
|
|
572
|
-
const handle = await fs.open(this.normalizeTarget(targetPath),
|
|
594
|
+
const handle = await fs.open(this.normalizeTarget(targetPath), fsSync.constants.O_WRONLY);
|
|
573
595
|
try {
|
|
574
596
|
await handle.write(data, 0, data.length, offset);
|
|
575
597
|
}
|
|
@@ -857,7 +879,6 @@ export const WASMVM_COMMANDS = Object.freeze([
|
|
|
857
879
|
"unzip",
|
|
858
880
|
"sqlite3",
|
|
859
881
|
"curl",
|
|
860
|
-
"wget",
|
|
861
882
|
"git",
|
|
862
883
|
"git-remote-http",
|
|
863
884
|
"git-remote-https",
|
|
@@ -1021,7 +1042,6 @@ export const DEFAULT_FIRST_PARTY_TIERS = Object.freeze({
|
|
|
1021
1042
|
tac: "read-only",
|
|
1022
1043
|
tsort: "read-only",
|
|
1023
1044
|
curl: "full",
|
|
1024
|
-
wget: "full",
|
|
1025
1045
|
sqlite3: "read-write",
|
|
1026
1046
|
});
|
|
1027
1047
|
class NativeRuntimeDescriptor {
|
|
@@ -1148,8 +1168,8 @@ class WasmVmRuntimeDescriptor {
|
|
|
1148
1168
|
recordModuleExecution(command) {
|
|
1149
1169
|
const normalized = normalizeCommandLookup(command);
|
|
1150
1170
|
if (this._commandPaths.has(normalized) ||
|
|
1151
|
-
(!this.commandDirs || this.commandDirs.length === 0) &&
|
|
1152
|
-
this.commands.includes(normalized)) {
|
|
1171
|
+
((!this.commandDirs || this.commandDirs.length === 0) &&
|
|
1172
|
+
this.commands.includes(normalized))) {
|
|
1153
1173
|
this._moduleCache.set(normalized, true);
|
|
1154
1174
|
}
|
|
1155
1175
|
}
|
|
@@ -1200,7 +1220,7 @@ function sidecarBinaryNeedsBuild() {
|
|
|
1200
1220
|
function ensureNativeSidecarBinary() {
|
|
1201
1221
|
// A published install has no in-repo Cargo workspace to build from: resolve
|
|
1202
1222
|
// the prebuilt platform binary (or an explicit sidecar override).
|
|
1203
|
-
if (process.env.
|
|
1223
|
+
if (process.env.AGENTOS_NATIVE_SIDECAR_BIN ||
|
|
1204
1224
|
process.env.AGENTOS_SIDECAR_BIN ||
|
|
1205
1225
|
!fsSync.existsSync(path.join(REPO_ROOT, "Cargo.toml"))) {
|
|
1206
1226
|
return resolvePublishedSidecarBinary();
|
|
@@ -1243,9 +1263,13 @@ function createBootstrapEntries(commandNames) {
|
|
|
1243
1263
|
...KERNEL_POSIX_BOOTSTRAP_DIRS.map((entryPath) => ({
|
|
1244
1264
|
path: entryPath,
|
|
1245
1265
|
kind: "directory",
|
|
1246
|
-
mode:
|
|
1247
|
-
|
|
1248
|
-
|
|
1266
|
+
mode: entryPath === "/tmp" || entryPath === "/var/tmp"
|
|
1267
|
+
? 0o1777
|
|
1268
|
+
: entryPath === "/home/agentos"
|
|
1269
|
+
? 0o2755
|
|
1270
|
+
: 0o755,
|
|
1271
|
+
uid: entryPath === "/home/agentos" || entryPath === "/workspace" ? 1000 : 0,
|
|
1272
|
+
gid: entryPath === "/home/agentos" || entryPath === "/workspace" ? 1000 : 0,
|
|
1249
1273
|
})),
|
|
1250
1274
|
{
|
|
1251
1275
|
path: "/usr/bin/env",
|
|
@@ -1394,12 +1418,83 @@ function planNodeFilesystemPassthroughMounts(filesystem, existingMounts) {
|
|
|
1394
1418
|
fs: new NodeFileSystem({ root: hostPath }),
|
|
1395
1419
|
readOnly: true,
|
|
1396
1420
|
});
|
|
1421
|
+
if (directoryName === "node_modules") {
|
|
1422
|
+
appendNodeModulesSymlinkTargetMounts(mounts, existingGuestPaths, guestPath, hostPath);
|
|
1423
|
+
}
|
|
1397
1424
|
}
|
|
1398
1425
|
return {
|
|
1399
1426
|
mounts,
|
|
1400
1427
|
passthroughDirectories,
|
|
1401
1428
|
};
|
|
1402
1429
|
}
|
|
1430
|
+
function appendNodeModulesSymlinkTargetMounts(mounts, existingGuestPaths, guestRoot, hostRoot) {
|
|
1431
|
+
let canonicalHostRoot;
|
|
1432
|
+
try {
|
|
1433
|
+
canonicalHostRoot = fsSync.realpathSync(hostRoot);
|
|
1434
|
+
}
|
|
1435
|
+
catch {
|
|
1436
|
+
return;
|
|
1437
|
+
}
|
|
1438
|
+
const appendTarget = (guestPath, symlinkPath) => {
|
|
1439
|
+
if (existingGuestPaths.has(guestPath))
|
|
1440
|
+
return;
|
|
1441
|
+
try {
|
|
1442
|
+
const target = fsSync.realpathSync(symlinkPath);
|
|
1443
|
+
if (!fsSync.statSync(target).isDirectory())
|
|
1444
|
+
return;
|
|
1445
|
+
const relativeTarget = path.relative(canonicalHostRoot, target);
|
|
1446
|
+
if (relativeTarget === "" ||
|
|
1447
|
+
(!relativeTarget.startsWith(`..${path.sep}`) &&
|
|
1448
|
+
relativeTarget !== ".." &&
|
|
1449
|
+
!path.isAbsolute(relativeTarget))) {
|
|
1450
|
+
// pnpm and similar stores deliberately use links that remain inside
|
|
1451
|
+
// node_modules. Keeping those on the root mount preserves the realpath
|
|
1452
|
+
// ancestry needed to resolve their nested dependency links.
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
mounts.push({
|
|
1456
|
+
path: guestPath,
|
|
1457
|
+
fs: new NodeFileSystem({ root: target }),
|
|
1458
|
+
readOnly: true,
|
|
1459
|
+
});
|
|
1460
|
+
existingGuestPaths.add(guestPath);
|
|
1461
|
+
}
|
|
1462
|
+
catch {
|
|
1463
|
+
// Broken or concurrently-removed links remain unavailable, matching Node.
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
let entries;
|
|
1467
|
+
try {
|
|
1468
|
+
entries = fsSync.readdirSync(hostRoot, { withFileTypes: true });
|
|
1469
|
+
}
|
|
1470
|
+
catch {
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
for (const entry of entries) {
|
|
1474
|
+
if (entry.name.startsWith("."))
|
|
1475
|
+
continue;
|
|
1476
|
+
const entryPath = path.join(hostRoot, entry.name);
|
|
1477
|
+
if (entry.isSymbolicLink()) {
|
|
1478
|
+
appendTarget(`${guestRoot}/${entry.name}`, entryPath);
|
|
1479
|
+
continue;
|
|
1480
|
+
}
|
|
1481
|
+
if (!entry.isDirectory() || !entry.name.startsWith("@"))
|
|
1482
|
+
continue;
|
|
1483
|
+
let scopedEntries;
|
|
1484
|
+
try {
|
|
1485
|
+
scopedEntries = fsSync.readdirSync(entryPath, { withFileTypes: true });
|
|
1486
|
+
}
|
|
1487
|
+
catch {
|
|
1488
|
+
continue;
|
|
1489
|
+
}
|
|
1490
|
+
for (const scopedEntry of scopedEntries) {
|
|
1491
|
+
if (scopedEntry.name.startsWith(".") || !scopedEntry.isSymbolicLink()) {
|
|
1492
|
+
continue;
|
|
1493
|
+
}
|
|
1494
|
+
appendTarget(`${guestRoot}/${entry.name}/${scopedEntry.name}`, path.join(entryPath, scopedEntry.name));
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1403
1498
|
function collectGuestCommandPaths(commandDirs, startIndex = 0) {
|
|
1404
1499
|
const guestPaths = new Map();
|
|
1405
1500
|
for (const entry of discoverWasmCommandEntries(commandDirs)) {
|
|
@@ -1412,9 +1507,13 @@ function collectGuestCommandPaths(commandDirs, startIndex = 0) {
|
|
|
1412
1507
|
async function ensureCommandStubs(proxy, commands) {
|
|
1413
1508
|
const rootView = proxy.createRootView();
|
|
1414
1509
|
for (const command of commands) {
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1510
|
+
// `/bin` supports PATH-based test commands. `/opt/agentos/bin` mirrors
|
|
1511
|
+
// the package projection used by production VMs and is required by
|
|
1512
|
+
// upstream tools that exec private helpers via an absolute libexec path.
|
|
1513
|
+
for (const stubPath of [`/bin/${command}`, `/opt/agentos/bin/${command}`]) {
|
|
1514
|
+
await rootView.writeFile(stubPath, KERNEL_COMMAND_STUB);
|
|
1515
|
+
await rootView.chmod(stubPath, 0o755);
|
|
1516
|
+
}
|
|
1418
1517
|
}
|
|
1419
1518
|
}
|
|
1420
1519
|
class DeferredFileSystem {
|
|
@@ -1483,8 +1582,8 @@ class DeferredFileSystem {
|
|
|
1483
1582
|
chmod(path, mode) {
|
|
1484
1583
|
return this.filesystem().chmod(path, mode);
|
|
1485
1584
|
}
|
|
1486
|
-
chown(path, uid, gid) {
|
|
1487
|
-
return this.filesystem().chown(path, uid, gid);
|
|
1585
|
+
chown(path, uid, gid, options) {
|
|
1586
|
+
return this.filesystem().chown(path, uid, gid, options);
|
|
1488
1587
|
}
|
|
1489
1588
|
utimes(path, atime, mtime) {
|
|
1490
1589
|
return this.filesystem().utimes(path, atime, mtime);
|
|
@@ -1524,7 +1623,10 @@ const VIRTUAL_FILESYSTEM_METHOD_NAMES = [
|
|
|
1524
1623
|
"pread",
|
|
1525
1624
|
"pwrite",
|
|
1526
1625
|
];
|
|
1527
|
-
const
|
|
1626
|
+
const DEFAULT_LIVE_FILESYSTEM_SYNC_MAX_BYTES = 64 * 1024 * 1024;
|
|
1627
|
+
class LiveFilesystemSyncLimitError extends Error {
|
|
1628
|
+
code = "ERR_AGENTOS_LIVE_FILESYSTEM_SYNC_LIMIT";
|
|
1629
|
+
}
|
|
1528
1630
|
function topLevelSyncRoot(targetPath) {
|
|
1529
1631
|
const normalized = normalizePath(targetPath);
|
|
1530
1632
|
const [first] = normalized.split("/").filter(Boolean);
|
|
@@ -1552,48 +1654,83 @@ async function ensureBoundParentDirectory(methods, targetPath) {
|
|
|
1552
1654
|
if (parent === targetPath) {
|
|
1553
1655
|
return;
|
|
1554
1656
|
}
|
|
1555
|
-
await callBoundFilesystemMethod(methods, "mkdir", parent, {
|
|
1657
|
+
await callBoundFilesystemMethod(methods, "mkdir", parent, {
|
|
1658
|
+
recursive: true,
|
|
1659
|
+
});
|
|
1556
1660
|
}
|
|
1557
|
-
async function syncLiveFilesystemToBoundMethods(live, methods, paths) {
|
|
1661
|
+
async function syncLiveFilesystemToBoundMethods(live, methods, paths, maxBytes) {
|
|
1662
|
+
const snapshot = [];
|
|
1663
|
+
const usage = { bytes: 0 };
|
|
1558
1664
|
for (const targetPath of [...new Set(paths.map(normalizePath))].sort((left, right) => left.localeCompare(right))) {
|
|
1559
1665
|
if (!(await live.exists(targetPath).catch(() => false))) {
|
|
1560
1666
|
continue;
|
|
1561
1667
|
}
|
|
1562
|
-
await
|
|
1668
|
+
await snapshotLiveFilesystemPath(live, targetPath, snapshot, usage, maxBytes);
|
|
1669
|
+
}
|
|
1670
|
+
if (usage.bytes >= maxBytes * 0.8) {
|
|
1671
|
+
process.emitWarning(`live filesystem sync retained ${usage.bytes} of ${maxBytes} bytes; ` +
|
|
1672
|
+
"raise createKernel({ maxFilesystemBytes }) before increasing VM filesystem limits", { code: "AGENTOS_LIVE_FILESYSTEM_SYNC_NEAR_LIMIT" });
|
|
1673
|
+
}
|
|
1674
|
+
for (const entry of snapshot) {
|
|
1675
|
+
await applyLiveFilesystemSnapshotEntry(methods, entry);
|
|
1563
1676
|
}
|
|
1564
1677
|
}
|
|
1565
|
-
async function
|
|
1566
|
-
const stat =
|
|
1678
|
+
async function snapshotLiveFilesystemPath(live, targetPath, snapshot, usage, maxBytes, knownEntry) {
|
|
1679
|
+
const stat = knownEntry ??
|
|
1680
|
+
(targetPath === "/"
|
|
1681
|
+
? await live.stat(targetPath)
|
|
1682
|
+
: await live.lstat(targetPath));
|
|
1567
1683
|
if (stat.isSymbolicLink) {
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1684
|
+
snapshot.push({
|
|
1685
|
+
kind: "symlink",
|
|
1686
|
+
path: targetPath,
|
|
1687
|
+
target: await live.readlink(targetPath),
|
|
1688
|
+
});
|
|
1571
1689
|
return;
|
|
1572
1690
|
}
|
|
1573
1691
|
if (stat.isDirectory) {
|
|
1574
|
-
|
|
1575
|
-
recursive: true,
|
|
1576
|
-
});
|
|
1692
|
+
snapshot.push({ kind: "directory", path: targetPath });
|
|
1577
1693
|
const children = (await live.readDirWithTypes(targetPath))
|
|
1578
|
-
.
|
|
1579
|
-
.
|
|
1580
|
-
.sort((left, right) => left.localeCompare(right));
|
|
1694
|
+
.filter((entry) => entry.name !== "." && entry.name !== "..")
|
|
1695
|
+
.sort((left, right) => left.name.localeCompare(right.name));
|
|
1581
1696
|
for (const child of children) {
|
|
1582
|
-
await
|
|
1697
|
+
await snapshotLiveFilesystemPath(live, targetPath === "/"
|
|
1698
|
+
? posixPath.join("/", child.name)
|
|
1699
|
+
: posixPath.join(targetPath, child.name), snapshot, usage, maxBytes, child);
|
|
1583
1700
|
}
|
|
1584
1701
|
return;
|
|
1585
1702
|
}
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
}
|
|
1593
|
-
await callBoundFilesystemMethod(methods, "pwrite", targetPath, offset, chunk);
|
|
1703
|
+
const fileSize = "size" in stat && typeof stat.size === "number"
|
|
1704
|
+
? stat.size
|
|
1705
|
+
: (await live.lstat(targetPath)).size;
|
|
1706
|
+
if (fileSize > maxBytes - usage.bytes) {
|
|
1707
|
+
throw new LiveFilesystemSyncLimitError(`live filesystem sync for ${targetPath} exceeds ${maxBytes} bytes ` +
|
|
1708
|
+
"(createKernel maxFilesystemBytes); raise createKernel({ maxFilesystemBytes })");
|
|
1594
1709
|
}
|
|
1710
|
+
const content = await live.readFile(targetPath);
|
|
1711
|
+
if (content.byteLength > maxBytes - usage.bytes) {
|
|
1712
|
+
throw new LiveFilesystemSyncLimitError(`live filesystem sync for ${targetPath} exceeds ${maxBytes} bytes ` +
|
|
1713
|
+
"(createKernel maxFilesystemBytes); raise createKernel({ maxFilesystemBytes })");
|
|
1714
|
+
}
|
|
1715
|
+
usage.bytes += content.byteLength;
|
|
1716
|
+
snapshot.push({ kind: "file", path: targetPath, content });
|
|
1595
1717
|
}
|
|
1596
|
-
function
|
|
1718
|
+
async function applyLiveFilesystemSnapshotEntry(methods, entry) {
|
|
1719
|
+
if (entry.kind === "directory") {
|
|
1720
|
+
await callBoundFilesystemMethod(methods, "mkdir", entry.path, {
|
|
1721
|
+
recursive: true,
|
|
1722
|
+
});
|
|
1723
|
+
return;
|
|
1724
|
+
}
|
|
1725
|
+
await ensureBoundParentDirectory(methods, entry.path);
|
|
1726
|
+
if (entry.kind === "symlink") {
|
|
1727
|
+
await callBoundFilesystemMethod(methods, "removeFile", entry.path).catch(() => { });
|
|
1728
|
+
await callBoundFilesystemMethod(methods, "symlink", entry.target, entry.path);
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
await callBoundFilesystemMethod(methods, "writeFile", entry.path, entry.content);
|
|
1732
|
+
}
|
|
1733
|
+
function bindLiveFilesystem(target, getFilesystem, maxBytes) {
|
|
1597
1734
|
const fallback = {};
|
|
1598
1735
|
for (const method of VIRTUAL_FILESYSTEM_METHOD_NAMES) {
|
|
1599
1736
|
const candidate = target[method];
|
|
@@ -1619,7 +1756,7 @@ function bindLiveFilesystem(target, getFilesystem) {
|
|
|
1619
1756
|
if (!filesystem) {
|
|
1620
1757
|
return;
|
|
1621
1758
|
}
|
|
1622
|
-
await syncLiveFilesystemToBoundMethods(filesystem, fallback, paths);
|
|
1759
|
+
await syncLiveFilesystemToBoundMethods(filesystem, fallback, paths, maxBytes);
|
|
1623
1760
|
},
|
|
1624
1761
|
restore() {
|
|
1625
1762
|
for (const [method, delegate] of Object.entries(fallback)) {
|
|
@@ -1653,9 +1790,9 @@ class NativeKernel {
|
|
|
1653
1790
|
loopbackExemptPorts;
|
|
1654
1791
|
// Bindings registered with the VM, keyed by the callback key the sidecar
|
|
1655
1792
|
// sends back on a host_callback request (the binding name). Installed lazily
|
|
1656
|
-
// on the first
|
|
1657
|
-
|
|
1658
|
-
|
|
1793
|
+
// on the first registerBindings call.
|
|
1794
|
+
bindingHandlers = new Map();
|
|
1795
|
+
bindingRequestHandlerInstalled = false;
|
|
1659
1796
|
constructor(options) {
|
|
1660
1797
|
this.options = options;
|
|
1661
1798
|
this.env = { ...(options.env ?? {}) };
|
|
@@ -1685,7 +1822,7 @@ class NativeKernel {
|
|
|
1685
1822
|
});
|
|
1686
1823
|
}
|
|
1687
1824
|
this.vfs = new DeferredFileSystem(() => this.rootFilesystem);
|
|
1688
|
-
this.liveFilesystemBinding = bindLiveFilesystem(this.options.filesystem, () => this.rootFilesystem);
|
|
1825
|
+
this.liveFilesystemBinding = bindLiveFilesystem(this.options.filesystem, () => this.rootFilesystem, options.maxFilesystemBytes ?? DEFAULT_LIVE_FILESYSTEM_SYNC_MAX_BYTES);
|
|
1689
1826
|
}
|
|
1690
1827
|
get zombieTimerCount() {
|
|
1691
1828
|
return this.proxy?.zombieTimerCount ?? 0;
|
|
@@ -1880,7 +2017,7 @@ class NativeKernel {
|
|
|
1880
2017
|
await this.ensureReady();
|
|
1881
2018
|
return this.proxy.vmFetch(request);
|
|
1882
2019
|
}
|
|
1883
|
-
async
|
|
2020
|
+
async registerBindings(bindings) {
|
|
1884
2021
|
await this.ensureReady();
|
|
1885
2022
|
if (!this.client || !this.session || !this.vm) {
|
|
1886
2023
|
throw new Error("kernel is not ready");
|
|
@@ -1888,12 +2025,12 @@ class NativeKernel {
|
|
|
1888
2025
|
// Install the dispatcher once. It routes every host_callback request the
|
|
1889
2026
|
// sidecar emits to the matching registered handler and replies with a
|
|
1890
2027
|
// host_callback_result frame.
|
|
1891
|
-
if (!this.
|
|
1892
|
-
this.client.setSidecarRequestHandler((request) => this.
|
|
1893
|
-
this.
|
|
2028
|
+
if (!this.bindingRequestHandlerInstalled) {
|
|
2029
|
+
this.client.setSidecarRequestHandler((request) => this.dispatchBindingRequest(request));
|
|
2030
|
+
this.bindingRequestHandlerInstalled = true;
|
|
1894
2031
|
}
|
|
1895
|
-
for (const [name, binding] of Object.entries(
|
|
1896
|
-
this.
|
|
2032
|
+
for (const [name, binding] of Object.entries(bindings)) {
|
|
2033
|
+
this.bindingHandlers.set(name, binding.handler);
|
|
1897
2034
|
const definition = {
|
|
1898
2035
|
description: binding.description,
|
|
1899
2036
|
inputSchema: binding.inputSchema,
|
|
@@ -1909,9 +2046,9 @@ class NativeKernel {
|
|
|
1909
2046
|
}
|
|
1910
2047
|
: {}),
|
|
1911
2048
|
};
|
|
1912
|
-
// Register each binding as its own single-callback
|
|
2049
|
+
// Register each binding as its own single-callback binding collection so the guest
|
|
1913
2050
|
// can invoke it directly by name (or by any caller-provided alias). The
|
|
1914
|
-
// sidecar exposes the
|
|
2051
|
+
// sidecar exposes the binding collection name as a guest command; the single
|
|
1915
2052
|
// callback carries the binding's schema and gates the `binding`
|
|
1916
2053
|
// permission.
|
|
1917
2054
|
await this.client.registerHostCallbacks(this.session, this.vm, {
|
|
@@ -1926,21 +2063,21 @@ class NativeKernel {
|
|
|
1926
2063
|
}
|
|
1927
2064
|
}
|
|
1928
2065
|
}
|
|
1929
|
-
async
|
|
2066
|
+
async dispatchBindingRequest(request) {
|
|
1930
2067
|
const { payload } = request;
|
|
1931
2068
|
if (payload.type !== "host_callback") {
|
|
1932
2069
|
throw new Error(`unsupported sidecar request for bindings: ${payload.type}`);
|
|
1933
2070
|
}
|
|
1934
|
-
// Callback keys arrive as `${
|
|
1935
|
-
// as the bare command name otherwise. The
|
|
1936
|
-
// the same here, so the registered
|
|
2071
|
+
// Callback keys arrive as `${collection}:${binding}` for collection invocations
|
|
2072
|
+
// and as the bare command name otherwise. The collection and binding name are
|
|
2073
|
+
// the same here, so the registered binding name is the segment after the last
|
|
1937
2074
|
// colon (or the whole key when no colon is present).
|
|
1938
2075
|
const callbackKey = payload.callback_key;
|
|
1939
|
-
const
|
|
2076
|
+
const bindingName = callbackKey.includes(":")
|
|
1940
2077
|
? callbackKey.slice(callbackKey.lastIndexOf(":") + 1)
|
|
1941
2078
|
: callbackKey;
|
|
1942
|
-
const handler = this.
|
|
1943
|
-
this.
|
|
2079
|
+
const handler = this.bindingHandlers.get(bindingName) ??
|
|
2080
|
+
this.bindingHandlers.get(callbackKey);
|
|
1944
2081
|
if (!handler) {
|
|
1945
2082
|
return {
|
|
1946
2083
|
type: "host_callback_result",
|
|
@@ -1996,6 +2133,10 @@ class NativeKernel {
|
|
|
1996
2133
|
await this.ensureReady();
|
|
1997
2134
|
return this.proxy.rename(oldPath, newPath);
|
|
1998
2135
|
}
|
|
2136
|
+
async pwrite(targetPath, offset, data) {
|
|
2137
|
+
await this.ensureReady();
|
|
2138
|
+
return this.proxy.vfs.pwrite(targetPath, offset, data);
|
|
2139
|
+
}
|
|
1999
2140
|
tryResolveMountedCommand(command) {
|
|
2000
2141
|
const normalized = normalizeCommandLookup(command);
|
|
2001
2142
|
for (const driver of this.mountedRuntimeDrivers) {
|
|
@@ -2062,15 +2203,21 @@ class NativeKernel {
|
|
|
2062
2203
|
cwd: REPO_ROOT,
|
|
2063
2204
|
command: ensureNativeSidecarBinary(),
|
|
2064
2205
|
args: [],
|
|
2206
|
+
gracefulExitMs: 100,
|
|
2207
|
+
forceExitMs: 100,
|
|
2065
2208
|
}));
|
|
2066
2209
|
const session = await this.measureBoot("session_open", () => client.authenticateAndOpenSession());
|
|
2067
2210
|
const vm = await this.measureBoot("vm_create", () => client.createVm(session, {
|
|
2068
2211
|
runtime: "java_script",
|
|
2069
2212
|
config: {
|
|
2070
2213
|
env: createVmEnv,
|
|
2214
|
+
...(this.options.user ? { user: this.options.user } : {}),
|
|
2071
2215
|
rootFilesystem,
|
|
2072
|
-
...(bootstrapPermissions
|
|
2216
|
+
...(bootstrapPermissions
|
|
2217
|
+
? { permissions: bootstrapPermissions }
|
|
2218
|
+
: {}),
|
|
2073
2219
|
loopbackExemptPorts: this.loopbackExemptPorts,
|
|
2220
|
+
...(this.options.limits ? { limits: this.options.limits } : {}),
|
|
2074
2221
|
...(this.options.jsRuntime
|
|
2075
2222
|
? { jsRuntime: this.options.jsRuntime }
|
|
2076
2223
|
: {}),
|
package/dist/vm-config.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export type { AcpLimitsConfig } from "./generated/AcpLimitsConfig.js";
|
|
2
2
|
export type { CreateVmConfig } from "./generated/CreateVmConfig.js";
|
|
3
|
+
export type { VmUserConfig } from "./generated/VmUserConfig.js";
|
|
4
|
+
export type { VmUserAccountConfig } from "./generated/VmUserAccountConfig.js";
|
|
5
|
+
export type { VmGroupConfig } from "./generated/VmGroupConfig.js";
|
|
3
6
|
export type { FsPermissionRule } from "./generated/FsPermissionRule.js";
|
|
4
7
|
export type { FsPermissionRuleSet } from "./generated/FsPermissionRuleSet.js";
|
|
5
8
|
export type { FsPermissionScope } from "./generated/FsPermissionScope.js";
|
|
@@ -16,6 +19,7 @@ export type { PatternPermissionScope } from "./generated/PatternPermissionScope.
|
|
|
16
19
|
export type { PermissionMode } from "./generated/PermissionMode.js";
|
|
17
20
|
export type { PermissionsPolicy } from "./generated/PermissionsPolicy.js";
|
|
18
21
|
export type { PluginLimitsConfig } from "./generated/PluginLimitsConfig.js";
|
|
22
|
+
export type { ProcessLimitsConfig } from "./generated/ProcessLimitsConfig.js";
|
|
19
23
|
export type { PythonLimitsConfig } from "./generated/PythonLimitsConfig.js";
|
|
20
24
|
export type { ResourceLimitsConfig } from "./generated/ResourceLimitsConfig.js";
|
|
21
25
|
export type { RootFilesystemConfig } from "./generated/RootFilesystemConfig.js";
|
|
@@ -24,7 +28,7 @@ export type { RootFilesystemEntryEncoding } from "./generated/RootFilesystemEntr
|
|
|
24
28
|
export type { RootFilesystemEntryKind } from "./generated/RootFilesystemEntryKind.js";
|
|
25
29
|
export type { RootFilesystemLowerDescriptor } from "./generated/RootFilesystemLowerDescriptor.js";
|
|
26
30
|
export type { RootFilesystemMode } from "./generated/RootFilesystemMode.js";
|
|
27
|
-
export type {
|
|
31
|
+
export type { BindingLimitsConfig } from "./generated/BindingLimitsConfig.js";
|
|
28
32
|
export type { VmDnsConfig } from "./generated/VmDnsConfig.js";
|
|
29
33
|
export type { VmLimitsConfig } from "./generated/VmLimitsConfig.js";
|
|
30
34
|
export type { VmListenPolicyConfig } from "./generated/VmListenPolicyConfig.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rivet-dev/agentos-runtime-core",
|
|
3
|
-
"version": "0.2.8-rc.
|
|
3
|
+
"version": "0.2.8-rc.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -184,15 +184,20 @@
|
|
|
184
184
|
},
|
|
185
185
|
"scripts": {
|
|
186
186
|
"build:protocol": "pnpm --dir ../build-tools build:protocol",
|
|
187
|
-
"
|
|
187
|
+
"generate:vm-config": "cargo test -p agentos-vm-config --quiet",
|
|
188
188
|
"copy-commands": "node scripts/copy-wasm-commands.mjs",
|
|
189
|
-
"check-types": "pnpm run build:protocol &&
|
|
190
|
-
"build": "pnpm run build:protocol &&
|
|
189
|
+
"check-types": "pnpm run build:protocol && tsc --noEmit",
|
|
190
|
+
"build": "pnpm run build:protocol && tsc && pnpm run copy-commands",
|
|
191
191
|
"prepack": "node scripts/copy-wasm-commands.mjs --require",
|
|
192
|
-
"test": "vitest run"
|
|
192
|
+
"test": "vitest run --exclude '**/*.nightly.test.ts'",
|
|
193
|
+
"test:pr": "vitest run --exclude '**/*.nightly.test.ts' --fileParallelism=false",
|
|
194
|
+
"test:nightly": "vitest run tests/integration/*.nightly.test.ts --passWithNoTests",
|
|
195
|
+
"test:ecosystem": "AGENTOS_ECOSYSTEM_E2E=1 vitest run tests/integration/e2e-project-matrix.nightly.test.ts -t 'required Node ecosystem reactor matrix' --reporter=verbose",
|
|
196
|
+
"test:ecosystem:full": "AGENTOS_ECOSYSTEM_FULL_E2E=1 vitest run tests/integration/e2e-project-matrix.nightly.test.ts -t 'full Node ecosystem matrix through kernel' --reporter=verbose",
|
|
197
|
+
"test:npm-workflows": "AGENTOS_NPM_WORKFLOWS_E2E=1 vitest run tests/integration/e2e-npm-*.nightly.test.ts tests/integration/e2e-npx-and-pipes.nightly.test.ts tests/integration/e2e-concurrently.nightly.test.ts tests/integration/e2e-nextjs-build.nightly.test.ts --reporter=verbose"
|
|
193
198
|
},
|
|
194
199
|
"dependencies": {
|
|
195
|
-
"@rivet-dev/agentos-runtime-sidecar": "0.2.8-rc.
|
|
200
|
+
"@rivet-dev/agentos-runtime-sidecar": "0.2.8-rc.3",
|
|
196
201
|
"@rivetkit/bare-ts": "^0.6.2",
|
|
197
202
|
"zod": "^4.1.11"
|
|
198
203
|
},
|
package/commands/codex
DELETED
|
Binary file
|
package/commands/codex-exec
DELETED
|
Binary file
|
package/commands/http_get
DELETED
|
Binary file
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export type ToolLimitsConfig = {
|
|
2
|
-
defaultToolTimeoutMs?: number;
|
|
3
|
-
maxToolTimeoutMs?: number;
|
|
4
|
-
maxRegisteredToolkits?: number;
|
|
5
|
-
maxRegisteredToolsPerVm?: number;
|
|
6
|
-
maxToolsPerToolkit?: number;
|
|
7
|
-
maxToolSchemaBytes?: number;
|
|
8
|
-
maxToolExamplesPerTool?: number;
|
|
9
|
-
maxToolExampleInputBytes?: number;
|
|
10
|
-
};
|
|
File without changes
|