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,308 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { RuntimeError } from "./errors.js";
|
|
3
|
+
import { named } from "./cli-name.js";
|
|
4
|
+
/** Private until launch. CLOUD.md section 4. cli.ts does not call this module. */
|
|
5
|
+
export const RECORD_PRODUCTS = ["queue", "stream"];
|
|
6
|
+
export const RECORD_HELP = {
|
|
7
|
+
queue: `runtime queue <command> (private until launch)
|
|
8
|
+
create --name work [--input '{"settings":{"fifo":false}}']
|
|
9
|
+
get <id> | list [--input '{"limit":10}']
|
|
10
|
+
update <id> --input '{"labels":{"team":"orders"}}'
|
|
11
|
+
delete <id> | purge <id>
|
|
12
|
+
send <id> --input '{"body":"hello"}'
|
|
13
|
+
receive <id> [--input '{"max":1,"waitSeconds":20}']
|
|
14
|
+
consume <id> --exec '<command>' [--max 1] [--wait-seconds 20]
|
|
15
|
+
[--visibility-seconds 30] Body on stdin; exit 0 acknowledges.
|
|
16
|
+
A failure releases the message immediately. max counts attempts, including
|
|
17
|
+
failures. Omit max to run until Ctrl-C. Cancellation releases known receipts.
|
|
18
|
+
--timeout-ms bounds each network call (default 30000); settlement can finish
|
|
19
|
+
after cancellation. Set visibility longer than processing; repeats are possible.
|
|
20
|
+
Consume makes a key per operation; --idempotency-key does not apply.
|
|
21
|
+
ack <id> --input '{"receiptHandles":["receipt"]}'
|
|
22
|
+
retry <id> --input '{"receiptHandle":"receipt","visibilitySeconds":0}'
|
|
23
|
+
wait <id> [--state ready|deleted] [--poll-ms 250]
|
|
24
|
+
Every call: --idempotency-key <key> --timeout-ms <ms>; use --json for JSON.
|
|
25
|
+
Retry a lost reply with the same key and input. Receives also need that key.
|
|
26
|
+
Settings: visibilityTimeoutSeconds, retentionSeconds, maxMessageBytes,
|
|
27
|
+
delaySeconds, fifo, deadLetter {queue,maxReceives}. At most 32 labels.
|
|
28
|
+
Send: body, attributes, delaySeconds, groupId, dedupId. Receive: max 1-10,
|
|
29
|
+
waitSeconds 0-20, visibilitySeconds. get returns the SQS URL.
|
|
30
|
+
`,
|
|
31
|
+
stream: `runtime stream <command> (private until launch)
|
|
32
|
+
create --name events [--input '{"partitions":1}']
|
|
33
|
+
get <id> | list [--input '{"limit":10}']
|
|
34
|
+
update <id> --input '{"retentionMs":86400000}' | delete <id>
|
|
35
|
+
publish <id> --input '{"records":[{"key":"order","value":"hello","headers":[]}]}'
|
|
36
|
+
read <id> --input '{"partition":0,"offset":"0","maxBytes":1048576,"waitMs":0}'
|
|
37
|
+
trim <id> --input '{"partition":0,"before":"100"}'
|
|
38
|
+
wait <id> [--state ready|deleted] [--poll-ms 250]
|
|
39
|
+
Every call: --idempotency-key <key> --timeout-ms <ms>; use --json for JSON.
|
|
40
|
+
Retry a lost reply with the same key and input. Offsets and retentionBytes
|
|
41
|
+
are decimal strings. Read takes offset OR time (Unix milliseconds).
|
|
42
|
+
get returns the Kafka bootstrap address and topic. At most 32 labels.
|
|
43
|
+
`,
|
|
44
|
+
};
|
|
45
|
+
function usage(product, message) {
|
|
46
|
+
throw new RuntimeError({
|
|
47
|
+
code: "usage",
|
|
48
|
+
status: 0,
|
|
49
|
+
message,
|
|
50
|
+
hint: `Run \`${named("runtime")} ${product} help\`.`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** Parsed like networkProductCommand; never obtains credentials for help or bad flags. */
|
|
54
|
+
export async function recordCommand(product, args, out, client, signal) {
|
|
55
|
+
if (args.rest?.length)
|
|
56
|
+
usage(product, "This command takes no arguments after --.");
|
|
57
|
+
const [given = "help", id, ...extra] = args.positional;
|
|
58
|
+
const verb = given === "ls" ? "list" : given === "rm" ? "delete" : given;
|
|
59
|
+
const actions = product === "queue"
|
|
60
|
+
? ["send", "receive", "ack", "retry", "purge", "consume"]
|
|
61
|
+
: ["publish", "read", "trim"];
|
|
62
|
+
if (!["help", "create", "get", "list", "update", "delete", "wait", ...actions].includes(verb))
|
|
63
|
+
usage(product, `Unknown command ${given}.`);
|
|
64
|
+
const hasInput = [
|
|
65
|
+
"create",
|
|
66
|
+
"list",
|
|
67
|
+
"update",
|
|
68
|
+
"send",
|
|
69
|
+
"receive",
|
|
70
|
+
"ack",
|
|
71
|
+
"retry",
|
|
72
|
+
"publish",
|
|
73
|
+
"read",
|
|
74
|
+
"trim",
|
|
75
|
+
].includes(verb);
|
|
76
|
+
const allowed = new Set([
|
|
77
|
+
...(verb === "consume" ? [] : ["idempotency-key"]),
|
|
78
|
+
"timeout-ms",
|
|
79
|
+
...(hasInput ? ["input"] : []),
|
|
80
|
+
...(verb === "create" ? ["name"] : []),
|
|
81
|
+
...(verb === "wait" ? ["state", "poll-ms"] : []),
|
|
82
|
+
...(verb === "consume" ? ["exec", "max", "wait-seconds", "visibility-seconds"] : []),
|
|
83
|
+
]);
|
|
84
|
+
for (const [flag, values] of args.flags) {
|
|
85
|
+
if (!allowed.has(flag))
|
|
86
|
+
usage(product, `Unknown option --${flag} for ${verb}.`);
|
|
87
|
+
if (values.length !== 1 || !values[0])
|
|
88
|
+
usage(product, `Give --${flag} exactly once with a value.`);
|
|
89
|
+
}
|
|
90
|
+
if (extra.length || (["help", "create", "list"].includes(verb) && id))
|
|
91
|
+
usage(product, "Unexpected positional argument.");
|
|
92
|
+
if (verb === "help") {
|
|
93
|
+
out.write(named(RECORD_HELP[product]));
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
if (!["create", "list"].includes(verb) && !id)
|
|
97
|
+
usage(product, "Give the resource id.");
|
|
98
|
+
const flag = (key) => args.flags.get(key)?.[0];
|
|
99
|
+
const number = (key) => {
|
|
100
|
+
const text = flag(key);
|
|
101
|
+
if (text === undefined)
|
|
102
|
+
return undefined;
|
|
103
|
+
const value = Number(text);
|
|
104
|
+
if (!/^\d+$/.test(text) || !Number.isSafeInteger(value))
|
|
105
|
+
usage(product, `--${key} needs a nonnegative safe integer.`);
|
|
106
|
+
return value;
|
|
107
|
+
};
|
|
108
|
+
let input = {};
|
|
109
|
+
if (flag("input") !== undefined) {
|
|
110
|
+
try {
|
|
111
|
+
input = JSON.parse(flag("input"));
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
usage(product, "--input needs a JSON object.");
|
|
115
|
+
}
|
|
116
|
+
if (!input || Array.isArray(input) || typeof input !== "object")
|
|
117
|
+
usage(product, "--input needs a JSON object.");
|
|
118
|
+
}
|
|
119
|
+
if (flag("name")) {
|
|
120
|
+
if (Object.hasOwn(input, "name"))
|
|
121
|
+
usage(product, "Give name in --name or --input, not both.");
|
|
122
|
+
input.name = flag("name");
|
|
123
|
+
}
|
|
124
|
+
if (verb === "create" && (typeof input.name !== "string" || !input.name.trim()))
|
|
125
|
+
usage(product, "Give a name with --name or --input.");
|
|
126
|
+
if (["update", "send", "ack", "retry", "publish", "read", "trim"].includes(verb) &&
|
|
127
|
+
!flag("input"))
|
|
128
|
+
usage(product, `${verb} needs --input.`);
|
|
129
|
+
const state = flag("state") ?? "ready";
|
|
130
|
+
if (verb === "wait" && state !== "ready" && state !== "deleted")
|
|
131
|
+
usage(product, "--state must be ready or deleted.");
|
|
132
|
+
const timeoutMs = number("timeout-ms");
|
|
133
|
+
const pollMs = number("poll-ms");
|
|
134
|
+
const options = {
|
|
135
|
+
idempotencyKey: flag("idempotency-key") ?? crypto.randomUUID(),
|
|
136
|
+
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
137
|
+
};
|
|
138
|
+
const consumeOptions = verb === "consume"
|
|
139
|
+
? {
|
|
140
|
+
...(number("max") === undefined ? {} : { max: number("max") }),
|
|
141
|
+
...(number("wait-seconds") === undefined ? {} : { waitSeconds: number("wait-seconds") }),
|
|
142
|
+
...(number("visibility-seconds") === undefined
|
|
143
|
+
? {}
|
|
144
|
+
: { visibilitySeconds: number("visibility-seconds") }),
|
|
145
|
+
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
146
|
+
}
|
|
147
|
+
: {};
|
|
148
|
+
if (verb === "consume") {
|
|
149
|
+
if (!flag("exec")?.trim())
|
|
150
|
+
usage(product, "consume needs --exec with a command.");
|
|
151
|
+
if ((consumeOptions.waitSeconds ?? 20) > 20)
|
|
152
|
+
usage(product, "--wait-seconds must be 0 to 20.");
|
|
153
|
+
if ((consumeOptions.visibilitySeconds ?? 30) > 43_200)
|
|
154
|
+
usage(product, "--visibility-seconds must be 0 to 43200.");
|
|
155
|
+
if (timeoutMs !== undefined && (timeoutMs < 1 || timeoutMs > 2_147_483_647))
|
|
156
|
+
usage(product, "consume --timeout-ms must be 1 to 2147483647.");
|
|
157
|
+
}
|
|
158
|
+
const api = await client();
|
|
159
|
+
const resource = product === "queue" ? api.queues : api.streams;
|
|
160
|
+
let result;
|
|
161
|
+
switch (verb) {
|
|
162
|
+
case "consume": {
|
|
163
|
+
const stopped = new AbortController();
|
|
164
|
+
const interrupt = () => stopped.abort();
|
|
165
|
+
const combined = signal ? AbortSignal.any([signal, stopped.signal]) : stopped.signal;
|
|
166
|
+
process.on("SIGINT", interrupt);
|
|
167
|
+
process.on("SIGTERM", interrupt);
|
|
168
|
+
try {
|
|
169
|
+
const consumed = await api.queues.consume(id, (message, running) => executeMessage(flag("exec"), message.body, running, out), { ...consumeOptions, signal: combined });
|
|
170
|
+
out.write(JSON.stringify(consumed, null, out.json ? undefined : 2));
|
|
171
|
+
return consumed.aborted ? 130 : consumed.retried ? 1 : 0;
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
process.removeListener("SIGINT", interrupt);
|
|
175
|
+
process.removeListener("SIGTERM", interrupt);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
case "create":
|
|
179
|
+
result =
|
|
180
|
+
product === "queue"
|
|
181
|
+
? await api.queues.create(input, options)
|
|
182
|
+
: await api.streams.create(input, options);
|
|
183
|
+
break;
|
|
184
|
+
case "update":
|
|
185
|
+
result =
|
|
186
|
+
product === "queue"
|
|
187
|
+
? await api.queues.update(id, input, options)
|
|
188
|
+
: await api.streams.update(id, input, options);
|
|
189
|
+
break;
|
|
190
|
+
case "list":
|
|
191
|
+
result = await resource.list(input, options);
|
|
192
|
+
break;
|
|
193
|
+
case "get":
|
|
194
|
+
result = await resource.get(id, options);
|
|
195
|
+
break;
|
|
196
|
+
case "delete":
|
|
197
|
+
result = await resource.delete(id, options);
|
|
198
|
+
break;
|
|
199
|
+
case "wait":
|
|
200
|
+
result = await resource.wait(id, state, {
|
|
201
|
+
...options,
|
|
202
|
+
...(pollMs === undefined ? {} : { pollMs }),
|
|
203
|
+
});
|
|
204
|
+
break;
|
|
205
|
+
case "send":
|
|
206
|
+
result = await api.queues.send(id, input, options);
|
|
207
|
+
break;
|
|
208
|
+
case "receive":
|
|
209
|
+
result = await api.queues.receive(id, input, options);
|
|
210
|
+
break;
|
|
211
|
+
case "ack": {
|
|
212
|
+
const receipts = await api.queues.ack(id, input, options);
|
|
213
|
+
if (receipts.failed.length)
|
|
214
|
+
throw new RuntimeError({
|
|
215
|
+
code: receipts.failed[0].code,
|
|
216
|
+
status: 0,
|
|
217
|
+
message: receipts.failed[0].message,
|
|
218
|
+
hint: receipts.failed[0].hint,
|
|
219
|
+
details: { ...receipts },
|
|
220
|
+
idempotencyKey: options.idempotencyKey,
|
|
221
|
+
});
|
|
222
|
+
result = receipts;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
case "retry":
|
|
226
|
+
result = await api.queues.retry(id, input, options);
|
|
227
|
+
break;
|
|
228
|
+
case "purge":
|
|
229
|
+
result = await api.queues.purge(id, options);
|
|
230
|
+
break;
|
|
231
|
+
case "publish":
|
|
232
|
+
result = await api.streams.publish(id, input, options);
|
|
233
|
+
break;
|
|
234
|
+
case "read":
|
|
235
|
+
result = await api.streams.read(id, input, options);
|
|
236
|
+
break;
|
|
237
|
+
case "trim":
|
|
238
|
+
result = await api.streams.trim(id, input, options);
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
// Include cursors, receipt failures and endpoint settings in either output mode.
|
|
242
|
+
out.write(JSON.stringify(result, null, out.json ? undefined : 2));
|
|
243
|
+
return 0;
|
|
244
|
+
}
|
|
245
|
+
/** Only the requested command is shell code. Message bytes go through stdin.
|
|
246
|
+
* Output goes to stderr so stdout keeps the CLI's JSON result parseable. */
|
|
247
|
+
function executeMessage(command, body, signal, out) {
|
|
248
|
+
return new Promise((resolve, reject) => {
|
|
249
|
+
const failed = (message) => new RuntimeError({
|
|
250
|
+
code: "command_failed",
|
|
251
|
+
status: 0,
|
|
252
|
+
message,
|
|
253
|
+
hint: "Fix the consumer command; the message will be made visible again.",
|
|
254
|
+
});
|
|
255
|
+
if (signal.aborted) {
|
|
256
|
+
reject(failed("Consumer command cancelled."));
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const grouped = process.platform !== "win32";
|
|
260
|
+
const child = spawn(command, {
|
|
261
|
+
shell: true,
|
|
262
|
+
detached: grouped,
|
|
263
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
264
|
+
});
|
|
265
|
+
const abort = () => {
|
|
266
|
+
if (grouped && child.pid) {
|
|
267
|
+
try {
|
|
268
|
+
process.kill(-child.pid, "SIGKILL");
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
if (error.code !== "ESRCH")
|
|
272
|
+
child.kill("SIGKILL");
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
else
|
|
276
|
+
child.kill("SIGKILL");
|
|
277
|
+
};
|
|
278
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
279
|
+
if (signal.aborted)
|
|
280
|
+
abort();
|
|
281
|
+
child.stdout.on("data", (bytes) => out.error(bytes.toString("utf8")));
|
|
282
|
+
child.stderr.on("data", (bytes) => out.error(bytes.toString("utf8")));
|
|
283
|
+
let inputError;
|
|
284
|
+
child.stdin.on("error", (error) => {
|
|
285
|
+
if (error.code !== "EPIPE") {
|
|
286
|
+
inputError = error;
|
|
287
|
+
abort();
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
child.once("error", (error) => {
|
|
291
|
+
signal.removeEventListener("abort", abort);
|
|
292
|
+
const failure = failed(`Consumer could not start: ${error.message}`);
|
|
293
|
+
out.error(`${failure.code}: ${failure.message} ${failure.hint}`);
|
|
294
|
+
reject(failure);
|
|
295
|
+
});
|
|
296
|
+
child.once("close", (code, killed) => {
|
|
297
|
+
signal.removeEventListener("abort", abort);
|
|
298
|
+
if (code === 0 && !signal.aborted && !inputError) {
|
|
299
|
+
resolve();
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
const failure = failed(inputError?.message ?? `Consumer exited ${code ?? killed ?? "without a status"}.`);
|
|
303
|
+
out.error(`${failure.code}: ${failure.message} ${failure.hint}`);
|
|
304
|
+
reject(failure);
|
|
305
|
+
});
|
|
306
|
+
child.stdin.end(body);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ProductName } from "./product-names.js";
|
|
2
|
+
import type { Sandboxes } from "./client.js";
|
|
3
|
+
import type { Snapshots } from "./snapshots.js";
|
|
4
|
+
import type { ClientExtensions } from "./products/index.js";
|
|
5
|
+
/** The client's properties under their old words, each the product it became. */
|
|
6
|
+
export type RenamedProducts = {
|
|
7
|
+
/** @deprecated Renamed `runtime.sandboxes`; works for 30 days after the rename, with a warning. */
|
|
8
|
+
readonly sandbox: Sandboxes;
|
|
9
|
+
/** @deprecated Renamed `runtime.snapshots`; works for 30 days after the rename, with a warning. */
|
|
10
|
+
readonly snapshot: Snapshots;
|
|
11
|
+
/** @deprecated Renamed `runtime.images`; works for 30 days after the rename, with a warning. */
|
|
12
|
+
readonly image: ClientExtensions["images"];
|
|
13
|
+
/** @deprecated Renamed `runtime.volumes`; works for 30 days after the rename, with a warning. */
|
|
14
|
+
readonly volume: ClientExtensions["volumes"];
|
|
15
|
+
/** @deprecated Renamed `runtime.jobs`; works for 30 days after the rename, with a warning. */
|
|
16
|
+
readonly job: ClientExtensions["jobs"];
|
|
17
|
+
/** @deprecated Renamed `runtime.domains`; works for 30 days after the rename, with a warning. */
|
|
18
|
+
readonly domain: ClientExtensions["domains"];
|
|
19
|
+
/** @deprecated Renamed `runtime.ports`; works for 30 days after the rename, with a warning. */
|
|
20
|
+
readonly port: ClientExtensions["ports"];
|
|
21
|
+
/** @deprecated Renamed `runtime.ips`; works for 30 days after the rename, with a warning. */
|
|
22
|
+
readonly address: ClientExtensions["ips"];
|
|
23
|
+
/** @deprecated Renamed `runtime.ips`; works for 30 days after the rename, with a warning. */
|
|
24
|
+
readonly addresses: ClientExtensions["ips"];
|
|
25
|
+
/** @deprecated Renamed `runtime.networks`; works for 30 days after the rename, with a warning. */
|
|
26
|
+
readonly network: ClientExtensions["networks"];
|
|
27
|
+
/** @deprecated Renamed `runtime.networks.wireguard`; works for 30 days after the rename, with a warning. */
|
|
28
|
+
readonly tunnel: ClientExtensions["networks"]["wireguard"];
|
|
29
|
+
};
|
|
30
|
+
/** Puts each old word on `client` as a property that answers the product it
|
|
31
|
+
* became and says so once per process, or, from the table's date, throws
|
|
32
|
+
* name_retired with a hint naming the new property. An old word the client
|
|
33
|
+
* already uses for something else is left alone. */
|
|
34
|
+
export declare function installRenamedProducts(client: object, options?: {
|
|
35
|
+
now?: () => Date;
|
|
36
|
+
table?: readonly ProductName[];
|
|
37
|
+
say?: (line: string) => void;
|
|
38
|
+
}): void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RuntimeError } from "./errors.js";
|
|
2
|
+
import { PRODUCT_NAMES, wordOf } from "./product-names.js";
|
|
3
|
+
import { resolveWord, sdkPath } from "./product-renames.js";
|
|
4
|
+
const said = new Set();
|
|
5
|
+
/** Puts each old word on `client` as a property that answers the product it
|
|
6
|
+
* became and says so once per process, or, from the table's date, throws
|
|
7
|
+
* name_retired with a hint naming the new property. An old word the client
|
|
8
|
+
* already uses for something else is left alone. */
|
|
9
|
+
export function installRenamedProducts(client, options = {}) {
|
|
10
|
+
const table = options.table ?? PRODUCT_NAMES;
|
|
11
|
+
for (const product of table) {
|
|
12
|
+
for (const old of product.old) {
|
|
13
|
+
const [property] = sdkPath(wordOf(old.name));
|
|
14
|
+
if (property === undefined || property in client)
|
|
15
|
+
continue;
|
|
16
|
+
Object.defineProperty(client, property, {
|
|
17
|
+
configurable: true,
|
|
18
|
+
enumerable: false,
|
|
19
|
+
get() {
|
|
20
|
+
const use = resolveWord(old.name, "sdk", options.now?.() ?? new Date(), table);
|
|
21
|
+
if (use === undefined || use.kind === "current")
|
|
22
|
+
return undefined;
|
|
23
|
+
if (use.kind === "retired")
|
|
24
|
+
throw new RuntimeError({ ...use.error });
|
|
25
|
+
if (!said.has(use.warning)) {
|
|
26
|
+
said.add(use.warning);
|
|
27
|
+
(options.say ?? console.warn)(`Runtime: ${use.warning}`);
|
|
28
|
+
}
|
|
29
|
+
return sdkPath(use.to).reduce((at, key) => at[key], client);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/runloop/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PagePromise, DevboxViewsCursorIDPage } from "./pagination.js";
|
|
2
|
+
export { RunloopSDK, Devbox, Execution, ExecutionResult, RunloopError } from "./sdk.js";
|
|
2
3
|
import type { Runtime } from "../client.js";
|
|
3
4
|
import { Sandbox } from "../sandbox.js";
|
|
4
5
|
import { DiskSnapshots, type DevboxSnapshotDiskParams, type DevboxSnapshotView, type DiskSnapshotListParams } from "./snapshots.js";
|
|
@@ -101,6 +102,12 @@ export interface DevboxListParams {
|
|
|
101
102
|
}
|
|
102
103
|
export declare class Runloop {
|
|
103
104
|
readonly devboxes: Devboxes;
|
|
105
|
+
get secrets(): never;
|
|
106
|
+
get objects(): never;
|
|
107
|
+
get axons(): never;
|
|
108
|
+
get gatewayConfigs(): never;
|
|
109
|
+
get mcpConfigs(): never;
|
|
110
|
+
get networkPolicies(): never;
|
|
104
111
|
constructor(options?: ClientOptions & {
|
|
105
112
|
bearerToken?: string;
|
|
106
113
|
baseURL?: string;
|
|
@@ -302,10 +309,10 @@ export declare class Executions {
|
|
|
302
309
|
kill(id: string, execution: string, body?: {
|
|
303
310
|
kill_process_group?: boolean | null;
|
|
304
311
|
} | RequestOptions, options?: RequestOptions): Promise<DevboxAsyncExecutionDetailView>;
|
|
305
|
-
sendStdIn(id: string, execution: string, body
|
|
312
|
+
sendStdIn(id: string, execution: string, body: {
|
|
306
313
|
text?: string | null;
|
|
307
314
|
signal?: "EOF" | "INTERRUPT" | null;
|
|
308
|
-
}
|
|
315
|
+
}, options?: RequestOptions): Promise<{
|
|
309
316
|
devbox_id: string;
|
|
310
317
|
execution_id: string;
|
|
311
318
|
success: boolean;
|
package/dist/runloop/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { PagePromise, DevboxViewsCursorIDPage } from "./pagination.js";
|
|
2
|
+
export { RunloopSDK, Devbox, Execution, ExecutionResult, RunloopError } from "./sdk.js";
|
|
2
3
|
import { Sandbox } from "../sandbox.js";
|
|
4
|
+
import { timeoutSignal } from "../transport.js";
|
|
3
5
|
import { DiskSnapshots, requestOptions, snapshotOptions, snapshotView, nativeOptions, } from "./snapshots.js";
|
|
4
6
|
export { DiskSnapshots, } from "./snapshots.js";
|
|
5
7
|
export { PagePromise, DevboxSnapshotViewsDiskSnapshotsCursorIDPage, DevboxViewsCursorIDPage, } from "./pagination.js";
|
|
@@ -82,6 +84,24 @@ function view(sandbox) {
|
|
|
82
84
|
}
|
|
83
85
|
export class Runloop {
|
|
84
86
|
devboxes;
|
|
87
|
+
get secrets() {
|
|
88
|
+
throw new CompatibilityError("Runloop", "duplicate-name secret rows and secret-ID handles; use the Runtime secrets API");
|
|
89
|
+
}
|
|
90
|
+
get objects() {
|
|
91
|
+
throw new CompatibilityError("Runloop", "signed storage-object uploads; use Runtime sandbox files");
|
|
92
|
+
}
|
|
93
|
+
get axons() {
|
|
94
|
+
throw new CompatibilityError("Runloop", "Axon registries and deleted event records; use the Runtime events API");
|
|
95
|
+
}
|
|
96
|
+
get gatewayConfigs() {
|
|
97
|
+
throw new CompatibilityError("Runloop", "named gateway bindings; use the Runtime secrets API with direct service requests");
|
|
98
|
+
}
|
|
99
|
+
get mcpConfigs() {
|
|
100
|
+
throw new CompatibilityError("Runloop", "named MCP grants; use the Runtime secrets API with your MCP client");
|
|
101
|
+
}
|
|
102
|
+
get networkPolicies() {
|
|
103
|
+
throw new CompatibilityError("Runloop", "reusable named network-policy bindings; use Runtime sandbox egress settings");
|
|
104
|
+
}
|
|
85
105
|
constructor(options = {}) {
|
|
86
106
|
const { bearerToken, baseURL, ...rest } = options;
|
|
87
107
|
this.devboxes = new Devboxes(client({ ...rest, apiKey: rest.apiKey ?? bearerToken, baseUrl: rest.baseUrl ?? baseURL }));
|
|
@@ -217,7 +237,7 @@ export class Devboxes {
|
|
|
217
237
|
throw new Error("timeoutMs must be positive");
|
|
218
238
|
if (options.signal?.aborted)
|
|
219
239
|
throw new LongPollAbortError("Long poll aborted", undefined);
|
|
220
|
-
const deadline = timeoutMs === undefined ? undefined :
|
|
240
|
+
const deadline = timeoutMs === undefined ? undefined : timeoutSignal(timeoutMs);
|
|
221
241
|
const signal = deadline && options.signal
|
|
222
242
|
? AbortSignal.any([deadline, options.signal])
|
|
223
243
|
: (deadline ?? options.signal);
|
|
@@ -484,21 +504,22 @@ export class Executions {
|
|
|
484
504
|
await (await (await lookup(this.runtime, id, nativeOptions(options))).processes.get(execution, nativeOptions(options))).kill("SIGKILL", nativeOptions(options));
|
|
485
505
|
return this.retrieve(id, execution, {}, options);
|
|
486
506
|
}
|
|
487
|
-
async sendStdIn(id, execution, body
|
|
488
|
-
if (requestOptions(body) &&
|
|
489
|
-
(body.signal === undefined || (typeof body.signal === "object" && body.signal !== null)))
|
|
490
|
-
return this.sendStdIn(id, execution, {}, body);
|
|
507
|
+
async sendStdIn(id, execution, body, options = {}) {
|
|
491
508
|
options.signal?.throwIfAborted();
|
|
509
|
+
if (!body || typeof body !== "object" || Array.isArray(body))
|
|
510
|
+
throw new TypeError("Runloop stdin requires a body with nonempty text or a signal");
|
|
492
511
|
only("Runloop stdin", body, ["text", "signal"]);
|
|
493
|
-
const text =
|
|
512
|
+
const text = body.text;
|
|
494
513
|
const bodySignal = body.signal;
|
|
495
|
-
if (text !== undefined && text !== null && typeof text !== "string")
|
|
496
|
-
throw new TypeError("Runloop stdin text must be a string");
|
|
514
|
+
if (text !== undefined && text !== null && (typeof text !== "string" || text.length === 0))
|
|
515
|
+
throw new TypeError("Runloop stdin text must be a nonempty string");
|
|
497
516
|
if (bodySignal !== undefined &&
|
|
498
517
|
bodySignal !== null &&
|
|
499
518
|
bodySignal !== "EOF" &&
|
|
500
519
|
bodySignal !== "INTERRUPT")
|
|
501
520
|
throw new TypeError("Runloop stdin signal must be EOF or INTERRUPT");
|
|
521
|
+
if ((text != null) === (bodySignal != null))
|
|
522
|
+
throw new TypeError("Runloop stdin requires exactly one of nonempty text or a signal");
|
|
502
523
|
if (options.idempotencyKey !== undefined && (text || bodySignal === "EOF"))
|
|
503
524
|
throw new CompatibilityError("Runloop", "caller idempotency keys for process input; native offsets protect transport retries");
|
|
504
525
|
const p = await (await lookup(this.runtime, id, nativeOptions(options))).processes.get(execution, nativeOptions(options));
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { Runloop, type DevboxAsyncExecutionDetailView, type DevboxCreateParams, type DevboxExecuteParams, type RequestOptions } from "./index.js";
|
|
2
|
+
export declare class RunloopError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
/** The high-level command handles share the low-level adapter's validation,
|
|
6
|
+
* cancellation and process input path; they never send a provider request. */
|
|
7
|
+
export declare class RunloopSDK {
|
|
8
|
+
readonly api: Runloop;
|
|
9
|
+
readonly devbox: {
|
|
10
|
+
fromId: (id: string) => Devbox;
|
|
11
|
+
create: (params?: DevboxCreateParams, request?: RequestOptions) => Promise<Devbox>;
|
|
12
|
+
};
|
|
13
|
+
constructor(options?: ConstructorParameters<typeof Runloop>[0]);
|
|
14
|
+
get secret(): never;
|
|
15
|
+
get storageObject(): never;
|
|
16
|
+
get axon(): never;
|
|
17
|
+
get gatewayConfig(): never;
|
|
18
|
+
get mcpConfig(): never;
|
|
19
|
+
get networkPolicy(): never;
|
|
20
|
+
}
|
|
21
|
+
export declare class Devbox {
|
|
22
|
+
private readonly client;
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly cmd: {
|
|
25
|
+
execAsync: (command: string, params?: Omit<DevboxExecuteParams, "command">, options?: RequestOptions) => Promise<Execution>;
|
|
26
|
+
exec: (command: string, params?: Omit<DevboxExecuteParams, "command">, options?: RequestOptions) => Promise<ExecutionResult>;
|
|
27
|
+
};
|
|
28
|
+
constructor(client: Runloop, id: string);
|
|
29
|
+
getInfo(options?: RequestOptions): Promise<{
|
|
30
|
+
id: string;
|
|
31
|
+
name: string | null;
|
|
32
|
+
metadata: {
|
|
33
|
+
[k: string]: string;
|
|
34
|
+
};
|
|
35
|
+
status: string;
|
|
36
|
+
create_time_ms: number;
|
|
37
|
+
end_time_ms: number | null;
|
|
38
|
+
capabilities: never[];
|
|
39
|
+
state_transitions: never[];
|
|
40
|
+
launch_parameters: {
|
|
41
|
+
custom_cpu_cores: number;
|
|
42
|
+
custom_gb_memory: number;
|
|
43
|
+
custom_disk_size: number;
|
|
44
|
+
keep_alive_time_seconds: number;
|
|
45
|
+
resource_size_request: "CUSTOM_SIZE";
|
|
46
|
+
};
|
|
47
|
+
}>;
|
|
48
|
+
shutdown(options?: RequestOptions): Promise<{
|
|
49
|
+
id: string;
|
|
50
|
+
name: string | null;
|
|
51
|
+
metadata: {
|
|
52
|
+
[k: string]: string;
|
|
53
|
+
};
|
|
54
|
+
status: string;
|
|
55
|
+
create_time_ms: number;
|
|
56
|
+
end_time_ms: number | null;
|
|
57
|
+
capabilities: never[];
|
|
58
|
+
state_transitions: never[];
|
|
59
|
+
launch_parameters: {
|
|
60
|
+
custom_cpu_cores: number;
|
|
61
|
+
custom_gb_memory: number;
|
|
62
|
+
custom_disk_size: number;
|
|
63
|
+
keep_alive_time_seconds: number;
|
|
64
|
+
resource_size_request: "CUSTOM_SIZE";
|
|
65
|
+
};
|
|
66
|
+
}>;
|
|
67
|
+
suspend(options?: RequestOptions): Promise<{
|
|
68
|
+
id: string;
|
|
69
|
+
name: string | null;
|
|
70
|
+
metadata: {
|
|
71
|
+
[k: string]: string;
|
|
72
|
+
};
|
|
73
|
+
status: string;
|
|
74
|
+
create_time_ms: number;
|
|
75
|
+
end_time_ms: number | null;
|
|
76
|
+
capabilities: never[];
|
|
77
|
+
state_transitions: never[];
|
|
78
|
+
launch_parameters: {
|
|
79
|
+
custom_cpu_cores: number;
|
|
80
|
+
custom_gb_memory: number;
|
|
81
|
+
custom_disk_size: number;
|
|
82
|
+
keep_alive_time_seconds: number;
|
|
83
|
+
resource_size_request: "CUSTOM_SIZE";
|
|
84
|
+
};
|
|
85
|
+
}>;
|
|
86
|
+
resume(options?: RequestOptions): Promise<{
|
|
87
|
+
id: string;
|
|
88
|
+
name: string | null;
|
|
89
|
+
metadata: {
|
|
90
|
+
[k: string]: string;
|
|
91
|
+
};
|
|
92
|
+
status: string;
|
|
93
|
+
create_time_ms: number;
|
|
94
|
+
end_time_ms: number | null;
|
|
95
|
+
capabilities: never[];
|
|
96
|
+
state_transitions: never[];
|
|
97
|
+
launch_parameters: {
|
|
98
|
+
custom_cpu_cores: number;
|
|
99
|
+
custom_gb_memory: number;
|
|
100
|
+
custom_disk_size: number;
|
|
101
|
+
keep_alive_time_seconds: number;
|
|
102
|
+
resource_size_request: "CUSTOM_SIZE";
|
|
103
|
+
};
|
|
104
|
+
}>;
|
|
105
|
+
}
|
|
106
|
+
export declare class Execution {
|
|
107
|
+
private readonly client;
|
|
108
|
+
readonly devboxId: string;
|
|
109
|
+
readonly executionId: string;
|
|
110
|
+
private readonly streamingPromise?;
|
|
111
|
+
constructor(client: Runloop, devboxId: string, executionId: string, _initialResult: DevboxAsyncExecutionDetailView, streamingPromise?: Promise<void> | undefined);
|
|
112
|
+
sendStdIn(input: string, options?: RequestOptions): Promise<void>;
|
|
113
|
+
closeStdIn(options?: RequestOptions): Promise<void>;
|
|
114
|
+
private input;
|
|
115
|
+
getState(options?: RequestOptions): Promise<DevboxAsyncExecutionDetailView>;
|
|
116
|
+
kill(options?: RequestOptions): Promise<void>;
|
|
117
|
+
result(options?: RequestOptions): Promise<ExecutionResult>;
|
|
118
|
+
}
|
|
119
|
+
export declare class ExecutionResult {
|
|
120
|
+
private readonly client;
|
|
121
|
+
private readonly devboxId;
|
|
122
|
+
readonly executionId: string;
|
|
123
|
+
readonly result: DevboxAsyncExecutionDetailView;
|
|
124
|
+
constructor(client: Runloop, devboxId: string, executionId: string, result: DevboxAsyncExecutionDetailView);
|
|
125
|
+
get exitCode(): number | null;
|
|
126
|
+
get success(): boolean;
|
|
127
|
+
get failed(): boolean;
|
|
128
|
+
stdout(numLines?: number): Promise<string>;
|
|
129
|
+
stderr(numLines?: number): Promise<string>;
|
|
130
|
+
private output;
|
|
131
|
+
}
|