withruntime 0.5.1 → 0.6.1

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 (47) hide show
  1. package/LICENSE +55 -0
  2. package/README.md +8 -4
  3. package/dist/ai-harness/index.d.ts +194 -0
  4. package/dist/ai-harness/index.js +504 -0
  5. package/dist/cli-extras.d.ts +24 -0
  6. package/dist/cli-extras.js +205 -0
  7. package/dist/cli.d.ts +20 -0
  8. package/dist/cli.js +403 -28
  9. package/dist/e2b/filesystem.d.ts +26 -1
  10. package/dist/e2b/filesystem.js +30 -2
  11. package/dist/e2b/index.d.ts +1 -1
  12. package/dist/e2b/index.js +1 -1
  13. package/dist/errors.js +2 -0
  14. package/dist/identity.d.ts +27 -0
  15. package/dist/identity.js +56 -0
  16. package/dist/index.d.ts +14 -0
  17. package/dist/index.js +7 -0
  18. package/dist/mcp.js +16 -3
  19. package/dist/network-cli.d.ts +15 -0
  20. package/dist/network-cli.js +323 -0
  21. package/dist/products/desktop.d.ts +41 -4
  22. package/dist/products/desktop.js +73 -3
  23. package/dist/products/index.d.ts +12 -0
  24. package/dist/products/index.js +12 -0
  25. package/dist/products/interpreter.d.ts +5 -3
  26. package/dist/products/interpreter.js +2 -1
  27. package/dist/products/mcp.d.ts +79 -0
  28. package/dist/products/mcp.js +37 -0
  29. package/dist/products/mounts.d.ts +49 -0
  30. package/dist/products/mounts.js +21 -0
  31. package/dist/products/network-products.d.ts +167 -0
  32. package/dist/products/network-products.js +82 -0
  33. package/dist/products/network.d.ts +1 -1
  34. package/dist/products/sso.d.ts +44 -0
  35. package/dist/products/sso.js +8 -0
  36. package/dist/products/volumes.d.ts +68 -5
  37. package/dist/products/volumes.js +52 -4
  38. package/dist/products/watch.d.ts +91 -0
  39. package/dist/products/watch.js +135 -0
  40. package/dist/sandbox.d.ts +32 -2
  41. package/dist/sandbox.js +93 -16
  42. package/dist/snapshots.d.ts +11 -1
  43. package/dist/transport.d.ts +1 -1
  44. package/dist/transport.js +4 -1
  45. package/dist/wireguard.d.ts +7 -0
  46. package/dist/wireguard.js +13 -0
  47. package/package.json +49 -18
@@ -21,6 +21,27 @@ export type DesktopStart = {
21
21
  streamUrl: string;
22
22
  preview: Preview;
23
23
  };
24
+ export type DesktopRecording = {
25
+ id: string;
26
+ state: "starting" | "installing" | "recording" | "finished" | "failed";
27
+ /** The MP4 file in the sandbox. */
28
+ path: string;
29
+ bytes: number;
30
+ seconds?: number;
31
+ /** Why it ended: stopped, max-seconds, max-bytes, disk-low, desktop-gone, error. */
32
+ reason: string | null;
33
+ startedAt?: number | null;
34
+ };
35
+ export type RecordOptions = {
36
+ /** Frames a second, 1 to 30. Default 10. */
37
+ fps?: number;
38
+ /** Stop after this much video, up to 7200. Default 1800. */
39
+ maxSeconds?: number;
40
+ /** The file never grows past this, 16 to 4096. Default 512. */
41
+ maxMiB?: number;
42
+ /** Quality, 18 (sharp, large) to 45 (small). Default 30. */
43
+ crf?: number;
44
+ };
24
45
  /** `sbx.desktop`: a Linux desktop in the sandbox, driven like a person would.
25
46
  *
26
47
  * const { streamUrl } = await sbx.desktop.start();
@@ -31,10 +52,12 @@ export type DesktopStart = {
31
52
  *
32
53
  * Coordinates are pixels from the top left of the screen. */
33
54
  export declare function sandboxDesktop(t: Transport, sandbox: Sandbox): {
34
- start: (size?: {
55
+ /** Starts the desktop. The first start in a sandbox installs it, which
56
+ * takes a minute or two; this waits for that (up to 10 minutes). */
57
+ start(size?: {
35
58
  width?: number;
36
59
  height?: number;
37
- }, options?: RequestOptions) => Promise<DesktopStart>;
60
+ }, options?: RequestOptions): Promise<DesktopStart>;
38
61
  stop: (options?: RequestOptions) => Promise<{
39
62
  ok: boolean;
40
63
  }>;
@@ -92,12 +115,26 @@ export declare function sandboxDesktop(t: Transport, sandbox: Sandbox): {
92
115
  focus: (windowId: string, options?: RequestOptions) => Promise<{
93
116
  ok: true;
94
117
  }>;
95
- /** Opens `url` in Firefox on the desktop. */
96
- open: (url: string, options?: RequestOptions) => Promise<{
118
+ /** Opens `url` in Firefox on the desktop. Right after a sandbox's first
119
+ * start, Firefox may still be installing; this waits for it. */
120
+ open(url: string, options?: RequestOptions): Promise<{
97
121
  ok: true;
98
122
  }>;
99
123
  /** Starts a program on the desktop, detached. */
100
124
  launch: (argv: string[], options?: RequestOptions) => Promise<{
101
125
  ok: true;
102
126
  }>;
127
+ /** Screen recordings to MP4: `const rec = await sbx.desktop.recordings.start();`
128
+ * ... `await sbx.desktop.recordings.stop(rec.id)`, then `download(rec.id)`. */
129
+ recordings: {
130
+ start: (input?: RecordOptions, options?: RequestOptions) => Promise<DesktopRecording>;
131
+ stop: (id: string, options?: RequestOptions) => Promise<DesktopRecording>;
132
+ get: (id: string, options?: RequestOptions) => Promise<DesktopRecording>;
133
+ list: (options?: RequestOptions) => Promise<DesktopRecording[]>;
134
+ /** The MP4 bytes. */
135
+ download: (id: string, options?: RequestOptions) => Promise<Uint8Array<ArrayBufferLike>>;
136
+ delete: (id: string, options?: RequestOptions) => Promise<{
137
+ deleted: boolean;
138
+ }>;
139
+ };
103
140
  };
@@ -11,7 +11,27 @@ export function sandboxDesktop(t, sandbox) {
11
11
  const base = () => `/v1/sandboxes/${encodeURIComponent(sandbox.id)}/desktop`;
12
12
  const act = (body, options) => t.json({ method: "POST", path: `${base()}:act`, body, ...options });
13
13
  return {
14
- start: (size = {}, options) => t.json({ method: "POST", path: `${base()}:start`, body: size, ...options }),
14
+ /** Starts the desktop. The first start in a sandbox installs it, which
15
+ * takes a minute or two; this waits for that (up to 10 minutes). */
16
+ async start(size = {}, options) {
17
+ const deadline = Date.now() + 600_000;
18
+ for (;;) {
19
+ try {
20
+ return await t.json({
21
+ method: "POST",
22
+ path: `${base()}:start`,
23
+ body: size,
24
+ ...options,
25
+ });
26
+ }
27
+ catch (error) {
28
+ const code = error.code;
29
+ if (code !== "desktop_installing" || Date.now() > deadline)
30
+ throw error;
31
+ await new Promise((resolve) => setTimeout(resolve, error.retryAfterMs ?? 10_000));
32
+ }
33
+ }
34
+ },
15
35
  stop: (options) => t.json({ method: "POST", path: `${base()}:stop`, ...options }),
16
36
  /** PNG bytes, or JPEG with `format: "jpeg"`. */
17
37
  screenshot: (input = {}, options) => t.bytes({ method: "GET", path: `${base()}/screenshot`, query: input, ...options }),
@@ -30,9 +50,59 @@ export function sandboxDesktop(t, sandbox) {
30
50
  cursor: (options) => act({ action: "cursor" }, options),
31
51
  windows: async (options) => (await act({ action: "windows" }, options)).windows,
32
52
  focus: (windowId, options) => act({ action: "focus", windowId }, options),
33
- /** Opens `url` in Firefox on the desktop. */
34
- open: (url, options) => act({ action: "open", url }, options),
53
+ /** Opens `url` in Firefox on the desktop. Right after a sandbox's first
54
+ * start, Firefox may still be installing; this waits for it. */
55
+ async open(url, options) {
56
+ const deadline = Date.now() + 600_000;
57
+ for (;;) {
58
+ try {
59
+ return await act({ action: "open", url }, options);
60
+ }
61
+ catch (error) {
62
+ const code = error.code;
63
+ if (code !== "desktop_installing" || Date.now() > deadline)
64
+ throw error;
65
+ await new Promise((resolve) => setTimeout(resolve, error.retryAfterMs ?? 10_000));
66
+ }
67
+ }
68
+ },
35
69
  /** Starts a program on the desktop, detached. */
36
70
  launch: (argv, options) => act({ action: "launch", argv }, options),
71
+ /** Screen recordings to MP4: `const rec = await sbx.desktop.recordings.start();`
72
+ * ... `await sbx.desktop.recordings.stop(rec.id)`, then `download(rec.id)`. */
73
+ recordings: {
74
+ start: (input = {}, options) => t.json({
75
+ method: "POST",
76
+ path: `${base()}/recordings`,
77
+ body: input,
78
+ ...options,
79
+ }),
80
+ stop: (id, options) => t.json({
81
+ method: "POST",
82
+ path: `${base()}/recordings/${encodeURIComponent(id)}:stop`,
83
+ ...options,
84
+ }),
85
+ get: (id, options) => t.json({
86
+ method: "GET",
87
+ path: `${base()}/recordings/${encodeURIComponent(id)}`,
88
+ ...options,
89
+ }),
90
+ list: async (options) => (await t.json({
91
+ method: "GET",
92
+ path: `${base()}/recordings`,
93
+ ...options,
94
+ })).data,
95
+ /** The MP4 bytes. */
96
+ download: (id, options) => t.bytes({
97
+ method: "GET",
98
+ path: `${base()}/recordings/${encodeURIComponent(id)}/video`,
99
+ ...options,
100
+ }),
101
+ delete: (id, options) => t.json({
102
+ method: "DELETE",
103
+ path: `${base()}/recordings/${encodeURIComponent(id)}`,
104
+ ...options,
105
+ }),
106
+ },
37
107
  };
38
108
  }
@@ -4,13 +4,17 @@ import { images } from "./images.js";
4
4
  import { sandboxDesktop } from "./desktop.js";
5
5
  import { sandboxInterpreter } from "./interpreter.js";
6
6
  import { sandboxNetwork } from "./network.js";
7
+ import { addresses, domains, ports, tunnel } from "./network-products.js";
7
8
  import { sandboxPreviews } from "./previews.js";
8
9
  import { referrals } from "./referrals.js";
9
10
  import { audit } from "./audit.js";
11
+ import { sso } from "./sso.js";
10
12
  import { switching } from "./switching.js";
11
13
  import { limits } from "./limits.js";
12
14
  import { volumes } from "./volumes.js";
15
+ import { sandboxMounts } from "./mounts.js";
13
16
  import { secrets } from "./secrets.js";
17
+ import { mcp, sandboxMcp } from "./mcp.js";
14
18
  import { events, otel, sandboxMetrics, webhooks } from "./observability.js";
15
19
  export declare const clientExtensions: {
16
20
  images: typeof images;
@@ -23,13 +27,21 @@ export declare const clientExtensions: {
23
27
  otel: typeof otel;
24
28
  events: typeof events;
25
29
  audit: typeof audit;
30
+ mcp: typeof mcp;
31
+ sso: typeof sso;
32
+ domains: typeof domains;
33
+ ports: typeof ports;
34
+ addresses: typeof addresses;
35
+ tunnel: typeof tunnel;
26
36
  };
27
37
  export declare const sandboxExtensions: {
28
38
  interpreter: typeof sandboxInterpreter;
29
39
  previews: typeof sandboxPreviews;
30
40
  network: typeof sandboxNetwork;
31
41
  desktop: typeof sandboxDesktop;
42
+ mounts: typeof sandboxMounts;
32
43
  metrics: typeof sandboxMetrics;
44
+ mcp: typeof sandboxMcp;
33
45
  };
34
46
  export type ClientExtensions = {
35
47
  readonly [K in keyof typeof clientExtensions]: ReturnType<(typeof clientExtensions)[K]>;
@@ -2,13 +2,17 @@ import { images } from "./images.js";
2
2
  import { sandboxDesktop } from "./desktop.js";
3
3
  import { sandboxInterpreter } from "./interpreter.js";
4
4
  import { sandboxNetwork } from "./network.js";
5
+ import { addresses, domains, ports, tunnel } from "./network-products.js";
5
6
  import { sandboxPreviews } from "./previews.js";
6
7
  import { referrals } from "./referrals.js";
7
8
  import { audit } from "./audit.js";
9
+ import { sso } from "./sso.js";
8
10
  import { switching } from "./switching.js";
9
11
  import { limits } from "./limits.js";
10
12
  import { volumes } from "./volumes.js";
13
+ import { sandboxMounts } from "./mounts.js";
11
14
  import { secrets } from "./secrets.js";
15
+ import { mcp, sandboxMcp } from "./mcp.js";
12
16
  import { events, otel, sandboxMetrics, webhooks } from "./observability.js";
13
17
  /* HOW A LANE ADDS A PRODUCT TO THE SDK
14
18
  *
@@ -36,13 +40,21 @@ export const clientExtensions = {
36
40
  otel,
37
41
  events,
38
42
  audit,
43
+ mcp,
44
+ sso,
45
+ domains,
46
+ ports,
47
+ addresses,
48
+ tunnel,
39
49
  };
40
50
  export const sandboxExtensions = {
41
51
  interpreter: sandboxInterpreter,
42
52
  previews: sandboxPreviews,
43
53
  network: sandboxNetwork,
44
54
  desktop: sandboxDesktop,
55
+ mounts: sandboxMounts,
45
56
  metrics: sandboxMetrics,
57
+ mcp: sandboxMcp,
46
58
  };
47
59
  /** The factories as plain pairs, for the constructors that install them. */
48
60
  export function clientFactories() {
@@ -1,6 +1,6 @@
1
1
  import type { Sandbox } from "../sandbox.js";
2
2
  import type { RequestOptions, Transport } from "../transport.js";
3
- export type InterpreterLanguage = "python" | "javascript";
3
+ export type InterpreterLanguage = "python" | "javascript" | "typescript" | "r" | "java" | "bash" | "go";
4
4
  export type ResultRef = {
5
5
  path: string;
6
6
  bytes: number;
@@ -47,7 +47,8 @@ export type InterpreterContext = {
47
47
  };
48
48
  export type RunOptions = RequestOptions & {
49
49
  language?: InterpreterLanguage;
50
- /** A context id; "python" and "javascript" are the defaults, started on first use. */
50
+ /** A context id; each language's own name ("python", "typescript", "r"...) is
51
+ * its default context, started on first use. */
51
52
  context?: string;
52
53
  timeoutMs?: number;
53
54
  onStdout?: (text: string) => void;
@@ -59,7 +60,8 @@ export type RunOptions = RequestOptions & {
59
60
  traceback: string;
60
61
  }) => void;
61
62
  };
62
- /** A stateful Python and JavaScript interpreter in the sandbox:
63
+ /** A stateful interpreter in the sandbox, in Python, JavaScript, TypeScript,
64
+ * R, Java, Bash or Go:
63
65
  * `await sbx.interpreter.run("import pandas as pd; pd.DataFrame({'a': [1]})")`.
64
66
  * Variables persist between runs of the same context, like a notebook. */
65
67
  export declare function sandboxInterpreter(t: Transport, sandbox: Sandbox): {
@@ -1,4 +1,5 @@
1
- /** A stateful Python and JavaScript interpreter in the sandbox:
1
+ /** A stateful interpreter in the sandbox, in Python, JavaScript, TypeScript,
2
+ * R, Java, Bash or Go:
2
3
  * `await sbx.interpreter.run("import pandas as pd; pd.DataFrame({'a': [1]})")`.
3
4
  * Variables persist between runs of the same context, like a notebook. */
4
5
  export function sandboxInterpreter(t, sandbox) {
@@ -0,0 +1,79 @@
1
+ import type { Sandbox } from "../sandbox.js";
2
+ import type { RequestOptions, Transport } from "../transport.js";
3
+ export type McpCatalogEntry = {
4
+ id: string;
5
+ title: string;
6
+ description: string;
7
+ license: string;
8
+ source: string;
9
+ version: string;
10
+ env: {
11
+ name: string;
12
+ description: string;
13
+ required: boolean;
14
+ secret: boolean;
15
+ hosts?: string[];
16
+ }[];
17
+ options: {
18
+ name: string;
19
+ description: string;
20
+ required: boolean;
21
+ }[];
22
+ egress: string[];
23
+ checked: string;
24
+ };
25
+ export type McpServerRequest = {
26
+ /** A catalog id, e.g. "github". */
27
+ id: string;
28
+ name?: string;
29
+ /** A secret setting to the Runtime secret that fills it. */
30
+ secrets?: Record<string, string>;
31
+ env?: Record<string, string>;
32
+ options?: Record<string, string>;
33
+ } | {
34
+ name: string;
35
+ command: string[];
36
+ env?: Record<string, string>;
37
+ };
38
+ export type McpGateway = {
39
+ running: boolean;
40
+ port: number | null;
41
+ /** Send it as `Authorization: Bearer <token>`. */
42
+ token?: string | null;
43
+ headers?: Record<string, string>;
44
+ urlExpiresAt?: string | null;
45
+ servers: {
46
+ name: string;
47
+ status: "installing" | "ready" | "failed";
48
+ message?: string | null;
49
+ /** Its Streamable HTTP endpoint. */
50
+ url: string | null;
51
+ }[];
52
+ warnings: string[];
53
+ };
54
+ /** `runtime.mcp`: the catalog of MCP servers a sandbox can run. */
55
+ export declare function mcp(t: Transport): {
56
+ catalog: (options?: RequestOptions) => Promise<McpCatalogEntry[]>;
57
+ };
58
+ /** `sbx.mcp`: catalog MCP servers running inside the sandbox, at URLs an
59
+ * agent connects to.
60
+ *
61
+ * const gw = await sbx.mcp.start([{ id: "github", secrets: { GITHUB_PERSONAL_ACCESS_TOKEN: "GITHUB_TOKEN" } }]);
62
+ * // gw.servers[0].url with gw.headers, in any MCP client
63
+ */
64
+ export declare function sandboxMcp(t: Transport, sandbox: Sandbox): {
65
+ start: (servers: McpServerRequest[], input?: {
66
+ port?: number;
67
+ replace?: boolean;
68
+ }, options?: RequestOptions) => Promise<McpGateway>;
69
+ /** Their state, and fresh URLs. */
70
+ get: (options?: RequestOptions) => Promise<McpGateway>;
71
+ /** Wait until every server is ready (or one failed). */
72
+ ready(input?: {
73
+ timeoutMs?: number;
74
+ intervalMs?: number;
75
+ }): Promise<McpGateway>;
76
+ stop: (options?: RequestOptions) => Promise<{
77
+ stopped: boolean;
78
+ }>;
79
+ };
@@ -0,0 +1,37 @@
1
+ /** `runtime.mcp`: the catalog of MCP servers a sandbox can run. */
2
+ export function mcp(t) {
3
+ return {
4
+ catalog: async (options) => (await t.json({
5
+ method: "GET",
6
+ path: "/v1/mcp/catalog",
7
+ ...options,
8
+ })).data,
9
+ };
10
+ }
11
+ /** `sbx.mcp`: catalog MCP servers running inside the sandbox, at URLs an
12
+ * agent connects to.
13
+ *
14
+ * const gw = await sbx.mcp.start([{ id: "github", secrets: { GITHUB_PERSONAL_ACCESS_TOKEN: "GITHUB_TOKEN" } }]);
15
+ * // gw.servers[0].url with gw.headers, in any MCP client
16
+ */
17
+ export function sandboxMcp(t, sandbox) {
18
+ const path = () => `/v1/sandboxes/${encodeURIComponent(sandbox.id)}/mcp`;
19
+ return {
20
+ start: (servers, input = {}, options) => t.json({ method: "POST", path: path(), body: { servers, ...input }, ...options }),
21
+ /** Their state, and fresh URLs. */
22
+ get: (options) => t.json({ method: "GET", path: path(), ...options }),
23
+ /** Wait until every server is ready (or one failed). */
24
+ async ready(input = {}) {
25
+ const deadline = Date.now() + (input.timeoutMs ?? 600_000);
26
+ for (;;) {
27
+ const state = await t.json({ method: "GET", path: path() });
28
+ if (!state.running || state.servers.every((server) => server.status !== "installing"))
29
+ return state;
30
+ if (Date.now() > deadline)
31
+ return state;
32
+ await new Promise((resolve) => setTimeout(resolve, input.intervalMs ?? 2_000));
33
+ }
34
+ },
35
+ stop: (options) => t.json({ method: "DELETE", path: path(), ...options }),
36
+ };
37
+ }
@@ -0,0 +1,49 @@
1
+ import type { Sandbox } from "../sandbox.js";
2
+ import type { RequestOptions, Transport } from "../transport.js";
3
+ /** A bucket mounted in a sandbox. */
4
+ export type Mount = {
5
+ path: string;
6
+ provider: "s3" | "r2" | "gcs";
7
+ bucket: string;
8
+ prefix: string | null;
9
+ /** The endpoint host the sandbox reaches the bucket at. */
10
+ endpoint: string;
11
+ /** The secret whose key the egress proxy signs with; null for a public bucket. */
12
+ secret: string | null;
13
+ readOnly: boolean;
14
+ /** Whether it is mounted right now. */
15
+ mounted: boolean;
16
+ mountedAt?: string;
17
+ };
18
+ export type MountBucket = {
19
+ /** s3 for Amazon S3, or any S3-compatible store with `endpoint`; r2 for
20
+ * Cloudflare R2 (with `accountId`); gcs for Google Cloud Storage (HMAC keys). */
21
+ provider: "s3" | "r2" | "gcs";
22
+ bucket: string;
23
+ /** Where it appears in the sandbox, such as /data. */
24
+ path: string;
25
+ prefix?: string;
26
+ region?: string;
27
+ endpoint?: string;
28
+ accountId?: string;
29
+ /** A secret stored with header `Authorization`, format
30
+ * `AWS4-HMAC-SHA256 {value}` and value `ACCESS_KEY_ID:SECRET_KEY`, naming
31
+ * the endpoint host. The sandbox never sees the key. Omit for a public bucket. */
32
+ secret?: string;
33
+ readOnly?: boolean;
34
+ };
35
+ /** `sbx.mounts`: your own S3, R2 or Google Cloud Storage bucket as a
36
+ * directory in this sandbox.
37
+ *
38
+ * await sbx.mounts.add({ provider: "s3", bucket: "data", region: "eu-west-1",
39
+ * path: "/data", secret: "DATA_BUCKET" });
40
+ *
41
+ * A mount lasts through a pause and a wake, and ends when the sandbox stops. */
42
+ export declare function sandboxMounts(t: Transport, sandbox: Sandbox): {
43
+ add: (input: MountBucket, options?: RequestOptions) => Promise<Mount>;
44
+ list: (options?: RequestOptions) => Promise<Mount[]>;
45
+ remove: (path: string, options?: RequestOptions) => Promise<{
46
+ path: string;
47
+ mounted: false;
48
+ }>;
49
+ };
@@ -0,0 +1,21 @@
1
+ const enc = encodeURIComponent;
2
+ /** `sbx.mounts`: your own S3, R2 or Google Cloud Storage bucket as a
3
+ * directory in this sandbox.
4
+ *
5
+ * await sbx.mounts.add({ provider: "s3", bucket: "data", region: "eu-west-1",
6
+ * path: "/data", secret: "DATA_BUCKET" });
7
+ *
8
+ * A mount lasts through a pause and a wake, and ends when the sandbox stops. */
9
+ export function sandboxMounts(t, sandbox) {
10
+ const base = () => `/v1/sandboxes/${enc(sandbox.id)}/mounts`;
11
+ return {
12
+ add: (input, options) => t.json({ method: "POST", path: base(), body: input, ...options }),
13
+ list: async (options) => (await t.json({ method: "GET", path: base(), ...options })).data,
14
+ remove: (path, options) => t.json({
15
+ method: "POST",
16
+ path: `${base()}:unmount`,
17
+ body: { path },
18
+ ...options,
19
+ }),
20
+ };
21
+ }
@@ -0,0 +1,167 @@
1
+ import type { RequestOptions, Transport } from "../transport.js";
2
+ export type DnsRecord = {
3
+ type: string;
4
+ name: string;
5
+ value: string;
6
+ purpose: string;
7
+ };
8
+ export type Domain = {
9
+ id: string;
10
+ hostname: string;
11
+ sandboxId: string;
12
+ port: number;
13
+ /** pending until the TXT record proves the name is yours, then active. */
14
+ state: "pending" | "active" | "released";
15
+ url: string;
16
+ /** Turned off by Runtime after a report. */
17
+ disabled: boolean;
18
+ /** The TXT record that proves the name, and the CNAME (or A) that sends visitors here. */
19
+ records: DnsRecord[];
20
+ verifiedAt: string | null;
21
+ checkedAt: string | null;
22
+ checkError: string | null;
23
+ createdAt: string;
24
+ };
25
+ export type CheckedDomain = Domain & {
26
+ /** The name resolves to Runtime's edge now. */
27
+ pointed: boolean | null;
28
+ hint: string;
29
+ };
30
+ export type TcpPort = {
31
+ id: string;
32
+ sandboxId: string;
33
+ /** The port inside the sandbox. */
34
+ port: number;
35
+ address: string;
36
+ publicPort: number;
37
+ /** address:publicPort, for a client's host and port. */
38
+ connect: string;
39
+ protocol: "tcp";
40
+ disabled: boolean;
41
+ createdAt: string;
42
+ };
43
+ export type NetworkFunding = {
44
+ /** False disables traffic; the reservation remains until explicitly released. */
45
+ funded: boolean;
46
+ /** Last funded-through ISO timestamp, possibly past. Null means no meter exists. */
47
+ fundedUntil: string | null;
48
+ /** Immutable monthly quote in millionths of a US dollar. */
49
+ rateMicros: number;
50
+ rateUnit: "unit_month";
51
+ };
52
+ export type EgressAddress = NetworkFunding & {
53
+ id: string;
54
+ address: string;
55
+ family: 4 | 6;
56
+ createdAt: string;
57
+ };
58
+ export type TunnelPeer = {
59
+ id: string;
60
+ name: string;
61
+ publicKey: string;
62
+ /** The peer's address inside the tunnel's subnet. */
63
+ address: string;
64
+ /** Your own ranges behind the peer that sandboxes may reach through it. */
65
+ routes: string[];
66
+ createdAt: string;
67
+ rotatedAt: string | null;
68
+ };
69
+ export type Tunnel = NetworkFunding & {
70
+ id: string;
71
+ subnet: string;
72
+ gatewayAddress: string;
73
+ /** Where peers send WireGuard: address:udpPort. */
74
+ endpoint: string;
75
+ /** Null for a few seconds after creation. */
76
+ gatewayPublicKey: string | null;
77
+ disabled: boolean;
78
+ peers: TunnelPeer[];
79
+ /** Each sandbox's address in the tunnel. */
80
+ sandboxes: {
81
+ sandboxId: string;
82
+ name: string | null;
83
+ address: string;
84
+ state: string;
85
+ }[];
86
+ createdAt: string;
87
+ };
88
+ export type TunnelPeerCreated = {
89
+ tunnel: Tunnel;
90
+ peer: TunnelPeer;
91
+ /** A wg-quick file. It holds the private key only when Runtime generated it. */
92
+ config: string | null;
93
+ /** False means config is a draft preserving the private key; fill its gateway PublicKey before use. */
94
+ configReady: boolean;
95
+ hint: string;
96
+ };
97
+ /** `runtime.domains`: serve a sandbox's port at your own hostname, with HTTPS. */
98
+ export declare function domains(t: Transport): {
99
+ /** Claims the hostname and answers the DNS records to set. Calling it again
100
+ * with another sandbox or port points the name there. */
101
+ add: (input: {
102
+ hostname: string;
103
+ sandboxId: string;
104
+ port: number;
105
+ }, options?: RequestOptions) => Promise<CheckedDomain>;
106
+ /** Checks the TXT record now; the name goes live when it matches. */
107
+ verify: (hostname: string, options?: RequestOptions) => Promise<CheckedDomain>;
108
+ get: (hostname: string, options?: RequestOptions) => Promise<Domain>;
109
+ list: (options?: RequestOptions) => Promise<Domain[]>;
110
+ remove: (hostname: string, options?: RequestOptions) => Promise<{
111
+ hostname: string;
112
+ deleted: true;
113
+ }>;
114
+ };
115
+ /** `runtime.ports`: a public TCP port to a port of a sandbox. */
116
+ export declare function ports(t: Transport): {
117
+ /** Returns the same public port when called again for the same sandbox and port. */
118
+ open: (input: {
119
+ sandboxId: string;
120
+ port: number;
121
+ }, options?: RequestOptions) => Promise<TcpPort & {
122
+ hint: string;
123
+ }>;
124
+ list: (filter?: {
125
+ sandboxId?: string;
126
+ }, options?: RequestOptions) => Promise<TcpPort[]>;
127
+ close: (portId: string, options?: RequestOptions) => Promise<{
128
+ id: string;
129
+ deleted: true;
130
+ }>;
131
+ };
132
+ /** `runtime.addresses`: a dedicated outbound address every sandbox of the
133
+ * account sends from, for allow-lists. */
134
+ export declare function addresses(t: Transport): {
135
+ reserve: (input?: {
136
+ family?: 4 | 6;
137
+ }, options?: RequestOptions) => Promise<EgressAddress>;
138
+ list: (options?: RequestOptions) => Promise<EgressAddress[]>;
139
+ release: (addressId: string, options?: RequestOptions) => Promise<{
140
+ id: string;
141
+ address: string;
142
+ deleted: true;
143
+ }>;
144
+ };
145
+ /** `runtime.tunnel`: a WireGuard tunnel from your own network into your sandboxes. */
146
+ export declare function tunnel(t: Transport): {
147
+ get: (options?: RequestOptions) => Promise<Tunnel>;
148
+ /** Idempotent: returns the tunnel you have. */
149
+ create: (input?: {
150
+ subnet?: string;
151
+ }, options?: RequestOptions) => Promise<Tunnel>;
152
+ delete: (options?: RequestOptions) => Promise<{
153
+ id: string;
154
+ deleted: true;
155
+ }>;
156
+ /** Leave publicKey out and Runtime generates the pair; the private key is
157
+ * then in `config`, shown once. */
158
+ addPeer: (input: {
159
+ name: string;
160
+ publicKey?: string;
161
+ routes?: string[];
162
+ }, options?: RequestOptions) => Promise<TunnelPeerCreated>;
163
+ rotatePeer: (peerId: string, input?: {
164
+ publicKey?: string;
165
+ }, options?: RequestOptions) => Promise<TunnelPeerCreated>;
166
+ removePeer: (peerId: string, options?: RequestOptions) => Promise<Tunnel>;
167
+ };