@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.
Files changed (125) hide show
  1. package/README.md +43 -43
  2. package/dist/agent-os.d.ts +313 -226
  3. package/dist/agent-os.js +1418 -1545
  4. package/dist/agentos-package.d.ts +31 -0
  5. package/dist/agentos-package.js +91 -0
  6. package/dist/base-filesystem.d.ts +2 -15
  7. package/dist/base-filesystem.js +23 -171
  8. package/dist/{host-tools-zod.d.ts → bindings-zod.d.ts} +1 -1
  9. package/dist/{host-tools-zod.js → bindings-zod.js} +52 -25
  10. package/dist/bindings.d.ts +43 -0
  11. package/dist/bindings.js +34 -0
  12. package/dist/cron/cron-manager.js +43 -10
  13. package/dist/cron/index.d.ts +1 -1
  14. package/dist/cron/types.d.ts +26 -10
  15. package/dist/default-software.d.ts +8 -0
  16. package/dist/default-software.js +10 -0
  17. package/dist/filesystem-snapshot.d.ts +1 -2
  18. package/dist/filesystem-snapshot.js +0 -43
  19. package/dist/generated/AcpLimitsConfig.d.ts +20 -0
  20. package/dist/generated/AcpLimitsConfig.js +2 -0
  21. package/dist/generated/BindingLimitsConfig.d.ts +10 -0
  22. package/dist/generated/BindingLimitsConfig.js +2 -0
  23. package/dist/generated/CreateVmConfig.d.ts +28 -0
  24. package/dist/generated/FsPermissionRule.d.ts +6 -0
  25. package/dist/generated/FsPermissionRule.js +1 -0
  26. package/dist/generated/FsPermissionRuleSet.d.ts +6 -0
  27. package/dist/generated/FsPermissionRuleSet.js +1 -0
  28. package/dist/generated/FsPermissionScope.d.ts +3 -0
  29. package/dist/generated/FsPermissionScope.js +1 -0
  30. package/dist/generated/HttpLimitsConfig.d.ts +3 -0
  31. package/dist/generated/HttpLimitsConfig.js +2 -0
  32. package/dist/generated/JsModuleResolution.d.ts +1 -0
  33. package/dist/generated/JsModuleResolution.js +2 -0
  34. package/dist/generated/JsRuntimeConfig.d.ts +31 -0
  35. package/dist/generated/JsRuntimeConfig.js +1 -0
  36. package/dist/generated/JsRuntimeLimitsConfig.d.ts +11 -0
  37. package/dist/generated/JsRuntimeLimitsConfig.js +2 -0
  38. package/dist/generated/JsRuntimePlatform.d.ts +1 -0
  39. package/dist/generated/JsRuntimePlatform.js +2 -0
  40. package/dist/generated/MountPluginDescriptor.d.ts +4 -0
  41. package/dist/generated/MountPluginDescriptor.js +2 -0
  42. package/dist/generated/NativeRootFilesystemConfig.d.ts +5 -0
  43. package/dist/generated/NativeRootFilesystemConfig.js +1 -0
  44. package/dist/generated/PatternPermissionRule.d.ts +6 -0
  45. package/dist/generated/PatternPermissionRule.js +1 -0
  46. package/dist/generated/PatternPermissionRuleSet.d.ts +6 -0
  47. package/dist/generated/PatternPermissionRuleSet.js +1 -0
  48. package/dist/generated/PatternPermissionScope.d.ts +3 -0
  49. package/dist/generated/PatternPermissionScope.js +1 -0
  50. package/dist/generated/PermissionMode.d.ts +1 -0
  51. package/dist/generated/PermissionMode.js +2 -0
  52. package/dist/generated/PermissionsPolicy.d.ts +10 -0
  53. package/dist/generated/PermissionsPolicy.js +1 -0
  54. package/dist/generated/PluginLimitsConfig.d.ts +4 -0
  55. package/dist/generated/PluginLimitsConfig.js +2 -0
  56. package/dist/generated/ProcessLimitsConfig.d.ts +7 -0
  57. package/dist/generated/ProcessLimitsConfig.js +2 -0
  58. package/dist/generated/PythonLimitsConfig.d.ts +6 -0
  59. package/dist/generated/PythonLimitsConfig.js +2 -0
  60. package/dist/generated/ResourceLimitsConfig.d.ts +24 -0
  61. package/dist/generated/ResourceLimitsConfig.js +2 -0
  62. package/dist/generated/RootFilesystemConfig.d.ts +9 -0
  63. package/dist/generated/RootFilesystemConfig.js +1 -0
  64. package/dist/generated/RootFilesystemEntry.d.ts +13 -0
  65. package/dist/generated/RootFilesystemEntry.js +1 -0
  66. package/dist/generated/RootFilesystemEntryEncoding.d.ts +1 -0
  67. package/dist/generated/RootFilesystemEntryEncoding.js +2 -0
  68. package/dist/generated/RootFilesystemEntryKind.d.ts +1 -0
  69. package/dist/generated/RootFilesystemEntryKind.js +2 -0
  70. package/dist/generated/RootFilesystemLowerDescriptor.d.ts +7 -0
  71. package/dist/generated/RootFilesystemLowerDescriptor.js +1 -0
  72. package/dist/generated/RootFilesystemMode.d.ts +1 -0
  73. package/dist/generated/RootFilesystemMode.js +2 -0
  74. package/dist/generated/VmDnsConfig.d.ts +6 -0
  75. package/dist/generated/VmDnsConfig.js +2 -0
  76. package/dist/generated/VmGroupConfig.d.ts +5 -0
  77. package/dist/generated/VmGroupConfig.js +2 -0
  78. package/dist/generated/VmLimitsConfig.d.ts +20 -0
  79. package/dist/generated/VmLimitsConfig.js +1 -0
  80. package/dist/generated/VmListenPolicyConfig.d.ts +5 -0
  81. package/dist/generated/VmListenPolicyConfig.js +2 -0
  82. package/dist/generated/VmUserAccountConfig.d.ts +9 -0
  83. package/dist/generated/VmUserAccountConfig.js +2 -0
  84. package/dist/generated/VmUserConfig.d.ts +19 -0
  85. package/dist/generated/VmUserConfig.js +1 -0
  86. package/dist/generated/WasmLimitsConfig.d.ts +8 -0
  87. package/dist/generated/WasmLimitsConfig.js +2 -0
  88. package/dist/host-dir-mount.d.ts +1 -1
  89. package/dist/index.d.ts +6 -5
  90. package/dist/index.js +5 -5
  91. package/dist/layers.d.ts +7 -4
  92. package/dist/layers.js +0 -176
  93. package/dist/options-schema.d.ts +556 -0
  94. package/dist/options-schema.js +386 -0
  95. package/dist/packages.d.ts +17 -116
  96. package/dist/packages.js +35 -322
  97. package/dist/runtime-compat.d.ts +33 -46
  98. package/dist/runtime-compat.js +197 -511
  99. package/dist/runtime.d.ts +42 -8
  100. package/dist/sandbox.d.ts +112 -0
  101. package/dist/sandbox.js +264 -0
  102. package/dist/session-api.d.ts +180 -0
  103. package/dist/session-api.js +1 -0
  104. package/dist/sidecar/agentos-protocol.d.ts +509 -20
  105. package/dist/sidecar/agentos-protocol.js +808 -81
  106. package/dist/sidecar/native-process-client.d.ts +6 -2
  107. package/dist/sidecar/native-process-client.js +8 -1
  108. package/dist/sidecar/permissions.d.ts +1 -1
  109. package/dist/sidecar/permissions.js +4 -4
  110. package/dist/sidecar/rpc-client.d.ts +100 -9
  111. package/dist/sidecar/rpc-client.js +445 -110
  112. package/dist/test/runtime.d.ts +2 -1
  113. package/dist/test/runtime.js +2 -1
  114. package/dist/test/terminal-harness.js +0 -3
  115. package/dist/types.d.ts +13 -7
  116. package/package.json +46 -35
  117. package/dist/agent-session-types.d.ts +0 -67
  118. package/dist/agents.d.ts +0 -63
  119. package/dist/agents.js +0 -42
  120. package/dist/host-tools.d.ts +0 -45
  121. package/dist/host-tools.js +0 -26
  122. package/dist/overlay-filesystem.d.ts +0 -19
  123. package/dist/overlay-filesystem.js +0 -645
  124. package/fixtures/AGENTOS_SYSTEM_PROMPT.md +0 -21
  125. /package/dist/{agent-session-types.js → generated/CreateVmConfig.js} +0 -0
@@ -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 { NATIVE_SIDECAR_FRAME_TIMEOUT_MS, NativeSidecarKernelProxy, SidecarProcess, serializeMountConfigForSidecar, } from "./sidecar/rpc-client.js";
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 S_IFREG = 0o100000;
17
- const S_IFDIR = 0o040000;
18
- const S_IFLNK = 0o120000;
19
- const MAX_SYMLINK_DEPTH = 40;
20
- const KERNEL_COMMAND_STUB = "#!/bin/sh\n# kernel command stub\n";
21
- const NODE_RUNTIME_BOOTSTRAP_COMMANDS = ["node", "npm", "npx"];
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/user",
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/sidecar"),
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
- commandDirs.forEach((commandDir, dirOffset) => {
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
- return;
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(commandNames) {
1194
- const entries = [
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 LIVE_FILESYSTEM_SYNC_CHUNK_SIZE = 512 * 1024;
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 syncLiveFilesystemPathToBoundMethods(live, methods, targetPath);
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 syncLiveFilesystemPathToBoundMethods(live, methods, targetPath) {
1540
- const stat = targetPath === "/"
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
- await ensureBoundParentDirectory(methods, targetPath);
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
- await callBoundFilesystemMethod(methods, "mkdir", targetPath, {
1551
- recursive: true,
1552
- });
1196
+ snapshot.push({ kind: "directory", path: targetPath });
1553
1197
  const children = (await live.readDirWithTypes(targetPath))
1554
- .map((entry) => entry.name)
1555
- .filter((name) => name !== "." && name !== "..")
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 syncLiveFilesystemPathToBoundMethods(live, methods, targetPath === "/"
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
- await ensureBoundParentDirectory(methods, targetPath);
1565
- await callBoundFilesystemMethod(methods, "writeFile", targetPath, new Uint8Array(0));
1566
- for (let offset = 0; offset < stat.size; offset += LIVE_FILESYSTEM_SYNC_CHUNK_SIZE) {
1567
- const chunk = await live.pread(targetPath, offset, Math.min(LIVE_FILESYSTEM_SYNC_CHUNK_SIZE, stat.size - offset));
1568
- if (chunk.length === 0) {
1569
- break;
1570
- }
1571
- await callBoundFilesystemMethod(methods, "pwrite", targetPath, offset, chunk);
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 bindLiveFilesystem(target, getFilesystem) {
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 ?? "/home/user";
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: normalizePath(mount.path),
1337
+ this.pendingLocalMounts.push(makeLocalCompatMount({
1338
+ path: mount.path,
1650
1339
  fs: mount.fs,
1651
- readOnly: mount.readOnly ?? false,
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 ensureCommandStubs(this.proxy, driver.commands);
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 ensureCommandStubs(this.proxy, driver.commands);
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 sidecarMounts = allCommandDirs.map((commandDir, index) => serializeMountConfigForSidecar({
1688
- path: `/__secure_exec/commands/${index}`,
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
- this.runtimeDriverCommandDirStarts.set(driver, startIndex);
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
- this.pendingLocalMounts.push({
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, options);
1510
+ return this.proxy.mountFs(mountPath, filesystem, {
1511
+ readOnly: localMount.readOnly,
1512
+ sidecarMount: localMount.sidecarMount,
1513
+ });
1829
1514
  }
1830
1515
  unmountFs(mountPath) {
1831
- this.proxy?.unmountFs(mountPath);
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([...NODE_RUNTIME_BOOTSTRAP_COMMANDS]), snapshotEntries)),
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: this.pendingLocalMounts.map((mount) => mount.fs instanceof NodeFileSystem
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 ? "/home/user" : this.cwd,
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);