withruntime 0.11.1 → 0.12.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 (176) hide show
  1. package/BLAXEL.md +3 -3
  2. package/COMPATIBILITY.md +74 -9
  3. package/DAYTONA.md +33 -5
  4. package/E2B.md +137 -48
  5. package/README.md +11 -9
  6. package/README.src.md +11 -9
  7. package/VERCEL.md +43 -5
  8. package/compatibility-lock.json +58 -49
  9. package/dist/billing-cli.d.ts +1 -1
  10. package/dist/billing-cli.js +77 -1
  11. package/dist/blaxel/errors.d.ts +14 -0
  12. package/dist/blaxel/errors.js +33 -4
  13. package/dist/blaxel/index.d.ts +2 -2
  14. package/dist/blaxel/index.js +4 -4
  15. package/dist/blaxel/interpreter.d.ts +2 -5
  16. package/dist/blaxel/sandbox.d.ts +15 -7
  17. package/dist/blaxel/sandbox.js +64 -9
  18. package/dist/blaxel/snapshot.d.ts +4 -0
  19. package/dist/blaxel/snapshot.js +4 -0
  20. package/dist/cli/logs.d.ts +21 -0
  21. package/dist/cli/logs.js +188 -0
  22. package/dist/cli/logs.test.d.ts +1 -0
  23. package/dist/cli/logs.test.js +272 -0
  24. package/dist/cli-extras.d.ts +3 -3
  25. package/dist/cli-extras.js +17 -12
  26. package/dist/cli-words.d.ts +10 -1
  27. package/dist/cli-words.js +18 -0
  28. package/dist/cli.d.ts +6 -2
  29. package/dist/cli.js +468 -219
  30. package/dist/client.d.ts +13 -63
  31. package/dist/client.js +35 -124
  32. package/dist/cloudflare/errors.d.ts +143 -0
  33. package/dist/cloudflare/errors.js +167 -0
  34. package/dist/cloudflare/index.d.ts +175 -6
  35. package/dist/cloudflare/index.js +416 -26
  36. package/dist/cloudflare/interpreter.d.ts +119 -0
  37. package/dist/cloudflare/interpreter.js +223 -0
  38. package/dist/cloudflare/streams.d.ts +38 -0
  39. package/dist/cloudflare/streams.js +145 -0
  40. package/dist/cloudflare/watch.d.ts +9 -0
  41. package/dist/cloudflare/watch.js +24 -0
  42. package/dist/codesandbox/index.d.ts +216 -28
  43. package/dist/codesandbox/index.js +478 -78
  44. package/dist/compat/core.d.ts +18 -0
  45. package/dist/compat/core.js +29 -0
  46. package/dist/compat/files.d.ts +1 -0
  47. package/dist/compat/files.js +25 -5
  48. package/dist/daytona/computer-use.d.ts +13 -4
  49. package/dist/daytona/computer-use.js +66 -8
  50. package/dist/daytona/daytona.d.ts +7 -2
  51. package/dist/daytona/daytona.js +31 -5
  52. package/dist/daytona/errors.d.ts +11 -0
  53. package/dist/daytona/errors.js +18 -0
  54. package/dist/daytona/filesystem.js +2 -1
  55. package/dist/daytona/image.d.ts +13 -9
  56. package/dist/daytona/image.js +18 -12
  57. package/dist/daytona/index.d.ts +1 -1
  58. package/dist/daytona/sandbox.d.ts +9 -3
  59. package/dist/daytona/sandbox.js +17 -3
  60. package/dist/domains/index.d.ts +9 -0
  61. package/dist/domains/index.js +10 -0
  62. package/dist/e2b/client.d.ts +15 -2
  63. package/dist/e2b/client.js +61 -7
  64. package/dist/e2b/commands.d.ts +4 -1
  65. package/dist/e2b/commands.js +17 -7
  66. package/dist/e2b/errors.d.ts +43 -2
  67. package/dist/e2b/errors.js +78 -6
  68. package/dist/e2b/filesystem.d.ts +1 -1
  69. package/dist/e2b/filesystem.js +82 -16
  70. package/dist/e2b/index.d.ts +3 -3
  71. package/dist/e2b/index.js +2 -2
  72. package/dist/e2b/sandbox.d.ts +50 -35
  73. package/dist/e2b/sandbox.js +228 -185
  74. package/dist/e2b/unsupported.d.ts +19 -0
  75. package/dist/e2b/unsupported.js +22 -1
  76. package/dist/e2b/users.d.ts +9 -0
  77. package/dist/e2b/users.js +22 -0
  78. package/dist/errors.d.ts +14 -5
  79. package/dist/errors.js +28 -14
  80. package/dist/freestyle/index.d.ts +285 -37
  81. package/dist/freestyle/index.js +656 -144
  82. package/dist/identity.d.ts +3 -0
  83. package/dist/identity.js +27 -0
  84. package/dist/images/index.d.ts +9 -0
  85. package/dist/images/index.js +10 -0
  86. package/dist/index.d.ts +1 -0
  87. package/dist/ips/index.d.ts +9 -0
  88. package/dist/ips/index.js +10 -0
  89. package/dist/jobs/index.d.ts +9 -0
  90. package/dist/jobs/index.js +10 -0
  91. package/dist/keys.js +2 -0
  92. package/dist/login.js +2 -0
  93. package/dist/machine.d.ts +189 -0
  94. package/dist/machine.js +521 -0
  95. package/dist/mcp.js +1 -1
  96. package/dist/modal/index.d.ts +339 -61
  97. package/dist/modal/index.js +781 -121
  98. package/dist/network-cli.d.ts +3 -1
  99. package/dist/network-cli.js +78 -36
  100. package/dist/networks/index.d.ts +11 -0
  101. package/dist/networks/index.js +10 -0
  102. package/dist/openai-agents/index.d.ts +1 -1
  103. package/dist/openai-agents/index.js +1 -1
  104. package/dist/ports/index.d.ts +9 -0
  105. package/dist/ports/index.js +10 -0
  106. package/dist/product-names.d.ts +52 -0
  107. package/dist/product-names.js +164 -0
  108. package/dist/product-renames.d.ts +103 -0
  109. package/dist/product-renames.js +189 -0
  110. package/dist/products/apps.d.ts +176 -0
  111. package/dist/products/apps.js +165 -0
  112. package/dist/products/billing.d.ts +41 -0
  113. package/dist/products/billing.js +13 -0
  114. package/dist/products/browser.d.ts +10 -0
  115. package/dist/products/browsers.d.ts +71 -0
  116. package/dist/products/browsers.js +102 -0
  117. package/dist/products/builds.d.ts +126 -0
  118. package/dist/products/builds.js +221 -0
  119. package/dist/products/index.d.ts +3 -16
  120. package/dist/products/index.js +3 -14
  121. package/dist/products/jobs.d.ts +19 -3
  122. package/dist/products/jobs.js +28 -12
  123. package/dist/products/limits.d.ts +4 -10
  124. package/dist/products/logs.d.ts +245 -0
  125. package/dist/products/logs.js +274 -0
  126. package/dist/products/logs.test.d.ts +1 -0
  127. package/dist/products/logs.test.js +343 -0
  128. package/dist/products/network-products.d.ts +38 -7
  129. package/dist/products/network-products.js +31 -18
  130. package/dist/products/network.d.ts +1 -1
  131. package/dist/products/observability.d.ts +3 -2
  132. package/dist/products/private-network.js +1 -1
  133. package/dist/products/queues.d.ts +149 -0
  134. package/dist/products/queues.js +213 -0
  135. package/dist/products/referrals.d.ts +21 -7
  136. package/dist/products/referrals.js +3 -3
  137. package/dist/products/secrets.d.ts +8 -4
  138. package/dist/products/secrets.js +39 -18
  139. package/dist/products/signed-requests.d.ts +21 -0
  140. package/dist/products/signed-requests.js +11 -0
  141. package/dist/products/streams.d.ts +73 -0
  142. package/dist/products/streams.js +17 -0
  143. package/dist/products/switching.d.ts +37 -10
  144. package/dist/products/switching.js +4 -3
  145. package/dist/products/volumes.d.ts +3 -0
  146. package/dist/record-cli.d.ts +23 -0
  147. package/dist/record-cli.js +308 -0
  148. package/dist/renamed-products.d.ts +38 -0
  149. package/dist/renamed-products.js +34 -0
  150. package/dist/runloop/index.d.ts +9 -2
  151. package/dist/runloop/index.js +29 -8
  152. package/dist/runloop/sdk.d.ts +131 -0
  153. package/dist/runloop/sdk.js +167 -0
  154. package/dist/sandbox.d.ts +10 -94
  155. package/dist/sandbox.js +22 -371
  156. package/dist/sandboxes/index.d.ts +11 -0
  157. package/dist/sandboxes/index.js +12 -0
  158. package/dist/snapshots/index.d.ts +9 -0
  159. package/dist/snapshots/index.js +11 -0
  160. package/dist/snapshots.d.ts +7 -4
  161. package/dist/sprites/index.d.ts +343 -31
  162. package/dist/sprites/index.js +866 -84
  163. package/dist/ssh.d.ts +1 -1
  164. package/dist/ssh.js +11 -11
  165. package/dist/terminal.d.ts +24 -0
  166. package/dist/terminal.js +32 -0
  167. package/dist/transport.d.ts +18 -2
  168. package/dist/transport.js +61 -6
  169. package/dist/tunnel.js +1 -1
  170. package/dist/types.d.ts +116 -8
  171. package/dist/vercel/sandbox.d.ts +1 -2
  172. package/dist/vercel/sandbox.js +6 -5
  173. package/dist/vercel/snapshot.js +10 -2
  174. package/dist/volumes/index.d.ts +9 -0
  175. package/dist/volumes/index.js +10 -0
  176. package/package.json +48 -2
package/dist/client.d.ts CHANGED
@@ -1,11 +1,12 @@
1
- import { RuntimeError } from "./errors.js";
2
- import type { Page } from "./page.js";
3
1
  import { type ClientExtensions } from "./products/index.js";
2
+ import { type RenamedProducts } from "./renamed-products.js";
4
3
  import { usageExport as makeUsageExport } from "./products/observability.js";
4
+ import { Machines } from "./machine.js";
5
5
  import { Sandbox } from "./sandbox.js";
6
6
  import { Snapshots } from "./snapshots.js";
7
7
  import { Transport, type RequestOptions } from "./transport.js";
8
8
  import type { CreateSandbox, DeletedSandbox, FeedbackKind, SandboxInfo, Usage } from "./types.js";
9
+ export type { CreateOptions } from "./machine.js";
9
10
  export type RuntimeOptions = {
10
11
  /** Default: the RUNTIME_API_KEY environment variable. */
11
12
  apiKey?: string;
@@ -22,23 +23,23 @@ export type RuntimeOptions = {
22
23
  * before it has used a valid key. 8 are kept for calls whatever the
23
24
  * streams hold. */
24
25
  maxConnections?: number;
26
+ /** Called each time a call has to wait for one of those connections: an
27
+ * adapter warns with it, once, that its caller is being held back. */
28
+ onQueued?: (maxConnections: number) => void;
25
29
  /** How long `sandboxes.create` keeps retrying, with the same key and input,
26
- * when the trial's slots, the account's quota or the region is full
27
- * (trial_busy, quota_exceeded, no_capacity and the like). Default 120 000
30
+ * when the slots without credit, the account's quota or the region is full
31
+ * (no_credit_running_limit, quota_exceeded, no_capacity and the like). Default 120 000
28
32
  * (two minutes); 0 fails at once. The refusal is thrown as it came when the
29
33
  * wait runs out. */
30
34
  waitForCapacityMs?: number;
31
35
  };
32
36
  /** One client for every Runtime Cloud product. Create it once and reuse it:
33
37
  * it keeps its connections open. */
34
- export interface Runtime extends ClientExtensions {
38
+ export interface Runtime extends ClientExtensions, RenamedProducts {
35
39
  }
36
40
  export declare class Runtime {
37
41
  readonly transport: Transport;
38
- /** The sandbox product; `sandboxes` remains the same client for compatibility. */
39
- readonly sandbox: Sandboxes;
40
42
  readonly sandboxes: Sandboxes;
41
- readonly snapshot: Snapshots;
42
43
  readonly snapshots: Snapshots;
43
44
  readonly feedback: FeedbackApi;
44
45
  readonly support: SupportApi;
@@ -57,8 +58,8 @@ export declare class Runtime {
57
58
  /** The role of the member who made this key: owner, admin, developer or billing. */
58
59
  role?: string | null;
59
60
  }>;
60
- /** Balance, holds, trial time and per-resource charges, in integer microdollars. */
61
- /** Credit, holds, trial time and per-resource charges. */
61
+ /** Balance, holds, free time and per-resource charges, in integer microdollars. */
62
+ /** Credit, holds, free time and per-resource charges. */
62
63
  usage(options?: RequestOptions): Promise<Usage>;
63
64
  /** This account's authenticated API answers, in hourly windows. Counts are
64
65
  * exact decimal strings, and an empty window has a null error percentage.
@@ -80,60 +81,9 @@ export declare class Runtime {
80
81
  }>;
81
82
  }>;
82
83
  }
83
- /** How `sandboxes.create` waits when every trial slot, the account's quota or
84
- * the region is full. */
85
- export type CreateOptions = RequestOptions & {
86
- /** How long to keep retrying a refusal that clears by itself. Default: the
87
- * client's, two minutes; 0 fails at once. */
88
- waitForCapacityMs?: number;
89
- /** Called before each wait, with the refusal and the milliseconds until the
90
- * next try: to tell a person why nothing has happened yet. */
91
- onCapacityWait?: (refusal: RuntimeError, waitMs: number) => void;
92
- };
93
- export declare class Sandboxes {
94
- private readonly t;
84
+ /** `runtime.sandboxes`: the sandbox product of the machine engine. */
85
+ export declare class Sandboxes extends Machines<Sandbox, SandboxInfo, CreateSandbox, DeletedSandbox> {
95
86
  constructor(t: Transport);
96
- /** Creates a sandbox and waits until it is running. Every field is optional:
97
- * with none you get the free trial while it lasts, the default region and a
98
- * 2 vCPU / 4 GiB machine from a warm template. `wait: false` returns at once.
99
- * When every trial slot or the account's quota is taken, it waits for one to
100
- * free, up to `waitForCapacityMs` (the client's, two minutes by default). */
101
- create(input?: CreateSandbox & {
102
- wait?: boolean;
103
- }, options?: CreateOptions): Promise<Sandbox>;
104
- /** The sandbox named `name` in this account, ready to use: running as it
105
- * is, woken if it is paused, restarted if it is stopped and persistent, or
106
- * created with `input` when no sandbox has the name. `sandbox.info.reused`
107
- * says which. The other fields apply only when it is created. */
108
- getOrCreate(name: string, input?: Omit<CreateSandbox, "name" | "getOrCreate"> & {
109
- wait?: boolean;
110
- }, options?: CreateOptions): Promise<Sandbox>;
111
- get(id: string, options?: RequestOptions): Promise<Sandbox>;
112
- /** Deletes a sandbox for good, by id, without reading it first: see
113
- * `sandbox.delete()`. Deleting it again answers the same. */
114
- delete(id: string, options?: RequestOptions): Promise<DeletedSandbox>;
115
- /** Live sandboxes, oldest first. Await for a page, or `for await` over all.
116
- * Request options apply to the initial request and every subsequent page. */
117
- list(filter?: {
118
- state?: SandboxInfo["state"][];
119
- includeStopped?: boolean;
120
- /** Every label must match. */
121
- labels?: Record<string, string>;
122
- name?: string;
123
- limit?: number;
124
- }, options?: RequestOptions): Promise<Page<Sandbox>>;
125
- /** Stops every live sandbox whose labels all match, eight at a time, and
126
- * says which stopped and which failed; one failure does not stop the rest.
127
- * Needs at least one label, so stopping everything is never one call. */
128
- stopAll(filter: {
129
- labels: Record<string, string>;
130
- }, options?: RequestOptions): Promise<{
131
- stopped: string[];
132
- failed: {
133
- id: string;
134
- error: unknown;
135
- }[];
136
- }>;
137
87
  }
138
88
  export declare class FeedbackApi {
139
89
  private readonly t;
package/dist/client.js CHANGED
@@ -1,10 +1,12 @@
1
- import { WAIT_FOR_TIMEOUT_SECONDS } from "./api-defaults.js";
2
- import { RuntimeError } from "./errors.js";
3
- import { clientFactories, clientProductAliases } from "./products/index.js";
1
+ import { clientFactories } from "./products/index.js";
2
+ import { installRenamedProducts } from "./renamed-products.js";
4
3
  import { usageExport as makeUsageExport } from "./products/observability.js";
5
- import { Sandbox, deleteSandbox, sandboxPage } from "./sandbox.js";
4
+ import { Machines } from "./machine.js";
5
+ import { SANDBOXES, Sandbox } from "./sandbox.js";
6
6
  import { Snapshots } from "./snapshots.js";
7
- import { DEFAULT_BASE_URL, Transport, missingKey } from "./transport.js";
7
+ import { DEFAULT_BASE_URL, Transport, missingKey, sayRenamed, } from "./transport.js";
8
+ import { RuntimeError } from "./errors.js";
9
+ import { RENAMED_FIELDS, fieldUse } from "./product-renames.js";
8
10
  /** The key `runtime login` saved for this machine and this API origin, found
9
11
  * on first use. A constructor override must never receive another API's key. */
10
12
  const savedKey = async (apiOrigin) => {
@@ -19,10 +21,7 @@ const env = (name) => typeof process === "undefined"
19
21
  // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
20
22
  export class Runtime {
21
23
  transport;
22
- /** The sandbox product; `sandboxes` remains the same client for compatibility. */
23
- sandbox;
24
24
  sandboxes;
25
- snapshot;
26
25
  snapshots;
27
26
  feedback;
28
27
  support;
@@ -43,22 +42,20 @@ export class Runtime {
43
42
  ...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
44
43
  ...(options.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),
45
44
  ...(options.maxConnections !== undefined ? { maxConnections: options.maxConnections } : {}),
45
+ ...(options.onQueued ? { onQueued: options.onQueued } : {}),
46
46
  ...(options.waitForCapacityMs !== undefined
47
47
  ? { waitForCapacityMs: options.waitForCapacityMs }
48
48
  : {}),
49
49
  });
50
50
  this.sandboxes = new Sandboxes(this.transport);
51
- this.sandbox = this.sandboxes;
52
51
  this.snapshots = new Snapshots(this.transport);
53
- this.snapshot = this.snapshots;
54
52
  this.feedback = new FeedbackApi(this.transport);
55
53
  this.support = new SupportApi(this.transport);
56
54
  this.account = new AccountApi(this.transport);
57
55
  this.usageExport = makeUsageExport(this.transport);
58
56
  for (const [name, make] of clientFactories())
59
57
  Object.defineProperty(this, name, { value: make(this.transport), enumerable: true });
60
- for (const [alias, name] of Object.entries(clientProductAliases))
61
- Object.defineProperty(this, alias, { value: this[name], enumerable: true });
58
+ installRenamedProducts(this);
62
59
  }
63
60
  /** Who this key is: organization, agent and credential. */
64
61
  me(options = {}) {
@@ -68,14 +65,33 @@ export class Runtime {
68
65
  ...options,
69
66
  });
70
67
  }
71
- /** Balance, holds, trial time and per-resource charges, in integer microdollars. */
72
- /** Credit, holds, trial time and per-resource charges. */
73
- usage(options = {}) {
74
- return this.transport.json({
68
+ /** Balance, holds, free time and per-resource charges, in integer microdollars. */
69
+ /** Credit, holds, free time and per-resource charges. */
70
+ async usage(options = {}) {
71
+ const value = await this.transport.json({
75
72
  method: "GET",
76
73
  path: "/v1/usage",
77
74
  ...options,
78
75
  });
76
+ const fields = value;
77
+ for (const field of RENAMED_FIELDS) {
78
+ // An older server only sends the old name. Preserve its value before
79
+ // replacing that property with the warning getter.
80
+ if (!(field.now in fields) && field.name in fields)
81
+ fields[field.now] = fields[field.name];
82
+ Object.defineProperty(value, field.name, {
83
+ configurable: true,
84
+ enumerable: false,
85
+ get() {
86
+ const use = fieldUse(field.name);
87
+ if (use.kind === "retired")
88
+ throw new RuntimeError({ ...use.error });
89
+ sayRenamed(`299 runtime "${use.warning.replaceAll('"', "'")}"`);
90
+ return fields[field.now];
91
+ },
92
+ });
93
+ }
94
+ return value;
79
95
  }
80
96
  /** This account's authenticated API answers, in hourly windows. Counts are
81
97
  * exact decimal strings, and an empty window has a null error percentage.
@@ -89,115 +105,10 @@ export class Runtime {
89
105
  });
90
106
  }
91
107
  }
92
- export class Sandboxes {
93
- t;
108
+ /** `runtime.sandboxes`: the sandbox product of the machine engine. */
109
+ export class Sandboxes extends Machines {
94
110
  constructor(t) {
95
- this.t = t;
96
- }
97
- /** Creates a sandbox and waits until it is running. Every field is optional:
98
- * with none you get the free trial while it lasts, the default region and a
99
- * 2 vCPU / 4 GiB machine from a warm template. `wait: false` returns at once.
100
- * When every trial slot or the account's quota is taken, it waits for one to
101
- * free, up to `waitForCapacityMs` (the client's, two minutes by default). */
102
- async create(input = {}, options = {}) {
103
- const { wait, ...body } = input;
104
- const began = performance.now();
105
- // Time spent waiting for capacity is the room's, not the deadline's.
106
- let waited = 0;
107
- const info = await this.t.json({
108
- method: "POST",
109
- path: "/v1/sandboxes",
110
- body,
111
- wait: wait === false ? 0 : 60,
112
- ...options,
113
- waitForCapacityMs: options.waitForCapacityMs ?? this.t.waitForCapacityMs,
114
- onCapacityWait: (refusal, waitMs) => {
115
- waited += waitMs;
116
- options.onCapacityWait?.(refusal, waitMs);
117
- },
118
- });
119
- const sandbox = new Sandbox(this.t, info);
120
- if (wait !== false && info.state !== "running") {
121
- // One deadline for the whole create: the wait for running gets what the
122
- // create left of it (1 ms when nothing is left, so it ends as a timeout).
123
- const { timeoutMs } = options;
124
- await sandbox.waitFor("running", {
125
- timeoutSeconds: WAIT_FOR_TIMEOUT_SECONDS,
126
- signal: options.signal,
127
- timeoutMs: timeoutMs
128
- ? Math.max(1, Math.ceil(timeoutMs - (performance.now() - began - waited)))
129
- : timeoutMs,
130
- idempotencyKey: options.idempotencyKey,
131
- });
132
- if (sandbox.state !== "running")
133
- throw new RuntimeError({
134
- message: `Sandbox ${info.id} is ${sandbox.state}, not running.`,
135
- code: "start_failed",
136
- status: 0,
137
- hint: "Read it with runtime.sandboxes.get(id); stopReason says why.",
138
- });
139
- }
140
- return sandbox;
141
- }
142
- /** The sandbox named `name` in this account, ready to use: running as it
143
- * is, woken if it is paused, restarted if it is stopped and persistent, or
144
- * created with `input` when no sandbox has the name. `sandbox.info.reused`
145
- * says which. The other fields apply only when it is created. */
146
- async getOrCreate(name, input = {}, options = {}) {
147
- return this.create({ ...input, name, getOrCreate: true }, options);
148
- }
149
- async get(id, options = {}) {
150
- return new Sandbox(this.t, await this.t.json({
151
- method: "GET",
152
- path: `/v1/sandboxes/${encodeURIComponent(id)}`,
153
- ...options,
154
- }));
155
- }
156
- /** Deletes a sandbox for good, by id, without reading it first: see
157
- * `sandbox.delete()`. Deleting it again answers the same. */
158
- delete(id, options = {}) {
159
- return deleteSandbox(this.t, id, options);
160
- }
161
- /** Live sandboxes, oldest first. Await for a page, or `for await` over all.
162
- * Request options apply to the initial request and every subsequent page. */
163
- async list(filter = {}, options = {}) {
164
- const query = {
165
- ...(filter.state ? { state: filter.state } : {}),
166
- ...(filter.includeStopped ? { includeStopped: true } : {}),
167
- ...(filter.labels
168
- ? { label: Object.entries(filter.labels).map(([k, v]) => `${k}:${v}`) }
169
- : {}),
170
- ...(filter.name ? { name: filter.name } : {}),
171
- ...(filter.limit ? { limit: filter.limit } : {}),
172
- };
173
- return sandboxPage(this.t, await this.t.json({ method: "GET", path: "/v1/sandboxes", query, ...options }), query, options);
174
- }
175
- /** Stops every live sandbox whose labels all match, eight at a time, and
176
- * says which stopped and which failed; one failure does not stop the rest.
177
- * Needs at least one label, so stopping everything is never one call. */
178
- async stopAll(filter, options = {}) {
179
- if (!filter?.labels || Object.keys(filter.labels).length === 0)
180
- throw new RuntimeError({
181
- message: "stopAll needs at least one label to match.",
182
- code: "invalid_request",
183
- status: 0,
184
- hint: "Stop one sandbox with sandbox.stop(), or label the ones to stop together.",
185
- });
186
- const live = await (await this.list({ labels: filter.labels, limit: 100 }, options)).toArray(Infinity);
187
- // One key cannot name several stops: each stop makes its own.
188
- const { idempotencyKey: _one, ...each } = options;
189
- // In list order, oldest first, whichever finishes first.
190
- const errors = new Array(live.length);
191
- let next = 0;
192
- const worker = async () => {
193
- for (let at = next++; at < live.length; at = next++)
194
- await live[at].stop(each).catch((error) => (errors[at] = error ?? "failed"));
195
- };
196
- await Promise.all(Array.from({ length: Math.min(8, live.length) }, worker));
197
- return {
198
- stopped: live.filter((_, at) => errors[at] === undefined).map((sbx) => sbx.id),
199
- failed: live.flatMap((sbx, at) => errors[at] === undefined ? [] : [{ id: sbx.id, error: errors[at] }]),
200
- };
111
+ super(SANDBOXES, t, (transport, info) => new Sandbox(transport, info));
201
112
  }
202
113
  }
203
114
  export class FeedbackApi {
@@ -0,0 +1,143 @@
1
+ /** Cloudflare's exported error classes, with its fields, so a caller's
2
+ * `instanceof` and `error.code` keep working. The adapter throws them where
3
+ * Cloudflare would: a process that never becomes ready, a bucket that will
4
+ * not mount or unmount. */
5
+ export type ErrorResponse<TContext = Record<string, unknown>> = {
6
+ code: string;
7
+ message: string;
8
+ operation?: string;
9
+ context: TContext;
10
+ httpStatus: number;
11
+ timestamp: string;
12
+ suggestion?: string;
13
+ documentation?: string;
14
+ };
15
+ declare class SandboxError<TContext = Record<string, unknown>> extends Error {
16
+ readonly errorResponse: ErrorResponse<TContext>;
17
+ constructor(errorResponse: ErrorResponse<TContext>, options?: {
18
+ cause?: unknown;
19
+ });
20
+ get code(): string;
21
+ get context(): TContext;
22
+ get httpStatus(): number;
23
+ get operation(): string | undefined;
24
+ get suggestion(): string | undefined;
25
+ get timestamp(): string;
26
+ get documentation(): string | undefined;
27
+ toJSON(): {
28
+ name: string;
29
+ message: string;
30
+ code: string;
31
+ context: TContext;
32
+ httpStatus: number;
33
+ operation: string | undefined;
34
+ suggestion: string | undefined;
35
+ timestamp: string;
36
+ documentation: string | undefined;
37
+ stack: string | undefined;
38
+ };
39
+ }
40
+ export { SandboxError };
41
+ export declare class SessionTerminatedError extends SandboxError<{
42
+ sessionId: string;
43
+ exitCode: number | null;
44
+ }> {
45
+ get sessionId(): string;
46
+ get exitCode(): number | null;
47
+ }
48
+ type ReadyContext = {
49
+ processId: string;
50
+ command: string;
51
+ condition: string;
52
+ };
53
+ export declare class ProcessReadyTimeoutError extends SandboxError<ReadyContext & {
54
+ timeout: number;
55
+ }> {
56
+ get processId(): string;
57
+ get command(): string;
58
+ get condition(): string;
59
+ get timeout(): number;
60
+ }
61
+ export declare class ProcessExitedBeforeReadyError extends SandboxError<ReadyContext & {
62
+ exitCode: number;
63
+ }> {
64
+ get processId(): string;
65
+ get command(): string;
66
+ get condition(): string;
67
+ get exitCode(): number;
68
+ }
69
+ export declare class BackupNotFoundError extends SandboxError<{
70
+ backupId: string;
71
+ }> {
72
+ get backupId(): string;
73
+ }
74
+ export declare class BackupExpiredError extends SandboxError<{
75
+ backupId: string;
76
+ expiredAt?: string;
77
+ }> {
78
+ get backupId(): string;
79
+ get expiredAt(): string | undefined;
80
+ }
81
+ export declare class InvalidBackupConfigError extends SandboxError<{
82
+ reason: string;
83
+ }> {
84
+ get reason(): string;
85
+ }
86
+ export declare class BackupCreateError extends SandboxError<{
87
+ dir: string;
88
+ backupId?: string;
89
+ stderr?: string;
90
+ exitCode?: number;
91
+ }> {
92
+ get dir(): string;
93
+ get backupId(): string | undefined;
94
+ }
95
+ export declare class BackupRestoreError extends SandboxError<{
96
+ dir: string;
97
+ backupId: string;
98
+ stderr?: string;
99
+ exitCode?: number;
100
+ }> {
101
+ get dir(): string;
102
+ get backupId(): string;
103
+ }
104
+ export declare class ContainerUnavailableError extends SandboxError<{
105
+ reason: string;
106
+ retryable: true;
107
+ retryAfterMs?: number;
108
+ originalMessage?: string;
109
+ }> {
110
+ get reason(): string;
111
+ get retryAfterMs(): number | undefined;
112
+ }
113
+ export declare class OperationInterruptedError extends SandboxError<{
114
+ reason: string;
115
+ operation: string;
116
+ phase: string;
117
+ admitted: boolean | "unknown";
118
+ retryable: boolean;
119
+ }> {
120
+ get reason(): string;
121
+ }
122
+ export declare class BucketMountError extends Error {
123
+ readonly code: string;
124
+ constructor(message: string, code?: string);
125
+ }
126
+ export declare class S3FSMountError extends BucketMountError {
127
+ constructor(message: string);
128
+ }
129
+ export declare class BucketUnmountError extends BucketMountError {
130
+ constructor(message: string);
131
+ }
132
+ export declare class MissingCredentialsError extends BucketMountError {
133
+ constructor(message: string);
134
+ }
135
+ export declare class InvalidMountConfigError extends BucketMountError {
136
+ constructor(message: string);
137
+ }
138
+ /** An ErrorResponse as the container would send it. */
139
+ export declare function response<TContext>(code: string, message: string, context: TContext, extra?: {
140
+ httpStatus?: number;
141
+ operation?: string;
142
+ suggestion?: string;
143
+ }): ErrorResponse<TContext>;
@@ -0,0 +1,167 @@
1
+ class SandboxError extends Error {
2
+ errorResponse;
3
+ constructor(errorResponse, options) {
4
+ super(errorResponse.message, options);
5
+ this.name = new.target.name;
6
+ this.errorResponse = errorResponse;
7
+ }
8
+ get code() {
9
+ return this.errorResponse.code;
10
+ }
11
+ get context() {
12
+ return this.errorResponse.context;
13
+ }
14
+ get httpStatus() {
15
+ return this.errorResponse.httpStatus;
16
+ }
17
+ get operation() {
18
+ return this.errorResponse.operation;
19
+ }
20
+ get suggestion() {
21
+ return this.errorResponse.suggestion;
22
+ }
23
+ get timestamp() {
24
+ return this.errorResponse.timestamp;
25
+ }
26
+ get documentation() {
27
+ return this.errorResponse.documentation;
28
+ }
29
+ toJSON() {
30
+ return {
31
+ name: this.name,
32
+ message: this.message,
33
+ code: this.code,
34
+ context: this.context,
35
+ httpStatus: this.httpStatus,
36
+ operation: this.operation,
37
+ suggestion: this.suggestion,
38
+ timestamp: this.timestamp,
39
+ documentation: this.documentation,
40
+ stack: this.stack,
41
+ };
42
+ }
43
+ }
44
+ export { SandboxError };
45
+ export class SessionTerminatedError extends SandboxError {
46
+ get sessionId() {
47
+ return this.context.sessionId;
48
+ }
49
+ get exitCode() {
50
+ return this.context.exitCode;
51
+ }
52
+ }
53
+ export class ProcessReadyTimeoutError extends SandboxError {
54
+ get processId() {
55
+ return this.context.processId;
56
+ }
57
+ get command() {
58
+ return this.context.command;
59
+ }
60
+ get condition() {
61
+ return this.context.condition;
62
+ }
63
+ get timeout() {
64
+ return this.context.timeout;
65
+ }
66
+ }
67
+ export class ProcessExitedBeforeReadyError extends SandboxError {
68
+ get processId() {
69
+ return this.context.processId;
70
+ }
71
+ get command() {
72
+ return this.context.command;
73
+ }
74
+ get condition() {
75
+ return this.context.condition;
76
+ }
77
+ get exitCode() {
78
+ return this.context.exitCode;
79
+ }
80
+ }
81
+ export class BackupNotFoundError extends SandboxError {
82
+ get backupId() {
83
+ return this.context.backupId;
84
+ }
85
+ }
86
+ export class BackupExpiredError extends SandboxError {
87
+ get backupId() {
88
+ return this.context.backupId;
89
+ }
90
+ get expiredAt() {
91
+ return this.context.expiredAt;
92
+ }
93
+ }
94
+ export class InvalidBackupConfigError extends SandboxError {
95
+ get reason() {
96
+ return this.context.reason;
97
+ }
98
+ }
99
+ export class BackupCreateError extends SandboxError {
100
+ get dir() {
101
+ return this.context.dir;
102
+ }
103
+ get backupId() {
104
+ return this.context.backupId;
105
+ }
106
+ }
107
+ export class BackupRestoreError extends SandboxError {
108
+ get dir() {
109
+ return this.context.dir;
110
+ }
111
+ get backupId() {
112
+ return this.context.backupId;
113
+ }
114
+ }
115
+ export class ContainerUnavailableError extends SandboxError {
116
+ get reason() {
117
+ return this.context.reason;
118
+ }
119
+ get retryAfterMs() {
120
+ return this.context.retryAfterMs;
121
+ }
122
+ }
123
+ export class OperationInterruptedError extends SandboxError {
124
+ get reason() {
125
+ return this.context.reason;
126
+ }
127
+ }
128
+ export class BucketMountError extends Error {
129
+ code;
130
+ constructor(message, code = "BUCKET_MOUNT_ERROR") {
131
+ super(message);
132
+ this.name = new.target.name;
133
+ this.code = code;
134
+ }
135
+ }
136
+ export class S3FSMountError extends BucketMountError {
137
+ constructor(message) {
138
+ super(message, "S3FS_MOUNT_ERROR");
139
+ }
140
+ }
141
+ export class BucketUnmountError extends BucketMountError {
142
+ constructor(message) {
143
+ super(message, "BUCKET_UNMOUNT_ERROR");
144
+ }
145
+ }
146
+ export class MissingCredentialsError extends BucketMountError {
147
+ constructor(message) {
148
+ super(message, "MISSING_CREDENTIALS");
149
+ }
150
+ }
151
+ export class InvalidMountConfigError extends BucketMountError {
152
+ constructor(message) {
153
+ super(message, "INVALID_MOUNT_CONFIG");
154
+ }
155
+ }
156
+ /** An ErrorResponse as the container would send it. */
157
+ export function response(code, message, context, extra = {}) {
158
+ return {
159
+ code,
160
+ message,
161
+ context,
162
+ httpStatus: extra.httpStatus ?? 500,
163
+ timestamp: new Date().toISOString(),
164
+ ...(extra.operation ? { operation: extra.operation } : {}),
165
+ ...(extra.suggestion ? { suggestion: extra.suggestion } : {}),
166
+ };
167
+ }