withruntime 0.10.0 → 0.11.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/DAYTONA.md +40 -34
- package/E2B.md +56 -57
- package/VERCEL.md +21 -19
- package/compatibility-lock.json +8 -84
- package/dist/cli.js +73 -2
- package/dist/client.d.ts +12 -0
- package/dist/client.js +27 -0
- package/dist/compat/lease.d.ts +36 -0
- package/dist/compat/lease.js +87 -0
- package/dist/daytona/computer-use.d.ts +162 -0
- package/dist/daytona/computer-use.js +324 -0
- package/dist/daytona/context.d.ts +10 -0
- package/dist/daytona/context.js +24 -0
- package/dist/daytona/daytona.d.ts +20 -0
- package/dist/daytona/daytona.js +123 -16
- package/dist/daytona/filesystem.js +8 -0
- package/dist/daytona/index.d.ts +2 -26
- package/dist/daytona/index.js +2 -7
- package/dist/daytona/process.d.ts +63 -6
- package/dist/daytona/process.js +224 -23
- package/dist/daytona/sandbox.d.ts +19 -5
- package/dist/daytona/sandbox.js +39 -25
- package/dist/e2b/client.d.ts +5 -0
- package/dist/e2b/client.js +5 -1
- package/dist/e2b/commands.d.ts +15 -6
- package/dist/e2b/commands.js +83 -18
- package/dist/e2b/errors.d.ts +7 -0
- package/dist/e2b/errors.js +20 -0
- package/dist/e2b/filesystem.d.ts +2 -1
- package/dist/e2b/filesystem.js +43 -6
- package/dist/e2b/index.d.ts +2 -2
- package/dist/e2b/index.js +1 -1
- package/dist/e2b/pty.js +6 -3
- package/dist/e2b/sandbox.d.ts +15 -5
- package/dist/e2b/sandbox.js +190 -28
- package/dist/e2b/users.d.ts +30 -0
- package/dist/e2b/users.js +185 -0
- package/dist/index.d.ts +1 -0
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.js +6 -1
- package/dist/network-cli.js +28 -0
- package/dist/products/browser.d.ts +60 -0
- package/dist/products/browser.js +37 -0
- package/dist/products/desktop.d.ts +2 -2
- package/dist/products/desktop.js +2 -2
- package/dist/products/images.d.ts +3 -1
- package/dist/products/images.js +14 -2
- package/dist/products/index.d.ts +2 -0
- package/dist/products/index.js +2 -0
- package/dist/products/network-products.d.ts +7 -0
- package/dist/products/network-products.js +3 -0
- package/dist/products/private-network.d.ts +22 -0
- package/dist/products/private-network.js +10 -0
- package/dist/sandbox.d.ts +22 -0
- package/dist/sandbox.js +47 -0
- package/dist/transport.d.ts +1 -1
- package/dist/transport.js +1 -1
- package/dist/types.d.ts +5 -2
- package/dist/vercel/index.d.ts +1 -7
- package/dist/vercel/index.js +1 -3
- package/dist/vercel/sandbox-user.d.ts +70 -0
- package/dist/vercel/sandbox-user.js +206 -0
- package/dist/vercel/sandbox.d.ts +47 -12
- package/dist/vercel/sandbox.js +201 -42
- package/package.json +1 -1
package/dist/network-cli.js
CHANGED
|
@@ -70,6 +70,12 @@ export const NETWORK_HELP = {
|
|
|
70
70
|
upstream-proxy remove Connections leave directly again
|
|
71
71
|
A proxy that refuses or cannot be reached fails the connection; nothing goes
|
|
72
72
|
around it. Paid accounts only.
|
|
73
|
+
|
|
74
|
+
private on Your sandboxes reach each other by name, over TCP:
|
|
75
|
+
<name>.sandbox.internal:<port> or <id>.sandbox.internal:<port>
|
|
76
|
+
private off They stop; open connections between them are cut
|
|
77
|
+
private status On or off
|
|
78
|
+
Only your own sandboxes answer. Paid accounts only, and free.
|
|
73
79
|
`,
|
|
74
80
|
};
|
|
75
81
|
function usage(product, message) {
|
|
@@ -400,6 +406,28 @@ export async function networkProductCommand(product, argv, args, out, client) {
|
|
|
400
406
|
}
|
|
401
407
|
}
|
|
402
408
|
}
|
|
409
|
+
if (product === "network" && verb === "private") {
|
|
410
|
+
const describe = (state) => state.enabled
|
|
411
|
+
? "On: your sandboxes reach each other at <name>.sandbox.internal:<port> over TCP."
|
|
412
|
+
: state.allowed
|
|
413
|
+
? "Off. Turn it on: runtime network private on"
|
|
414
|
+
: "Off. Reaching your sandboxes by name is for paid accounts; add credit to turn it on.";
|
|
415
|
+
switch (rest[0]) {
|
|
416
|
+
case "on":
|
|
417
|
+
case "off": {
|
|
418
|
+
const state = await runtime.network.private.set({ enabled: rest[0] === "on" });
|
|
419
|
+
print(state.enabled ? describe(state) : "Off. Open connections between your sandboxes are cut.", state);
|
|
420
|
+
return 0;
|
|
421
|
+
}
|
|
422
|
+
case "status":
|
|
423
|
+
case undefined: {
|
|
424
|
+
const state = await runtime.network.private.get();
|
|
425
|
+
print(describe(state), state);
|
|
426
|
+
return 0;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
throw usage(product, "private takes on, off or status.");
|
|
430
|
+
}
|
|
403
431
|
if (product === "network") {
|
|
404
432
|
if (verb !== "upstream-proxy")
|
|
405
433
|
throw usage(product, `Unknown network command ${verb}.`);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Sandbox } from "../sandbox.js";
|
|
2
|
+
import type { RequestOptions, Transport } from "../transport.js";
|
|
3
|
+
export type SandboxBrowser = {
|
|
4
|
+
running: false;
|
|
5
|
+
} | {
|
|
6
|
+
running: true;
|
|
7
|
+
headless: boolean;
|
|
8
|
+
/** Chromium's version, e.g. "Chrome/154.0.8037.92". */
|
|
9
|
+
version: string;
|
|
10
|
+
/** The browser's DevTools WebSocket with its private token: give it as it
|
|
11
|
+
* is to Playwright's `chromium.connectOverCDP`, `puppeteer.connect({
|
|
12
|
+
* browserWSEndpoint })`, browser-use or Stagehand. */
|
|
13
|
+
cdpUrl: string;
|
|
14
|
+
/** The DevTools HTTP endpoint; send `headers` with it. */
|
|
15
|
+
httpUrl: string;
|
|
16
|
+
headers: Record<string, string>;
|
|
17
|
+
/** When the token in cdpUrl ends; `get()` returns a fresh one. */
|
|
18
|
+
expiresAt: string | null;
|
|
19
|
+
/** headless: false only: the desktop's live view. */
|
|
20
|
+
streamUrl?: string;
|
|
21
|
+
};
|
|
22
|
+
export type BrowserStartOptions = {
|
|
23
|
+
/** true (the default): no window. false: on the sandbox's desktop, with a live view. */
|
|
24
|
+
headless?: boolean;
|
|
25
|
+
width?: number;
|
|
26
|
+
height?: number;
|
|
27
|
+
};
|
|
28
|
+
/** `sbx.browser`: Chromium in the sandbox, for agents that speak CDP.
|
|
29
|
+
*
|
|
30
|
+
* const { cdpUrl } = await sbx.browser.start();
|
|
31
|
+
* const browser = await chromium.connectOverCDP(cdpUrl);
|
|
32
|
+
*
|
|
33
|
+
* Inside the sandbox the same browser is at http://127.0.0.1:9222. */
|
|
34
|
+
export declare function sandboxBrowser(t: Transport, sandbox: Sandbox): {
|
|
35
|
+
/** Starts Chromium and returns its CDP address. The first start in a
|
|
36
|
+
* sandbox installs Chromium, about a minute; this waits for it (up to 10
|
|
37
|
+
* minutes). Starting a running browser returns it as it is. */
|
|
38
|
+
start(input?: BrowserStartOptions, options?: RequestOptions): Promise<{
|
|
39
|
+
running: true;
|
|
40
|
+
headless: boolean;
|
|
41
|
+
/** Chromium's version, e.g. "Chrome/154.0.8037.92". */
|
|
42
|
+
version: string;
|
|
43
|
+
/** The browser's DevTools WebSocket with its private token: give it as it
|
|
44
|
+
* is to Playwright's `chromium.connectOverCDP`, `puppeteer.connect({
|
|
45
|
+
* browserWSEndpoint })`, browser-use or Stagehand. */
|
|
46
|
+
cdpUrl: string;
|
|
47
|
+
/** The DevTools HTTP endpoint; send `headers` with it. */
|
|
48
|
+
httpUrl: string;
|
|
49
|
+
headers: Record<string, string>;
|
|
50
|
+
/** When the token in cdpUrl ends; `get()` returns a fresh one. */
|
|
51
|
+
expiresAt: string | null;
|
|
52
|
+
/** headless: false only: the desktop's live view. */
|
|
53
|
+
streamUrl?: string;
|
|
54
|
+
}>;
|
|
55
|
+
/** Whether it runs, and a fresh cdpUrl when it does. */
|
|
56
|
+
get: (options?: RequestOptions) => Promise<SandboxBrowser>;
|
|
57
|
+
stop: (options?: RequestOptions) => Promise<{
|
|
58
|
+
stopped: boolean;
|
|
59
|
+
}>;
|
|
60
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** `sbx.browser`: Chromium in the sandbox, for agents that speak CDP.
|
|
2
|
+
*
|
|
3
|
+
* const { cdpUrl } = await sbx.browser.start();
|
|
4
|
+
* const browser = await chromium.connectOverCDP(cdpUrl);
|
|
5
|
+
*
|
|
6
|
+
* Inside the sandbox the same browser is at http://127.0.0.1:9222. */
|
|
7
|
+
export function sandboxBrowser(t, sandbox) {
|
|
8
|
+
const base = () => `/v1/sandboxes/${encodeURIComponent(sandbox.id)}/browser`;
|
|
9
|
+
return {
|
|
10
|
+
/** Starts Chromium and returns its CDP address. The first start in a
|
|
11
|
+
* sandbox installs Chromium, about a minute; this waits for it (up to 10
|
|
12
|
+
* minutes). Starting a running browser returns it as it is. */
|
|
13
|
+
async start(input = {}, options) {
|
|
14
|
+
const deadline = Date.now() + 600_000;
|
|
15
|
+
for (;;) {
|
|
16
|
+
try {
|
|
17
|
+
return await t.json({
|
|
18
|
+
method: "POST",
|
|
19
|
+
path: `${base()}:start`,
|
|
20
|
+
body: input,
|
|
21
|
+
...options,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const code = error.code;
|
|
26
|
+
if ((code !== "browser_installing" && code !== "desktop_installing") ||
|
|
27
|
+
Date.now() > deadline)
|
|
28
|
+
throw error;
|
|
29
|
+
await new Promise((resolve) => setTimeout(resolve, error.retryAfterMs ?? 10_000));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
/** Whether it runs, and a fresh cdpUrl when it does. */
|
|
34
|
+
get: (options) => t.json({ method: "GET", path: base(), ...options }),
|
|
35
|
+
stop: (options) => t.json({ method: "POST", path: `${base()}:stop`, ...options }),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -115,8 +115,8 @@ export declare function sandboxDesktop(t: Transport, sandbox: Sandbox): {
|
|
|
115
115
|
focus: (windowId: string, options?: RequestOptions) => Promise<{
|
|
116
116
|
ok: true;
|
|
117
117
|
}>;
|
|
118
|
-
/** Opens `url` in
|
|
119
|
-
* start,
|
|
118
|
+
/** Opens `url` in Chromium on the desktop. Right after a sandbox's first
|
|
119
|
+
* start, Chromium may still be installing; this waits for it. */
|
|
120
120
|
open(url: string, options?: RequestOptions): Promise<{
|
|
121
121
|
ok: true;
|
|
122
122
|
}>;
|
package/dist/products/desktop.js
CHANGED
|
@@ -50,8 +50,8 @@ export function sandboxDesktop(t, sandbox) {
|
|
|
50
50
|
cursor: (options) => act({ action: "cursor" }, options),
|
|
51
51
|
windows: async (options) => (await act({ action: "windows" }, options)).windows,
|
|
52
52
|
focus: (windowId, options) => act({ action: "focus", windowId }, options),
|
|
53
|
-
/** Opens `url` in
|
|
54
|
-
* start,
|
|
53
|
+
/** Opens `url` in Chromium on the desktop. Right after a sandbox's first
|
|
54
|
+
* start, Chromium may still be installing; this waits for it. */
|
|
55
55
|
async open(url, options) {
|
|
56
56
|
const deadline = Date.now() + 600_000;
|
|
57
57
|
for (;;) {
|
|
@@ -212,7 +212,9 @@ export declare function images(t: Transport): {
|
|
|
212
212
|
/** Point `tag` of the image's name at this version. */
|
|
213
213
|
tag(ref: string, tag: string, options?: RequestOptions): Promise<Image>;
|
|
214
214
|
untag(ref: string, tag: string, options?: RequestOptions): Promise<Image>;
|
|
215
|
-
/** Delete one version (by id, name:tag or name@version) and its tags.
|
|
215
|
+
/** Delete one version (by id, name:tag or name@version) and its tags. A
|
|
216
|
+
* bare name deletes its latest tag's version, or its only version when
|
|
217
|
+
* it has one and no latest tag; with several, the error names its tags. */
|
|
216
218
|
delete(ref: string, options?: RequestOptions): Promise<Image>;
|
|
217
219
|
/** Credentials for private registries. The secret is sealed on arrival
|
|
218
220
|
* and never returned. */
|
package/dist/products/images.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RuntimeError } from "../errors.js";
|
|
1
2
|
import { Page } from "../page.js";
|
|
2
3
|
const UUID = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i;
|
|
3
4
|
const PARALLEL_UPLOADS = 4;
|
|
@@ -189,11 +190,22 @@ export function images(t) {
|
|
|
189
190
|
...options,
|
|
190
191
|
});
|
|
191
192
|
},
|
|
192
|
-
/** Delete one version (by id, name:tag or name@version) and its tags.
|
|
193
|
+
/** Delete one version (by id, name:tag or name@version) and its tags. A
|
|
194
|
+
* bare name deletes its latest tag's version, or its only version when
|
|
195
|
+
* it has one and no latest tag; with several, the error names its tags. */
|
|
193
196
|
async delete(ref, options) {
|
|
197
|
+
const id = await idOf(ref, options).catch(async (error) => {
|
|
198
|
+
if (!(error instanceof RuntimeError && error.code === "image_not_found") ||
|
|
199
|
+
/[:@]/.test(ref))
|
|
200
|
+
throw error;
|
|
201
|
+
const live = (await list({ name: ref, limit: 100 }, options)).data.filter((image) => image.state !== "deleted" && image.state !== "deleting");
|
|
202
|
+
if (live.length !== 1)
|
|
203
|
+
throw error;
|
|
204
|
+
return live[0].id;
|
|
205
|
+
});
|
|
194
206
|
return t.json({
|
|
195
207
|
method: "POST",
|
|
196
|
-
path: `/v1/images/${enc(
|
|
208
|
+
path: `/v1/images/${enc(id)}:delete`,
|
|
197
209
|
body: {},
|
|
198
210
|
...options,
|
|
199
211
|
});
|
package/dist/products/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Transport } from "../transport.js";
|
|
|
2
2
|
import type { Sandbox } from "../sandbox.js";
|
|
3
3
|
import { images } from "./images.js";
|
|
4
4
|
import { sandboxDesktop } from "./desktop.js";
|
|
5
|
+
import { sandboxBrowser } from "./browser.js";
|
|
5
6
|
import { sandboxInterpreter } from "./interpreter.js";
|
|
6
7
|
import { sandboxNetwork } from "./network.js";
|
|
7
8
|
import { addresses, domains, network, ports, tunnel } from "./network-products.js";
|
|
@@ -55,6 +56,7 @@ export declare const sandboxExtensions: {
|
|
|
55
56
|
previews: typeof sandboxPreviews;
|
|
56
57
|
network: typeof sandboxNetwork;
|
|
57
58
|
desktop: typeof sandboxDesktop;
|
|
59
|
+
browser: typeof sandboxBrowser;
|
|
58
60
|
mounts: typeof sandboxMounts;
|
|
59
61
|
tailscale: typeof sandboxTailscale;
|
|
60
62
|
metrics: typeof sandboxMetrics;
|
package/dist/products/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { images } from "./images.js";
|
|
2
2
|
import { sandboxDesktop } from "./desktop.js";
|
|
3
|
+
import { sandboxBrowser } from "./browser.js";
|
|
3
4
|
import { sandboxInterpreter } from "./interpreter.js";
|
|
4
5
|
import { sandboxNetwork } from "./network.js";
|
|
5
6
|
import { addresses, domains, network, ports, tunnel } from "./network-products.js";
|
|
@@ -68,6 +69,7 @@ export const sandboxExtensions = {
|
|
|
68
69
|
previews: sandboxPreviews,
|
|
69
70
|
network: sandboxNetwork,
|
|
70
71
|
desktop: sandboxDesktop,
|
|
72
|
+
browser: sandboxBrowser,
|
|
71
73
|
mounts: sandboxMounts,
|
|
72
74
|
tailscale: sandboxTailscale,
|
|
73
75
|
metrics: sandboxMetrics,
|
|
@@ -195,6 +195,13 @@ export type SetUpstreamProxy = {
|
|
|
195
195
|
* logs apply. A proxy that refuses or cannot be reached fails the connection
|
|
196
196
|
* (upstream-proxy-failed); nothing goes around it. Paid accounts only. */
|
|
197
197
|
export declare function network(t: Transport): {
|
|
198
|
+
/** Your sandboxes reaching each other by name (`private-network.ts`). */
|
|
199
|
+
private: {
|
|
200
|
+
get: (options?: RequestOptions) => Promise<import("./private-network.js").PrivateNetwork>;
|
|
201
|
+
set: (input: {
|
|
202
|
+
enabled: boolean;
|
|
203
|
+
}, options?: RequestOptions) => Promise<import("./private-network.js").PrivateNetwork>;
|
|
204
|
+
};
|
|
198
205
|
upstreamProxy: {
|
|
199
206
|
/** Send outbound connections through your proxy, replacing any set before. */
|
|
200
207
|
set: (input: SetUpstreamProxy, options?: RequestOptions) => Promise<UpstreamProxy & {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { privateNetwork } from "./private-network.js";
|
|
1
2
|
const enc = encodeURIComponent;
|
|
2
3
|
/** `runtime.domains`: serve a sandbox's port at your own hostname, with HTTPS. */
|
|
3
4
|
export function domains(t) {
|
|
@@ -91,6 +92,8 @@ export function tunnel(t) {
|
|
|
91
92
|
export function network(t) {
|
|
92
93
|
const path = "/v1/network/upstream-proxy";
|
|
93
94
|
return {
|
|
95
|
+
/** Your sandboxes reaching each other by name (`private-network.ts`). */
|
|
96
|
+
private: privateNetwork(t),
|
|
94
97
|
upstreamProxy: {
|
|
95
98
|
/** Send outbound connections through your proxy, replacing any set before. */
|
|
96
99
|
set: (input, options) => t.json({
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RequestOptions, Transport } from "../transport.js";
|
|
2
|
+
export type PrivateNetwork = {
|
|
3
|
+
/** Whether your sandboxes reach each other by name now. */
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
/** `sandbox.internal`. */
|
|
6
|
+
suffix: string;
|
|
7
|
+
/** Whether this account may turn it on: paid accounts only. */
|
|
8
|
+
allowed: boolean;
|
|
9
|
+
/** Why not, when `allowed` is false: `not_paid`, `revoked` or `suspended`. */
|
|
10
|
+
why: string | null;
|
|
11
|
+
enabledAt: string | null;
|
|
12
|
+
disabledAt: string | null;
|
|
13
|
+
};
|
|
14
|
+
export declare function privateNetwork(t: Transport): {
|
|
15
|
+
/** On or off, and whether this account may turn it on. */
|
|
16
|
+
get: (options?: RequestOptions) => Promise<PrivateNetwork>;
|
|
17
|
+
/** `enabled: true` lets your sandboxes reach each other by name; `false`
|
|
18
|
+
* stops it and cuts open connections between them within seconds. */
|
|
19
|
+
set: (input: {
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
}, options?: RequestOptions) => Promise<PrivateNetwork>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function privateNetwork(t) {
|
|
2
|
+
const path = "/v1/network/private";
|
|
3
|
+
return {
|
|
4
|
+
/** On or off, and whether this account may turn it on. */
|
|
5
|
+
get: (options) => t.json({ method: "GET", path, ...options }),
|
|
6
|
+
/** `enabled: true` lets your sandboxes reach each other by name; `false`
|
|
7
|
+
* stops it and cuts open connections between them within seconds. */
|
|
8
|
+
set: (input, options) => t.json({ method: "PUT", path, body: input, ...options }),
|
|
9
|
+
};
|
|
10
|
+
}
|
package/dist/sandbox.d.ts
CHANGED
|
@@ -127,6 +127,21 @@ export declare class Sandbox implements AsyncDisposable {
|
|
|
127
127
|
switchImage(image: string, options: RequestOptions & {
|
|
128
128
|
keep: "workspace";
|
|
129
129
|
}): Promise<this>;
|
|
130
|
+
/** Gives it more or fewer vCPUs or more or less memory by a restart: its id,
|
|
131
|
+
* whole disk, volumes, environment, name and previews stay, and its
|
|
132
|
+
* programs stop, which `restart: true` says you know (snapshot it first to
|
|
133
|
+
* keep its memory too). A running sandbox is paused, or stopped if it is
|
|
134
|
+
* persistent, and comes back running at the new size on the same server; a
|
|
135
|
+
* paused or stopped one is started. Memory bills on the new size from then.
|
|
136
|
+
* Refused, with nothing changed, when the server has no room
|
|
137
|
+
* (`no_capacity`), above your quota or the trial's 2 vCPU and 4 GiB, or
|
|
138
|
+
* while a snapshot or fork of it is being taken. */
|
|
139
|
+
resize(size: {
|
|
140
|
+
vcpu?: number;
|
|
141
|
+
memoryMiB?: number;
|
|
142
|
+
}, options: RequestOptions & {
|
|
143
|
+
restart: true;
|
|
144
|
+
}): Promise<this>;
|
|
130
145
|
/** Keeps a running sandbox's lease ahead of now, in the background, until
|
|
131
146
|
* stop() or the returned function ends it: every `everySeconds` (60) it
|
|
132
147
|
* extends the lease so that `marginSeconds` (600) remain, never more than
|
|
@@ -229,6 +244,13 @@ export declare class Process {
|
|
|
229
244
|
info: ProcessInfo;
|
|
230
245
|
constructor(t: Transport, sandboxId: string, info: ProcessInfo);
|
|
231
246
|
get id(): string;
|
|
247
|
+
/** The command line as the sandbox reports it. */
|
|
248
|
+
get command(): string;
|
|
249
|
+
/** As of the last answer: spawn, `wait()` or `refresh()`. */
|
|
250
|
+
get state(): ProcessInfo["state"];
|
|
251
|
+
/** null while it runs, and when it was killed or timed out. */
|
|
252
|
+
get exitCode(): number | null;
|
|
253
|
+
toJSON(): ProcessInfo;
|
|
232
254
|
/** Every output event from the start (or `cursor`) until exit. */
|
|
233
255
|
output(options?: {
|
|
234
256
|
cursor?: number;
|
package/dist/sandbox.js
CHANGED
|
@@ -427,6 +427,27 @@ export class Sandbox {
|
|
|
427
427
|
}));
|
|
428
428
|
return this;
|
|
429
429
|
}
|
|
430
|
+
/** Gives it more or fewer vCPUs or more or less memory by a restart: its id,
|
|
431
|
+
* whole disk, volumes, environment, name and previews stay, and its
|
|
432
|
+
* programs stop, which `restart: true` says you know (snapshot it first to
|
|
433
|
+
* keep its memory too). A running sandbox is paused, or stopped if it is
|
|
434
|
+
* persistent, and comes back running at the new size on the same server; a
|
|
435
|
+
* paused or stopped one is started. Memory bills on the new size from then.
|
|
436
|
+
* Refused, with nothing changed, when the server has no room
|
|
437
|
+
* (`no_capacity`), above your quota or the trial's 2 vCPU and 4 GiB, or
|
|
438
|
+
* while a snapshot or fork of it is being taken. */
|
|
439
|
+
async resize(size, options) {
|
|
440
|
+
const { restart, ...rest } = options;
|
|
441
|
+
this.#keep(await this.#t.json({
|
|
442
|
+
method: "POST",
|
|
443
|
+
path: `/v1/sandboxes/${enc(this.id)}:resize`,
|
|
444
|
+
body: { ...size, restart },
|
|
445
|
+
// A pause or stop and a cold boot.
|
|
446
|
+
wait: 120,
|
|
447
|
+
...pick(rest),
|
|
448
|
+
}));
|
|
449
|
+
return this;
|
|
450
|
+
}
|
|
430
451
|
/** Keeps a running sandbox's lease ahead of now, in the background, until
|
|
431
452
|
* stop() or the returned function ends it: every `everySeconds` (60) it
|
|
432
453
|
* extends the lease so that `marginSeconds` (600) remain, never more than
|
|
@@ -839,6 +860,26 @@ export class Process {
|
|
|
839
860
|
get id() {
|
|
840
861
|
return this.info.id;
|
|
841
862
|
}
|
|
863
|
+
/** The command line as the sandbox reports it. */
|
|
864
|
+
get command() {
|
|
865
|
+
return this.info.command;
|
|
866
|
+
}
|
|
867
|
+
/** As of the last answer: spawn, `wait()` or `refresh()`. */
|
|
868
|
+
get state() {
|
|
869
|
+
return this.info.state;
|
|
870
|
+
}
|
|
871
|
+
/** null while it runs, and when it was killed or timed out. */
|
|
872
|
+
get exitCode() {
|
|
873
|
+
return this.info.exitCode;
|
|
874
|
+
}
|
|
875
|
+
toJSON() {
|
|
876
|
+
return this.info;
|
|
877
|
+
}
|
|
878
|
+
/** console.log shows what the process is, not the client inside it. */
|
|
879
|
+
[Symbol.for("nodejs.util.inspect.custom")](_depth, options, show) {
|
|
880
|
+
const { id, sandboxId, command, state, exitCode } = this;
|
|
881
|
+
return `Process ${show({ id, sandboxId, command, state, exitCode }, options)}`;
|
|
882
|
+
}
|
|
842
883
|
/** Every output event from the start (or `cursor`) until exit. */
|
|
843
884
|
output(options = {}) {
|
|
844
885
|
return new Processes(this.t, this.sandboxId).follow(this.id, options);
|
|
@@ -884,6 +925,12 @@ export class Process {
|
|
|
884
925
|
if (event.type === "exit")
|
|
885
926
|
exit = event;
|
|
886
927
|
}
|
|
928
|
+
if (exit)
|
|
929
|
+
this.info = {
|
|
930
|
+
...this.info,
|
|
931
|
+
state: exit.state,
|
|
932
|
+
exitCode: exit.exitCode,
|
|
933
|
+
};
|
|
887
934
|
return {
|
|
888
935
|
exitCode: exit?.exitCode ?? null,
|
|
889
936
|
...out,
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RuntimeError } from "./errors.js";
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.11.0";
|
|
3
3
|
export declare const DEFAULT_BASE_URL = "https://api.withruntime.com";
|
|
4
4
|
/** Runtime's API as code inside a Runtime sandbox reaches it: the sandbox's
|
|
5
5
|
* own host sends each request on to DEFAULT_BASE_URL over HTTPS. The API runs
|
package/dist/transport.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConnectionError, DELIBERATE, errorFor, RuntimeError, WAITS_FOR_ROOM } from "./errors.js";
|
|
2
2
|
import { describeRoute, envFetch, openWebSocket } from "./proxy.js";
|
|
3
|
-
export const VERSION = "0.
|
|
3
|
+
export const VERSION = "0.11.0";
|
|
4
4
|
export const DEFAULT_BASE_URL = "https://api.withruntime.com";
|
|
5
5
|
/** Runtime's API as code inside a Runtime sandbox reaches it: the sandbox's
|
|
6
6
|
* own host sends each request on to DEFAULT_BASE_URL over HTTPS. The API runs
|
package/dist/types.d.ts
CHANGED
|
@@ -42,8 +42,9 @@ export type SandboxInfo = {
|
|
|
42
42
|
/** The names of its own environment variables (`env`), on a create, an
|
|
43
43
|
* update and a read of one sandbox. Values are never shown. */
|
|
44
44
|
envNames?: string[];
|
|
45
|
-
/** On a create from an image with a start command: whether it started
|
|
46
|
-
*
|
|
45
|
+
/** On a create from an image with a start command: whether it started
|
|
46
|
+
* (and was still running half a second later), became ready (readyMs),
|
|
47
|
+
* timed out, or exited first (exitCode, and stderr's last lines). The create's answer
|
|
47
48
|
* alone carries it, and the Sandbox that create returned keeps it through
|
|
48
49
|
* later reads; `sandboxes.get` and `list` have none, because the API keeps
|
|
49
50
|
* no record of it. */
|
|
@@ -52,6 +53,8 @@ export type SandboxInfo = {
|
|
|
52
53
|
processId?: string;
|
|
53
54
|
exitCode?: number | null;
|
|
54
55
|
readyMs?: number;
|
|
56
|
+
/** With exited: the last lines the start command wrote to stderr. */
|
|
57
|
+
stderr?: string;
|
|
55
58
|
};
|
|
56
59
|
/** Present and true when getOrCreate answered a sandbox that already held the name. */
|
|
57
60
|
reused?: boolean;
|
package/dist/vercel/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { Sandbox, DEFAULT_TIMEOUT_MS, DEFAULT_VCPUS, MEMORY_MIB_PER_VCPU, networkRules, toRuntimePath, type CreateSandboxParams, type RunCommandParams, type NetworkPolicy, type SandboxRoute, } from "./sandbox.js";
|
|
2
2
|
export { Command, CommandFinished, type CommandOutput, type LogOutputLine, type Signal, } from "./command.js";
|
|
3
3
|
export { FileSystem, Stats, Dirent } from "./filesystem.js";
|
|
4
|
+
export { SandboxUser, SandboxUserAlreadyExistsError } from "./sandbox-user.js";
|
|
4
5
|
export { Snapshot } from "./snapshot.js";
|
|
5
6
|
export { APIError, StreamError, AuthenticationError, NotSupportedError } from "./errors.js";
|
|
6
7
|
export type { Credentials, WithRuntime } from "./client.js";
|
|
@@ -16,13 +17,6 @@ export declare const Session: {
|
|
|
16
17
|
new (...args: unknown[]): never;
|
|
17
18
|
readonly [key: string]: (...args: unknown[]) => never;
|
|
18
19
|
};
|
|
19
|
-
export declare const SandboxUser: {
|
|
20
|
-
(...args: unknown[]): never;
|
|
21
|
-
new (...args: unknown[]): never;
|
|
22
|
-
readonly [key: string]: (...args: unknown[]) => never;
|
|
23
|
-
};
|
|
24
|
-
export declare class SandboxUserAlreadyExistsError extends Error {
|
|
25
|
-
}
|
|
26
20
|
export declare const defineSandboxProxy: {
|
|
27
21
|
(...args: unknown[]): never;
|
|
28
22
|
new (...args: unknown[]): never;
|
package/dist/vercel/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { NotSupportedError } from "./errors.js";
|
|
|
9
9
|
export { Sandbox, DEFAULT_TIMEOUT_MS, DEFAULT_VCPUS, MEMORY_MIB_PER_VCPU, networkRules, toRuntimePath, } from "./sandbox.js";
|
|
10
10
|
export { Command, CommandFinished, } from "./command.js";
|
|
11
11
|
export { FileSystem, Stats, Dirent } from "./filesystem.js";
|
|
12
|
+
export { SandboxUser, SandboxUserAlreadyExistsError } from "./sandbox-user.js";
|
|
12
13
|
export { Snapshot } from "./snapshot.js";
|
|
13
14
|
export { APIError, StreamError, AuthenticationError, NotSupportedError } from "./errors.js";
|
|
14
15
|
/** Vercel's default region; Runtime runs in one US region. */
|
|
@@ -32,7 +33,4 @@ function unsupportedExport(name, alternative) {
|
|
|
32
33
|
}
|
|
33
34
|
export const Drive = unsupportedExport("Drive", "Use a Runtime volume (runtime.volumes) and mount it with withruntime: { create: { volumes: [{ volumeId, path }] } }.");
|
|
34
35
|
export const Session = unsupportedExport("Session", "A Runtime sandbox is its own session: call the methods on the sandbox.");
|
|
35
|
-
export const SandboxUser = unsupportedExport("SandboxUser", "Commands run as the sandbox owner with passwordless sudo; create users with `sudo useradd` in runCommand.");
|
|
36
|
-
export class SandboxUserAlreadyExistsError extends Error {
|
|
37
|
-
}
|
|
38
36
|
export const defineSandboxProxy = unsupportedExport("sandbox proxy (defineSandboxProxy)", "Share a port with sandbox.withruntime.previews.create(port) instead.");
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Command, CommandFinished } from "./command.js";
|
|
2
|
+
import type { RunCommandParams, Sandbox } from "./sandbox.js";
|
|
3
|
+
/** A Linux user or group name Vercel accepts, which is also safe to pass to
|
|
4
|
+
* useradd, groupadd and sudo. */
|
|
5
|
+
export declare function validateName(name: string, kind: string): void;
|
|
6
|
+
/** Thrown when `sandbox.createUser` is called for an existing username. */
|
|
7
|
+
export declare class SandboxUserAlreadyExistsError extends Error {
|
|
8
|
+
readonly username: string;
|
|
9
|
+
constructor(username: string);
|
|
10
|
+
}
|
|
11
|
+
type Signal = {
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
};
|
|
14
|
+
/** A user in a sandbox, made with `sandbox.createUser` or found with
|
|
15
|
+
* `sandbox.asUser`. Commands and file calls run as this user. */
|
|
16
|
+
export declare class SandboxUser {
|
|
17
|
+
#private;
|
|
18
|
+
readonly username: string;
|
|
19
|
+
/** `/root` for root, else `/home/<username>`. */
|
|
20
|
+
readonly homeDir: string;
|
|
21
|
+
/** Use sandbox.createUser or sandbox.asUser. */
|
|
22
|
+
constructor({ sandbox, username }: {
|
|
23
|
+
sandbox: Sandbox;
|
|
24
|
+
username: string;
|
|
25
|
+
});
|
|
26
|
+
/** Runs a command as this user. `sudo: true` runs it as root instead. */
|
|
27
|
+
runCommand(command: string, args?: string[], opts?: {
|
|
28
|
+
signal?: AbortSignal;
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
}): Promise<CommandFinished>;
|
|
31
|
+
runCommand(params: RunCommandParams & {
|
|
32
|
+
detached: true;
|
|
33
|
+
}): Promise<Command>;
|
|
34
|
+
runCommand(params: RunCommandParams): Promise<CommandFinished>;
|
|
35
|
+
/** Writes files into this user's home (or absolute paths), then gives them
|
|
36
|
+
* and the directories made for them to this user. */
|
|
37
|
+
writeFiles(files: {
|
|
38
|
+
path: string;
|
|
39
|
+
content: string | Uint8Array;
|
|
40
|
+
mode?: number;
|
|
41
|
+
}[], opts?: Signal): Promise<void>;
|
|
42
|
+
/** The file as this user may read it, as a stream; null when missing. */
|
|
43
|
+
readFile(file: {
|
|
44
|
+
path: string;
|
|
45
|
+
cwd?: string;
|
|
46
|
+
}, opts?: Signal): Promise<NodeJS.ReadableStream | null>;
|
|
47
|
+
/** The file as this user may read it; null when missing. */
|
|
48
|
+
readFileToBuffer(file: {
|
|
49
|
+
path: string;
|
|
50
|
+
cwd?: string;
|
|
51
|
+
}, opts?: Signal): Promise<Buffer | null>;
|
|
52
|
+
/** Copies a file this user may read to the local disk; null when missing. */
|
|
53
|
+
downloadFile(src: {
|
|
54
|
+
path: string;
|
|
55
|
+
cwd?: string;
|
|
56
|
+
}, dst: {
|
|
57
|
+
path: string;
|
|
58
|
+
cwd?: string;
|
|
59
|
+
}, opts?: {
|
|
60
|
+
mkdirRecursive?: boolean;
|
|
61
|
+
signal?: AbortSignal;
|
|
62
|
+
}): Promise<string | null>;
|
|
63
|
+
/** Makes a directory owned by this user. */
|
|
64
|
+
mkDir(path: string, opts?: Signal): Promise<void>;
|
|
65
|
+
addToGroup(groupname: string, opts?: Signal): Promise<void>;
|
|
66
|
+
removeFromGroup(groupname: string, opts?: Signal): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
/** Runs `cmd args` under sudo; a non-zero exit throws `what(): <stderr>`. */
|
|
69
|
+
export declare function rootOrThrow(sandbox: Sandbox, cmd: string, args: string[], signal: AbortSignal | undefined, what: () => string): Promise<CommandFinished>;
|
|
70
|
+
export {};
|