@rivet-dev/agentos-core 0.2.5-rc.3 → 0.2.5-rc.5

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 (93) hide show
  1. package/README.md +4 -4
  2. package/dist/agent-os.d.ts +25 -28
  3. package/dist/agent-os.js +129 -403
  4. package/dist/agentos-package.d.ts +3 -3
  5. package/dist/agentos-package.js +7 -1
  6. package/dist/cron/types.d.ts +1 -1
  7. package/dist/default-software.d.ts +6 -46
  8. package/dist/default-software.js +7 -90
  9. package/dist/generated/AcpLimitsConfig.d.ts +4 -0
  10. package/dist/generated/AcpLimitsConfig.js +2 -0
  11. package/dist/generated/CreateVmConfig.d.ts +26 -0
  12. package/dist/generated/CreateVmConfig.js +1 -0
  13. package/dist/generated/FsPermissionRule.d.ts +6 -0
  14. package/dist/generated/FsPermissionRule.js +1 -0
  15. package/dist/generated/FsPermissionRuleSet.d.ts +6 -0
  16. package/dist/generated/FsPermissionRuleSet.js +1 -0
  17. package/dist/generated/FsPermissionScope.d.ts +3 -0
  18. package/dist/generated/FsPermissionScope.js +1 -0
  19. package/dist/generated/HttpLimitsConfig.d.ts +3 -0
  20. package/dist/generated/HttpLimitsConfig.js +2 -0
  21. package/dist/generated/JsModuleResolution.d.ts +1 -0
  22. package/dist/generated/JsModuleResolution.js +2 -0
  23. package/dist/generated/JsRuntimeConfig.d.ts +31 -0
  24. package/dist/generated/JsRuntimeConfig.js +1 -0
  25. package/dist/generated/JsRuntimeLimitsConfig.d.ts +11 -0
  26. package/dist/generated/JsRuntimeLimitsConfig.js +2 -0
  27. package/dist/generated/JsRuntimePlatform.d.ts +1 -0
  28. package/dist/generated/JsRuntimePlatform.js +2 -0
  29. package/dist/generated/MountPluginDescriptor.d.ts +4 -0
  30. package/dist/generated/MountPluginDescriptor.js +2 -0
  31. package/dist/generated/NativeRootFilesystemConfig.d.ts +5 -0
  32. package/dist/generated/NativeRootFilesystemConfig.js +1 -0
  33. package/dist/generated/PatternPermissionRule.d.ts +6 -0
  34. package/dist/generated/PatternPermissionRule.js +1 -0
  35. package/dist/generated/PatternPermissionRuleSet.d.ts +6 -0
  36. package/dist/generated/PatternPermissionRuleSet.js +1 -0
  37. package/dist/generated/PatternPermissionScope.d.ts +3 -0
  38. package/dist/generated/PatternPermissionScope.js +1 -0
  39. package/dist/generated/PermissionMode.d.ts +1 -0
  40. package/dist/generated/PermissionMode.js +2 -0
  41. package/dist/generated/PermissionsPolicy.d.ts +10 -0
  42. package/dist/generated/PermissionsPolicy.js +1 -0
  43. package/dist/generated/PluginLimitsConfig.d.ts +4 -0
  44. package/dist/generated/PluginLimitsConfig.js +2 -0
  45. package/dist/generated/PythonLimitsConfig.d.ts +6 -0
  46. package/dist/generated/PythonLimitsConfig.js +2 -0
  47. package/dist/generated/ResourceLimitsConfig.d.ts +24 -0
  48. package/dist/generated/ResourceLimitsConfig.js +2 -0
  49. package/dist/generated/RootFilesystemConfig.d.ts +9 -0
  50. package/dist/generated/RootFilesystemConfig.js +1 -0
  51. package/dist/generated/RootFilesystemEntry.d.ts +13 -0
  52. package/dist/generated/RootFilesystemEntry.js +1 -0
  53. package/dist/generated/RootFilesystemEntryEncoding.d.ts +1 -0
  54. package/dist/generated/RootFilesystemEntryEncoding.js +2 -0
  55. package/dist/generated/RootFilesystemEntryKind.d.ts +1 -0
  56. package/dist/generated/RootFilesystemEntryKind.js +2 -0
  57. package/dist/generated/RootFilesystemLowerDescriptor.d.ts +7 -0
  58. package/dist/generated/RootFilesystemLowerDescriptor.js +1 -0
  59. package/dist/generated/RootFilesystemMode.d.ts +1 -0
  60. package/dist/generated/RootFilesystemMode.js +2 -0
  61. package/dist/generated/ToolLimitsConfig.d.ts +10 -0
  62. package/dist/generated/ToolLimitsConfig.js +2 -0
  63. package/dist/generated/VmDnsConfig.d.ts +6 -0
  64. package/dist/generated/VmDnsConfig.js +2 -0
  65. package/dist/generated/VmLimitsConfig.d.ts +18 -0
  66. package/dist/generated/VmLimitsConfig.js +1 -0
  67. package/dist/generated/VmListenPolicyConfig.d.ts +5 -0
  68. package/dist/generated/VmListenPolicyConfig.js +2 -0
  69. package/dist/generated/WasmLimitsConfig.d.ts +7 -0
  70. package/dist/generated/WasmLimitsConfig.js +2 -0
  71. package/dist/host-dir-mount.d.ts +1 -1
  72. package/dist/index.d.ts +0 -1
  73. package/dist/index.js +0 -1
  74. package/dist/options-schema.d.ts +14 -1
  75. package/dist/options-schema.js +27 -21
  76. package/dist/packages.d.ts +2 -2
  77. package/dist/packages.js +20 -6
  78. package/dist/runtime-compat.d.ts +17 -4
  79. package/dist/runtime-compat.js +51 -88
  80. package/dist/runtime.d.ts +27 -0
  81. package/dist/sandbox.d.ts +112 -0
  82. package/dist/sandbox.js +264 -0
  83. package/dist/sidecar/agentos-protocol.d.ts +27 -1
  84. package/dist/sidecar/agentos-protocol.js +77 -20
  85. package/dist/sidecar/native-process-client.d.ts +5 -4
  86. package/dist/sidecar/native-process-client.js +4 -4
  87. package/dist/sidecar/permissions.d.ts +1 -1
  88. package/dist/sidecar/rpc-client.d.ts +21 -2
  89. package/dist/sidecar/rpc-client.js +113 -41
  90. package/dist/types.d.ts +7 -1
  91. package/package.json +34 -35
  92. package/dist/agents.d.ts +0 -79
  93. package/dist/agents.js +0 -48
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // @rivet-dev/agentos
2
2
  export { AgentOs, AgentOsSidecar } from "./agent-os.js";
3
- export { AGENT_CONFIGS } from "./agents.js";
4
3
  export { CronManager, InvalidScheduleError, PastScheduleError, TimerScheduleDriver, } from "./cron/index.js";
5
4
  export { createHostDirBackend, nodeModulesMount } from "./host-dir-mount.js";
6
5
  export { hostTool, MAX_TOOL_DESCRIPTION_LENGTH, toolKit, validateToolkits, } from "./host-tools.js";
@@ -151,6 +151,10 @@ export declare const agentOsLimitsSchema: z.ZodObject<{
151
151
  }, z.core.$strict>>;
152
152
  jsRuntime: z.ZodOptional<z.ZodObject<{
153
153
  v8HeapLimitMb: z.ZodOptional<z.ZodNumber>;
154
+ syncRpcWaitTimeoutMs: z.ZodOptional<z.ZodNumber>;
155
+ cpuTimeLimitMs: z.ZodOptional<z.ZodNumber>;
156
+ wallClockLimitMs: z.ZodOptional<z.ZodNumber>;
157
+ importCacheMaterializeTimeoutMs: z.ZodOptional<z.ZodNumber>;
154
158
  capturedOutputLimitBytes: z.ZodOptional<z.ZodNumber>;
155
159
  stdinBufferLimitBytes: z.ZodOptional<z.ZodNumber>;
156
160
  eventPayloadLimitBytes: z.ZodOptional<z.ZodNumber>;
@@ -159,12 +163,15 @@ export declare const agentOsLimitsSchema: z.ZodObject<{
159
163
  python: z.ZodOptional<z.ZodObject<{
160
164
  outputBufferMaxBytes: z.ZodOptional<z.ZodNumber>;
161
165
  executionTimeoutMs: z.ZodOptional<z.ZodNumber>;
166
+ maxOldSpaceMb: z.ZodOptional<z.ZodNumber>;
162
167
  vfsRpcTimeoutMs: z.ZodOptional<z.ZodNumber>;
163
168
  }, z.core.$strict>>;
164
169
  wasm: z.ZodOptional<z.ZodObject<{
165
170
  maxModuleFileBytes: z.ZodOptional<z.ZodNumber>;
166
171
  capturedOutputLimitBytes: z.ZodOptional<z.ZodNumber>;
167
172
  syncReadLimitBytes: z.ZodOptional<z.ZodNumber>;
173
+ prewarmTimeoutMs: z.ZodOptional<z.ZodNumber>;
174
+ runnerHeapLimitMb: z.ZodOptional<z.ZodNumber>;
168
175
  }, z.core.$strict>>;
169
176
  }, z.core.$strict>;
170
177
  export declare const rootFilesystemConfigSchema: z.ZodObject<{
@@ -255,7 +262,6 @@ export declare const agentOsOptionFieldSchemas: {
255
262
  lowers: z.ZodArray<z.ZodUnknown>;
256
263
  }, z.core.$strict>;
257
264
  }, z.core.$strict>]>>>;
258
- readonly moduleAccessCwd: z.ZodOptional<z.ZodString>;
259
265
  readonly additionalInstructions: z.ZodOptional<z.ZodString>;
260
266
  readonly scheduleDriver: z.ZodOptional<z.ZodCustom<unknown, unknown>>;
261
267
  readonly toolKits: z.ZodOptional<z.ZodArray<z.ZodType<ToolKit, unknown, z.core.$ZodTypeInternals<ToolKit, unknown>>>>;
@@ -416,6 +422,10 @@ export declare const agentOsOptionFieldSchemas: {
416
422
  }, z.core.$strict>>;
417
423
  jsRuntime: z.ZodOptional<z.ZodObject<{
418
424
  v8HeapLimitMb: z.ZodOptional<z.ZodNumber>;
425
+ syncRpcWaitTimeoutMs: z.ZodOptional<z.ZodNumber>;
426
+ cpuTimeLimitMs: z.ZodOptional<z.ZodNumber>;
427
+ wallClockLimitMs: z.ZodOptional<z.ZodNumber>;
428
+ importCacheMaterializeTimeoutMs: z.ZodOptional<z.ZodNumber>;
419
429
  capturedOutputLimitBytes: z.ZodOptional<z.ZodNumber>;
420
430
  stdinBufferLimitBytes: z.ZodOptional<z.ZodNumber>;
421
431
  eventPayloadLimitBytes: z.ZodOptional<z.ZodNumber>;
@@ -424,12 +434,15 @@ export declare const agentOsOptionFieldSchemas: {
424
434
  python: z.ZodOptional<z.ZodObject<{
425
435
  outputBufferMaxBytes: z.ZodOptional<z.ZodNumber>;
426
436
  executionTimeoutMs: z.ZodOptional<z.ZodNumber>;
437
+ maxOldSpaceMb: z.ZodOptional<z.ZodNumber>;
427
438
  vfsRpcTimeoutMs: z.ZodOptional<z.ZodNumber>;
428
439
  }, z.core.$strict>>;
429
440
  wasm: z.ZodOptional<z.ZodObject<{
430
441
  maxModuleFileBytes: z.ZodOptional<z.ZodNumber>;
431
442
  capturedOutputLimitBytes: z.ZodOptional<z.ZodNumber>;
432
443
  syncReadLimitBytes: z.ZodOptional<z.ZodNumber>;
444
+ prewarmTimeoutMs: z.ZodOptional<z.ZodNumber>;
445
+ runnerHeapLimitMb: z.ZodOptional<z.ZodNumber>;
433
446
  }, z.core.$strict>>;
434
447
  }, z.core.$strict>>;
435
448
  readonly onAgentStderr: z.ZodOptional<z.ZodCustom<AgentStderrHandler, AgentStderrHandler>>;
@@ -73,59 +73,66 @@ export const agentOsLimitsSchema = z
73
73
  .strict()
74
74
  .optional(),
75
75
  http: z
76
- .object({ maxFetchResponseBytes: nonNegativeInteger.optional() })
76
+ .object({ maxFetchResponseBytes: positiveInteger.optional() })
77
77
  .strict()
78
78
  .optional(),
79
79
  tools: z
80
80
  .object({
81
81
  defaultToolTimeoutMs: nonNegativeInteger.optional(),
82
82
  maxToolTimeoutMs: nonNegativeInteger.optional(),
83
- maxRegisteredToolkits: nonNegativeInteger.optional(),
84
- maxRegisteredToolsPerVm: nonNegativeInteger.optional(),
85
- maxToolsPerToolkit: nonNegativeInteger.optional(),
86
- maxToolSchemaBytes: nonNegativeInteger.optional(),
83
+ maxRegisteredToolkits: positiveInteger.optional(),
84
+ maxRegisteredToolsPerVm: positiveInteger.optional(),
85
+ maxToolsPerToolkit: positiveInteger.optional(),
86
+ maxToolSchemaBytes: positiveInteger.optional(),
87
87
  maxToolExamplesPerTool: nonNegativeInteger.optional(),
88
- maxToolExampleInputBytes: nonNegativeInteger.optional(),
88
+ maxToolExampleInputBytes: positiveInteger.optional(),
89
89
  })
90
90
  .strict()
91
91
  .optional(),
92
92
  plugins: z
93
93
  .object({
94
- maxPersistedManifestBytes: nonNegativeInteger.optional(),
94
+ maxPersistedManifestBytes: positiveInteger.optional(),
95
95
  maxPersistedManifestFileBytes: nonNegativeInteger.optional(),
96
96
  })
97
97
  .strict()
98
98
  .optional(),
99
99
  acp: z
100
100
  .object({
101
- maxReadLineBytes: nonNegativeInteger.optional(),
102
- stdoutBufferByteLimit: nonNegativeInteger.optional(),
101
+ maxReadLineBytes: positiveInteger.optional(),
102
+ stdoutBufferByteLimit: positiveInteger.optional(),
103
103
  })
104
104
  .strict()
105
105
  .optional(),
106
106
  jsRuntime: z
107
107
  .object({
108
- v8HeapLimitMb: nonNegativeInteger.optional(),
109
- capturedOutputLimitBytes: nonNegativeInteger.optional(),
110
- stdinBufferLimitBytes: nonNegativeInteger.optional(),
111
- eventPayloadLimitBytes: nonNegativeInteger.optional(),
112
- v8IpcMaxFrameBytes: nonNegativeInteger.optional(),
108
+ v8HeapLimitMb: positiveInteger.optional(),
109
+ syncRpcWaitTimeoutMs: nonNegativeInteger.optional(),
110
+ cpuTimeLimitMs: nonNegativeInteger.optional(),
111
+ wallClockLimitMs: nonNegativeInteger.optional(),
112
+ importCacheMaterializeTimeoutMs: positiveInteger.optional(),
113
+ capturedOutputLimitBytes: positiveInteger.optional(),
114
+ stdinBufferLimitBytes: positiveInteger.optional(),
115
+ eventPayloadLimitBytes: positiveInteger.optional(),
116
+ v8IpcMaxFrameBytes: positiveInteger.optional(),
113
117
  })
114
118
  .strict()
115
119
  .optional(),
116
120
  python: z
117
121
  .object({
118
- outputBufferMaxBytes: nonNegativeInteger.optional(),
119
- executionTimeoutMs: nonNegativeInteger.optional(),
120
- vfsRpcTimeoutMs: nonNegativeInteger.optional(),
122
+ outputBufferMaxBytes: positiveInteger.optional(),
123
+ executionTimeoutMs: positiveInteger.optional(),
124
+ maxOldSpaceMb: nonNegativeInteger.optional(),
125
+ vfsRpcTimeoutMs: positiveInteger.optional(),
121
126
  })
122
127
  .strict()
123
128
  .optional(),
124
129
  wasm: z
125
130
  .object({
126
- maxModuleFileBytes: nonNegativeInteger.optional(),
127
- capturedOutputLimitBytes: nonNegativeInteger.optional(),
128
- syncReadLimitBytes: nonNegativeInteger.optional(),
131
+ maxModuleFileBytes: positiveInteger.optional(),
132
+ capturedOutputLimitBytes: positiveInteger.optional(),
133
+ syncReadLimitBytes: positiveInteger.optional(),
134
+ prewarmTimeoutMs: positiveInteger.optional(),
135
+ runnerHeapLimitMb: positiveInteger.optional(),
129
136
  })
130
137
  .strict()
131
138
  .optional(),
@@ -239,7 +246,6 @@ export const agentOsOptionFieldSchemas = {
239
246
  highResolutionTime: z.boolean().optional(),
240
247
  rootFilesystem: rootFilesystemConfigSchema.optional(),
241
248
  mounts: z.array(mountConfigSchema).optional(),
242
- moduleAccessCwd: z.string().optional(),
243
249
  additionalInstructions: z.string().optional(),
244
250
  scheduleDriver: z
245
251
  .custom((value) => typeof value === "object" && value !== null, {
@@ -1,4 +1,4 @@
1
- import { type SoftwarePackageRef } from "./agentos-package.js";
1
+ import type { SoftwarePackageRef } from "./agentos-package.js";
2
2
  /**
3
3
  * Input type for the `software` option. Software is a self-contained package
4
4
  * directory that the secure-exec sidecar materializes into the `/opt/agentos`
@@ -23,6 +23,6 @@ export declare function defineSoftware<T extends SoftwareEntry>(desc: T): T;
23
23
  * the software set. Returns its source so it can be evaluated once into the
24
24
  * per-sidecar V8 startup snapshot (`jsRuntime.snapshotUserlandCode`) and reused
25
25
  * across sessions. Returns `undefined` when no agent opts in (`agent.snapshot`)
26
- * or the bundle is absent — the runtime then keeps the per-session import path.
26
+ * or the bundle is absent -- the runtime then keeps the per-session import path.
27
27
  */
28
28
  export declare function resolveAgentSnapshotBundle(software: SoftwareInput[]): string | undefined;
package/dist/packages.js CHANGED
@@ -1,6 +1,6 @@
1
- import { existsSync, readFileSync } from "node:fs";
1
+ import { existsSync, readFileSync, statSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { tryReadAgentosPackageManifest, } from "./agentos-package.js";
3
+ import { tryReadAgentosPackageManifest } from "./agentos-package.js";
4
4
  // ── defineSoftware ───────────────────────────────────────────────────
5
5
  /**
6
6
  * Define a software descriptor. A type-safe identity function that validates the
@@ -16,19 +16,33 @@ export function defineSoftware(desc) {
16
16
  * the software set. Returns its source so it can be evaluated once into the
17
17
  * per-sidecar V8 startup snapshot (`jsRuntime.snapshotUserlandCode`) and reused
18
18
  * across sessions. Returns `undefined` when no agent opts in (`agent.snapshot`)
19
- * or the bundle is absent — the runtime then keeps the per-session import path.
19
+ * or the bundle is absent -- the runtime then keeps the per-session import path.
20
20
  */
21
21
  export function resolveAgentSnapshotBundle(software) {
22
22
  const descriptors = software.flat();
23
23
  for (const entry of descriptors) {
24
- const dir = entry.packageDir;
25
- const manifest = tryReadAgentosPackageManifest(dir);
24
+ // Only transition package DIRS are readable host-side (their
25
+ // agentos-package.json is the toolchain-input manifest). Packed
26
+ // `.aospkg` refs carry the bundle inside the mount tar; the sidecar
27
+ // reads it from the packed vbare manifest's snapshotBundlePath.
28
+ const path = entry.packagePath;
29
+ if (path === undefined || !statIsDirectory(path))
30
+ continue;
31
+ const manifest = tryReadAgentosPackageManifest(path);
26
32
  if (!manifest?.agent?.snapshot)
27
33
  continue;
28
- const bundlePath = join(dir, "dist", "sdk-snapshot.js");
34
+ const bundlePath = join(path, "dist", "sdk-snapshot.js");
29
35
  if (existsSync(bundlePath)) {
30
36
  return readFileSync(bundlePath, "utf-8");
31
37
  }
32
38
  }
33
39
  return undefined;
34
40
  }
41
+ function statIsDirectory(path) {
42
+ try {
43
+ return statSync(path).isDirectory();
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
@@ -1,3 +1,4 @@
1
+ import type { NodeModulesMountConfig } from "./host-dir-mount.js";
1
2
  export declare const AF_INET = 2;
2
3
  export declare const AF_UNIX = 1;
3
4
  export declare const SOCK_STREAM = 1;
@@ -229,6 +230,7 @@ export interface SystemDriver {
229
230
  network?: NetworkAdapter;
230
231
  commandExecutor?: CommandExecutor;
231
232
  permissions?: Permissions;
233
+ mounts: readonly NodeModulesMountConfig[];
232
234
  runtime: {
233
235
  process: ProcessConfig;
234
236
  os: OSConfig;
@@ -263,6 +265,13 @@ export interface NodeRuntimeDriverFactory {
263
265
  export interface KernelInterface {
264
266
  vfs: VirtualFileSystem;
265
267
  }
268
+ export interface KernelRecursiveDirEntry {
269
+ name: string;
270
+ path: string;
271
+ isDirectory: boolean;
272
+ isSymbolicLink: boolean;
273
+ size: number;
274
+ }
266
275
  export interface Kernel extends KernelInterface {
267
276
  mount(driver: KernelRuntimeDriver): Promise<void>;
268
277
  dispose(): Promise<void>;
@@ -278,11 +287,18 @@ export interface Kernel extends KernelInterface {
278
287
  writeFile(path: string, content: string | Uint8Array): Promise<void>;
279
288
  mkdir(path: string): Promise<void>;
280
289
  readdir(path: string): Promise<string[]>;
290
+ readdirRecursive(path: string, options?: {
291
+ maxDepth?: number;
292
+ }): Promise<KernelRecursiveDirEntry[]>;
281
293
  stat(path: string): Promise<VirtualStat>;
282
294
  exists(path: string): Promise<boolean>;
283
295
  removeFile(path: string): Promise<void>;
284
296
  removeDir(path: string): Promise<void>;
297
+ removePath(path: string, options?: {
298
+ recursive?: boolean;
299
+ }): Promise<void>;
285
300
  rename(oldPath: string, newPath: string): Promise<void>;
301
+ movePath(oldPath: string, newPath: string): Promise<void>;
286
302
  readonly commands: ReadonlyMap<string, string>;
287
303
  readonly processes: ReadonlyMap<number, ProcessInfo>;
288
304
  readonly env: Record<string, string>;
@@ -304,17 +320,14 @@ export interface BindingTree {
304
320
  [key: string]: BindingFunction | BindingTree;
305
321
  }
306
322
  export type BindingFunction = (...args: unknown[]) => unknown;
307
- export interface ModuleAccessOptions {
308
- cwd?: string;
309
- }
310
323
  export interface NodeDriverOptions {
311
324
  filesystem?: VirtualFileSystem;
312
325
  networkAdapter?: NetworkAdapter;
313
326
  commandExecutor?: CommandExecutor;
314
327
  permissions?: Permissions;
328
+ mounts?: readonly NodeModulesMountConfig[];
315
329
  processConfig?: ProcessConfig;
316
330
  osConfig?: OSConfig;
317
- moduleAccess?: ModuleAccessOptions;
318
331
  }
319
332
  export interface DefaultNetworkAdapterOptions {
320
333
  loopbackExemptPorts?: number[];
@@ -17,7 +17,6 @@ const S_IFREG = 0o100000;
17
17
  const S_IFDIR = 0o040000;
18
18
  const S_IFLNK = 0o120000;
19
19
  const MAX_SYMLINK_DEPTH = 40;
20
- const KERNEL_COMMAND_STUB = "#!/bin/sh\n# kernel command stub\n";
21
20
  const NODE_RUNTIME_BOOTSTRAP_COMMANDS = [
22
21
  "node",
23
22
  "npm",
@@ -738,6 +737,7 @@ export function createNodeDriver(options = {}) {
738
737
  network: options.networkAdapter,
739
738
  commandExecutor: options.commandExecutor,
740
739
  permissions: options.permissions,
740
+ mounts: options.mounts ?? [],
741
741
  runtime: {
742
742
  process: options.processConfig ?? {},
743
743
  os: options.osConfig ?? {},
@@ -1022,7 +1022,7 @@ function isWasmBinaryFile(filePath) {
1022
1022
  function discoverWasmCommandEntries(commandDirs) {
1023
1023
  const discovered = [];
1024
1024
  const seen = new Set();
1025
- commandDirs.forEach((commandDir, dirOffset) => {
1025
+ for (const commandDir of commandDirs) {
1026
1026
  let entries;
1027
1027
  try {
1028
1028
  entries = fsSync
@@ -1030,7 +1030,7 @@ function discoverWasmCommandEntries(commandDirs) {
1030
1030
  .sort((left, right) => left.localeCompare(right));
1031
1031
  }
1032
1032
  catch {
1033
- return;
1033
+ continue;
1034
1034
  }
1035
1035
  for (const entry of entries) {
1036
1036
  if (entry.startsWith("."))
@@ -1043,7 +1043,6 @@ function discoverWasmCommandEntries(commandDirs) {
1043
1043
  discovered.push({
1044
1044
  name: entry,
1045
1045
  hostPath: fullPath,
1046
- dirOffset,
1047
1046
  });
1048
1047
  continue;
1049
1048
  }
@@ -1054,13 +1053,12 @@ function discoverWasmCommandEntries(commandDirs) {
1054
1053
  discovered.push({
1055
1054
  name: entry,
1056
1055
  hostPath: fullPath,
1057
- dirOffset,
1058
1056
  });
1059
1057
  }
1060
1058
  }
1061
1059
  catch { }
1062
1060
  }
1063
- });
1061
+ }
1064
1062
  return discovered;
1065
1063
  }
1066
1064
  class WasmVmRuntimeDescriptor {
@@ -1070,7 +1068,6 @@ class WasmVmRuntimeDescriptor {
1070
1068
  commandDirs;
1071
1069
  _commandPaths = new Map();
1072
1070
  _moduleCache = new Map();
1073
- commandDirOffsets = new Map();
1074
1071
  constructor(options) {
1075
1072
  this.commandDirs =
1076
1073
  options.commandDirs && options.commandDirs.length > 0
@@ -1101,17 +1098,6 @@ class WasmVmRuntimeDescriptor {
1101
1098
  this.refreshDiscovery();
1102
1099
  return this._commandPaths.has(normalized);
1103
1100
  }
1104
- getGuestCommandPaths(startIndex) {
1105
- const guestPaths = new Map();
1106
- for (const [name] of this._commandPaths) {
1107
- const dirOffset = this.commandDirOffsets.get(name);
1108
- if (dirOffset === undefined) {
1109
- continue;
1110
- }
1111
- guestPaths.set(name, `/__secure_exec/commands/${startIndex + dirOffset}/${name}`);
1112
- }
1113
- return guestPaths;
1114
- }
1115
1101
  recordModuleExecution(command) {
1116
1102
  const normalized = normalizeCommandLookup(command);
1117
1103
  if (this._commandPaths.has(normalized) ||
@@ -1127,11 +1113,9 @@ class WasmVmRuntimeDescriptor {
1127
1113
  const discovered = discoverWasmCommandEntries(this.commandDirs);
1128
1114
  this.commands.length = 0;
1129
1115
  this._commandPaths.clear();
1130
- this.commandDirOffsets.clear();
1131
1116
  for (const entry of discovered) {
1132
1117
  this.commands.push(entry.name);
1133
1118
  this._commandPaths.set(entry.name, entry.hostPath);
1134
- this.commandDirOffsets.set(entry.name, entry.dirOffset);
1135
1119
  }
1136
1120
  }
1137
1121
  }
@@ -1197,8 +1181,8 @@ function ensureNativeSidecarBinary() {
1197
1181
  function rootEntryExecutable(kind, mode) {
1198
1182
  return kind === "file" && (mode & 0o111) !== 0;
1199
1183
  }
1200
- function createBootstrapEntries(commandNames) {
1201
- const entries = [
1184
+ function createBootstrapEntries() {
1185
+ return [
1202
1186
  {
1203
1187
  path: "/",
1204
1188
  kind: "directory",
@@ -1226,19 +1210,6 @@ function createBootstrapEntries(commandNames) {
1226
1210
  executable: false,
1227
1211
  },
1228
1212
  ];
1229
- for (const command of [...new Set(commandNames)].sort((left, right) => left.localeCompare(right))) {
1230
- entries.push({
1231
- path: `/bin/${command}`,
1232
- kind: "file",
1233
- mode: 0o755,
1234
- uid: 0,
1235
- gid: 0,
1236
- content: KERNEL_COMMAND_STUB,
1237
- encoding: "utf8",
1238
- executable: true,
1239
- });
1240
- }
1241
- return entries;
1242
1213
  }
1243
1214
  function mergeRootFilesystemEntries(baseEntries, overrideEntries) {
1244
1215
  const merged = new Map();
@@ -1379,23 +1350,6 @@ function planNodeFilesystemPassthroughMounts(filesystem, existingMounts) {
1379
1350
  passthroughDirectories,
1380
1351
  };
1381
1352
  }
1382
- function collectGuestCommandPaths(commandDirs, startIndex = 0) {
1383
- const guestPaths = new Map();
1384
- for (const entry of discoverWasmCommandEntries(commandDirs)) {
1385
- if (!guestPaths.has(entry.name)) {
1386
- guestPaths.set(entry.name, `/__secure_exec/commands/${startIndex + entry.dirOffset}/${entry.name}`);
1387
- }
1388
- }
1389
- return guestPaths;
1390
- }
1391
- async function ensureCommandStubs(proxy, commands) {
1392
- const rootView = proxy.createRootView();
1393
- for (const command of commands) {
1394
- const stubPath = `/bin/${command}`;
1395
- await rootView.writeFile(stubPath, KERNEL_COMMAND_STUB);
1396
- await rootView.chmod(stubPath, 0o755);
1397
- }
1398
- }
1399
1353
  class DeferredFileSystem {
1400
1354
  getFilesystem;
1401
1355
  constructor(getFilesystem) {
@@ -1663,7 +1617,6 @@ class NativeKernel {
1663
1617
  pendingLocalMounts = [];
1664
1618
  mountedCommandDirs = [];
1665
1619
  mountedRuntimeDrivers = [];
1666
- runtimeDriverCommandDirStarts = new Map();
1667
1620
  loopbackExemptPorts;
1668
1621
  constructor(options) {
1669
1622
  this.options = options;
@@ -1693,6 +1646,32 @@ class NativeKernel {
1693
1646
  get zombieTimerCount() {
1694
1647
  return this.proxy?.zombieTimerCount ?? 0;
1695
1648
  }
1649
+ async configureRuntimeCommandStubs(commands, commandDirs = this.mountedCommandDirs) {
1650
+ if (!this.client || !this.session || !this.vm) {
1651
+ throw new Error("kernel is not ready");
1652
+ }
1653
+ const sidecarMounts = commandDirs.map((commandDir, index) => serializeMountConfigForSidecar({
1654
+ path: `/__secure_exec/commands/${index}`,
1655
+ readOnly: true,
1656
+ plugin: {
1657
+ id: "host_dir",
1658
+ config: {
1659
+ hostPath: commandDir,
1660
+ readOnly: true,
1661
+ },
1662
+ },
1663
+ }));
1664
+ const localMounts = this.pendingLocalMounts.map((mount) => serializeLocalCompatMountForSidecar(mount));
1665
+ const configuredVm = await this.client.configureVm(this.session, this.vm, {
1666
+ mounts: [...localMounts, ...sidecarMounts],
1667
+ loopbackExemptPorts: this.loopbackExemptPorts,
1668
+ bootstrapCommands: [...new Set(commands)].sort((left, right) => left.localeCompare(right)),
1669
+ });
1670
+ return new Map(configuredVm.projectedCommands.map((command) => [
1671
+ command.name,
1672
+ command.guestPath,
1673
+ ]));
1674
+ }
1696
1675
  async mount(driver) {
1697
1676
  await this.ensureReady();
1698
1677
  if (!this.proxy || !this.client || !this.session || !this.vm) {
@@ -1704,7 +1683,7 @@ class NativeKernel {
1704
1683
  this.commands.set(command, "node");
1705
1684
  }
1706
1685
  this.mountedRuntimeDrivers.push(driver);
1707
- await ensureCommandStubs(this.proxy, driver.commands);
1686
+ await this.configureRuntimeCommandStubs(driver.commands);
1708
1687
  return;
1709
1688
  }
1710
1689
  const commandDirs = driver.commandDirs ?? [];
@@ -1713,37 +1692,17 @@ class NativeKernel {
1713
1692
  this.commands.set(command, "wasmvm");
1714
1693
  }
1715
1694
  this.mountedRuntimeDrivers.push(driver);
1716
- await ensureCommandStubs(this.proxy, driver.commands);
1695
+ await this.configureRuntimeCommandStubs(driver.commands);
1717
1696
  return;
1718
1697
  }
1719
- const startIndex = this.mountedCommandDirs.length;
1720
- const newGuestPaths = driver.getGuestCommandPaths?.(startIndex) ??
1721
- collectGuestCommandPaths(commandDirs, startIndex);
1722
1698
  const allCommandDirs = [...this.mountedCommandDirs, ...commandDirs];
1723
- const sidecarMounts = allCommandDirs.map((commandDir, index) => serializeMountConfigForSidecar({
1724
- path: `/__secure_exec/commands/${index}`,
1725
- readOnly: true,
1726
- plugin: {
1727
- id: "host_dir",
1728
- config: {
1729
- hostPath: commandDir,
1730
- readOnly: true,
1731
- },
1732
- },
1733
- }));
1734
- const localMounts = this.pendingLocalMounts.map((mount) => serializeLocalCompatMountForSidecar(mount));
1735
- await this.client.configureVm(this.session, this.vm, {
1736
- mounts: [...localMounts, ...sidecarMounts],
1737
- loopbackExemptPorts: this.loopbackExemptPorts,
1738
- });
1739
- this.proxy.registerCommandGuestPaths(newGuestPaths);
1699
+ const projectedCommands = await this.configureRuntimeCommandStubs(driver.commands, allCommandDirs);
1700
+ this.proxy.registerCommandGuestPaths(projectedCommands);
1740
1701
  this.mountedCommandDirs.push(...commandDirs);
1741
1702
  this.mountedRuntimeDrivers.push(driver);
1742
- this.runtimeDriverCommandDirStarts.set(driver, startIndex);
1743
- for (const command of newGuestPaths.keys()) {
1703
+ for (const command of projectedCommands.keys()) {
1744
1704
  this.commands.set(command, "wasmvm");
1745
1705
  }
1746
- await ensureCommandStubs(this.proxy, newGuestPaths.keys());
1747
1706
  }
1748
1707
  async dispose() {
1749
1708
  await this.readyPromise?.catch(() => { });
@@ -1876,6 +1835,10 @@ class NativeKernel {
1876
1835
  await this.ensureReady();
1877
1836
  return this.proxy.readdir(targetPath);
1878
1837
  }
1838
+ async readdirRecursive(targetPath, options) {
1839
+ await this.ensureReady();
1840
+ return this.proxy.readdirRecursive(targetPath, options);
1841
+ }
1879
1842
  async stat(targetPath) {
1880
1843
  await this.ensureReady();
1881
1844
  return this.proxy.stat(targetPath);
@@ -1892,10 +1855,18 @@ class NativeKernel {
1892
1855
  await this.ensureReady();
1893
1856
  return this.proxy.removeDir(targetPath);
1894
1857
  }
1858
+ async removePath(targetPath, options) {
1859
+ await this.ensureReady();
1860
+ return this.proxy.removePath(targetPath, options);
1861
+ }
1895
1862
  async rename(oldPath, newPath) {
1896
1863
  await this.ensureReady();
1897
1864
  return this.proxy.rename(oldPath, newPath);
1898
1865
  }
1866
+ async movePath(oldPath, newPath) {
1867
+ await this.ensureReady();
1868
+ return this.proxy.movePath(oldPath, newPath);
1869
+ }
1899
1870
  tryResolveMountedCommand(command) {
1900
1871
  const normalized = normalizeCommandLookup(command);
1901
1872
  for (const driver of this.mountedRuntimeDrivers) {
@@ -1903,15 +1874,6 @@ class NativeKernel {
1903
1874
  continue;
1904
1875
  }
1905
1876
  this.commands.set(normalized, driver.kind);
1906
- if (driver.kind === "wasmvm" && this.proxy) {
1907
- const startIndex = this.runtimeDriverCommandDirStarts.get(driver);
1908
- if (startIndex !== undefined) {
1909
- const guestPaths = driver.getGuestCommandPaths?.(startIndex);
1910
- if (guestPaths?.has(normalized)) {
1911
- this.proxy.registerCommandGuestPaths(new Map([[normalized, guestPaths.get(normalized)]]));
1912
- }
1913
- }
1914
- }
1915
1877
  return true;
1916
1878
  }
1917
1879
  return false;
@@ -1946,7 +1908,7 @@ class NativeKernel {
1946
1908
  lowers: [
1947
1909
  {
1948
1910
  kind: "snapshot",
1949
- entries: rootFilesystemEntriesForConfig(mergeRootFilesystemEntries(createBootstrapEntries([...NODE_RUNTIME_BOOTSTRAP_COMMANDS]), snapshotEntries)),
1911
+ entries: rootFilesystemEntriesForConfig(mergeRootFilesystemEntries(createBootstrapEntries(), snapshotEntries)),
1950
1912
  },
1951
1913
  ],
1952
1914
  bootstrapEntries: [],
@@ -1965,6 +1927,7 @@ class NativeKernel {
1965
1927
  ? serializePermissionsForSidecar(bootstrapPermissions)
1966
1928
  : undefined,
1967
1929
  loopbackExemptPorts: this.loopbackExemptPorts,
1930
+ bootstrapCommands: [...NODE_RUNTIME_BOOTSTRAP_COMMANDS],
1968
1931
  };
1969
1932
  const vm = await client.createVm(session, {
1970
1933
  runtime: "java_script",
package/dist/runtime.d.ts CHANGED
@@ -224,6 +224,7 @@ export interface SystemDriver {
224
224
  network?: NetworkAdapter;
225
225
  commandExecutor?: CommandExecutor;
226
226
  permissions?: Permissions;
227
+ mounts: readonly NodeModulesMountConfig[];
227
228
  runtime: {
228
229
  process: ProcessConfig;
229
230
  os: OSConfig;
@@ -258,6 +259,13 @@ export interface NodeRuntimeDriverFactory {
258
259
  export interface KernelInterface {
259
260
  vfs: VirtualFileSystem;
260
261
  }
262
+ export interface KernelRecursiveDirEntry {
263
+ name: string;
264
+ path: string;
265
+ isDirectory: boolean;
266
+ isSymbolicLink: boolean;
267
+ size: number;
268
+ }
261
269
  export interface Kernel extends KernelInterface {
262
270
  mount(driver: KernelRuntimeDriver): Promise<void>;
263
271
  dispose(): Promise<void>;
@@ -273,11 +281,18 @@ export interface Kernel extends KernelInterface {
273
281
  writeFile(path: string, content: string | Uint8Array): Promise<void>;
274
282
  mkdir(path: string): Promise<void>;
275
283
  readdir(path: string): Promise<string[]>;
284
+ readdirRecursive(path: string, options?: {
285
+ maxDepth?: number;
286
+ }): Promise<KernelRecursiveDirEntry[]>;
276
287
  stat(path: string): Promise<VirtualStat>;
277
288
  exists(path: string): Promise<boolean>;
278
289
  removeFile(path: string): Promise<void>;
279
290
  removeDir(path: string): Promise<void>;
291
+ removePath(path: string, options?: {
292
+ recursive?: boolean;
293
+ }): Promise<void>;
280
294
  rename(oldPath: string, newPath: string): Promise<void>;
295
+ movePath(oldPath: string, newPath: string): Promise<void>;
281
296
  readonly commands: ReadonlyMap<string, string>;
282
297
  readonly processes: ReadonlyMap<number, ProcessInfo>;
283
298
  readonly env: Record<string, string>;
@@ -299,11 +314,23 @@ export interface BindingTree {
299
314
  [key: string]: BindingFunction | BindingTree;
300
315
  }
301
316
  export type BindingFunction = (...args: unknown[]) => unknown;
317
+ export interface NodeModulesMountConfig {
318
+ path: string;
319
+ plugin: {
320
+ id: "host_dir";
321
+ config: {
322
+ hostPath: string;
323
+ readOnly: boolean;
324
+ };
325
+ };
326
+ readOnly: boolean;
327
+ }
302
328
  export interface NodeDriverOptions {
303
329
  filesystem?: VirtualFileSystem;
304
330
  networkAdapter?: NetworkAdapter;
305
331
  commandExecutor?: CommandExecutor;
306
332
  permissions?: Permissions;
333
+ mounts?: readonly NodeModulesMountConfig[];
307
334
  processConfig?: ProcessConfig;
308
335
  osConfig?: OSConfig;
309
336
  }