withruntime 0.11.2 → 0.14.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.
- package/BLAXEL.md +2 -2
- package/COMPATIBILITY.md +74 -9
- package/DAYTONA.md +33 -5
- package/E2B.md +85 -24
- package/README.md +11 -10
- package/README.src.md +10 -9
- package/VERCEL.md +43 -5
- package/compatibility-lock.json +58 -49
- package/dist/billing-cli.d.ts +1 -1
- package/dist/billing-cli.js +85 -5
- package/dist/blaxel/errors.d.ts +14 -0
- package/dist/blaxel/errors.js +29 -0
- package/dist/blaxel/index.d.ts +2 -2
- package/dist/blaxel/index.js +4 -4
- package/dist/blaxel/interpreter.d.ts +2 -5
- package/dist/blaxel/sandbox.d.ts +15 -6
- package/dist/blaxel/sandbox.js +64 -8
- package/dist/blaxel/snapshot.d.ts +4 -0
- package/dist/blaxel/snapshot.js +4 -0
- package/dist/cli/logs.d.ts +21 -0
- package/dist/cli/logs.js +188 -0
- package/dist/cli-extras.d.ts +3 -3
- package/dist/cli-extras.js +17 -12
- package/dist/cli-words.d.ts +10 -1
- package/dist/cli-words.js +18 -0
- package/dist/cli.d.ts +22 -3
- package/dist/cli.js +647 -273
- package/dist/client.d.ts +2 -4
- package/dist/client.js +27 -11
- package/dist/cloudflare/errors.d.ts +143 -0
- package/dist/cloudflare/errors.js +167 -0
- package/dist/cloudflare/index.d.ts +175 -6
- package/dist/cloudflare/index.js +416 -26
- package/dist/cloudflare/interpreter.d.ts +119 -0
- package/dist/cloudflare/interpreter.js +223 -0
- package/dist/cloudflare/streams.d.ts +38 -0
- package/dist/cloudflare/streams.js +145 -0
- package/dist/cloudflare/watch.d.ts +9 -0
- package/dist/cloudflare/watch.js +24 -0
- package/dist/codesandbox/index.d.ts +216 -28
- package/dist/codesandbox/index.js +478 -78
- package/dist/compat/core.d.ts +18 -0
- package/dist/compat/core.js +29 -0
- package/dist/compat/files.d.ts +1 -0
- package/dist/compat/files.js +25 -5
- package/dist/credentials.d.ts +3 -0
- package/dist/credentials.js +15 -0
- package/dist/daytona/computer-use.d.ts +13 -4
- package/dist/daytona/computer-use.js +66 -8
- package/dist/daytona/daytona.d.ts +7 -1
- package/dist/daytona/daytona.js +31 -4
- package/dist/daytona/errors.d.ts +11 -0
- package/dist/daytona/errors.js +18 -0
- package/dist/daytona/filesystem.js +2 -1
- package/dist/daytona/image.d.ts +13 -9
- package/dist/daytona/image.js +18 -12
- package/dist/daytona/index.d.ts +1 -1
- package/dist/daytona/sandbox.d.ts +8 -2
- package/dist/daytona/sandbox.js +16 -2
- package/dist/domains/index.d.ts +9 -0
- package/dist/domains/index.js +10 -0
- package/dist/e2b/commands.d.ts +1 -1
- package/dist/e2b/commands.js +6 -7
- package/dist/e2b/errors.d.ts +17 -0
- package/dist/e2b/errors.js +40 -1
- package/dist/e2b/index.d.ts +2 -2
- package/dist/e2b/index.js +1 -1
- package/dist/e2b/sandbox.d.ts +28 -22
- package/dist/e2b/sandbox.js +34 -8
- package/dist/e2b/unsupported.js +1 -1
- package/dist/errors.d.ts +11 -2
- package/dist/errors.js +17 -5
- package/dist/freestyle/index.d.ts +285 -37
- package/dist/freestyle/index.js +656 -144
- package/dist/identity.d.ts +3 -0
- package/dist/identity.js +27 -0
- package/dist/images/index.d.ts +9 -0
- package/dist/images/index.js +10 -0
- package/dist/index.d.ts +3 -1
- package/dist/ips/index.d.ts +9 -0
- package/dist/ips/index.js +10 -0
- package/dist/jobs/index.d.ts +9 -0
- package/dist/jobs/index.js +10 -0
- package/dist/keys.js +2 -0
- package/dist/login.js +2 -0
- package/dist/machine.d.ts +27 -4
- package/dist/machine.js +46 -14
- package/dist/mcp.js +144 -20
- package/dist/modal/index.d.ts +339 -61
- package/dist/modal/index.js +781 -121
- package/dist/network-cli.d.ts +3 -1
- package/dist/network-cli.js +78 -36
- package/dist/networks/index.d.ts +11 -0
- package/dist/networks/index.js +10 -0
- package/dist/ports/index.d.ts +9 -0
- package/dist/ports/index.js +10 -0
- package/dist/product-names.d.ts +52 -0
- package/dist/product-names.js +164 -0
- package/dist/product-renames.d.ts +103 -0
- package/dist/product-renames.js +189 -0
- package/dist/products/api-keys.d.ts +73 -0
- package/dist/products/api-keys.js +23 -0
- package/dist/products/apps.d.ts +157 -0
- package/dist/products/apps.js +60 -0
- package/dist/products/balancers.d.ts +87 -0
- package/dist/products/balancers.js +8 -0
- package/dist/products/billing.d.ts +41 -0
- package/dist/products/billing.js +13 -0
- package/dist/products/browser.d.ts +10 -0
- package/dist/products/browsers.d.ts +71 -0
- package/dist/products/browsers.js +102 -0
- package/dist/products/builds.d.ts +156 -0
- package/dist/products/builds.js +227 -0
- package/dist/products/index.d.ts +5 -16
- package/dist/products/index.js +5 -14
- package/dist/products/jobs.d.ts +19 -2
- package/dist/products/jobs.js +28 -11
- package/dist/products/logs.d.ts +245 -0
- package/dist/products/logs.js +274 -0
- package/dist/products/network-products.d.ts +38 -7
- package/dist/products/network-products.js +31 -18
- package/dist/products/observability.d.ts +8 -2
- package/dist/products/private-network.js +1 -1
- package/dist/products/queues.d.ts +149 -0
- package/dist/products/queues.js +213 -0
- package/dist/products/referrals.d.ts +21 -7
- package/dist/products/referrals.js +3 -3
- package/dist/products/resources.d.ts +54 -0
- package/dist/products/resources.js +122 -0
- package/dist/products/secrets.d.ts +29 -3
- package/dist/products/secrets.js +47 -18
- package/dist/products/signed-requests.d.ts +21 -0
- package/dist/products/signed-requests.js +11 -0
- package/dist/products/streams.d.ts +73 -0
- package/dist/products/streams.js +17 -0
- package/dist/products/switching.d.ts +35 -7
- package/dist/products/switching.js +4 -3
- package/dist/products/volumes.d.ts +6 -0
- package/dist/record-cli.d.ts +23 -0
- package/dist/record-cli.js +308 -0
- package/dist/renamed-products.d.ts +38 -0
- package/dist/renamed-products.js +34 -0
- package/dist/runloop/index.d.ts +9 -2
- package/dist/runloop/index.js +29 -8
- package/dist/runloop/sdk.d.ts +131 -0
- package/dist/runloop/sdk.js +167 -0
- package/dist/sandbox.d.ts +7 -2
- package/dist/sandbox.js +41 -11
- package/dist/sandboxes/index.d.ts +11 -0
- package/dist/sandboxes/index.js +12 -0
- package/dist/snapshots/index.d.ts +9 -0
- package/dist/snapshots/index.js +11 -0
- package/dist/snapshots.d.ts +7 -4
- package/dist/sprites/index.d.ts +343 -31
- package/dist/sprites/index.js +866 -84
- package/dist/ssh.d.ts +1 -1
- package/dist/ssh.js +11 -11
- package/dist/terminal.d.ts +24 -0
- package/dist/terminal.js +32 -0
- package/dist/transport.d.ts +18 -1
- package/dist/transport.js +80 -6
- package/dist/tunnel.js +1 -1
- package/dist/types.d.ts +71 -4
- package/dist/vercel/sandbox.d.ts +1 -1
- package/dist/vercel/sandbox.js +6 -4
- package/dist/vercel/snapshot.js +10 -2
- package/dist/volumes/index.d.ts +9 -0
- package/dist/volumes/index.js +10 -0
- package/dist/wallet.d.ts +4 -1
- package/dist/wallet.js +2 -1
- package/package.json +48 -14
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { RuntimeError } from "../errors.js";
|
|
2
|
+
import { Page } from "../page.js";
|
|
3
|
+
import { pause } from "../wait.js";
|
|
4
|
+
export const enc = encodeURIComponent;
|
|
5
|
+
function invalid(field) {
|
|
6
|
+
return new RuntimeError({
|
|
7
|
+
code: "invalid_request",
|
|
8
|
+
status: 0,
|
|
9
|
+
message: `${field} must be a finite, nonnegative number.`,
|
|
10
|
+
hint: "Fix the option and call again; nothing was sent.",
|
|
11
|
+
details: { field },
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/** One deadline covers the write, retries and every read. A timed-out delete
|
|
15
|
+
* can be retried after a process restart with this same key. */
|
|
16
|
+
export async function following(options, work) {
|
|
17
|
+
const { pollMs = 250, timeoutMs = 300_000, signal, ...rest } = options;
|
|
18
|
+
if (!Number.isFinite(pollMs) || pollMs < 0)
|
|
19
|
+
throw invalid("pollMs");
|
|
20
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 0)
|
|
21
|
+
throw invalid("timeoutMs");
|
|
22
|
+
const deadline = new AbortController();
|
|
23
|
+
const combined = signal ? AbortSignal.any([signal, deadline.signal]) : deadline.signal;
|
|
24
|
+
const timer = timeoutMs > 0 ? setTimeout(() => deadline.abort(), timeoutMs) : undefined;
|
|
25
|
+
const request = { ...rest, timeoutMs: 0, signal: combined };
|
|
26
|
+
const poll = () => pause(pollMs, combined);
|
|
27
|
+
try {
|
|
28
|
+
combined.throwIfAborted();
|
|
29
|
+
const result = await work(request, poll);
|
|
30
|
+
combined.throwIfAborted();
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
catch (cause) {
|
|
34
|
+
if (!combined.aborted) {
|
|
35
|
+
// A read failure still belongs to the write that started this wait.
|
|
36
|
+
// Keep its key so a caller can recover after losing the reply.
|
|
37
|
+
if (cause instanceof RuntimeError && rest.idempotencyKey && !cause.idempotencyKey)
|
|
38
|
+
throw new RuntimeError({
|
|
39
|
+
message: cause.message,
|
|
40
|
+
code: cause.code,
|
|
41
|
+
status: cause.status,
|
|
42
|
+
requestId: cause.requestId,
|
|
43
|
+
hint: cause.hint,
|
|
44
|
+
details: cause.details,
|
|
45
|
+
retryAfterMs: cause.retryAfterMs,
|
|
46
|
+
idempotencyKey: rest.idempotencyKey,
|
|
47
|
+
cause,
|
|
48
|
+
});
|
|
49
|
+
throw cause;
|
|
50
|
+
}
|
|
51
|
+
throw new RuntimeError({
|
|
52
|
+
code: "timeout",
|
|
53
|
+
status: 0,
|
|
54
|
+
message: "Waiting was cancelled or reached its deadline; the resource may still change.",
|
|
55
|
+
hint: "Read the resource to resume waiting. Retry a write with the same idempotencyKey.",
|
|
56
|
+
...(rest.idempotencyKey === undefined ? {} : { idempotencyKey: rest.idempotencyKey }),
|
|
57
|
+
cause,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
clearTimeout(timer);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** A resource product's client at `/v1/<path>`. A wait ends at its target
|
|
65
|
+
* or at any of `settled`, which answers with the resource's error. */
|
|
66
|
+
export function resource(t, path, settled) {
|
|
67
|
+
const base = `/v1/${path}`;
|
|
68
|
+
const get = (id, options = {}) => {
|
|
69
|
+
const { waitFor, timeoutSeconds, ...request } = options;
|
|
70
|
+
return t.json({
|
|
71
|
+
method: "GET",
|
|
72
|
+
path: `${base}/${enc(id)}`,
|
|
73
|
+
query: { waitFor, timeoutSeconds },
|
|
74
|
+
...request,
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
const list = async (query = {}, options) => {
|
|
78
|
+
const page = await t.json({
|
|
79
|
+
method: "GET",
|
|
80
|
+
path: base,
|
|
81
|
+
query,
|
|
82
|
+
...options,
|
|
83
|
+
});
|
|
84
|
+
return new Page(page.data, page.nextCursor, (cursor) => list({ ...query, cursor }, options));
|
|
85
|
+
};
|
|
86
|
+
const follow = async (id, target, request, pause, initial) => {
|
|
87
|
+
let record = initial ?? (await get(id, request));
|
|
88
|
+
for (;;) {
|
|
89
|
+
if (record.state === target)
|
|
90
|
+
return record;
|
|
91
|
+
if (settled.includes(record.state))
|
|
92
|
+
throw new RuntimeError({
|
|
93
|
+
code: record.error?.code ?? "unexpected_state",
|
|
94
|
+
status: 0,
|
|
95
|
+
message: record.error?.message ?? `Expected ${target}, but ${id} reached ${record.state}.`,
|
|
96
|
+
hint: "Read the resource and inspect its error before starting another change.",
|
|
97
|
+
details: { id, state: record.state, target, resource: record },
|
|
98
|
+
...(request.idempotencyKey === undefined
|
|
99
|
+
? {}
|
|
100
|
+
: { idempotencyKey: request.idempotencyKey }),
|
|
101
|
+
});
|
|
102
|
+
await pause();
|
|
103
|
+
record = await get(id, request);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
base,
|
|
108
|
+
/** Defaults belong to the API, so the SDK does not override them. */
|
|
109
|
+
create: (input, options) => t.json({ method: "POST", path: base, body: input, ...options }),
|
|
110
|
+
get,
|
|
111
|
+
list,
|
|
112
|
+
update: (id, input, options) => t.json({ method: "POST", path: `${base}/${enc(id)}:update`, body: input, ...options }),
|
|
113
|
+
wait: (id, target, options = {}) => following(options, (request, pause) => follow(id, target, request, pause)),
|
|
114
|
+
delete: (id, options = {}) => {
|
|
115
|
+
const { wait = false, pollMs, ...request } = options;
|
|
116
|
+
const remove = (rest) => t.json({ method: "DELETE", path: `${base}/${enc(id)}`, ...rest });
|
|
117
|
+
if (!wait)
|
|
118
|
+
return remove(request);
|
|
119
|
+
return following({ ...request, pollMs, idempotencyKey: request.idempotencyKey ?? crypto.randomUUID() }, async (rest, pause) => follow(id, "deleted", rest, pause, await remove(rest)));
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -9,10 +9,23 @@ export type SecretRule = {
|
|
|
9
9
|
methods?: string[];
|
|
10
10
|
paths: string[];
|
|
11
11
|
};
|
|
12
|
+
/** Which sandboxes get a secret: those whose labels hold every pair of any one
|
|
13
|
+
* selector in `labels` (including sandboxes created or labelled later), and
|
|
14
|
+
* those named in `sandboxes`. Any other sandbox of the organization sees no
|
|
15
|
+
* placeholder, and its requests never carry the value. Absent on a secret:
|
|
16
|
+
* every sandbox of the organization. */
|
|
17
|
+
export type SecretScope = {
|
|
18
|
+
/** 1 to 8 selectors of 1 to 8 key/value pairs: `[{ role: "hub" }]`. */
|
|
19
|
+
labels?: Array<Record<string, string>>;
|
|
20
|
+
/** 1 to 100 sandbox ids of the organization. */
|
|
21
|
+
sandboxes?: string[];
|
|
22
|
+
};
|
|
12
23
|
/** A secret your sandboxes use without seeing it. Every sandbox of your
|
|
13
24
|
* organization has an environment variable of the secret's name holding
|
|
14
|
-
* `placeholder`; the egress proxy
|
|
15
|
-
* `hosts
|
|
25
|
+
* `placeholder`; the egress proxy sets `header` on every HTTPS request to
|
|
26
|
+
* `hosts`, or, without `header`, replaces the placeholder in a credential
|
|
27
|
+
* header (Authorization, x-api-key, x-goog-api-key, api-key, xi-api-key,
|
|
28
|
+
* x-subscription-token, private-token). Never in the URL or another header.
|
|
16
29
|
* The value is never returned. */
|
|
17
30
|
export type Secret = {
|
|
18
31
|
name: string;
|
|
@@ -20,6 +33,8 @@ export type Secret = {
|
|
|
20
33
|
header?: string;
|
|
21
34
|
format?: string;
|
|
22
35
|
rules?: SecretRule[];
|
|
36
|
+
/** Absent: every sandbox of the organization. */
|
|
37
|
+
only?: SecretScope;
|
|
23
38
|
placeholder: string;
|
|
24
39
|
valueBytes: number;
|
|
25
40
|
createdAt: string;
|
|
@@ -33,7 +48,9 @@ export type SetSecret = {
|
|
|
33
48
|
/** Where the value may go: `api.openai.com`, `*.github.com`. 1 to 16.
|
|
34
49
|
* Required unless `jobs` is true. */
|
|
35
50
|
hosts?: string[];
|
|
36
|
-
/** Set this header on every request to the hosts, replacing the sandbox's
|
|
51
|
+
/** Set this header on every request to the hosts, replacing the sandbox's
|
|
52
|
+
* own; the value then goes nowhere else. Needed when the API reads its key
|
|
53
|
+
* from a header that is not a credential header (see `Secret`). */
|
|
37
54
|
header?: string;
|
|
38
55
|
/** With `header`: its value, `{value}` where the secret goes. Default `{value}`. */
|
|
39
56
|
format?: string;
|
|
@@ -41,6 +58,10 @@ export type SetSecret = {
|
|
|
41
58
|
* Absent: every request to the hosts; replacing a secret without rules
|
|
42
59
|
* clears them. */
|
|
43
60
|
rules?: SecretRule[];
|
|
61
|
+
/** Only these sandboxes get it. Absent when replacing a secret: the scope it
|
|
62
|
+
* has stays, so a new value never widens who gets it. `{}`: every sandbox of
|
|
63
|
+
* the organization again. */
|
|
64
|
+
only?: SecretScope;
|
|
44
65
|
/** Also keep a copy for scheduled jobs, which a job puts into its run's
|
|
45
66
|
* environment (`jobs.create({ secrets: [...] })`). Unlike the sandboxes'
|
|
46
67
|
* copy, the jobs copy is yours rather than the account's, versioned, and can
|
|
@@ -94,6 +115,11 @@ export declare function secrets(t: Transport): {
|
|
|
94
115
|
enforced: boolean;
|
|
95
116
|
}>>;
|
|
96
117
|
};
|
|
118
|
+
/** Changes which sandboxes get a secret, without its value: `{}` is every
|
|
119
|
+
* sandbox of the organization again. */
|
|
120
|
+
scope: (name: string, only: SecretScope, options?: RequestOptions) => Promise<Secret & {
|
|
121
|
+
enforced: boolean;
|
|
122
|
+
}>;
|
|
97
123
|
/** The sandboxes' secrets: names, hosts and placeholders. Never values.
|
|
98
124
|
* `all()` includes the jobs copies. */
|
|
99
125
|
list: (options?: RequestOptions) => Promise<Secret[]>;
|
package/dist/products/secrets.js
CHANGED
|
@@ -36,16 +36,47 @@ export function secrets(t) {
|
|
|
36
36
|
const key = (options, part) => options?.idempotencyKey
|
|
37
37
|
? { ...options, idempotencyKey: `${options.idempotencyKey}:${part}`.slice(0, 128) }
|
|
38
38
|
: options;
|
|
39
|
+
const create = (name, value, options) => store({ method: "POST", path: "/v1/secrets", body: { name, value }, ...options });
|
|
40
|
+
const rotate = (live, value, version, options) => store({
|
|
41
|
+
method: "POST",
|
|
42
|
+
path: `${jobPath(live.id)}:rotate`,
|
|
43
|
+
body: { value, expectedVersion: version },
|
|
44
|
+
...options,
|
|
45
|
+
});
|
|
46
|
+
/** Rotates the jobs copy from the version it has now. A key used before,
|
|
47
|
+
* by this same call whose answer was lost, is answered by the identical
|
|
48
|
+
* request again, with no second rotation: the rotate from the version
|
|
49
|
+
* before, or one of `earlier` (a set's create). Until 10 October 2026 the
|
|
50
|
+
* retry read the copy as it is now, changed its request, and was refused
|
|
51
|
+
* as a conflict. */
|
|
52
|
+
async function rotateOrReplay(live, value, options, earlier = []) {
|
|
53
|
+
try {
|
|
54
|
+
return await rotate(live, value, live.version, options);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (!(error instanceof RuntimeError) || error.code !== "idempotency_conflict")
|
|
58
|
+
throw error;
|
|
59
|
+
const replays = [
|
|
60
|
+
...earlier,
|
|
61
|
+
...(live.version > 1 ? [() => rotate(live, value, live.version - 1, options)] : []),
|
|
62
|
+
];
|
|
63
|
+
for (const replay of replays) {
|
|
64
|
+
const answer = await replay().catch((again) => {
|
|
65
|
+
if (again instanceof RuntimeError && again.status === 409)
|
|
66
|
+
return undefined;
|
|
67
|
+
throw again;
|
|
68
|
+
});
|
|
69
|
+
if (answer)
|
|
70
|
+
return answer;
|
|
71
|
+
}
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
39
75
|
async function setJobCopy(name, value, options) {
|
|
40
76
|
const copies = await jobCopies(options);
|
|
41
77
|
const live = copies.find((s) => s.name === name && s.deletedAt === null);
|
|
42
78
|
if (live)
|
|
43
|
-
return
|
|
44
|
-
method: "POST",
|
|
45
|
-
path: `${jobPath(live.id)}:rotate`,
|
|
46
|
-
body: { value, expectedVersion: live.version },
|
|
47
|
-
...options,
|
|
48
|
-
});
|
|
79
|
+
return rotateOrReplay(live, value, options, [() => create(name, value, options)]);
|
|
49
80
|
if (copies.some((s) => s.name === name))
|
|
50
81
|
throw new RuntimeError({
|
|
51
82
|
message: `A jobs secret named ${name} was deleted, and a deleted name cannot be used again.`,
|
|
@@ -54,12 +85,7 @@ export function secrets(t) {
|
|
|
54
85
|
hint: "Store it under another name.",
|
|
55
86
|
details: { field: "name" },
|
|
56
87
|
});
|
|
57
|
-
return
|
|
58
|
-
method: "POST",
|
|
59
|
-
path: "/v1/secrets",
|
|
60
|
-
body: { name, value },
|
|
61
|
-
...options,
|
|
62
|
-
});
|
|
88
|
+
return create(name, value, options);
|
|
63
89
|
}
|
|
64
90
|
async function all(options) {
|
|
65
91
|
const [forSandboxes, forJobs] = await Promise.all([
|
|
@@ -127,6 +153,14 @@ export function secrets(t) {
|
|
|
127
153
|
* at once store both; if only the first lands, `SecretPartlyStoredError`
|
|
128
154
|
* says so and the same call again finishes it. */
|
|
129
155
|
set,
|
|
156
|
+
/** Changes which sandboxes get a secret, without its value: `{}` is every
|
|
157
|
+
* sandbox of the organization again. */
|
|
158
|
+
scope: (name, only, options) => t.json({
|
|
159
|
+
method: "PUT",
|
|
160
|
+
path: `${path(name)}/sandboxes`,
|
|
161
|
+
body: only,
|
|
162
|
+
...options,
|
|
163
|
+
}),
|
|
130
164
|
/** The sandboxes' secrets: names, hosts and placeholders. Never values.
|
|
131
165
|
* `all()` includes the jobs copies. */
|
|
132
166
|
list,
|
|
@@ -156,12 +190,7 @@ export function secrets(t) {
|
|
|
156
190
|
status: 404,
|
|
157
191
|
hint: "Store one with set(name, { value, jobs: true }). The sandboxes' copy is replaced by set, not rotated.",
|
|
158
192
|
});
|
|
159
|
-
return
|
|
160
|
-
method: "POST",
|
|
161
|
-
path: `${jobPath(live.id)}:rotate`,
|
|
162
|
-
body: { value, expectedVersion: live.version },
|
|
163
|
-
...options,
|
|
164
|
-
});
|
|
193
|
+
return rotateOrReplay(live, value, options);
|
|
165
194
|
},
|
|
166
195
|
/** Read the jobs copy's value back (needs the key's secrets_reveal
|
|
167
196
|
* permission). The sandboxes' copy can never be read back. */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RequestOptions, Transport } from "../transport.js";
|
|
2
|
+
export type SignedRequests = {
|
|
3
|
+
/** Whether your sandboxes may get Runtime's request signature now. */
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
/** Whether this account may turn it on: it must have credit. */
|
|
6
|
+
allowed: boolean;
|
|
7
|
+
/** Why not, when `allowed` is false: `no_credit`, `revoked` or `suspended`. */
|
|
8
|
+
why: string | null;
|
|
9
|
+
enabledAt: string | null;
|
|
10
|
+
disabledAt: string | null;
|
|
11
|
+
};
|
|
12
|
+
export declare function signedRequests(t: Transport): {
|
|
13
|
+
/** On or off, and whether this account may turn it on. */
|
|
14
|
+
get: (options?: RequestOptions) => Promise<SignedRequests>;
|
|
15
|
+
/** `enabled: true` lets your sandboxes get Runtime's request signature;
|
|
16
|
+
* `false` stops new signatures at once, and ones already given expire
|
|
17
|
+
* within 5 minutes. */
|
|
18
|
+
set: (input: {
|
|
19
|
+
enabled: boolean;
|
|
20
|
+
}, options?: RequestOptions) => Promise<SignedRequests>;
|
|
21
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function signedRequests(t) {
|
|
2
|
+
const path = "/v1/networks/signed-requests";
|
|
3
|
+
return {
|
|
4
|
+
/** On or off, and whether this account may turn it on. */
|
|
5
|
+
get: (options) => t.json({ method: "GET", path, ...options }),
|
|
6
|
+
/** `enabled: true` lets your sandboxes get Runtime's request signature;
|
|
7
|
+
* `false` stops new signatures at once, and ones already given expire
|
|
8
|
+
* within 5 minutes. */
|
|
9
|
+
set: (input, options) => t.json({ method: "PUT", path, body: input, ...options }),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { RequestOptions, Transport } from "../transport.js";
|
|
2
|
+
import { type RecordResource } from "./queues.js";
|
|
3
|
+
/** Private until launch.
|
|
4
|
+
* Kafka clients use kafka.bootstrap and kafka.topic unchanged.
|
|
5
|
+
* Offsets and byte counts use decimal strings so JSON never rounds them. */
|
|
6
|
+
export type Stream = RecordResource & {
|
|
7
|
+
partitions: number;
|
|
8
|
+
retentionMs: number;
|
|
9
|
+
retentionBytes: string;
|
|
10
|
+
kafka: {
|
|
11
|
+
bootstrap: string;
|
|
12
|
+
topic: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export type CreateStream = {
|
|
16
|
+
name: string;
|
|
17
|
+
labels?: Record<string, string>;
|
|
18
|
+
partitions?: number;
|
|
19
|
+
retentionMs?: number;
|
|
20
|
+
retentionBytes?: string;
|
|
21
|
+
};
|
|
22
|
+
export type UpdateStream = Partial<CreateStream>;
|
|
23
|
+
/** Text values are UTF-8. Use a Kafka client for arbitrary binary records. */
|
|
24
|
+
export type StreamRecord = {
|
|
25
|
+
key?: string | null;
|
|
26
|
+
value: string | null;
|
|
27
|
+
headers?: {
|
|
28
|
+
key: string;
|
|
29
|
+
value: string | null;
|
|
30
|
+
}[];
|
|
31
|
+
};
|
|
32
|
+
export type PublishRecords = {
|
|
33
|
+
records: StreamRecord[];
|
|
34
|
+
};
|
|
35
|
+
export type ReadStream = {
|
|
36
|
+
partition: number;
|
|
37
|
+
maxBytes?: number;
|
|
38
|
+
waitMs?: number;
|
|
39
|
+
} & ({
|
|
40
|
+
offset: string;
|
|
41
|
+
time?: never;
|
|
42
|
+
} | {
|
|
43
|
+
time: number;
|
|
44
|
+
offset?: never;
|
|
45
|
+
});
|
|
46
|
+
export type PublishedRecord = {
|
|
47
|
+
partition: number;
|
|
48
|
+
offset: string;
|
|
49
|
+
};
|
|
50
|
+
export type StreamRead = {
|
|
51
|
+
records: (StreamRecord & PublishedRecord & {
|
|
52
|
+
time: number;
|
|
53
|
+
})[];
|
|
54
|
+
nextOffset: string;
|
|
55
|
+
};
|
|
56
|
+
/** Private until launch. Proposed routes only; nothing is registered here. */
|
|
57
|
+
export declare function streams(t: Transport): {
|
|
58
|
+
publish: (id: string, input: PublishRecords, options?: RequestOptions) => Promise<{
|
|
59
|
+
records: PublishedRecord[];
|
|
60
|
+
}>;
|
|
61
|
+
read: (id: string, input: ReadStream, options?: RequestOptions) => Promise<StreamRead>;
|
|
62
|
+
/** Trim returns the resource; follow its state with wait(id). */
|
|
63
|
+
trim: (id: string, input: {
|
|
64
|
+
partition: number;
|
|
65
|
+
before: string;
|
|
66
|
+
}, options?: RequestOptions) => Promise<Stream>;
|
|
67
|
+
create: (input: CreateStream, options?: RequestOptions) => Promise<Stream>;
|
|
68
|
+
get: (id: string, options?: RequestOptions) => Promise<Stream>;
|
|
69
|
+
list: (query?: import("./queues.js").RecordListQuery, options?: RequestOptions) => Promise<import("../page.js").Page<Stream>>;
|
|
70
|
+
update: (id: string, input: Partial<CreateStream>, options?: RequestOptions) => Promise<Stream>;
|
|
71
|
+
delete: (id: string, options?: RequestOptions) => Promise<Stream>;
|
|
72
|
+
wait(id: string, target?: "ready" | "deleted", options?: import("./queues.js").RecordWaitOptions): Promise<Stream>;
|
|
73
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { recordResources } from "./queues.js";
|
|
2
|
+
/** Private until launch. Proposed routes only; nothing is registered here. */
|
|
3
|
+
export function streams(t) {
|
|
4
|
+
const path = (id) => `/v1/streams/${encodeURIComponent(id)}`;
|
|
5
|
+
return {
|
|
6
|
+
...recordResources(t, "streams"),
|
|
7
|
+
publish: (id, input, options) => t.json({
|
|
8
|
+
...options,
|
|
9
|
+
method: "POST",
|
|
10
|
+
path: `${path(id)}:publish`,
|
|
11
|
+
body: input,
|
|
12
|
+
}),
|
|
13
|
+
read: (id, input, options) => t.json({ ...options, method: "GET", path: `${path(id)}:read`, query: input }),
|
|
14
|
+
/** Trim returns the resource; follow its state with wait(id). */
|
|
15
|
+
trim: (id, input, options) => t.json({ ...options, method: "POST", path: `${path(id)}:trim`, body: input }),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -9,7 +9,7 @@ export type SwitchProvider = "e2b" | "daytona" | "vercel" | "modal" | "cloudflar
|
|
|
9
9
|
export type SwitchingSummary = {
|
|
10
10
|
/** False while the programme is paused. */
|
|
11
11
|
enabled: boolean;
|
|
12
|
-
/** The most
|
|
12
|
+
/** The most the organization's payments are matched to, in total. */
|
|
13
13
|
maxMicros: string;
|
|
14
14
|
providers: SwitchProvider[];
|
|
15
15
|
/** Whether this organization can record a switch now: none recorded, and
|
|
@@ -17,14 +17,41 @@ export type SwitchingSummary = {
|
|
|
17
17
|
eligible: boolean;
|
|
18
18
|
switch: {
|
|
19
19
|
provider: SwitchProvider;
|
|
20
|
-
/** superseded: a referral
|
|
20
|
+
/** superseded: a referral matches the payments instead, which is
|
|
21
21
|
* never less. The two are never both paid. */
|
|
22
22
|
status: "pending" | "paid" | "superseded" | "refused" | "reversed";
|
|
23
|
-
refusedReason: "program_off" | "suspended" | "same_card" | "fraud" | null;
|
|
23
|
+
refusedReason: "program_off" | "suspended" | "same_card" | "fraud" | "too_late" | null;
|
|
24
24
|
recordedAt: string;
|
|
25
|
-
/** The
|
|
25
|
+
/** The matches this organization got and kept. */
|
|
26
26
|
creditMicros: string;
|
|
27
27
|
} | null;
|
|
28
|
+
/** The welcome match: credit an organization adds within 30 days of
|
|
29
|
+
* signing up is matched, up to $1,000 in total. */
|
|
30
|
+
welcome: WelcomeMatch;
|
|
31
|
+
};
|
|
32
|
+
export type WelcomeMatch = {
|
|
33
|
+
/** False while the match is paused. */
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
/** The most the organization's payments are matched to, in total. */
|
|
36
|
+
maxMicros: string;
|
|
37
|
+
/** When the offer ends: 30 days after the organization signed up. */
|
|
38
|
+
endsAt: string;
|
|
39
|
+
/** Whether credit added now would be matched: some is left, before endsAt. */
|
|
40
|
+
eligible: boolean;
|
|
41
|
+
/** Whether credit has been added. */
|
|
42
|
+
toppedUp: boolean;
|
|
43
|
+
/** Null until a payment is decided; paid while a match is kept.
|
|
44
|
+
* superseded: a referral matches the payments instead, which is never
|
|
45
|
+
* less. */
|
|
46
|
+
status: "pending" | "paid" | "superseded" | "refused" | "reversed" | null;
|
|
47
|
+
/** The matches this organization got and kept. */
|
|
48
|
+
creditMicros: string;
|
|
49
|
+
/** The part of maxMicros used so far. Absent from a server before
|
|
50
|
+
* 8 October 2026. */
|
|
51
|
+
usedMicros?: string;
|
|
52
|
+
/** What credit added now could still get; "0" once the offer ends. Absent
|
|
53
|
+
* from a server before 8 October 2026. */
|
|
54
|
+
leftMicros?: string;
|
|
28
55
|
};
|
|
29
56
|
export type UsageComparison = {
|
|
30
57
|
provider: CompareProvider;
|
|
@@ -76,8 +103,9 @@ export type UsageComparison = {
|
|
|
76
103
|
switching: SwitchingSummary;
|
|
77
104
|
};
|
|
78
105
|
/** `runtime.switching`: compare your usage with a rival's published rates,
|
|
79
|
-
*
|
|
80
|
-
* $
|
|
106
|
+
* record the rival you are leaving, and read the welcome match: credit added
|
|
107
|
+
* within 30 days of signing up is matched, up to $1,000 in total, as each
|
|
108
|
+
* payment settles. */
|
|
81
109
|
export declare function switching(t: Transport): {
|
|
82
110
|
/** Your settled sandbox usage over the last `days` (default 30, at most
|
|
83
111
|
* 90), priced on Runtime and at the rival, with the saving. */
|
|
@@ -85,7 +113,7 @@ export declare function switching(t: Transport): {
|
|
|
85
113
|
provider: CompareProvider;
|
|
86
114
|
days?: number;
|
|
87
115
|
}, options?: RequestOptions) => Promise<UsageComparison>;
|
|
88
|
-
/** Whether a switch can still be recorded, and what
|
|
116
|
+
/** Whether a switch can still be recorded, and what the welcome match paid. */
|
|
89
117
|
get: (options?: RequestOptions) => Promise<SwitchingSummary>;
|
|
90
118
|
/** Once per organization, before its first top-up. Recording the same
|
|
91
119
|
* provider again answers the same summary; another fails with 409. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** `runtime.switching`: compare your usage with a rival's published rates,
|
|
2
|
-
*
|
|
3
|
-
* $
|
|
2
|
+
* record the rival you are leaving, and read the welcome match: credit added
|
|
3
|
+
* within 30 days of signing up is matched, up to $1,000 in total, as each
|
|
4
|
+
* payment settles. */
|
|
4
5
|
export function switching(t) {
|
|
5
6
|
return {
|
|
6
7
|
/** Your settled sandbox usage over the last `days` (default 30, at most
|
|
@@ -11,7 +12,7 @@ export function switching(t) {
|
|
|
11
12
|
query: { provider: input.provider, days: input.days },
|
|
12
13
|
...options,
|
|
13
14
|
}),
|
|
14
|
-
/** Whether a switch can still be recorded, and what
|
|
15
|
+
/** Whether a switch can still be recorded, and what the welcome match paid. */
|
|
15
16
|
get: (options) => t.json({ method: "GET", path: "/v1/switching", ...options }),
|
|
16
17
|
/** Once per organization, before its first top-up. Recording the same
|
|
17
18
|
* provider again answers the same summary; another fails with 409. */
|
|
@@ -86,7 +86,13 @@ export type VolumeBackup = {
|
|
|
86
86
|
storedBytes: number | null;
|
|
87
87
|
meteredBytes: number | null;
|
|
88
88
|
error: string | null;
|
|
89
|
+
/** Why it failed, when a code says it: `backup_stalled` when its copy off
|
|
90
|
+
* the host never began; back it up again. */
|
|
91
|
+
errorCode?: string | null;
|
|
89
92
|
createdAt: string;
|
|
93
|
+
/** When its copy off the volume's server began; null while it waits its
|
|
94
|
+
* turn behind other copies there. */
|
|
95
|
+
copyStartedAt?: string | null;
|
|
90
96
|
readyAt: string | null;
|
|
91
97
|
expiresAt: string;
|
|
92
98
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { queues } from "./products/queues.js";
|
|
2
|
+
import type { streams } from "./products/streams.js";
|
|
3
|
+
/** Private until launch. CLOUD.md section 4. cli.ts does not call this module. */
|
|
4
|
+
export declare const RECORD_PRODUCTS: readonly ["queue", "stream"];
|
|
5
|
+
export type RecordProduct = (typeof RECORD_PRODUCTS)[number];
|
|
6
|
+
export type RecordClient = {
|
|
7
|
+
queues: ReturnType<typeof queues>;
|
|
8
|
+
streams: ReturnType<typeof streams>;
|
|
9
|
+
};
|
|
10
|
+
type Args = {
|
|
11
|
+
positional: string[];
|
|
12
|
+
flags: Map<string, string[]>;
|
|
13
|
+
rest?: string[];
|
|
14
|
+
};
|
|
15
|
+
type Out = {
|
|
16
|
+
json: boolean;
|
|
17
|
+
write(text: string): void;
|
|
18
|
+
error(text: string): void;
|
|
19
|
+
};
|
|
20
|
+
export declare const RECORD_HELP: Record<RecordProduct, string>;
|
|
21
|
+
/** Parsed like networkProductCommand; never obtains credentials for help or bad flags. */
|
|
22
|
+
export declare function recordCommand(product: RecordProduct, args: Args, out: Out, client: () => Promise<RecordClient>, signal?: AbortSignal): Promise<number>;
|
|
23
|
+
export {};
|