withruntime 0.33.3 → 0.35.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/E2B.md +7 -0
- package/dist/agents-cli.d.ts +1 -1
- package/dist/agents-cli.js +171 -7
- package/dist/agents-deploy.d.ts +13 -3
- package/dist/agents-deploy.js +68 -9
- package/dist/apps-cli.d.ts +1 -1
- package/dist/apps-cli.js +41 -9
- package/dist/browsers/index.d.ts +9 -0
- package/dist/browsers/index.js +10 -0
- package/dist/browsers-cli.d.ts +13 -0
- package/dist/browsers-cli.js +160 -0
- package/dist/ci-cli.d.ts +1 -1
- package/dist/ci-cli.js +16 -3
- package/dist/cli-words.js +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +103 -12
- package/dist/desktops/index.d.ts +9 -0
- package/dist/desktops/index.js +10 -0
- package/dist/e2b/code-interpreter.d.ts +3 -12
- package/dist/e2b/code-interpreter.js +3 -6
- package/dist/e2b/index.d.ts +7 -1
- package/dist/e2b/index.js +9 -2
- package/dist/functions/index.d.ts +10 -0
- package/dist/functions/index.js +11 -0
- package/dist/index.d.ts +5 -3
- package/dist/products/agents.d.ts +162 -8
- package/dist/products/agents.js +108 -3
- package/dist/products/apps.d.ts +46 -5
- package/dist/products/browsers.d.ts +26 -0
- package/dist/products/browsers.js +11 -0
- package/dist/products/ci.d.ts +10 -4
- package/dist/products/ci.js +8 -0
- package/dist/products/desktops.d.ts +71 -0
- package/dist/products/desktops.js +27 -0
- package/dist/products/functions.d.ts +2 -0
- package/dist/products/functions.js +5 -0
- package/dist/products/index.d.ts +6 -0
- package/dist/products/index.js +8 -0
- package/dist/products/network.d.ts +4 -2
- package/dist/products/secrets.d.ts +10 -2
- package/dist/products/secrets.js +27 -7
- package/dist/products/uptime.d.ts +97 -0
- package/dist/products/uptime.js +42 -0
- package/dist/products/volumes.d.ts +41 -9
- package/dist/products/volumes.js +5 -2
- package/dist/transport.d.ts +4 -1
- package/dist/transport.js +2 -2
- package/dist/types.d.ts +15 -3
- package/package.json +17 -1
package/E2B.md
CHANGED
|
@@ -38,6 +38,12 @@ may be two accounts, a warning says so once (`RUNTIME_E2B_TWO_KEYS`; Python: a
|
|
|
38
38
|
`RuntimeWarning`). A template with no image of its name fails naming the
|
|
39
39
|
account the key belongs to and where the key came from.
|
|
40
40
|
|
|
41
|
+
E2B's client works the same way: `new E2B({ apiKey }).Sandbox` (Python:
|
|
42
|
+
`E2B(api_key=...).Sandbox` and `.AsyncSandbox`) uses that key unless a call
|
|
43
|
+
names its own, and the code interpreter's `E2B` gives its own `Sandbox`. The
|
|
44
|
+
client's `Template`, `Volume` and `Secret` (Python: and their `Async` forms)
|
|
45
|
+
refuse as the top-level ones do, naming the alternative under "Gaps".
|
|
46
|
+
|
|
41
47
|
## What a sandbox gets
|
|
42
48
|
|
|
43
49
|
- **Machine:** E2B's default, 2 vCPU and 512 MiB. For another, pass
|
|
@@ -145,6 +151,7 @@ before anything happens. The error's `feature` names the gap and its
|
|
|
145
151
|
| `git` | `commands.run("git ...")`. E2B has deprecated its git module too. |
|
|
146
152
|
| File `metadata` | Keep it in a file beside the data. |
|
|
147
153
|
| `runCode(code, { envs })` | A context made with them: `sandbox.runtime.interpreter.contexts.create({ env })`. |
|
|
154
|
+
| `new E2B(opts).Template`, `.Secret`, `.Volume` | As `Template`, `Secret` and `Volume` above: each throws `NotSupportedError` naming the alternative. |
|
|
148
155
|
| `domain`, `apiUrl`, `sandboxUrl`, `headers`, `proxy`, `debug` | Remove them. `RUNTIME_API_URL` sets Runtime's origin, and `HTTPS_PROXY` sets a proxy. |
|
|
149
156
|
|
|
150
157
|
Directory watches use Runtime's native watch stream. JavaScript uses
|
package/dist/agents-cli.d.ts
CHANGED
|
@@ -5,6 +5,6 @@ type Out = {
|
|
|
5
5
|
write: (text: string) => void;
|
|
6
6
|
error: (text: string) => void;
|
|
7
7
|
};
|
|
8
|
-
export declare const AGENT_HELP = "runtime agents <command>\n\n An agent runs a harness (Claude Code, Codex, Gemini CLI, or your own code on\n an agents SDK) in a sandbox of its own for each session, on your model key.\n In a private beta: outside it, each command says how to ask to join.\n\n templates The harnesses and uses to start from\n init [name] [--template <harness>] [--use support|team] [--file runtime.yml]\n Write a starter agents: section into runtime.yml\n deploy [--file runtime.yml] [--dry-run] [--prune [--prune-memory]]\n Make your agents match runtime.yml: create, update\n (a new version only when it changed) and set\n triggers; one line per change. --prune deletes the\n agents a deploy made that the file no longer names,\n with their triggers; one holding memory files only\n with --prune-memory too, which deletes them for good\n create <name> (--template <harness> | --command \"<cmd>\") [--use support|team]\n [--instructions <text> | --instructions-file <path>] [--secret NAME]...\n [--env KEY=VALUE]... [--image <image> | --snapshot <id>] [--vcpu n] [--memory n]\n [--max-concurrent n] [--idle-pause n] [--label key=value]...\n Make an agent; prints its id. --secret names an egress\n secret it may use: its model key, of any provider\n ls Your agents\n get <agent> One agent, in full (an id or its name)\n update <agent> [the options of create] A new version: what you give changes, the rest stays\n rm <agent> Delete it, its triggers, and stop its sessions\n start <agent> <words...> [--key <key>] [--follow]\n A session with these words, or the open one with the\n key (such as customer:42); --follow prints its log\n until it ends\n send <session> <words...> Words into a session\n events <session> [--after <seq>] [--follow] A session's log; --follow until it ends\n sessions [--agent <agent>] [--state <state>]...\n Sessions, newest first\n sessions delete <session> Delete an ended session and its log; its history is\n storage, kept until you delete it\n stop <session> Stop a session\n triggers <agent> Its triggers\n triggers add <agent> --kind <slack|github|schedule|webhook> --config '<json>'\n triggers
|
|
8
|
+
export declare const AGENT_HELP = "runtime agents <command>\n\n An agent runs a harness (Claude Code, Codex, Gemini CLI, or your own code on\n an agents SDK) in a sandbox of its own for each session, on your model key.\n In a private beta: outside it, each command says how to ask to join.\n\n templates The harnesses and uses to start from\n init [name] [--template <harness>] [--use support|team] [--file runtime.yml]\n Write a starter agents: section into runtime.yml\n deploy [--file runtime.yml] [--dry-run] [--prune [--prune-memory]]\n Make your agents match runtime.yml: create, update\n (a new version only when it changed) and set\n triggers; one line per change. --prune deletes the\n agents a deploy made that the file no longer names,\n with their triggers; one holding memory files only\n with --prune-memory too, which deletes them for good\n create <name> (--template <harness> | --command \"<cmd>\") [--use support|team]\n [--instructions <text> | --instructions-file <path>] [--secret NAME]... [--pool NAME]...\n [--env KEY=VALUE]... [--image <image> | --snapshot <id>] [--vcpu n] [--memory n]\n [--max-concurrent n] [--idle-pause n] [--label key=value]...\n Make an agent; prints its id. --secret names an egress\n secret it may use: its model key, of any provider.\n --pool names a Claude account's secret (each one\n given replaces the template's): each session takes\n the one with the most usage left\n ls Your agents\n get <agent> One agent, in full (an id or its name)\n update <agent> [the options of create] A new version: what you give changes, the rest stays\n rm <agent> Delete it, its triggers, and stop its sessions\n start <agent> <words...> [--key <key>] [--follow]\n A session with these words, or the open one with the\n key (such as customer:42); --follow prints its log\n until it ends\n send <session> <words...> Words into a session\n events <session> [--after <seq>] [--follow] A session's log; --follow until it ends\n sessions [--agent <agent>] [--state <state>]...\n Sessions, newest first\n sessions delete <session> Delete an ended session and its log; its history is\n storage, kept until you delete it\n stop <session> Stop a session\n asks [--state <state>]... [--agent <agent>] [--label key=value]...\n The inbox: what your agents' sessions need answered,\n one row per step however many sessions ask it\n asks get <ask> One ask: its options, pick and the sessions asking\n answer <ask> [<option>] [--text <words>] Answer it with an option's label, words, or both:\n every session asking reads it next and wakes\n triggers <agent> Its triggers\n triggers add <agent> --kind <slack|github|schedule|webhook> --config '<json>' [--rules '<json>']\n triggers rules <triggerId> '<json>' Set its rules in place: priority, maxStartsPerHour,\n onEnded (start|note|ask), notify (email|webhook)\n and a webhook's key (\"{cause}\"); its secret stays\n triggers call <triggerId> <words...> [--key <key>] [--label key=value]... [--secret <secret>]\n Call a webhook as its sender would, by its secret\n (or RUNTIME_TRIGGER_SECRET): starts, joins, notes or\n holds\n triggers held <triggerId> [--state held|started|dismissed]...\n Calls it held for you; none is dropped\n triggers held start <triggerId> <callId> Start one, with every call held for its key since\n triggers held dismiss <triggerId> <callId> Dismiss one; nothing runs\n triggers pause <triggerId> --why <words> Hold it: a webhook's calls are kept for you, saying why\n triggers resume <triggerId>\n triggers rm <triggerId>\n memory ls <agent> [--scope <key>] [--prefix <path>]\n Its memory files, with their scope (shared or a key)\n memory search <agent> <words...> [--scope <key>] [--limit n]\n Files whose words match, best first\n memory cat <agent> <path> [--scope <key>] A file's text\n memory put <agent> <path> [<file> | - | --content <text>] [--scope <key>]\n Seed or replace a file (from a file, or - for stdin)\n memory rm <agent> <path> [--scope <key>] Delete a file\n Without --scope: the shared memory, which every\n session reads and only a shared agent's write\n\n A subscription is for your own team's agents; an agent that serves your\n customers uses an API key.\n\nExamples\n printf %s \"$ANTHROPIC_API_KEY\" | runtime secrets set ANTHROPIC_API_KEY --host api.anthropic.com\n runtime agents create helper --template claude-code --use support --instructions \"Answer briefly.\"\n runtime agents start helper \"How do I reset my password?\" --key customer:42 --follow\n runtime agents memory put helper faq/refunds.md refunds.md\n runtime agents asks && runtime agents answer <ask> \"Raise to 20 TB\"\n runtime agents init --template claude-code && runtime agents deploy --dry-run\n runtime agents create ci-review --template review --pool CLAUDE_1 --pool CLAUDE_2\n";
|
|
9
9
|
export declare function agentsCommand(argv: string[], env: NodeJS.ProcessEnv, out: Out, client: () => Promise<Runtime>, kit: CliKit): Promise<number>;
|
|
10
10
|
export {};
|
package/dist/agents-cli.js
CHANGED
|
@@ -19,11 +19,14 @@ export const AGENT_HELP = `runtime agents <command>
|
|
|
19
19
|
with their triggers; one holding memory files only
|
|
20
20
|
with --prune-memory too, which deletes them for good
|
|
21
21
|
create <name> (--template <harness> | --command "<cmd>") [--use support|team]
|
|
22
|
-
[--instructions <text> | --instructions-file <path>] [--secret NAME]...
|
|
22
|
+
[--instructions <text> | --instructions-file <path>] [--secret NAME]... [--pool NAME]...
|
|
23
23
|
[--env KEY=VALUE]... [--image <image> | --snapshot <id>] [--vcpu n] [--memory n]
|
|
24
24
|
[--max-concurrent n] [--idle-pause n] [--label key=value]...
|
|
25
25
|
Make an agent; prints its id. --secret names an egress
|
|
26
|
-
secret it may use: its model key, of any provider
|
|
26
|
+
secret it may use: its model key, of any provider.
|
|
27
|
+
--pool names a Claude account's secret (each one
|
|
28
|
+
given replaces the template's): each session takes
|
|
29
|
+
the one with the most usage left
|
|
27
30
|
ls Your agents
|
|
28
31
|
get <agent> One agent, in full (an id or its name)
|
|
29
32
|
update <agent> [the options of create] A new version: what you give changes, the rest stays
|
|
@@ -39,9 +42,26 @@ export const AGENT_HELP = `runtime agents <command>
|
|
|
39
42
|
sessions delete <session> Delete an ended session and its log; its history is
|
|
40
43
|
storage, kept until you delete it
|
|
41
44
|
stop <session> Stop a session
|
|
45
|
+
asks [--state <state>]... [--agent <agent>] [--label key=value]...
|
|
46
|
+
The inbox: what your agents' sessions need answered,
|
|
47
|
+
one row per step however many sessions ask it
|
|
48
|
+
asks get <ask> One ask: its options, pick and the sessions asking
|
|
49
|
+
answer <ask> [<option>] [--text <words>] Answer it with an option's label, words, or both:
|
|
50
|
+
every session asking reads it next and wakes
|
|
42
51
|
triggers <agent> Its triggers
|
|
43
|
-
triggers add <agent> --kind <slack|github|schedule|webhook> --config '<json>'
|
|
44
|
-
triggers
|
|
52
|
+
triggers add <agent> --kind <slack|github|schedule|webhook> --config '<json>' [--rules '<json>']
|
|
53
|
+
triggers rules <triggerId> '<json>' Set its rules in place: priority, maxStartsPerHour,
|
|
54
|
+
onEnded (start|note|ask), notify (email|webhook)
|
|
55
|
+
and a webhook's key ("{cause}"); its secret stays
|
|
56
|
+
triggers call <triggerId> <words...> [--key <key>] [--label key=value]... [--secret <secret>]
|
|
57
|
+
Call a webhook as its sender would, by its secret
|
|
58
|
+
(or RUNTIME_TRIGGER_SECRET): starts, joins, notes or
|
|
59
|
+
holds
|
|
60
|
+
triggers held <triggerId> [--state held|started|dismissed]...
|
|
61
|
+
Calls it held for you; none is dropped
|
|
62
|
+
triggers held start <triggerId> <callId> Start one, with every call held for its key since
|
|
63
|
+
triggers held dismiss <triggerId> <callId> Dismiss one; nothing runs
|
|
64
|
+
triggers pause <triggerId> --why <words> Hold it: a webhook's calls are kept for you, saying why
|
|
45
65
|
triggers resume <triggerId>
|
|
46
66
|
triggers rm <triggerId>
|
|
47
67
|
memory ls <agent> [--scope <key>] [--prefix <path>]
|
|
@@ -63,9 +83,24 @@ Examples
|
|
|
63
83
|
runtime agents create helper --template claude-code --use support --instructions "Answer briefly."
|
|
64
84
|
runtime agents start helper "How do I reset my password?" --key customer:42 --follow
|
|
65
85
|
runtime agents memory put helper faq/refunds.md refunds.md
|
|
86
|
+
runtime agents asks && runtime agents answer <ask> "Raise to 20 TB"
|
|
66
87
|
runtime agents init --template claude-code && runtime agents deploy --dry-run
|
|
88
|
+
runtime agents create ci-review --template review --pool CLAUDE_1 --pool CLAUDE_2
|
|
67
89
|
`;
|
|
68
90
|
const when = (iso) => iso ?? "-";
|
|
91
|
+
/** A trigger's rules as the CLI takes them: one JSON object. */
|
|
92
|
+
function rulesOf(text, kit) {
|
|
93
|
+
let rules;
|
|
94
|
+
try {
|
|
95
|
+
rules = JSON.parse(text);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
rules = undefined;
|
|
99
|
+
}
|
|
100
|
+
if (!rules || typeof rules !== "object" || Array.isArray(rules))
|
|
101
|
+
throw kit.usage(`Rules are a JSON object, such as '{"key":"{cause}","maxStartsPerHour":60,"onEnded":"ask"}'.`);
|
|
102
|
+
return rules;
|
|
103
|
+
}
|
|
69
104
|
const OPTIONS = [
|
|
70
105
|
"template",
|
|
71
106
|
"use",
|
|
@@ -73,6 +108,7 @@ const OPTIONS = [
|
|
|
73
108
|
"instructions",
|
|
74
109
|
"instructions-file",
|
|
75
110
|
"secret",
|
|
111
|
+
"pool",
|
|
76
112
|
"env",
|
|
77
113
|
"image",
|
|
78
114
|
"snapshot",
|
|
@@ -82,6 +118,20 @@ const OPTIONS = [
|
|
|
82
118
|
"idle-pause",
|
|
83
119
|
"label",
|
|
84
120
|
];
|
|
121
|
+
const ASK_STATES = ["open", "answered", "expired", "withdrawn", "closed"];
|
|
122
|
+
const askLine = (a) => {
|
|
123
|
+
const options = a.options.map((o) => (o.label === a.pick ? `${o.label} (pick)` : o.label));
|
|
124
|
+
return [
|
|
125
|
+
`${a.id} ${a.state}${a.step ? ` step ${a.step}` : ""}, ${a.sessions.length} session${a.sessions.length === 1 ? "" : "s"} asking`,
|
|
126
|
+
` ${a.question}`,
|
|
127
|
+
...(a.why ? [` why: ${a.why}`] : []),
|
|
128
|
+
...(options.length ? [` options: ${options.join(" | ")}`] : []),
|
|
129
|
+
...(a.expiresAt ? [` expires ${a.expiresAt}`] : []),
|
|
130
|
+
...(a.answer
|
|
131
|
+
? [` answered: ${[a.answer.option, a.answer.text].filter(Boolean).join(": ")}`]
|
|
132
|
+
: []),
|
|
133
|
+
].join("\n");
|
|
134
|
+
};
|
|
85
135
|
const STATES = [
|
|
86
136
|
"queued",
|
|
87
137
|
"running",
|
|
@@ -122,6 +172,9 @@ function definitionOf(args, kit, env, base) {
|
|
|
122
172
|
set("instructions", instructions);
|
|
123
173
|
if (secrets)
|
|
124
174
|
set("secrets", [...new Set([...(definition.secrets ?? []), ...secrets])]);
|
|
175
|
+
const pool = args.flags.get("pool");
|
|
176
|
+
if (pool)
|
|
177
|
+
set("pool", [...new Set(pool)]);
|
|
125
178
|
if (args.flags.has("env"))
|
|
126
179
|
set("env", {
|
|
127
180
|
...(definition.env ?? {}),
|
|
@@ -317,6 +370,42 @@ export async function agentsCommand(argv, env, out, client, kit) {
|
|
|
317
370
|
: "No sessions.", page.data);
|
|
318
371
|
return 0;
|
|
319
372
|
}
|
|
373
|
+
case "asks": {
|
|
374
|
+
if (rest[0] === "get") {
|
|
375
|
+
const one = await api.asks.get(need(rest[1], "an ask's id"));
|
|
376
|
+
print(askLine(one), one);
|
|
377
|
+
return 0;
|
|
378
|
+
}
|
|
379
|
+
const args = parse(rest, [], ["state", "agent", "label"]);
|
|
380
|
+
const states = args.flags.get("state");
|
|
381
|
+
for (const state of states ?? [])
|
|
382
|
+
if (!ASK_STATES.includes(state))
|
|
383
|
+
throw usage(`--state takes ${ASK_STATES.join(", ")}.`);
|
|
384
|
+
const agent = flag(args, "agent");
|
|
385
|
+
const labels = args.flags.has("label") ? pairs(args, "label") : undefined;
|
|
386
|
+
const page = await api.asks.list({
|
|
387
|
+
limit: 100,
|
|
388
|
+
...(agent === undefined ? {} : { agent }),
|
|
389
|
+
...(states ? { state: states } : {}),
|
|
390
|
+
...(labels ? { labels } : {}),
|
|
391
|
+
});
|
|
392
|
+
print(page.data.map(askLine).join("\n\n") || "Nothing to answer.", page.data);
|
|
393
|
+
return 0;
|
|
394
|
+
}
|
|
395
|
+
case "answer": {
|
|
396
|
+
const args = parse(rest, [], ["text"]);
|
|
397
|
+
const id = need(args.positional[0], "an ask's id");
|
|
398
|
+
const option = args.positional.slice(1).join(" ") || undefined;
|
|
399
|
+
const text = flag(args, "text");
|
|
400
|
+
if (option === undefined && text === undefined)
|
|
401
|
+
throw usage(`Give an option's label, --text, or both: ${me} agents answer ${id} "Keep it"`);
|
|
402
|
+
const answered = await api.asks.answer(id, {
|
|
403
|
+
...(option === undefined ? {} : { option }),
|
|
404
|
+
...(text === undefined ? {} : { text }),
|
|
405
|
+
});
|
|
406
|
+
print(`${answered.id} answered; ${answered.sessions.filter((x) => x.state === "answered").length} session(s) woken.`, answered);
|
|
407
|
+
return 0;
|
|
408
|
+
}
|
|
320
409
|
case "stop": {
|
|
321
410
|
const session = await (await api.session(need(rest[0], "a session's id"))).stop();
|
|
322
411
|
print(`${session.id} ${session.state}.`, session);
|
|
@@ -325,7 +414,7 @@ export async function agentsCommand(argv, env, out, client, kit) {
|
|
|
325
414
|
case "triggers": {
|
|
326
415
|
const [sub, ...more] = rest;
|
|
327
416
|
if (sub === "add") {
|
|
328
|
-
const args = parse(more, [], ["kind", "config"]);
|
|
417
|
+
const args = parse(more, [], ["kind", "config", "rules"]);
|
|
329
418
|
const target = need(args.positional[0], "an agent's id or name");
|
|
330
419
|
let config;
|
|
331
420
|
try {
|
|
@@ -334,9 +423,11 @@ export async function agentsCommand(argv, env, out, client, kit) {
|
|
|
334
423
|
catch {
|
|
335
424
|
throw usage(`--config takes JSON, such as --config '{"cron":"0 9 * * 1-5","input":"Triage new issues"}'.`);
|
|
336
425
|
}
|
|
426
|
+
const rules = flag(args, "rules");
|
|
337
427
|
const trigger = await api.triggers.create(target, {
|
|
338
428
|
kind: need(flag(args, "kind"), "--kind"),
|
|
339
429
|
config,
|
|
430
|
+
...(rules === undefined ? {} : { rules: rulesOf(rules, kit) }),
|
|
340
431
|
});
|
|
341
432
|
// A webhook's secret is answered this once.
|
|
342
433
|
print(trigger.secret
|
|
@@ -344,6 +435,71 @@ export async function agentsCommand(argv, env, out, client, kit) {
|
|
|
344
435
|
: trigger.id, trigger);
|
|
345
436
|
return 0;
|
|
346
437
|
}
|
|
438
|
+
if (sub === "rules") {
|
|
439
|
+
const id = need(more[0], "a trigger's id");
|
|
440
|
+
const trigger = await api.triggers.setRules(id, rulesOf(need(more[1], `the rules as JSON: ${me} agents triggers rules ${id} '{"priority":10}'`), kit));
|
|
441
|
+
print(`${trigger.id} rules ${JSON.stringify(trigger.rules)}`, trigger);
|
|
442
|
+
return 0;
|
|
443
|
+
}
|
|
444
|
+
if (sub === "call") {
|
|
445
|
+
const args = parse(more, [], ["key", "label", "secret"]);
|
|
446
|
+
const id = need(args.positional[0], "a trigger's id");
|
|
447
|
+
const text = args.positional.slice(1).join(" ");
|
|
448
|
+
if (!text)
|
|
449
|
+
throw usage(`Give the words: ${me} agents triggers call ${id} "disk full on db-1"`);
|
|
450
|
+
const secret = flag(args, "secret") ?? env.RUNTIME_TRIGGER_SECRET;
|
|
451
|
+
if (!secret)
|
|
452
|
+
throw usage("Give the trigger's secret: --secret rtat_… or RUNTIME_TRIGGER_SECRET, as answered when the webhook was added.");
|
|
453
|
+
const key = flag(args, "key");
|
|
454
|
+
const done = await api.triggers.call(id, secret, {
|
|
455
|
+
text,
|
|
456
|
+
...(key === undefined ? {} : { key }),
|
|
457
|
+
...(args.flags.has("label") ? { labels: pairs(args, "label") } : {}),
|
|
458
|
+
});
|
|
459
|
+
print(done.outcome === "held"
|
|
460
|
+
? `held ${done.callId}: ${done.why}`
|
|
461
|
+
: `${done.outcome} ${done.sessionId} seq ${done.seq}`, done);
|
|
462
|
+
return 0;
|
|
463
|
+
}
|
|
464
|
+
if (sub === "held") {
|
|
465
|
+
const [action, ...after] = more;
|
|
466
|
+
if (action === "start" || action === "dismiss") {
|
|
467
|
+
const id = need(after[0], "a trigger's id");
|
|
468
|
+
const call = need(after[1], "a held call's id");
|
|
469
|
+
if (action === "start") {
|
|
470
|
+
const started = await api.triggers.startHeld(id, call);
|
|
471
|
+
print(`${started.joined ? "joined" : "started"} ${started.session.id} with ${started.calls} held call${started.calls === 1 ? "" : "s"}`, started);
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
const dismissed = await api.triggers.dismissHeld(id, call);
|
|
475
|
+
print(`${dismissed.id} dismissed.`, dismissed);
|
|
476
|
+
}
|
|
477
|
+
return 0;
|
|
478
|
+
}
|
|
479
|
+
const args = parse(more, [], ["state"]);
|
|
480
|
+
const states = args.flags.get("state");
|
|
481
|
+
for (const state of states ?? [])
|
|
482
|
+
if (!["held", "started", "dismissed"].includes(state))
|
|
483
|
+
throw usage("--state takes held, started, dismissed.");
|
|
484
|
+
const page = await api.triggers.held(need(args.positional[0], "a trigger's id"), {
|
|
485
|
+
limit: 100,
|
|
486
|
+
...(states ? { state: states } : {}),
|
|
487
|
+
});
|
|
488
|
+
print(page.data.length
|
|
489
|
+
? table([
|
|
490
|
+
["ID", "STATE", "WHY", "KEY", "CREATED", "WORDS"],
|
|
491
|
+
...page.data.map((c) => [
|
|
492
|
+
c.id,
|
|
493
|
+
c.state,
|
|
494
|
+
c.why,
|
|
495
|
+
c.key ?? "-",
|
|
496
|
+
when(c.createdAt),
|
|
497
|
+
c.text.replace(/\s+/g, " ").slice(0, 60),
|
|
498
|
+
]),
|
|
499
|
+
])
|
|
500
|
+
: "No held calls.", page.data);
|
|
501
|
+
return 0;
|
|
502
|
+
}
|
|
347
503
|
if (sub === "pause") {
|
|
348
504
|
const args = parse(more, [], ["why"]);
|
|
349
505
|
const trigger = await api.triggers.pause(need(args.positional[0], "a trigger's id"), need(flag(args, "why"), "--why"));
|
|
@@ -363,8 +519,14 @@ export async function agentsCommand(argv, env, out, client, kit) {
|
|
|
363
519
|
const all = await api.triggers.list(need(sub, "an agent's id or name"));
|
|
364
520
|
print(all.length
|
|
365
521
|
? table([
|
|
366
|
-
["ID", "KIND", "CONFIG", "PAUSED"],
|
|
367
|
-
...all.map((t) => [
|
|
522
|
+
["ID", "KIND", "CONFIG", "RULES", "PAUSED"],
|
|
523
|
+
...all.map((t) => [
|
|
524
|
+
t.id,
|
|
525
|
+
t.kind,
|
|
526
|
+
JSON.stringify(t.config),
|
|
527
|
+
Object.keys(t.rules ?? {}).length ? JSON.stringify(t.rules) : "-",
|
|
528
|
+
t.pausedWhy ?? "-",
|
|
529
|
+
]),
|
|
368
530
|
])
|
|
369
531
|
: "No triggers.", all);
|
|
370
532
|
return 0;
|
|
@@ -386,6 +548,8 @@ export async function agentsCommand(argv, env, out, client, kit) {
|
|
|
386
548
|
"events",
|
|
387
549
|
"sessions",
|
|
388
550
|
"stop",
|
|
551
|
+
"asks",
|
|
552
|
+
"answer",
|
|
389
553
|
"triggers",
|
|
390
554
|
"memory",
|
|
391
555
|
]);
|
package/dist/agents-deploy.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import type { Runtime } from "./client.js";
|
|
2
|
-
import { type Agent, type AgentDefinition, type AgentTrigger, type AgentTriggerKind, type CreateAgentTrigger } from "./products/agents.js";
|
|
3
|
-
/** One trigger as the file writes it. `paused` holds it, saying why
|
|
2
|
+
import { type Agent, type AgentDefinition, type AgentTrigger, type AgentTriggerKind, type AgentTriggerRules, type CreateAgentTrigger } from "./products/agents.js";
|
|
3
|
+
/** One trigger as the file writes it. `paused` holds it, saying why;
|
|
4
|
+
* `rules` are changed in place, never by making the trigger again. */
|
|
4
5
|
export type AgentsFileTrigger = {
|
|
5
6
|
kind: AgentTriggerKind;
|
|
6
7
|
config: Record<string, unknown>;
|
|
8
|
+
rules?: AgentTriggerRules;
|
|
7
9
|
paused?: string;
|
|
8
10
|
};
|
|
9
11
|
/** One agent as the file writes it: a harness template and a use fill in
|
|
10
12
|
* what it leaves out, then each definition field it sets. */
|
|
11
13
|
export type AgentsFileAgent = Omit<Partial<AgentDefinition>, "template"> & {
|
|
12
14
|
/** A harness: claude-code, codex, gemini-cli, claude-agent-sdk,
|
|
13
|
-
* openai-agents-sdk. Fills in `command` and
|
|
15
|
+
* openai-agents-sdk, review, judge. Fills in `command` and its model keys. */
|
|
14
16
|
template?: string;
|
|
15
17
|
/** support or team: a size and bounds for that use (`agents.uses`). */
|
|
16
18
|
use?: "support" | "team";
|
|
@@ -53,6 +55,7 @@ export type AgentsDeployPort = {
|
|
|
53
55
|
pauseTrigger(triggerId: string, why: string, key: string): Promise<AgentTrigger>;
|
|
54
56
|
resumeTrigger(triggerId: string, key: string): Promise<AgentTrigger>;
|
|
55
57
|
removeTrigger(triggerId: string, key: string): Promise<void>;
|
|
58
|
+
setTriggerRules(triggerId: string, rules: AgentTriggerRules, key: string): Promise<AgentTrigger>;
|
|
56
59
|
/** How many memory files the agent holds: deleting it deletes them. */
|
|
57
60
|
memoryFiles(agentId: string): Promise<number>;
|
|
58
61
|
};
|
|
@@ -101,6 +104,13 @@ export type AgentsDeployChange = {
|
|
|
101
104
|
triggerId: string;
|
|
102
105
|
key: string;
|
|
103
106
|
text: string;
|
|
107
|
+
} | {
|
|
108
|
+
action: "set-trigger-rules";
|
|
109
|
+
agent: string;
|
|
110
|
+
triggerId: string;
|
|
111
|
+
rules: AgentTriggerRules;
|
|
112
|
+
key: string;
|
|
113
|
+
text: string;
|
|
104
114
|
} | {
|
|
105
115
|
action: "remove-trigger";
|
|
106
116
|
agent: string;
|
package/dist/agents-deploy.js
CHANGED
|
@@ -22,6 +22,7 @@ const DEFINITION_FIELDS = [
|
|
|
22
22
|
"instructions",
|
|
23
23
|
"env",
|
|
24
24
|
"secrets",
|
|
25
|
+
"pool",
|
|
25
26
|
"mcp",
|
|
26
27
|
"volumes",
|
|
27
28
|
"idlePauseSeconds",
|
|
@@ -131,9 +132,10 @@ function checkAgent(name, entry, source, say) {
|
|
|
131
132
|
Object.assign(def, AGENT_USES[use].definition);
|
|
132
133
|
const found = typeof template === "string" ? agentTemplate(template) : undefined;
|
|
133
134
|
if (found) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
// A use's size wins over the template's, as the CLI's --use does.
|
|
136
|
+
for (const [k, v] of Object.entries(found.definition))
|
|
137
|
+
if (def[k] === undefined)
|
|
138
|
+
def[k] = Array.isArray(v) ? [...v] : v;
|
|
137
139
|
}
|
|
138
140
|
const integer = (field, min, max) => {
|
|
139
141
|
const v = entry[field];
|
|
@@ -200,8 +202,11 @@ function checkAgent(name, entry, source, say) {
|
|
|
200
202
|
if (!isObject(v) ||
|
|
201
203
|
keys.length !== 1 ||
|
|
202
204
|
!((typeof v.image === "string" && /^[A-Za-z0-9][A-Za-z0-9_./:@-]{0,255}$/.test(v.image)) ||
|
|
203
|
-
(typeof v.snapshot === "string" && UUID.test(v.snapshot))
|
|
204
|
-
|
|
205
|
+
(typeof v.snapshot === "string" && UUID.test(v.snapshot)) ||
|
|
206
|
+
// The API's own pattern (packages/cloud/src/api/products/agents.ts).
|
|
207
|
+
(typeof v.repo === "string" &&
|
|
208
|
+
/^[A-Za-z0-9_.-]{1,100}\/[A-Za-z0-9_.-]{1,100}$/.test(v.repo))))
|
|
209
|
+
note(at("from"), "takes { image: name[:tag] }, { snapshot: <snapshot id> } or { repo: owner/name }.");
|
|
205
210
|
else
|
|
206
211
|
def.from = { ...v };
|
|
207
212
|
}
|
|
@@ -258,6 +263,18 @@ function checkAgent(name, entry, source, say) {
|
|
|
258
263
|
def.secrets = [...new Set(v)];
|
|
259
264
|
}
|
|
260
265
|
}
|
|
266
|
+
if (entry.pool !== undefined) {
|
|
267
|
+
const v = entry.pool;
|
|
268
|
+
if (!Array.isArray(v) || v.length < 1 || v.length > 16)
|
|
269
|
+
note(at("pool"), "takes a list of 1 to 16 egress secrets' names, one per Claude account.");
|
|
270
|
+
else {
|
|
271
|
+
v.forEach((s, i) => {
|
|
272
|
+
if (typeof s !== "string" || !SHELL_NAME.test(s))
|
|
273
|
+
note(at("pool", i), "is not a secret's name, such as CLAUDE_1.");
|
|
274
|
+
});
|
|
275
|
+
def.pool = [...new Set(v)];
|
|
276
|
+
}
|
|
277
|
+
}
|
|
261
278
|
if (entry.mcp !== undefined) {
|
|
262
279
|
const v = entry.mcp;
|
|
263
280
|
if (!Array.isArray(v) || v.length > 16)
|
|
@@ -347,8 +364,8 @@ function checkTrigger(t, note) {
|
|
|
347
364
|
note(rest, message);
|
|
348
365
|
};
|
|
349
366
|
for (const key of Object.keys(t))
|
|
350
|
-
if (!["kind", "config", "paused"].includes(key))
|
|
351
|
-
bad([key], `is not a field a trigger takes${hint(key, ["kind", "config", "paused"])}`);
|
|
367
|
+
if (!["kind", "config", "rules", "paused"].includes(key))
|
|
368
|
+
bad([key], `is not a field a trigger takes${hint(key, ["kind", "config", "rules", "paused"])}`);
|
|
352
369
|
const kind = t.kind;
|
|
353
370
|
if (!TRIGGER_KINDS.includes(kind)) {
|
|
354
371
|
bad(["kind"], `takes ${TRIGGER_KINDS.join(", ")}.`);
|
|
@@ -391,12 +408,37 @@ function checkTrigger(t, note) {
|
|
|
391
408
|
if (paused !== undefined &&
|
|
392
409
|
(typeof paused !== "string" || paused.length < 1 || paused.length > 1024))
|
|
393
410
|
bad(["paused"], "takes the words a held trigger says, 1 to 1024 characters.");
|
|
411
|
+
const rules = t.rules ?? {};
|
|
412
|
+
if (!isObject(rules))
|
|
413
|
+
bad(["rules"], `takes ${RULES}.`);
|
|
414
|
+
else
|
|
415
|
+
for (const [k, v] of Object.entries(rules)) {
|
|
416
|
+
const whole = (lo, hi) => typeof v === "number" && Number.isInteger(v) && v >= lo && v <= hi;
|
|
417
|
+
if (!((k === "priority" && whole(-100, 100)) ||
|
|
418
|
+
(k === "maxStartsPerHour" && whole(1, 100000)) ||
|
|
419
|
+
(k === "onEnded" && ["start", "note", "ask"].includes(v)) ||
|
|
420
|
+
(k === "notify" && ["email", "webhook"].includes(v)) ||
|
|
421
|
+
(k === "key" &&
|
|
422
|
+
kind === "webhook" &&
|
|
423
|
+
typeof v === "string" &&
|
|
424
|
+
v.length <= 256 &&
|
|
425
|
+
RULE_KEY.test(v))))
|
|
426
|
+
bad(["rules", k], `takes ${RULES}.`);
|
|
427
|
+
}
|
|
394
428
|
if (ok && !within(config, TRIGGER_MAX_BYTES))
|
|
395
429
|
bad(["config"], "is over 40 KiB.");
|
|
396
430
|
if (!ok)
|
|
397
431
|
return null;
|
|
398
|
-
return {
|
|
432
|
+
return {
|
|
433
|
+
kind,
|
|
434
|
+
config,
|
|
435
|
+
...(isObject(rules) && Object.keys(rules).length ? { rules: rules } : {}),
|
|
436
|
+
...(typeof paused === "string" ? { paused } : {}),
|
|
437
|
+
};
|
|
399
438
|
}
|
|
439
|
+
const RULES = '{ priority?: -100 to 100, maxStartsPerHour?: 1 to 100000, onEnded?: start | note | ask, notify?: email | webhook, key?: "{field}" (a webhook\'s) }';
|
|
440
|
+
/** A webhook's key template, as the API holds it. */
|
|
441
|
+
const RULE_KEY = /^([A-Za-z0-9._:/@#+=-]|\{[A-Za-z0-9_-]{1,64}(\.[A-Za-z0-9_-]{1,64}){0,7}\})+$/;
|
|
400
442
|
const TRIGGER_KEYS = {
|
|
401
443
|
slack: ["team", "channel"],
|
|
402
444
|
github: ["installation", "repository", "events"],
|
|
@@ -479,6 +521,15 @@ export async function planAgents(port, desired, options = {}) {
|
|
|
479
521
|
continue;
|
|
480
522
|
}
|
|
481
523
|
const [match] = open.splice(at, 1);
|
|
524
|
+
if (canonical(trigger.rules ?? {}) !== canonical(match.rules ?? {}))
|
|
525
|
+
changes.push({
|
|
526
|
+
action: "set-trigger-rules",
|
|
527
|
+
agent: want.name,
|
|
528
|
+
triggerId: match.id,
|
|
529
|
+
rules: trigger.rules ?? {},
|
|
530
|
+
key: await keyOf("set-trigger-rules", match.id, trigger.rules ?? {}, match.updatedAt),
|
|
531
|
+
text: `set rules of trigger ${match.id} (${triggerText(trigger)}) of ${want.name}: ${canonical(trigger.rules ?? {})}`,
|
|
532
|
+
});
|
|
482
533
|
if (trigger.paused !== undefined && match.pausedWhy !== trigger.paused)
|
|
483
534
|
changes.push({
|
|
484
535
|
action: "pause-trigger",
|
|
@@ -590,7 +641,11 @@ async function apply(port, change, ids) {
|
|
|
590
641
|
if (!change.agentId)
|
|
591
642
|
change.key = await keyOf(change.key, agentId);
|
|
592
643
|
const key = change.key;
|
|
593
|
-
const made = await port.addTrigger(agentId, {
|
|
644
|
+
const made = await port.addTrigger(agentId, {
|
|
645
|
+
kind: change.trigger.kind,
|
|
646
|
+
config: change.trigger.config,
|
|
647
|
+
...(change.trigger.rules ? { rules: change.trigger.rules } : {}),
|
|
648
|
+
}, key);
|
|
594
649
|
change.triggerId = made.id;
|
|
595
650
|
if (made.secret)
|
|
596
651
|
change.secret = made.secret;
|
|
@@ -607,6 +662,9 @@ async function apply(port, change, ids) {
|
|
|
607
662
|
case "remove-trigger":
|
|
608
663
|
await port.removeTrigger(change.triggerId, change.key);
|
|
609
664
|
return;
|
|
665
|
+
case "set-trigger-rules":
|
|
666
|
+
await port.setTriggerRules(change.triggerId, change.rules, change.key);
|
|
667
|
+
return;
|
|
610
668
|
}
|
|
611
669
|
}
|
|
612
670
|
/** The fields whose value differs. A field the file leaves out matches the
|
|
@@ -740,6 +798,7 @@ function clientPort(api) {
|
|
|
740
798
|
pauseTrigger: (id, why, idempotencyKey) => api.triggers.pause(id, why, { idempotencyKey }),
|
|
741
799
|
resumeTrigger: (id, idempotencyKey) => api.triggers.resume(id, { idempotencyKey }),
|
|
742
800
|
removeTrigger: (id, idempotencyKey) => api.triggers.delete(id, { idempotencyKey }),
|
|
801
|
+
setTriggerRules: (id, rules, idempotencyKey) => api.triggers.setRules(id, rules, { idempotencyKey }),
|
|
743
802
|
memoryFiles: async (agentId) => (await api.memory.list(agentId, { limit: 1 })).usage.files,
|
|
744
803
|
};
|
|
745
804
|
}
|
package/dist/apps-cli.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ type Out = {
|
|
|
5
5
|
write: (text: string) => void;
|
|
6
6
|
error: (text: string) => void;
|
|
7
7
|
};
|
|
8
|
-
export declare const APP_HELP = "runtime apps <command>\n\n An App serves your web server from an image or a build. Copies start when\n requests come and stop when they end, between --min-copies and --max-copies.\n In a private beta: outside it, each command says how to ask to join.\n\n create [<name>] --vcpu <1-16> --memory <128-65536> --max-copies <1-1000>\n [--min-copies 0] [--concurrency 100] [--spares 2] [--port 8080]\n [--health-path /healthz] [--health-fail 60] [--stop-grace 30] [--cdn on|off]\n [--volume <volumeId>:<path>] [--label key=value]...\n Make an App, waiting for its first deploy; prints its id.\n --health-fail: seconds a live copy may fail its health\n check before it is replaced. --stop-grace: seconds a\n stopped copy has after SIGTERM. --volume mounts one\n volume of yours at a path under /data, /mnt, /state,\n /storage or /volumes, in the App's one copy: it needs\n --max-copies 1 (--min-copies is then 1, --spares 0), and\n each deploy stops the old copy before the new one boots\n ls [--all] Your Apps: state, live version, copies; --all, deleted too\n get <app> One App, in full (an id or its name)\n update <app> [--name <name>] [--vcpu n] [--memory n] [--min-copies n] [--max-copies n]\n [--concurrency n] [--spares n] [--port n] [--health-path /path] [--health-fail n]\n [--stop-grace n] [--volume <volumeId>:<path> | none] [--cdn on|off]\n [--label key=value]...\n Change its settings; --volume none takes the volume\n away, only before its first deploy;\n --cdn off sends visitors straight to Runtime's routers,\n with nothing cached (on: Cloudflare's CDN in front)\n rm <app> Delete it and stop its copies\n deploy <app> (--image <image> | --build <buildId>) [--env KEY=VALUE]... [--keep-env]\n [--port 8080] [--health-path /healthz] [--no-wait]\n A new version. Waits until it is live, or says why it\n failed; --no-wait prints the deploy's id at once.\n --image: an image of yours (id, name, name:tag);\n --build: a build that succeeded (runtime builds).\n --env KEY alone sends KEY's value from your environment.\n --keep-env keeps the last deploy's environment, sealed\n deploys <app> [<deployId>] [--wait] Each version's deploy: state and address; with an id,\n that one (--wait: until it ends)\n versions <app> Its versions; the live and previous ones keep saved copies\n copies <app> Its copies now: version, region, state\n logs <app> [--follow] [--since 1h] [--version n] [--copy <copyId>] [--stream stdout|stderr]\n [--limit 100] [--raw] What its copies printed: the newest lines since --since\n (a time, or 30s, 15m, 2h, 7d; kept 14 days), or with\n --follow every line as it comes, until Ctrl-C. On a\n terminal control characters show as \\uXXXX unless --raw\n exec <app> [--copy <id>] [--root] [--cwd <dir>] [--env K=V]... [--timeout <ms>] [--trace-files <file.json>] -- <command>\n Run a command in its live copy\n cp <file> <app>:/<path> [--copy <id>] Copy a file onto its live copy\n cp <app>:/<path> <file> [--copy <id>] Copy a file off it\n exec and cp go to a serving copy of the live version unless --copy names\n one. A copy holds the App's secrets, so only an owner's or admin's key\n reaches into one. A file written to a copy lasts as long as that copy; a\n deploy replaces its copies.\n rollback <app> [--no-wait] Put the previous version live again\n restart <app> [--no-wait] Start the live version afresh, as a deploy of its own;\n with a volume, the old copy stops first and the\n downtime is said\n\nExamples\n runtime apps create web --vcpu 1 --memory 512 --max-copies 3\n runtime apps deploy web --image web:latest --env NODE_ENV=production\n runtime apps logs web --follow\n runtime apps rollback web\n runtime apps create db --vcpu 1 --memory 1024 --max-copies 1 --volume <volumeId>:/data\n";
|
|
8
|
+
export declare const APP_HELP = "runtime apps <command>\n\n An App serves your web server from an image or a build. Copies start when\n requests come and stop when they end, between --min-copies and --max-copies.\n In a private beta: outside it, each command says how to ask to join.\n\n create [<name>] --vcpu <1-16> --memory <128-65536> --max-copies <1-1000>\n [--min-copies 0] [--concurrency 100] [--spares 2] [--port 8080]\n [--health-path /healthz] [--health-fail 60] [--stop-grace 30] [--cdn on|off]\n [--release at-once|staged] [--soak 300] [--volume <volumeId>:<path>] [--label key=value]...\n Make an App, waiting for its first deploy; prints its id.\n --health-fail: seconds a live copy may fail its health\n check before it is replaced. --stop-grace: seconds a\n stopped copy has after SIGTERM. --release staged: a new\n version goes live on one copy, then about 10%, 50% and\n all of them, each stage running --soak seconds (60 to\n 3600) and judged on its visitors' errors and speed\n before the next; a stage that does worse goes back and\n the deploy fails, the live version never stopping.\n --volume mounts one\n volume of yours at a path under /data, /mnt, /state,\n /storage or /volumes, in the App's one copy: it needs\n --max-copies 1 (--min-copies is then 1, --spares 0), and\n each deploy stops the old copy before the new one boots\n ls [--all] Your Apps: state, live version, copies; --all, deleted too\n get <app> One App, in full (an id or its name)\n update <app> [--name <name>] [--vcpu n] [--memory n] [--min-copies n] [--max-copies n]\n [--concurrency n] [--spares n] [--port n] [--health-path /path] [--health-fail n]\n [--stop-grace n] [--volume <volumeId>:<path> | none] [--cdn on|off]\n [--release at-once|staged] [--soak n] [--label key=value]...\n Change its settings; --volume none takes the volume\n away, only before its first deploy;\n --cdn off sends visitors straight to Runtime's routers,\n with nothing cached (on: Cloudflare's CDN in front)\n rm <app> Delete it and stop its copies\n deploy <app> (--image <image> | --build <buildId>) [--env KEY=VALUE]... [--keep-env]\n [--port 8080] [--health-path /healthz] [--no-wait]\n A new version. Waits until it is live, or says why it\n failed; --no-wait prints the deploy's id at once.\n --image: an image of yours (id, name, name:tag);\n --build: a build that succeeded (runtime builds).\n --env KEY alone sends KEY's value from your environment.\n --keep-env keeps the last deploy's environment, sealed\n deploys <app> [<deployId>] [--wait] Each version's deploy: state and address; with an id,\n that one (--wait: until it ends)\n versions <app> Its versions; the live and previous ones keep saved copies\n copies <app> Its copies now: version, region, state\n logs <app> [--follow] [--since 1h] [--version n] [--copy <copyId>] [--stream stdout|stderr]\n [--limit 100] [--raw] What its copies printed: the newest lines since --since\n (a time, or 30s, 15m, 2h, 7d; kept 14 days), or with\n --follow every line as it comes, until Ctrl-C. On a\n terminal control characters show as \\uXXXX unless --raw\n exec <app> [--copy <id>] [--root] [--cwd <dir>] [--env K=V]... [--timeout <ms>] [--trace-files <file.json>] -- <command>\n Run a command in its live copy\n cp <file> <app>:/<path> [--copy <id>] Copy a file onto its live copy\n cp <app>:/<path> <file> [--copy <id>] Copy a file off it\n exec and cp go to a serving copy of the live version unless --copy names\n one. A copy holds the App's secrets, so only an owner's or admin's key\n reaches into one. A file written to a copy lasts as long as that copy; a\n deploy replaces its copies.\n rollback <app> [--no-wait] Put the previous version live again\n restart <app> [--no-wait] Start the live version afresh, as a deploy of its own;\n with a volume, the old copy stops first and the\n downtime is said\n\nExamples\n runtime apps create web --vcpu 1 --memory 512 --max-copies 3\n runtime apps deploy web --image web:latest --env NODE_ENV=production\n runtime apps logs web --follow\n runtime apps rollback web\n runtime apps create db --vcpu 1 --memory 1024 --max-copies 1 --volume <volumeId>:/data\n";
|
|
9
9
|
export declare const FUNCTION_HELP = "runtime functions <command>\n\n A Function serves your HTTP handler from an image or a build, at its own\n address. Copies start when calls come, up to --max-copies, and sleep when\n they stop: an idle Function has no copy awake.\n In a private beta: outside it, each command says how to ask to join.\n\n create [<name>] --vcpu <1-16> --memory <128-65536> --max-copies <1-1000>\n [--concurrency 100] [--spares 2] [--port 8080]\n [--health-path /healthz] [--health-fail 60] [--label key=value]...\n Make a Function, waiting for its first deploy; prints its id.\n --health-fail: seconds a live copy may fail its health\n check before it is replaced\n ls [--all] Your Functions: state, live version, copies; --all, deleted too\n get <function> One Function, in full (an id or its name)\n update <function> [--name <name>] [--vcpu n] [--memory n] [--max-copies n]\n [--concurrency n] [--spares n] [--port n] [--health-path /path] [--health-fail n]\n [--label key=value]...\n Change its settings\n rm <function> Delete it and stop its copies\n deploy <function> (--image <image> | --build <buildId>) [--env KEY=VALUE]... [--keep-env]\n [--port 8080] [--health-path /healthz] [--no-wait]\n A new version. Waits until it is live, or says why it\n failed; --no-wait prints the deploy's id at once.\n --image: an image of yours (id, name, name:tag);\n --build: a build that succeeded (runtime builds).\n --env KEY alone sends KEY's value from your environment.\n --keep-env keeps the last deploy's environment, sealed\n deploys <function> [<deployId>] [--wait] Each version's deploy: state and address; with an id,\n that one (--wait: until it ends)\n versions <function> Its versions; the live and previous ones keep saved copies\n copies <function> Its copies now: version, region, state\n logs <function> [--follow] [--since 1h] [--version n] [--copy <copyId>] [--stream stdout|stderr]\n [--limit 100] [--raw] What its copies printed: the newest lines since --since\n (a time, or 30s, 15m, 2h, 7d; kept 14 days), or with\n --follow every line as it comes, until Ctrl-C. On a\n terminal control characters show as \\uXXXX unless --raw\n rollback <function> [--no-wait] Put the previous version live again\n restart <function> [--no-wait] Start the live version afresh, as a deploy of its own\n\nExamples\n runtime functions create resize --vcpu 1 --memory 512 --max-copies 10\n runtime functions deploy resize --image resize:latest\n runtime functions logs resize --follow\n runtime functions rollback resize\n";
|
|
10
10
|
export declare const BUILD_HELP = "runtime builds <command>\n\n A build turns a commit of a connected repository into a saved server an App\n deploys. A push to the production branch builds and deploys by itself.\n In a private beta: outside it, each command says how to ask to join.\n\n repos connect <owner/name | https URL> --deploy <app name> [--branch main] [--no-previews]\n [--root <folder>] [--install <command>] [--build <command>] [--start <command>]\n [--port 8080] [--health-path /healthz] [--build-env KEY=VALUE]... [--name <name>]\n Connect a repository; prints its id. --deploy takes an\n App's name, or function:<name>. --start runs once the\n build is done, with PORT set: the server the App deploys\n repos ls Connected repositories\n repos change <repoId> [the options of connect but the repository]\n Change its settings; its id and builds stay\n repos disconnect <repoId> Stop building it; its builds stay\n repos install A link to install Runtime's GitHub App, so a private\n repository builds\n create <repoId> [--ref main] [--branch <name>] [--name <name>]\n Build a branch, tag or commit now; prints the build's id\n run <repoId> [--ref main] [--branch <name>] [--name <name>] [--raw]\n The same, then follows its log; exits 0 once it succeeds\n ls [--repository <repoId>] [--commit <sha>] [--state <state>]...\n Builds, oldest first; --commit: a full sha\n get <buildId> One build: state, commit, step times, what it made\n cancel <buildId> Stop a build that has not ended\n logs <buildId> [--follow] [--raw] Its last 200 lines, or every line as it comes until it\n ends; on a terminal control characters show as \\uXXXX\n unless --raw\n\nExamples\n runtime builds repos connect acme/web --deploy web --start \"npm start\"\n runtime builds run <repoId> --ref main\n runtime builds ls --commit $(git rev-parse HEAD)\n";
|
|
11
11
|
export declare const CONTAINER_HELP = "runtime containers <command>\n\n A container runs one OCI image's process on its own microVM, billed at the\n sandbox rates. It never sleeps unless --sleep; on exit it restarts when it\n serves a port, else it stops (--on-exit sets either).\n In a private beta: outside it, each command says how to ask to join.\n\n create <image> --vcpu <1-16> --memory <128-65536> [--name <name>] [--label key=value]...\n [--env KEY[=VALUE]]... [--entrypoint <program>] [--workdir /app] [--user <user>]\n [--port <1-65535>] [--on-exit restart|stop] [--sleep] [-- <command...>]\n Run it; prints its id. The image's digest is pinned.\n --env KEY alone sends KEY's value from your environment.\n --entrypoint drops the image's command; after --, the\n command replaces the image's\n ls [--all] [--state <state>]... [--label key=value]...\n Your containers: all but deleting and deleted, unless\n --all or --state\n get <container> One container, in full (an id or its name): its\n environment's names, never their values\n update <container> [--name <name>] [--label key=value]...\n Rename it or replace its labels\n rm <container> [--wait] Delete it and stop its process; --wait: until deleted\n\nExamples\n runtime containers create nginx:1.27 --vcpu 1 --memory 512 --name web\n runtime containers create python:3.12 --vcpu 1 --memory 1024 -- python3 -m http.server 8000\n runtime containers rm web --wait\n";
|