@rivet-dev/agentos-core 0.0.0-integrate-dylib-into-main.815fcda → 0.0.0-main.29b0797
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 +43 -43
- package/dist/agent-os.d.ts +313 -226
- package/dist/agent-os.js +1418 -1545
- package/dist/agentos-package.d.ts +31 -0
- package/dist/agentos-package.js +91 -0
- package/dist/base-filesystem.d.ts +2 -15
- package/dist/base-filesystem.js +23 -171
- package/dist/{host-tools-zod.d.ts → bindings-zod.d.ts} +1 -1
- package/dist/{host-tools-zod.js → bindings-zod.js} +52 -25
- package/dist/bindings.d.ts +43 -0
- package/dist/bindings.js +34 -0
- package/dist/cron/cron-manager.js +43 -10
- package/dist/cron/index.d.ts +1 -1
- package/dist/cron/types.d.ts +26 -10
- package/dist/default-software.d.ts +8 -0
- package/dist/default-software.js +10 -0
- package/dist/filesystem-snapshot.d.ts +1 -2
- package/dist/filesystem-snapshot.js +0 -43
- package/dist/generated/AcpLimitsConfig.d.ts +20 -0
- package/dist/generated/AcpLimitsConfig.js +2 -0
- package/dist/generated/BindingLimitsConfig.d.ts +10 -0
- package/dist/generated/BindingLimitsConfig.js +2 -0
- package/dist/generated/CreateVmConfig.d.ts +28 -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/ProcessLimitsConfig.d.ts +7 -0
- package/dist/generated/ProcessLimitsConfig.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/VmDnsConfig.d.ts +6 -0
- package/dist/generated/VmDnsConfig.js +2 -0
- package/dist/generated/VmGroupConfig.d.ts +5 -0
- package/dist/generated/VmGroupConfig.js +2 -0
- package/dist/generated/VmLimitsConfig.d.ts +20 -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/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 +8 -0
- package/dist/generated/WasmLimitsConfig.js +2 -0
- package/dist/host-dir-mount.d.ts +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -5
- package/dist/layers.d.ts +7 -4
- package/dist/layers.js +0 -176
- package/dist/options-schema.d.ts +556 -0
- package/dist/options-schema.js +386 -0
- package/dist/packages.d.ts +17 -116
- package/dist/packages.js +35 -322
- package/dist/runtime-compat.d.ts +33 -46
- package/dist/runtime-compat.js +197 -511
- package/dist/runtime.d.ts +42 -8
- package/dist/sandbox.d.ts +112 -0
- package/dist/sandbox.js +264 -0
- package/dist/session-api.d.ts +180 -0
- package/dist/session-api.js +1 -0
- package/dist/sidecar/agentos-protocol.d.ts +509 -20
- package/dist/sidecar/agentos-protocol.js +808 -81
- package/dist/sidecar/native-process-client.d.ts +6 -2
- package/dist/sidecar/native-process-client.js +8 -1
- package/dist/sidecar/permissions.d.ts +1 -1
- package/dist/sidecar/permissions.js +4 -4
- package/dist/sidecar/rpc-client.d.ts +100 -9
- package/dist/sidecar/rpc-client.js +445 -110
- package/dist/test/runtime.d.ts +2 -1
- package/dist/test/runtime.js +2 -1
- package/dist/test/terminal-harness.js +0 -3
- package/dist/types.d.ts +13 -7
- package/package.json +46 -35
- package/dist/agent-session-types.d.ts +0 -67
- package/dist/agents.d.ts +0 -63
- package/dist/agents.js +0 -42
- package/dist/host-tools.d.ts +0 -45
- package/dist/host-tools.js +0 -26
- package/dist/overlay-filesystem.d.ts +0 -19
- package/dist/overlay-filesystem.js +0 -645
- package/fixtures/AGENTOS_SYSTEM_PROMPT.md +0 -21
- /package/dist/{agent-session-types.js → generated/CreateVmConfig.js} +0 -0
package/dist/runtime-compat.js
CHANGED
|
@@ -7,18 +7,19 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { resolvePublishedSidecarBinary } from "./sidecar/binary.js";
|
|
8
8
|
import { findCargoBinary, resolveCargoBinary } from "./sidecar/cargo.js";
|
|
9
9
|
import { serializePermissionsForSidecar } from "./sidecar/permissions.js";
|
|
10
|
-
import {
|
|
10
|
+
import { NativeSidecarKernelProxy, SidecarProcess, serializeMountConfigForSidecar, } from "./sidecar/rpc-client.js";
|
|
11
11
|
export const AF_INET = 2;
|
|
12
12
|
export const AF_UNIX = 1;
|
|
13
13
|
export const SOCK_STREAM = 1;
|
|
14
14
|
export const SOCK_DGRAM = 2;
|
|
15
15
|
export const SIGTERM = 15;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
const NODE_RUNTIME_BOOTSTRAP_COMMANDS = [
|
|
17
|
+
"node",
|
|
18
|
+
"npm",
|
|
19
|
+
"npx",
|
|
20
|
+
"python",
|
|
21
|
+
"python3",
|
|
22
|
+
];
|
|
22
23
|
const KERNEL_POSIX_BOOTSTRAP_DIRS = [
|
|
23
24
|
"/dev",
|
|
24
25
|
"/proc",
|
|
@@ -36,7 +37,8 @@ const KERNEL_POSIX_BOOTSTRAP_DIRS = [
|
|
|
36
37
|
"/mnt",
|
|
37
38
|
"/media",
|
|
38
39
|
"/home",
|
|
39
|
-
"/home/
|
|
40
|
+
"/home/agentos",
|
|
41
|
+
"/workspace",
|
|
40
42
|
"/usr",
|
|
41
43
|
"/usr/bin",
|
|
42
44
|
"/usr/games",
|
|
@@ -65,9 +67,23 @@ const SIDECAR_BUILD_INPUTS = [
|
|
|
65
67
|
path.join(REPO_ROOT, "Cargo.toml"),
|
|
66
68
|
path.join(REPO_ROOT, "Cargo.lock"),
|
|
67
69
|
path.join(REPO_ROOT, "crates/bridge"),
|
|
70
|
+
path.join(REPO_ROOT, "crates/build-support"),
|
|
68
71
|
path.join(REPO_ROOT, "crates/execution"),
|
|
69
72
|
path.join(REPO_ROOT, "crates/kernel"),
|
|
70
|
-
path.join(REPO_ROOT, "crates/
|
|
73
|
+
path.join(REPO_ROOT, "crates/agentos-protocol"),
|
|
74
|
+
path.join(REPO_ROOT, "crates/agentos-sidecar"),
|
|
75
|
+
path.join(REPO_ROOT, "crates/native-sidecar"),
|
|
76
|
+
path.join(REPO_ROOT, "crates/native-sidecar-core"),
|
|
77
|
+
path.join(REPO_ROOT, "crates/sidecar-protocol"),
|
|
78
|
+
path.join(REPO_ROOT, "crates/v8-runtime"),
|
|
79
|
+
path.join(REPO_ROOT, "crates/vfs"),
|
|
80
|
+
path.join(REPO_ROOT, "crates/vm-config"),
|
|
81
|
+
path.join(REPO_ROOT, "packages/build-tools/bridge-src"),
|
|
82
|
+
path.join(REPO_ROOT, "packages/build-tools/package.json"),
|
|
83
|
+
path.join(REPO_ROOT, "packages/build-tools/scripts/build-v8-bridge.mjs"),
|
|
84
|
+
path.join(REPO_ROOT, "packages/core/fixtures/base-filesystem.json"),
|
|
85
|
+
path.join(REPO_ROOT, "packages/runtime-core/fixtures/base-filesystem.json"),
|
|
86
|
+
path.join(REPO_ROOT, "pnpm-lock.yaml"),
|
|
71
87
|
];
|
|
72
88
|
let ensuredSidecarBinary = null;
|
|
73
89
|
export class KernelError extends Error {
|
|
@@ -106,336 +122,6 @@ function dirnameVirtual(inputPath) {
|
|
|
106
122
|
const parts = normalized.split("/").filter(Boolean);
|
|
107
123
|
return parts.length <= 1 ? "/" : `/${parts.slice(0, -1).join("/")}`;
|
|
108
124
|
}
|
|
109
|
-
let nextInode = 1;
|
|
110
|
-
export class InMemoryFileSystem {
|
|
111
|
-
entries = new Map();
|
|
112
|
-
constructor() {
|
|
113
|
-
this.entries.set("/", this.newDirectory());
|
|
114
|
-
}
|
|
115
|
-
async readFile(targetPath) {
|
|
116
|
-
const entry = this.resolveEntry(targetPath);
|
|
117
|
-
if (!entry || entry.type !== "file") {
|
|
118
|
-
throw errnoError("ENOENT", `open '${targetPath}'`);
|
|
119
|
-
}
|
|
120
|
-
entry.atimeMs = Date.now();
|
|
121
|
-
return entry.data;
|
|
122
|
-
}
|
|
123
|
-
async readTextFile(targetPath) {
|
|
124
|
-
return new TextDecoder().decode(await this.readFile(targetPath));
|
|
125
|
-
}
|
|
126
|
-
async readDir(targetPath) {
|
|
127
|
-
return (await this.readDirWithTypes(targetPath)).map((entry) => entry.name);
|
|
128
|
-
}
|
|
129
|
-
async readDirWithTypes(targetPath) {
|
|
130
|
-
const resolved = this.resolvePath(targetPath);
|
|
131
|
-
const entry = this.entries.get(resolved);
|
|
132
|
-
if (!entry || entry.type !== "dir") {
|
|
133
|
-
throw errnoError("ENOENT", `scandir '${targetPath}'`);
|
|
134
|
-
}
|
|
135
|
-
const prefix = resolved === "/" ? "/" : `${resolved}/`;
|
|
136
|
-
const output = new Map();
|
|
137
|
-
for (const [entryPath, candidate] of this.entries) {
|
|
138
|
-
if (!entryPath.startsWith(prefix))
|
|
139
|
-
continue;
|
|
140
|
-
const rest = entryPath.slice(prefix.length);
|
|
141
|
-
if (!rest || rest.includes("/"))
|
|
142
|
-
continue;
|
|
143
|
-
output.set(rest, {
|
|
144
|
-
name: rest,
|
|
145
|
-
isDirectory: candidate.type === "dir",
|
|
146
|
-
isSymbolicLink: candidate.type === "symlink",
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
return [...output.values()];
|
|
150
|
-
}
|
|
151
|
-
async writeFile(targetPath, content) {
|
|
152
|
-
const normalized = normalizePath(targetPath);
|
|
153
|
-
await this.mkdir(dirnameVirtual(normalized), { recursive: true });
|
|
154
|
-
const data = typeof content === "string" ? new TextEncoder().encode(content) : content;
|
|
155
|
-
const existing = this.entries.get(normalized);
|
|
156
|
-
if (existing?.type === "file") {
|
|
157
|
-
existing.data = data;
|
|
158
|
-
existing.mtimeMs = Date.now();
|
|
159
|
-
existing.ctimeMs = Date.now();
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const now = Date.now();
|
|
163
|
-
this.entries.set(normalized, {
|
|
164
|
-
type: "file",
|
|
165
|
-
data,
|
|
166
|
-
mode: S_IFREG | 0o644,
|
|
167
|
-
uid: 0,
|
|
168
|
-
gid: 0,
|
|
169
|
-
nlink: 1,
|
|
170
|
-
ino: nextInode++,
|
|
171
|
-
atimeMs: now,
|
|
172
|
-
mtimeMs: now,
|
|
173
|
-
ctimeMs: now,
|
|
174
|
-
birthtimeMs: now,
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
async createDir(targetPath) {
|
|
178
|
-
const normalized = normalizePath(targetPath);
|
|
179
|
-
if (!this.entries.has(dirnameVirtual(normalized))) {
|
|
180
|
-
throw errnoError("ENOENT", `mkdir '${targetPath}'`);
|
|
181
|
-
}
|
|
182
|
-
if (!this.entries.has(normalized)) {
|
|
183
|
-
this.entries.set(normalized, this.newDirectory());
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
async mkdir(targetPath, options) {
|
|
187
|
-
const normalized = normalizePath(targetPath);
|
|
188
|
-
if (options?.recursive === false) {
|
|
189
|
-
return this.createDir(normalized);
|
|
190
|
-
}
|
|
191
|
-
let current = "";
|
|
192
|
-
for (const part of normalized.split("/").filter(Boolean)) {
|
|
193
|
-
current += `/${part}`;
|
|
194
|
-
if (!this.entries.has(current)) {
|
|
195
|
-
this.entries.set(current, this.newDirectory());
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
async exists(targetPath) {
|
|
200
|
-
try {
|
|
201
|
-
return this.entries.has(this.resolvePath(targetPath));
|
|
202
|
-
}
|
|
203
|
-
catch {
|
|
204
|
-
return false;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
async stat(targetPath) {
|
|
208
|
-
const entry = this.resolveEntry(targetPath);
|
|
209
|
-
if (!entry)
|
|
210
|
-
throw errnoError("ENOENT", `stat '${targetPath}'`);
|
|
211
|
-
return this.toStat(entry);
|
|
212
|
-
}
|
|
213
|
-
async removeFile(targetPath) {
|
|
214
|
-
const resolved = this.resolvePath(targetPath);
|
|
215
|
-
const entry = this.entries.get(resolved);
|
|
216
|
-
if (!entry || entry.type === "dir") {
|
|
217
|
-
throw errnoError("ENOENT", `unlink '${targetPath}'`);
|
|
218
|
-
}
|
|
219
|
-
this.entries.delete(resolved);
|
|
220
|
-
}
|
|
221
|
-
async removeDir(targetPath) {
|
|
222
|
-
const resolved = this.resolvePath(targetPath);
|
|
223
|
-
if (resolved === "/") {
|
|
224
|
-
throw errnoError("EPERM", "operation not permitted");
|
|
225
|
-
}
|
|
226
|
-
const entry = this.entries.get(resolved);
|
|
227
|
-
if (!entry || entry.type !== "dir") {
|
|
228
|
-
throw errnoError("ENOENT", `rmdir '${targetPath}'`);
|
|
229
|
-
}
|
|
230
|
-
const prefix = `${resolved}/`;
|
|
231
|
-
for (const key of this.entries.keys()) {
|
|
232
|
-
if (key.startsWith(prefix)) {
|
|
233
|
-
throw errnoError("ENOTEMPTY", `directory not empty '${targetPath}'`);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
this.entries.delete(resolved);
|
|
237
|
-
}
|
|
238
|
-
async rename(oldPath, newPath) {
|
|
239
|
-
const oldResolved = this.resolvePath(oldPath);
|
|
240
|
-
const newResolved = normalizePath(newPath);
|
|
241
|
-
const entry = this.entries.get(oldResolved);
|
|
242
|
-
if (!entry)
|
|
243
|
-
throw errnoError("ENOENT", `rename '${oldPath}'`);
|
|
244
|
-
if (!this.entries.has(dirnameVirtual(newResolved))) {
|
|
245
|
-
throw errnoError("ENOENT", `rename '${newPath}'`);
|
|
246
|
-
}
|
|
247
|
-
if (entry.type !== "dir") {
|
|
248
|
-
this.entries.set(newResolved, entry);
|
|
249
|
-
this.entries.delete(oldResolved);
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
const prefix = `${oldResolved}/`;
|
|
253
|
-
const moved = [];
|
|
254
|
-
for (const candidate of this.entries) {
|
|
255
|
-
if (candidate[0] === oldResolved || candidate[0].startsWith(prefix)) {
|
|
256
|
-
moved.push(candidate);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
for (const [candidatePath] of moved) {
|
|
260
|
-
this.entries.delete(candidatePath);
|
|
261
|
-
}
|
|
262
|
-
for (const [candidatePath, candidate] of moved) {
|
|
263
|
-
const nextPath = candidatePath === oldResolved
|
|
264
|
-
? newResolved
|
|
265
|
-
: `${newResolved}${candidatePath.slice(oldResolved.length)}`;
|
|
266
|
-
this.entries.set(nextPath, candidate);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
async realpath(targetPath) {
|
|
270
|
-
return this.resolvePath(targetPath);
|
|
271
|
-
}
|
|
272
|
-
async symlink(target, linkPath) {
|
|
273
|
-
const normalized = normalizePath(linkPath);
|
|
274
|
-
if (this.entries.has(normalized)) {
|
|
275
|
-
throw errnoError("EEXIST", `symlink '${linkPath}'`);
|
|
276
|
-
}
|
|
277
|
-
const now = Date.now();
|
|
278
|
-
this.entries.set(normalized, {
|
|
279
|
-
type: "symlink",
|
|
280
|
-
target,
|
|
281
|
-
mode: S_IFLNK | 0o777,
|
|
282
|
-
uid: 0,
|
|
283
|
-
gid: 0,
|
|
284
|
-
nlink: 1,
|
|
285
|
-
ino: nextInode++,
|
|
286
|
-
atimeMs: now,
|
|
287
|
-
mtimeMs: now,
|
|
288
|
-
ctimeMs: now,
|
|
289
|
-
birthtimeMs: now,
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
async readlink(targetPath) {
|
|
293
|
-
const normalized = normalizePath(targetPath);
|
|
294
|
-
const entry = this.entries.get(normalized);
|
|
295
|
-
if (!entry || entry.type !== "symlink") {
|
|
296
|
-
throw errnoError("ENOENT", `readlink '${targetPath}'`);
|
|
297
|
-
}
|
|
298
|
-
return entry.target;
|
|
299
|
-
}
|
|
300
|
-
async lstat(targetPath) {
|
|
301
|
-
const entry = this.entries.get(normalizePath(targetPath));
|
|
302
|
-
if (!entry)
|
|
303
|
-
throw errnoError("ENOENT", `lstat '${targetPath}'`);
|
|
304
|
-
return this.toStat(entry);
|
|
305
|
-
}
|
|
306
|
-
async link(oldPath, newPath) {
|
|
307
|
-
const entry = this.resolveEntry(oldPath);
|
|
308
|
-
if (!entry || entry.type !== "file") {
|
|
309
|
-
throw errnoError("ENOENT", `link '${oldPath}'`);
|
|
310
|
-
}
|
|
311
|
-
const normalized = normalizePath(newPath);
|
|
312
|
-
if (this.entries.has(normalized)) {
|
|
313
|
-
throw errnoError("EEXIST", `link '${newPath}'`);
|
|
314
|
-
}
|
|
315
|
-
entry.nlink += 1;
|
|
316
|
-
this.entries.set(normalized, entry);
|
|
317
|
-
}
|
|
318
|
-
async chmod(targetPath, mode) {
|
|
319
|
-
const entry = this.resolveEntry(targetPath);
|
|
320
|
-
if (!entry)
|
|
321
|
-
throw errnoError("ENOENT", `chmod '${targetPath}'`);
|
|
322
|
-
const typeBits = mode & 0o170000;
|
|
323
|
-
entry.mode =
|
|
324
|
-
typeBits === 0 ? (entry.mode & 0o170000) | (mode & 0o7777) : mode;
|
|
325
|
-
entry.ctimeMs = Date.now();
|
|
326
|
-
}
|
|
327
|
-
async chown(targetPath, uid, gid) {
|
|
328
|
-
const entry = this.resolveEntry(targetPath);
|
|
329
|
-
if (!entry)
|
|
330
|
-
throw errnoError("ENOENT", `chown '${targetPath}'`);
|
|
331
|
-
entry.uid = uid;
|
|
332
|
-
entry.gid = gid;
|
|
333
|
-
entry.ctimeMs = Date.now();
|
|
334
|
-
}
|
|
335
|
-
async utimes(targetPath, atime, mtime) {
|
|
336
|
-
const entry = this.resolveEntry(targetPath);
|
|
337
|
-
if (!entry)
|
|
338
|
-
throw errnoError("ENOENT", `utimes '${targetPath}'`);
|
|
339
|
-
entry.atimeMs = atime;
|
|
340
|
-
entry.mtimeMs = mtime;
|
|
341
|
-
entry.ctimeMs = Date.now();
|
|
342
|
-
}
|
|
343
|
-
async truncate(targetPath, length) {
|
|
344
|
-
const entry = this.resolveEntry(targetPath);
|
|
345
|
-
if (!entry || entry.type !== "file") {
|
|
346
|
-
throw errnoError("ENOENT", `truncate '${targetPath}'`);
|
|
347
|
-
}
|
|
348
|
-
if (length < entry.data.length) {
|
|
349
|
-
entry.data = entry.data.slice(0, length);
|
|
350
|
-
}
|
|
351
|
-
else if (length > entry.data.length) {
|
|
352
|
-
const expanded = new Uint8Array(length);
|
|
353
|
-
expanded.set(entry.data);
|
|
354
|
-
entry.data = expanded;
|
|
355
|
-
}
|
|
356
|
-
entry.mtimeMs = Date.now();
|
|
357
|
-
entry.ctimeMs = Date.now();
|
|
358
|
-
}
|
|
359
|
-
async pread(targetPath, offset, length) {
|
|
360
|
-
const entry = this.resolveEntry(targetPath);
|
|
361
|
-
if (!entry || entry.type !== "file") {
|
|
362
|
-
throw errnoError("ENOENT", `open '${targetPath}'`);
|
|
363
|
-
}
|
|
364
|
-
if (offset >= entry.data.length)
|
|
365
|
-
return new Uint8Array(0);
|
|
366
|
-
return entry.data.slice(offset, Math.min(offset + length, entry.data.length));
|
|
367
|
-
}
|
|
368
|
-
async pwrite(targetPath, offset, data) {
|
|
369
|
-
const entry = this.resolveEntry(targetPath);
|
|
370
|
-
if (!entry || entry.type !== "file") {
|
|
371
|
-
throw errnoError("ENOENT", `open '${targetPath}'`);
|
|
372
|
-
}
|
|
373
|
-
const nextSize = Math.max(entry.data.length, offset + data.length);
|
|
374
|
-
const updated = new Uint8Array(nextSize);
|
|
375
|
-
updated.set(entry.data);
|
|
376
|
-
updated.set(data, offset);
|
|
377
|
-
entry.data = updated;
|
|
378
|
-
entry.mtimeMs = Date.now();
|
|
379
|
-
entry.ctimeMs = Date.now();
|
|
380
|
-
}
|
|
381
|
-
resolvePath(targetPath, depth = 0) {
|
|
382
|
-
if (depth > MAX_SYMLINK_DEPTH) {
|
|
383
|
-
throw errnoError("ELOOP", `too many symbolic links '${targetPath}'`);
|
|
384
|
-
}
|
|
385
|
-
const normalized = normalizePath(targetPath);
|
|
386
|
-
const entry = this.entries.get(normalized);
|
|
387
|
-
if (!entry)
|
|
388
|
-
return normalized;
|
|
389
|
-
if (entry.type === "symlink") {
|
|
390
|
-
const target = entry.target.startsWith("/")
|
|
391
|
-
? entry.target
|
|
392
|
-
: `${dirnameVirtual(normalized)}/${entry.target}`;
|
|
393
|
-
return this.resolvePath(target, depth + 1);
|
|
394
|
-
}
|
|
395
|
-
return normalized;
|
|
396
|
-
}
|
|
397
|
-
resolveEntry(targetPath) {
|
|
398
|
-
return this.entries.get(this.resolvePath(targetPath));
|
|
399
|
-
}
|
|
400
|
-
newDirectory() {
|
|
401
|
-
const now = Date.now();
|
|
402
|
-
return {
|
|
403
|
-
type: "dir",
|
|
404
|
-
mode: S_IFDIR | 0o755,
|
|
405
|
-
uid: 0,
|
|
406
|
-
gid: 0,
|
|
407
|
-
nlink: 2,
|
|
408
|
-
ino: nextInode++,
|
|
409
|
-
atimeMs: now,
|
|
410
|
-
mtimeMs: now,
|
|
411
|
-
ctimeMs: now,
|
|
412
|
-
birthtimeMs: now,
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
toStat(entry) {
|
|
416
|
-
const size = entry.type === "file" ? entry.data.length : 4096;
|
|
417
|
-
return {
|
|
418
|
-
mode: entry.mode,
|
|
419
|
-
size,
|
|
420
|
-
blocks: size === 0 ? 0 : Math.ceil(size / 512),
|
|
421
|
-
dev: 1,
|
|
422
|
-
rdev: 0,
|
|
423
|
-
isDirectory: entry.type === "dir",
|
|
424
|
-
isSymbolicLink: entry.type === "symlink",
|
|
425
|
-
atimeMs: entry.atimeMs,
|
|
426
|
-
mtimeMs: entry.mtimeMs,
|
|
427
|
-
ctimeMs: entry.ctimeMs,
|
|
428
|
-
birthtimeMs: entry.birthtimeMs,
|
|
429
|
-
ino: entry.ino,
|
|
430
|
-
nlink: entry.nlink,
|
|
431
|
-
uid: entry.uid,
|
|
432
|
-
gid: entry.gid,
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
export function createInMemoryFileSystem() {
|
|
437
|
-
return new InMemoryFileSystem();
|
|
438
|
-
}
|
|
439
125
|
export class NodeFileSystem {
|
|
440
126
|
rootPath;
|
|
441
127
|
constructor(options) {
|
|
@@ -729,6 +415,7 @@ export function createNodeDriver(options = {}) {
|
|
|
729
415
|
network: options.networkAdapter,
|
|
730
416
|
commandExecutor: options.commandExecutor,
|
|
731
417
|
permissions: options.permissions,
|
|
418
|
+
mounts: options.mounts ?? [],
|
|
732
419
|
runtime: {
|
|
733
420
|
process: options.processConfig ?? {},
|
|
734
421
|
os: options.osConfig ?? {},
|
|
@@ -815,8 +502,6 @@ export const WASMVM_COMMANDS = Object.freeze([
|
|
|
815
502
|
"unzip",
|
|
816
503
|
"sqlite3",
|
|
817
504
|
"curl",
|
|
818
|
-
"wget",
|
|
819
|
-
"make",
|
|
820
505
|
"git",
|
|
821
506
|
"git-remote-http",
|
|
822
507
|
"git-remote-https",
|
|
@@ -915,7 +600,6 @@ export const DEFAULT_FIRST_PARTY_TIERS = Object.freeze({
|
|
|
915
600
|
nice: "full",
|
|
916
601
|
nohup: "full",
|
|
917
602
|
stdbuf: "full",
|
|
918
|
-
make: "full",
|
|
919
603
|
codex: "full",
|
|
920
604
|
"codex-exec": "full",
|
|
921
605
|
git: "full",
|
|
@@ -981,7 +665,6 @@ export const DEFAULT_FIRST_PARTY_TIERS = Object.freeze({
|
|
|
981
665
|
tac: "read-only",
|
|
982
666
|
tsort: "read-only",
|
|
983
667
|
curl: "full",
|
|
984
|
-
wget: "full",
|
|
985
668
|
sqlite3: "read-write",
|
|
986
669
|
});
|
|
987
670
|
class NativeRuntimeDescriptor {
|
|
@@ -1015,7 +698,7 @@ function isWasmBinaryFile(filePath) {
|
|
|
1015
698
|
function discoverWasmCommandEntries(commandDirs) {
|
|
1016
699
|
const discovered = [];
|
|
1017
700
|
const seen = new Set();
|
|
1018
|
-
|
|
701
|
+
for (const commandDir of commandDirs) {
|
|
1019
702
|
let entries;
|
|
1020
703
|
try {
|
|
1021
704
|
entries = fsSync
|
|
@@ -1023,7 +706,7 @@ function discoverWasmCommandEntries(commandDirs) {
|
|
|
1023
706
|
.sort((left, right) => left.localeCompare(right));
|
|
1024
707
|
}
|
|
1025
708
|
catch {
|
|
1026
|
-
|
|
709
|
+
continue;
|
|
1027
710
|
}
|
|
1028
711
|
for (const entry of entries) {
|
|
1029
712
|
if (entry.startsWith("."))
|
|
@@ -1036,7 +719,6 @@ function discoverWasmCommandEntries(commandDirs) {
|
|
|
1036
719
|
discovered.push({
|
|
1037
720
|
name: entry,
|
|
1038
721
|
hostPath: fullPath,
|
|
1039
|
-
dirOffset,
|
|
1040
722
|
});
|
|
1041
723
|
continue;
|
|
1042
724
|
}
|
|
@@ -1047,13 +729,12 @@ function discoverWasmCommandEntries(commandDirs) {
|
|
|
1047
729
|
discovered.push({
|
|
1048
730
|
name: entry,
|
|
1049
731
|
hostPath: fullPath,
|
|
1050
|
-
dirOffset,
|
|
1051
732
|
});
|
|
1052
733
|
}
|
|
1053
734
|
}
|
|
1054
735
|
catch { }
|
|
1055
736
|
}
|
|
1056
|
-
}
|
|
737
|
+
}
|
|
1057
738
|
return discovered;
|
|
1058
739
|
}
|
|
1059
740
|
class WasmVmRuntimeDescriptor {
|
|
@@ -1063,7 +744,6 @@ class WasmVmRuntimeDescriptor {
|
|
|
1063
744
|
commandDirs;
|
|
1064
745
|
_commandPaths = new Map();
|
|
1065
746
|
_moduleCache = new Map();
|
|
1066
|
-
commandDirOffsets = new Map();
|
|
1067
747
|
constructor(options) {
|
|
1068
748
|
this.commandDirs =
|
|
1069
749
|
options.commandDirs && options.commandDirs.length > 0
|
|
@@ -1094,17 +774,6 @@ class WasmVmRuntimeDescriptor {
|
|
|
1094
774
|
this.refreshDiscovery();
|
|
1095
775
|
return this._commandPaths.has(normalized);
|
|
1096
776
|
}
|
|
1097
|
-
getGuestCommandPaths(startIndex) {
|
|
1098
|
-
const guestPaths = new Map();
|
|
1099
|
-
for (const [name] of this._commandPaths) {
|
|
1100
|
-
const dirOffset = this.commandDirOffsets.get(name);
|
|
1101
|
-
if (dirOffset === undefined) {
|
|
1102
|
-
continue;
|
|
1103
|
-
}
|
|
1104
|
-
guestPaths.set(name, `/__secure_exec/commands/${startIndex + dirOffset}/${name}`);
|
|
1105
|
-
}
|
|
1106
|
-
return guestPaths;
|
|
1107
|
-
}
|
|
1108
777
|
recordModuleExecution(command) {
|
|
1109
778
|
const normalized = normalizeCommandLookup(command);
|
|
1110
779
|
if (this._commandPaths.has(normalized) ||
|
|
@@ -1120,11 +789,9 @@ class WasmVmRuntimeDescriptor {
|
|
|
1120
789
|
const discovered = discoverWasmCommandEntries(this.commandDirs);
|
|
1121
790
|
this.commands.length = 0;
|
|
1122
791
|
this._commandPaths.clear();
|
|
1123
|
-
this.commandDirOffsets.clear();
|
|
1124
792
|
for (const entry of discovered) {
|
|
1125
793
|
this.commands.push(entry.name);
|
|
1126
794
|
this._commandPaths.set(entry.name, entry.hostPath);
|
|
1127
|
-
this.commandDirOffsets.set(entry.name, entry.dirOffset);
|
|
1128
795
|
}
|
|
1129
796
|
}
|
|
1130
797
|
}
|
|
@@ -1190,8 +857,8 @@ function ensureNativeSidecarBinary() {
|
|
|
1190
857
|
function rootEntryExecutable(kind, mode) {
|
|
1191
858
|
return kind === "file" && (mode & 0o111) !== 0;
|
|
1192
859
|
}
|
|
1193
|
-
function createBootstrapEntries(
|
|
1194
|
-
|
|
860
|
+
function createBootstrapEntries() {
|
|
861
|
+
return [
|
|
1195
862
|
{
|
|
1196
863
|
path: "/",
|
|
1197
864
|
kind: "directory",
|
|
@@ -1203,7 +870,7 @@ function createBootstrapEntries(commandNames) {
|
|
|
1203
870
|
...KERNEL_POSIX_BOOTSTRAP_DIRS.map((entryPath) => ({
|
|
1204
871
|
path: entryPath,
|
|
1205
872
|
kind: "directory",
|
|
1206
|
-
mode: 0o755,
|
|
873
|
+
mode: entryPath === "/tmp" || entryPath === "/var/tmp" ? 0o1777 : 0o755,
|
|
1207
874
|
uid: 0,
|
|
1208
875
|
gid: 0,
|
|
1209
876
|
executable: false,
|
|
@@ -1219,19 +886,6 @@ function createBootstrapEntries(commandNames) {
|
|
|
1219
886
|
executable: false,
|
|
1220
887
|
},
|
|
1221
888
|
];
|
|
1222
|
-
for (const command of [...new Set(commandNames)].sort((left, right) => left.localeCompare(right))) {
|
|
1223
|
-
entries.push({
|
|
1224
|
-
path: `/bin/${command}`,
|
|
1225
|
-
kind: "file",
|
|
1226
|
-
mode: 0o755,
|
|
1227
|
-
uid: 0,
|
|
1228
|
-
gid: 0,
|
|
1229
|
-
content: KERNEL_COMMAND_STUB,
|
|
1230
|
-
encoding: "utf8",
|
|
1231
|
-
executable: true,
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
1234
|
-
return entries;
|
|
1235
889
|
}
|
|
1236
890
|
function mergeRootFilesystemEntries(baseEntries, overrideEntries) {
|
|
1237
891
|
const merged = new Map();
|
|
@@ -1372,23 +1026,6 @@ function planNodeFilesystemPassthroughMounts(filesystem, existingMounts) {
|
|
|
1372
1026
|
passthroughDirectories,
|
|
1373
1027
|
};
|
|
1374
1028
|
}
|
|
1375
|
-
function collectGuestCommandPaths(commandDirs, startIndex = 0) {
|
|
1376
|
-
const guestPaths = new Map();
|
|
1377
|
-
for (const entry of discoverWasmCommandEntries(commandDirs)) {
|
|
1378
|
-
if (!guestPaths.has(entry.name)) {
|
|
1379
|
-
guestPaths.set(entry.name, `/__secure_exec/commands/${startIndex + entry.dirOffset}/${entry.name}`);
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1382
|
-
return guestPaths;
|
|
1383
|
-
}
|
|
1384
|
-
async function ensureCommandStubs(proxy, commands) {
|
|
1385
|
-
const rootView = proxy.createRootView();
|
|
1386
|
-
for (const command of commands) {
|
|
1387
|
-
const stubPath = `/bin/${command}`;
|
|
1388
|
-
await rootView.writeFile(stubPath, KERNEL_COMMAND_STUB);
|
|
1389
|
-
await rootView.chmod(stubPath, 0o755);
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
1029
|
class DeferredFileSystem {
|
|
1393
1030
|
getFilesystem;
|
|
1394
1031
|
constructor(getFilesystem) {
|
|
@@ -1496,7 +1133,10 @@ const VIRTUAL_FILESYSTEM_METHOD_NAMES = [
|
|
|
1496
1133
|
"pread",
|
|
1497
1134
|
"pwrite",
|
|
1498
1135
|
];
|
|
1499
|
-
const
|
|
1136
|
+
const DEFAULT_LIVE_FILESYSTEM_SYNC_MAX_BYTES = 64 * 1024 * 1024;
|
|
1137
|
+
class LiveFilesystemSyncLimitError extends Error {
|
|
1138
|
+
code = "ERR_AGENTOS_LIVE_FILESYSTEM_SYNC_LIMIT";
|
|
1139
|
+
}
|
|
1500
1140
|
function topLevelSyncRoot(targetPath) {
|
|
1501
1141
|
const normalized = normalizePath(targetPath);
|
|
1502
1142
|
const [first] = normalized.split("/").filter(Boolean);
|
|
@@ -1528,50 +1168,71 @@ async function ensureBoundParentDirectory(methods, targetPath) {
|
|
|
1528
1168
|
recursive: true,
|
|
1529
1169
|
});
|
|
1530
1170
|
}
|
|
1531
|
-
async function syncLiveFilesystemToBoundMethods(live, methods, paths) {
|
|
1171
|
+
async function syncLiveFilesystemToBoundMethods(live, methods, paths, maxBytes) {
|
|
1172
|
+
const snapshot = [];
|
|
1173
|
+
const usage = { bytes: 0 };
|
|
1532
1174
|
for (const targetPath of [...new Set(paths.map(normalizePath))].sort((left, right) => left.localeCompare(right))) {
|
|
1533
1175
|
if (!(await live.exists(targetPath).catch(() => false))) {
|
|
1534
1176
|
continue;
|
|
1535
1177
|
}
|
|
1536
|
-
await
|
|
1178
|
+
await snapshotLiveFilesystemPath(live, targetPath, snapshot, usage, maxBytes);
|
|
1179
|
+
}
|
|
1180
|
+
if (usage.bytes >= maxBytes * 0.8) {
|
|
1181
|
+
process.emitWarning(`live filesystem sync retained ${usage.bytes} of ${maxBytes} bytes; ` +
|
|
1182
|
+
"raise createKernel({ maxFilesystemBytes }) before increasing VM filesystem limits", { code: "AGENTOS_LIVE_FILESYSTEM_SYNC_NEAR_LIMIT" });
|
|
1183
|
+
}
|
|
1184
|
+
for (const entry of snapshot) {
|
|
1185
|
+
await applyLiveFilesystemSnapshotEntry(methods, entry);
|
|
1537
1186
|
}
|
|
1538
1187
|
}
|
|
1539
|
-
async function
|
|
1540
|
-
const stat =
|
|
1541
|
-
? await live.stat(targetPath)
|
|
1542
|
-
: await live.lstat(targetPath);
|
|
1188
|
+
async function snapshotLiveFilesystemPath(live, targetPath, snapshot, usage, maxBytes, knownEntry) {
|
|
1189
|
+
const stat = knownEntry ??
|
|
1190
|
+
(targetPath === "/" ? await live.stat(targetPath) : await live.lstat(targetPath));
|
|
1543
1191
|
if (stat.isSymbolicLink) {
|
|
1544
|
-
|
|
1545
|
-
await callBoundFilesystemMethod(methods, "removeFile", targetPath).catch(() => { });
|
|
1546
|
-
await callBoundFilesystemMethod(methods, "symlink", await live.readlink(targetPath), targetPath);
|
|
1192
|
+
snapshot.push({ kind: "symlink", path: targetPath, target: await live.readlink(targetPath) });
|
|
1547
1193
|
return;
|
|
1548
1194
|
}
|
|
1549
1195
|
if (stat.isDirectory) {
|
|
1550
|
-
|
|
1551
|
-
recursive: true,
|
|
1552
|
-
});
|
|
1196
|
+
snapshot.push({ kind: "directory", path: targetPath });
|
|
1553
1197
|
const children = (await live.readDirWithTypes(targetPath))
|
|
1554
|
-
.
|
|
1555
|
-
.
|
|
1556
|
-
.sort((left, right) => left.localeCompare(right));
|
|
1198
|
+
.filter((entry) => entry.name !== "." && entry.name !== "..")
|
|
1199
|
+
.sort((left, right) => left.name.localeCompare(right.name));
|
|
1557
1200
|
for (const child of children) {
|
|
1558
|
-
await
|
|
1559
|
-
? posixPath.join("/", child)
|
|
1560
|
-
: posixPath.join(targetPath, child));
|
|
1201
|
+
await snapshotLiveFilesystemPath(live, targetPath === "/"
|
|
1202
|
+
? posixPath.join("/", child.name)
|
|
1203
|
+
: posixPath.join(targetPath, child.name), snapshot, usage, maxBytes, child);
|
|
1561
1204
|
}
|
|
1562
1205
|
return;
|
|
1563
1206
|
}
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1207
|
+
const fileSize = "size" in stat && typeof stat.size === "number"
|
|
1208
|
+
? stat.size
|
|
1209
|
+
: (await live.lstat(targetPath)).size;
|
|
1210
|
+
if (fileSize > maxBytes - usage.bytes) {
|
|
1211
|
+
throw new LiveFilesystemSyncLimitError(`live filesystem sync for ${targetPath} exceeds ${maxBytes} bytes ` +
|
|
1212
|
+
"(createKernel maxFilesystemBytes); raise createKernel({ maxFilesystemBytes })");
|
|
1213
|
+
}
|
|
1214
|
+
const content = await live.readFile(targetPath);
|
|
1215
|
+
if (content.byteLength > maxBytes - usage.bytes) {
|
|
1216
|
+
throw new LiveFilesystemSyncLimitError(`live filesystem sync for ${targetPath} exceeds ${maxBytes} bytes ` +
|
|
1217
|
+
"(createKernel maxFilesystemBytes); raise createKernel({ maxFilesystemBytes })");
|
|
1572
1218
|
}
|
|
1219
|
+
usage.bytes += content.byteLength;
|
|
1220
|
+
snapshot.push({ kind: "file", path: targetPath, content });
|
|
1573
1221
|
}
|
|
1574
|
-
function
|
|
1222
|
+
async function applyLiveFilesystemSnapshotEntry(methods, entry) {
|
|
1223
|
+
if (entry.kind === "directory") {
|
|
1224
|
+
await callBoundFilesystemMethod(methods, "mkdir", entry.path, { recursive: true });
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
await ensureBoundParentDirectory(methods, entry.path);
|
|
1228
|
+
if (entry.kind === "symlink") {
|
|
1229
|
+
await callBoundFilesystemMethod(methods, "removeFile", entry.path).catch(() => { });
|
|
1230
|
+
await callBoundFilesystemMethod(methods, "symlink", entry.target, entry.path);
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
await callBoundFilesystemMethod(methods, "writeFile", entry.path, entry.content);
|
|
1234
|
+
}
|
|
1235
|
+
function bindLiveFilesystem(target, getFilesystem, maxBytes) {
|
|
1575
1236
|
const fallback = {};
|
|
1576
1237
|
for (const method of VIRTUAL_FILESYSTEM_METHOD_NAMES) {
|
|
1577
1238
|
const candidate = target[method];
|
|
@@ -1597,7 +1258,7 @@ function bindLiveFilesystem(target, getFilesystem) {
|
|
|
1597
1258
|
if (!filesystem) {
|
|
1598
1259
|
return;
|
|
1599
1260
|
}
|
|
1600
|
-
await syncLiveFilesystemToBoundMethods(filesystem, fallback, paths);
|
|
1261
|
+
await syncLiveFilesystemToBoundMethods(filesystem, fallback, paths, maxBytes);
|
|
1601
1262
|
},
|
|
1602
1263
|
restore() {
|
|
1603
1264
|
for (const [method, delegate] of Object.entries(fallback)) {
|
|
@@ -1606,6 +1267,35 @@ function bindLiveFilesystem(target, getFilesystem) {
|
|
|
1606
1267
|
},
|
|
1607
1268
|
};
|
|
1608
1269
|
}
|
|
1270
|
+
function serializeLocalCompatMountForSidecar(mount) {
|
|
1271
|
+
return (mount.sidecarMount ??
|
|
1272
|
+
(mount.fs instanceof NodeFileSystem
|
|
1273
|
+
? serializeMountConfigForSidecar({
|
|
1274
|
+
path: mount.path,
|
|
1275
|
+
readOnly: mount.readOnly,
|
|
1276
|
+
plugin: {
|
|
1277
|
+
id: "host_dir",
|
|
1278
|
+
config: {
|
|
1279
|
+
hostPath: mount.fs.rootPath,
|
|
1280
|
+
readOnly: mount.readOnly,
|
|
1281
|
+
},
|
|
1282
|
+
},
|
|
1283
|
+
})
|
|
1284
|
+
: serializeMountConfigForSidecar({
|
|
1285
|
+
path: mount.path,
|
|
1286
|
+
driver: mount.fs,
|
|
1287
|
+
readOnly: mount.readOnly,
|
|
1288
|
+
})));
|
|
1289
|
+
}
|
|
1290
|
+
function makeLocalCompatMount(options) {
|
|
1291
|
+
const localMount = {
|
|
1292
|
+
path: normalizePath(options.path),
|
|
1293
|
+
fs: options.fs,
|
|
1294
|
+
readOnly: options.readOnly ?? false,
|
|
1295
|
+
};
|
|
1296
|
+
localMount.sidecarMount = serializeLocalCompatMountForSidecar(localMount);
|
|
1297
|
+
return localMount;
|
|
1298
|
+
}
|
|
1609
1299
|
class NativeKernel {
|
|
1610
1300
|
options;
|
|
1611
1301
|
env;
|
|
@@ -1627,12 +1317,11 @@ class NativeKernel {
|
|
|
1627
1317
|
pendingLocalMounts = [];
|
|
1628
1318
|
mountedCommandDirs = [];
|
|
1629
1319
|
mountedRuntimeDrivers = [];
|
|
1630
|
-
runtimeDriverCommandDirStarts = new Map();
|
|
1631
1320
|
loopbackExemptPorts;
|
|
1632
1321
|
constructor(options) {
|
|
1633
1322
|
this.options = options;
|
|
1634
1323
|
this.env = { ...(options.env ?? {}) };
|
|
1635
|
-
this.cwd = options.cwd ?? "/
|
|
1324
|
+
this.cwd = options.cwd ?? "/workspace";
|
|
1636
1325
|
this.socketTable = {
|
|
1637
1326
|
hasHostNetworkAdapter: () => Boolean(options.hostNetworkAdapter),
|
|
1638
1327
|
findListener: (request) => this.proxy?.findListener(request) ?? null,
|
|
@@ -1645,18 +1334,44 @@ class NativeKernel {
|
|
|
1645
1334
|
};
|
|
1646
1335
|
this.loopbackExemptPorts = [...(options.loopbackExemptPorts ?? [])];
|
|
1647
1336
|
for (const mount of options.mounts ?? []) {
|
|
1648
|
-
this.pendingLocalMounts.push({
|
|
1649
|
-
path:
|
|
1337
|
+
this.pendingLocalMounts.push(makeLocalCompatMount({
|
|
1338
|
+
path: mount.path,
|
|
1650
1339
|
fs: mount.fs,
|
|
1651
|
-
readOnly: mount.readOnly
|
|
1652
|
-
});
|
|
1340
|
+
readOnly: mount.readOnly,
|
|
1341
|
+
}));
|
|
1653
1342
|
}
|
|
1654
1343
|
this.vfs = new DeferredFileSystem(() => this.rootFilesystem);
|
|
1655
|
-
this.liveFilesystemBinding = bindLiveFilesystem(this.options.filesystem, () => this.rootFilesystem);
|
|
1344
|
+
this.liveFilesystemBinding = bindLiveFilesystem(this.options.filesystem, () => this.rootFilesystem, options.maxFilesystemBytes ?? DEFAULT_LIVE_FILESYSTEM_SYNC_MAX_BYTES);
|
|
1656
1345
|
}
|
|
1657
1346
|
get zombieTimerCount() {
|
|
1658
1347
|
return this.proxy?.zombieTimerCount ?? 0;
|
|
1659
1348
|
}
|
|
1349
|
+
async configureRuntimeCommandStubs(commands, commandDirs = this.mountedCommandDirs) {
|
|
1350
|
+
if (!this.client || !this.session || !this.vm) {
|
|
1351
|
+
throw new Error("kernel is not ready");
|
|
1352
|
+
}
|
|
1353
|
+
const sidecarMounts = commandDirs.map((commandDir, index) => serializeMountConfigForSidecar({
|
|
1354
|
+
path: `/__secure_exec/commands/${index}`,
|
|
1355
|
+
readOnly: true,
|
|
1356
|
+
plugin: {
|
|
1357
|
+
id: "host_dir",
|
|
1358
|
+
config: {
|
|
1359
|
+
hostPath: commandDir,
|
|
1360
|
+
readOnly: true,
|
|
1361
|
+
},
|
|
1362
|
+
},
|
|
1363
|
+
}));
|
|
1364
|
+
const localMounts = this.pendingLocalMounts.map((mount) => serializeLocalCompatMountForSidecar(mount));
|
|
1365
|
+
const configuredVm = await this.client.configureVm(this.session, this.vm, {
|
|
1366
|
+
mounts: [...localMounts, ...sidecarMounts],
|
|
1367
|
+
loopbackExemptPorts: this.loopbackExemptPorts,
|
|
1368
|
+
bootstrapCommands: [...new Set(commands)].sort((left, right) => left.localeCompare(right)),
|
|
1369
|
+
});
|
|
1370
|
+
return new Map(configuredVm.projectedCommands.map((command) => [
|
|
1371
|
+
command.name,
|
|
1372
|
+
command.guestPath,
|
|
1373
|
+
]));
|
|
1374
|
+
}
|
|
1660
1375
|
async mount(driver) {
|
|
1661
1376
|
await this.ensureReady();
|
|
1662
1377
|
if (!this.proxy || !this.client || !this.session || !this.vm) {
|
|
@@ -1668,7 +1383,7 @@ class NativeKernel {
|
|
|
1668
1383
|
this.commands.set(command, "node");
|
|
1669
1384
|
}
|
|
1670
1385
|
this.mountedRuntimeDrivers.push(driver);
|
|
1671
|
-
await
|
|
1386
|
+
await this.configureRuntimeCommandStubs(driver.commands);
|
|
1672
1387
|
return;
|
|
1673
1388
|
}
|
|
1674
1389
|
const commandDirs = driver.commandDirs ?? [];
|
|
@@ -1677,53 +1392,17 @@ class NativeKernel {
|
|
|
1677
1392
|
this.commands.set(command, "wasmvm");
|
|
1678
1393
|
}
|
|
1679
1394
|
this.mountedRuntimeDrivers.push(driver);
|
|
1680
|
-
await
|
|
1395
|
+
await this.configureRuntimeCommandStubs(driver.commands);
|
|
1681
1396
|
return;
|
|
1682
1397
|
}
|
|
1683
|
-
const startIndex = this.mountedCommandDirs.length;
|
|
1684
|
-
const newGuestPaths = driver.getGuestCommandPaths?.(startIndex) ??
|
|
1685
|
-
collectGuestCommandPaths(commandDirs, startIndex);
|
|
1686
1398
|
const allCommandDirs = [...this.mountedCommandDirs, ...commandDirs];
|
|
1687
|
-
const
|
|
1688
|
-
|
|
1689
|
-
readOnly: true,
|
|
1690
|
-
plugin: {
|
|
1691
|
-
id: "host_dir",
|
|
1692
|
-
config: {
|
|
1693
|
-
hostPath: commandDir,
|
|
1694
|
-
readOnly: true,
|
|
1695
|
-
},
|
|
1696
|
-
},
|
|
1697
|
-
}));
|
|
1698
|
-
const localMounts = this.pendingLocalMounts.map((mount) => mount.fs instanceof NodeFileSystem
|
|
1699
|
-
? serializeMountConfigForSidecar({
|
|
1700
|
-
path: mount.path,
|
|
1701
|
-
readOnly: mount.readOnly,
|
|
1702
|
-
plugin: {
|
|
1703
|
-
id: "host_dir",
|
|
1704
|
-
config: {
|
|
1705
|
-
hostPath: mount.fs.rootPath,
|
|
1706
|
-
readOnly: mount.readOnly,
|
|
1707
|
-
},
|
|
1708
|
-
},
|
|
1709
|
-
})
|
|
1710
|
-
: serializeMountConfigForSidecar({
|
|
1711
|
-
path: mount.path,
|
|
1712
|
-
driver: mount.fs,
|
|
1713
|
-
readOnly: mount.readOnly,
|
|
1714
|
-
}));
|
|
1715
|
-
await this.client.configureVm(this.session, this.vm, {
|
|
1716
|
-
mounts: [...localMounts, ...sidecarMounts],
|
|
1717
|
-
loopbackExemptPorts: this.loopbackExemptPorts,
|
|
1718
|
-
});
|
|
1719
|
-
this.proxy.registerCommandGuestPaths(newGuestPaths);
|
|
1399
|
+
const projectedCommands = await this.configureRuntimeCommandStubs(driver.commands, allCommandDirs);
|
|
1400
|
+
this.proxy.registerCommandGuestPaths(projectedCommands);
|
|
1720
1401
|
this.mountedCommandDirs.push(...commandDirs);
|
|
1721
1402
|
this.mountedRuntimeDrivers.push(driver);
|
|
1722
|
-
|
|
1723
|
-
for (const command of newGuestPaths.keys()) {
|
|
1403
|
+
for (const command of projectedCommands.keys()) {
|
|
1724
1404
|
this.commands.set(command, "wasmvm");
|
|
1725
1405
|
}
|
|
1726
|
-
await ensureCommandStubs(this.proxy, newGuestPaths.keys());
|
|
1727
1406
|
}
|
|
1728
1407
|
async dispose() {
|
|
1729
1408
|
await this.readyPromise?.catch(() => { });
|
|
@@ -1784,10 +1463,10 @@ class NativeKernel {
|
|
|
1784
1463
|
return {
|
|
1785
1464
|
pid: proc.pid,
|
|
1786
1465
|
writeStdin(data) {
|
|
1787
|
-
proc.writeStdin(data);
|
|
1466
|
+
return proc.writeStdin(data);
|
|
1788
1467
|
},
|
|
1789
1468
|
closeStdin() {
|
|
1790
|
-
proc.closeStdin();
|
|
1469
|
+
return proc.closeStdin();
|
|
1791
1470
|
},
|
|
1792
1471
|
kill(signal) {
|
|
1793
1472
|
proc.kill(signal);
|
|
@@ -1817,18 +1496,29 @@ class NativeKernel {
|
|
|
1817
1496
|
return this.proxy.connectTerminal(options);
|
|
1818
1497
|
}
|
|
1819
1498
|
mountFs(mountPath, filesystem, options) {
|
|
1499
|
+
const localMount = makeLocalCompatMount({
|
|
1500
|
+
path: mountPath,
|
|
1501
|
+
fs: filesystem,
|
|
1502
|
+
readOnly: options?.readOnly,
|
|
1503
|
+
});
|
|
1504
|
+
this.pendingLocalMounts.unshift(localMount);
|
|
1505
|
+
this.pendingLocalMounts.sort((left, right) => right.path.length - left.path.length);
|
|
1820
1506
|
if (!this.proxy) {
|
|
1821
|
-
|
|
1822
|
-
path: normalizePath(mountPath),
|
|
1823
|
-
fs: filesystem,
|
|
1824
|
-
readOnly: options?.readOnly ?? false,
|
|
1825
|
-
});
|
|
1507
|
+
// Pre-boot mounts apply during kernel initialization.
|
|
1826
1508
|
return;
|
|
1827
1509
|
}
|
|
1828
|
-
this.proxy.mountFs(mountPath, filesystem,
|
|
1510
|
+
return this.proxy.mountFs(mountPath, filesystem, {
|
|
1511
|
+
readOnly: localMount.readOnly,
|
|
1512
|
+
sidecarMount: localMount.sidecarMount,
|
|
1513
|
+
});
|
|
1829
1514
|
}
|
|
1830
1515
|
unmountFs(mountPath) {
|
|
1831
|
-
|
|
1516
|
+
const normalized = normalizePath(mountPath);
|
|
1517
|
+
const pendingIndex = this.pendingLocalMounts.findIndex((mount) => mount.path === normalized);
|
|
1518
|
+
if (pendingIndex >= 0) {
|
|
1519
|
+
this.pendingLocalMounts.splice(pendingIndex, 1);
|
|
1520
|
+
}
|
|
1521
|
+
return this.proxy?.unmountFs(mountPath);
|
|
1832
1522
|
}
|
|
1833
1523
|
async readFile(targetPath) {
|
|
1834
1524
|
await this.ensureReady();
|
|
@@ -1846,6 +1536,10 @@ class NativeKernel {
|
|
|
1846
1536
|
await this.ensureReady();
|
|
1847
1537
|
return this.proxy.readdir(targetPath);
|
|
1848
1538
|
}
|
|
1539
|
+
async readdirRecursive(targetPath, options) {
|
|
1540
|
+
await this.ensureReady();
|
|
1541
|
+
return this.proxy.readdirRecursive(targetPath, options);
|
|
1542
|
+
}
|
|
1849
1543
|
async stat(targetPath) {
|
|
1850
1544
|
await this.ensureReady();
|
|
1851
1545
|
return this.proxy.stat(targetPath);
|
|
@@ -1862,10 +1556,18 @@ class NativeKernel {
|
|
|
1862
1556
|
await this.ensureReady();
|
|
1863
1557
|
return this.proxy.removeDir(targetPath);
|
|
1864
1558
|
}
|
|
1559
|
+
async removePath(targetPath, options) {
|
|
1560
|
+
await this.ensureReady();
|
|
1561
|
+
return this.proxy.removePath(targetPath, options);
|
|
1562
|
+
}
|
|
1865
1563
|
async rename(oldPath, newPath) {
|
|
1866
1564
|
await this.ensureReady();
|
|
1867
1565
|
return this.proxy.rename(oldPath, newPath);
|
|
1868
1566
|
}
|
|
1567
|
+
async movePath(oldPath, newPath) {
|
|
1568
|
+
await this.ensureReady();
|
|
1569
|
+
return this.proxy.movePath(oldPath, newPath);
|
|
1570
|
+
}
|
|
1869
1571
|
tryResolveMountedCommand(command) {
|
|
1870
1572
|
const normalized = normalizeCommandLookup(command);
|
|
1871
1573
|
for (const driver of this.mountedRuntimeDrivers) {
|
|
@@ -1873,15 +1575,6 @@ class NativeKernel {
|
|
|
1873
1575
|
continue;
|
|
1874
1576
|
}
|
|
1875
1577
|
this.commands.set(normalized, driver.kind);
|
|
1876
|
-
if (driver.kind === "wasmvm" && this.proxy) {
|
|
1877
|
-
const startIndex = this.runtimeDriverCommandDirStarts.get(driver);
|
|
1878
|
-
if (startIndex !== undefined) {
|
|
1879
|
-
const guestPaths = driver.getGuestCommandPaths?.(startIndex);
|
|
1880
|
-
if (guestPaths?.has(normalized)) {
|
|
1881
|
-
this.proxy.registerCommandGuestPaths(new Map([[normalized, guestPaths.get(normalized)]]));
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
1578
|
return true;
|
|
1886
1579
|
}
|
|
1887
1580
|
return false;
|
|
@@ -1916,7 +1609,7 @@ class NativeKernel {
|
|
|
1916
1609
|
lowers: [
|
|
1917
1610
|
{
|
|
1918
1611
|
kind: "snapshot",
|
|
1919
|
-
entries: rootFilesystemEntriesForConfig(mergeRootFilesystemEntries(createBootstrapEntries(
|
|
1612
|
+
entries: rootFilesystemEntriesForConfig(mergeRootFilesystemEntries(createBootstrapEntries(), snapshotEntries)),
|
|
1920
1613
|
},
|
|
1921
1614
|
],
|
|
1922
1615
|
bootstrapEntries: [],
|
|
@@ -1925,7 +1618,6 @@ class NativeKernel {
|
|
|
1925
1618
|
cwd: REPO_ROOT,
|
|
1926
1619
|
command: ensureNativeSidecarBinary(),
|
|
1927
1620
|
args: [],
|
|
1928
|
-
frameTimeoutMs: NATIVE_SIDECAR_FRAME_TIMEOUT_MS,
|
|
1929
1621
|
});
|
|
1930
1622
|
const session = await client.authenticateAndOpenSession();
|
|
1931
1623
|
const createVmConfig = {
|
|
@@ -1935,6 +1627,7 @@ class NativeKernel {
|
|
|
1935
1627
|
? serializePermissionsForSidecar(bootstrapPermissions)
|
|
1936
1628
|
: undefined,
|
|
1937
1629
|
loopbackExemptPorts: this.loopbackExemptPorts,
|
|
1630
|
+
bootstrapCommands: [...NODE_RUNTIME_BOOTSTRAP_COMMANDS],
|
|
1938
1631
|
};
|
|
1939
1632
|
const vm = await client.createVm(session, {
|
|
1940
1633
|
runtime: "java_script",
|
|
@@ -1954,41 +1647,34 @@ class NativeKernel {
|
|
|
1954
1647
|
await materializeSnapshotEntriesIntoVm(client, session, vm, snapshotEntries);
|
|
1955
1648
|
}
|
|
1956
1649
|
if (rootPassthroughPlan.mounts.length > 0) {
|
|
1957
|
-
this.pendingLocalMounts.push(...rootPassthroughPlan.mounts)
|
|
1650
|
+
this.pendingLocalMounts.push(...rootPassthroughPlan.mounts.map((mount) => makeLocalCompatMount({
|
|
1651
|
+
path: mount.path,
|
|
1652
|
+
fs: mount.fs,
|
|
1653
|
+
readOnly: mount.readOnly,
|
|
1654
|
+
})));
|
|
1958
1655
|
}
|
|
1959
1656
|
if (this.pendingLocalMounts.length > 0 ||
|
|
1960
1657
|
this.loopbackExemptPorts.length > 0 ||
|
|
1961
1658
|
requestedPermissions) {
|
|
1659
|
+
const sidecarMounts = this.pendingLocalMounts.map((mount) => serializeLocalCompatMountForSidecar(mount));
|
|
1962
1660
|
await client.configureVm(session, vm, {
|
|
1963
|
-
mounts:
|
|
1964
|
-
? serializeMountConfigForSidecar({
|
|
1965
|
-
path: mount.path,
|
|
1966
|
-
readOnly: mount.readOnly,
|
|
1967
|
-
plugin: {
|
|
1968
|
-
id: "host_dir",
|
|
1969
|
-
config: {
|
|
1970
|
-
hostPath: mount.fs.rootPath,
|
|
1971
|
-
readOnly: mount.readOnly,
|
|
1972
|
-
},
|
|
1973
|
-
},
|
|
1974
|
-
})
|
|
1975
|
-
: serializeMountConfigForSidecar({
|
|
1976
|
-
path: mount.path,
|
|
1977
|
-
driver: mount.fs,
|
|
1978
|
-
readOnly: mount.readOnly,
|
|
1979
|
-
})),
|
|
1661
|
+
mounts: sidecarMounts,
|
|
1980
1662
|
permissions: requestedPermissions,
|
|
1981
1663
|
loopbackExemptPorts: this.loopbackExemptPorts,
|
|
1982
1664
|
});
|
|
1983
1665
|
}
|
|
1666
|
+
const configuredSidecarMounts = this.pendingLocalMounts.map((mount) => serializeLocalCompatMountForSidecar(mount));
|
|
1984
1667
|
const proxy = new NativeSidecarKernelProxy({
|
|
1985
1668
|
client,
|
|
1986
1669
|
session,
|
|
1987
1670
|
vm,
|
|
1988
1671
|
env: this.env,
|
|
1989
1672
|
cwd: this.cwd,
|
|
1990
|
-
defaultExecCwd: this.options.cwd === undefined ? "/
|
|
1673
|
+
defaultExecCwd: this.options.cwd === undefined ? "/workspace" : this.cwd,
|
|
1991
1674
|
localMounts: this.pendingLocalMounts,
|
|
1675
|
+
sidecarMounts: configuredSidecarMounts,
|
|
1676
|
+
permissions: requestedPermissions,
|
|
1677
|
+
loopbackExemptPorts: this.loopbackExemptPorts,
|
|
1992
1678
|
commandGuestPaths: new Map(),
|
|
1993
1679
|
onWasmCommandResolved: (command) => {
|
|
1994
1680
|
this.recordModuleExecution(command);
|