withruntime 0.33.3 → 0.34.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 (43) hide show
  1. package/E2B.md +7 -0
  2. package/dist/agents-cli.d.ts +1 -1
  3. package/dist/agents-cli.js +171 -7
  4. package/dist/agents-deploy.d.ts +13 -3
  5. package/dist/agents-deploy.js +68 -9
  6. package/dist/apps-cli.d.ts +1 -1
  7. package/dist/apps-cli.js +41 -9
  8. package/dist/browsers/index.d.ts +9 -0
  9. package/dist/browsers/index.js +10 -0
  10. package/dist/browsers-cli.d.ts +13 -0
  11. package/dist/browsers-cli.js +160 -0
  12. package/dist/ci-cli.d.ts +1 -1
  13. package/dist/ci-cli.js +16 -3
  14. package/dist/cli.d.ts +4 -0
  15. package/dist/cli.js +94 -10
  16. package/dist/desktops/index.d.ts +9 -0
  17. package/dist/desktops/index.js +10 -0
  18. package/dist/e2b/code-interpreter.d.ts +3 -12
  19. package/dist/e2b/code-interpreter.js +3 -6
  20. package/dist/e2b/index.d.ts +7 -1
  21. package/dist/e2b/index.js +9 -2
  22. package/dist/index.d.ts +5 -3
  23. package/dist/products/agents.d.ts +162 -8
  24. package/dist/products/agents.js +108 -3
  25. package/dist/products/apps.d.ts +46 -5
  26. package/dist/products/browsers.d.ts +26 -0
  27. package/dist/products/browsers.js +11 -0
  28. package/dist/products/ci.d.ts +10 -4
  29. package/dist/products/ci.js +8 -0
  30. package/dist/products/desktops.d.ts +71 -0
  31. package/dist/products/desktops.js +27 -0
  32. package/dist/products/index.d.ts +4 -0
  33. package/dist/products/index.js +5 -0
  34. package/dist/products/network.d.ts +4 -2
  35. package/dist/products/secrets.d.ts +10 -2
  36. package/dist/products/secrets.js +27 -7
  37. package/dist/products/uptime.d.ts +97 -0
  38. package/dist/products/uptime.js +42 -0
  39. package/dist/products/volumes.d.ts +41 -9
  40. package/dist/products/volumes.js +5 -2
  41. package/dist/transport.d.ts +4 -1
  42. package/dist/transport.js +2 -2
  43. package/package.json +12 -1
@@ -96,6 +96,17 @@ export function browsers(t) {
96
96
  ...options,
97
97
  }));
98
98
  },
99
+ /** Open `url` in a new tab and shoot it once it loads (without `url`, what
100
+ * the browser shows now); the image is `base64`, its page's url, title
101
+ * and HTTP status beside it. Runs inside the browser's own sandbox. */
102
+ screenshot(id, input = {}, options) {
103
+ return t.json({
104
+ method: "POST",
105
+ path: `${path(id)}:screenshot`,
106
+ body: input,
107
+ ...options,
108
+ });
109
+ },
99
110
  /** End a browser by id; pass RequestOptions to bound or deduplicate the request. */
100
111
  delete: remove,
101
112
  };
@@ -144,7 +144,8 @@ export type CiReviewFinding = {
144
144
  /** What would put it right. */
145
145
  fix: string;
146
146
  };
147
- /** A review step's verdict on one commit: it passes only with no findings. */
147
+ /** An agent step's verdict on one commit (`review:` is its short form): it
148
+ * passes only with no findings. */
148
149
  export type CiReview = {
149
150
  verdict: "pass" | "block";
150
151
  summary: string;
@@ -155,10 +156,11 @@ export type CiReview = {
155
156
  line: number;
156
157
  what: string;
157
158
  }[];
158
- /** The Runtime Agent that reviewed, the account it ran on and its model. */
159
+ /** The Runtime Agent that judged, and the model the step asked for. */
159
160
  agent: string;
160
- account: string;
161
- model: string;
161
+ model: string | null;
162
+ /** The Claude account a verdict before agent steps ran on. */
163
+ account?: string;
162
164
  /** The agent session that gave the verdict. */
163
165
  session: string;
164
166
  /** True when the diff was too long and its end was not read. */
@@ -353,6 +355,10 @@ export declare function ci(t: Transport): {
353
355
  * are let go. A check that has ended is answered as it is; to a key
354
356
  * that may cancel it but not read it, with its id and state alone. */
355
357
  cancel: (id: string, options?: RequestOptions) => Promise<CiCheckDetail | CiCancelled>;
358
+ /** Run a check again, as GitHub's Re-run does: a new check of the
359
+ * same commit (a pull request's as it would land now), trusted only as
360
+ * the commit's last check was. A check still going is answered as it is. */
361
+ rerun: (id: string, options?: RequestOptions) => Promise<CiCheckDetail | CiCancelled>;
356
362
  };
357
363
  jobs: {
358
364
  /** A job with the tail of its log and the sandboxes it ran in. */
@@ -92,6 +92,14 @@ export function ci(t) {
92
92
  path: `${at("/v1/ci/checks", id)}:cancel`,
93
93
  ...options,
94
94
  }),
95
+ /** Run a check again, as GitHub's Re-run does: a new check of the
96
+ * same commit (a pull request's as it would land now), trusted only as
97
+ * the commit's last check was. A check still going is answered as it is. */
98
+ rerun: (id, options) => t.json({
99
+ method: "POST",
100
+ path: `${at("/v1/ci/checks", id)}:rerun`,
101
+ ...options,
102
+ }),
95
103
  },
96
104
  jobs: {
97
105
  /** A job with the tail of its log and the sandboxes it ran in. */
@@ -0,0 +1,71 @@
1
+ /** Desktops: a Linux desktop on its own sandbox, billed at the sandbox rates
2
+ * (packages/cloud/src/api/products/desktops.ts), at /v1/desktops, with a
3
+ * private live view and computer use: screenshot and act. In a private beta:
4
+ * an account outside it is refused with product_in_beta (403), and retrying
5
+ * does not change it. */
6
+ import type { RequestOptions, Transport } from "../transport.js";
7
+ import { type ResourceRecord } from "./resources.js";
8
+ export type DesktopState = "starting" | "running" | "paused" | "stopped" | "failed" | "deleted";
9
+ export type Desktop = ResourceRecord & {
10
+ name: string | null;
11
+ labels: Record<string, string>;
12
+ state: DesktopState;
13
+ sandboxId: string;
14
+ createdAt: number;
15
+ updatedAt: number;
16
+ deletedAt: number | null;
17
+ memoryMiB: number;
18
+ vcpu: number;
19
+ width: number;
20
+ height: number;
21
+ timeoutSeconds: number;
22
+ idlePauseSeconds: number;
23
+ /** Opens the live desktop in a browser; carries a private preview token. */
24
+ liveViewUrl?: string;
25
+ /** When liveViewUrl's token ends; get the desktop again for a fresh one. */
26
+ expiresAt: string | null;
27
+ actions: {
28
+ screenshot: string;
29
+ act: string;
30
+ record: string;
31
+ };
32
+ };
33
+ export type CreateDesktop = {
34
+ /** 1024–16384 MiB; the server defaults to 2048. */
35
+ memoryMiB?: number;
36
+ /** The server defaults to 2 vCPU. */
37
+ vcpu?: number;
38
+ /** The screen, 640x480 to 3840x2160; 1280x800 by default. */
39
+ width?: number;
40
+ height?: number;
41
+ timeoutSeconds?: number;
42
+ idlePauseSeconds?: number;
43
+ name?: string;
44
+ labels?: Record<string, string>;
45
+ };
46
+ /** Only the name and labels change; a null name clears it. */
47
+ export type UpdateDesktop = {
48
+ name?: string | null;
49
+ labels?: Record<string, string>;
50
+ };
51
+ /** One computer-use step, as POST /v1/desktops/{id}:act takes it. */
52
+ export type DesktopAct = {
53
+ action: string;
54
+ } & Record<string, unknown>;
55
+ export declare function desktops(t: Transport): {
56
+ /** The screen as PNG (or JPEG) bytes. A write: it runs in the desktop's
57
+ * sandbox and wakes a paused one, so a read-only key is refused it. */
58
+ screenshot(id: string, shot?: {
59
+ format?: "png" | "jpeg";
60
+ quality?: number;
61
+ }, options?: RequestOptions): Promise<Uint8Array<ArrayBufferLike>>;
62
+ /** Move, click, drag, scroll, type, press keys, open a URL or launch a program. */
63
+ act(id: string, step: DesktopAct, options?: RequestOptions): Promise<Record<string, unknown>>;
64
+ base: string;
65
+ create: (input: CreateDesktop, options?: RequestOptions) => Promise<Desktop>;
66
+ get: (id: string, options?: import("./resources.js").ResourceGetOptions<"paused" | "stopped" | "starting" | "running" | "deleted" | "failed">) => Promise<Desktop>;
67
+ list: (query?: import("./resources.js").ResourceListQuery<"paused" | "stopped" | "starting" | "running" | "deleted" | "failed">, options?: RequestOptions) => Promise<import("../page.js").Page<Desktop>>;
68
+ update: (id: string, input: UpdateDesktop, options?: RequestOptions) => Promise<Desktop>;
69
+ wait: (id: string, target: "paused" | "stopped" | "starting" | "running" | "deleted" | "failed", options?: import("./resources.js").ResourceWaitOptions) => Promise<Desktop>;
70
+ delete: (id: string, options?: import("./resources.js").ResourceDeleteOptions) => Promise<Desktop>;
71
+ };
@@ -0,0 +1,27 @@
1
+ import { enc, resource } from "./resources.js";
2
+ /** A wait ends at its target or at one of these, with the desktop's error. */
3
+ const SETTLED = ["failed", "deleted"];
4
+ export function desktops(t) {
5
+ return {
6
+ ...resource(t, "desktops", SETTLED),
7
+ /** The screen as PNG (or JPEG) bytes. A write: it runs in the desktop's
8
+ * sandbox and wakes a paused one, so a read-only key is refused it. */
9
+ screenshot(id, shot = {}, options) {
10
+ return t.bytes({
11
+ method: "POST",
12
+ path: `/v1/desktops/${enc(id)}:screenshot`,
13
+ body: shot,
14
+ ...options,
15
+ });
16
+ },
17
+ /** Move, click, drag, scroll, type, press keys, open a URL or launch a program. */
18
+ act(id, step, options) {
19
+ return t.json({
20
+ method: "POST",
21
+ path: `/v1/desktops/${enc(id)}:act`,
22
+ body: step,
23
+ ...options,
24
+ });
25
+ },
26
+ };
27
+ }
@@ -27,6 +27,8 @@ import { agents } from "./agents.js";
27
27
  import { builds } from "./builds.js";
28
28
  import { ci } from "./ci.js";
29
29
  import { containers } from "./containers.js";
30
+ import { browsers } from "./browsers.js";
31
+ import { desktops } from "./desktops.js";
30
32
  import { apps } from "./apps.js";
31
33
  export declare const clientExtensions: {
32
34
  images: typeof images;
@@ -54,6 +56,8 @@ export declare const clientExtensions: {
54
56
  builds: typeof builds;
55
57
  ci: typeof ci;
56
58
  containers: typeof containers;
59
+ browsers: typeof browsers;
60
+ desktops: typeof desktops;
57
61
  apps: typeof apps;
58
62
  };
59
63
  export declare const sandboxExtensions: {
@@ -25,6 +25,8 @@ import { agents } from "./agents.js";
25
25
  import { builds } from "./builds.js";
26
26
  import { ci } from "./ci.js";
27
27
  import { containers } from "./containers.js";
28
+ import { browsers } from "./browsers.js";
29
+ import { desktops } from "./desktops.js";
28
30
  // The hub loads this file, so it loads apps.ts and resources.ts too: request
29
31
  // builders over Transport whose top level holds only types, functions and
30
32
  // imports of files the hub loads, so importing them runs nothing in the hub
@@ -73,6 +75,9 @@ export const clientExtensions = {
73
75
  // CI/CD (beta): the API answers product_in_beta outside its list.
74
76
  ci,
75
77
  containers,
78
+ // Browsers and Desktops (beta): the API answers product_in_beta outside its list.
79
+ browsers,
80
+ desktops,
76
81
  // A private beta (PRODUCT_BETAS): an account outside it is refused with
77
82
  // product_in_beta until Apps launches.
78
83
  apps,
@@ -2,9 +2,11 @@ import type { Sandbox } from "../sandbox.js";
2
2
  import type { RequestOptions, Transport } from "../transport.js";
3
3
  /** A sandbox's own network rules. */
4
4
  export type NetworkRules = {
5
- /** false refuses every outbound connection. */
5
+ /** false refuses every outbound connection; with `allow`, everything but the
6
+ * list (allow-list only, stored as `internet: true` with that list). */
6
7
  internet: boolean;
7
- /** When not empty, only these web destinations are reachable: `example.com`,
8
+ /** When not empty, only these web destinations are reachable, the internet on
9
+ * or off: `example.com`,
8
10
  * `*.example.com` (subdomains, not the apex), an address or a CIDR range. */
9
11
  allow?: string[];
10
12
  /** Never reachable. Wins over everything. */
@@ -171,6 +171,13 @@ export type JobSecret = {
171
171
  /** One secret by name, and where its value may go: to sandboxes through the
172
172
  * egress proxy (`sandboxes`), into scheduled jobs' environments (`jobs`), or
173
173
  * both. */
174
+ /** A page of `secrets.list`: at most `limit` (1 to 100, default 50) secrets,
175
+ * by name, those named after `after`. The next page's `after` is the last
176
+ * name of this one; a page shorter than `limit` is the last. */
177
+ export type ListSecrets = {
178
+ limit?: number;
179
+ after?: string;
180
+ };
174
181
  export type SecretUse = {
175
182
  name: string;
176
183
  sandboxes: Secret | null;
@@ -219,8 +226,9 @@ export declare function secrets(t: Transport): {
219
226
  enforced: boolean;
220
227
  }>;
221
228
  /** The sandboxes' secrets: names, hosts and placeholders. Never values.
222
- * `all()` includes the jobs copies. */
223
- list: (options?: RequestOptions) => Promise<Secret[]>;
229
+ * `list({ limit, after })` gives one page, by name; `all()` includes
230
+ * the jobs copies. */
231
+ list: (query?: ListSecrets & RequestOptions) => Promise<Secret[]>;
224
232
  /** Every secret by name, with where its value may go. */
225
233
  all: (options?: RequestOptions) => Promise<SecretUse[]>;
226
234
  /** One secret by name, with where its value may go. */
@@ -30,11 +30,29 @@ export function secrets(t) {
30
30
  }
31
31
  }
32
32
  const liveCopy = async (name, options) => (await jobCopies(options)).find((s) => s.name === name && s.deletedAt === null);
33
- const list = async (options) => (await t.json({
34
- method: "GET",
35
- path: "/v1/egress-secrets",
36
- ...options,
37
- })).secrets;
33
+ /** One page with `limit` or `after`; every secret, page after page, without. */
34
+ async function list(query = {}) {
35
+ const { limit, after, ...options } = query;
36
+ const paged = limit !== undefined || after !== undefined;
37
+ const all = [];
38
+ let from = after;
39
+ for (;;) {
40
+ const params = {
41
+ ...(limit === undefined ? {} : { limit }),
42
+ ...(from === undefined ? {} : { after: from }),
43
+ };
44
+ const page = await t.json({
45
+ method: "GET",
46
+ path: "/v1/egress-secrets",
47
+ ...(Object.keys(params).length ? { query: params } : {}),
48
+ ...options,
49
+ });
50
+ all.push(...page.secrets);
51
+ if (paged || !page.next)
52
+ return all;
53
+ from = page.next;
54
+ }
55
+ }
38
56
  const key = (options, part) => options?.idempotencyKey
39
57
  ? { ...options, idempotencyKey: `${options.idempotencyKey}:${part}`.slice(0, 128) }
40
58
  : options;
@@ -111,7 +129,8 @@ export function secrets(t) {
111
129
  sandboxes: byName.get(j.name)?.sandboxes ?? null,
112
130
  jobs: j,
113
131
  });
114
- return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
132
+ // By code point, as the API pages them (`after` compares names so).
133
+ return [...byName.values()].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
115
134
  }
116
135
  async function set(name, input, options) {
117
136
  const { jobs, value, ...egress } = input;
@@ -178,7 +197,8 @@ export function secrets(t) {
178
197
  ...options,
179
198
  }),
180
199
  /** The sandboxes' secrets: names, hosts and placeholders. Never values.
181
- * `all()` includes the jobs copies. */
200
+ * `list({ limit, after })` gives one page, by name; `all()` includes
201
+ * the jobs copies. */
182
202
  list,
183
203
  /** Every secret by name, with where its value may go. */
184
204
  all,
@@ -0,0 +1,97 @@
1
+ import { Page } from "../page.js";
2
+ import type { RequestOptions, Transport } from "../transport.js";
3
+ export type UptimeRegion = "wnam" | "enam" | "sam" | "weur" | "eeur" | "apac" | "oc" | "afr" | "me";
4
+ export type UptimeState = "applying" | "active" | "deleted";
5
+ export type UptimeHealth = "unknown" | "up" | "down";
6
+ export type StatusRange = {
7
+ low: number;
8
+ high: number;
9
+ };
10
+ export type UptimeCheck = {
11
+ id: string;
12
+ name: string | null;
13
+ labels: Record<string, string>;
14
+ /** applying until the probes have it, within a minute; then active. */
15
+ state: UptimeState;
16
+ createdAt: number;
17
+ updatedAt: number;
18
+ deletedAt: number | null;
19
+ /** `target_refused` while the newest knock found the target on a private
20
+ * or Runtime address. */
21
+ error: {
22
+ code: string;
23
+ message: string;
24
+ } | null;
25
+ url: string;
26
+ method: "GET" | "HEAD";
27
+ intervalSeconds: number;
28
+ timeoutMs: number;
29
+ regions: UptimeRegion[];
30
+ confirm: number;
31
+ statuses: StatusRange[];
32
+ bodyContains?: string;
33
+ health: UptimeHealth;
34
+ healthSince: number | null;
35
+ };
36
+ export type CreateUptimeCheck = {
37
+ /** https://, http:// or tcp://host:port; its host must resolve to public
38
+ * addresses (a Runtime App's hostname on 80 or 443 is allowed). */
39
+ url: string;
40
+ name?: string;
41
+ labels?: Record<string, string>;
42
+ /** Defaults to GET. */
43
+ method?: "GET" | "HEAD";
44
+ /** 30 to 3,600 per region; defaults to 60. Regions knock in turn. */
45
+ intervalSeconds?: number;
46
+ /** 1 to 30,000; defaults to 10,000. */
47
+ timeoutMs?: number;
48
+ /** Defaults to enam, wnam, weur, eeur, apac. */
49
+ regions?: UptimeRegion[];
50
+ /** Regions that must fail to call it down; defaults to 2 (1 with one region). */
51
+ confirm?: number;
52
+ /** Ranges that pass; defaults to 200 to 399. */
53
+ statuses?: StatusRange[];
54
+ /** Text the body must contain; GET only. */
55
+ bodyContains?: string;
56
+ };
57
+ export type UptimeResult = {
58
+ region: UptimeRegion;
59
+ scheduledAt: number;
60
+ at: number;
61
+ ms: number;
62
+ up: boolean;
63
+ status: number | null;
64
+ reason: string | null;
65
+ timing: Record<string, unknown>;
66
+ };
67
+ export type UptimeListQuery = {
68
+ limit?: number;
69
+ cursor?: string;
70
+ name?: string;
71
+ label?: string[];
72
+ state?: UptimeState[];
73
+ };
74
+ export type UptimeResultsQuery = {
75
+ before?: number;
76
+ limit?: number;
77
+ region?: UptimeRegion;
78
+ };
79
+ export declare function uptime(t: Transport): {
80
+ create: (input: CreateUptimeCheck, options?: RequestOptions) => Promise<UptimeCheck>;
81
+ /** waitFor follows a state for up to 60 seconds; the answer says where it got. */
82
+ get: (id: string, options?: RequestOptions & {
83
+ waitFor?: UptimeState;
84
+ timeoutSeconds?: number;
85
+ }) => Promise<UptimeCheck>;
86
+ list: (query?: UptimeListQuery, options?: RequestOptions) => Promise<Page<UptimeCheck>>;
87
+ update: (id: string, input: {
88
+ name?: string | null;
89
+ labels?: Record<string, string>;
90
+ }, options?: RequestOptions) => Promise<UptimeCheck>;
91
+ delete: (id: string, options?: RequestOptions) => Promise<UptimeCheck>;
92
+ /** Knocks, newest first, kept 7 days; pass nextBefore as before for older ones. */
93
+ results: (id: string, query?: UptimeResultsQuery, options?: RequestOptions) => Promise<{
94
+ data: UptimeResult[];
95
+ nextBefore: number | null;
96
+ }>;
97
+ };
@@ -0,0 +1,42 @@
1
+ import { Page } from "../page.js";
2
+ const enc = encodeURIComponent;
3
+ export function uptime(t) {
4
+ const base = "/v1/uptime";
5
+ const list = async (query = {}, options) => {
6
+ const page = await t.json({
7
+ method: "GET",
8
+ path: base,
9
+ query,
10
+ ...options,
11
+ });
12
+ return new Page(page.data, page.nextCursor, (cursor) => list({ ...query, cursor }, options));
13
+ };
14
+ return {
15
+ create: (input, options) => t.json({ method: "POST", path: base, body: input, ...options }),
16
+ /** waitFor follows a state for up to 60 seconds; the answer says where it got. */
17
+ get: (id, options = {}) => {
18
+ const { waitFor, timeoutSeconds, ...request } = options;
19
+ return t.json({
20
+ method: "GET",
21
+ path: `${base}/${enc(id)}`,
22
+ query: { waitFor, timeoutSeconds },
23
+ ...request,
24
+ });
25
+ },
26
+ list,
27
+ update: (id, input, options) => t.json({
28
+ method: "POST",
29
+ path: `${base}/${enc(id)}:update`,
30
+ body: input,
31
+ ...options,
32
+ }),
33
+ delete: (id, options) => t.json({ method: "DELETE", path: `${base}/${enc(id)}`, ...options }),
34
+ /** Knocks, newest first, kept 7 days; pass nextBefore as before for older ones. */
35
+ results: (id, query = {}, options) => t.json({
36
+ method: "GET",
37
+ path: `${base}/${enc(id)}/results`,
38
+ query,
39
+ ...options,
40
+ }),
41
+ };
42
+ }
@@ -25,10 +25,14 @@ export type Volume = {
25
25
  measuredAt: string | null;
26
26
  /** True once a backup of it has been copied off its host and checked. */
27
27
  backedUp: boolean;
28
- /** Daily backups, how long each is kept, and when the newest was taken. */
28
+ /** Automatic backups: daily, kept `retentionDays`, or on the volume's own
29
+ * `schedule` with `keep` counts; `nextAt` is the schedule's next backup. */
29
30
  backups: {
30
31
  daily: boolean;
31
32
  retentionDays: number;
33
+ schedule?: VolumeBackupSchedule | null;
34
+ keep?: Required<VolumeBackupKeep> | null;
35
+ nextAt?: string | null;
32
36
  lastReadyAt: string | null;
33
37
  };
34
38
  /** The backup this volume was restored from, if any. */
@@ -69,6 +73,24 @@ export type VolumeAttachment = {
69
73
  changedAt: string;
70
74
  };
71
75
  export type VolumeBackupState = "pending" | "ready" | "failed" | "deleting" | "deleted";
76
+ /** Back up every N minutes (15 or more, from 1970-01-01 UTC), or on a
77
+ * five-field cron in UTC such as `"30 2 * * 1-5"` (02:30 on weekdays). */
78
+ export type VolumeBackupSchedule = {
79
+ everyMinutes: number;
80
+ } | {
81
+ cron: string;
82
+ };
83
+ /** Which scheduled backups stay: the last N, and the newest in each of the
84
+ * newest N hours, days, weeks (from Monday), months and years. Any backup a
85
+ * count keeps is kept; the newest ready backup always is. Missing counts are 0. */
86
+ export type VolumeBackupKeep = {
87
+ last?: number;
88
+ hourly?: number;
89
+ daily?: number;
90
+ weekly?: number;
91
+ monthly?: number;
92
+ yearly?: number;
93
+ };
72
94
  /** A point-in-time copy of a volume, kept off its host. */
73
95
  export type VolumeBackup = {
74
96
  id: string;
@@ -80,25 +102,30 @@ export type VolumeBackup = {
80
102
  region: string;
81
103
  volumeId: string;
82
104
  sizeMiB: number;
83
- trigger: "manual" | "daily";
84
- retentionDays: number;
105
+ /** `scheduled`: made on the volume's schedule and kept by its keep counts. */
106
+ trigger: "manual" | "daily" | "scheduled";
107
+ /** Null while the volume's keep counts decide. */
108
+ retentionDays: number | null;
85
109
  logicalBytes: number | null;
86
110
  storedBytes: number | null;
87
111
  meteredBytes: number | null;
88
112
  error: string | null;
89
113
  /** Why it failed, when a code says it: `backup_stalled` when its copy off
90
- * the host never began; back it up again. */
114
+ * the volume's server had not begun 15 minutes after `createdAt`; back it
115
+ * up again. */
91
116
  errorCode?: string | null;
92
117
  createdAt: string;
93
- /** When its copy off the volume's server began; null while it waits its
94
- * turn behind other copies there. */
118
+ /** When its copy off the volume's server began; null while it waits,
119
+ * behind other backups there only (never Runtime's own copies). */
95
120
  copyStartedAt?: string | null;
96
121
  readyAt: string | null;
97
- expiresAt: string;
122
+ /** Null while the volume's keep counts decide. */
123
+ expiresAt: string | null;
98
124
  };
99
125
  /** Persistent disks: create once, attach when creating a sandbox with
100
126
  * `volumes: [{ volumeId: v.id, path: "/data" }]`. Backed up off their host
101
- * daily unless that is turned off; restore one with `create({ fromBackup })`. */
127
+ * daily, or on a schedule of their own, unless that is turned off; restore
128
+ * one with `create({ fromBackup })`. */
102
129
  export declare function volumes(t: Transport): {
103
130
  /** Create and wait (up to 10 s) until it is ready. With `fromBackup`, a
104
131
  * restore; it is ready once the backup is downloaded and checked. */
@@ -136,10 +163,15 @@ export declare function volumes(t: Transport): {
136
163
  }, options?: RequestOptions & {
137
164
  wait?: number;
138
165
  }) => Promise<VolumeBackup>;
139
- /** Daily backups on or off, and how many days each is kept. */
166
+ /** Automatic backups on or off, days a daily one is kept, or a schedule
167
+ * of the volume's own with keep counts:
168
+ * `setBackupPolicy(id, { schedule: { everyMinutes: 60 }, keep: { hourly: 24, daily: 7 } })`. */
140
169
  setBackupPolicy: (id: string, input: {
141
170
  daily?: boolean;
142
171
  retentionDays?: number;
172
+ /** Null goes back to daily backups kept `retentionDays`. */
173
+ schedule?: VolumeBackupSchedule | null;
174
+ keep?: VolumeBackupKeep;
143
175
  }, options?: RequestOptions) => Promise<Volume>;
144
176
  /** Backups, newest first; `{ volumeId }` for one volume's. */
145
177
  backups: (query?: {
@@ -2,7 +2,8 @@ import { Page } from "../page.js";
2
2
  const enc = encodeURIComponent;
3
3
  /** Persistent disks: create once, attach when creating a sandbox with
4
4
  * `volumes: [{ volumeId: v.id, path: "/data" }]`. Backed up off their host
5
- * daily unless that is turned off; restore one with `create({ fromBackup })`. */
5
+ * daily, or on a schedule of their own, unless that is turned off; restore
6
+ * one with `create({ fromBackup })`. */
6
7
  export function volumes(t) {
7
8
  const get = (id, options) => t.json({ method: "GET", path: `/v1/volumes/${enc(id)}`, ...options });
8
9
  const list = async (query = {}, options) => {
@@ -83,7 +84,9 @@ export function volumes(t) {
83
84
  ...rest,
84
85
  });
85
86
  },
86
- /** Daily backups on or off, and how many days each is kept. */
87
+ /** Automatic backups on or off, days a daily one is kept, or a schedule
88
+ * of the volume's own with keep counts:
89
+ * `setBackupPolicy(id, { schedule: { everyMinutes: 60 }, keep: { hourly: 24, daily: 7 } })`. */
87
90
  setBackupPolicy: (id, input, options) => t.json({
88
91
  method: "POST",
89
92
  path: `/v1/volumes/${enc(id)}:backup-policy`,
@@ -1,5 +1,5 @@
1
1
  import { RuntimeError } from "./errors.js";
2
- export declare const VERSION = "0.33.3";
2
+ export declare const VERSION = "0.34.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
@@ -47,6 +47,9 @@ export type Call = RequestOptions & {
47
47
  /** Seconds the server may hold the answer for a long-running result. */
48
48
  wait?: number;
49
49
  accept?: string;
50
+ /** Sent as the Bearer token instead of the client's API key: a webhook
51
+ * trigger's secret, which is all its calls carry. */
52
+ bearer?: string;
50
53
  /** Whether retrying after an unknown outcome is safe. Default: true for
51
54
  * reads and for writes (the key makes them safe); false only for calls
52
55
  * the server cannot deduplicate. */
package/dist/transport.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ConnectionError, DELIBERATE, errorFor, NOTHING_RAN, RuntimeError, WAITS_FOR_ROOM, } from "./errors.js";
2
2
  import { describeRoute, envFetch, openWebSocket, untrustedCertificate } from "./proxy.js";
3
3
  import { warningText } from "./product-renames.js";
4
- export const VERSION = "0.33.3";
4
+ export const VERSION = "0.34.0";
5
5
  export const DEFAULT_BASE_URL = "https://api.withruntime.com";
6
6
  /** Runtime's API as code inside a Runtime sandbox reaches it: the sandbox's
7
7
  * own host sends each request on to DEFAULT_BASE_URL over HTTPS. The API runs
@@ -374,7 +374,7 @@ export class Transport {
374
374
  let apiKey;
375
375
  try {
376
376
  call.signal?.throwIfAborted();
377
- apiKey = await untilAborted(this.#key(), call.signal);
377
+ apiKey = call.bearer ?? (await untilAborted(this.#key(), call.signal));
378
378
  }
379
379
  catch (cause) {
380
380
  if (call.signal?.aborted)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "withruntime",
3
- "version": "0.33.3",
3
+ "version": "0.34.0",
4
4
  "license": "Apache-2.0",
5
5
  "mcpName": "com.withruntime/runtime",
6
6
  "type": "module",
@@ -66,6 +66,16 @@
66
66
  "import": "./dist/containers/index.js",
67
67
  "default": "./dist/containers/index.js"
68
68
  },
69
+ "./browsers": {
70
+ "types": "./dist/browsers/index.d.ts",
71
+ "import": "./dist/browsers/index.js",
72
+ "default": "./dist/browsers/index.js"
73
+ },
74
+ "./desktops": {
75
+ "types": "./dist/desktops/index.d.ts",
76
+ "import": "./dist/desktops/index.js",
77
+ "default": "./dist/desktops/index.js"
78
+ },
69
79
  "./builds": {
70
80
  "types": "./dist/builds/index.d.ts",
71
81
  "import": "./dist/builds/index.js",
@@ -220,6 +230,7 @@
220
230
  "ai": "7.0.87",
221
231
  "groq-sdk": "1.6.0",
222
232
  "openai": "7.23.0",
233
+ "playwright": "1.63.0",
223
234
  "together-ai": "0.55.0",
224
235
  "typescript": "^5",
225
236
  "zod": "^4.1.8"