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,227 @@
|
|
|
1
|
+
/** Builds uses the shared request keys and paged lists.
|
|
2
|
+
* Unwired until the build planner's production adapter is ready. */
|
|
3
|
+
import { ConnectionError, RuntimeError } from "../errors.js";
|
|
4
|
+
import { Page } from "../page.js";
|
|
5
|
+
import { timeoutSignal } from "../transport.js";
|
|
6
|
+
const terminal = new Set(["succeeded", "failed", "cancelled", "superseded"]);
|
|
7
|
+
function validFailure(value) {
|
|
8
|
+
if (value === null)
|
|
9
|
+
return true;
|
|
10
|
+
if (!value || typeof value !== "object")
|
|
11
|
+
return false;
|
|
12
|
+
const step = value;
|
|
13
|
+
return (typeof step.name === "string" &&
|
|
14
|
+
(step.exitCode === null || Number.isSafeInteger(step.exitCode)) &&
|
|
15
|
+
Array.isArray(step.lastLines) &&
|
|
16
|
+
step.lastLines.length <= 20 &&
|
|
17
|
+
step.lastLines.every((line) => typeof line === "string"));
|
|
18
|
+
}
|
|
19
|
+
function failure(code, hint, cursor) {
|
|
20
|
+
return new RuntimeError({ code, status: 0, message: hint, hint, details: { cursor } });
|
|
21
|
+
}
|
|
22
|
+
function validCursor(value) {
|
|
23
|
+
return (typeof value === "string" &&
|
|
24
|
+
value.length > 0 &&
|
|
25
|
+
value.length <= 4096 &&
|
|
26
|
+
![...value].some((c) => c.charCodeAt(0) < 0x20 || c.charCodeAt(0) === 0x7f));
|
|
27
|
+
}
|
|
28
|
+
/** Why a wait ended: the signal's own reason, always as an Error. */
|
|
29
|
+
const abortReason = (signal) => signal?.reason instanceof Error ? signal.reason : new Error(String(signal?.reason ?? "aborted"));
|
|
30
|
+
async function* boundedEvents(source, signal) {
|
|
31
|
+
try {
|
|
32
|
+
for (;;) {
|
|
33
|
+
signal?.throwIfAborted();
|
|
34
|
+
let abort = () => { };
|
|
35
|
+
let next;
|
|
36
|
+
try {
|
|
37
|
+
next = await Promise.race([
|
|
38
|
+
source.next(),
|
|
39
|
+
new Promise((_, reject) => {
|
|
40
|
+
abort = () => reject(abortReason(signal));
|
|
41
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
42
|
+
if (signal?.aborted)
|
|
43
|
+
abort();
|
|
44
|
+
}),
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
signal?.removeEventListener("abort", abort);
|
|
49
|
+
}
|
|
50
|
+
if (next.done)
|
|
51
|
+
return;
|
|
52
|
+
yield next.value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
// An injected transport can ignore abort while next() is pending. It must
|
|
57
|
+
// not prevent the caller's deadline from resolving; request its cleanup.
|
|
58
|
+
const closed = source.return(undefined);
|
|
59
|
+
if (signal?.aborted)
|
|
60
|
+
void closed.catch(() => { });
|
|
61
|
+
else
|
|
62
|
+
await closed;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export function builds(t) {
|
|
66
|
+
const path = (id) => `/v1/builds/${encodeURIComponent(id)}`;
|
|
67
|
+
const list = async (query = {}, options) => {
|
|
68
|
+
const page = await t.json({
|
|
69
|
+
method: "GET",
|
|
70
|
+
path: "/v1/builds",
|
|
71
|
+
query,
|
|
72
|
+
...options,
|
|
73
|
+
});
|
|
74
|
+
return new Page(page.data, page.nextCursor, (cursor) => list({ ...query, cursor }, options));
|
|
75
|
+
};
|
|
76
|
+
const listRepositories = async (query = {}, options) => {
|
|
77
|
+
const page = await t.json({
|
|
78
|
+
method: "GET",
|
|
79
|
+
path: "/v1/repositories",
|
|
80
|
+
query,
|
|
81
|
+
...options,
|
|
82
|
+
});
|
|
83
|
+
return new Page(page.data, page.nextCursor, (cursor) => listRepositories({ ...query, cursor }, options));
|
|
84
|
+
};
|
|
85
|
+
async function* follow(id, query, options = {}) {
|
|
86
|
+
let cursor = query.cursor ?? null;
|
|
87
|
+
if ((cursor !== null && !validCursor(cursor)) || query.pageCursor !== undefined)
|
|
88
|
+
throw failure("invalid_log_options", "Use an opaque cursor for follow; pageCursor is only for search pages.", cursor);
|
|
89
|
+
const seen = new Set(cursor === null ? [] : [cursor]);
|
|
90
|
+
let failures = 0;
|
|
91
|
+
// Bound the entire follow when the caller sets a deadline, including
|
|
92
|
+
// reconnections. Transport's per-request deadline alone resets on retry.
|
|
93
|
+
const signal = (options.timeoutMs ?? 120_000) > 0
|
|
94
|
+
? AbortSignal.any([
|
|
95
|
+
...(options.signal ? [options.signal] : []),
|
|
96
|
+
timeoutSignal(options.timeoutMs ?? 120_000),
|
|
97
|
+
])
|
|
98
|
+
: options.signal;
|
|
99
|
+
for (;;) {
|
|
100
|
+
signal?.throwIfAborted();
|
|
101
|
+
let continued = false;
|
|
102
|
+
try {
|
|
103
|
+
for await (const event of boundedEvents(t.events({
|
|
104
|
+
method: "GET",
|
|
105
|
+
path: `${path(id)}/logs`,
|
|
106
|
+
query: { follow: true, ...(cursor === null ? {} : { cursor }) },
|
|
107
|
+
...options,
|
|
108
|
+
...(signal ? { signal } : {}),
|
|
109
|
+
}), signal)) {
|
|
110
|
+
signal?.throwIfAborted();
|
|
111
|
+
if (!event || typeof event !== "object")
|
|
112
|
+
throw failure("build_log_invalid", "Retry the log from the last received cursor.", cursor);
|
|
113
|
+
if (event.cursor !== null && !validCursor(event.cursor))
|
|
114
|
+
throw failure("build_log_invalid", "Retry from the last received cursor.", cursor);
|
|
115
|
+
if (event.type === "line") {
|
|
116
|
+
if (typeof event.text !== "string" ||
|
|
117
|
+
!["stdout", "stderr"].includes(event.stream) ||
|
|
118
|
+
!Number.isSafeInteger(event.at) ||
|
|
119
|
+
event.at < 0 ||
|
|
120
|
+
(event.step !== null && typeof event.step !== "string") ||
|
|
121
|
+
!validCursor(event.cursor))
|
|
122
|
+
throw failure("build_log_invalid", "Retry the log from the last received cursor.", cursor);
|
|
123
|
+
// Opaque physical positions cannot be ordered or incremented.
|
|
124
|
+
if (seen.has(event.cursor))
|
|
125
|
+
continue;
|
|
126
|
+
seen.add(event.cursor);
|
|
127
|
+
if (seen.size > 10_000)
|
|
128
|
+
seen.delete(seen.values().next().value);
|
|
129
|
+
cursor = event.cursor;
|
|
130
|
+
failures = 0;
|
|
131
|
+
yield event;
|
|
132
|
+
}
|
|
133
|
+
else if (event.type === "gap") {
|
|
134
|
+
if (!validCursor(event.earliestCursor) || (cursor !== null && event.cursor !== cursor))
|
|
135
|
+
throw failure("build_log_invalid", "Retry from the last received cursor.", cursor);
|
|
136
|
+
cursor = event.cursor;
|
|
137
|
+
yield event;
|
|
138
|
+
}
|
|
139
|
+
else if (event.type === "terminal") {
|
|
140
|
+
if ((cursor !== null && event.cursor !== cursor) ||
|
|
141
|
+
!terminal.has(event.state) ||
|
|
142
|
+
typeof event.reason !== "string" ||
|
|
143
|
+
!event.reason ||
|
|
144
|
+
!validFailure(event.failingStep) ||
|
|
145
|
+
(event.state !== "failed" && event.failingStep !== null))
|
|
146
|
+
throw failure("build_log_invalid", "Retry the log from the last received cursor.", cursor);
|
|
147
|
+
yield event;
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
else if (event.type === "continue") {
|
|
151
|
+
if (cursor !== null && event.cursor !== cursor)
|
|
152
|
+
throw failure("build_log_gap", "Resume from details.cursor; report a persistent missing log line.", cursor);
|
|
153
|
+
cursor = event.cursor;
|
|
154
|
+
continued = true;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
else if (event.type === "error") {
|
|
158
|
+
if (event.cursor !== cursor ||
|
|
159
|
+
typeof event.code !== "string" ||
|
|
160
|
+
!event.code ||
|
|
161
|
+
typeof event.hint !== "string" ||
|
|
162
|
+
!event.hint)
|
|
163
|
+
throw failure("build_log_invalid", "Retry the log from the last received cursor.", cursor);
|
|
164
|
+
throw failure(event.code, event.hint, cursor);
|
|
165
|
+
}
|
|
166
|
+
else
|
|
167
|
+
throw failure("build_log_invalid", "Retry the log from the last received cursor.", cursor);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
signal?.throwIfAborted();
|
|
172
|
+
if (error instanceof SyntaxError)
|
|
173
|
+
throw failure("build_log_invalid", "The log contained invalid JSON; retry from details.cursor.", cursor);
|
|
174
|
+
// HTTP refusals and protocol errors are actionable, not connection
|
|
175
|
+
// loss. The transport itself retries retryable HTTP responses.
|
|
176
|
+
if (!(error instanceof TypeError) && !(error instanceof ConnectionError))
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
if (!continued && ++failures > 3)
|
|
180
|
+
throw failure("build_log_interrupted", "Reconnect with logs(id, { follow: true, cursor: details.cursor }).", cursor);
|
|
181
|
+
// Prevent a disconnected service or repeated continuations busy-looping.
|
|
182
|
+
await new Promise((resolve, reject) => {
|
|
183
|
+
const done = () => {
|
|
184
|
+
signal?.removeEventListener("abort", abort);
|
|
185
|
+
resolve();
|
|
186
|
+
};
|
|
187
|
+
const timer = setTimeout(done, 50 * Math.max(1, failures));
|
|
188
|
+
const abort = () => {
|
|
189
|
+
clearTimeout(timer);
|
|
190
|
+
signal?.removeEventListener("abort", abort);
|
|
191
|
+
reject(abortReason(signal));
|
|
192
|
+
};
|
|
193
|
+
if (signal?.aborted)
|
|
194
|
+
abort();
|
|
195
|
+
else
|
|
196
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function logs(id, query = {}, options) {
|
|
201
|
+
return query.follow
|
|
202
|
+
? follow(id, query, options)
|
|
203
|
+
: t.json({ method: "GET", path: `${path(id)}/logs`, query, ...options });
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
create: (input, options) => t.json({ method: "POST", path: "/v1/builds", body: input, ...options }),
|
|
207
|
+
get: (id, options) => t.json({ method: "GET", path: path(id), ...options }),
|
|
208
|
+
list,
|
|
209
|
+
logs,
|
|
210
|
+
cancel: (id, options) => t.json({ method: "POST", path: `${path(id)}:cancel`, ...options }),
|
|
211
|
+
repositories: {
|
|
212
|
+
connect: (input, options) => t.json({ method: "POST", path: "/v1/repositories", body: input, ...options }),
|
|
213
|
+
list: listRepositories,
|
|
214
|
+
update: (id, change, options) => t.json({
|
|
215
|
+
method: "POST",
|
|
216
|
+
path: `/v1/repositories/${encodeURIComponent(id)}:update`,
|
|
217
|
+
body: change,
|
|
218
|
+
...options,
|
|
219
|
+
}),
|
|
220
|
+
disconnect: (id, options) => t.json({
|
|
221
|
+
method: "DELETE",
|
|
222
|
+
path: `/v1/repositories/${encodeURIComponent(id)}`,
|
|
223
|
+
...options,
|
|
224
|
+
}),
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
package/dist/products/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { sandboxDesktop } from "./desktop.js";
|
|
|
5
5
|
import { sandboxBrowser } from "./browser.js";
|
|
6
6
|
import { sandboxInterpreter } from "./interpreter.js";
|
|
7
7
|
import { sandboxNetwork } from "./network.js";
|
|
8
|
-
import {
|
|
8
|
+
import { domains, ips, networks, ports } from "./network-products.js";
|
|
9
9
|
import { sandboxPreviews } from "./previews.js";
|
|
10
10
|
import { referrals } from "./referrals.js";
|
|
11
11
|
import { billing } from "./billing.js";
|
|
@@ -13,6 +13,7 @@ import { audit } from "./audit.js";
|
|
|
13
13
|
import { sso } from "./sso.js";
|
|
14
14
|
import { switching } from "./switching.js";
|
|
15
15
|
import { limits } from "./limits.js";
|
|
16
|
+
import { keys } from "./api-keys.js";
|
|
16
17
|
import { volumes } from "./volumes.js";
|
|
17
18
|
import { jobs } from "./jobs.js";
|
|
18
19
|
import { sandboxMounts } from "./mounts.js";
|
|
@@ -27,6 +28,7 @@ export declare const clientExtensions: {
|
|
|
27
28
|
referrals: typeof referrals;
|
|
28
29
|
billing: typeof billing;
|
|
29
30
|
limits: typeof limits;
|
|
31
|
+
keys: typeof keys;
|
|
30
32
|
switching: typeof switching;
|
|
31
33
|
secrets: typeof secrets;
|
|
32
34
|
webhooks: typeof webhooks;
|
|
@@ -37,19 +39,8 @@ export declare const clientExtensions: {
|
|
|
37
39
|
sso: typeof sso;
|
|
38
40
|
domains: typeof domains;
|
|
39
41
|
ports: typeof ports;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
network: typeof network;
|
|
43
|
-
};
|
|
44
|
-
/** Canonical CLI product names share the existing factory instance. Account
|
|
45
|
-
* commands such as secrets, events and billing retain their current names. */
|
|
46
|
-
export declare const clientProductAliases: {
|
|
47
|
-
readonly image: "images";
|
|
48
|
-
readonly volume: "volumes";
|
|
49
|
-
readonly job: "jobs";
|
|
50
|
-
readonly domain: "domains";
|
|
51
|
-
readonly port: "ports";
|
|
52
|
-
readonly address: "addresses";
|
|
42
|
+
ips: typeof ips;
|
|
43
|
+
networks: typeof networks;
|
|
53
44
|
};
|
|
54
45
|
export declare const sandboxExtensions: {
|
|
55
46
|
interpreter: typeof sandboxInterpreter;
|
|
@@ -64,8 +55,6 @@ export declare const sandboxExtensions: {
|
|
|
64
55
|
};
|
|
65
56
|
export type ClientExtensions = {
|
|
66
57
|
readonly [K in keyof typeof clientExtensions]: ReturnType<(typeof clientExtensions)[K]>;
|
|
67
|
-
} & {
|
|
68
|
-
readonly [K in keyof typeof clientProductAliases]: ReturnType<(typeof clientExtensions)[(typeof clientProductAliases)[K]]>;
|
|
69
58
|
};
|
|
70
59
|
export type SandboxExtensions = {
|
|
71
60
|
readonly [K in keyof typeof sandboxExtensions]: ReturnType<(typeof sandboxExtensions)[K]>;
|
package/dist/products/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { sandboxDesktop } from "./desktop.js";
|
|
|
3
3
|
import { sandboxBrowser } from "./browser.js";
|
|
4
4
|
import { sandboxInterpreter } from "./interpreter.js";
|
|
5
5
|
import { sandboxNetwork } from "./network.js";
|
|
6
|
-
import {
|
|
6
|
+
import { domains, ips, networks, ports } from "./network-products.js";
|
|
7
7
|
import { sandboxPreviews } from "./previews.js";
|
|
8
8
|
import { referrals } from "./referrals.js";
|
|
9
9
|
import { billing } from "./billing.js";
|
|
@@ -11,6 +11,7 @@ import { audit } from "./audit.js";
|
|
|
11
11
|
import { sso } from "./sso.js";
|
|
12
12
|
import { switching } from "./switching.js";
|
|
13
13
|
import { limits } from "./limits.js";
|
|
14
|
+
import { keys } from "./api-keys.js";
|
|
14
15
|
import { volumes } from "./volumes.js";
|
|
15
16
|
import { jobs } from "./jobs.js";
|
|
16
17
|
import { sandboxMounts } from "./mounts.js";
|
|
@@ -40,6 +41,7 @@ export const clientExtensions = {
|
|
|
40
41
|
referrals,
|
|
41
42
|
billing,
|
|
42
43
|
limits,
|
|
44
|
+
keys,
|
|
43
45
|
switching,
|
|
44
46
|
secrets,
|
|
45
47
|
webhooks,
|
|
@@ -50,19 +52,8 @@ export const clientExtensions = {
|
|
|
50
52
|
sso,
|
|
51
53
|
domains,
|
|
52
54
|
ports,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
network,
|
|
56
|
-
};
|
|
57
|
-
/** Canonical CLI product names share the existing factory instance. Account
|
|
58
|
-
* commands such as secrets, events and billing retain their current names. */
|
|
59
|
-
export const clientProductAliases = {
|
|
60
|
-
image: "images",
|
|
61
|
-
volume: "volumes",
|
|
62
|
-
job: "jobs",
|
|
63
|
-
domain: "domains",
|
|
64
|
-
port: "ports",
|
|
65
|
-
address: "addresses",
|
|
55
|
+
ips,
|
|
56
|
+
networks,
|
|
66
57
|
};
|
|
67
58
|
export const sandboxExtensions = {
|
|
68
59
|
interpreter: sandboxInterpreter,
|
package/dist/products/jobs.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Page } from "../page.js";
|
|
2
2
|
import type { RequestOptions, Transport } from "../transport.js";
|
|
3
3
|
/** A run's sandbox. Every field has a default; a run is a sandbox of this
|
|
4
|
-
* size, on the
|
|
4
|
+
* size, on the free usage first and then on credit at the sandbox rates. */
|
|
5
5
|
export type JobCompute = {
|
|
6
6
|
region: string;
|
|
7
7
|
vcpu: number;
|
|
@@ -53,6 +53,9 @@ export type Job = {
|
|
|
53
53
|
version: number;
|
|
54
54
|
/** Unix milliseconds, or null when nothing more is scheduled. */
|
|
55
55
|
nextRunAt: number | null;
|
|
56
|
+
/** When `trigger` asked for a run that has not started yet, in Unix
|
|
57
|
+
* milliseconds; null otherwise. */
|
|
58
|
+
runRequestedAt: number | null;
|
|
56
59
|
/** Why the last due run could not start, retried every 30 seconds:
|
|
57
60
|
* `credits` (add credit), `capacity`, `cost_cap` (maxTotalCostMicros or a
|
|
58
61
|
* key's daily limit) or `permission` (the key that made the job lost it). */
|
|
@@ -68,6 +71,8 @@ export type JobRun = {
|
|
|
68
71
|
occurrenceId: string;
|
|
69
72
|
attempt: number;
|
|
70
73
|
scheduledFor: number;
|
|
74
|
+
/** `manual`: a run `trigger` asked for, and its retries. */
|
|
75
|
+
trigger: "schedule" | "manual";
|
|
71
76
|
resourceId: string;
|
|
72
77
|
/** `unknown`: the outcome could not be observed (the sandbox stopped under
|
|
73
78
|
* it). It is never retried by itself. */
|
|
@@ -159,6 +164,9 @@ export declare const JOB_LIMITS: {
|
|
|
159
164
|
};
|
|
160
165
|
/** Unix milliseconds from a Date, an ISO time or a number. */
|
|
161
166
|
export declare function jobTime(at: Date | string | number): number;
|
|
167
|
+
/** The API's schedule from what `create` and `reschedule` take: `{ at }`,
|
|
168
|
+
* `{ cron, timezone? }` or the raw `{ kind: ... }`. */
|
|
169
|
+
export declare function jobSchedule(input: CreateJob["schedule"]): JobSchedule;
|
|
162
170
|
/** The API's job body from `CreateJob`, with every default filled in and the
|
|
163
171
|
* sandbox's size checked before anything is sent. */
|
|
164
172
|
export declare function jobBody(input: CreateJob): Record<string, unknown>;
|
|
@@ -168,7 +176,7 @@ export declare function jobBody(input: CreateJob): Record<string, unknown>;
|
|
|
168
176
|
* request id, and says no retry will change it. */
|
|
169
177
|
export declare function switchedOff(product: string): (error: unknown) => never;
|
|
170
178
|
/** Scheduled jobs: a command run in a fresh sandbox, once or on a cron
|
|
171
|
-
* schedule. Each run is a sandbox, paid for as one: from the
|
|
179
|
+
* schedule. Each run is a sandbox, paid for as one: from the free usage first while the run fits the limits without credit, then from credit
|
|
172
180
|
* at the sandbox rates, through the same holds and spending limits.
|
|
173
181
|
*
|
|
174
182
|
* const job = await runtime.jobs.create({
|
|
@@ -211,4 +219,13 @@ export declare function jobs(transport: Transport): {
|
|
|
211
219
|
/** End the job for good and stop any run in progress. A run that already
|
|
212
220
|
* finished keeps its result. Cancelling again answers the same job. */
|
|
213
221
|
cancel: (id: string, options?: RequestOptions) => Promise<Job>;
|
|
222
|
+
/** Run it now, once, beside its schedule, which does not move. A paused
|
|
223
|
+
* job runs once and stays paused. While a run is starting or going it is
|
|
224
|
+
* refused with `run_in_progress`; a cancelled or finished job with
|
|
225
|
+
* `invalid_state`. The run is in `runs` with `trigger: "manual"`. */
|
|
226
|
+
trigger: (id: string, options?: RequestOptions) => Promise<Job>;
|
|
227
|
+
/** A new schedule, in any form `create` takes: `{ cron, timezone? }` or
|
|
228
|
+
* `{ at }`. The next run is the new schedule's next time; a run going
|
|
229
|
+
* finishes as it began, and a paused job stays paused. */
|
|
230
|
+
reschedule: (id: string, schedule: CreateJob["schedule"], options?: RequestOptions) => Promise<Job>;
|
|
214
231
|
};
|
package/dist/products/jobs.js
CHANGED
|
@@ -47,25 +47,28 @@ export function jobTime(at) {
|
|
|
47
47
|
throw invalid(`schedule.at must be a time: a Date, an ISO time such as 2026-10-01T03:00:00Z, or Unix milliseconds; got ${String(at)}.`, "schedule.at");
|
|
48
48
|
return ms;
|
|
49
49
|
}
|
|
50
|
-
/** The API's
|
|
51
|
-
*
|
|
52
|
-
export function
|
|
53
|
-
const s = input
|
|
54
|
-
let schedule;
|
|
50
|
+
/** The API's schedule from what `create` and `reschedule` take: `{ at }`,
|
|
51
|
+
* `{ cron, timezone? }` or the raw `{ kind: ... }`. */
|
|
52
|
+
export function jobSchedule(input) {
|
|
53
|
+
const s = (input ?? {});
|
|
55
54
|
if (s.kind === "once" || (s.kind === undefined && s.at !== undefined))
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
return { kind: "once", at: jobTime(s.at) };
|
|
56
|
+
if (s.kind === "cron" || (s.kind === undefined && s.cron !== undefined)) {
|
|
58
57
|
const expression = String(s.expression ?? s.cron).trim();
|
|
59
58
|
if (expression.split(/\s+/).length !== 5)
|
|
60
59
|
throw invalid(`A cron schedule has five fields, minute hour day-of-month month day-of-week, such as "0 3 * * *"; got "${expression}".`, "schedule.cron");
|
|
61
|
-
|
|
60
|
+
return {
|
|
62
61
|
kind: "cron",
|
|
63
62
|
expression,
|
|
64
63
|
...(s.timezone === undefined ? {} : { timezone: s.timezone }),
|
|
65
64
|
};
|
|
66
65
|
}
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
throw invalid("schedule takes { at } or { cron }.", "schedule");
|
|
67
|
+
}
|
|
68
|
+
/** The API's job body from `CreateJob`, with every default filled in and the
|
|
69
|
+
* sandbox's size checked before anything is sent. */
|
|
70
|
+
export function jobBody(input) {
|
|
71
|
+
const schedule = jobSchedule(input.schedule);
|
|
69
72
|
const command = Array.isArray(input.command) ? { argv: input.command } : input.command;
|
|
70
73
|
if (!command?.argv?.length)
|
|
71
74
|
throw invalid('command is an argv array such as ["python3", "job.py"].', "command");
|
|
@@ -128,7 +131,7 @@ export function switchedOff(product) {
|
|
|
128
131
|
};
|
|
129
132
|
}
|
|
130
133
|
/** Scheduled jobs: a command run in a fresh sandbox, once or on a cron
|
|
131
|
-
* schedule. Each run is a sandbox, paid for as one: from the
|
|
134
|
+
* schedule. Each run is a sandbox, paid for as one: from the free usage first while the run fits the limits without credit, then from credit
|
|
132
135
|
* at the sandbox rates, through the same holds and spending limits.
|
|
133
136
|
*
|
|
134
137
|
* const job = await runtime.jobs.create({
|
|
@@ -186,5 +189,19 @@ export function jobs(transport) {
|
|
|
186
189
|
/** End the job for good and stop any run in progress. A run that already
|
|
187
190
|
* finished keeps its result. Cancelling again answers the same job. */
|
|
188
191
|
cancel: (id, options) => verb(id, "cancel", options),
|
|
192
|
+
/** Run it now, once, beside its schedule, which does not move. A paused
|
|
193
|
+
* job runs once and stays paused. While a run is starting or going it is
|
|
194
|
+
* refused with `run_in_progress`; a cancelled or finished job with
|
|
195
|
+
* `invalid_state`. The run is in `runs` with `trigger: "manual"`. */
|
|
196
|
+
trigger: (id, options) => verb(id, "trigger", options),
|
|
197
|
+
/** A new schedule, in any form `create` takes: `{ cron, timezone? }` or
|
|
198
|
+
* `{ at }`. The next run is the new schedule's next time; a run going
|
|
199
|
+
* finishes as it began, and a paused job stays paused. */
|
|
200
|
+
reschedule: (id, schedule, options) => t.json({
|
|
201
|
+
method: "POST",
|
|
202
|
+
path: `/v1/jobs/${enc(id)}:reschedule`,
|
|
203
|
+
body: { schedule: jobSchedule(schedule) },
|
|
204
|
+
...options,
|
|
205
|
+
}),
|
|
189
206
|
};
|
|
190
207
|
}
|