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 +7 -5
- package/dist/identity.js +45 -22
- package/dist/machine.d.ts +4 -1
- package/dist/machine.js +3 -1
- package/dist/transport.d.ts +1 -1
- package/dist/transport.js +1 -1
- package/package.json +1 -1
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
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
|
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 = (
|
|
48
|
-
const url = new 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 ${
|
|
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
|
|
59
|
-
//
|
|
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
|
|
63
|
-
if (
|
|
64
|
-
|
|
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(
|
|
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(
|
|
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",
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RuntimeError } from "./errors.js";
|
|
2
|
-
export declare const VERSION = "0.16.
|
|
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.
|
|
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
|