withruntime 0.8.4 → 0.9.0

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 (91) hide show
  1. package/COMPATIBILITY.md +145 -0
  2. package/E2B.md +23 -13
  3. package/README.md +8 -5
  4. package/README.src.md +8 -5
  5. package/compatibility-lock.json +281 -0
  6. package/dist/ai-harness/index.js +2 -2
  7. package/dist/api-defaults.d.ts +17 -0
  8. package/dist/api-defaults.js +22 -0
  9. package/dist/blaxel/preview.d.ts +1 -1
  10. package/dist/blaxel/preview.js +1 -1
  11. package/dist/blaxel/process.d.ts +1 -1
  12. package/dist/blaxel/process.js +11 -2
  13. package/dist/cli-words.d.ts +27 -0
  14. package/dist/cli-words.js +135 -0
  15. package/dist/cli.js +162 -31
  16. package/dist/client.d.ts +4 -1
  17. package/dist/client.js +8 -2
  18. package/dist/cloudflare/index.d.ts +294 -0
  19. package/dist/cloudflare/index.js +554 -0
  20. package/dist/cloudflare/worker.d.ts +415 -0
  21. package/dist/cloudflare/worker.js +297 -0
  22. package/dist/codesandbox/guest-service.d.ts +31 -0
  23. package/dist/codesandbox/guest-service.js +453 -0
  24. package/dist/codesandbox/index.d.ts +386 -0
  25. package/dist/codesandbox/index.js +1313 -0
  26. package/dist/compat/core.d.ts +39 -0
  27. package/dist/compat/core.js +199 -0
  28. package/dist/compat/files.d.ts +26 -0
  29. package/dist/compat/files.js +115 -0
  30. package/dist/compat/shell.d.ts +4 -0
  31. package/dist/compat/shell.js +165 -0
  32. package/dist/daytona/context.js +2 -1
  33. package/dist/daytona/process.d.ts +1 -1
  34. package/dist/daytona/process.js +27 -4
  35. package/dist/e2b/code-interpreter.d.ts +4 -5
  36. package/dist/e2b/code-interpreter.js +54 -56
  37. package/dist/e2b/commands.d.ts +5 -4
  38. package/dist/e2b/commands.js +37 -29
  39. package/dist/e2b/errors.js +1 -1
  40. package/dist/e2b/filesystem.d.ts +8 -6
  41. package/dist/e2b/filesystem.js +127 -28
  42. package/dist/e2b/sandbox.d.ts +4 -3
  43. package/dist/e2b/sandbox.js +10 -10
  44. package/dist/errors.d.ts +8 -0
  45. package/dist/errors.js +15 -2
  46. package/dist/freestyle/index.d.ts +301 -0
  47. package/dist/freestyle/index.js +310 -0
  48. package/dist/index.d.ts +1 -0
  49. package/dist/mcp.js +2 -2
  50. package/dist/modal/index.d.ts +205 -0
  51. package/dist/modal/index.js +485 -0
  52. package/dist/network-cli.js +1 -1
  53. package/dist/openai-agents/index.js +9 -26
  54. package/dist/products/audit.d.ts +3 -0
  55. package/dist/products/index.d.ts +2 -0
  56. package/dist/products/index.js +2 -0
  57. package/dist/products/interpreter.d.ts +11 -4
  58. package/dist/products/interpreter.js +33 -9
  59. package/dist/products/jobs.js +3 -2
  60. package/dist/products/limits.d.ts +10 -0
  61. package/dist/products/previews.d.ts +10 -2
  62. package/dist/products/previews.js +3 -2
  63. package/dist/products/tailscale.d.ts +57 -0
  64. package/dist/products/tailscale.js +17 -0
  65. package/dist/products/watch.d.ts +25 -4
  66. package/dist/products/watch.js +75 -14
  67. package/dist/runloop/index.d.ts +340 -0
  68. package/dist/runloop/index.js +438 -0
  69. package/dist/runloop/pagination.d.ts +46 -0
  70. package/dist/runloop/pagination.js +82 -0
  71. package/dist/runloop/snapshots.d.ts +52 -0
  72. package/dist/runloop/snapshots.js +244 -0
  73. package/dist/sandbox.d.ts +40 -9
  74. package/dist/sandbox.js +273 -76
  75. package/dist/snapshots.d.ts +11 -1
  76. package/dist/snapshots.js +11 -1
  77. package/dist/sprites/index.d.ts +251 -0
  78. package/dist/sprites/index.js +552 -0
  79. package/dist/tar.d.ts +8 -1
  80. package/dist/tar.js +185 -35
  81. package/dist/tools/index.js +2 -1
  82. package/dist/transport.d.ts +20 -2
  83. package/dist/transport.js +48 -11
  84. package/dist/types.d.ts +52 -3
  85. package/dist/vercel/command.js +12 -1
  86. package/dist/vercel/errors.d.ts +2 -2
  87. package/dist/vercel/errors.js +12 -1
  88. package/dist/vercel/filesystem.d.ts +21 -18
  89. package/dist/vercel/filesystem.js +95 -48
  90. package/dist/vercel/sandbox.js +5 -5
  91. package/package.json +45 -3
@@ -0,0 +1,22 @@
1
+ /* Every value this SDK sends the API for a bounded time field when the caller
2
+ * names none, in one place. packages/cloud/tests/sdk-defaults.test.ts holds
3
+ * each inside the range the API's registry gives that field, and the same
4
+ * names in the Python, Go, Java and Ruby SDKs to theirs. The suffix is the
5
+ * unit; a new default goes here, under a name that test maps to its field. */
6
+ /** A server-side wait for a state (`GET /v1/sandboxes/{id}?waitFor=`). */
7
+ export const WAIT_FOR_TIMEOUT_SECONDS = 60;
8
+ /** A streamed exec's command limit when none is given: the API's longest. */
9
+ export const STREAMED_EXEC_TIMEOUT_MS = 86_400_000;
10
+ /** The lease keepAlive keeps ahead of now, and so the most it extends by. */
11
+ export const KEEP_ALIVE_MARGIN_SECONDS = 600;
12
+ /** A webhook watch runs until stopped. */
13
+ export const WEBHOOK_WATCH_TIMEOUT_MS = 0;
14
+ /** A job run's limit, and the time added to it for its sandbox to start. */
15
+ export const JOB_TIMEOUT_SECONDS = 1800;
16
+ export const JOB_START_SECONDS = 60;
17
+ /** A command the framework-free tools run without a timeout of its own. */
18
+ export const TOOL_EXEC_TIMEOUT_SECONDS = 300;
19
+ /** A command the AI SDK harness runs without a timeout of its own. */
20
+ export const AI_HARNESS_COMMAND_TIMEOUT_MS = 3_600_000;
21
+ /** A command the OpenAI Agents sandbox runs without a timeout of its own. */
22
+ export const OPENAI_AGENTS_EXEC_TIMEOUT_MS = 3_600_000;
@@ -98,7 +98,7 @@ export declare class SandboxPreviews {
98
98
  /** The named preview, or a new one when there is none. */
99
99
  createIfNotExists(preview: Preview, force?: boolean): Promise<SandboxPreview>;
100
100
  get(previewName: string): Promise<SandboxPreview>;
101
- /** Stops sharing the port; open connections close within seconds. */
101
+ /** Stops sharing the port; its open connections are closed before this returns. */
102
102
  delete(previewName: string): Promise<Preview>;
103
103
  }
104
104
  /** A private preview of `port` with a token that lasts a while, for
@@ -193,7 +193,7 @@ export class SandboxPreviews {
193
193
  const found = await this.#ctx.run((runtime) => runtime.previews.get(port));
194
194
  return new SandboxPreview(modelOf(found, previewName, this.sandboxName), this.#ctx);
195
195
  }
196
- /** Stops sharing the port; open connections close within seconds. */
196
+ /** Stops sharing the port; its open connections are closed before this returns. */
197
197
  async delete(previewName) {
198
198
  const port = this.#portOf(previewName);
199
199
  if (port === undefined)
@@ -87,7 +87,7 @@ export declare class SandboxProcess {
87
87
  * process running; with it, once the process ends, with its output. */
88
88
  exec(request: ProcessRequest | ProcessRequestWithLog): Promise<PostProcessResponse | ProcessResponseWithLog>;
89
89
  /** The process, with the output it has written so far. */
90
- get(identifier: string, _options?: {
90
+ get(identifier: string, options?: {
91
91
  signal?: AbortSignal;
92
92
  retry?: boolean;
93
93
  }): Promise<GetProcessByIdentifierResponse>;
@@ -182,6 +182,8 @@ export class SandboxProcess {
182
182
  const startedAt = new Date().toISOString();
183
183
  const run = async () => {
184
184
  for await (const event of runtime.execStream(line, { ...options, signal: abort.signal })) {
185
+ if (event.type === "truncated")
186
+ throw responseError(502, "Some command output is no longer available.");
185
187
  if (event.type === "start") {
186
188
  id = event.processId;
187
189
  this.#remember(id, meta);
@@ -324,12 +326,15 @@ export class SandboxProcess {
324
326
  const runtime = await this.#ctx.live();
325
327
  const abort = new AbortController();
326
328
  const forward = () => abort.abort();
329
+ signal?.throwIfAborted();
327
330
  signal?.addEventListener("abort", forward, { once: true });
328
331
  try {
329
332
  for await (const event of runtime.processes.follow(found.id, {
330
333
  cursor: 0,
331
334
  signal: abort.signal,
332
335
  })) {
336
+ if (event.type === "truncated")
337
+ throw responseError(502, "Some command output is no longer available.");
333
338
  if (event.type === "stdout" || event.type === "stderr") {
334
339
  out[event.type] += event.data;
335
340
  out.logs += event.data;
@@ -362,9 +367,10 @@ export class SandboxProcess {
362
367
  return out;
363
368
  }
364
369
  /** The process, with the output it has written so far. */
365
- async get(identifier, _options = {}) {
370
+ async get(identifier, options = {}) {
371
+ options.signal?.throwIfAborted();
366
372
  const found = await this.#find(identifier);
367
- const out = await this.#output(found, false);
373
+ const out = await this.#output(found, false, options.signal);
368
374
  return this.#settled(this.#response(found.info, this.#registry.meta.get(found.id), out));
369
375
  }
370
376
  /** Waits for the process to end (at most `maxWait` ms, -1 for no limit) and
@@ -381,6 +387,7 @@ export class SandboxProcess {
381
387
  throw late();
382
388
  const abort = new AbortController();
383
389
  const forward = () => abort.abort(signal?.reason);
390
+ signal?.throwIfAborted();
384
391
  signal?.addEventListener("abort", forward, { once: true });
385
392
  const timer = maxWait === -1 ? undefined : setTimeout(() => abort.abort(late()), maxWait);
386
393
  try {
@@ -476,6 +483,8 @@ export class SandboxProcess {
476
483
  cursor: 0,
477
484
  signal: abort.signal,
478
485
  })) {
486
+ if (event.type === "truncated")
487
+ throw responseError(502, "Some command output is no longer available.");
479
488
  if (event.type === "stdout" || event.type === "stderr") {
480
489
  const lines = (partial[event.type] + event.data).split(/\r?\n/);
481
490
  partial[event.type] = lines.pop();
@@ -0,0 +1,27 @@
1
+ import type { RuntimeError } from "./errors.js";
2
+ import type { SandboxMetrics } from "./products/observability.js";
3
+ /** A refusal of what a command sent, reworded for the command line: every
4
+ * issue named by its option, since the CLI never prints details.issues, and
5
+ * a hint that names the options rather than the request's fields. Anything
6
+ * else is left as the API said it. */
7
+ export declare function cliRefusal(error: RuntimeError): {
8
+ message: string;
9
+ hint?: string;
10
+ };
11
+ /** A resource read as one fact a line, as `sandbox get` prints: a list
12
+ * joined, a nested record as its own facts, nothing as `-`. */
13
+ export declare function describeRecord(record: Record<string, unknown>, table: (rows: string[][]) => string): string;
14
+ /** The newest CPU reading the metrics hold, and how old it is. `latest` is
15
+ * the last sample, which can carry no CPU figure (the first after a wake has
16
+ * nothing to compare with), while the points before it do; "no reading"
17
+ * above a sparkline of readings contradicted itself. */
18
+ export declare function newestCpu(m: SandboxMetrics, now?: number): {
19
+ percent: number;
20
+ cores: number | null;
21
+ ago: string | null;
22
+ } | null;
23
+ /** The lines of the top-level help about one command, ` feedback ...` and
24
+ * the lines that continue it, or null when it has none. `runtime feedback
25
+ * help` filed "help" as feedback, and `runtime support help` sent it to
26
+ * support, until 30 September 2026. */
27
+ export declare function topicHelp(help: string, command: string): string | null;
@@ -0,0 +1,135 @@
1
+ /* What the CLI says in its own words where the API's would mislead: the
2
+ option a refusal is about rather than the request field it was sent as,
3
+ one fact a line for a resource read, and the newest CPU reading a
4
+ sandbox's metrics hold. Kept out of cli.ts, which many hands edit. */
5
+ /** The request fields a command line sets, by the option that sets them.
6
+ * An amount in microdollars is typed in dollars. */
7
+ const OPTIONS = {
8
+ name: { flag: "--name" },
9
+ labels: { flag: "--label" },
10
+ env: { flag: "--env" },
11
+ region: { flag: "--region" },
12
+ vcpu: { flag: "--vcpu" },
13
+ memoryMiB: { flag: "--memory" },
14
+ diskMiB: { flag: "--disk" },
15
+ cpu: { flag: "--cpu" },
16
+ cpuFloorMillis: { flag: "--cpu-floor" },
17
+ timeoutSeconds: { flag: "--timeout" },
18
+ onLeaseEnd: { flag: "--on-timeout" },
19
+ idlePauseSeconds: { flag: "--idle-pause" },
20
+ autoWake: { flag: "--no-auto-wake / --auto-wake" },
21
+ persistent: { flag: "--persistent" },
22
+ funding: { flag: "--trial / --paid" },
23
+ image: { flag: "--image" },
24
+ snapshot: { flag: "--snapshot" },
25
+ volumes: { flag: "--volume" },
26
+ network: { flag: "--allow / --deny / --connect / --no-internet" },
27
+ maxCostMicros: { flag: "--max-cost", micros: true },
28
+ maxTotalCostMicros: { flag: "--max-total-cost", micros: true },
29
+ };
30
+ const usd = (micros) => `$${(micros / 1e6).toLocaleString("en-US", { maximumFractionDigits: 6 })}`;
31
+ /** One issue the API found in a request, in the command line's words:
32
+ * `body.timeoutSeconds must be at least 60` is `--timeout must be at least 60`. */
33
+ function issueWords(path, message) {
34
+ const field = /^(?:\$\.)?body\.([A-Za-z]+)/.exec(path)?.[1];
35
+ const option = field && Object.hasOwn(OPTIONS, field) ? OPTIONS[field] : undefined;
36
+ if (!option) {
37
+ const where = path.replace(/^\$\.?/, "").replace(/^(body|query|path)\./, "") || "the request";
38
+ return `${where} ${message}`;
39
+ }
40
+ const said = option.micros ? message.replace(/-?\d+(?:\.\d+)?/g, (n) => usd(Number(n))) : message;
41
+ return `${option.flag} ${said}`;
42
+ }
43
+ /** A refusal of what a command sent, reworded for the command line: every
44
+ * issue named by its option, since the CLI never prints details.issues, and
45
+ * a hint that names the options rather than the request's fields. Anything
46
+ * else is left as the API said it. */
47
+ export function cliRefusal(error) {
48
+ const issues = error.details?.issues;
49
+ if (error.code === "invalid_request" && Array.isArray(issues) && issues.length) {
50
+ const lines = issues
51
+ .filter((i) => typeof i.path === "string" && typeof i.message === "string")
52
+ .map((i) => issueWords(i.path, i.message));
53
+ if (lines.length)
54
+ return {
55
+ message: lines.length === 1 ? `${lines[0]}.` : lines.map((l) => `\n ${l}`).join(""),
56
+ hint: "Change what is named above and run the command again.",
57
+ };
58
+ }
59
+ const field = typeof error.details?.field === "string" ? error.details.field : "";
60
+ const option = Object.hasOwn(OPTIONS, field) ? OPTIONS[field] : undefined;
61
+ if (option && !option.micros && error.message.includes(field)) {
62
+ const named = new RegExp(`\\b${field}\\b`, "g");
63
+ return {
64
+ message: error.message.replace(named, option.flag),
65
+ ...(error.hint ? { hint: error.hint.replace(named, option.flag) } : {}),
66
+ };
67
+ }
68
+ return { message: error.message, ...(error.hint ? { hint: error.hint } : {}) };
69
+ }
70
+ /** A resource read as one fact a line, as `sandbox get` prints: a list
71
+ * joined, a nested record as its own facts, nothing as `-`. */
72
+ export function describeRecord(record, table) {
73
+ const rows = [];
74
+ const cell = (value) => {
75
+ if (value === null || value === undefined || value === "")
76
+ return "-";
77
+ if (Array.isArray(value))
78
+ return value.length
79
+ ? value.map((v) => (v && typeof v === "object" ? JSON.stringify(v) : String(v))).join(", ")
80
+ : "-";
81
+ // A string as it is; a number, a boolean or a record as JSON writes it.
82
+ return typeof value === "string" ? value : JSON.stringify(value);
83
+ };
84
+ const add = (prefix, value) => {
85
+ for (const [key, v] of Object.entries(value)) {
86
+ const name = prefix ? `${prefix}.${key}` : key;
87
+ if (v && typeof v === "object" && !Array.isArray(v) && Object.keys(v).length <= 8)
88
+ add(name, v);
89
+ else
90
+ rows.push([name, cell(v)]);
91
+ }
92
+ };
93
+ add("", record);
94
+ return table(rows);
95
+ }
96
+ /** The newest CPU reading the metrics hold, and how old it is. `latest` is
97
+ * the last sample, which can carry no CPU figure (the first after a wake has
98
+ * nothing to compare with), while the points before it do; "no reading"
99
+ * above a sparkline of readings contradicted itself. */
100
+ export function newestCpu(m, now = Date.now()) {
101
+ if (m.latest?.cpuPercent != null)
102
+ return { percent: m.latest.cpuPercent, cores: m.latest.cpuCores, ago: null };
103
+ for (let i = m.points.length - 1; i >= 0; i--) {
104
+ const p = m.points[i];
105
+ if (p.cpuPercent == null)
106
+ continue;
107
+ const seconds = Math.max(0, Math.round((now - Date.parse(p.at)) / 1000));
108
+ const ago = seconds < 90
109
+ ? `${seconds} s ago`
110
+ : seconds < 5400
111
+ ? `${Math.round(seconds / 60)} min ago`
112
+ : `${Math.round(seconds / 3600)} h ago`;
113
+ return { percent: p.cpuPercent, cores: p.cpuCores, ago };
114
+ }
115
+ return null;
116
+ }
117
+ /** The lines of the top-level help about one command, ` feedback ...` and
118
+ * the lines that continue it, or null when it has none. `runtime feedback
119
+ * help` filed "help" as feedback, and `runtime support help` sent it to
120
+ * support, until 30 September 2026. */
121
+ export function topicHelp(help, command) {
122
+ const lines = help.split("\n");
123
+ const out = [];
124
+ let inside = false;
125
+ for (const line of lines) {
126
+ const starts = line.startsWith(` ${command} `) || line === ` ${command}`;
127
+ if (starts)
128
+ inside = true;
129
+ else if (inside && !/^ {3,}\S/.test(line))
130
+ inside = false;
131
+ if (inside)
132
+ out.push(line);
133
+ }
134
+ return out.length ? out.join("\n") : null;
135
+ }