withruntime 0.33.2 → 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 +66 -13
  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 +6 -4
  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 +49 -7
  29. package/dist/products/ci.js +15 -1
  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 +13 -2
@@ -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.2";
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.2";
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.2",
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"
@@ -258,7 +269,7 @@
258
269
  "llm"
259
270
  ],
260
271
  "dependencies": {
261
- "undici": "^7.29.1",
272
+ "undici": "^7.30.1",
262
273
  "yaml": "^2.8.1"
263
274
  },
264
275
  "peerDependencies": {