withruntime 0.8.4 → 0.10.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/BLAXEL.md +4 -4
- package/COMPATIBILITY.md +145 -0
- package/DAYTONA.md +13 -7
- package/E2B.md +34 -20
- package/README.md +22 -11
- package/README.src.md +22 -11
- package/VERCEL.md +13 -3
- package/compatibility-lock.json +357 -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/errors.js +1 -1
- package/dist/blaxel/lookup.d.ts +3 -2
- package/dist/blaxel/lookup.js +3 -2
- package/dist/blaxel/pagination.d.ts +2 -2
- package/dist/blaxel/pagination.js +45 -17
- package/dist/blaxel/preview.d.ts +3 -2
- package/dist/blaxel/preview.js +16 -14
- package/dist/blaxel/process.d.ts +1 -1
- package/dist/blaxel/process.js +66 -11
- package/dist/blaxel/sandbox.d.ts +2 -0
- package/dist/blaxel/sandbox.js +2 -0
- package/dist/blaxel/snapshot.js +3 -5
- package/dist/cli-words.d.ts +27 -0
- package/dist/cli-words.js +135 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +351 -85
- package/dist/client.d.ts +33 -4
- package/dist/client.js +47 -12
- package/dist/cloudflare/identity.d.ts +7 -0
- package/dist/cloudflare/identity.js +13 -0
- package/dist/cloudflare/index.d.ts +303 -0
- package/dist/cloudflare/index.js +592 -0
- package/dist/cloudflare/worker.d.ts +419 -0
- package/dist/cloudflare/worker.js +447 -0
- package/dist/codesandbox/guest-service.d.ts +31 -0
- package/dist/codesandbox/guest-service.js +490 -0
- package/dist/codesandbox/index.d.ts +386 -0
- package/dist/codesandbox/index.js +1347 -0
- package/dist/compat/core.d.ts +40 -0
- package/dist/compat/core.js +238 -0
- package/dist/compat/files.d.ts +26 -0
- package/dist/compat/files.js +133 -0
- package/dist/compat/shell.d.ts +4 -0
- package/dist/compat/shell.js +165 -0
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +107 -38
- package/dist/daytona/context.js +2 -1
- package/dist/daytona/daytona.js +11 -4
- package/dist/daytona/filesystem.d.ts +17 -4
- package/dist/daytona/filesystem.js +121 -38
- package/dist/daytona/index.d.ts +1 -1
- package/dist/daytona/process.d.ts +1 -1
- package/dist/daytona/process.js +27 -4
- package/dist/daytona/sandbox.d.ts +1 -1
- package/dist/daytona/sandbox.js +16 -7
- package/dist/e2b/client.js +1 -1
- package/dist/e2b/code-interpreter.d.ts +4 -5
- package/dist/e2b/code-interpreter.js +54 -56
- package/dist/e2b/commands.d.ts +35 -12
- package/dist/e2b/commands.js +169 -73
- 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/index.d.ts +1 -0
- package/dist/e2b/index.js +1 -0
- package/dist/e2b/pty.d.ts +24 -0
- package/dist/e2b/pty.js +80 -0
- package/dist/e2b/sandbox.d.ts +6 -4
- package/dist/e2b/sandbox.js +59 -25
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +15 -2
- package/dist/file-source.d.ts +16 -0
- package/dist/file-source.js +162 -0
- package/dist/freestyle/index.d.ts +309 -0
- package/dist/freestyle/index.js +343 -0
- package/dist/index.d.ts +3 -1
- package/dist/login.js +16 -10
- package/dist/mcp.js +2 -2
- package/dist/modal/index.d.ts +205 -0
- package/dist/modal/index.js +486 -0
- package/dist/network-cli.js +112 -44
- package/dist/openai-agents/index.js +18 -71
- package/dist/page.d.ts +1 -1
- package/dist/page.js +2 -2
- package/dist/products/audit.d.ts +3 -0
- package/dist/products/index.d.ts +14 -0
- package/dist/products/index.js +12 -0
- package/dist/products/interpreter.d.ts +11 -4
- package/dist/products/interpreter.js +33 -9
- package/dist/products/jobs.js +3 -2
- package/dist/products/limits.d.ts +10 -0
- package/dist/products/observability.d.ts +44 -0
- package/dist/products/observability.js +6 -0
- package/dist/products/previews.d.ts +18 -4
- package/dist/products/previews.js +14 -5
- package/dist/products/tailscale.d.ts +57 -0
- package/dist/products/tailscale.js +17 -0
- package/dist/products/volumes.d.ts +42 -0
- package/dist/products/volumes.js +36 -0
- package/dist/products/watch.d.ts +25 -4
- package/dist/products/watch.js +132 -18
- package/dist/proxy.js +3 -1
- package/dist/runloop/index.d.ts +326 -0
- package/dist/runloop/index.js +535 -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 +76 -16
- package/dist/sandbox.js +696 -135
- package/dist/snapshots.d.ts +20 -5
- package/dist/snapshots.js +11 -1
- package/dist/sprites/index.d.ts +251 -0
- package/dist/sprites/index.js +588 -0
- package/dist/tar.d.ts +10 -1
- package/dist/tar.js +311 -35
- package/dist/tools/index.js +2 -1
- package/dist/transport.d.ts +23 -8
- package/dist/transport.js +247 -127
- package/dist/types.d.ts +52 -3
- package/dist/vercel/command.d.ts +1 -1
- package/dist/vercel/command.js +15 -3
- package/dist/vercel/errors.d.ts +2 -2
- package/dist/vercel/errors.js +19 -2
- package/dist/vercel/filesystem.d.ts +21 -18
- package/dist/vercel/filesystem.js +95 -48
- package/dist/vercel/sandbox.d.ts +8 -8
- package/dist/vercel/sandbox.js +159 -64
- package/dist/vercel/snapshot.d.ts +3 -2
- package/dist/vercel/snapshot.js +9 -5
- package/package.json +46 -3
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Runtime } from "../client.js";
|
|
2
|
+
import type { Snapshot, SnapshotOptions } from "../snapshots.js";
|
|
3
|
+
import { type RequestOptions, type LongPollRequestOptions } from "./index.js";
|
|
4
|
+
import { DevboxSnapshotViewsDiskSnapshotsCursorIDPage, PagePromise } from "./pagination.js";
|
|
5
|
+
export interface DevboxSnapshotDiskParams {
|
|
6
|
+
name?: string | null;
|
|
7
|
+
metadata?: Record<string, string> | null;
|
|
8
|
+
commit_message?: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface DevboxSnapshotView {
|
|
11
|
+
id: string;
|
|
12
|
+
create_time_ms: number;
|
|
13
|
+
metadata: Record<string, string>;
|
|
14
|
+
source_devbox_id: string;
|
|
15
|
+
commit_message?: string | null;
|
|
16
|
+
name?: string | null;
|
|
17
|
+
size_bytes?: number | null;
|
|
18
|
+
source_blueprint_id?: string | null;
|
|
19
|
+
}
|
|
20
|
+
export interface DevboxSnapshotAsyncStatusView {
|
|
21
|
+
status: "in_progress" | "error" | "complete" | "deleted";
|
|
22
|
+
error_message?: string | null;
|
|
23
|
+
snapshot?: DevboxSnapshotView | null;
|
|
24
|
+
}
|
|
25
|
+
export interface DiskSnapshotListParams {
|
|
26
|
+
starting_after?: string;
|
|
27
|
+
limit?: number;
|
|
28
|
+
devbox_id?: string;
|
|
29
|
+
include_total_count?: boolean;
|
|
30
|
+
source_blueprint_id?: string;
|
|
31
|
+
[key: `metadata[${string}]`]: string | undefined;
|
|
32
|
+
}
|
|
33
|
+
export declare function requestOptions(value: object): value is RequestOptions;
|
|
34
|
+
export declare function nativeOptions(options: RequestOptions): {
|
|
35
|
+
signal: AbortSignal | undefined;
|
|
36
|
+
timeoutMs: number | undefined;
|
|
37
|
+
idempotencyKey: string | undefined;
|
|
38
|
+
};
|
|
39
|
+
export declare function snapshotOptions(body: DevboxSnapshotDiskParams): SnapshotOptions;
|
|
40
|
+
export declare function snapshotView(snapshot: Snapshot): DevboxSnapshotView;
|
|
41
|
+
export declare class DiskSnapshots {
|
|
42
|
+
private readonly runtime;
|
|
43
|
+
constructor(runtime: Runtime);
|
|
44
|
+
update(id: string, body?: DevboxSnapshotDiskParams, options?: RequestOptions): Promise<DevboxSnapshotView>;
|
|
45
|
+
update(id: string, options?: RequestOptions): Promise<DevboxSnapshotView>;
|
|
46
|
+
awaitCompleted(id: string, options?: LongPollRequestOptions): Promise<DevboxSnapshotAsyncStatusView>;
|
|
47
|
+
queryStatus(id: string, options?: RequestOptions): Promise<DevboxSnapshotAsyncStatusView>;
|
|
48
|
+
delete(id: string, options?: RequestOptions): Promise<unknown>;
|
|
49
|
+
list(query?: DiskSnapshotListParams, options?: RequestOptions): PagePromise<DevboxSnapshotView, DevboxSnapshotViewsDiskSnapshotsCursorIDPage<DevboxSnapshotView>>;
|
|
50
|
+
list(options?: RequestOptions): PagePromise<DevboxSnapshotView, DevboxSnapshotViewsDiskSnapshotsCursorIDPage<DevboxSnapshotView>>;
|
|
51
|
+
private page;
|
|
52
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { RuntimeError } from "../errors.js";
|
|
2
|
+
import { CompatibilityError, only } from "../compat/core.js";
|
|
3
|
+
import { LongPollAbortError, PollingTimeoutError, MaxAttemptsExceededError, } from "./index.js";
|
|
4
|
+
import { DevboxSnapshotViewsDiskSnapshotsCursorIDPage, PagePromise } from "./pagination.js";
|
|
5
|
+
const PAYLOAD = "compat.runloop.snapshot.";
|
|
6
|
+
export function requestOptions(value) {
|
|
7
|
+
const keys = Object.keys(value);
|
|
8
|
+
return (keys.length > 0 && keys.every((key) => ["signal", "timeout", "idempotencyKey"].includes(key)));
|
|
9
|
+
}
|
|
10
|
+
export function nativeOptions(options) {
|
|
11
|
+
return {
|
|
12
|
+
signal: options.signal,
|
|
13
|
+
timeoutMs: options.timeout,
|
|
14
|
+
idempotencyKey: options.idempotencyKey,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function snapshotOptions(body) {
|
|
18
|
+
only("Runloop snapshot", body, ["name", "metadata", "commit_message"]);
|
|
19
|
+
if (body.commit_message != null &&
|
|
20
|
+
(typeof body.commit_message !== "string" || body.commit_message.length > 1000))
|
|
21
|
+
throw new TypeError("commit_message must be a string of at most 1000 characters");
|
|
22
|
+
if (body.name != null && typeof body.name !== "string")
|
|
23
|
+
throw new TypeError("name must be a string");
|
|
24
|
+
if (body.metadata != null &&
|
|
25
|
+
(typeof body.metadata !== "object" ||
|
|
26
|
+
Array.isArray(body.metadata) ||
|
|
27
|
+
Object.values(body.metadata).some((value) => typeof value !== "string")))
|
|
28
|
+
throw new TypeError("metadata must contain string values");
|
|
29
|
+
// Keep the entire public payload durable, including arbitrary names and the
|
|
30
|
+
// official 1000-character commit message. Native labels have 256-char values.
|
|
31
|
+
const payload = JSON.stringify({
|
|
32
|
+
name: body.name ?? null,
|
|
33
|
+
metadata: body.metadata ?? {},
|
|
34
|
+
commit_message: body.commit_message ?? null,
|
|
35
|
+
});
|
|
36
|
+
const chunks = [];
|
|
37
|
+
let chunk = "";
|
|
38
|
+
for (const character of payload) {
|
|
39
|
+
if (chunk.length + character.length > 256) {
|
|
40
|
+
chunks.push(chunk);
|
|
41
|
+
chunk = "";
|
|
42
|
+
}
|
|
43
|
+
chunk += character;
|
|
44
|
+
}
|
|
45
|
+
if (chunk)
|
|
46
|
+
chunks.push(chunk);
|
|
47
|
+
if (chunks.length > 31)
|
|
48
|
+
throw new CompatibilityError("Runloop", "snapshot metadata exceeding Runtime's 31 label chunks");
|
|
49
|
+
const labels = {
|
|
50
|
+
"compat.provider": "runloop",
|
|
51
|
+
...Object.fromEntries(chunks.map((chunk, index) => [`${PAYLOAD}${index.toString().padStart(2, "0")}`, chunk])),
|
|
52
|
+
};
|
|
53
|
+
// Match the spine's JSONB text bound, including its spaces between entries.
|
|
54
|
+
// Count UTF-8 bytes and never split surrogate pairs into invalid JSON strings.
|
|
55
|
+
const stored = `{${Object.entries(labels)
|
|
56
|
+
.map(([key, value]) => `${JSON.stringify(key)}: ${JSON.stringify(value)}`)
|
|
57
|
+
.join(", ")}}`;
|
|
58
|
+
if (new TextEncoder().encode(stored).length > 4096)
|
|
59
|
+
throw new CompatibilityError("Runloop", "snapshot metadata exceeding Runtime's 4096-byte label bound");
|
|
60
|
+
return {
|
|
61
|
+
mode: "disk",
|
|
62
|
+
labels,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function labelsOf(snapshot) {
|
|
66
|
+
const value = snapshot.labels;
|
|
67
|
+
return value && typeof value === "object"
|
|
68
|
+
? Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string"))
|
|
69
|
+
: {};
|
|
70
|
+
}
|
|
71
|
+
export function snapshotView(snapshot) {
|
|
72
|
+
if (snapshot.mode !== "disk")
|
|
73
|
+
throw new CompatibilityError("Runloop", "using a memory snapshot as a disk snapshot");
|
|
74
|
+
const labels = labelsOf(snapshot);
|
|
75
|
+
const packed = Object.keys(labels)
|
|
76
|
+
.filter((key) => key.startsWith(PAYLOAD))
|
|
77
|
+
.sort()
|
|
78
|
+
.map((key) => labels[key])
|
|
79
|
+
.join("");
|
|
80
|
+
const body = packed
|
|
81
|
+
? JSON.parse(packed)
|
|
82
|
+
: {
|
|
83
|
+
name: snapshot.name,
|
|
84
|
+
metadata: Object.fromEntries(Object.entries(labels).filter(([key]) => !key.startsWith("compat."))),
|
|
85
|
+
};
|
|
86
|
+
return {
|
|
87
|
+
id: snapshot.id,
|
|
88
|
+
create_time_ms: Date.parse(snapshot.createdAt),
|
|
89
|
+
metadata: body.metadata ?? {},
|
|
90
|
+
source_devbox_id: snapshot.sourceSandboxId,
|
|
91
|
+
commit_message: body.commit_message ?? null,
|
|
92
|
+
name: body.name ?? null,
|
|
93
|
+
size_bytes: snapshot.meteredBytes,
|
|
94
|
+
source_blueprint_id: typeof snapshot.sourceImageId === "string" ? snapshot.sourceImageId : null,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
export class DiskSnapshots {
|
|
98
|
+
runtime;
|
|
99
|
+
constructor(runtime) {
|
|
100
|
+
this.runtime = runtime;
|
|
101
|
+
}
|
|
102
|
+
async update(id, body = {}, options = {}) {
|
|
103
|
+
if (requestOptions(body))
|
|
104
|
+
return this.update(id, {}, body);
|
|
105
|
+
snapshotOptions(body); // Reject invalid input before any request.
|
|
106
|
+
for (let attempt = 0;; attempt++) {
|
|
107
|
+
const current = await this.runtime.snapshots.get(id, nativeOptions(options));
|
|
108
|
+
const previous = snapshotView(current);
|
|
109
|
+
const merged = {
|
|
110
|
+
name: body.name === undefined ? previous.name : body.name,
|
|
111
|
+
metadata: body.metadata === undefined ? previous.metadata : body.metadata,
|
|
112
|
+
commit_message: body.commit_message === undefined ? previous.commit_message : body.commit_message,
|
|
113
|
+
};
|
|
114
|
+
const labels = snapshotOptions(merged).labels;
|
|
115
|
+
try {
|
|
116
|
+
return snapshotView(await this.runtime.snapshots.update(id, { labels, ifLabels: labelsOf(current) }, nativeOptions(options)));
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
if (!(error instanceof RuntimeError) ||
|
|
120
|
+
error.code !== "snapshot_metadata_changed" ||
|
|
121
|
+
attempt >= 2)
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async awaitCompleted(id, options = {}) {
|
|
127
|
+
const timeoutMs = options.longPoll?.timeoutMs ?? options.polling?.timeoutMs;
|
|
128
|
+
const { maxAttempts, initialDelayMs = 0, pollingIntervalMs = 1000 } = options.polling ?? {};
|
|
129
|
+
if (options.signal?.aborted)
|
|
130
|
+
throw new LongPollAbortError("Polling aborted", undefined);
|
|
131
|
+
for (const [name, value] of Object.entries({ initialDelayMs, pollingIntervalMs, maxAttempts }))
|
|
132
|
+
if (value !== undefined && (!Number.isFinite(value) || value < 0))
|
|
133
|
+
throw new Error(`${name} must be non-negative`);
|
|
134
|
+
if (timeoutMs !== undefined && (!Number.isFinite(timeoutMs) || timeoutMs <= 0))
|
|
135
|
+
throw new Error("timeoutMs must be positive");
|
|
136
|
+
const controller = new AbortController();
|
|
137
|
+
const timer = timeoutMs === undefined ? undefined : setTimeout(() => controller.abort(), timeoutMs);
|
|
138
|
+
const signal = options.signal
|
|
139
|
+
? AbortSignal.any([controller.signal, options.signal])
|
|
140
|
+
: controller.signal;
|
|
141
|
+
let lastResult;
|
|
142
|
+
const delay = (ms) => new Promise((resolve, reject) => {
|
|
143
|
+
signal.throwIfAborted();
|
|
144
|
+
const onAbort = () => {
|
|
145
|
+
clearTimeout(wait);
|
|
146
|
+
reject(signal.reason instanceof Error ? signal.reason : new Error(String(signal.reason)));
|
|
147
|
+
};
|
|
148
|
+
const wait = setTimeout(() => {
|
|
149
|
+
signal.removeEventListener("abort", onAbort);
|
|
150
|
+
resolve();
|
|
151
|
+
}, ms);
|
|
152
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
153
|
+
});
|
|
154
|
+
try {
|
|
155
|
+
let attempts = 0;
|
|
156
|
+
while (true) {
|
|
157
|
+
lastResult = await this.queryStatus(id, { ...options, signal });
|
|
158
|
+
if (lastResult.status === "error")
|
|
159
|
+
throw new Error(`Snapshot ${id} failed: ${lastResult.error_message || "Unknown error"}`);
|
|
160
|
+
if (lastResult.status === "complete" || (maxAttempts === 0 && attempts === 0))
|
|
161
|
+
return lastResult;
|
|
162
|
+
if (maxAttempts !== undefined && attempts === maxAttempts)
|
|
163
|
+
throw new MaxAttemptsExceededError(`Polling exceeded maximum attempts (${maxAttempts})`, lastResult);
|
|
164
|
+
await delay(attempts++ === 0 ? initialDelayMs : pollingIntervalMs);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (options.signal?.aborted)
|
|
169
|
+
throw new LongPollAbortError("Polling aborted", lastResult);
|
|
170
|
+
if (controller.signal.aborted)
|
|
171
|
+
throw new PollingTimeoutError(`Polling timed out after ${timeoutMs}ms`, lastResult);
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
clearTimeout(timer);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async queryStatus(id, options = {}) {
|
|
179
|
+
const snapshot = await this.runtime.snapshots.get(id, nativeOptions(options));
|
|
180
|
+
const view = snapshotView(snapshot);
|
|
181
|
+
return {
|
|
182
|
+
status: snapshot.state === "ready"
|
|
183
|
+
? "complete"
|
|
184
|
+
: snapshot.state === "failed"
|
|
185
|
+
? "error"
|
|
186
|
+
: snapshot.state === "deleted" || snapshot.state === "deleting"
|
|
187
|
+
? "deleted"
|
|
188
|
+
: "in_progress",
|
|
189
|
+
error_message: snapshot.error,
|
|
190
|
+
snapshot: view,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
async delete(id, options = {}) {
|
|
194
|
+
snapshotView(await this.runtime.snapshots.get(id, nativeOptions(options)));
|
|
195
|
+
await this.runtime.snapshots.delete(id, nativeOptions(options));
|
|
196
|
+
return {};
|
|
197
|
+
}
|
|
198
|
+
list(query = {}, options = {}) {
|
|
199
|
+
if (requestOptions(query))
|
|
200
|
+
return this.list({}, query);
|
|
201
|
+
return new PagePromise(this.page(query, options));
|
|
202
|
+
}
|
|
203
|
+
async page(query, options) {
|
|
204
|
+
options.signal?.throwIfAborted();
|
|
205
|
+
const filters = Object.entries(query).filter(([key]) => /^metadata\[[^\]]+\](\[in\])?$/.test(key));
|
|
206
|
+
only("Runloop snapshot list", query, [
|
|
207
|
+
"starting_after",
|
|
208
|
+
"limit",
|
|
209
|
+
"devbox_id",
|
|
210
|
+
"include_total_count",
|
|
211
|
+
"source_blueprint_id",
|
|
212
|
+
...filters.map(([key]) => key),
|
|
213
|
+
]);
|
|
214
|
+
if (query.limit !== undefined && (!Number.isInteger(query.limit) || query.limit <= 0))
|
|
215
|
+
throw new TypeError("limit must be positive");
|
|
216
|
+
const values = [];
|
|
217
|
+
const page = await this.runtime.snapshots.list({ sandboxId: query.devbox_id }, nativeOptions(options));
|
|
218
|
+
for await (const snapshot of page) {
|
|
219
|
+
options.signal?.throwIfAborted();
|
|
220
|
+
if (snapshot.mode !== "disk" || labelsOf(snapshot)["compat.provider"] !== "runloop")
|
|
221
|
+
continue;
|
|
222
|
+
const value = snapshotView(snapshot);
|
|
223
|
+
if (query.source_blueprint_id && value.source_blueprint_id !== query.source_blueprint_id)
|
|
224
|
+
continue;
|
|
225
|
+
if (!filters.every(([key, expected]) => {
|
|
226
|
+
const name = key.slice(9, key.indexOf("]"));
|
|
227
|
+
return key.endsWith("[in]")
|
|
228
|
+
? typeof expected === "string" &&
|
|
229
|
+
expected.split(",").includes(value.metadata[name] ?? "")
|
|
230
|
+
: value.metadata[name] === expected;
|
|
231
|
+
}))
|
|
232
|
+
continue;
|
|
233
|
+
values.push(value);
|
|
234
|
+
}
|
|
235
|
+
const total = values.length;
|
|
236
|
+
const offset = query.starting_after
|
|
237
|
+
? values.findIndex((value) => value.id === query.starting_after) + 1
|
|
238
|
+
: 0;
|
|
239
|
+
if (query.starting_after && offset === 0)
|
|
240
|
+
throw new TypeError("starting_after does not identify a matching snapshot");
|
|
241
|
+
const data = values.slice(offset, offset + (query.limit ?? 20));
|
|
242
|
+
return new DevboxSnapshotViewsDiskSnapshotsCursorIDPage(data, offset + data.length < total, query.include_total_count === false ? 0 : total, (after) => this.page({ ...query, starting_after: after }, options));
|
|
243
|
+
}
|
|
244
|
+
}
|
package/dist/sandbox.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { Page } from "./page.js";
|
|
2
2
|
import { type FileEvent, type WatchHandle, type WatchOptions } from "./products/watch.js";
|
|
3
3
|
import { Transport, type RequestOptions } from "./transport.js";
|
|
4
|
-
import type { CommandResult, ExecOptions, FileEntry, OutputEvent, KeepAliveOptions, ProcessInfo, SandboxInfo, SandboxSettings } from "./types.js";
|
|
4
|
+
import type { CommandResult, DeletedSandbox, ExecOptions, FileEntry, OutputEvent, BinaryOutputEvent, KeepAliveOptions, ProcessInfo, SandboxInfo, SandboxSettings } from "./types.js";
|
|
5
5
|
import { type SandboxExtensions } from "./products/index.js";
|
|
6
6
|
import type { Snapshot, SnapshotOptions } from "./snapshots.js";
|
|
7
7
|
import { Tunnel, type PortForward } from "./tunnel.js";
|
|
8
|
+
import type { StreamUploadSource } from "./file-source.js";
|
|
9
|
+
/** DELETE /v1/sandboxes/{id}, for `sandbox.delete()` and
|
|
10
|
+
* `runtime.sandboxes.delete(id)`. */
|
|
11
|
+
export declare function deleteSandbox(t: Transport, id: string, options?: RequestOptions): Promise<DeletedSandbox>;
|
|
8
12
|
/** A running (or stopped) sandbox. Every method is one API call or a short
|
|
9
13
|
* sequence of them; `await using sbx = await Sandbox.create()` stops it for
|
|
10
14
|
* you at the end of the block. */
|
|
@@ -63,6 +67,9 @@ export declare class Sandbox implements AsyncDisposable {
|
|
|
63
67
|
cols?: number;
|
|
64
68
|
rows?: number;
|
|
65
69
|
};
|
|
70
|
+
outputEncoding?: "utf8" | "base64";
|
|
71
|
+
/** HTTP request options, independently of the process execution deadline. */
|
|
72
|
+
request?: RequestOptions;
|
|
66
73
|
}): Promise<Process>;
|
|
67
74
|
/** An interactive terminal over a WebSocket. Bytes you write are typed;
|
|
68
75
|
* onData receives what the terminal prints. */
|
|
@@ -93,6 +100,11 @@ export declare class Sandbox implements AsyncDisposable {
|
|
|
93
100
|
pause(options?: RequestOptions & {
|
|
94
101
|
wait?: boolean;
|
|
95
102
|
}): Promise<this>;
|
|
103
|
+
/** Deletes it for good: stops it if it runs or is paused, deletes its disk
|
|
104
|
+
* and paused memory, revokes its previews and ports, and removes it from
|
|
105
|
+
* lists. Its snapshots, usage and audit entries stay. Deleting it again
|
|
106
|
+
* answers the same. */
|
|
107
|
+
delete(options?: RequestOptions): Promise<DeletedSandbox>;
|
|
96
108
|
/** Carries on a paused sandbox; `timeoutSeconds` is its new lease. */
|
|
97
109
|
wake(options?: RequestOptions & {
|
|
98
110
|
wait?: boolean;
|
|
@@ -104,6 +116,17 @@ export declare class Sandbox implements AsyncDisposable {
|
|
|
104
116
|
* fields left out stay as they are. `persistent: true` keeps it running
|
|
105
117
|
* while credit lasts (paid only). */
|
|
106
118
|
update(settings: SandboxSettings, options?: RequestOptions): Promise<this>;
|
|
119
|
+
/** Moves it to another image (id, name, name:tag or name@version), keeping
|
|
120
|
+
* its id, /workspace (its home: dotfiles, pip --user and npm -g installs),
|
|
121
|
+
* volumes, environment, name and previews. Its processes restart, and
|
|
122
|
+
* everything else on its old disk (sudo installs, apt packages, /etc) is
|
|
123
|
+
* lost, which `keep: "workspace"` says you know; snapshot it first to keep
|
|
124
|
+
* everything. A running sandbox is paused first. A switch that fails is
|
|
125
|
+
* undone (`switch_undone`), the sandbox on its old image with nothing lost.
|
|
126
|
+
* Charged as a wake. */
|
|
127
|
+
switchImage(image: string, options: RequestOptions & {
|
|
128
|
+
keep: "workspace";
|
|
129
|
+
}): Promise<this>;
|
|
107
130
|
/** Keeps a running sandbox's lease ahead of now, in the background, until
|
|
108
131
|
* stop() or the returned function ends it: every `everySeconds` (60) it
|
|
109
132
|
* extends the lease so that `marginSeconds` (600) remain, never more than
|
|
@@ -190,8 +213,8 @@ export declare class Processes {
|
|
|
190
213
|
private readonly t;
|
|
191
214
|
private readonly sandboxId;
|
|
192
215
|
constructor(t: Transport, sandboxId: string);
|
|
193
|
-
list(): Promise<ProcessInfo[]>;
|
|
194
|
-
get(processId: string): Promise<Process>;
|
|
216
|
+
list(options?: RequestOptions): Promise<ProcessInfo[]>;
|
|
217
|
+
get(processId: string, options?: RequestOptions): Promise<Process>;
|
|
195
218
|
/** Output events from `cursor` until the process exits, across stream slices. */
|
|
196
219
|
follow(processId: string, options?: {
|
|
197
220
|
cursor?: number;
|
|
@@ -211,16 +234,23 @@ export declare class Process {
|
|
|
211
234
|
cursor?: number;
|
|
212
235
|
signal?: AbortSignal;
|
|
213
236
|
}): AsyncGenerator<OutputEvent>;
|
|
237
|
+
/** Lossless output for a process spawned with outputEncoding: "base64".
|
|
238
|
+
* Refuses text-only output rather than inventing bytes that were discarded. */
|
|
239
|
+
outputBytes(options?: {
|
|
240
|
+
cursor?: number;
|
|
241
|
+
signal?: AbortSignal;
|
|
242
|
+
}): AsyncGenerator<BinaryOutputEvent>;
|
|
214
243
|
/** Waits for the process to end and returns its result. */
|
|
215
244
|
wait(options?: {
|
|
216
245
|
signal?: AbortSignal;
|
|
217
246
|
}): Promise<CommandResult>;
|
|
218
|
-
/** Sends input. Offsets
|
|
247
|
+
/** Sends input. Offsets protect transport retries; signal and timeoutMs cover
|
|
248
|
+
* the whole logical write, including its queue and backpressure. */
|
|
219
249
|
write(data: string | Uint8Array, options?: {
|
|
220
250
|
eof?: boolean;
|
|
221
|
-
}): Promise<void>;
|
|
222
|
-
kill(signal?: "SIGTERM" | "SIGKILL" | "SIGINT" | "SIGHUP" | "SIGQUIT" | "SIGUSR1" | "SIGUSR2"): Promise<void>;
|
|
223
|
-
resize(cols: number, rows: number): Promise<void>;
|
|
251
|
+
} & Pick<RequestOptions, "signal" | "timeoutMs">): Promise<void>;
|
|
252
|
+
kill(signal?: "SIGTERM" | "SIGKILL" | "SIGINT" | "SIGHUP" | "SIGQUIT" | "SIGUSR1" | "SIGUSR2", options?: RequestOptions): Promise<void>;
|
|
253
|
+
resize(cols: number, rows: number, options?: RequestOptions): Promise<void>;
|
|
224
254
|
refresh(): Promise<ProcessInfo>;
|
|
225
255
|
}
|
|
226
256
|
export declare class Terminal {
|
|
@@ -262,6 +292,9 @@ export declare class Files {
|
|
|
262
292
|
lostBytes: number;
|
|
263
293
|
ended: boolean;
|
|
264
294
|
}>;
|
|
295
|
+
webhook: (path: string, input?: import("./products/watch.js").WebhookWatchOptions) => Promise<import("./products/watch.js").WatchInfo & {
|
|
296
|
+
cursor: number;
|
|
297
|
+
}>;
|
|
265
298
|
stop: (id: string, options?: RequestOptions) => Promise<{
|
|
266
299
|
stopped: boolean;
|
|
267
300
|
}>;
|
|
@@ -290,38 +323,65 @@ export declare class Files {
|
|
|
290
323
|
path: string;
|
|
291
324
|
size: number;
|
|
292
325
|
}>;
|
|
326
|
+
/** Uploads byte streams with bounded memory on Node/Bun. Unknown-length
|
|
327
|
+
* inputs stage once in a private local temporary file; known local files
|
|
328
|
+
* and Blobs avoid that extra disk copy. Paths are local file paths. */
|
|
329
|
+
writeStream(path: string, input: StreamUploadSource | Uint8Array, writeOptions?: RequestOptions & {
|
|
330
|
+
mode?: number;
|
|
331
|
+
onProgress?: (progress: {
|
|
332
|
+
bytesSent: number;
|
|
333
|
+
}) => void;
|
|
334
|
+
}): Promise<{
|
|
335
|
+
path: string;
|
|
336
|
+
size: number;
|
|
337
|
+
}>;
|
|
293
338
|
/** Directory entries; `depth` goes deeper, `glob` filters (e.g. "**\/*.py"). */
|
|
294
339
|
list(path?: string, options?: {
|
|
295
340
|
depth?: number;
|
|
296
341
|
glob?: string;
|
|
297
342
|
hidden?: boolean;
|
|
298
343
|
limit?: number;
|
|
299
|
-
}): Promise<FileEntry[]>;
|
|
344
|
+
} & RequestOptions): Promise<FileEntry[]>;
|
|
300
345
|
glob(pattern: string, root?: string): Promise<FileEntry[]>;
|
|
301
|
-
stat(path: string): Promise<(FileEntry & {
|
|
346
|
+
stat(path: string, options?: RequestOptions): Promise<(FileEntry & {
|
|
302
347
|
exists: true;
|
|
303
348
|
}) | {
|
|
304
349
|
exists: false;
|
|
305
350
|
path: string;
|
|
306
351
|
}>;
|
|
307
|
-
exists(path: string): Promise<boolean>;
|
|
352
|
+
exists(path: string, options?: RequestOptions): Promise<boolean>;
|
|
308
353
|
mkdir(path: string, options?: {
|
|
309
354
|
parents?: boolean;
|
|
310
|
-
}): Promise<void>;
|
|
355
|
+
} & RequestOptions): Promise<void>;
|
|
311
356
|
remove(path: string, options?: {
|
|
312
357
|
recursive?: boolean;
|
|
313
|
-
}): Promise<boolean>;
|
|
358
|
+
} & RequestOptions): Promise<boolean>;
|
|
314
359
|
rename(from: string, to: string, options?: {
|
|
315
360
|
overwrite?: boolean;
|
|
361
|
+
} & RequestOptions): Promise<void>;
|
|
362
|
+
/** Packs a directory as archive bytes; `gzip: false` returns plain tar.
|
|
363
|
+
* Exclusions are relative paths, not globs. `user: root` selects guest root. */
|
|
364
|
+
archive(path: string, options?: RequestOptions & {
|
|
365
|
+
gzip?: boolean;
|
|
366
|
+
exclude?: string[];
|
|
367
|
+
user?: "sandbox" | "root";
|
|
368
|
+
}): Promise<Uint8Array>;
|
|
369
|
+
/** Unpacks archive bytes in a directory with the sandbox user's rights by
|
|
370
|
+
* default; `user: root` explicitly selects root inside this guest. */
|
|
371
|
+
unarchive(path: string, bytes: Uint8Array, options?: RequestOptions & {
|
|
372
|
+
gzip?: boolean;
|
|
373
|
+
user?: "sandbox" | "root";
|
|
316
374
|
}): Promise<void>;
|
|
317
375
|
/** Copies a local file or directory into the sandbox. A directory travels as
|
|
318
|
-
* one gzipped tar and
|
|
376
|
+
* one gzipped tar to the API's folder routes, and the sandbox's own `tar`
|
|
377
|
+
* unpacks it as it arrives, making the folder. */
|
|
319
378
|
upload(localPath: string, remotePath: string): Promise<void>;
|
|
320
379
|
/** Copies a file or directory out of the sandbox. A file streams to disk,
|
|
321
|
-
* any size, checked against its length
|
|
322
|
-
|
|
380
|
+
* any size, checked against its length; a directory comes as one tar from
|
|
381
|
+
* the API's folder route. */
|
|
382
|
+
download(remotePath: string, localPath: string, options?: RequestOptions): Promise<void>;
|
|
323
383
|
}
|
|
324
384
|
export declare function sandboxPage(t: Transport, body: {
|
|
325
385
|
data: SandboxInfo[];
|
|
326
386
|
nextCursor: string | null;
|
|
327
|
-
}, query: Record<string, unknown
|
|
387
|
+
}, query: Record<string, unknown>, options?: RequestOptions): Page<Sandbox>;
|