@rivet-dev/agentos-core 0.2.8-rc.1 → 0.2.8-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +41 -38
  2. package/dist/agent-os.d.ts +189 -231
  3. package/dist/agent-os.js +756 -1162
  4. package/dist/agentos-package.d.ts +5 -3
  5. package/dist/agentos-package.js +5 -2
  6. package/dist/{host-tools-zod.d.ts → bindings-zod.d.ts} +1 -1
  7. package/dist/{host-tools-zod.js → bindings-zod.js} +27 -20
  8. package/dist/bindings.d.ts +43 -0
  9. package/dist/bindings.js +34 -0
  10. package/dist/cron/cron-manager.js +43 -10
  11. package/dist/cron/index.d.ts +1 -1
  12. package/dist/cron/types.d.ts +25 -9
  13. package/dist/filesystem-snapshot.d.ts +1 -2
  14. package/dist/filesystem-snapshot.js +0 -43
  15. package/dist/generated/AcpLimitsConfig.d.ts +16 -0
  16. package/dist/generated/BindingLimitsConfig.d.ts +10 -0
  17. package/dist/generated/CreateVmConfig.d.ts +2 -0
  18. package/dist/generated/ProcessLimitsConfig.d.ts +7 -0
  19. package/dist/generated/ProcessLimitsConfig.js +2 -0
  20. package/dist/generated/VmGroupConfig.d.ts +5 -0
  21. package/dist/generated/VmGroupConfig.js +2 -0
  22. package/dist/generated/VmLimitsConfig.d.ts +4 -2
  23. package/dist/generated/VmUserAccountConfig.d.ts +9 -0
  24. package/dist/generated/VmUserAccountConfig.js +2 -0
  25. package/dist/generated/VmUserConfig.d.ts +19 -0
  26. package/dist/generated/WasmLimitsConfig.d.ts +1 -0
  27. package/dist/index.d.ts +4 -5
  28. package/dist/index.js +4 -5
  29. package/dist/layers.d.ts +5 -2
  30. package/dist/layers.js +0 -185
  31. package/dist/options-schema.d.ts +133 -31
  32. package/dist/options-schema.js +143 -26
  33. package/dist/runtime-compat.d.ts +6 -35
  34. package/dist/runtime-compat.js +84 -372
  35. package/dist/runtime.d.ts +5 -1
  36. package/dist/sandbox.d.ts +4 -4
  37. package/dist/sandbox.js +4 -4
  38. package/dist/session-api.d.ts +180 -0
  39. package/dist/session-api.js +1 -0
  40. package/dist/sidecar/agentos-protocol.d.ts +429 -29
  41. package/dist/sidecar/agentos-protocol.js +691 -93
  42. package/dist/sidecar/rpc-client.d.ts +18 -6
  43. package/dist/sidecar/rpc-client.js +78 -31
  44. package/dist/test/runtime.d.ts +2 -1
  45. package/dist/test/runtime.js +2 -1
  46. package/dist/test/terminal-harness.js +0 -3
  47. package/dist/types.d.ts +4 -5
  48. package/package.json +21 -20
  49. package/dist/agent-session-types.d.ts +0 -67
  50. package/dist/generated/ToolLimitsConfig.d.ts +0 -10
  51. package/dist/host-tools.d.ts +0 -45
  52. package/dist/host-tools.js +0 -35
  53. package/dist/overlay-filesystem.d.ts +0 -19
  54. package/dist/overlay-filesystem.js +0 -645
  55. /package/dist/generated/{ToolLimitsConfig.js → BindingLimitsConfig.js} +0 -0
  56. /package/dist/{agent-session-types.js → generated/VmUserConfig.js} +0 -0
@@ -21,9 +21,11 @@ export type PackageRef = ManifestPackageRef;
21
21
  export type SoftwarePackageRef = {
22
22
  packagePath: string;
23
23
  };
24
- /** @deprecated Package software is now represented by its package directory. */
25
- export type PackageDescriptor = PackageRef;
26
- /** Discriminate the dir-only package reference. */
24
+ /** Portable descriptor used to link a package into a running VM. */
25
+ export interface PackageDescriptor {
26
+ path: string;
27
+ }
28
+ /** Discriminate the path-only package reference. */
27
29
  export declare function isPackageDescriptor(value: unknown): value is PackageDescriptor;
28
30
  export declare function readAgentosPackageManifest(dir: string): AgentosPackageManifest;
29
31
  export declare function tryReadAgentosPackageManifest(dir: string): AgentosPackageManifest | undefined;
@@ -17,9 +17,12 @@ import { join } from "node:path";
17
17
  export const OPT_AGENTOS_ROOT = "/opt/agentos";
18
18
  /** The symlink farm on `$PATH` (commands link here). */
19
19
  export const OPT_AGENTOS_BIN = "/opt/agentos/bin";
20
- /** Discriminate the dir-only package reference. */
20
+ /** Discriminate the path-only package reference. */
21
21
  export function isPackageDescriptor(value) {
22
- return typeof value === "string";
22
+ return (typeof value === "object" &&
23
+ value !== null &&
24
+ !Array.isArray(value) &&
25
+ typeof value.path === "string");
23
26
  }
24
27
  export function readAgentosPackageManifest(dir) {
25
28
  const manifestPath = join(dir, "agentos-package.json");
@@ -1,5 +1,5 @@
1
1
  import type { ZodType } from "zod";
2
- export declare class HostToolSchemaConversionError extends Error {
2
+ export declare class BindingSchemaConversionError extends Error {
3
3
  readonly path: string;
4
4
  readonly zodType: string;
5
5
  constructor(path: string, zodType: string, details?: string);
@@ -15,7 +15,7 @@ const UNSUPPORTED_TYPES = new Set([
15
15
  "pipe",
16
16
  "tuple",
17
17
  ]);
18
- export class HostToolSchemaConversionError extends Error {
18
+ export class BindingSchemaConversionError extends Error {
19
19
  path;
20
20
  zodType;
21
21
  constructor(path, zodType, details) {
@@ -25,7 +25,7 @@ export class HostToolSchemaConversionError extends Error {
25
25
  ]
26
26
  .filter(Boolean)
27
27
  .join(" "));
28
- this.name = "HostToolSchemaConversionError";
28
+ this.name = "BindingSchemaConversionError";
29
29
  this.path = path;
30
30
  this.zodType = zodType;
31
31
  }
@@ -50,7 +50,10 @@ function normalizeTypeName(schema) {
50
50
  if (constructorName === "discriminatedunion" || "discriminator" in def) {
51
51
  return "discriminatedunion";
52
52
  }
53
- const rawTypeName = String(def.typeName ?? def.type ?? schema.type ?? constructorName);
53
+ const rawTypeName = String(def.typeName ??
54
+ def.type ??
55
+ schema.type ??
56
+ constructorName);
54
57
  return rawTypeName.replace(/^Zod/, "").toLowerCase();
55
58
  }
56
59
  function displayTypeName(typeName) {
@@ -93,24 +96,24 @@ function isCustomRefinement(check) {
93
96
  }
94
97
  function validateChecks(schema, path, typeName) {
95
98
  if (getChecks(schema).some(isCustomRefinement)) {
96
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName), "custom refinements cannot be represented faithfully in JSON Schema");
99
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName), "custom refinements cannot be represented faithfully in JSON Schema");
97
100
  }
98
101
  }
99
102
  function validateSchema(schema, path) {
100
103
  const typeName = normalizeTypeName(schema);
101
104
  if (metadataProducesRefs(schema)) {
102
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName), "metadata that emits $ref/$defs is not supported");
105
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName), "metadata that emits $ref/$defs is not supported");
103
106
  }
104
107
  if (UNSUPPORTED_TYPES.has(typeName)) {
105
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName));
108
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName));
106
109
  }
107
110
  if (typeName === "discriminatedunion") {
108
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName));
111
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName));
109
112
  }
110
113
  if (TRANSPARENT_WRAPPER_TYPES.has(typeName)) {
111
114
  const inner = getInnerSchema(schema);
112
115
  if (!inner) {
113
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName), "wrapper schema is missing its inner schema");
116
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName), "wrapper schema is missing its inner schema");
114
117
  }
115
118
  validateSchema(inner, path);
116
119
  return;
@@ -118,7 +121,7 @@ function validateSchema(schema, path) {
118
121
  if (typeName === "nullable") {
119
122
  const inner = getInnerSchema(schema);
120
123
  if (!inner) {
121
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName), "nullable schema is missing its inner schema");
124
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName), "nullable schema is missing its inner schema");
122
125
  }
123
126
  validateSchema(inner, path);
124
127
  return;
@@ -138,7 +141,7 @@ function validateSchema(schema, path) {
138
141
  const def = getSchemaDef(schema);
139
142
  const itemSchema = (def.element ?? def.type);
140
143
  if (!itemSchema) {
141
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName), "array schema is missing its item schema");
144
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName), "array schema is missing its item schema");
142
145
  }
143
146
  validateSchema(itemSchema, `${path}[]`);
144
147
  return;
@@ -148,11 +151,11 @@ function validateSchema(schema, path) {
148
151
  const keySchema = def.keyType;
149
152
  const valueSchema = def.valueType;
150
153
  if (!keySchema || !valueSchema) {
151
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName), "record schema is missing its key or value schema");
154
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName), "record schema is missing its key or value schema");
152
155
  }
153
156
  const keyTypeName = normalizeTypeName(keySchema);
154
157
  if (keyTypeName !== "string" || getChecks(keySchema).length > 0) {
155
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName), "record keys must be unconstrained strings");
158
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName), "record keys must be unconstrained strings");
156
159
  }
157
160
  validateSchema(valueSchema, `${path}<record-value>`);
158
161
  return;
@@ -160,7 +163,7 @@ function validateSchema(schema, path) {
160
163
  if (typeName === "union") {
161
164
  const options = getSchemaDef(schema).options;
162
165
  if (!Array.isArray(options) || options.length === 0) {
163
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName), "union schema is missing its options");
166
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName), "union schema is missing its options");
164
167
  }
165
168
  for (let index = 0; index < options.length; index += 1) {
166
169
  validateSchema(options[index], `${path}<union:${index}>`);
@@ -176,8 +179,9 @@ function validateSchema(schema, path) {
176
179
  : [];
177
180
  const [literalValue] = literalValues;
178
181
  if (literalValues.length !== 1 ||
179
- !("string number boolean".split(" ").includes(typeof literalValue) || literalValue === null)) {
180
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName), "literal values must be JSON primitives");
182
+ !("string number boolean".split(" ").includes(typeof literalValue) ||
183
+ literalValue === null)) {
184
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName), "literal values must be JSON primitives");
181
185
  }
182
186
  return;
183
187
  }
@@ -188,7 +192,7 @@ function validateSchema(schema, path) {
188
192
  typeName === "nativeenum") {
189
193
  return;
190
194
  }
191
- throw new HostToolSchemaConversionError(path, displayTypeName(typeName));
195
+ throw new BindingSchemaConversionError(path, displayTypeName(typeName));
192
196
  }
193
197
  function sanitizeJsonSchema(value) {
194
198
  if (Array.isArray(value)) {
@@ -203,7 +207,9 @@ function sanitizeJsonSchema(value) {
203
207
  if (key === "$schema") {
204
208
  continue;
205
209
  }
206
- if (key === "additionalProperties" && entry === false && record.type === "object") {
210
+ if (key === "additionalProperties" &&
211
+ entry === false &&
212
+ record.type === "object") {
207
213
  continue;
208
214
  }
209
215
  sanitized[key] = sanitizeJsonSchema(entry);
@@ -243,8 +249,9 @@ function generateJsonSchema(schema) {
243
249
  $refStrategy: "none",
244
250
  target: "jsonSchema7",
245
251
  });
246
- if (!generated || (typeof generated === "object" && Object.keys(generated).length === 0)) {
247
- throw new HostToolSchemaConversionError("$", displayTypeName(normalizeTypeName(schema)), "schema cannot be converted to JSON Schema");
252
+ if (!generated ||
253
+ (typeof generated === "object" && Object.keys(generated).length === 0)) {
254
+ throw new BindingSchemaConversionError("$", displayTypeName(normalizeTypeName(schema)), "schema cannot be converted to JSON Schema");
248
255
  }
249
256
  return generated;
250
257
  }
@@ -253,7 +260,7 @@ export function zodToJsonSchema(schema) {
253
260
  const jsonSchema = generateJsonSchema(schema);
254
261
  const unsupportedKeyword = findUnsupportedGeneratedKeyword(jsonSchema, "$");
255
262
  if (unsupportedKeyword) {
256
- throw new HostToolSchemaConversionError("$", displayTypeName(normalizeTypeName(schema)), `${unsupportedKeyword.keyword} emitted at ${unsupportedKeyword.path} is not supported`);
263
+ throw new BindingSchemaConversionError("$", displayTypeName(normalizeTypeName(schema)), `${unsupportedKeyword.keyword} emitted at ${unsupportedKeyword.path} is not supported`);
257
264
  }
258
265
  const sanitized = sanitizeJsonSchema(jsonSchema);
259
266
  const description = getDescription(schema);
@@ -0,0 +1,43 @@
1
+ import type { ZodType } from "zod";
2
+ /** Maximum length for binding descriptions (characters). */
3
+ export declare const MAX_BINDING_DESCRIPTION_LENGTH = 200;
4
+ /**
5
+ * A single binding that executes on the host.
6
+ */
7
+ export interface Binding<INPUT = any, OUTPUT = any> {
8
+ /** Description shown to the agent in --help and prompt docs. Max 200 characters. */
9
+ description: string;
10
+ /** Zod schema for the input. Drives CLI flag generation and validation. */
11
+ inputSchema: ZodType<INPUT>;
12
+ /** Runs on the host when the agent invokes the binding. */
13
+ execute: (input: INPUT) => Promise<OUTPUT> | OUTPUT;
14
+ /** Examples included in auto-generated prompt docs. */
15
+ examples?: BindingExample<INPUT>[];
16
+ /** Timeout in ms. Default: 30000. */
17
+ timeout?: number;
18
+ }
19
+ export interface BindingExample<INPUT = any> {
20
+ /** Human description of what this example does. */
21
+ description: string;
22
+ /** The input args for the example. */
23
+ input: INPUT;
24
+ }
25
+ /**
26
+ * A named collection of bindings. Becomes a CLI binary: agentos-{name}.
27
+ */
28
+ export interface Bindings {
29
+ /** Collection name. Must be lowercase alphanumeric + hyphens. Becomes the CLI suffix: agentos-{name}. */
30
+ name: string;
31
+ /** Description shown in `agentos list-bindings` and prompt docs. */
32
+ description: string;
33
+ /** The bindings in this collection. Keys become subcommands. */
34
+ bindings: Record<string, Binding>;
35
+ }
36
+ /** Helper to create a binding with type inference. */
37
+ export declare function binding<INPUT, OUTPUT>(def: Binding<INPUT, OUTPUT>): Binding<INPUT, OUTPUT>;
38
+ /** Helper to create a named binding collection. */
39
+ export declare function bindings(def: Bindings): Bindings;
40
+ /**
41
+ * Validate every binding collection and binding.
42
+ */
43
+ export declare function validateBindings(collections: Bindings[]): void;
@@ -0,0 +1,34 @@
1
+ /** Maximum length for binding descriptions (characters). */
2
+ export const MAX_BINDING_DESCRIPTION_LENGTH = 200;
3
+ /** Helper to create a binding with type inference. */
4
+ export function binding(def) {
5
+ return def;
6
+ }
7
+ /** Helper to create a named binding collection. */
8
+ export function bindings(def) {
9
+ return def;
10
+ }
11
+ const BINDING_COMMAND_NAME_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
12
+ function validateBindingCommandName(kind, name) {
13
+ if (BINDING_COMMAND_NAME_RE.test(name)) {
14
+ return;
15
+ }
16
+ throw new Error(`${kind} name "${name}" must be lowercase alphanumeric with optional single hyphen separators`);
17
+ }
18
+ /**
19
+ * Validate every binding collection and binding.
20
+ */
21
+ export function validateBindings(collections) {
22
+ for (const collection of collections) {
23
+ validateBindingCommandName("Binding collection", collection.name);
24
+ if (collection.description.length > MAX_BINDING_DESCRIPTION_LENGTH) {
25
+ throw new Error(`Binding collection "${collection.name}" description is ${collection.description.length} characters, max is ${MAX_BINDING_DESCRIPTION_LENGTH}`);
26
+ }
27
+ for (const [bindingName, definition] of Object.entries(collection.bindings)) {
28
+ validateBindingCommandName("Binding", bindingName);
29
+ if (definition.description.length > MAX_BINDING_DESCRIPTION_LENGTH) {
30
+ throw new Error(`Binding "${collection.name}/${bindingName}" description is ${definition.description.length} characters, max is ${MAX_BINDING_DESCRIPTION_LENGTH}`);
31
+ }
32
+ }
33
+ }
34
+ }
@@ -1,5 +1,26 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { resolveSchedule, validateScheduleForRegistration, } from "./parse-schedule.js";
3
+ function describeAction(action) {
4
+ switch (action.type) {
5
+ case "session":
6
+ return {
7
+ type: "session",
8
+ agentType: action.agentType,
9
+ prompt: action.prompt,
10
+ ...(action.options === undefined
11
+ ? {}
12
+ : { options: structuredClone(action.options) }),
13
+ };
14
+ case "exec":
15
+ return {
16
+ type: "exec",
17
+ command: action.command,
18
+ ...(action.args === undefined ? {} : { args: [...action.args] }),
19
+ };
20
+ case "callback":
21
+ return { type: "callback" };
22
+ }
23
+ }
3
24
  /**
4
25
  * Compute the next fire time for a schedule string. Returns undefined if
5
26
  * the schedule is a one-shot ISO timestamp in the past or if croner
@@ -58,10 +79,10 @@ export class CronManager {
58
79
  result.push({
59
80
  id: state.id,
60
81
  schedule: state.schedule,
61
- action: state.action,
82
+ action: describeAction(state.action),
62
83
  overlap: state.overlap,
63
- lastRun: state.lastRun,
64
- nextRun: state.nextRun,
84
+ lastRun: state.lastRun?.toISOString(),
85
+ nextRun: state.nextRun?.toISOString(),
65
86
  runCount: state.runCount,
66
87
  running: state.running,
67
88
  });
@@ -103,14 +124,18 @@ export class CronManager {
103
124
  state.running = true;
104
125
  state.lastRun = new Date();
105
126
  state.runCount++;
106
- this.emit({ type: "cron:fire", jobId: state.id, time: new Date() });
127
+ this.emit({
128
+ type: "cron:fire",
129
+ jobId: state.id,
130
+ time: new Date().toISOString(),
131
+ });
107
132
  const startTime = Date.now();
108
133
  try {
109
134
  await this.runAction(state.action);
110
135
  this.emit({
111
136
  type: "cron:complete",
112
137
  jobId: state.id,
113
- time: new Date(),
138
+ time: new Date().toISOString(),
114
139
  durationMs: Date.now() - startTime,
115
140
  });
116
141
  }
@@ -118,8 +143,8 @@ export class CronManager {
118
143
  this.emit({
119
144
  type: "cron:error",
120
145
  jobId: state.id,
121
- time: new Date(),
122
- error: error,
146
+ time: new Date().toISOString(),
147
+ error: error instanceof Error ? error.message : String(error),
123
148
  });
124
149
  }
125
150
  finally {
@@ -135,12 +160,20 @@ export class CronManager {
135
160
  async runAction(action) {
136
161
  switch (action.type) {
137
162
  case "session": {
138
- const { sessionId } = await this.vm.createSession(action.agentType, action.options);
163
+ const sessionId = `cron-${randomUUID()}`;
164
+ await this.vm.openSession({
165
+ ...action.options,
166
+ sessionId,
167
+ agent: action.agentType,
168
+ });
139
169
  try {
140
- await this.vm.prompt(sessionId, action.prompt);
170
+ await this.vm.prompt({
171
+ sessionId,
172
+ content: [{ type: "text", text: action.prompt }],
173
+ });
141
174
  }
142
175
  finally {
143
- this.vm.closeSession(sessionId);
176
+ await this.vm.deleteSession({ sessionId });
144
177
  }
145
178
  break;
146
179
  }
@@ -2,4 +2,4 @@ export { CronManager } from "./cron-manager.js";
2
2
  export { InvalidScheduleError, PastScheduleError, } from "./parse-schedule.js";
3
3
  export type { ScheduleDriver, ScheduleEntry, ScheduleHandle, } from "./schedule-driver.js";
4
4
  export { TimerScheduleDriver } from "./timer-driver.js";
5
- export type { CronAction, CronEvent, CronEventHandler, CronJob, CronJobInfo, CronJobOptions, } from "./types.js";
5
+ export type { CronAction, CronActionInfo, CronEvent, CronEventHandler, CronJob, CronJobInfo, CronJobOptions, } from "./types.js";
@@ -1,10 +1,10 @@
1
- import type { CreateSessionOptions } from "../agent-os.js";
1
+ import type { OpenSessionInput } from "../session-api.js";
2
2
  import type { AgentType } from "../types.js";
3
3
  export type CronAction = {
4
4
  type: "session";
5
5
  agentType: AgentType;
6
6
  prompt: string;
7
- options?: CreateSessionOptions;
7
+ options?: Omit<OpenSessionInput, "agent" | "sessionId">;
8
8
  } | {
9
9
  type: "exec";
10
10
  command: string;
@@ -13,6 +13,22 @@ export type CronAction = {
13
13
  type: "callback";
14
14
  fn: () => void | Promise<void>;
15
15
  };
16
+ /**
17
+ * Serializable description of a scheduled action. Callback jobs deliberately
18
+ * expose only their kind: the host closure is execution state, not job data.
19
+ */
20
+ export type CronActionInfo = {
21
+ type: "session";
22
+ agentType: AgentType;
23
+ prompt: string;
24
+ options?: Omit<OpenSessionInput, "agent" | "sessionId">;
25
+ } | {
26
+ type: "exec";
27
+ command: string;
28
+ args?: string[];
29
+ } | {
30
+ type: "callback";
31
+ };
16
32
  export interface CronJobOptions {
17
33
  /** Optional ID. Auto-generated UUID if omitted. */
18
34
  id?: string;
@@ -30,26 +46,26 @@ export interface CronJob {
30
46
  export interface CronJobInfo {
31
47
  id: string;
32
48
  schedule: string;
33
- action: CronAction;
49
+ action: CronActionInfo;
34
50
  overlap: "allow" | "skip" | "queue";
35
- lastRun?: Date;
36
- nextRun?: Date;
51
+ lastRun?: string;
52
+ nextRun?: string;
37
53
  runCount: number;
38
54
  running: boolean;
39
55
  }
40
56
  export type CronEvent = {
41
57
  type: "cron:fire";
42
58
  jobId: string;
43
- time: Date;
59
+ time: string;
44
60
  } | {
45
61
  type: "cron:complete";
46
62
  jobId: string;
47
- time: Date;
63
+ time: string;
48
64
  durationMs: number;
49
65
  } | {
50
66
  type: "cron:error";
51
67
  jobId: string;
52
- time: Date;
53
- error: Error;
68
+ time: string;
69
+ error: string;
54
70
  };
55
71
  export type CronEventHandler = (event: CronEvent) => void;
@@ -1,4 +1,4 @@
1
- import { type VirtualFileSystem } from "./runtime-compat.js";
1
+ import type { VirtualFileSystem } from "./runtime-compat.js";
2
2
  export interface FilesystemEntry {
3
3
  path: string;
4
4
  type: "directory" | "file" | "symlink";
@@ -10,5 +10,4 @@ export interface FilesystemEntry {
10
10
  target?: string;
11
11
  }
12
12
  export declare function sortFilesystemEntries(entries: FilesystemEntry[]): FilesystemEntry[];
13
- export declare function createFilesystemFromEntries(entries: FilesystemEntry[]): Promise<VirtualFileSystem>;
14
13
  export declare function snapshotVirtualFilesystem(filesystem: VirtualFileSystem, rootPath?: string): Promise<FilesystemEntry[]>;
@@ -1,8 +1,4 @@
1
1
  import * as posixPath from "node:path/posix";
2
- import { createInMemoryFileSystem, } from "./runtime-compat.js";
3
- function parseMode(mode) {
4
- return Number.parseInt(mode, 8);
5
- }
6
2
  export function sortFilesystemEntries(entries) {
7
3
  return [...entries].sort((a, b) => {
8
4
  const depthA = a.path === "/" ? 0 : a.path.split("/").filter(Boolean).length;
@@ -13,45 +9,6 @@ export function sortFilesystemEntries(entries) {
13
9
  return a.path.localeCompare(b.path);
14
10
  });
15
11
  }
16
- async function applyDirectory(filesystem, entry) {
17
- if (entry.path !== "/") {
18
- await filesystem.mkdir(entry.path, { recursive: true });
19
- }
20
- await filesystem.chmod(entry.path, parseMode(entry.mode));
21
- await filesystem.chown(entry.path, entry.uid, entry.gid);
22
- }
23
- async function applyFile(filesystem, entry) {
24
- const content = entry.content ?? "";
25
- await filesystem.writeFile(entry.path, entry.encoding === "base64" ? Buffer.from(content, "base64") : content);
26
- await filesystem.chmod(entry.path, parseMode(entry.mode));
27
- await filesystem.chown(entry.path, entry.uid, entry.gid);
28
- }
29
- async function applySymlink(filesystem, entry) {
30
- if (!entry.target) {
31
- throw new Error(`Missing symlink target for ${entry.path}`);
32
- }
33
- await filesystem.symlink(entry.target, entry.path);
34
- }
35
- export async function createFilesystemFromEntries(entries) {
36
- const filesystem = createInMemoryFileSystem();
37
- const sortedEntries = sortFilesystemEntries(entries);
38
- for (const entry of sortedEntries) {
39
- if (entry.type === "directory") {
40
- await applyDirectory(filesystem, entry);
41
- }
42
- }
43
- for (const entry of sortedEntries) {
44
- if (entry.type === "file") {
45
- await applyFile(filesystem, entry);
46
- }
47
- }
48
- for (const entry of sortedEntries) {
49
- if (entry.type === "symlink") {
50
- await applySymlink(filesystem, entry);
51
- }
52
- }
53
- return filesystem;
54
- }
55
12
  function toModeString(mode) {
56
13
  return `0${(mode & 0o7777).toString(8)}`;
57
14
  }
@@ -1,4 +1,20 @@
1
1
  export type AcpLimitsConfig = {
2
2
  maxReadLineBytes?: number;
3
3
  stdoutBufferByteLimit?: number;
4
+ maxCompletedMessageBytes?: number;
5
+ maxTurnOutputBytes?: number;
6
+ maxPromptBytes?: number;
7
+ maxPromptBlocks?: number;
8
+ maxFallbackContinuationBytes?: number;
9
+ maxSessionHistoryBytes?: number;
10
+ maxSessionHistoryEvents?: number;
11
+ maxHistoryPageEntries?: number;
12
+ maxSessionListEntries?: number;
13
+ maxSessionsPerVm?: number;
14
+ maxPromptsPerSession?: number;
15
+ maxPromptsPerVm?: number;
16
+ maxPendingPermissionsPerSession?: number;
17
+ maxPendingPermissionsPerVm?: number;
18
+ maxPermissionOutcomesPerSession?: number;
19
+ maxPermissionOutcomesPerVm?: number;
4
20
  };
@@ -0,0 +1,10 @@
1
+ export type BindingLimitsConfig = {
2
+ defaultBindingTimeoutMs?: number;
3
+ maxBindingTimeoutMs?: number;
4
+ maxRegisteredCollections?: number;
5
+ maxRegisteredBindingsPerVm?: number;
6
+ maxBindingsPerCollection?: number;
7
+ maxBindingSchemaBytes?: number;
8
+ maxExamplesPerBinding?: number;
9
+ maxBindingExampleInputBytes?: number;
10
+ };
@@ -5,6 +5,7 @@ import type { RootFilesystemConfig } from "./RootFilesystemConfig.js";
5
5
  import type { VmDnsConfig } from "./VmDnsConfig.js";
6
6
  import type { VmLimitsConfig } from "./VmLimitsConfig.js";
7
7
  import type { VmListenPolicyConfig } from "./VmListenPolicyConfig.js";
8
+ import type { VmUserConfig } from "./VmUserConfig.js";
8
9
  /**
9
10
  * Canonical Rust-side VM config. Unknown fields must stay rejected here and in
10
11
  * the TS preflight schema at
@@ -14,6 +15,7 @@ import type { VmListenPolicyConfig } from "./VmListenPolicyConfig.js";
14
15
  export type CreateVmConfig = {
15
16
  cwd?: string;
16
17
  env: Record<string, string>;
18
+ user?: VmUserConfig;
17
19
  rootFilesystem: RootFilesystemConfig;
18
20
  permissions?: PermissionsPolicy;
19
21
  limits?: VmLimitsConfig;
@@ -0,0 +1,7 @@
1
+ export type ProcessLimitsConfig = {
2
+ maxSpawnFileActions?: number;
3
+ maxSpawnFileActionBytes?: number;
4
+ pendingStdinBytes?: number;
5
+ pendingEventCount?: number;
6
+ pendingEventBytes?: number;
7
+ };
@@ -0,0 +1,2 @@
1
+ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2
+ export {};
@@ -0,0 +1,5 @@
1
+ export type VmGroupConfig = {
2
+ gid: number;
3
+ name: string;
4
+ members: Array<string>;
5
+ };
@@ -0,0 +1,2 @@
1
+ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2
+ export {};
@@ -1,18 +1,20 @@
1
1
  import type { AcpLimitsConfig } from "./AcpLimitsConfig.js";
2
+ import type { BindingLimitsConfig } from "./BindingLimitsConfig.js";
2
3
  import type { HttpLimitsConfig } from "./HttpLimitsConfig.js";
3
4
  import type { JsRuntimeLimitsConfig } from "./JsRuntimeLimitsConfig.js";
4
5
  import type { PluginLimitsConfig } from "./PluginLimitsConfig.js";
6
+ import type { ProcessLimitsConfig } from "./ProcessLimitsConfig.js";
5
7
  import type { PythonLimitsConfig } from "./PythonLimitsConfig.js";
6
8
  import type { ResourceLimitsConfig } from "./ResourceLimitsConfig.js";
7
- import type { ToolLimitsConfig } from "./ToolLimitsConfig.js";
8
9
  import type { WasmLimitsConfig } from "./WasmLimitsConfig.js";
9
10
  export type VmLimitsConfig = {
10
11
  resources?: ResourceLimitsConfig;
11
12
  http?: HttpLimitsConfig;
12
- tools?: ToolLimitsConfig;
13
+ bindings?: BindingLimitsConfig;
13
14
  plugins?: PluginLimitsConfig;
14
15
  acp?: AcpLimitsConfig;
15
16
  jsRuntime?: JsRuntimeLimitsConfig;
16
17
  python?: PythonLimitsConfig;
17
18
  wasm?: WasmLimitsConfig;
19
+ process?: ProcessLimitsConfig;
18
20
  };
@@ -0,0 +1,9 @@
1
+ export type VmUserAccountConfig = {
2
+ uid: number;
3
+ gid: number;
4
+ username: string;
5
+ homedir: string;
6
+ shell: string;
7
+ gecos?: string;
8
+ supplementaryGids: Array<number>;
9
+ };
@@ -0,0 +1,2 @@
1
+ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2
+ export {};
@@ -0,0 +1,19 @@
1
+ import type { VmGroupConfig } from "./VmGroupConfig.js";
2
+ import type { VmUserAccountConfig } from "./VmUserAccountConfig.js";
3
+ /**
4
+ * Initial Linux-style credentials and account record for processes in a VM.
5
+ */
6
+ export type VmUserConfig = {
7
+ uid?: number;
8
+ gid?: number;
9
+ euid?: number;
10
+ egid?: number;
11
+ username?: string;
12
+ homedir?: string;
13
+ shell?: string;
14
+ gecos?: string;
15
+ groupName?: string;
16
+ supplementaryGids?: Array<number>;
17
+ accounts?: Array<VmUserAccountConfig>;
18
+ groups?: Array<VmGroupConfig>;
19
+ };
@@ -4,4 +4,5 @@ export type WasmLimitsConfig = {
4
4
  syncReadLimitBytes?: number;
5
5
  prewarmTimeoutMs?: number;
6
6
  runnerHeapLimitMb?: number;
7
+ runnerCpuTimeLimitMs?: number;
7
8
  };