withruntime 0.11.0 → 0.11.2

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 (84) hide show
  1. package/BLAXEL.md +8 -9
  2. package/DAYTONA.md +8 -9
  3. package/E2B.md +63 -21
  4. package/README.md +6 -5
  5. package/README.src.md +6 -5
  6. package/VERCEL.md +3 -2
  7. package/compatibility-lock.json +69 -14
  8. package/dist/api-defaults.d.ts +1 -1
  9. package/dist/api-defaults.js +1 -1
  10. package/dist/blaxel/errors.js +4 -4
  11. package/dist/blaxel/lookup.d.ts +2 -1
  12. package/dist/blaxel/lookup.js +2 -1
  13. package/dist/blaxel/sandbox.d.ts +8 -7
  14. package/dist/blaxel/sandbox.js +16 -12
  15. package/dist/cli.d.ts +1 -1
  16. package/dist/cli.js +99 -27
  17. package/dist/client.d.ts +16 -60
  18. package/dist/client.js +14 -103
  19. package/dist/compat/files.js +5 -1
  20. package/dist/compat/lease.d.ts +1 -0
  21. package/dist/compat/lease.js +14 -8
  22. package/dist/credentials.d.ts +9 -0
  23. package/dist/credentials.js +26 -4
  24. package/dist/daytona/daytona.d.ts +1 -2
  25. package/dist/daytona/daytona.js +30 -14
  26. package/dist/daytona/sandbox.d.ts +9 -4
  27. package/dist/daytona/sandbox.js +24 -5
  28. package/dist/e2b/client.d.ts +15 -2
  29. package/dist/e2b/client.js +61 -7
  30. package/dist/e2b/commands.d.ts +3 -0
  31. package/dist/e2b/commands.js +16 -5
  32. package/dist/e2b/errors.d.ts +26 -2
  33. package/dist/e2b/errors.js +38 -5
  34. package/dist/e2b/filesystem.d.ts +1 -1
  35. package/dist/e2b/filesystem.js +82 -16
  36. package/dist/e2b/index.d.ts +2 -2
  37. package/dist/e2b/index.js +2 -2
  38. package/dist/e2b/sandbox.d.ts +25 -12
  39. package/dist/e2b/sandbox.js +196 -165
  40. package/dist/e2b/unsupported.d.ts +19 -0
  41. package/dist/e2b/unsupported.js +21 -0
  42. package/dist/e2b/users.d.ts +9 -0
  43. package/dist/e2b/users.js +22 -0
  44. package/dist/errors.d.ts +10 -4
  45. package/dist/errors.js +18 -10
  46. package/dist/identity.js +2 -1
  47. package/dist/index.d.ts +2 -1
  48. package/dist/index.js +2 -1
  49. package/dist/machine.d.ts +180 -0
  50. package/dist/machine.js +504 -0
  51. package/dist/modal/index.js +6 -2
  52. package/dist/network-cli.js +7 -7
  53. package/dist/openai-agents/index.d.ts +1 -1
  54. package/dist/openai-agents/index.js +1 -1
  55. package/dist/products/browser.d.ts +2 -1
  56. package/dist/products/browser.js +9 -19
  57. package/dist/products/desktop.d.ts +2 -1
  58. package/dist/products/desktop.js +5 -30
  59. package/dist/products/jobs.d.ts +6 -5
  60. package/dist/products/jobs.js +6 -3
  61. package/dist/products/limits.d.ts +4 -10
  62. package/dist/products/mcp.d.ts +5 -1
  63. package/dist/products/mcp.js +29 -8
  64. package/dist/products/network-products.d.ts +1 -1
  65. package/dist/products/network-products.js +1 -1
  66. package/dist/products/network.d.ts +1 -1
  67. package/dist/products/observability.d.ts +1 -1
  68. package/dist/products/private-network.d.ts +1 -1
  69. package/dist/products/secrets.d.ts +3 -3
  70. package/dist/products/switching.d.ts +2 -3
  71. package/dist/runloop/index.js +6 -2
  72. package/dist/sandbox.d.ts +7 -84
  73. package/dist/sandbox.js +58 -345
  74. package/dist/tar.d.ts +2 -0
  75. package/dist/tar.js +74 -16
  76. package/dist/transport.d.ts +36 -8
  77. package/dist/transport.js +174 -37
  78. package/dist/types.d.ts +102 -12
  79. package/dist/vercel/filesystem.js +3 -1
  80. package/dist/vercel/sandbox.d.ts +18 -12
  81. package/dist/vercel/sandbox.js +27 -15
  82. package/dist/wait.d.ts +12 -0
  83. package/dist/wait.js +47 -0
  84. package/package.json +1 -1
package/dist/e2b/users.js CHANGED
@@ -62,6 +62,28 @@ export function commandAs(user, script, cwdGiven) {
62
62
  export function shellAs(user, cwdGiven) {
63
63
  return commandAs(user, "exec /bin/bash -i -l", cwdGiven);
64
64
  }
65
+ /** A running command as E2B lists it, from the command line Runtime keeps
66
+ * (its words joined by spaces, at most 256 characters): `/bin/bash -l -c
67
+ * <script>` for a command, `/bin/bash -i -l` for a PTY, as E2B starts them,
68
+ * whether it runs as the sandbox user or through `commandAs`. Anything else,
69
+ * started outside this package, is its first word and the rest. */
70
+ export function listedAs(command) {
71
+ const wrapped = AS_USER.exec(command);
72
+ if (wrapped) {
73
+ const inner = command.slice(wrapped[0].length);
74
+ if (inner === "exec /bin/bash -i -l")
75
+ return { cmd: "/bin/bash", args: ["-i", "-l"] };
76
+ return { cmd: "/bin/bash", args: ["-l", "-c", inner] };
77
+ }
78
+ if (command.startsWith("bash -c "))
79
+ return { cmd: "/bin/bash", args: ["-l", "-c", command.slice(8)] };
80
+ if (command === "/bin/bash -i -l")
81
+ return { cmd: "/bin/bash", args: ["-i", "-l"] };
82
+ const [cmd = "", ...args] = command.split(" ");
83
+ return { cmd, args };
84
+ }
85
+ /** What `commandAs` puts before the script, as the joined command line shows it. */
86
+ const AS_USER = /^sudo -n -E -H -u [^ ]+ -- \/bin\/bash -c (?:cd ~ 2>\/dev\/null\n)?/;
65
87
  /** One `sh -c` script as `user`, with its arguments passed apart, never
66
88
  * pasted into the script. */
67
89
  function script(user, text, ...args) {
package/dist/errors.d.ts CHANGED
@@ -6,9 +6,15 @@
6
6
  * packages/cloud/src/api/respond.ts) and retrying cannot change them.
7
7
  * host_unavailable and busy pass, and are retried. */
8
8
  export declare const DELIBERATE: ReadonlySet<string>;
9
+ /** Refusals that guarantee nothing ran: a sandbox running as many commands
10
+ * as it can (`guest_busy`), and the API's own limits, which answer before any
11
+ * work starts (`busy`, `rate_limited`). Sending such a call again is always
12
+ * safe, so the SDK does, with backoff, until the call's deadline (five
13
+ * minutes when it has none), however many retries it allows otherwise. */
14
+ export declare const NOTHING_RAN: ReadonlySet<string>;
9
15
  /** Refusals of a create that clear when a sandbox stops or pauses, or a host
10
- * frees room: the trial's slots, an email domain's trial slots, the account's
11
- * quota and the region's capacity. `sandboxes.create` waits them out, retrying
16
+ * frees room: an account without credit's eight at once and its total, an
17
+ * email domain's, the account's quota and the region's capacity. `sandboxes.create` waits them out, retrying
12
18
  * with the same key and input, for up to `waitForCapacityMs`. */
13
19
  export declare const WAITS_FOR_ROOM: ReadonlySet<string>;
14
20
  export declare class RuntimeError extends Error {
@@ -32,8 +38,8 @@ export declare class RuntimeError extends Error {
32
38
  cause?: unknown;
33
39
  });
34
40
  /** Retrying this exact call (the SDK keeps the key) is safe and may work.
35
- * True for no_capacity and trial_busy as well, which clear by themselves when
36
- * a host frees room or a trial sandbox stops. `sandboxes.create` already
41
+ * True for no_capacity and no_credit_running_limit as well, which clear by themselves when
42
+ * a host frees room or a sandbox without credit stops. `sandboxes.create` already
37
43
  * waits for those (see `waitForCapacityMs`), so seeing one from a create
38
44
  * means the wait ran out or was switched off. */
39
45
  get retryable(): boolean;
package/dist/errors.js CHANGED
@@ -16,16 +16,24 @@ export const DELIBERATE = new Set([
16
16
  "identity_unavailable",
17
17
  "env_unavailable",
18
18
  ]);
19
- /** Refusals that pass on their own: a host frees room, a trial slot frees. */
20
- const PASSING = new Set(["no_capacity", "trial_busy"]);
19
+ /** Refusals that guarantee nothing ran: a sandbox running as many commands
20
+ * as it can (`guest_busy`), and the API's own limits, which answer before any
21
+ * work starts (`busy`, `rate_limited`). Sending such a call again is always
22
+ * safe, so the SDK does, with backoff, until the call's deadline (five
23
+ * minutes when it has none), however many retries it allows otherwise. */
24
+ export const NOTHING_RAN = new Set(["guest_busy", "busy", "rate_limited"]);
25
+ /** Refusals that pass on their own: a host frees room, a sandbox of an
26
+ * account without credit stops. */
27
+ const PASSING = new Set(["no_capacity", "no_credit_running_limit", "no_credit_total_limit"]);
21
28
  /** Refusals of a create that clear when a sandbox stops or pauses, or a host
22
- * frees room: the trial's slots, an email domain's trial slots, the account's
23
- * quota and the region's capacity. `sandboxes.create` waits them out, retrying
29
+ * frees room: an account without credit's eight at once and its total, an
30
+ * email domain's, the account's quota and the region's capacity. `sandboxes.create` waits them out, retrying
24
31
  * with the same key and input, for up to `waitForCapacityMs`. */
25
32
  export const WAITS_FOR_ROOM = new Set([
26
- "trial_busy",
27
- "trial_domain_limit",
28
- "trial_capacity",
33
+ "no_credit_running_limit",
34
+ "no_credit_total_limit",
35
+ "no_credit_domain_limit",
36
+ "no_credit_capacity_full",
29
37
  "quota_exceeded",
30
38
  "no_capacity",
31
39
  // A volume whose last sandbox is stopping: free within seconds.
@@ -57,14 +65,14 @@ export class RuntimeError extends Error {
57
65
  this.retryAfterMs = init.retryAfterMs;
58
66
  }
59
67
  /** Retrying this exact call (the SDK keeps the key) is safe and may work.
60
- * True for no_capacity and trial_busy as well, which clear by themselves when
61
- * a host frees room or a trial sandbox stops. `sandboxes.create` already
68
+ * True for no_capacity and no_credit_running_limit as well, which clear by themselves when
69
+ * a host frees room or a sandbox without credit stops. `sandboxes.create` already
62
70
  * waits for those (see `waitForCapacityMs`), so seeing one from a create
63
71
  * means the wait ran out or was switched off. */
64
72
  get retryable() {
65
73
  if (DELIBERATE.has(this.code))
66
74
  return false;
67
- // A fork asking for more copies than the trial runs at once never fits.
75
+ // A fork asking for more copies than an account without credit runs at once never fits.
68
76
  if (PASSING.has(this.code))
69
77
  return this.details?.field !== "count";
70
78
  return [0, 429, 502, 503, 504].includes(this.status);
package/dist/identity.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { RuntimeError } from "./errors.js";
2
+ import { sandboxMarker } from "./transport.js";
2
3
  async function requestCredentials() {
3
4
  let url = process.env.RUNTIME_ID_TOKEN_REQUEST_URL;
4
5
  let token = process.env.RUNTIME_ID_TOKEN_REQUEST_TOKEN;
@@ -7,7 +8,7 @@ async function requestCredentials() {
7
8
  try {
8
9
  // Loaded here, so the SDK still loads where there is no file system.
9
10
  const { readFile } = await import("node:fs/promises");
10
- const env = JSON.parse(await readFile("/run/runtime/environment.json", "utf8"));
11
+ const env = JSON.parse(await readFile(sandboxMarker.path, "utf8"));
11
12
  url = env.RUNTIME_ID_TOKEN_REQUEST_URL;
12
13
  token = env.RUNTIME_ID_TOKEN_REQUEST_TOKEN;
13
14
  }
package/dist/index.d.ts CHANGED
@@ -35,7 +35,8 @@ export type * from "./types.js";
35
35
  * does the same with an explicit client. */
36
36
  export declare class Sandbox extends SandboxClass {
37
37
  /** Creates a sandbox (every field optional) and waits until it is running.
38
- * `keepAlive: true` (or its options) extends its lease in the background
38
+ * With no `timeoutSeconds` it runs while it works and pauses when idle.
39
+ * `keepAlive: true` (or its options) carries one with a time limit past it
39
40
  * until you stop it; see `sandbox.keepAlive()`. */
40
41
  static create(input?: CreateSandbox & {
41
42
  wait?: boolean;
package/dist/index.js CHANGED
@@ -14,7 +14,8 @@ export * from "./errors.js";
14
14
  * does the same with an explicit client. */
15
15
  export class Sandbox extends SandboxClass {
16
16
  /** Creates a sandbox (every field optional) and waits until it is running.
17
- * `keepAlive: true` (or its options) extends its lease in the background
17
+ * With no `timeoutSeconds` it runs while it works and pauses when idle.
18
+ * `keepAlive: true` (or its options) carries one with a time limit past it
18
19
  * until you stop it; see `sandbox.keepAlive()`. */
19
20
  static async create(input = {}, options = {}) {
20
21
  const { client, ...rest } = options;
@@ -0,0 +1,180 @@
1
+ import { RuntimeError } from "./errors.js";
2
+ import { Page } from "./page.js";
3
+ import type { Snapshot, SnapshotOptions } from "./snapshots.js";
4
+ import type { RequestOptions, Transport } from "./transport.js";
5
+ import type { KeepAliveOptions } from "./types.js";
6
+ /** One machine product: the API serves it at /v1/<plural>, and its errors
7
+ * call one of it by `noun`. */
8
+ export type MachineProduct = {
9
+ readonly plural: string;
10
+ readonly noun: string;
11
+ };
12
+ /** What every machine's record carries for the verbs shared here. */
13
+ export type MachineState = "starting" | "running" | "pausing" | "paused" | "resuming" | "stopping" | "stopped";
14
+ export type MachineInfo = {
15
+ id: string;
16
+ state: MachineState;
17
+ expiresAt: string;
18
+ endsAt?: string | null;
19
+ start?: unknown;
20
+ };
21
+ /** Any other call's request options, as the caller gave them: `timeoutMs` is
22
+ * the call's whole deadline, and 0 turns it off. */
23
+ export declare function requestOnly(options: RequestOptions): RequestOptions;
24
+ /** DELETE /v1/<plural>/{id}, for `machine.delete()` and the product's
25
+ * `delete(id)`. */
26
+ export declare function deleteMachine<Deleted>(product: MachineProduct, t: Transport, id: string, options?: RequestOptions): Promise<Deleted>;
27
+ /** One page of a product's list, and the pages after it. */
28
+ export declare function machinePage<M, Info>(product: MachineProduct, t: Transport, wrap: (t: Transport, info: Info) => M, body: {
29
+ data: Info[];
30
+ nextCursor: string | null;
31
+ }, query: Record<string, unknown>, options?: RequestOptions): Page<M>;
32
+ /** One machine: its record and the verbs every machine product shares. */
33
+ export declare abstract class Machine<Info extends MachineInfo, Settings extends object, Deleted> implements AsyncDisposable {
34
+ #private;
35
+ constructor(product: MachineProduct, transport: Transport, info: Info);
36
+ get id(): string;
37
+ /** What the API last said about this sandbox. `refresh()` asks again. */
38
+ get info(): Info;
39
+ get state(): Info["state"];
40
+ refresh(options?: RequestOptions): Promise<this>;
41
+ /** Waits (server-side, no polling) until the sandbox reaches `state`. */
42
+ waitFor(state: "running" | "paused" | "stopped", options?: {
43
+ timeoutSeconds?: number;
44
+ } & RequestOptions): Promise<this>;
45
+ stop(options?: RequestOptions & {
46
+ wait?: boolean;
47
+ }): Promise<this>;
48
+ pause(options?: RequestOptions & {
49
+ wait?: boolean;
50
+ }): Promise<this>;
51
+ /** Deletes it for good: stops it if it runs or is paused, deletes its disk
52
+ * and paused memory, revokes its previews and ports, and removes it from
53
+ * lists. Its snapshots, usage and audit entries stay. Deleting it again
54
+ * answers the same. */
55
+ delete(options?: RequestOptions): Promise<Deleted>;
56
+ /** Carries on a paused sandbox; for one with a time limit,
57
+ * `timeoutSeconds` is its new one. */
58
+ wake(options?: RequestOptions & {
59
+ wait?: boolean;
60
+ timeoutSeconds?: number;
61
+ }): Promise<this>;
62
+ /** More time before its time limit ends (at most an hour ahead of now). A
63
+ * sandbox with no time limit needs none: the call answers at once and
64
+ * changes nothing. */
65
+ extend(seconds: number, options?: RequestOptions): Promise<this>;
66
+ /** Changes its name, labels, automatic wake, idle pause or persistence;
67
+ * fields left out stay as they are. `persistent: true` keeps it running
68
+ * while credit lasts (paid only). */
69
+ update(settings: Settings, options?: RequestOptions): Promise<this>;
70
+ /** Moves it to another image (id, name, name:tag or name@version), keeping
71
+ * its id, /workspace (its home: dotfiles, pip --user and npm -g installs),
72
+ * volumes, environment, name and previews. Its processes restart, and
73
+ * everything else on its old disk (sudo installs, apt packages, /etc) is
74
+ * lost; snapshot it first to keep everything. A running sandbox is paused
75
+ * first. A switch that fails is undone (`switch_undone`), the sandbox on
76
+ * its old image with nothing lost. Charged as a wake. `keep` is optional:
77
+ * "workspace" is the only value, and it is sent either way, so an API from
78
+ * before it was optional accepts the call too. */
79
+ switchImage(image: string, options?: RequestOptions & {
80
+ keep?: "workspace";
81
+ }): Promise<this>;
82
+ /** Gives it more or fewer vCPUs or more or less memory by a restart: its id,
83
+ * whole disk, volumes, environment, name and previews stay, and its
84
+ * programs stop (snapshot it first to keep its memory too). A running sandbox is paused, or stopped if it is
85
+ * persistent, and comes back running at the new size on the same server; a
86
+ * paused or stopped one is started. Memory bills on the new size from then.
87
+ * Refused, with nothing changed, when the server has no room
88
+ * (`no_capacity`), above your quota or the 2 vCPU and 4 GiB without credit, or
89
+ * while a snapshot or fork of it is being taken. `restart` is optional:
90
+ * true is the only value, and it is sent either way, so an API from before
91
+ * it was optional accepts the call too. */
92
+ resize(size: {
93
+ vcpu?: number;
94
+ memoryMiB?: number;
95
+ }, options?: RequestOptions & {
96
+ restart?: true;
97
+ }): Promise<this>;
98
+ /** Keeps a sandbox with a time limit running past it, in the background,
99
+ * until stop() or the returned function ends it: every `everySeconds` (60)
100
+ * it extends the limit so that `marginSeconds` (600) remain, never more
101
+ * than the hour ahead the API allows. A sandbox with no time limit
102
+ * (`endsAt` null) needs none, and is only watched. Running time is billed
103
+ * as it is used. A paused sandbox is left paused (a request wakes it,
104
+ * unless autoWake is off); a stopped one ends the loop. It does not keep a
105
+ * Node or Bun process alive by itself. */
106
+ keepAlive(options?: KeepAliveOptions): () => void;
107
+ /** Days a paused sandbox is kept before deletion (1 to 365). */
108
+ setRetention(days: number, options?: RequestOptions): Promise<this>;
109
+ /** Keeps this sandbox's whole machine (files, memory, running processes) as
110
+ * a snapshot to start new sandboxes from. A running sandbox is paused for
111
+ * the moment it takes, then woken; a paused one stays paused. Past
112
+ * `timeoutMs` (ten minutes unless given) mid-capture, it stays paused and
113
+ * the error names the snapshot. */
114
+ snapshot(options?: SnapshotOptions & RequestOptions): Promise<Snapshot>;
115
+ /** Starts a stopped persistent sandbox again from its disk (memory is not kept). */
116
+ restart(options?: RequestOptions & {
117
+ wait?: boolean;
118
+ }): Promise<this>;
119
+ [Symbol.asyncDispose](): Promise<void>;
120
+ toJSON(): Info;
121
+ }
122
+ /** How a product's `create` waits when every slot without credit, the account's quota
123
+ * or the region is full. */
124
+ export type CreateOptions = RequestOptions & {
125
+ /** How long to keep retrying a refusal that clears by itself. Default: the
126
+ * client's, two minutes; 0 fails at once. */
127
+ waitForCapacityMs?: number;
128
+ /** Called before each wait, with the refusal and the milliseconds until the
129
+ * next try: to tell a person why nothing has happened yet. */
130
+ onCapacityWait?: (refusal: RuntimeError, waitMs: number) => void;
131
+ };
132
+ /** A machine product's collection: `runtime.<product>`. */
133
+ export declare abstract class Machines<M extends Machine<Info, object, Deleted>, Info extends MachineInfo, Create extends {
134
+ name?: string;
135
+ getOrCreate?: boolean;
136
+ }, Deleted> {
137
+ #private;
138
+ constructor(product: MachineProduct, t: Transport, wrap: (t: Transport, info: Info) => M);
139
+ /** Creates a sandbox and waits until it is running. Every field is optional:
140
+ * with none you get the included usage while it lasts, the default region and a
141
+ * 2 vCPU / 4 GiB machine from a warm template. `wait: false` returns at once.
142
+ * When every slot without credit or the account's quota is taken, it waits for one to
143
+ * free, up to `waitForCapacityMs` (the client's, two minutes by default). */
144
+ create(input?: Create & {
145
+ wait?: boolean;
146
+ }, options?: CreateOptions): Promise<M>;
147
+ /** The sandbox named `name` in this account, ready to use: running as it
148
+ * is, woken if it is paused, restarted if it is stopped and persistent, or
149
+ * created with `input` when no sandbox has the name. `sandbox.info.reused`
150
+ * says which. The other fields apply only when it is created. */
151
+ getOrCreate(name: string, input?: Omit<Create, "name" | "getOrCreate"> & {
152
+ wait?: boolean;
153
+ }, options?: CreateOptions): Promise<M>;
154
+ get(id: string, options?: RequestOptions): Promise<M>;
155
+ /** Deletes a sandbox for good, by id, without reading it first: see
156
+ * `sandbox.delete()`. Deleting it again answers the same. */
157
+ delete(id: string, options?: RequestOptions): Promise<Deleted>;
158
+ /** Live sandboxes, oldest first. Await for a page, or `for await` over all.
159
+ * Request options apply to the initial request and every subsequent page. */
160
+ list(filter?: {
161
+ state?: Info["state"][];
162
+ includeStopped?: boolean;
163
+ /** Every label must match. */
164
+ labels?: Record<string, string>;
165
+ name?: string;
166
+ limit?: number;
167
+ }, options?: RequestOptions): Promise<Page<M>>;
168
+ /** Stops every live sandbox whose labels all match, eight at a time, and
169
+ * says which stopped and which failed; one failure does not stop the rest.
170
+ * Needs at least one label, so stopping everything is never one call. */
171
+ stopAll(filter: {
172
+ labels: Record<string, string>;
173
+ }, options?: RequestOptions): Promise<{
174
+ stopped: string[];
175
+ failed: {
176
+ id: string;
177
+ error: unknown;
178
+ }[];
179
+ }>;
180
+ }