withruntime 0.16.0 → 0.16.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.
package/dist/cli.js CHANGED
@@ -161,9 +161,10 @@ const SANDBOX_HELP = `runtime sandboxes <command>
161
161
  switch-image <id> <image> --keep-workspace Move it to another image, keeping /workspace (your home),
162
162
  volumes, env and previews; processes restart, the rest of
163
163
  its disk is lost (snapshot it first to keep everything)
164
- resize <id> [--vcpu 2] [--memory 4096] --restart
165
- Change its size by a restart: the whole disk stays,
166
- programs stop (snapshot it first to keep memory)
164
+ resize <id> [--vcpu 2] [--memory 4096] [--disk 20480] --restart
165
+ Change its size by a restart: the whole disk stays and
166
+ --disk only grows it; programs stop (snapshot it first
167
+ to keep memory)
167
168
  extend <id> <seconds> Move a time limit on (one with none needs nothing)
168
169
  update <id> [--name n] [--label k=v]... [--env K=V]... [--unset-env K]... [--idle-pause <seconds>] [--auto-wake on|off]
169
170
  [--persistent on|off] [--max-total-cost <usd>|none]
@@ -1718,13 +1719,14 @@ async function sandbox(argv, env, out) {
1718
1719
  return 0;
1719
1720
  }
1720
1721
  case "resize": {
1721
- const args = parse(rest, ["restart"], ["vcpu", "memory"]);
1722
+ const args = parse(rest, ["restart"], ["vcpu", "memory", "disk"]);
1722
1723
  const sbx = await use(need(args.positional[0], `a sandbox, e.g. ${me} sandboxes resize <id> --memory 4096 --restart`));
1723
1724
  const size = {
1724
1725
  ...(integer(args, "vcpu") !== undefined ? { vcpu: integer(args, "vcpu") } : {}),
1725
1726
  ...(integer(args, "memory") !== undefined ? { memoryMiB: integer(args, "memory") } : {}),
1727
+ ...(integer(args, "disk") !== undefined ? { diskMiB: integer(args, "disk") } : {}),
1726
1728
  };
1727
- if (size.vcpu === undefined && size.memoryMiB === undefined)
1729
+ if (size.vcpu === undefined && size.memoryMiB === undefined && size.diskMiB === undefined)
1728
1730
  throw usage(`Name a new size, e.g. ${me} sandboxes resize ${sbx.id} --memory 4096 --restart`);
1729
1731
  if (!args.flags.has("restart"))
1730
1732
  throw usage(`A resize restarts it: its whole disk stays and its programs stop. Add --restart to say so, or snapshot it first (${me} sandboxes snapshot ${sbx.id}) to keep its memory too.`);
package/dist/identity.js CHANGED
@@ -1,29 +1,51 @@
1
1
  import { RuntimeError } from "./errors.js";
2
2
  import { sandboxMarker } from "./transport.js";
3
- /** The guest's environment file, which holds the sandbox's current request
4
- * token: the guest writes it again when the token changes (a wake on another
5
- * server, a restore), while a process keeps the environment it started with. */
3
+ async function requestCredentials() {
4
+ const url = process.env.RUNTIME_ID_TOKEN_REQUEST_URL;
5
+ const token = process.env.RUNTIME_ID_TOKEN_REQUEST_TOKEN;
6
+ if (url && token)
7
+ return { url, token };
8
+ // A process started before the guest wrote its environment still finds it.
9
+ return fileCredentials();
10
+ }
6
11
  async function fileCredentials() {
7
12
  try {
8
13
  // Loaded here, so the SDK still loads where there is no file system.
9
14
  const { readFile } = await import("node:fs/promises");
10
15
  const env = JSON.parse(await readFile(sandboxMarker.path, "utf8"));
11
- return { url: env.RUNTIME_ID_TOKEN_REQUEST_URL, token: env.RUNTIME_ID_TOKEN_REQUEST_TOKEN };
16
+ const url = env.RUNTIME_ID_TOKEN_REQUEST_URL;
17
+ const token = env.RUNTIME_ID_TOKEN_REQUEST_TOKEN;
18
+ return url && token ? { url, token } : null;
12
19
  }
13
20
  catch {
14
21
  return null;
15
22
  }
16
23
  }
17
- async function requestCredentials() {
18
- let url = process.env.RUNTIME_ID_TOKEN_REQUEST_URL;
19
- let token = process.env.RUNTIME_ID_TOKEN_REQUEST_TOKEN;
20
- if (!url || !token) {
21
- // A process started before the guest wrote its environment still finds it.
22
- const file = await fileCredentials();
23
- url = file?.url;
24
- token = file?.token;
24
+ /** The sandbox's own listener (packages/cloud/src/linux/egress.ts). */
25
+ const ENVIRONMENT_URL = "http://runtime.internal/v1/environment";
26
+ /** The sandbox's request token as its host holds it now. The one in
27
+ * process.env was current when the process started: it changes with every
28
+ * renewal of the sandbox's lease (about every 30 minutes for one that keeps
29
+ * running), and a server restored from a snapshot (an App's copies, a fork)
30
+ * holds the statement of the sandbox it was saved from. The host's listener
31
+ * answers this sandbox's own; guest-net.py's file is a few seconds behind it. */
32
+ async function currentCredentials(signal) {
33
+ try {
34
+ const response = await fetch(ENVIRONMENT_URL, {
35
+ signal: signal ?? AbortSignal.timeout(5_000),
36
+ });
37
+ if (response.ok) {
38
+ const env = (await response.json());
39
+ const url = env.RUNTIME_ID_TOKEN_REQUEST_URL;
40
+ const token = env.RUNTIME_ID_TOKEN_REQUEST_TOKEN;
41
+ if (typeof url === "string" && url && typeof token === "string" && token)
42
+ return { url, token };
43
+ }
44
+ }
45
+ catch {
46
+ // Not in a sandbox, or a host that predates the listener's environment.
25
47
  }
26
- return url && token ? { url, token } : null;
48
+ return fileCredentials();
27
49
  }
28
50
  /**
29
51
  * Inside a Runtime sandbox: a short-lived OIDC token, signed by Runtime,
@@ -44,24 +66,25 @@ export async function identityToken(input) {
44
66
  status: 0,
45
67
  message: "Identity tokens are issued only inside a Runtime sandbox (RUNTIME_ID_TOKEN_REQUEST_TOKEN is not set).",
46
68
  });
47
- const ask = (from) => {
48
- const url = new URL(from.url);
69
+ const ask = (credentials) => {
70
+ const url = new URL(credentials.url);
49
71
  url.searchParams.set("audience", input.audience);
50
72
  if (input.lifetimeSeconds !== undefined)
51
73
  url.searchParams.set("lifetimeSeconds", String(input.lifetimeSeconds));
52
74
  return fetch(url, {
53
- headers: { authorization: `Bearer ${from.token}` },
75
+ headers: { authorization: `Bearer ${credentials.token}` },
54
76
  signal: input.signal ?? AbortSignal.timeout(10_000),
55
77
  });
56
78
  };
57
79
  let response = await ask(found);
58
- // Refused for a request token that has since changed: a long-running
59
- // process asks again with the current one from the guest's file (the hub's
60
- // own, 16 October 2026, from its start until it was restarted).
80
+ // Refused for a request token that is no longer this sandbox's current one:
81
+ // ask once more with the one its host holds now.
61
82
  if (response.status === 401 || response.status === 403) {
62
- const file = await fileCredentials();
63
- if (file?.url && file.token && file.token !== found.token)
64
- response = await ask({ url: file.url, token: file.token });
83
+ const current = await currentCredentials(input.signal);
84
+ if (current && current.token !== found.token) {
85
+ await response.body?.cancel();
86
+ response = await ask(current);
87
+ }
65
88
  }
66
89
  const body = (await response.json().catch(() => ({})));
67
90
  if (!response.ok || !body.token)
package/dist/machine.d.ts CHANGED
@@ -95,9 +95,12 @@ export declare abstract class Machine<Info extends MachineInfo, Settings extends
95
95
  * while a snapshot or fork of it is being taken. `restart` is optional:
96
96
  * true is the only value, and it is sent either way, so an API from before
97
97
  * it was optional accepts the call too. */
98
- resize(size: {
98
+ resize(
99
+ /** diskMiB only grows; the filesystem fills it at the restart. */
100
+ size: {
99
101
  vcpu?: number;
100
102
  memoryMiB?: number;
103
+ diskMiB?: number;
101
104
  }, options?: RequestOptions & {
102
105
  restart?: true;
103
106
  }): Promise<this>;
package/dist/machine.js CHANGED
@@ -175,7 +175,9 @@ export class Machine {
175
175
  * while a snapshot or fork of it is being taken. `restart` is optional:
176
176
  * true is the only value, and it is sent either way, so an API from before
177
177
  * it was optional accepts the call too. */
178
- async resize(size, options = {}) {
178
+ async resize(
179
+ /** diskMiB only grows; the filesystem fills it at the restart. */
180
+ size, options = {}) {
179
181
  const { restart = true, ...rest } = options;
180
182
  this.#keep(await this.#t.json({
181
183
  method: "POST",
@@ -1,5 +1,5 @@
1
1
  import { RuntimeError } from "./errors.js";
2
- export declare const VERSION = "0.16.0";
2
+ export declare const VERSION = "0.16.1";
3
3
  export declare const DEFAULT_BASE_URL = "https://api.withruntime.com";
4
4
  /** Runtime's API as code inside a Runtime sandbox reaches it: the sandbox's
5
5
  * own host sends each request on to DEFAULT_BASE_URL over HTTPS. The API runs
package/dist/transport.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ConnectionError, DELIBERATE, errorFor, NOTHING_RAN, RuntimeError, WAITS_FOR_ROOM, } from "./errors.js";
2
2
  import { describeRoute, envFetch, openWebSocket } from "./proxy.js";
3
3
  import { warningText } from "./product-renames.js";
4
- export const VERSION = "0.16.0";
4
+ export const VERSION = "0.16.1";
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "withruntime",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "license": "Apache-2.0",
5
5
  "mcpName": "com.withruntime/runtime",
6
6
  "type": "module",