withruntime 0.11.2 → 0.12.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 (164) hide show
  1. package/BLAXEL.md +2 -2
  2. package/COMPATIBILITY.md +74 -9
  3. package/DAYTONA.md +33 -5
  4. package/E2B.md +85 -24
  5. package/README.md +9 -8
  6. package/README.src.md +8 -7
  7. package/VERCEL.md +43 -5
  8. package/compatibility-lock.json +58 -49
  9. package/dist/billing-cli.d.ts +1 -1
  10. package/dist/billing-cli.js +77 -1
  11. package/dist/blaxel/errors.d.ts +14 -0
  12. package/dist/blaxel/errors.js +29 -0
  13. package/dist/blaxel/index.d.ts +2 -2
  14. package/dist/blaxel/index.js +4 -4
  15. package/dist/blaxel/interpreter.d.ts +2 -5
  16. package/dist/blaxel/sandbox.d.ts +14 -5
  17. package/dist/blaxel/sandbox.js +63 -7
  18. package/dist/blaxel/snapshot.d.ts +4 -0
  19. package/dist/blaxel/snapshot.js +4 -0
  20. package/dist/cli/logs.d.ts +21 -0
  21. package/dist/cli/logs.js +188 -0
  22. package/dist/cli/logs.test.d.ts +1 -0
  23. package/dist/cli/logs.test.js +272 -0
  24. package/dist/cli-extras.d.ts +3 -3
  25. package/dist/cli-extras.js +17 -12
  26. package/dist/cli-words.d.ts +10 -1
  27. package/dist/cli-words.js +18 -0
  28. package/dist/cli.d.ts +5 -1
  29. package/dist/cli.js +405 -204
  30. package/dist/client.d.ts +2 -4
  31. package/dist/client.js +27 -11
  32. package/dist/cloudflare/errors.d.ts +143 -0
  33. package/dist/cloudflare/errors.js +167 -0
  34. package/dist/cloudflare/index.d.ts +175 -6
  35. package/dist/cloudflare/index.js +416 -26
  36. package/dist/cloudflare/interpreter.d.ts +119 -0
  37. package/dist/cloudflare/interpreter.js +223 -0
  38. package/dist/cloudflare/streams.d.ts +38 -0
  39. package/dist/cloudflare/streams.js +145 -0
  40. package/dist/cloudflare/watch.d.ts +9 -0
  41. package/dist/cloudflare/watch.js +24 -0
  42. package/dist/codesandbox/index.d.ts +216 -28
  43. package/dist/codesandbox/index.js +478 -78
  44. package/dist/compat/core.d.ts +18 -0
  45. package/dist/compat/core.js +29 -0
  46. package/dist/compat/files.d.ts +1 -0
  47. package/dist/compat/files.js +25 -5
  48. package/dist/daytona/computer-use.d.ts +13 -4
  49. package/dist/daytona/computer-use.js +66 -8
  50. package/dist/daytona/daytona.d.ts +6 -0
  51. package/dist/daytona/daytona.js +30 -3
  52. package/dist/daytona/errors.d.ts +11 -0
  53. package/dist/daytona/errors.js +18 -0
  54. package/dist/daytona/filesystem.js +2 -1
  55. package/dist/daytona/image.d.ts +13 -9
  56. package/dist/daytona/image.js +18 -12
  57. package/dist/daytona/index.d.ts +1 -1
  58. package/dist/daytona/sandbox.d.ts +8 -2
  59. package/dist/daytona/sandbox.js +16 -2
  60. package/dist/domains/index.d.ts +9 -0
  61. package/dist/domains/index.js +10 -0
  62. package/dist/e2b/commands.d.ts +1 -1
  63. package/dist/e2b/commands.js +6 -7
  64. package/dist/e2b/errors.d.ts +17 -0
  65. package/dist/e2b/errors.js +40 -1
  66. package/dist/e2b/index.d.ts +2 -2
  67. package/dist/e2b/index.js +1 -1
  68. package/dist/e2b/sandbox.d.ts +27 -21
  69. package/dist/e2b/sandbox.js +34 -8
  70. package/dist/e2b/unsupported.js +1 -1
  71. package/dist/errors.d.ts +10 -1
  72. package/dist/errors.js +16 -4
  73. package/dist/freestyle/index.d.ts +285 -37
  74. package/dist/freestyle/index.js +656 -144
  75. package/dist/identity.d.ts +3 -0
  76. package/dist/identity.js +27 -0
  77. package/dist/images/index.d.ts +9 -0
  78. package/dist/images/index.js +10 -0
  79. package/dist/index.d.ts +1 -0
  80. package/dist/ips/index.d.ts +9 -0
  81. package/dist/ips/index.js +10 -0
  82. package/dist/jobs/index.d.ts +9 -0
  83. package/dist/jobs/index.js +10 -0
  84. package/dist/keys.js +2 -0
  85. package/dist/login.js +2 -0
  86. package/dist/machine.d.ts +12 -3
  87. package/dist/machine.js +20 -3
  88. package/dist/mcp.js +1 -1
  89. package/dist/modal/index.d.ts +339 -61
  90. package/dist/modal/index.js +781 -121
  91. package/dist/network-cli.d.ts +3 -1
  92. package/dist/network-cli.js +78 -36
  93. package/dist/networks/index.d.ts +11 -0
  94. package/dist/networks/index.js +10 -0
  95. package/dist/ports/index.d.ts +9 -0
  96. package/dist/ports/index.js +10 -0
  97. package/dist/product-names.d.ts +52 -0
  98. package/dist/product-names.js +164 -0
  99. package/dist/product-renames.d.ts +103 -0
  100. package/dist/product-renames.js +189 -0
  101. package/dist/products/apps.d.ts +176 -0
  102. package/dist/products/apps.js +165 -0
  103. package/dist/products/billing.d.ts +41 -0
  104. package/dist/products/billing.js +13 -0
  105. package/dist/products/browser.d.ts +10 -0
  106. package/dist/products/browsers.d.ts +71 -0
  107. package/dist/products/browsers.js +102 -0
  108. package/dist/products/builds.d.ts +126 -0
  109. package/dist/products/builds.js +221 -0
  110. package/dist/products/index.d.ts +3 -16
  111. package/dist/products/index.js +3 -14
  112. package/dist/products/jobs.d.ts +17 -0
  113. package/dist/products/jobs.js +27 -10
  114. package/dist/products/logs.d.ts +245 -0
  115. package/dist/products/logs.js +274 -0
  116. package/dist/products/logs.test.d.ts +1 -0
  117. package/dist/products/logs.test.js +343 -0
  118. package/dist/products/network-products.d.ts +38 -7
  119. package/dist/products/network-products.js +31 -18
  120. package/dist/products/observability.d.ts +3 -2
  121. package/dist/products/private-network.js +1 -1
  122. package/dist/products/queues.d.ts +149 -0
  123. package/dist/products/queues.js +213 -0
  124. package/dist/products/referrals.d.ts +21 -7
  125. package/dist/products/referrals.js +3 -3
  126. package/dist/products/secrets.d.ts +7 -3
  127. package/dist/products/secrets.js +39 -18
  128. package/dist/products/signed-requests.d.ts +21 -0
  129. package/dist/products/signed-requests.js +11 -0
  130. package/dist/products/streams.d.ts +73 -0
  131. package/dist/products/streams.js +17 -0
  132. package/dist/products/switching.d.ts +35 -7
  133. package/dist/products/switching.js +4 -3
  134. package/dist/products/volumes.d.ts +3 -0
  135. package/dist/record-cli.d.ts +23 -0
  136. package/dist/record-cli.js +308 -0
  137. package/dist/renamed-products.d.ts +38 -0
  138. package/dist/renamed-products.js +34 -0
  139. package/dist/runloop/index.d.ts +9 -2
  140. package/dist/runloop/index.js +29 -8
  141. package/dist/runloop/sdk.d.ts +131 -0
  142. package/dist/runloop/sdk.js +167 -0
  143. package/dist/sandbox.d.ts +3 -2
  144. package/dist/sandbox.js +14 -9
  145. package/dist/sandboxes/index.d.ts +11 -0
  146. package/dist/sandboxes/index.js +12 -0
  147. package/dist/snapshots/index.d.ts +9 -0
  148. package/dist/snapshots/index.js +11 -0
  149. package/dist/snapshots.d.ts +7 -4
  150. package/dist/sprites/index.d.ts +343 -31
  151. package/dist/sprites/index.js +866 -84
  152. package/dist/ssh.d.ts +1 -1
  153. package/dist/ssh.js +11 -11
  154. package/dist/terminal.d.ts +24 -0
  155. package/dist/terminal.js +32 -0
  156. package/dist/transport.d.ts +15 -1
  157. package/dist/transport.js +56 -3
  158. package/dist/tunnel.js +1 -1
  159. package/dist/types.d.ts +63 -0
  160. package/dist/vercel/sandbox.js +5 -3
  161. package/dist/vercel/snapshot.js +10 -2
  162. package/dist/volumes/index.d.ts +9 -0
  163. package/dist/volumes/index.js +10 -0
  164. package/package.json +48 -2
@@ -8,8 +8,10 @@ type Args = {
8
8
  positional: string[];
9
9
  flags: Map<string, string[]>;
10
10
  };
11
- export declare const NETWORK_PRODUCTS: readonly ["domain", "port", "address", "tunnel", "network"];
11
+ export declare const NETWORK_PRODUCTS: readonly ["domains", "ports", "ips", "wireguard", "networks"];
12
12
  export type NetworkProduct = (typeof NETWORK_PRODUCTS)[number];
13
+ /** The command each is typed as: WireGuard is inside networks. */
14
+ export declare const NETWORK_COMMAND: Record<NetworkProduct, string>;
13
15
  export declare const NETWORK_HELP: Record<NetworkProduct, string>;
14
16
  export declare function networkProductCommand(product: NetworkProduct, argv: string[], args: Args, out: Out, client: () => Promise<Runtime>): Promise<number>;
15
17
  export {};
@@ -14,9 +14,17 @@ function fundingState(value) {
14
14
  ? `Funded until ${value.fundedUntil}.`
15
15
  : "Funding active; no deadline reported.";
16
16
  }
17
- export const NETWORK_PRODUCTS = ["domain", "port", "address", "tunnel", "network"];
17
+ export const NETWORK_PRODUCTS = ["domains", "ports", "ips", "wireguard", "networks"];
18
+ /** The command each is typed as: WireGuard is inside networks. */
19
+ export const NETWORK_COMMAND = {
20
+ domains: "domains",
21
+ ports: "ports",
22
+ ips: "ips",
23
+ wireguard: "networks wireguard",
24
+ networks: "networks",
25
+ };
18
26
  export const NETWORK_HELP = {
19
- domain: `runtime domain <command>
27
+ domains: `runtime domains <command>
20
28
 
21
29
  add <hostname> <sandbox> <port> Serve a sandbox's port at your own hostname, with HTTPS
22
30
  Prints the DNS records to set: a TXT that proves the
@@ -27,7 +35,7 @@ export const NETWORK_HELP = {
27
35
  rm <hostname> Stop serving it
28
36
  Needs a kept top-up. The first visit gets the certificate, in a few seconds.
29
37
  `,
30
- port: `runtime port <command>
38
+ ports: `runtime ports <command>
31
39
 
32
40
  open <sandbox> <port> A public TCP port to a port in the sandbox: Postgres,
33
41
  Redis, a game server, anything that is not HTTP
@@ -36,7 +44,7 @@ export const NETWORK_HELP = {
36
44
  close <portId> Close one, its open connections too
37
45
  Needs a kept top-up. TCP, carried as it is: use your service's own password and TLS.
38
46
  `,
39
- address: `runtime address <command>
47
+ ips: `runtime ips <command>
40
48
 
41
49
  reserve [--ipv6] A dedicated outbound address: every sandbox of your
42
50
  account sends from it, for allow-lists
@@ -44,7 +52,7 @@ export const NETWORK_HELP = {
44
52
  release <addressId> Give it back; sandboxes use the shared addresses again
45
53
  Needs credit on the account.
46
54
  `,
47
- tunnel: `runtime tunnel <command>
55
+ wireguard: `runtime networks wireguard <command>
48
56
 
49
57
  create [--subnet 10.250.0.0/16] A WireGuard tunnel from your network into your sandboxes
50
58
  get The tunnel, its peers, and each sandbox's address in it
@@ -58,7 +66,9 @@ export const NETWORK_HELP = {
58
66
  peer rm <peerId> Remove it; its tunnel ends within seconds
59
67
  --route: your own ranges behind the peer that sandboxes may reach. Needs a kept top-up.
60
68
  `,
61
- network: `runtime network <command>
69
+ networks: `runtime networks <command>
70
+ wireguard <command> A WireGuard tunnel from your network into your
71
+ sandboxes: runtime networks wireguard help
62
72
 
63
73
  upstream-proxy set <http://host:port|https://host:port> [--secret NAME] [--host <host>]...
64
74
  Send your sandboxes' outbound connections through your
@@ -76,6 +86,12 @@ export const NETWORK_HELP = {
76
86
  private off They stop; open connections between them are cut
77
87
  private status On or off
78
88
  Only your own sandboxes answer. Needs a kept top-up; free.
89
+
90
+ signed-requests on Your sandboxes can get Runtime's Web Bot Auth signature
91
+ for outbound HTTP requests (https://withruntime.com/docs/egress)
92
+ signed-requests off New signatures stop at once; given ones expire within 5 minutes
93
+ signed-requests status On or off
94
+ Needs credit on the account; free.
79
95
  `,
80
96
  };
81
97
  function usage(product, message) {
@@ -83,7 +99,7 @@ function usage(product, message) {
83
99
  message,
84
100
  code: "usage",
85
101
  status: 0,
86
- hint: `Run \`${named("runtime")} ${product} help\`.`,
102
+ hint: `Run \`${named("runtime")} ${NETWORK_COMMAND[product]} help\`.`,
87
103
  });
88
104
  }
89
105
  function table(rows) {
@@ -127,7 +143,7 @@ async function prepareOutput(path, privateKey) {
127
143
  try {
128
144
  const info = await lstat(path);
129
145
  if (!info.isFile() || info.isSymbolicLink())
130
- throw usage("tunnel", "The output must be a regular file, not a directory or symbolic link.");
146
+ throw usage("wireguard", "The output must be a regular file, not a directory or symbolic link.");
131
147
  }
132
148
  catch (error) {
133
149
  if (error.code !== "ENOENT")
@@ -181,7 +197,7 @@ export async function networkProductCommand(product, argv, args, out, client) {
181
197
  return 0;
182
198
  }
183
199
  const runtime = await client();
184
- if (product === "domain") {
200
+ if (product === "domains") {
185
201
  const records = (domain) => table([
186
202
  ["TYPE", "NAME", "VALUE"],
187
203
  ...domain.records.map((record) => [record.type, record.name, record.value]),
@@ -214,7 +230,7 @@ export async function networkProductCommand(product, argv, args, out, client) {
214
230
  String(d.port),
215
231
  ]),
216
232
  ])
217
- : named("No domains. Add one: runtime domain add app.example.com <sandbox> 3000"), all);
233
+ : named("No domains. Add one: runtime domains add app.example.com <sandbox> 3000"), all);
218
234
  return 0;
219
235
  }
220
236
  case "get": {
@@ -230,7 +246,7 @@ export async function networkProductCommand(product, argv, args, out, client) {
230
246
  }
231
247
  }
232
248
  }
233
- if (product === "port") {
249
+ if (product === "ports") {
234
250
  switch (verb) {
235
251
  case "open": {
236
252
  const opened = await runtime.ports.open({
@@ -251,7 +267,7 @@ export async function networkProductCommand(product, argv, args, out, client) {
251
267
  ["ID", "CONNECT", "SANDBOX", "PORT"],
252
268
  ...all.map((p) => [p.id, p.connect, p.sandboxId, String(p.port)]),
253
269
  ])
254
- : named("No open ports. Open one: runtime port open <sandbox> 5432"), all);
270
+ : named("No open ports. Open one: runtime ports open <sandbox> 5432"), all);
255
271
  return 0;
256
272
  }
257
273
  case "close":
@@ -262,10 +278,10 @@ export async function networkProductCommand(product, argv, args, out, client) {
262
278
  }
263
279
  }
264
280
  }
265
- if (product === "address") {
281
+ if (product === "ips") {
266
282
  switch (verb) {
267
283
  case "reserve": {
268
- const reserved = await runtime.addresses.reserve({ family: has("ipv6") ? 6 : 4 });
284
+ const reserved = await runtime.ips.reserve({ family: has("ipv6") ? 6 : 4 });
269
285
  if (!out.json)
270
286
  out.error(reserved.funded === true
271
287
  ? `Every sandbox of this account sends from it. ${fundingState(reserved)}`
@@ -275,24 +291,24 @@ export async function networkProductCommand(product, argv, args, out, client) {
275
291
  }
276
292
  case "ls":
277
293
  case "list": {
278
- const all = await runtime.addresses.list();
294
+ const all = await runtime.ips.list();
279
295
  print(all.length
280
296
  ? table([
281
297
  ["ID", "ADDRESS", "FAMILY", "FUNDING"],
282
298
  ...all.map((a) => [a.id, a.address, `IPv${a.family}`, fundingState(a)]),
283
299
  ])
284
- : named("No dedicated address. Reserve one: runtime address reserve"), all);
300
+ : named("No dedicated address. Reserve one: runtime ips reserve"), all);
285
301
  return 0;
286
302
  }
287
303
  case "release":
288
304
  case "rm": {
289
- const gone = await runtime.addresses.release(need(rest[0], "an address id"));
305
+ const gone = await runtime.ips.release(need(rest[0], "an address id"));
290
306
  print(`Released ${gone.address}.`, gone);
291
307
  return 0;
292
308
  }
293
309
  }
294
310
  }
295
- if (product === "tunnel") {
311
+ if (product === "wireguard") {
296
312
  const view = (tunnel) => [
297
313
  fundingState(tunnel),
298
314
  `Endpoint ${tunnel.endpoint}, subnet ${tunnel.subnet}, gateway key ${tunnel.gatewayPublicKey ?? "(starting)"}`,
@@ -302,7 +318,7 @@ export async function networkProductCommand(product, argv, args, out, client) {
302
318
  ["PEER", "NAME", "ADDRESS", "ROUTES"],
303
319
  ...tunnel.peers.map((p) => [p.id, p.name, p.address, p.routes.join(",") || "-"]),
304
320
  ])
305
- : named("No peers. Add one: runtime tunnel peer add office --route 10.0.0.0/16"),
321
+ : named("No peers. Add one: runtime networks wireguard peer add office --route 10.0.0.0/16"),
306
322
  "",
307
323
  tunnel.sandboxes.length
308
324
  ? table([
@@ -313,19 +329,19 @@ export async function networkProductCommand(product, argv, args, out, client) {
313
329
  ].join("\n");
314
330
  switch (verb) {
315
331
  case "create": {
316
- const made = await runtime.tunnel.create(flag("subnet") ? { subnet: flag("subnet") } : {});
332
+ const made = await runtime.networks.wireguard.create(flag("subnet") ? { subnet: flag("subnet") } : {});
317
333
  print(view(made), made);
318
334
  return 0;
319
335
  }
320
336
  case "get":
321
337
  case "ls": {
322
- const found = await runtime.tunnel.get();
338
+ const found = await runtime.networks.wireguard.get();
323
339
  print(view(found), found);
324
340
  return 0;
325
341
  }
326
342
  case "rm":
327
343
  case "delete": {
328
- const gone = await runtime.tunnel.delete();
344
+ const gone = await runtime.networks.wireguard.delete();
329
345
  print(`Deleted the tunnel ${gone.id}.`, gone);
330
346
  return 0;
331
347
  }
@@ -343,14 +359,14 @@ export async function networkProductCommand(product, argv, args, out, client) {
343
359
  const prepared = path ? await prepareOutput(path, pair?.privateKey) : undefined;
344
360
  try {
345
361
  const answer = action === "add"
346
- ? await runtime.tunnel.addPeer({
362
+ ? await runtime.networks.wireguard.addPeer({
347
363
  name: argument,
348
364
  publicKey,
349
365
  routes: args.flags.get("route") ?? [],
350
366
  })
351
- : await runtime.tunnel.rotatePeer(argument, { publicKey });
367
+ : await runtime.networks.wireguard.rotatePeer(argument, { publicKey });
352
368
  const configReady = answer.configReady ?? !!answer.config;
353
- const draftHint = "Keep this file: it preserves your private key. Read runtime tunnel get when the gateway is ready, replace PublicKey in [Peer] with gatewayPublicKey, then run wg-quick up.";
369
+ const draftHint = "Keep this file: it preserves your private key. Read runtime networks wireguard get when the gateway is ready, replace PublicKey in [Peer] with gatewayPublicKey, then run wg-quick up.";
354
370
  // Older servers returned no config while the gateway was starting.
355
371
  // Preserve the locally generated key in a draft rather than discard it.
356
372
  const supplied = answer.config ??
@@ -361,7 +377,7 @@ export async function networkProductCommand(product, argv, args, out, client) {
361
377
  `Address = ${answer.peer.address}/32`,
362
378
  "",
363
379
  "[Peer]",
364
- `PublicKey = ${answer.tunnel.gatewayPublicKey ?? "<gatewayPublicKey from runtime tunnel get>"}`,
380
+ `PublicKey = ${answer.tunnel.gatewayPublicKey ?? "<gatewayPublicKey from runtime networks wireguard get>"}`,
365
381
  `Endpoint = ${answer.tunnel.endpoint}`,
366
382
  `AllowedIPs = ${answer.tunnel.subnet}`,
367
383
  "PersistentKeepalive = 25",
@@ -398,7 +414,7 @@ export async function networkProductCommand(product, argv, args, out, client) {
398
414
  }
399
415
  }
400
416
  if (action === "rm" || action === "remove") {
401
- const after = await runtime.tunnel.removePeer(need(rest[1], "a peer id"));
417
+ const after = await runtime.networks.wireguard.removePeer(need(rest[1], "a peer id"));
402
418
  print(`Removed. ${after.peers.length} peer(s) left.`, after);
403
419
  return 0;
404
420
  }
@@ -406,32 +422,58 @@ export async function networkProductCommand(product, argv, args, out, client) {
406
422
  }
407
423
  }
408
424
  }
409
- if (product === "network" && verb === "private") {
425
+ if (product === "networks" && verb === "private") {
410
426
  const describe = (state) => state.enabled
411
427
  ? "On: your sandboxes reach each other at <name>.sandbox.internal:<port> over TCP."
412
428
  : state.allowed
413
- ? "Off. Turn it on: runtime network private on"
429
+ ? "Off. Turn it on: runtime networks private on"
414
430
  : "Off. Reaching your sandboxes by name needs a kept top-up.";
415
431
  switch (rest[0]) {
416
432
  case "on":
417
433
  case "off": {
418
- const state = await runtime.network.private.set({ enabled: rest[0] === "on" });
434
+ const state = await runtime.networks.private.set({ enabled: rest[0] === "on" });
419
435
  print(state.enabled ? describe(state) : "Off. Open connections between your sandboxes are cut.", state);
420
436
  return 0;
421
437
  }
422
438
  case "status":
423
439
  case undefined: {
424
- const state = await runtime.network.private.get();
440
+ const state = await runtime.networks.private.get();
425
441
  print(describe(state), state);
426
442
  return 0;
427
443
  }
428
444
  }
429
445
  throw usage(product, "private takes on, off or status.");
430
446
  }
431
- if (product === "network") {
447
+ if (product === "networks" && verb === "signed-requests") {
448
+ const describe = (state) => state.enabled
449
+ ? "On. Each site's headers: https://withruntime.com/docs/egress"
450
+ : state.allowed
451
+ ? "Off. Turn it on: runtime networks signed-requests on"
452
+ : state.why === "no_credit"
453
+ ? "Needs credit on the account."
454
+ : `Not available (${state.why ?? "unknown"}).`;
455
+ switch (rest[0]) {
456
+ case "on":
457
+ case "off": {
458
+ const state = await runtime.networks.signedRequests.set({ enabled: rest[0] === "on" });
459
+ print(state.enabled
460
+ ? describe(state)
461
+ : "Off. New signatures stop at once; ones already given expire within 5 minutes.", state);
462
+ return 0;
463
+ }
464
+ case "status":
465
+ case undefined: {
466
+ const state = await runtime.networks.signedRequests.get();
467
+ print(describe(state), state);
468
+ return 0;
469
+ }
470
+ }
471
+ throw usage(product, "signed-requests takes on, off or status.");
472
+ }
473
+ if (product === "networks") {
432
474
  if (verb !== "upstream-proxy")
433
- throw usage(product, `Unknown network command ${verb}.`);
434
- const upstream = runtime.network.upstreamProxy;
475
+ throw usage(product, `Unknown networks command ${verb}.`);
476
+ const upstream = runtime.networks.upstreamProxy;
435
477
  const describe = (proxy) => [
436
478
  `Outbound connections${proxy.hosts?.length ? ` to ${proxy.hosts.join(", ")}` : ""} go through ${proxy.url}.`,
437
479
  ...(proxy.secret ? [`${proxy.secret} is sent as Proxy-Authorization.`] : []),
@@ -462,7 +504,7 @@ export async function networkProductCommand(product, argv, args, out, client) {
462
504
  catch (error) {
463
505
  if (!(error instanceof RuntimeError) || error.code !== "not_found")
464
506
  throw error;
465
- print(named("No upstream proxy. Set one: runtime network upstream-proxy set http://proxy.example.com:3128"), null);
507
+ print(named("No upstream proxy. Set one: runtime networks upstream-proxy set http://proxy.example.com:3128"), null);
466
508
  return 0;
467
509
  }
468
510
  print(describe(found), found);
@@ -477,5 +519,5 @@ export async function networkProductCommand(product, argv, args, out, client) {
477
519
  }
478
520
  throw usage(product, "upstream-proxy takes set, get or remove.");
479
521
  }
480
- throw usage(product, `Unknown ${product} command ${verb}.`);
522
+ throw usage(product, `Unknown ${NETWORK_COMMAND[product]} command ${verb}.`);
481
523
  }
@@ -0,0 +1,11 @@
1
+ /** `withruntime/networks`: Networks alone. The account's networks: WireGuard in, sandboxes by name, your proxy out.
2
+ *
3
+ * import { networks } from "withruntime/networks";
4
+ * const client = networks(); // RUNTIME_API_KEY, or this machine's saved connection
5
+ */
6
+ import { Runtime, type RuntimeOptions } from "../client.js";
7
+ export type { Tunnel, TunnelPeer, TunnelPeerCreated, UpstreamProxy, SetUpstreamProxy, } from "../products/network-products.js";
8
+ export type { PrivateNetwork } from "../products/private-network.js";
9
+ export type { SignedRequests } from "../products/signed-requests.js";
10
+ /** `runtime.networks` of a client made with `options`. */
11
+ export declare function networks(options?: RuntimeOptions): Runtime["networks"];
@@ -0,0 +1,10 @@
1
+ /** `withruntime/networks`: Networks alone. The account's networks: WireGuard in, sandboxes by name, your proxy out.
2
+ *
3
+ * import { networks } from "withruntime/networks";
4
+ * const client = networks(); // RUNTIME_API_KEY, or this machine's saved connection
5
+ */
6
+ import { Runtime } from "../client.js";
7
+ /** `runtime.networks` of a client made with `options`. */
8
+ export function networks(options) {
9
+ return new Runtime(options).networks;
10
+ }
@@ -0,0 +1,9 @@
1
+ /** `withruntime/ports`: Ports alone. A public TCP port to a sandbox's port.
2
+ *
3
+ * import { ports } from "withruntime/ports";
4
+ * const client = ports(); // RUNTIME_API_KEY, or this machine's saved connection
5
+ */
6
+ import { Runtime, type RuntimeOptions } from "../client.js";
7
+ export type { TcpPort } from "../products/network-products.js";
8
+ /** `runtime.ports` of a client made with `options`. */
9
+ export declare function ports(options?: RuntimeOptions): Runtime["ports"];
@@ -0,0 +1,10 @@
1
+ /** `withruntime/ports`: Ports alone. A public TCP port to a sandbox's port.
2
+ *
3
+ * import { ports } from "withruntime/ports";
4
+ * const client = ports(); // RUNTIME_API_KEY, or this machine's saved connection
5
+ */
6
+ import { Runtime } from "../client.js";
7
+ /** `runtime.ports` of a client made with `options`. */
8
+ export function ports(options) {
9
+ return new Runtime(options).ports;
10
+ }
@@ -0,0 +1,52 @@
1
+ /** CLOUD.md section 4: one plural word per product on every interface (Marc,
2
+ * 6 October 2026). The API path `/v1/<name>`, the SDK's `runtime.<name>`, the
3
+ * CLI's `runtime <name>` and the MCP's `runtime_<name>` all use `name` below;
4
+ * the CLI also takes `singular` as a typing shortcut, and nothing else does.
5
+ *
6
+ * An old name keeps working for ALIAS_DAYS after the rename ships, with a
7
+ * warning naming the new one, then fails with `name_retired` and a hint. Its
8
+ * `retires` is null until the deploy that ships the rename sets it: the date
9
+ * is the deploy's, never a guess made before it.
10
+ *
11
+ * This is the one table of product names. PRODUCT_LAUNCHES in mcp-groups.ts
12
+ * says whether a product is open; this says what it is called. */
13
+ export declare const ALIAS_DAYS = 30;
14
+ /** CLOUD.md section 2's seven engines. */
15
+ export type Engine = "machine" | "disk" | "record" | "address" | "identity" | "meter" | "database";
16
+ export type OldName = {
17
+ /** The old word, as it appeared on any interface: `sandbox` stands for
18
+ * `/v1/sandbox`, `runtime.sandbox`, `runtime sandbox` and
19
+ * `runtime_sandbox_*`. Separators are compared as one (`-` and `_`). */
20
+ readonly name: string;
21
+ /** ISO date (UTC midnight) on which the old name stops working; null until
22
+ * the rename's deploy sets it to that day plus ALIAS_DAYS. */
23
+ readonly retires: string | null;
24
+ /** Where the old word's things now live inside the product, when not at
25
+ * its root: the WireGuard tunnel was `tunnel` and is `networks/wireguard`,
26
+ * leaving `/v1/networks` free to list private networks. */
27
+ readonly under?: string;
28
+ };
29
+ export type ProductName = {
30
+ /** The plural word on every interface. */
31
+ readonly name: string;
32
+ /** What a customer reads in a title. */
33
+ readonly title: string;
34
+ readonly engine: Engine;
35
+ /** The CLI-only shortcut; absent when the name has no singular. */
36
+ readonly singular?: string;
37
+ readonly old: readonly OldName[];
38
+ };
39
+ /** Every product, in CLOUD.md section 2's order. Old names are only the ones a
40
+ * customer could have called: a planned name that never shipped has none. */
41
+ export declare const PRODUCT_NAMES: readonly ProductName[];
42
+ /** CLOUD.md section 4: what spans products, at the top level, as it is. */
43
+ export declare const TOP_LEVEL: readonly string[];
44
+ /** `-` and `_` are one separator: the API path says `web-analytics`, the MCP
45
+ * tool `runtime_web_analytics`. */
46
+ export declare function wordOf(name: string): string;
47
+ /** The table's own rules: each word means one thing. No shortcut or old name
48
+ * is a product's name. An old name may equal a shortcut: its own product's
49
+ * (`sandbox`, silent in the CLI, a warning elsewhere) or another's (`tunnel`,
50
+ * whose old name wins until it retires, and then the shortcut takes over).
51
+ * Returns the problems found. */
52
+ export declare function validateProductNames(table?: readonly ProductName[]): string[];
@@ -0,0 +1,164 @@
1
+ /** CLOUD.md section 4: one plural word per product on every interface (Marc,
2
+ * 6 October 2026). The API path `/v1/<name>`, the SDK's `runtime.<name>`, the
3
+ * CLI's `runtime <name>` and the MCP's `runtime_<name>` all use `name` below;
4
+ * the CLI also takes `singular` as a typing shortcut, and nothing else does.
5
+ *
6
+ * An old name keeps working for ALIAS_DAYS after the rename ships, with a
7
+ * warning naming the new one, then fails with `name_retired` and a hint. Its
8
+ * `retires` is null until the deploy that ships the rename sets it: the date
9
+ * is the deploy's, never a guess made before it.
10
+ *
11
+ * This is the one table of product names. PRODUCT_LAUNCHES in mcp-groups.ts
12
+ * says whether a product is open; this says what it is called. */
13
+ export const ALIAS_DAYS = 30;
14
+ /** The batch of 6 October 2026: shared by every old name it retired. Set at
15
+ * its deploy to that day plus ALIAS_DAYS. */
16
+ const RENAME_OF_6_OCTOBER = null;
17
+ const was = (...names) => names.map((name) => ({ name, retires: RENAME_OF_6_OCTOBER }));
18
+ /** Every product, in CLOUD.md section 2's order. Old names are only the ones a
19
+ * customer could have called: a planned name that never shipped has none. */
20
+ export const PRODUCT_NAMES = [
21
+ // Machine
22
+ {
23
+ name: "sandboxes",
24
+ title: "Sandboxes",
25
+ engine: "machine",
26
+ singular: "sandbox",
27
+ old: was("sandbox"),
28
+ },
29
+ { name: "browsers", title: "Browsers", engine: "machine", singular: "browser", old: [] },
30
+ { name: "desktops", title: "Desktops", engine: "machine", singular: "desktop", old: [] },
31
+ { name: "apps", title: "Apps", engine: "machine", singular: "app", old: [] },
32
+ { name: "functions", title: "Functions", engine: "machine", singular: "function", old: [] },
33
+ { name: "containers", title: "Containers", engine: "machine", singular: "container", old: [] },
34
+ { name: "jobs", title: "Jobs", engine: "machine", singular: "job", old: was("job") },
35
+ { name: "workflows", title: "Workflows", engine: "machine", singular: "workflow", old: [] },
36
+ { name: "builds", title: "Builds", engine: "machine", singular: "build", old: [] },
37
+ // Disk
38
+ { name: "volumes", title: "Volumes", engine: "disk", singular: "volume", old: was("volume") },
39
+ {
40
+ name: "snapshots",
41
+ title: "Snapshots",
42
+ engine: "disk",
43
+ singular: "snapshot",
44
+ old: was("snapshot"),
45
+ },
46
+ { name: "images", title: "Images", engine: "disk", singular: "image", old: was("image") },
47
+ { name: "buckets", title: "Buckets", engine: "disk", singular: "bucket", old: [] },
48
+ { name: "backups", title: "Backups", engine: "disk", singular: "backup", old: [] },
49
+ // Record
50
+ { name: "queues", title: "Queues", engine: "record", singular: "queue", old: [] },
51
+ { name: "streams", title: "Streams", engine: "record", singular: "stream", old: [] },
52
+ { name: "realtime", title: "Realtime", engine: "record", old: [] },
53
+ { name: "events", title: "Events", engine: "record", old: [] },
54
+ { name: "webhooks", title: "Webhooks", engine: "record", singular: "webhook", old: [] },
55
+ { name: "logs", title: "Logs", engine: "record", singular: "log", old: [] },
56
+ { name: "traces", title: "Traces", engine: "record", singular: "trace", old: [] },
57
+ { name: "alerts", title: "Alerts", engine: "record", singular: "alert", old: [] },
58
+ // Address. `networks` is the private network, which the guides called
59
+ // `runtime tunnel` (WireGuard) and `runtime network`; `tunnels` is incoming
60
+ // tunnels, ngrok's kind. Static IPs were `runtime address`.
61
+ { name: "domains", title: "Domains", engine: "address", singular: "domain", old: was("domain") },
62
+ { name: "dns", title: "DNS", engine: "address", old: [] },
63
+ { name: "balancers", title: "Load balancers", engine: "address", singular: "balancer", old: [] },
64
+ { name: "cdn", title: "CDN", engine: "address", old: [] },
65
+ {
66
+ name: "networks",
67
+ title: "Private networks",
68
+ engine: "address",
69
+ singular: "network",
70
+ old: [...was("network"), { name: "tunnel", retires: RENAME_OF_6_OCTOBER, under: "wireguard" }],
71
+ },
72
+ { name: "tunnels", title: "Tunnels", engine: "address", singular: "tunnel", old: [] },
73
+ {
74
+ name: "ips",
75
+ title: "Static IPs",
76
+ engine: "address",
77
+ singular: "ip",
78
+ old: was("address", "addresses"),
79
+ },
80
+ { name: "ports", title: "Public ports", engine: "address", singular: "port", old: was("port") },
81
+ { name: "firewall", title: "Firewall", engine: "address", old: [] },
82
+ { name: "uptime", title: "Uptime checks", engine: "address", old: [] },
83
+ // Identity
84
+ { name: "teams", title: "Teams", engine: "identity", singular: "team", old: [] },
85
+ { name: "keys", title: "API keys", engine: "identity", singular: "key", old: [] },
86
+ { name: "sso", title: "Single sign-on", engine: "identity", old: [] },
87
+ { name: "secrets", title: "Secrets", engine: "identity", singular: "secret", old: [] },
88
+ { name: "audit", title: "Audit log", engine: "identity", old: [] },
89
+ { name: "tokens", title: "Identity tokens", engine: "identity", singular: "token", old: [] },
90
+ // Meter
91
+ { name: "usage", title: "Usage", engine: "meter", old: [] },
92
+ { name: "billing", title: "Billing", engine: "meter", old: [] },
93
+ { name: "metrics", title: "Metrics", engine: "meter", old: [] },
94
+ // Database (not now: CLOUD.md section 2)
95
+ { name: "postgres", title: "Postgres", engine: "database", old: [] },
96
+ { name: "mysql", title: "MySQL", engine: "database", old: [] },
97
+ { name: "redis", title: "Redis", engine: "database", old: [] },
98
+ { name: "vector", title: "Vector", engine: "database", old: [] },
99
+ { name: "search", title: "Search", engine: "database", old: [] },
100
+ { name: "analytics", title: "Analytics", engine: "database", old: [] },
101
+ { name: "web-analytics", title: "Web analytics", engine: "database", old: [] },
102
+ ];
103
+ /** CLOUD.md section 4: what spans products, at the top level, as it is. */
104
+ export const TOP_LEVEL = [
105
+ "account",
106
+ "billing",
107
+ "usage",
108
+ "compare",
109
+ "keys",
110
+ "secrets",
111
+ "events",
112
+ "webhooks",
113
+ "ls",
114
+ "feedback",
115
+ "support",
116
+ ];
117
+ /** `-` and `_` are one separator: the API path says `web-analytics`, the MCP
118
+ * tool `runtime_web_analytics`. */
119
+ export function wordOf(name) {
120
+ return name.toLowerCase().replaceAll("_", "-");
121
+ }
122
+ /** The table's own rules: each word means one thing. No shortcut or old name
123
+ * is a product's name. An old name may equal a shortcut: its own product's
124
+ * (`sandbox`, silent in the CLI, a warning elsewhere) or another's (`tunnel`,
125
+ * whose old name wins until it retires, and then the shortcut takes over).
126
+ * Returns the problems found. */
127
+ export function validateProductNames(table = PRODUCT_NAMES) {
128
+ const problems = [];
129
+ const current = new Map();
130
+ for (const product of table) {
131
+ const word = wordOf(product.name);
132
+ if (word !== product.name)
133
+ problems.push(`${product.name}: write the name in its API form`);
134
+ if (current.has(word))
135
+ problems.push(`${word}: named twice`);
136
+ current.set(word, product.name);
137
+ }
138
+ const shortcuts = new Map();
139
+ for (const product of table) {
140
+ if (!product.singular)
141
+ continue;
142
+ const word = wordOf(product.singular);
143
+ if (current.has(word))
144
+ problems.push(`${product.name}: shortcut ${word} is a product's name`);
145
+ if (shortcuts.has(word))
146
+ problems.push(`${word}: shortcut of two products`);
147
+ shortcuts.set(word, product.name);
148
+ }
149
+ const olds = new Set();
150
+ for (const product of table) {
151
+ for (const old of product.old) {
152
+ const word = wordOf(old.name);
153
+ if (current.has(word))
154
+ problems.push(`${product.name}: old name ${word} is a product's name`);
155
+ if (olds.has(word))
156
+ problems.push(`${word}: old name of two products`);
157
+ if (old.retires !== null && !/^\d{4}-\d{2}-\d{2}$/.test(old.retires)) {
158
+ problems.push(`${word}: retires must be a date, YYYY-MM-DD`);
159
+ }
160
+ olds.add(word);
161
+ }
162
+ }
163
+ return problems;
164
+ }