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.
Files changed (132) hide show
  1. package/BLAXEL.md +4 -4
  2. package/COMPATIBILITY.md +145 -0
  3. package/DAYTONA.md +13 -7
  4. package/E2B.md +34 -20
  5. package/README.md +22 -11
  6. package/README.src.md +22 -11
  7. package/VERCEL.md +13 -3
  8. package/compatibility-lock.json +357 -0
  9. package/dist/ai-harness/index.js +2 -2
  10. package/dist/api-defaults.d.ts +17 -0
  11. package/dist/api-defaults.js +22 -0
  12. package/dist/blaxel/errors.js +1 -1
  13. package/dist/blaxel/lookup.d.ts +3 -2
  14. package/dist/blaxel/lookup.js +3 -2
  15. package/dist/blaxel/pagination.d.ts +2 -2
  16. package/dist/blaxel/pagination.js +45 -17
  17. package/dist/blaxel/preview.d.ts +3 -2
  18. package/dist/blaxel/preview.js +16 -14
  19. package/dist/blaxel/process.d.ts +1 -1
  20. package/dist/blaxel/process.js +66 -11
  21. package/dist/blaxel/sandbox.d.ts +2 -0
  22. package/dist/blaxel/sandbox.js +2 -0
  23. package/dist/blaxel/snapshot.js +3 -5
  24. package/dist/cli-words.d.ts +27 -0
  25. package/dist/cli-words.js +135 -0
  26. package/dist/cli.d.ts +2 -0
  27. package/dist/cli.js +351 -85
  28. package/dist/client.d.ts +33 -4
  29. package/dist/client.js +47 -12
  30. package/dist/cloudflare/identity.d.ts +7 -0
  31. package/dist/cloudflare/identity.js +13 -0
  32. package/dist/cloudflare/index.d.ts +303 -0
  33. package/dist/cloudflare/index.js +592 -0
  34. package/dist/cloudflare/worker.d.ts +419 -0
  35. package/dist/cloudflare/worker.js +447 -0
  36. package/dist/codesandbox/guest-service.d.ts +31 -0
  37. package/dist/codesandbox/guest-service.js +490 -0
  38. package/dist/codesandbox/index.d.ts +386 -0
  39. package/dist/codesandbox/index.js +1347 -0
  40. package/dist/compat/core.d.ts +40 -0
  41. package/dist/compat/core.js +238 -0
  42. package/dist/compat/files.d.ts +26 -0
  43. package/dist/compat/files.js +133 -0
  44. package/dist/compat/shell.d.ts +4 -0
  45. package/dist/compat/shell.js +165 -0
  46. package/dist/credentials.d.ts +6 -1
  47. package/dist/credentials.js +107 -38
  48. package/dist/daytona/context.js +2 -1
  49. package/dist/daytona/daytona.js +11 -4
  50. package/dist/daytona/filesystem.d.ts +17 -4
  51. package/dist/daytona/filesystem.js +121 -38
  52. package/dist/daytona/index.d.ts +1 -1
  53. package/dist/daytona/process.d.ts +1 -1
  54. package/dist/daytona/process.js +27 -4
  55. package/dist/daytona/sandbox.d.ts +1 -1
  56. package/dist/daytona/sandbox.js +16 -7
  57. package/dist/e2b/client.js +1 -1
  58. package/dist/e2b/code-interpreter.d.ts +4 -5
  59. package/dist/e2b/code-interpreter.js +54 -56
  60. package/dist/e2b/commands.d.ts +35 -12
  61. package/dist/e2b/commands.js +169 -73
  62. package/dist/e2b/errors.js +1 -1
  63. package/dist/e2b/filesystem.d.ts +8 -6
  64. package/dist/e2b/filesystem.js +127 -28
  65. package/dist/e2b/index.d.ts +1 -0
  66. package/dist/e2b/index.js +1 -0
  67. package/dist/e2b/pty.d.ts +24 -0
  68. package/dist/e2b/pty.js +80 -0
  69. package/dist/e2b/sandbox.d.ts +6 -4
  70. package/dist/e2b/sandbox.js +59 -25
  71. package/dist/errors.d.ts +8 -0
  72. package/dist/errors.js +15 -2
  73. package/dist/file-source.d.ts +16 -0
  74. package/dist/file-source.js +162 -0
  75. package/dist/freestyle/index.d.ts +309 -0
  76. package/dist/freestyle/index.js +343 -0
  77. package/dist/index.d.ts +3 -1
  78. package/dist/login.js +16 -10
  79. package/dist/mcp.js +2 -2
  80. package/dist/modal/index.d.ts +205 -0
  81. package/dist/modal/index.js +486 -0
  82. package/dist/network-cli.js +112 -44
  83. package/dist/openai-agents/index.js +18 -71
  84. package/dist/page.d.ts +1 -1
  85. package/dist/page.js +2 -2
  86. package/dist/products/audit.d.ts +3 -0
  87. package/dist/products/index.d.ts +14 -0
  88. package/dist/products/index.js +12 -0
  89. package/dist/products/interpreter.d.ts +11 -4
  90. package/dist/products/interpreter.js +33 -9
  91. package/dist/products/jobs.js +3 -2
  92. package/dist/products/limits.d.ts +10 -0
  93. package/dist/products/observability.d.ts +44 -0
  94. package/dist/products/observability.js +6 -0
  95. package/dist/products/previews.d.ts +18 -4
  96. package/dist/products/previews.js +14 -5
  97. package/dist/products/tailscale.d.ts +57 -0
  98. package/dist/products/tailscale.js +17 -0
  99. package/dist/products/volumes.d.ts +42 -0
  100. package/dist/products/volumes.js +36 -0
  101. package/dist/products/watch.d.ts +25 -4
  102. package/dist/products/watch.js +132 -18
  103. package/dist/proxy.js +3 -1
  104. package/dist/runloop/index.d.ts +326 -0
  105. package/dist/runloop/index.js +535 -0
  106. package/dist/runloop/pagination.d.ts +46 -0
  107. package/dist/runloop/pagination.js +82 -0
  108. package/dist/runloop/snapshots.d.ts +52 -0
  109. package/dist/runloop/snapshots.js +244 -0
  110. package/dist/sandbox.d.ts +76 -16
  111. package/dist/sandbox.js +696 -135
  112. package/dist/snapshots.d.ts +20 -5
  113. package/dist/snapshots.js +11 -1
  114. package/dist/sprites/index.d.ts +251 -0
  115. package/dist/sprites/index.js +588 -0
  116. package/dist/tar.d.ts +10 -1
  117. package/dist/tar.js +311 -35
  118. package/dist/tools/index.js +2 -1
  119. package/dist/transport.d.ts +23 -8
  120. package/dist/transport.js +247 -127
  121. package/dist/types.d.ts +52 -3
  122. package/dist/vercel/command.d.ts +1 -1
  123. package/dist/vercel/command.js +15 -3
  124. package/dist/vercel/errors.d.ts +2 -2
  125. package/dist/vercel/errors.js +19 -2
  126. package/dist/vercel/filesystem.d.ts +21 -18
  127. package/dist/vercel/filesystem.js +95 -48
  128. package/dist/vercel/sandbox.d.ts +8 -8
  129. package/dist/vercel/sandbox.js +159 -64
  130. package/dist/vercel/snapshot.d.ts +3 -2
  131. package/dist/vercel/snapshot.js +9 -5
  132. 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 are tracked for you, so a retried write is never typed twice. */
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 is unpacked in place. */
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
- download(remotePath: string, localPath: string): Promise<void>;
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>): Page<Sandbox>;
387
+ }, query: Record<string, unknown>, options?: RequestOptions): Page<Sandbox>;