@intent-engine/cli 0.1.28 → 0.1.31
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/dist/src/agent/mandate-revoke.js +3 -2
- package/dist/src/agent/mandate-revoke.js.map +1 -1
- package/dist/src/agent/problems.d.ts +1 -0
- package/dist/src/agent/problems.js +2 -1
- package/dist/src/agent/problems.js.map +1 -1
- package/dist/src/agent/settle.js +3 -2
- package/dist/src/agent/settle.js.map +1 -1
- package/dist/src/agent/wallet/attest.js +2 -2
- package/dist/src/agent/wallet/attest.js.map +1 -1
- package/dist/src/agent/wallet/committee.js +3 -3
- package/dist/src/agent/wallet/committee.js.map +1 -1
- package/dist/src/agent/wallet/guard.d.ts +7 -3
- package/dist/src/agent/wallet/guard.js +22 -5
- package/dist/src/agent/wallet/guard.js.map +1 -1
- package/dist/src/agent/wallet/split.js +2 -2
- package/dist/src/agent/wallet/split.js.map +1 -1
- package/dist/src/agent/work-claims.js +8 -1
- package/dist/src/agent/work-claims.js.map +1 -1
- package/dist/src/arg-options.d.ts +7 -1
- package/dist/src/arg-options.js +2 -1
- package/dist/src/arg-options.js.map +1 -1
- package/dist/src/arg-usage.js +1 -1
- package/dist/src/arg-usage.js.map +1 -1
- package/dist/src/arg-values.d.ts +2 -1
- package/dist/src/arg-values.js +2 -1
- package/dist/src/arg-values.js.map +1 -1
- package/dist/src/args.js +2 -4
- package/dist/src/args.js.map +1 -1
- package/dist/src/check-process.d.ts +1 -0
- package/dist/src/check-process.js +1 -1
- package/dist/src/check-process.js.map +1 -1
- package/dist/src/claim-commands.d.ts +1 -0
- package/dist/src/claim-commands.js +5 -0
- package/dist/src/claim-commands.js.map +1 -1
- package/dist/src/commands.js +4 -2
- package/dist/src/commands.js.map +1 -1
- package/dist/src/flows.d.ts +2 -2
- package/dist/src/flows.js +6 -2
- package/dist/src/flows.js.map +1 -1
- package/dist/src/host-judge.d.ts +10 -3
- package/dist/src/host-judge.js +18 -9
- package/dist/src/host-judge.js.map +1 -1
- package/dist/src/judge.d.ts +2 -0
- package/dist/src/judge.js +18 -5
- package/dist/src/judge.js.map +1 -1
- package/dist/src/node-judge.d.ts +30 -0
- package/dist/src/node-judge.js +231 -0
- package/dist/src/node-judge.js.map +1 -0
- package/dist/src/node-runner.d.ts +2 -0
- package/dist/src/node-runner.js +120 -0
- package/dist/src/node-runner.js.map +1 -0
- package/dist/src/sandbox.d.ts +10 -5
- package/dist/src/sandbox.js +33 -18
- package/dist/src/sandbox.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/viper.d.ts +7 -1
- package/dist/src/viper.js +10 -3
- package/dist/src/viper.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { chmod, mkdir, mkdtemp, writeFile } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join, posix } from "node:path";
|
|
6
|
+
import { removeCopy } from "./artifact.js";
|
|
7
|
+
import { removeContainer } from "./check-process.js";
|
|
8
|
+
import { nodeSeed, wireArgs } from "./host-judge.js";
|
|
9
|
+
import { SIGNAL_EXIT } from "./judge-errors.js";
|
|
10
|
+
import { NODE_CASE, NODE_LAUNCHER } from "./node-runner.js";
|
|
11
|
+
import { containerName, dockerEnv, SANDBOX_PIDS, SANDBOX_USER, shareable } from "./sandbox.js";
|
|
12
|
+
import { DIAGNOSTIC_BYTES, OUTPUT_BYTES, REPORTED_FAILURES, stoppedAll } from "./viper.js";
|
|
13
|
+
export const NODE_ENGINE = "node-docker";
|
|
14
|
+
export const NODE_ROOT = "/judge";
|
|
15
|
+
export const NODE_RUNNER = "runner";
|
|
16
|
+
export const NODE_CASE_MS = 5_000;
|
|
17
|
+
const SEARCHABLE = 0o755;
|
|
18
|
+
const LINE_BYTES = 2 * OUTPUT_BYTES;
|
|
19
|
+
export const moduleName = (name) => (name.endsWith(".mjs") ? name : `${name.replace(/\.[^.]*$/, "") || "delivery"}.mjs`);
|
|
20
|
+
export function nodeArgs(box, name, source, directory) {
|
|
21
|
+
return [
|
|
22
|
+
"run",
|
|
23
|
+
"-i",
|
|
24
|
+
"--name",
|
|
25
|
+
name,
|
|
26
|
+
"--network",
|
|
27
|
+
"none",
|
|
28
|
+
"--read-only",
|
|
29
|
+
"--cap-drop",
|
|
30
|
+
"ALL",
|
|
31
|
+
"--security-opt",
|
|
32
|
+
"no-new-privileges",
|
|
33
|
+
"--user",
|
|
34
|
+
SANDBOX_USER,
|
|
35
|
+
"--pids-limit",
|
|
36
|
+
String(SANDBOX_PIDS),
|
|
37
|
+
"--memory",
|
|
38
|
+
box.memory,
|
|
39
|
+
"--memory-swap",
|
|
40
|
+
box.memory,
|
|
41
|
+
"--cpus",
|
|
42
|
+
box.cpus,
|
|
43
|
+
"--ipc",
|
|
44
|
+
"none",
|
|
45
|
+
"--mount",
|
|
46
|
+
"type=tmpfs,target=/dev/mqueue,readonly",
|
|
47
|
+
"--mount",
|
|
48
|
+
`type=bind,source=${source},target=${NODE_ROOT},readonly`,
|
|
49
|
+
"--workdir",
|
|
50
|
+
directory,
|
|
51
|
+
"--entrypoint",
|
|
52
|
+
"node",
|
|
53
|
+
box.image,
|
|
54
|
+
posix.join(NODE_ROOT, NODE_RUNNER, "launch.mjs"),
|
|
55
|
+
posix.join(NODE_ROOT, NODE_RUNNER, "case.mjs"),
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
const same = (a, b) => a === b || (typeof a === "number" && typeof b === "number" && Number.isNaN(a) && Number.isNaN(b));
|
|
59
|
+
function valueOf(kind, value) {
|
|
60
|
+
if (kind === "string" && typeof value === "string")
|
|
61
|
+
return { ok: true, value };
|
|
62
|
+
if (kind === "number" && typeof value === "string")
|
|
63
|
+
return { ok: true, value: Number(value) };
|
|
64
|
+
if (kind === "boolean" && (value === "true" || value === "false"))
|
|
65
|
+
return { ok: true, value: value === "true" };
|
|
66
|
+
if (kind === "null" && value === null)
|
|
67
|
+
return { ok: true, value: null };
|
|
68
|
+
return { ok: false };
|
|
69
|
+
}
|
|
70
|
+
export function caseVerdict(answer, token, expected) {
|
|
71
|
+
if (answer.over)
|
|
72
|
+
return { verdict: "crashed", detail: `the case wrote more than ${OUTPUT_BYTES} bytes` };
|
|
73
|
+
if (answer.timedOut)
|
|
74
|
+
return { verdict: "stopped", detail: `the case gave no answer within ${NODE_CASE_MS} ms` };
|
|
75
|
+
const parts = Buffer.from(answer.out, "base64").toString("utf8").split(token);
|
|
76
|
+
if (parts.length !== 3) {
|
|
77
|
+
return { verdict: "crashed", detail: parts.length < 3 ? "the case wrote no answer framed by its token" : "the case wrote more than one answer framed by its token" };
|
|
78
|
+
}
|
|
79
|
+
let body;
|
|
80
|
+
try {
|
|
81
|
+
body = JSON.parse(parts[1] ?? "");
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return { verdict: "crashed", detail: "the case wrote a framed answer that is not JSON" };
|
|
85
|
+
}
|
|
86
|
+
if (!Array.isArray(body) || body.length !== 3)
|
|
87
|
+
return { verdict: "crashed", detail: "the case wrote a framed answer of the wrong shape" };
|
|
88
|
+
const [verdict, kind, value] = body;
|
|
89
|
+
if (verdict === "not-primitive")
|
|
90
|
+
return { verdict: "not-primitive" };
|
|
91
|
+
if (verdict === "threw" || verdict === "no-module")
|
|
92
|
+
return { verdict, detail: String(value).slice(0, 256) };
|
|
93
|
+
const got = verdict === "answer" ? valueOf(kind, value) : { ok: false };
|
|
94
|
+
if (!got.ok)
|
|
95
|
+
return { verdict: "crashed", detail: "the case wrote a framed answer the judge does not know" };
|
|
96
|
+
return same(got.value, expected) ? { verdict: "pass" } : { verdict: "wrong", detail: got.value };
|
|
97
|
+
}
|
|
98
|
+
function summarized(results, image, path) {
|
|
99
|
+
const failures = results.flatMap((result, index) => (result.verdict === "pass" ? [] : [{ case: index, ...result }]));
|
|
100
|
+
return { engine: NODE_ENGINE, image, path, total: results.length, passed: results.length - failures.length, failures: failures.slice(0, REPORTED_FAILURES) };
|
|
101
|
+
}
|
|
102
|
+
async function stage(source, name) {
|
|
103
|
+
const root = await mkdtemp(join(tmpdir(), "judge-node-"));
|
|
104
|
+
const mount = join(root, "judge");
|
|
105
|
+
const random = randomBytes(16).toString("hex");
|
|
106
|
+
const file = moduleName(name);
|
|
107
|
+
try {
|
|
108
|
+
await mkdir(join(mount, NODE_RUNNER), { recursive: true });
|
|
109
|
+
await mkdir(join(mount, random));
|
|
110
|
+
await writeFile(join(mount, NODE_RUNNER, "launch.mjs"), NODE_LAUNCHER);
|
|
111
|
+
await writeFile(join(mount, NODE_RUNNER, "case.mjs"), NODE_CASE);
|
|
112
|
+
await writeFile(join(mount, random, file), source);
|
|
113
|
+
await chmod(mount, SEARCHABLE);
|
|
114
|
+
await shareable(mount);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
await removeCopy(root);
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
return { root, mount, directory: posix.join(NODE_ROOT, random), path: posix.join(NODE_ROOT, random, file) };
|
|
121
|
+
}
|
|
122
|
+
function converse(args, name, staged, cases, seed, timeoutSeconds) {
|
|
123
|
+
return new Promise((done) => {
|
|
124
|
+
const env = dockerEnv(process.env);
|
|
125
|
+
const child = spawn("docker", args, { env, stdio: ["pipe", "pipe", "pipe"], windowsHide: true });
|
|
126
|
+
const results = [];
|
|
127
|
+
let buffered = "";
|
|
128
|
+
let diagnostic = "";
|
|
129
|
+
let token = "";
|
|
130
|
+
let ended;
|
|
131
|
+
let killing = Promise.resolve();
|
|
132
|
+
const kill = (why) => {
|
|
133
|
+
ended ??= why;
|
|
134
|
+
killing = removeContainer(name, env).then(() => {
|
|
135
|
+
if (child.exitCode === null)
|
|
136
|
+
child.kill("SIGKILL");
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
const handlers = Object.keys(SIGNAL_EXIT).map((signal) => {
|
|
140
|
+
const handler = () => {
|
|
141
|
+
kill({ verdict: "stopped", detail: `${signal} stopped the judge` });
|
|
142
|
+
};
|
|
143
|
+
process.on(signal, handler);
|
|
144
|
+
return [signal, handler];
|
|
145
|
+
});
|
|
146
|
+
const timer = setTimeout(() => kill({ verdict: "stopped", detail: "the judgement's --timeout ran out before this case finished" }), timeoutSeconds * 1000);
|
|
147
|
+
const send = (message) => {
|
|
148
|
+
child.stdin.write(`${JSON.stringify(message)}\n`);
|
|
149
|
+
};
|
|
150
|
+
const next = () => {
|
|
151
|
+
if (results.length === cases.cases.length) {
|
|
152
|
+
child.stdin.end();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
token = randomBytes(32).toString("hex");
|
|
156
|
+
send({ token, ...wireArgs(cases.cases[results.length]?.args ?? []) });
|
|
157
|
+
};
|
|
158
|
+
const answered = (line) => {
|
|
159
|
+
let answer;
|
|
160
|
+
try {
|
|
161
|
+
answer = JSON.parse(line);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
answer = undefined;
|
|
165
|
+
}
|
|
166
|
+
if (token === "" || answer === undefined || answer.token !== token) {
|
|
167
|
+
kill({ verdict: "crashed", detail: "the plain Node engine answered out of turn" });
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
results.push(caseVerdict(answer, token, cases.cases[results.length]?.expected ?? null));
|
|
171
|
+
token = "";
|
|
172
|
+
next();
|
|
173
|
+
};
|
|
174
|
+
child.stdout.setEncoding("utf8");
|
|
175
|
+
child.stdout.on("data", (chunk) => {
|
|
176
|
+
buffered += chunk;
|
|
177
|
+
let at = buffered.indexOf("\n");
|
|
178
|
+
while (at >= 0 && ended === undefined) {
|
|
179
|
+
const line = buffered.slice(0, at);
|
|
180
|
+
buffered = buffered.slice(at + 1);
|
|
181
|
+
answered(line);
|
|
182
|
+
at = buffered.indexOf("\n");
|
|
183
|
+
}
|
|
184
|
+
if (buffered.length > LINE_BYTES)
|
|
185
|
+
kill({ verdict: "crashed", detail: "the plain Node engine wrote an answer too long to read" });
|
|
186
|
+
});
|
|
187
|
+
child.stderr.setEncoding("utf8");
|
|
188
|
+
child.stderr.on("data", (chunk) => {
|
|
189
|
+
if (diagnostic.length < DIAGNOSTIC_BYTES)
|
|
190
|
+
diagnostic += chunk.slice(0, DIAGNOSTIC_BYTES - diagnostic.length);
|
|
191
|
+
});
|
|
192
|
+
child.stdin.on("error", () => undefined);
|
|
193
|
+
const finish = (exitCode) => {
|
|
194
|
+
clearTimeout(timer);
|
|
195
|
+
void killing.finally(() => {
|
|
196
|
+
for (const [signal, handler] of handlers)
|
|
197
|
+
process.removeListener(signal, handler);
|
|
198
|
+
const rest = ended ?? { verdict: "crashed", detail: `the plain Node engine ended with exit code ${exitCode}: ${diagnostic.trim().slice(0, 256)}` };
|
|
199
|
+
while (results.length < cases.cases.length)
|
|
200
|
+
results.push(rest);
|
|
201
|
+
done(results);
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
child.once("error", (error) => {
|
|
205
|
+
diagnostic = error.message;
|
|
206
|
+
finish(null);
|
|
207
|
+
});
|
|
208
|
+
child.once("close", finish);
|
|
209
|
+
send({ seed: nodeSeed(seed), caseMs: NODE_CASE_MS, outputBytes: OUTPUT_BYTES, path: staged.path });
|
|
210
|
+
next();
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
export async function judgeNode(box, source, name, cases, seed, timeoutSeconds) {
|
|
214
|
+
if (timeoutSeconds <= 0) {
|
|
215
|
+
const stopped = stoppedAll(cases.cases.length, "the judgement's --timeout ran out before the plain Node engine started");
|
|
216
|
+
return { judged: { engine: NODE_ENGINE, image: box.image, path: "", ...stopped }, cleanup: undefined };
|
|
217
|
+
}
|
|
218
|
+
const staged = await stage(source, name);
|
|
219
|
+
const container = containerName();
|
|
220
|
+
let results = [];
|
|
221
|
+
let cleanup;
|
|
222
|
+
try {
|
|
223
|
+
results = await converse(nodeArgs(box, container, staged.mount, staged.directory), container, staged, cases, seed, timeoutSeconds);
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
await removeContainer(container, dockerEnv(process.env));
|
|
227
|
+
cleanup = await removeCopy(staged.root);
|
|
228
|
+
}
|
|
229
|
+
return { judged: summarized(results, box.image, staged.path), cleanup };
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=node-judge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-judge.js","sourceRoot":"","sources":["../../src/node-judge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const NODE_LAUNCHER = "\nimport { spawn } from \"node:child_process\";\nimport { createInterface } from \"node:readline\";\nconst caseFile = process.argv[2];\nconst lines = createInterface({ input: process.stdin, crlfDelay: Infinity });\nlet config;\nconst sweep = () => {\n try {\n process.kill(-1, \"SIGKILL\");\n } catch {}\n};\nconst runCase = (token, json, zeros) =>\n new Promise((done) => {\n const child = spawn(process.execPath, [\"--random-seed=\" + config.seed, caseFile], { stdio: [\"pipe\", \"pipe\", \"ignore\"] });\n const out = [];\n let bytes = 0;\n let over = false;\n let timedOut = false;\n let code = null;\n const timer = setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGKILL\");\n }, config.caseMs);\n child.stdout.on(\"data\", (chunk) => {\n bytes += chunk.length;\n if (bytes > config.outputBytes) {\n over = true;\n child.kill(\"SIGKILL\");\n return;\n }\n if (!over) out.push(chunk);\n });\n child.stdin.on(\"error\", () => undefined);\n child.stdin.end(JSON.stringify({ token, json, zeros, path: config.path }));\n child.once(\"exit\", (exitCode) => {\n clearTimeout(timer);\n code = exitCode;\n sweep();\n });\n child.once(\"error\", () => {\n clearTimeout(timer);\n sweep();\n done({ token, out: \"\", code: null, timedOut, over });\n });\n child.once(\"close\", () => {\n done({ token, out: over ? \"\" : Buffer.concat(out).toString(\"base64\"), code, timedOut, over });\n });\n });\nfor await (const line of lines) {\n const message = JSON.parse(line);\n if (config === undefined) {\n config = message;\n continue;\n }\n const result = await runCase(message.token, message.json, message.zeros);\n sweep();\n process.stdout.write(JSON.stringify(result) + \"\\n\");\n}\n";
|
|
2
|
+
export declare const NODE_CASE = "\nimport { readFileSync, writeSync } from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nconst write = writeSync;\nconst from = Buffer.from;\nconst stringify = JSON.stringify;\nconst apply = Reflect.apply;\nconst exit = process.exit.bind(process);\nconst input = JSON.parse(readFileSync(0, \"utf8\"));\nconst token = \"\" + input.token;\nconst args = JSON.parse(\"\" + input.json);\nconst zeros = input.zeros;\nfor (let at = 0; at < zeros.length; at += 1) args[zeros[at]] = -0;\nconst url = pathToFileURL(\"\" + input.path).href;\nconst put = (text) => {\n const bytes = from(text, \"utf8\");\n let at = 0;\n while (at < bytes.length) {\n try {\n at += write(1, bytes, at, bytes.length - at);\n } catch (error) {\n if (error === null || typeof error !== \"object\" || error.code !== \"EAGAIN\") exit(70);\n }\n }\n};\nconst say = (verdict, kind, value) => {\n put(\"\\n\" + token + \"[\" + stringify(verdict) + \",\" + stringify(kind) + \",\" + stringify(value) + \"]\" + token + \"\\n\");\n exit(0);\n};\nconst describe = (error) => {\n try {\n const message = error !== null && typeof error === \"object\" ? error.message : error;\n return typeof message === \"string\" ? message : \"a value that is not an Error\";\n } catch {\n return \"a value that is not an Error\";\n }\n};\nlet fn;\ntry {\n fn = (await import(url)).default;\n} catch (error) {\n say(\"no-module\", \"string\", describe(error));\n}\nif (typeof fn !== \"function\") say(\"no-module\", \"string\", \"the delivery has no default export function\");\nlet got;\nlet threw = false;\nlet reason = \"\";\ntry {\n got = apply(fn, undefined, args);\n} catch (error) {\n threw = true;\n reason = describe(error);\n}\nif (threw) say(\"threw\", \"string\", reason);\nconst kind = got === null ? \"null\" : typeof got;\nif (kind === \"string\") say(\"answer\", kind, got);\nif (kind === \"number\" || kind === \"boolean\") say(\"answer\", kind, \"\" + got);\nif (kind === \"null\") say(\"answer\", kind, null);\nsay(\"not-primitive\", kind, null);\n";
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
export const NODE_LAUNCHER = `
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { createInterface } from "node:readline";
|
|
4
|
+
const caseFile = process.argv[2];
|
|
5
|
+
const lines = createInterface({ input: process.stdin, crlfDelay: Infinity });
|
|
6
|
+
let config;
|
|
7
|
+
const sweep = () => {
|
|
8
|
+
try {
|
|
9
|
+
process.kill(-1, "SIGKILL");
|
|
10
|
+
} catch {}
|
|
11
|
+
};
|
|
12
|
+
const runCase = (token, json, zeros) =>
|
|
13
|
+
new Promise((done) => {
|
|
14
|
+
const child = spawn(process.execPath, ["--random-seed=" + config.seed, caseFile], { stdio: ["pipe", "pipe", "ignore"] });
|
|
15
|
+
const out = [];
|
|
16
|
+
let bytes = 0;
|
|
17
|
+
let over = false;
|
|
18
|
+
let timedOut = false;
|
|
19
|
+
let code = null;
|
|
20
|
+
const timer = setTimeout(() => {
|
|
21
|
+
timedOut = true;
|
|
22
|
+
child.kill("SIGKILL");
|
|
23
|
+
}, config.caseMs);
|
|
24
|
+
child.stdout.on("data", (chunk) => {
|
|
25
|
+
bytes += chunk.length;
|
|
26
|
+
if (bytes > config.outputBytes) {
|
|
27
|
+
over = true;
|
|
28
|
+
child.kill("SIGKILL");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (!over) out.push(chunk);
|
|
32
|
+
});
|
|
33
|
+
child.stdin.on("error", () => undefined);
|
|
34
|
+
child.stdin.end(JSON.stringify({ token, json, zeros, path: config.path }));
|
|
35
|
+
child.once("exit", (exitCode) => {
|
|
36
|
+
clearTimeout(timer);
|
|
37
|
+
code = exitCode;
|
|
38
|
+
sweep();
|
|
39
|
+
});
|
|
40
|
+
child.once("error", () => {
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
sweep();
|
|
43
|
+
done({ token, out: "", code: null, timedOut, over });
|
|
44
|
+
});
|
|
45
|
+
child.once("close", () => {
|
|
46
|
+
done({ token, out: over ? "" : Buffer.concat(out).toString("base64"), code, timedOut, over });
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
for await (const line of lines) {
|
|
50
|
+
const message = JSON.parse(line);
|
|
51
|
+
if (config === undefined) {
|
|
52
|
+
config = message;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const result = await runCase(message.token, message.json, message.zeros);
|
|
56
|
+
sweep();
|
|
57
|
+
process.stdout.write(JSON.stringify(result) + "\\n");
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
60
|
+
export const NODE_CASE = `
|
|
61
|
+
import { readFileSync, writeSync } from "node:fs";
|
|
62
|
+
import { pathToFileURL } from "node:url";
|
|
63
|
+
const write = writeSync;
|
|
64
|
+
const from = Buffer.from;
|
|
65
|
+
const stringify = JSON.stringify;
|
|
66
|
+
const apply = Reflect.apply;
|
|
67
|
+
const exit = process.exit.bind(process);
|
|
68
|
+
const input = JSON.parse(readFileSync(0, "utf8"));
|
|
69
|
+
const token = "" + input.token;
|
|
70
|
+
const args = JSON.parse("" + input.json);
|
|
71
|
+
const zeros = input.zeros;
|
|
72
|
+
for (let at = 0; at < zeros.length; at += 1) args[zeros[at]] = -0;
|
|
73
|
+
const url = pathToFileURL("" + input.path).href;
|
|
74
|
+
const put = (text) => {
|
|
75
|
+
const bytes = from(text, "utf8");
|
|
76
|
+
let at = 0;
|
|
77
|
+
while (at < bytes.length) {
|
|
78
|
+
try {
|
|
79
|
+
at += write(1, bytes, at, bytes.length - at);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (error === null || typeof error !== "object" || error.code !== "EAGAIN") exit(70);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const say = (verdict, kind, value) => {
|
|
86
|
+
put("\\n" + token + "[" + stringify(verdict) + "," + stringify(kind) + "," + stringify(value) + "]" + token + "\\n");
|
|
87
|
+
exit(0);
|
|
88
|
+
};
|
|
89
|
+
const describe = (error) => {
|
|
90
|
+
try {
|
|
91
|
+
const message = error !== null && typeof error === "object" ? error.message : error;
|
|
92
|
+
return typeof message === "string" ? message : "a value that is not an Error";
|
|
93
|
+
} catch {
|
|
94
|
+
return "a value that is not an Error";
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
let fn;
|
|
98
|
+
try {
|
|
99
|
+
fn = (await import(url)).default;
|
|
100
|
+
} catch (error) {
|
|
101
|
+
say("no-module", "string", describe(error));
|
|
102
|
+
}
|
|
103
|
+
if (typeof fn !== "function") say("no-module", "string", "the delivery has no default export function");
|
|
104
|
+
let got;
|
|
105
|
+
let threw = false;
|
|
106
|
+
let reason = "";
|
|
107
|
+
try {
|
|
108
|
+
got = apply(fn, undefined, args);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
threw = true;
|
|
111
|
+
reason = describe(error);
|
|
112
|
+
}
|
|
113
|
+
if (threw) say("threw", "string", reason);
|
|
114
|
+
const kind = got === null ? "null" : typeof got;
|
|
115
|
+
if (kind === "string") say("answer", kind, got);
|
|
116
|
+
if (kind === "number" || kind === "boolean") say("answer", kind, "" + got);
|
|
117
|
+
if (kind === "null") say("answer", kind, null);
|
|
118
|
+
say("not-primitive", kind, null);
|
|
119
|
+
`;
|
|
120
|
+
//# sourceMappingURL=node-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-runner.js","sourceRoot":"","sources":["../../src/node-runner.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0D5B,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2DxB,CAAC"}
|
package/dist/src/sandbox.d.ts
CHANGED
|
@@ -9,16 +9,19 @@ export declare const SANDBOX_ROOT = "/judge";
|
|
|
9
9
|
export declare const SANDBOX_HOME = "/tmp";
|
|
10
10
|
export declare const SANDBOX_KINDS: readonly ["docker", "viper", "none"];
|
|
11
11
|
export type SandboxKind = (typeof SANDBOX_KINDS)[number];
|
|
12
|
+
export type Box = {
|
|
13
|
+
image: string;
|
|
14
|
+
memory: string;
|
|
15
|
+
cpus: string;
|
|
16
|
+
};
|
|
12
17
|
export type Sandbox = {
|
|
13
18
|
kind: "none";
|
|
14
19
|
} | {
|
|
15
20
|
kind: "viper";
|
|
16
|
-
|
|
21
|
+
node?: Box;
|
|
22
|
+
} | ({
|
|
17
23
|
kind: "docker";
|
|
18
|
-
|
|
19
|
-
memory: string;
|
|
20
|
-
cpus: string;
|
|
21
|
-
};
|
|
24
|
+
} & Box);
|
|
22
25
|
export declare const SANDBOX_NEEDED = "--sandbox must be docker, viper or none";
|
|
23
26
|
export declare const VIPER_TAKES_NO_RUN = "--sandbox viper judges the cases in the spec's judge-cases block, so it takes no --run and no --check";
|
|
24
27
|
export declare const IMAGE_NEEDS_DIGEST = "--sandbox-image must name an image by its digest, as <name>@sha256:<64 hex>; a reference without a digest is refused";
|
|
@@ -26,11 +29,13 @@ export declare const MEMORY_FORMAT = "--sandbox-memory must be a whole number of
|
|
|
26
29
|
export declare const CPUS_FORMAT = "--sandbox-cpus must be a number of CPUs above 0, such as 1 or 1.5";
|
|
27
30
|
export declare const DOCKER_ENV: readonly ["DOCKER_HOST", "DOCKER_CONTEXT", "DOCKER_CONFIG", "DOCKER_CERT_PATH", "DOCKER_TLS_VERIFY", "XDG_RUNTIME_DIR"];
|
|
28
31
|
export declare const sandboxOnly: (option: string) => string;
|
|
32
|
+
export declare const PLAIN_NODE_ONLY = "--plain-node applies only with --sandbox viper";
|
|
29
33
|
export declare function sandboxOf(values: Values): Sandbox;
|
|
30
34
|
export declare function dockerEnv(base: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
31
35
|
export declare const dockerMissing: (reason: string) => string;
|
|
32
36
|
export declare const imageMissing: (image: string, reason: string) => string;
|
|
33
37
|
export declare const NO_SANDBOX = "warning: --sandbox none ran the check with your own rights: it could read your files and keys and use your network";
|
|
38
|
+
export declare const boxIn: (sandbox: Sandbox) => Box | undefined;
|
|
34
39
|
export declare function sandboxReady(sandbox: Sandbox, env: NodeJS.ProcessEnv): Promise<void>;
|
|
35
40
|
export declare const containerName: () => string;
|
|
36
41
|
export type Mounted = {
|
package/dist/src/sandbox.js
CHANGED
|
@@ -25,12 +25,37 @@ const CPUS = /^\d{1,3}(\.\d{1,2})?$/;
|
|
|
25
25
|
const SANDBOX_ONLY = ["sandbox-image", "sandbox-memory", "sandbox-cpus"];
|
|
26
26
|
const READABLE = 0o444;
|
|
27
27
|
const SEARCHABLE = 0o755;
|
|
28
|
-
export const sandboxOnly = (option) => `--${option} applies only with --sandbox docker`;
|
|
28
|
+
export const sandboxOnly = (option) => `--${option} applies only with --sandbox docker, or with --sandbox viper and --plain-node`;
|
|
29
|
+
export const PLAIN_NODE_ONLY = "--plain-node applies only with --sandbox viper";
|
|
30
|
+
function boxOf(values) {
|
|
31
|
+
const image = values["sandbox-image"] ?? SANDBOX_IMAGE;
|
|
32
|
+
if (!DIGESTED.test(image)) {
|
|
33
|
+
throw new UsageError(IMAGE_NEEDS_DIGEST);
|
|
34
|
+
}
|
|
35
|
+
const memory = values["sandbox-memory"] ?? SANDBOX_MEMORY;
|
|
36
|
+
if (!MEMORY.test(memory)) {
|
|
37
|
+
throw new UsageError(MEMORY_FORMAT);
|
|
38
|
+
}
|
|
39
|
+
const cpus = values["sandbox-cpus"] ?? SANDBOX_CPUS;
|
|
40
|
+
if (!CPUS.test(cpus) || Number(cpus) <= 0) {
|
|
41
|
+
throw new UsageError(CPUS_FORMAT);
|
|
42
|
+
}
|
|
43
|
+
return { image, memory, cpus };
|
|
44
|
+
}
|
|
29
45
|
export function sandboxOf(values) {
|
|
30
46
|
const kind = values.sandbox ?? "docker";
|
|
31
47
|
if (!SANDBOX_KINDS.includes(kind)) {
|
|
32
48
|
throw new UsageError(SANDBOX_NEEDED);
|
|
33
49
|
}
|
|
50
|
+
if (values["plain-node"] === true && kind !== "viper") {
|
|
51
|
+
throw new UsageError(PLAIN_NODE_ONLY);
|
|
52
|
+
}
|
|
53
|
+
if (kind === "viper" && values["plain-node"] === true) {
|
|
54
|
+
if (values.run !== undefined || values.check !== undefined) {
|
|
55
|
+
throw new UsageError(VIPER_TAKES_NO_RUN);
|
|
56
|
+
}
|
|
57
|
+
return { kind, node: boxOf(values) };
|
|
58
|
+
}
|
|
34
59
|
if (kind === "none" || kind === "viper") {
|
|
35
60
|
const given = SANDBOX_ONLY.find((option) => values[option] !== undefined);
|
|
36
61
|
if (given !== undefined) {
|
|
@@ -41,19 +66,7 @@ export function sandboxOf(values) {
|
|
|
41
66
|
}
|
|
42
67
|
return { kind };
|
|
43
68
|
}
|
|
44
|
-
|
|
45
|
-
if (!DIGESTED.test(image)) {
|
|
46
|
-
throw new UsageError(IMAGE_NEEDS_DIGEST);
|
|
47
|
-
}
|
|
48
|
-
const memory = values["sandbox-memory"] ?? SANDBOX_MEMORY;
|
|
49
|
-
if (!MEMORY.test(memory)) {
|
|
50
|
-
throw new UsageError(MEMORY_FORMAT);
|
|
51
|
-
}
|
|
52
|
-
const cpus = values["sandbox-cpus"] ?? SANDBOX_CPUS;
|
|
53
|
-
if (!CPUS.test(cpus) || Number(cpus) <= 0) {
|
|
54
|
-
throw new UsageError(CPUS_FORMAT);
|
|
55
|
-
}
|
|
56
|
-
return { kind: "docker", image, memory, cpus };
|
|
69
|
+
return { kind: "docker", ...boxOf(values) };
|
|
57
70
|
}
|
|
58
71
|
export function dockerEnv(base) {
|
|
59
72
|
const env = {};
|
|
@@ -69,20 +82,22 @@ const DOCKER_INSTALL = ["https:", "", "docs.docker.com", "engine", "install", ""
|
|
|
69
82
|
export const dockerMissing = (reason) => `docker is not available (${reason || "no answer"}), so the check cannot run in its sandbox and nothing was run or paid; install Docker from ${DOCKER_INSTALL} and start it, or pass --sandbox none to run the check with your own rights, files, keys and network`;
|
|
70
83
|
export const imageMissing = (image, reason) => `docker could not pull ${image} (${reason || "no answer"}); nothing was run or paid`;
|
|
71
84
|
export const NO_SANDBOX = "warning: --sandbox none ran the check with your own rights: it could read your files and keys and use your network";
|
|
85
|
+
export const boxIn = (sandbox) => (sandbox.kind === "docker" ? sandbox : sandbox.kind === "viper" ? sandbox.node : undefined);
|
|
72
86
|
export async function sandboxReady(sandbox, env) {
|
|
73
|
-
|
|
87
|
+
const box = boxIn(sandbox);
|
|
88
|
+
if (box === undefined) {
|
|
74
89
|
return;
|
|
75
90
|
}
|
|
76
91
|
const server = await docker(["version", "--format", "{{.Server.Version}}"], env);
|
|
77
92
|
if (server.status !== 0) {
|
|
78
93
|
throw new JudgeRefused(dockerMissing(server.out));
|
|
79
94
|
}
|
|
80
|
-
if ((await docker(["image", "inspect", "--format", "{{.Id}}",
|
|
95
|
+
if ((await docker(["image", "inspect", "--format", "{{.Id}}", box.image], env)).status === 0) {
|
|
81
96
|
return;
|
|
82
97
|
}
|
|
83
|
-
const pulled = await docker(["pull",
|
|
98
|
+
const pulled = await docker(["pull", box.image], env, true);
|
|
84
99
|
if (pulled.status !== 0) {
|
|
85
|
-
throw new JudgeRefused(imageMissing(
|
|
100
|
+
throw new JudgeRefused(imageMissing(box.image, pulled.out));
|
|
86
101
|
}
|
|
87
102
|
}
|
|
88
103
|
export const containerName = () => `judge-${randomBytes(8).toString("hex")}`;
|
package/dist/src/sandbox.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC9G,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,CAAC,MAAM,aAAa,GAAG,+FAA+F,CAAC;AAC7H,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AACnC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AAChC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AAChC,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAClC,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;AAC1C,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC;AAEnC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/sandbox.ts"],"names":[],"mappings":"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"}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.31";
|
package/dist/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "0.1.
|
|
1
|
+
export const VERSION = "0.1.31";
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/dist/src/viper.d.ts
CHANGED
|
@@ -51,6 +51,12 @@ export declare function casesOf(spec: Uint8Array): Cases;
|
|
|
51
51
|
export declare const runOf: (cases: Cases) => Run;
|
|
52
52
|
export declare function encodeInput(source: string, cases: Cases, run: Run): Buffer;
|
|
53
53
|
export declare function decodeOutput(bytes: Buffer, expected: number): CaseResult[];
|
|
54
|
+
export declare function stoppedAll(total: number, detail: string): {
|
|
55
|
+
total: number;
|
|
56
|
+
passed: number;
|
|
57
|
+
failures: Failure[];
|
|
58
|
+
};
|
|
59
|
+
export declare const deadlineMissed: (engine: string, timeoutSeconds: number) => string;
|
|
54
60
|
export declare function summarize(results: CaseResult[], run: Run): Judged;
|
|
55
61
|
export declare function wasmPath(): string;
|
|
56
62
|
export declare function pinnedWasm(path?: string): Promise<Buffer>;
|
|
@@ -63,4 +69,4 @@ export type Ran = {
|
|
|
63
69
|
diagnostic: string;
|
|
64
70
|
};
|
|
65
71
|
export declare function runViper(wasm: Buffer, input: Buffer, timeoutSeconds: number): Promise<Ran>;
|
|
66
|
-
export declare function judgeViper(wasm: Buffer, source: Uint8Array, cases: Cases, timeoutSeconds: number): Promise<Judged>;
|
|
72
|
+
export declare function judgeViper(wasm: Buffer, source: Uint8Array, cases: Cases, timeoutSeconds: number, run?: Run): Promise<Judged>;
|
package/dist/src/viper.js
CHANGED
|
@@ -185,6 +185,11 @@ export function decodeOutput(bytes, expected) {
|
|
|
185
185
|
}
|
|
186
186
|
return results;
|
|
187
187
|
}
|
|
188
|
+
export function stoppedAll(total, detail) {
|
|
189
|
+
const failures = Array.from({ length: Math.min(total, REPORTED_FAILURES) }, (_, index) => (index === 0 ? { case: index, verdict: "stopped", detail } : { case: index, verdict: "stopped" }));
|
|
190
|
+
return { total, passed: 0, failures };
|
|
191
|
+
}
|
|
192
|
+
export const deadlineMissed = (engine, timeoutSeconds) => `${engine} did not finish within the ${Math.round(timeoutSeconds * 1000)} ms left of the judgement's --timeout`;
|
|
188
193
|
export function summarize(results, run) {
|
|
189
194
|
const failures = results.flatMap((result, index) => (result.verdict === "pass" ? [] : [{ case: index, ...result }]));
|
|
190
195
|
return { total: results.length, passed: results.length - failures.length, failures: failures.slice(0, REPORTED_FAILURES), ...run };
|
|
@@ -261,7 +266,7 @@ export function runViper(wasm, input, timeoutSeconds) {
|
|
|
261
266
|
});
|
|
262
267
|
});
|
|
263
268
|
}
|
|
264
|
-
export async function judgeViper(wasm, source, cases, timeoutSeconds) {
|
|
269
|
+
export async function judgeViper(wasm, source, cases, timeoutSeconds, run = runOf(cases)) {
|
|
265
270
|
let text;
|
|
266
271
|
try {
|
|
267
272
|
text = new TextDecoder("utf-8", { fatal: true }).decode(source);
|
|
@@ -269,10 +274,12 @@ export async function judgeViper(wasm, source, cases, timeoutSeconds) {
|
|
|
269
274
|
catch {
|
|
270
275
|
throw new JudgeRefused("--artifact is not UTF-8 text, so it is not a module the viper judge can run; nothing was paid");
|
|
271
276
|
}
|
|
272
|
-
|
|
277
|
+
if (timeoutSeconds <= 0) {
|
|
278
|
+
return { ...stoppedAll(cases.cases.length, deadlineMissed("the viper judge", timeoutSeconds)), ...run };
|
|
279
|
+
}
|
|
273
280
|
const ran = await runViper(wasm, encodeInput(text, cases, run), timeoutSeconds);
|
|
274
281
|
if (ran.timedOut) {
|
|
275
|
-
return {
|
|
282
|
+
return { ...stoppedAll(cases.cases.length, deadlineMissed("the viper judge", timeoutSeconds)), ...run };
|
|
276
283
|
}
|
|
277
284
|
if (ran.exitCode !== 0) {
|
|
278
285
|
return { total: cases.cases.length, passed: 0, failures: [{ case: 0, verdict: "crashed", detail: `the judge process ended with exit code ${ran.exitCode}: ${ran.diagnostic.trim().slice(0, 256)}` }], ...run };
|