withruntime 0.8.3 → 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.
- package/COMPATIBILITY.md +145 -0
- package/E2B.md +23 -13
- package/README.md +8 -5
- package/README.src.md +8 -5
- package/compatibility-lock.json +281 -0
- package/dist/ai-harness/index.js +2 -2
- package/dist/api-defaults.d.ts +17 -0
- package/dist/api-defaults.js +22 -0
- package/dist/blaxel/preview.d.ts +1 -1
- package/dist/blaxel/preview.js +1 -1
- package/dist/blaxel/process.d.ts +1 -1
- package/dist/blaxel/process.js +11 -2
- package/dist/cli-words.d.ts +27 -0
- package/dist/cli-words.js +135 -0
- package/dist/cli.js +162 -31
- package/dist/client.d.ts +4 -1
- package/dist/client.js +8 -2
- package/dist/cloudflare/index.d.ts +294 -0
- package/dist/cloudflare/index.js +554 -0
- package/dist/cloudflare/worker.d.ts +415 -0
- package/dist/cloudflare/worker.js +297 -0
- package/dist/codesandbox/guest-service.d.ts +31 -0
- package/dist/codesandbox/guest-service.js +453 -0
- package/dist/codesandbox/index.d.ts +386 -0
- package/dist/codesandbox/index.js +1313 -0
- package/dist/compat/core.d.ts +39 -0
- package/dist/compat/core.js +199 -0
- package/dist/compat/files.d.ts +26 -0
- package/dist/compat/files.js +115 -0
- package/dist/compat/shell.d.ts +4 -0
- package/dist/compat/shell.js +165 -0
- package/dist/daytona/context.js +2 -1
- package/dist/daytona/process.d.ts +1 -1
- package/dist/daytona/process.js +27 -4
- package/dist/e2b/code-interpreter.d.ts +4 -5
- package/dist/e2b/code-interpreter.js +54 -56
- package/dist/e2b/commands.d.ts +5 -4
- package/dist/e2b/commands.js +37 -29
- package/dist/e2b/errors.js +1 -1
- package/dist/e2b/filesystem.d.ts +8 -6
- package/dist/e2b/filesystem.js +127 -28
- package/dist/e2b/sandbox.d.ts +4 -3
- package/dist/e2b/sandbox.js +10 -10
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +15 -2
- package/dist/freestyle/index.d.ts +301 -0
- package/dist/freestyle/index.js +310 -0
- package/dist/index.d.ts +1 -0
- package/dist/mcp.js +2 -2
- package/dist/modal/index.d.ts +205 -0
- package/dist/modal/index.js +485 -0
- package/dist/network-cli.js +1 -1
- package/dist/openai-agents/index.js +9 -26
- package/dist/products/audit.d.ts +3 -0
- package/dist/products/index.d.ts +2 -0
- package/dist/products/index.js +2 -0
- package/dist/products/interpreter.d.ts +11 -4
- package/dist/products/interpreter.js +33 -9
- package/dist/products/jobs.d.ts +1 -1
- package/dist/products/jobs.js +5 -4
- package/dist/products/limits.d.ts +10 -0
- package/dist/products/previews.d.ts +10 -2
- package/dist/products/previews.js +3 -2
- package/dist/products/tailscale.d.ts +57 -0
- package/dist/products/tailscale.js +17 -0
- package/dist/products/watch.d.ts +25 -4
- package/dist/products/watch.js +75 -14
- package/dist/runloop/index.d.ts +340 -0
- package/dist/runloop/index.js +438 -0
- package/dist/runloop/pagination.d.ts +46 -0
- package/dist/runloop/pagination.js +82 -0
- package/dist/runloop/snapshots.d.ts +52 -0
- package/dist/runloop/snapshots.js +244 -0
- package/dist/sandbox.d.ts +40 -9
- package/dist/sandbox.js +273 -76
- package/dist/snapshots.d.ts +11 -1
- package/dist/snapshots.js +11 -1
- package/dist/sprites/index.d.ts +251 -0
- package/dist/sprites/index.js +552 -0
- package/dist/tar.d.ts +8 -1
- package/dist/tar.js +185 -35
- package/dist/tools/index.js +2 -1
- package/dist/transport.d.ts +20 -2
- package/dist/transport.js +48 -11
- package/dist/types.d.ts +52 -3
- package/dist/vercel/command.js +12 -1
- package/dist/vercel/errors.d.ts +2 -2
- package/dist/vercel/errors.js +12 -1
- package/dist/vercel/filesystem.d.ts +21 -18
- package/dist/vercel/filesystem.js +95 -48
- package/dist/vercel/sandbox.js +5 -5
- 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;
|
package/dist/blaxel/preview.d.ts
CHANGED
|
@@ -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
|
|
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
|
package/dist/blaxel/preview.js
CHANGED
|
@@ -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
|
|
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)
|
package/dist/blaxel/process.d.ts
CHANGED
|
@@ -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,
|
|
90
|
+
get(identifier: string, options?: {
|
|
91
91
|
signal?: AbortSignal;
|
|
92
92
|
retry?: boolean;
|
|
93
93
|
}): Promise<GetProcessByIdentifierResponse>;
|
package/dist/blaxel/process.js
CHANGED
|
@@ -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,
|
|
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
|
+
}
|