promigence 0.1.0-beta.12
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/NOTICE +14 -0
- package/README.md +88 -0
- package/dist/account.js +850 -0
- package/dist/agent.js +374 -0
- package/dist/argv.js +159 -0
- package/dist/bin.js +332 -0
- package/dist/bundle.js +133 -0
- package/dist/capacity.js +69 -0
- package/dist/commands.d.ts +110 -0
- package/dist/commands.js +2675 -0
- package/dist/connectreq.js +125 -0
- package/dist/credfile.js +188 -0
- package/dist/credits.js +197 -0
- package/dist/devcontainer.d.ts +99 -0
- package/dist/devcontainer.js +744 -0
- package/dist/device.js +129 -0
- package/dist/dirsnap.js +378 -0
- package/dist/errfix.js +262 -0
- package/dist/generated.d.ts +35 -0
- package/dist/generated.js +307 -0
- package/dist/github.js +307 -0
- package/dist/gitlab.js +210 -0
- package/dist/guide.d.ts +19 -0
- package/dist/guide.js +366 -0
- package/dist/handlers.js +511 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +7 -0
- package/dist/init.d.ts +40 -0
- package/dist/init.js +352 -0
- package/dist/install.d.ts +23 -0
- package/dist/install.js +127 -0
- package/dist/io.d.ts +37 -0
- package/dist/io.js +318 -0
- package/dist/live.js +469 -0
- package/dist/login.js +1063 -0
- package/dist/mcp.js +889 -0
- package/dist/money.js +5 -0
- package/dist/orgs.js +475 -0
- package/dist/pricing.d.ts +52 -0
- package/dist/pricing.js +181 -0
- package/dist/report.js +132 -0
- package/dist/routes.js +135 -0
- package/dist/runners-github.js +257 -0
- package/dist/runners-gitlab.js +125 -0
- package/dist/runners-spec.js +137 -0
- package/dist/runners.js +1458 -0
- package/dist/sdk/blake3.d.ts +10 -0
- package/dist/sdk/blake3.js +111 -0
- package/dist/sdk/bundle.d.ts +96 -0
- package/dist/sdk/bundle.js +227 -0
- package/dist/sdk/ca-guard.js +166 -0
- package/dist/sdk/caller.d.ts +73 -0
- package/dist/sdk/caller.js +47 -0
- package/dist/sdk/client.d.ts +3015 -0
- package/dist/sdk/client.js +2583 -0
- package/dist/sdk/command-errors.d.ts +41 -0
- package/dist/sdk/command-errors.js +36 -0
- package/dist/sdk/context.d.ts +119 -0
- package/dist/sdk/context.js +588 -0
- package/dist/sdk/core.d.ts +285 -0
- package/dist/sdk/core.js +266 -0
- package/dist/sdk/credstore.d.ts +90 -0
- package/dist/sdk/credstore.js +206 -0
- package/dist/sdk/dispatcher.js +86 -0
- package/dist/sdk/github.d.ts +158 -0
- package/dist/sdk/github.js +78 -0
- package/dist/sdk/gitlab.d.ts +104 -0
- package/dist/sdk/gitlab.js +20 -0
- package/dist/sdk/handles.d.ts +82 -0
- package/dist/sdk/handles.js +135 -0
- package/dist/sdk/hint.js +7 -0
- package/dist/sdk/http2.js +1921 -0
- package/dist/sdk/index.d.ts +34 -0
- package/dist/sdk/index.js +15 -0
- package/dist/sdk/keyed.gen.js +7 -0
- package/dist/sdk/models.gen.d.ts +6162 -0
- package/dist/sdk/models.gen.js +1 -0
- package/dist/sdk/proxy.js +249 -0
- package/dist/sdk/pty.d.ts +171 -0
- package/dist/sdk/pty.js +496 -0
- package/dist/sdk/sandbox.d.ts +537 -0
- package/dist/sdk/sandbox.js +725 -0
- package/dist/sdk/ssh.d.ts +25 -0
- package/dist/sdk/ssh.js +114 -0
- package/dist/sdk/trace.js +80 -0
- package/dist/sdk/transport-worker.js +466 -0
- package/dist/sdk/warm.js +40 -0
- package/dist/ssh.js +267 -0
- package/dist/surface.d.ts +95 -0
- package/dist/surface.js +1452 -0
- package/dist/templates.js +53 -0
- package/dist/term.js +50 -0
- package/dist/timing.js +71 -0
- package/dist/untar.js +324 -0
- package/dist/uploadguard.js +75 -0
- package/llms.txt +209 -0
- package/package.json +52 -0
package/dist/bin.js
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { GLOBAL_FLAGS, LISTED_COMMANDS, REQUEST_TIMEOUT_DEFAULT, SCHEMA, VERSION, findCommand, nearestFlag, notReleasedEnvelope, notReleasedLines, renderCommandHelp, renderHelp, unknownFlags, } from "./surface.js";
|
|
3
|
+
import { HANDLERS, client, serverLocation } from "./commands.js";
|
|
4
|
+
import { maybeFarNotice } from "./timing.js";
|
|
5
|
+
import { refineError } from "./errfix.js";
|
|
6
|
+
import { EXTRA_HANDLERS } from "./handlers.js";
|
|
7
|
+
import { BUNDLE_HANDLERS } from "./bundle.js";
|
|
8
|
+
import { LIVE_HANDLERS } from "./live.js";
|
|
9
|
+
import { SSH_HANDLERS } from "./ssh.js";
|
|
10
|
+
import { LOGIN_HANDLERS } from "./login.js";
|
|
11
|
+
import { ORG_HANDLERS } from "./orgs.js";
|
|
12
|
+
import { TEMPLATES_HANDLERS } from "./templates.js";
|
|
13
|
+
import { ACCOUNT_HANDLERS } from "./account.js";
|
|
14
|
+
import { MCP_HANDLERS } from "./mcp.js";
|
|
15
|
+
import { AGENT_HANDLERS } from "./agent.js";
|
|
16
|
+
import { CREDITS_HANDLERS, canAsk, claimOnRefusal } from "./credits.js";
|
|
17
|
+
import { RUNNERS_HANDLERS } from "./runners.js";
|
|
18
|
+
import { PRICING_HANDLERS } from "./pricing.js";
|
|
19
|
+
import { GITHUB_HANDLERS } from "./github.js";
|
|
20
|
+
import { GITLAB_HANDLERS } from "./gitlab.js";
|
|
21
|
+
import { emit, errorEnvelope, errorTextLines, parseDuration, setBeforeExit, toPromigenceError, usageError as usageFailure, USAGE_DOCS, write, } from "./io.js";
|
|
22
|
+
import { setCaller } from "./sdk/caller.js";
|
|
23
|
+
import { sh } from "./term.js";
|
|
24
|
+
import { parse, positionalsBeforeTail, takesTail } from "./argv.js";
|
|
25
|
+
setCaller("cli", VERSION, { default: true });
|
|
26
|
+
const flagValue = (p, name) => {
|
|
27
|
+
const v = p.flags.get(name);
|
|
28
|
+
const last = v?.[v.length - 1];
|
|
29
|
+
return typeof last === "string" ? last : undefined;
|
|
30
|
+
};
|
|
31
|
+
function editDistance(a, b) {
|
|
32
|
+
const d = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
33
|
+
for (let i = 1; i <= a.length; i++) {
|
|
34
|
+
let prev = d[0];
|
|
35
|
+
d[0] = i;
|
|
36
|
+
for (let j = 1; j <= b.length; j++) {
|
|
37
|
+
const cur = d[j];
|
|
38
|
+
d[j] = Math.min(d[j] + 1, d[j - 1] + 1, prev + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
39
|
+
prev = cur;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return d[b.length];
|
|
43
|
+
}
|
|
44
|
+
function outputMode(p) {
|
|
45
|
+
if (p.modeFlag)
|
|
46
|
+
return p.modeFlag;
|
|
47
|
+
const env = process.env["PROMIGENCE_OUTPUT"];
|
|
48
|
+
if (env === "json" || env === "text")
|
|
49
|
+
return env;
|
|
50
|
+
return process.stdout.isTTY ? "text" : "json";
|
|
51
|
+
}
|
|
52
|
+
function envProblem() {
|
|
53
|
+
const out = process.env["PROMIGENCE_OUTPUT"];
|
|
54
|
+
if (out !== undefined && out !== "" && out !== "json" && out !== "text") {
|
|
55
|
+
return { message: `PROMIGENCE_OUTPUT='${out}' is not an output mode`, fix: "Set PROMIGENCE_OUTPUT=json or text, or unset it." };
|
|
56
|
+
}
|
|
57
|
+
const url = process.env["PROMIGENCE_API_URL"];
|
|
58
|
+
if (url !== undefined && url !== "") {
|
|
59
|
+
let ok = false;
|
|
60
|
+
try {
|
|
61
|
+
ok = /^https?:$/.test(new URL(url).protocol);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
ok = false;
|
|
65
|
+
}
|
|
66
|
+
if (!ok)
|
|
67
|
+
return { message: `PROMIGENCE_API_URL='${url}' is not an http(s) URL`, fix: "Set it to the API's URL, e.g. https://api.promigence.ai/v1, or unset it." };
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
function commandMode(cmd, p, inferred) {
|
|
72
|
+
if (cmd.name === "sandbox ssh" && p.flags.has("--proxy"))
|
|
73
|
+
return "text";
|
|
74
|
+
const env = process.env["PROMIGENCE_OUTPUT"];
|
|
75
|
+
if (p.modeFlag || env === "json" || env === "text")
|
|
76
|
+
return inferred;
|
|
77
|
+
if (cmd.name === "exec" && p.flags.has("--sandbox") && !p.flags.has("--background"))
|
|
78
|
+
return "text";
|
|
79
|
+
return inferred;
|
|
80
|
+
}
|
|
81
|
+
function useColor(mode) {
|
|
82
|
+
return mode === "text" && !!process.stdout.isTTY && !("NO_COLOR" in process.env) && process.env["TERM"] !== "dumb";
|
|
83
|
+
}
|
|
84
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
85
|
+
function notReleased(mode, c) {
|
|
86
|
+
const env = notReleasedEnvelope(c);
|
|
87
|
+
return emit(mode, env, notReleasedLines(c, env), 1, !c.noGuidePointer);
|
|
88
|
+
}
|
|
89
|
+
function usageError(mode, raw, message) {
|
|
90
|
+
const env = {
|
|
91
|
+
schema: SCHEMA,
|
|
92
|
+
command: raw,
|
|
93
|
+
ok: false,
|
|
94
|
+
error: {
|
|
95
|
+
code: "usage",
|
|
96
|
+
message,
|
|
97
|
+
fix: "Run 'promigence --help' for the command list or 'promigence <command> --help' for one command.",
|
|
98
|
+
docs: USAGE_DOCS,
|
|
99
|
+
guide: "promigence agent-guide --section errors --code usage",
|
|
100
|
+
},
|
|
101
|
+
next: [{ cmd: "promigence --help", why: "command list" }],
|
|
102
|
+
};
|
|
103
|
+
return emit(mode, env, [`promigence: ${message} (exit 2)`, ` fix: ${env.error.fix}`], 2, true);
|
|
104
|
+
}
|
|
105
|
+
function checkFlags(cmd, p, argv = []) {
|
|
106
|
+
const unknown = unknownFlags(cmd, p.flags.keys());
|
|
107
|
+
if (unknown.length === 0) {
|
|
108
|
+
checkValueCounts(cmd, p);
|
|
109
|
+
return checkStrayWords(cmd, p, argv);
|
|
110
|
+
}
|
|
111
|
+
const first = unknown[0];
|
|
112
|
+
if (first === "--fresh") {
|
|
113
|
+
throw usageFailure(`--fresh does nothing for 'promigence ${cmd.name}': it sends no automatic idempotency key to skip`, `Drop --fresh: every \`promigence ${cmd.name}\` starts a new ${cmd.name === "run" ? "run" : "request"}. It is for the auto-keyed commands (${LISTED_COMMANDS.filter((c) => c.autoIdempotencyKey).map((c) => c.name).join(", ")}).`);
|
|
114
|
+
}
|
|
115
|
+
const near = nearestFlag(first, cmd);
|
|
116
|
+
const also = unknown.length > 1 ? ` (also ${unknown.slice(1).join(" ")})` : "";
|
|
117
|
+
throw usageFailure(`unknown flag ${first} for 'promigence ${cmd.name}'${also}`, `${near ? `Did you mean ${near}? ` : ""}Run 'promigence ${cmd.name} --help' for the flags this command takes.`);
|
|
118
|
+
}
|
|
119
|
+
function checkValueCounts(cmd, p) {
|
|
120
|
+
const spec = new Map([...GLOBAL_FLAGS, ...cmd.flags].map((f) => [f.name, f]));
|
|
121
|
+
for (const [name, values] of p.flags) {
|
|
122
|
+
const f = spec.get(name);
|
|
123
|
+
if (!f?.arg)
|
|
124
|
+
continue;
|
|
125
|
+
if (values.length > 1 && values.some((v) => v === true)) {
|
|
126
|
+
throw usageFailure(`${name} needs a value each time it is given`, `Pass ${name} <value> — or ${name}=<value> if the value starts with '-'.`);
|
|
127
|
+
}
|
|
128
|
+
if (values.length === 1 && values[0] === true && name !== "--devcontainer") {
|
|
129
|
+
throw usageFailure(`${name} needs a value`, `Pass ${name} ${f.arg} — or ${name}=<value> if the value starts with '-'.`);
|
|
130
|
+
}
|
|
131
|
+
const distinct = new Set(values.filter((v) => typeof v === "string"));
|
|
132
|
+
if (!f.repeatable && distinct.size > 1) {
|
|
133
|
+
throw usageFailure(`${name} was given ${values.length} times with different values; it takes one`, `Keep one ${name}. Run 'promigence ${cmd.name} --help' for what it takes.`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function checkStrayWords(cmd, p, argv) {
|
|
138
|
+
if (cmd.ownExtraWords)
|
|
139
|
+
return;
|
|
140
|
+
const room = cmd.name.split(" ").length + positionalsBeforeTail(cmd);
|
|
141
|
+
const extra = p.words.slice(room);
|
|
142
|
+
if (extra.length === 0)
|
|
143
|
+
return;
|
|
144
|
+
const at = argv.indexOf(extra[0]);
|
|
145
|
+
const flag = at >= 2 && argv[at - 2].startsWith("--") && !argv[at - 2].includes("=") ? argv[at - 2] : undefined;
|
|
146
|
+
const fixes = [
|
|
147
|
+
...(flag ? [`${flag} takes one value: to pass several, repeat it (${flag} A ${flag} B).`] : []),
|
|
148
|
+
...(takesTail(cmd) ? ["The command to run goes after `--`."] : []),
|
|
149
|
+
`Run 'promigence ${cmd.name} --help' for what it takes.`,
|
|
150
|
+
];
|
|
151
|
+
const near = !flag && at === cmd.name.split(" ").length ? nearestCommand([...cmd.name.split(" "), extra[0]]) : undefined;
|
|
152
|
+
throw usageFailure(`'promigence ${cmd.name}' has no place for ${extra.length === 1 ? "an argument" : `${extra.length} arguments`} here${flag ? ` (after ${flag} and its value)` : ""}; nothing was run`, [...(near && near !== cmd.name ? [`Did you mean 'promigence ${near}'?`] : []), ...fixes].join(" "));
|
|
153
|
+
}
|
|
154
|
+
function nearestCommand(words) {
|
|
155
|
+
const typed = words.join(" ");
|
|
156
|
+
let best;
|
|
157
|
+
let bestD = Number.POSITIVE_INFINITY;
|
|
158
|
+
for (const c of LISTED_COMMANDS) {
|
|
159
|
+
const d = editDistance(typed, c.name);
|
|
160
|
+
if (d < bestD) {
|
|
161
|
+
bestD = d;
|
|
162
|
+
best = c.name;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return best !== undefined && bestD > 0 && bestD <= Math.max(2, Math.floor(typed.length / 5)) ? best : undefined;
|
|
166
|
+
}
|
|
167
|
+
function requestTimeoutMs(p) {
|
|
168
|
+
if (p.flags.has("--request-timeout")) {
|
|
169
|
+
const flag = flagValue(p, "--request-timeout");
|
|
170
|
+
if (flag === undefined) {
|
|
171
|
+
throw usageFailure("--request-timeout needs a value", `Pass --request-timeout ${REQUEST_TIMEOUT_DEFAULT} (also ms, s, m, h; a bare number is seconds).`);
|
|
172
|
+
}
|
|
173
|
+
const ms = parseDuration(flag, "--request-timeout");
|
|
174
|
+
if (ms <= 0)
|
|
175
|
+
throw usageFailure("--request-timeout must be more than 0", `Pass --request-timeout ${REQUEST_TIMEOUT_DEFAULT}.`);
|
|
176
|
+
return ms;
|
|
177
|
+
}
|
|
178
|
+
const env = process.env["PROMIGENCE_REQUEST_TIMEOUT"];
|
|
179
|
+
if (env !== undefined && env !== "")
|
|
180
|
+
return parseDuration(env, "PROMIGENCE_REQUEST_TIMEOUT");
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
function errorNext(cmd, code, p) {
|
|
184
|
+
switch (code) {
|
|
185
|
+
case "auth":
|
|
186
|
+
return [
|
|
187
|
+
{ cmd: "promigence auth login --from-env PROMIGENCE_API_KEY", why: "store a key (the OS keychain, else ~/.config/promigence/credentials, 0600)" },
|
|
188
|
+
{ cmd: "promigence me", why: "confirm the key once you have one" },
|
|
189
|
+
{ cmd: "promigence login", why: "sign up or sign in; it mints a key and stores it" },
|
|
190
|
+
];
|
|
191
|
+
case "usage":
|
|
192
|
+
case "invalid_argument":
|
|
193
|
+
return [{ cmd: `promigence ${cmd.name} --help`, why: "flags, arguments and exit codes for this command" }];
|
|
194
|
+
case "not_found":
|
|
195
|
+
return [{ cmd: "promigence examples", why: "what you can fork with no build (the built-in base)" }];
|
|
196
|
+
case "rate_limited":
|
|
197
|
+
return [{ cmd: "promigence me", why: "your concurrency and rate limits" }];
|
|
198
|
+
case "cap_exceeded": {
|
|
199
|
+
const count = p ? flagValue(p, "--count") : undefined;
|
|
200
|
+
if (count === undefined)
|
|
201
|
+
return [{ cmd: "promigence agent-guide --section cost", why: "what a run costs, and how --cap bounds it" }];
|
|
202
|
+
const snap = (p ? flagValue(p, "--snapshot") : undefined) ?? "promigence/base";
|
|
203
|
+
const timeout = p ? flagValue(p, "--timeout") : undefined;
|
|
204
|
+
return [{
|
|
205
|
+
cmd: `${sh `promigence run quote --snapshot ${snap} --count ${count}`}${timeout ? sh ` --timeout ${timeout}` : ""}`,
|
|
206
|
+
why: "price the run before launching it",
|
|
207
|
+
}];
|
|
208
|
+
}
|
|
209
|
+
case "unreachable":
|
|
210
|
+
return [{ cmd: "promigence doctor", why: "check client, auth and API reachability" }];
|
|
211
|
+
default:
|
|
212
|
+
return [{ cmd: sh `promigence agent-guide --section errors --code ${code}`, why: "what this error means and how to fix it" }];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async function main(argv) {
|
|
216
|
+
const p = parse(argv);
|
|
217
|
+
let mode = outputMode(p);
|
|
218
|
+
if (p.version) {
|
|
219
|
+
if (p.modeFlag === "json")
|
|
220
|
+
await write(process.stdout, JSON.stringify({ schema: SCHEMA, command: "version", ok: true, version: VERSION, next: [] }) + "\n");
|
|
221
|
+
else
|
|
222
|
+
await write(process.stdout, `${VERSION}\n`);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (p.words[0] === "help" && !findCommand(p.words)) {
|
|
226
|
+
const target = p.words.length > 1 ? findCommand(p.words.slice(1)) : undefined;
|
|
227
|
+
if (p.words.length > 1 && !target)
|
|
228
|
+
return void (await usageError(mode, p.words.slice(1).join(" "), `unknown command '${p.words.slice(1).join(" ")}'`));
|
|
229
|
+
await write(process.stdout, target ? renderCommandHelp(target) : renderHelp());
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const cmd = findCommand(p.words);
|
|
233
|
+
if (p.words.length === 0) {
|
|
234
|
+
const stray = [...p.flags.keys()].filter((f) => !GLOBAL_FLAGS.some((g) => g.name === f));
|
|
235
|
+
if (stray.length) {
|
|
236
|
+
const known = ["--version", "--help", "--json", "--text", ...GLOBAL_FLAGS.map((g) => g.name)];
|
|
237
|
+
const short = { "-v": "--version", "-V": "--version", "-h": "--help" };
|
|
238
|
+
const near = short[stray[0]] ?? known.find((k) => editDistance(k, stray[0]) <= 2);
|
|
239
|
+
return void (await usageError(mode, stray[0], `unknown flag ${stray[0]}${near ? `; did you mean ${near}?` : ""}`));
|
|
240
|
+
}
|
|
241
|
+
if (p.modeFlag === "json") {
|
|
242
|
+
await write(process.stdout, JSON.stringify({ schema: SCHEMA, command: "help", ok: true, version: VERSION, commands: LISTED_COMMANDS.map((c) => c.name), next: [{ cmd: "promigence agent-guide", why: "the guide for agents" }] }) + "\n");
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const text = renderHelp();
|
|
246
|
+
await write(process.stdout, useColor(mode) ? text.replace(/^(Setup|Snapshots|Runs|Sandboxes|Ops)$/gm, bold) : text);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (!cmd) {
|
|
250
|
+
const prefix = p.words.join(" ") + " ";
|
|
251
|
+
const group = LISTED_COMMANDS.filter((c) => c.name.startsWith(prefix));
|
|
252
|
+
if (group.length) {
|
|
253
|
+
if (mode === "json") {
|
|
254
|
+
await write(process.stdout, JSON.stringify({ schema: SCHEMA, command: p.words.join(" "), ok: true, commands: group.map((c) => c.name), next: group.slice(0, 3).map((c) => ({ cmd: `promigence ${c.name} --help`, why: c.summary })) }) + "\n");
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
await write(process.stdout, [`promigence ${p.words.join(" ")} — one of:`, ...group.map((c) => ` ${c.name.padEnd(22)} ${c.summary}`), `Run 'promigence ${group[0].name} --help' for one of them.`, ""].join("\n"));
|
|
258
|
+
}
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const SHORT = { "version": "--version", "-v": "--version", "-V": "--version", "-h": "--help" };
|
|
262
|
+
const near = (p.words.length === 1 ? SHORT[p.words[0]] : undefined) ?? nearestCommand(p.words);
|
|
263
|
+
return void (await usageError(mode, p.words.join(" "), `unknown command '${p.words.join(" ")}'${near ? `; did you mean '${near}'?` : ""}`));
|
|
264
|
+
}
|
|
265
|
+
mode = commandMode(cmd, p, mode);
|
|
266
|
+
const badEnv = envProblem();
|
|
267
|
+
if (badEnv)
|
|
268
|
+
return void (await usageError(mode, cmd.name, badEnv.message));
|
|
269
|
+
if (p.help) {
|
|
270
|
+
await write(process.stdout, renderCommandHelp(cmd));
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const handler = HANDLERS[cmd.name] ?? EXTRA_HANDLERS[cmd.name] ?? BUNDLE_HANDLERS[cmd.name] ?? LOGIN_HANDLERS[cmd.name] ?? ORG_HANDLERS[cmd.name] ?? LIVE_HANDLERS[cmd.name] ?? SSH_HANDLERS[cmd.name] ?? ACCOUNT_HANDLERS[cmd.name] ?? MCP_HANDLERS[cmd.name] ?? AGENT_HANDLERS[cmd.name] ?? CREDITS_HANDLERS[cmd.name] ?? RUNNERS_HANDLERS[cmd.name] ?? PRICING_HANDLERS[cmd.name] ?? GITHUB_HANDLERS[cmd.name] ?? GITLAB_HANDLERS[cmd.name] ?? TEMPLATES_HANDLERS[cmd.name];
|
|
274
|
+
if (!handler)
|
|
275
|
+
return void (await notReleased(mode, cmd));
|
|
276
|
+
const ctx = {
|
|
277
|
+
cmd,
|
|
278
|
+
args: p.words.slice(cmd.name.split(" ").length),
|
|
279
|
+
flags: p.flags,
|
|
280
|
+
cmdTail: p.cmdTail,
|
|
281
|
+
mode,
|
|
282
|
+
requestTimeoutMs: undefined,
|
|
283
|
+
explicitMode: p.modeFlag,
|
|
284
|
+
pointer: !cmd.noGuidePointer,
|
|
285
|
+
apiKey: flagValue(p, "--api-key"),
|
|
286
|
+
};
|
|
287
|
+
if (ctx.apiKey !== undefined && cmd.name !== "auth login" && cmd.name !== "doctor") {
|
|
288
|
+
process.stderr.write("promigence: warning: --api-key puts the key on the command line, where `ps` and shell history can read it; prefer PROMIGENCE_API_KEY or `promigence auth login --from-env VAR`.\n");
|
|
289
|
+
}
|
|
290
|
+
setBeforeExit(() => maybeFarNotice({ json: ctx.mode === "json", location: () => serverLocation(ctx) }));
|
|
291
|
+
try {
|
|
292
|
+
checkFlags(cmd, p, argv);
|
|
293
|
+
ctx.requestTimeoutMs = requestTimeoutMs(p);
|
|
294
|
+
await handler(ctx);
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
let billingOff;
|
|
298
|
+
const refined = await refineError(toPromigenceError(err), {
|
|
299
|
+
command: cmd.name,
|
|
300
|
+
args: ctx.args,
|
|
301
|
+
...(flagValue(p, "--sandbox") === undefined ? {} : { sandbox: flagValue(p, "--sandbox") }),
|
|
302
|
+
billingOff: () => (billingOff ??= client(ctx).billing.usage()
|
|
303
|
+
.then((b) => b.billing_enabled === false)
|
|
304
|
+
.catch(() => false)),
|
|
305
|
+
}).catch(() => ({ err: toPromigenceError(err), next: undefined }));
|
|
306
|
+
const e = refined.err;
|
|
307
|
+
let next = refined.next ?? errorNext(cmd, e.code, p);
|
|
308
|
+
const runId = ctx.startedRunId;
|
|
309
|
+
if (runId !== undefined && !next.some((n) => n.cmd.includes(runId))) {
|
|
310
|
+
next = [
|
|
311
|
+
{ cmd: sh `promigence run report ${runId}`, why: "the run started and goes on: what it did" },
|
|
312
|
+
{ cmd: sh `promigence run kill ${runId}`, why: "end it, if you no longer want it" },
|
|
313
|
+
...next,
|
|
314
|
+
];
|
|
315
|
+
}
|
|
316
|
+
const env = errorEnvelope(cmd.name, e, next);
|
|
317
|
+
if (runId !== undefined)
|
|
318
|
+
env["run_id"] = runId;
|
|
319
|
+
let exit = e.cliExit;
|
|
320
|
+
if (cmd.passthroughExit && !p.flags.has("--no-passthrough")) {
|
|
321
|
+
env.promigence_exit = exit;
|
|
322
|
+
exit = e.code === "enoent" ? 127 : cmd.passthroughExit;
|
|
323
|
+
}
|
|
324
|
+
if (e.code === "credit_unclaimed" && mode === "text" && canAsk()) {
|
|
325
|
+
const lines = await claimOnRefusal(ctx).catch(() => undefined);
|
|
326
|
+
if (lines)
|
|
327
|
+
return void (await emit(mode, env, lines, exit, false));
|
|
328
|
+
}
|
|
329
|
+
await emit(mode, env, errorTextLines(cmd.name, e, exit, next), exit, !cmd.noGuidePointer);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
await main(process.argv.slice(2));
|
package/dist/bundle.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, dirname, resolve } from "node:path";
|
|
3
|
+
import { BUNDLE_EXT, BundleVerifyError, NotFoundError, NotVerifiedError, parseBundle, platformOf, renderBundle, verifyBundle, } from "./sdk/index.js";
|
|
4
|
+
import { bool, client, nexts, positional, snapshotSource, str, } from "./commands.js";
|
|
5
|
+
import { emit, okEnvelope, usageError, write } from "./io.js";
|
|
6
|
+
import { sh } from "./term.js";
|
|
7
|
+
function asPromigenceError(e, path) {
|
|
8
|
+
if (!(e instanceof BundleVerifyError))
|
|
9
|
+
return e;
|
|
10
|
+
if (e.kind === "canonical" || e.kind === "schema") {
|
|
11
|
+
return usageError(`${path}: ${e.message}`, `A bundle is written by 'promigence snapshot export'. Check you passed the right file.`);
|
|
12
|
+
}
|
|
13
|
+
return new NotVerifiedError(`${path}: ${e.message}`, "This file is not the environment it names. Ask whoever sent it for a fresh " +
|
|
14
|
+
"'promigence snapshot export', or export it yourself from the snapshot id it claims.");
|
|
15
|
+
}
|
|
16
|
+
export function loadBundle(path) {
|
|
17
|
+
let text;
|
|
18
|
+
try {
|
|
19
|
+
text = readFileSync(path, "utf8");
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
throw new NotFoundError(`no such bundle: ${path}`, `Pass the path to a .promigence file, or export one with \`${sh `promigence snapshot export <hash> --out ${basename(path)}`}\`.`);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const bundle = parseBundle(text);
|
|
26
|
+
const form = verifyBundle(bundle);
|
|
27
|
+
return { bundle, path, text, form };
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
throw asPromigenceError(e, path);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export const looksLikeBundle = (v) => v.endsWith(BUNDLE_EXT) || ((v.startsWith("./") || v.startsWith("../") || v.startsWith("/")) && fileExists(v));
|
|
34
|
+
function fileExists(p) {
|
|
35
|
+
try {
|
|
36
|
+
return statSync(p).isFile();
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export async function snapshotArg(ctx, c) {
|
|
43
|
+
const v = str(ctx, "--snapshot");
|
|
44
|
+
if (v === undefined) {
|
|
45
|
+
throw usageError("--snapshot is required", "Pass --snapshot snap_<id> | <alias> | <alias>@<commit7> | ./env.promigence, or promigence/base (the built-in base).");
|
|
46
|
+
}
|
|
47
|
+
if (!looksLikeBundle(v))
|
|
48
|
+
return v;
|
|
49
|
+
const loaded = loadBundle(v);
|
|
50
|
+
await write(process.stderr, `${v}: ${loaded.form} bundle, verified — ${loaded.bundle.snap_id} (${loaded.bundle.manifest_hash})\n`);
|
|
51
|
+
await registerBundle(c, loaded);
|
|
52
|
+
return loaded.bundle.snap_id;
|
|
53
|
+
}
|
|
54
|
+
export async function registerBundle(c, loaded) {
|
|
55
|
+
const id = loaded.bundle.snap_id;
|
|
56
|
+
const known = await c.snapshots.get(id).then(() => true).catch(() => false);
|
|
57
|
+
if (known)
|
|
58
|
+
return { known: true, registered: true, how: "already in your org" };
|
|
59
|
+
const origin = bundleOrigin(loaded.bundle);
|
|
60
|
+
throw new NotFoundError(`${id} is not in your org, and a bundle from another account cannot be brought in yet`, `The bundle verified: it names ${id}${origin.length ? ` (${origin.join(" · ")})` : ""}. To run it here, build ` +
|
|
61
|
+
"the same snapshot in your org ('promigence snapshot create' with the same inputs), or run it with the " +
|
|
62
|
+
"account that holds it.");
|
|
63
|
+
}
|
|
64
|
+
export function bundleOrigin(b, liveOf) {
|
|
65
|
+
const verification = { ...(b.verification ?? {}) };
|
|
66
|
+
if (liveOf)
|
|
67
|
+
verification["from_live_sandbox"] = liveOf;
|
|
68
|
+
const text = (v) => (typeof v === "string" ? v : "");
|
|
69
|
+
const source = snapshotSource({ repo: text(b.provenance["repo"]), commit: text(b.provenance["commit"]), verification });
|
|
70
|
+
const verify = text(b.provenance["verify"]?.cmd);
|
|
71
|
+
return [...(source === "-" ? [] : [source]), ...(verify ? [`verify ${JSON.stringify(verify)}`] : [])];
|
|
72
|
+
}
|
|
73
|
+
function outPath(ctx, b) {
|
|
74
|
+
const out = str(ctx, "--out");
|
|
75
|
+
if (out === "-")
|
|
76
|
+
return undefined;
|
|
77
|
+
if (out !== undefined)
|
|
78
|
+
return out;
|
|
79
|
+
if (!process.stdout.isTTY && ctx.explicitMode !== "json")
|
|
80
|
+
return undefined;
|
|
81
|
+
return `${b.alias ?? b.snap_id}${BUNDLE_EXT}`;
|
|
82
|
+
}
|
|
83
|
+
const snapshotExport = async (ctx) => {
|
|
84
|
+
const id = positional(ctx, "a snapshot id or alias", "promigence snapshot export snap_01");
|
|
85
|
+
const full = bool(ctx, "--full") || bool(ctx, "--layers");
|
|
86
|
+
const citation = bool(ctx, "--citation") || bool(ctx, "--no-layers");
|
|
87
|
+
if (full && citation) {
|
|
88
|
+
throw usageError("--full and --citation contradict each other", "Pass one: --full writes the full form however large, --citation writes identity, provenance and verification only.");
|
|
89
|
+
}
|
|
90
|
+
const c = client(ctx);
|
|
91
|
+
const { bundle, served_by } = await c.snapshots.bundle(id);
|
|
92
|
+
const form = verifyBundle(bundle);
|
|
93
|
+
const text = renderBundle(bundle);
|
|
94
|
+
const file = outPath(ctx, bundle);
|
|
95
|
+
if (file === undefined) {
|
|
96
|
+
await write(process.stdout, text);
|
|
97
|
+
return ctxExit(0);
|
|
98
|
+
}
|
|
99
|
+
const path = resolve(file);
|
|
100
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
101
|
+
writeFileSync(path, text);
|
|
102
|
+
const next = nexts([sh `promigence run --snapshot ${file} --count 2 --cap 1 -- CMD`, "run it from the file, here or anywhere"], [sh `promigence snapshot inspect ${bundle.snap_id}`, "the manifest behind it"]);
|
|
103
|
+
let origin = bundleOrigin(bundle);
|
|
104
|
+
if (origin.length === 0) {
|
|
105
|
+
const rec = await c.snapshots.get(bundle.snap_id).catch(() => undefined);
|
|
106
|
+
const live = rec?.verification?.["from_live_sandbox"];
|
|
107
|
+
if (typeof live === "string" && live !== "")
|
|
108
|
+
origin = bundleOrigin(bundle, live);
|
|
109
|
+
}
|
|
110
|
+
const platform = platformOf(bundle);
|
|
111
|
+
const lines = [
|
|
112
|
+
`wrote ${file} — ${text.length.toLocaleString("en-US")} B, ${form} form (${served_by}-composed)`,
|
|
113
|
+
` ${bundle.snap_id}${bundle.alias ? ` (alias ${bundle.alias})` : ""} · ${bundle.manifest_hash}`,
|
|
114
|
+
...(origin.length ? [` ${origin.join(" · ")}`] : []),
|
|
115
|
+
...(platform ? [` platform ${platform.slice(0, 19)}…`] : []),
|
|
116
|
+
" it runs where its snapshot already is",
|
|
117
|
+
];
|
|
118
|
+
return emit(ctx.mode, okEnvelope(ctx.cmd.name, {
|
|
119
|
+
path, bytes: text.length, form, served_by,
|
|
120
|
+
snapshot_id: bundle.snap_id, manifest_hash: bundle.manifest_hash,
|
|
121
|
+
platform: platform ?? null,
|
|
122
|
+
bundle,
|
|
123
|
+
}, next), lines, 0, ctx.pointer);
|
|
124
|
+
};
|
|
125
|
+
async function ctxExit(code) {
|
|
126
|
+
await write(process.stdout, "");
|
|
127
|
+
process.exit(code);
|
|
128
|
+
throw new Error("unreachable");
|
|
129
|
+
}
|
|
130
|
+
export const BUNDLE_HANDLERS = {
|
|
131
|
+
"snapshot export": snapshotExport,
|
|
132
|
+
};
|
|
133
|
+
export { existsSync };
|
package/dist/capacity.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const CR = "\r";
|
|
2
|
+
const CLEAR_LINE = "\u001b[2K";
|
|
3
|
+
export function statusLine(stream = process.stderr) {
|
|
4
|
+
const tty = stream.isTTY === true;
|
|
5
|
+
let shown = false;
|
|
6
|
+
let last = "";
|
|
7
|
+
return {
|
|
8
|
+
set(text) {
|
|
9
|
+
if (!tty || !text || text === last)
|
|
10
|
+
return;
|
|
11
|
+
stream.write(CR + CLEAR_LINE + fitLine(text, stream.columns));
|
|
12
|
+
shown = true;
|
|
13
|
+
last = text;
|
|
14
|
+
},
|
|
15
|
+
clear() {
|
|
16
|
+
if (!tty || !shown)
|
|
17
|
+
return;
|
|
18
|
+
stream.write(CR + CLEAR_LINE);
|
|
19
|
+
shown = false;
|
|
20
|
+
last = "";
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function fitLine(text, columns) {
|
|
25
|
+
if (!columns || columns < 2 || text.length < columns)
|
|
26
|
+
return text;
|
|
27
|
+
return `${text.slice(0, columns - 2)}…`;
|
|
28
|
+
}
|
|
29
|
+
export function queuedLines(rows, indent = " ") {
|
|
30
|
+
const by = new Map();
|
|
31
|
+
for (const r of rows) {
|
|
32
|
+
const m = r.queued_message;
|
|
33
|
+
if (typeof m === "string" && m !== "")
|
|
34
|
+
by.set(m, (by.get(m) ?? 0) + 1);
|
|
35
|
+
}
|
|
36
|
+
return [...by].map(([m, n]) => `${indent}${rows.length === 1 ? "" : `${n} `}queued: ${m}`);
|
|
37
|
+
}
|
|
38
|
+
export function queuedClause(rows) {
|
|
39
|
+
let best;
|
|
40
|
+
const by = new Map();
|
|
41
|
+
for (const r of rows) {
|
|
42
|
+
const m = r.queued_message;
|
|
43
|
+
if (typeof m !== "string" || m === "")
|
|
44
|
+
continue;
|
|
45
|
+
const n = (by.get(m) ?? 0) + 1;
|
|
46
|
+
by.set(m, n);
|
|
47
|
+
if (!best || n > best[1])
|
|
48
|
+
best = [m, n];
|
|
49
|
+
}
|
|
50
|
+
return best ? `${best[1]} still queued: ${best[0]}` : undefined;
|
|
51
|
+
}
|
|
52
|
+
export function capacityLine(c, ready, total) {
|
|
53
|
+
if (!c)
|
|
54
|
+
return undefined;
|
|
55
|
+
if (total > 0 && ready >= total)
|
|
56
|
+
return undefined;
|
|
57
|
+
const of = `${ready} of ${total} sandbox${total === 1 ? "" : "es"} ready`;
|
|
58
|
+
if (c.queued_message)
|
|
59
|
+
return `queued: ${c.queued_message} — ${of}`;
|
|
60
|
+
if (c.state === "blocked" && c.blocked)
|
|
61
|
+
return `capacity: cannot grow — ${c.blocked.reason}`;
|
|
62
|
+
if (c.state === "arriving") {
|
|
63
|
+
const when = c.eta_s === null || c.eta_s === undefined ? "" : `, ~${c.eta_s}s`;
|
|
64
|
+
return `capacity arriving: more capacity is being added${when} — ${of}`;
|
|
65
|
+
}
|
|
66
|
+
if (c.awaiting_capacity > 0)
|
|
67
|
+
return `waiting for capacity: ${c.awaiting_capacity} queued`;
|
|
68
|
+
return ready < total ? of : undefined;
|
|
69
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { PromigenceClient, type ExecResponse, type OptimizeFor, type RunReport, type SandboxRef, type ScoreMode, type SecretRecord, type SnapshotBuild } from "./sdk/index.js";
|
|
2
|
+
import { type Mode } from "./io.js";
|
|
3
|
+
import { type BuildPrice } from "./pricing.js";
|
|
4
|
+
import { type Command, type NextHint } from "./surface.js";
|
|
5
|
+
export interface Ctx {
|
|
6
|
+
cmd: Command;
|
|
7
|
+
args: string[];
|
|
8
|
+
flags: Map<string, Array<string | true>>;
|
|
9
|
+
cmdTail: string[];
|
|
10
|
+
mode: Mode;
|
|
11
|
+
explicitMode?: Mode | undefined;
|
|
12
|
+
pointer: boolean;
|
|
13
|
+
apiKey: string | undefined;
|
|
14
|
+
requestTimeoutMs?: number | undefined;
|
|
15
|
+
startedRunId?: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
export type Handler = (ctx: Ctx) => Promise<never>;
|
|
18
|
+
export declare function str(ctx: Ctx, name: string): string | undefined;
|
|
19
|
+
export declare function list(ctx: Ctx, name: string): string[];
|
|
20
|
+
export declare function bool(ctx: Ctx, name: string): boolean;
|
|
21
|
+
export declare function required(ctx: Ctx, name: string, hint: string): string;
|
|
22
|
+
export declare function clientOpts(ctx: Ctx): {
|
|
23
|
+
apiKey?: string;
|
|
24
|
+
requestTimeoutMs?: number;
|
|
25
|
+
cliErrors: true;
|
|
26
|
+
};
|
|
27
|
+
export declare function client(ctx: Ctx): PromigenceClient;
|
|
28
|
+
export declare function serverLocation(ctx: Ctx): Promise<string | undefined>;
|
|
29
|
+
export declare const nexts: (...items: Array<[string, string]>) => NextHint[];
|
|
30
|
+
export declare const KEPT_BY_HOLDERS = "sandboxes that were already given its value keep it until they end; it stays masked in their output";
|
|
31
|
+
export declare function waitBound(ctx: Ctx): number;
|
|
32
|
+
export declare function spendCap(ctx: Ctx, c: PromigenceClient): Promise<number>;
|
|
33
|
+
export declare function replayNote(started: {
|
|
34
|
+
idempotent_replay?: boolean;
|
|
35
|
+
idempotent_replay_age_s?: number;
|
|
36
|
+
}, explicitKey: boolean): string | undefined;
|
|
37
|
+
export declare function buildReplayNote(started: {
|
|
38
|
+
build_id?: string;
|
|
39
|
+
idempotent_replay?: boolean;
|
|
40
|
+
idempotent_replay_age_s?: number;
|
|
41
|
+
}, explicitKey: boolean): string | undefined;
|
|
42
|
+
export declare function optimizeForFlag(ctx: Ctx): OptimizeFor | undefined;
|
|
43
|
+
export declare function gradeOpts(ctx: Ctx): {
|
|
44
|
+
cmd: string;
|
|
45
|
+
holdoutCmd?: string;
|
|
46
|
+
timeoutMs?: number;
|
|
47
|
+
score?: ScoreMode;
|
|
48
|
+
} | undefined;
|
|
49
|
+
export declare function secretListLines(s: SecretRecord): string[];
|
|
50
|
+
export declare function buildPriceOf(b: SnapshotBuild): BuildPrice | undefined;
|
|
51
|
+
export declare function verifyTiming(v: Record<string, unknown> | undefined): string | undefined;
|
|
52
|
+
export declare function buildLogLines(log: string[] | undefined, state: string): string[];
|
|
53
|
+
export declare function snapshotSource(s: {
|
|
54
|
+
repo?: string;
|
|
55
|
+
commit?: string;
|
|
56
|
+
verification?: Record<string, unknown>;
|
|
57
|
+
}): string;
|
|
58
|
+
export declare function readyLine(ourMs: number | undefined, totalMs: number): string;
|
|
59
|
+
export declare function sandboxIdLines(sandboxes: ReadonlyArray<Pick<SandboxRef, "sandbox_id" | "state">>, cap?: number): string[];
|
|
60
|
+
type EnvError = {
|
|
61
|
+
code: string;
|
|
62
|
+
message: string;
|
|
63
|
+
fix: string;
|
|
64
|
+
docs: string;
|
|
65
|
+
guide: string;
|
|
66
|
+
};
|
|
67
|
+
export declare function envError(code: string, message: string, fix: string): EnvError;
|
|
68
|
+
export interface ExecOutcome {
|
|
69
|
+
exitCode: number | null;
|
|
70
|
+
fields: Record<string, unknown>;
|
|
71
|
+
error?: EnvError;
|
|
72
|
+
}
|
|
73
|
+
export declare function execOutcome(res: ExecResponse, sandboxId: string, timeoutMs?: number, words?: "cli" | "mcp"): ExecOutcome;
|
|
74
|
+
export declare function execTimingLine(exitCode: number | null | undefined, wallMs: unknown, totalMs: number, isTTY?: boolean, env?: NodeJS.ProcessEnv): string;
|
|
75
|
+
export declare function endNotice(res: ExecResponse, timeoutMs?: number): string;
|
|
76
|
+
export declare const MAX_OUTPUT_BYTES_PIPED: number;
|
|
77
|
+
export declare function truncationNotice(kept: "first" | "last", maxOutputBytes: number | undefined): string;
|
|
78
|
+
export declare function tagLines(sandboxId: string, text: string, escape?: boolean): string[];
|
|
79
|
+
export declare const GRADES_SHOWN = 10;
|
|
80
|
+
export declare function gradeRowLines(report: RunReport): string[];
|
|
81
|
+
export declare function commandOutputLines(report: RunReport, outputs: ReadonlyMap<string, OutputTail>): string[];
|
|
82
|
+
export declare const SETTLE_WAIT_MS = 15000;
|
|
83
|
+
type ReportRow = NonNullable<RunReport["sandboxes"]>[number];
|
|
84
|
+
export declare const limitPauseOf: (s: ReportRow) => "spend_cap" | "credits_exhausted" | undefined;
|
|
85
|
+
export declare function runError(report: RunReport, exit: number): EnvError | undefined;
|
|
86
|
+
export declare function runHeadline(report: RunReport, count: number): string;
|
|
87
|
+
export declare const FAILURES_SHOWN = 5;
|
|
88
|
+
export declare function limitPauseLines(report: RunReport): string[];
|
|
89
|
+
export declare function failureLines(report: RunReport, outputs: ReadonlyMap<string, OutputTail>, stderrTail: boolean): string[];
|
|
90
|
+
export interface OutputTail {
|
|
91
|
+
stdout: string;
|
|
92
|
+
stderr: string;
|
|
93
|
+
truncated: boolean;
|
|
94
|
+
}
|
|
95
|
+
export declare const OUTPUT_TAIL_SANDBOXES = 20;
|
|
96
|
+
export declare const OUTPUT_TAIL_CHARS = 4096;
|
|
97
|
+
export declare function outputTails(c: PromigenceClient, sandboxes: ReadonlyArray<{
|
|
98
|
+
sandbox_id: string;
|
|
99
|
+
execs?: Array<{
|
|
100
|
+
exec_id: string;
|
|
101
|
+
}>;
|
|
102
|
+
}>): Promise<Map<string, OutputTail>>;
|
|
103
|
+
export declare function positional(ctx: Ctx, what: string, example: string): string;
|
|
104
|
+
export declare function supportStoppedLines(sandboxes: ReadonlyArray<{
|
|
105
|
+
sandbox_id: string;
|
|
106
|
+
outcome?: string | null;
|
|
107
|
+
}>): string[];
|
|
108
|
+
export declare function filesPutTarArgs(out: string, parent: string, base: string, noMetadata?: string[]): string[];
|
|
109
|
+
export declare const HANDLERS: Readonly<Record<string, Handler>>;
|
|
110
|
+
export {};
|