@whiteroom-ai/cli 1.1.0 → 2.0.1
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/README.md +79 -0
- package/contract/catalog.json +264 -0
- package/dist/index.js +19 -15
- package/dist/index.js.map +1 -1
- package/dist/legacy-args.d.ts +4 -0
- package/dist/legacy-args.js +17 -0
- package/dist/legacy-args.js.map +1 -0
- package/dist/practice/adapter.d.ts +59 -0
- package/dist/practice/adapter.js +169 -0
- package/dist/practice/adapter.js.map +1 -0
- package/dist/practice/catalog.d.ts +27 -0
- package/dist/practice/catalog.js +6 -0
- package/dist/practice/catalog.js.map +1 -0
- package/dist/practice/engine.d.ts +52 -0
- package/dist/practice/engine.js +151 -0
- package/dist/practice/engine.js.map +1 -0
- package/dist/practice/index.d.ts +2 -0
- package/dist/practice/index.js +79 -0
- package/dist/practice/index.js.map +1 -0
- package/dist/practice/preflight.d.ts +64 -0
- package/dist/practice/preflight.js +204 -0
- package/dist/practice/preflight.js.map +1 -0
- package/dist/practice/run.d.ts +13 -0
- package/dist/practice/run.js +380 -0
- package/dist/practice/run.js.map +1 -0
- package/dist/practice/text.d.ts +107 -0
- package/dist/practice/text.js +185 -0
- package/dist/practice/text.js.map +1 -0
- package/dist/sandbox/index.d.ts +2 -0
- package/dist/sandbox/index.js +62 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/listen.d.ts +57 -0
- package/dist/sandbox/listen.js +299 -0
- package/dist/sandbox/listen.js.map +1 -0
- package/package.json +10 -3
- package/starters/wr-adapter.mjs +104 -0
- package/starters/wr_adapter.py +136 -0
- package/src/index.ts +0 -144
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export declare const DASHBOARD = "https://app.whiteroom.tech/sandbox";
|
|
2
|
+
/** Remembers a secret (provider key, run code, session) so `clean` never prints it. */
|
|
3
|
+
export declare function hideSecret(s: string): void;
|
|
4
|
+
/** Text safe to print: no terminal control characters, no known secret. */
|
|
5
|
+
export declare function clean(s: string): string;
|
|
6
|
+
export declare const say: (s: string) => boolean;
|
|
7
|
+
export declare const warn: (s: string) => boolean;
|
|
8
|
+
export declare const plural: (n: number, one: string, many?: string) => string;
|
|
9
|
+
/** A way the command ends: the exit code (§8) and what to print. */
|
|
10
|
+
export interface Ending {
|
|
11
|
+
code: 0 | 1 | 2 | 3;
|
|
12
|
+
lines: string[];
|
|
13
|
+
/** The test's result (printed on stdout), not a refusal. */
|
|
14
|
+
result?: true;
|
|
15
|
+
/** The run finished, but the reply didn't carry its result: ask tasks/next for it. */
|
|
16
|
+
replay?: true;
|
|
17
|
+
}
|
|
18
|
+
export declare const ending: (code: Ending["code"], ...lines: string[]) => Ending;
|
|
19
|
+
export declare const copy: {
|
|
20
|
+
ignoringUrl: string;
|
|
21
|
+
keyInUse: (v: string, key: string) => string;
|
|
22
|
+
host: (host: string) => string;
|
|
23
|
+
/** `tasks`: the practice tasks over all runs; `controls`: whether a control check makes calls. */
|
|
24
|
+
started: (tasks: number, runs: number, controls: boolean) => string;
|
|
25
|
+
restart: string;
|
|
26
|
+
lostTask: string;
|
|
27
|
+
offline: string;
|
|
28
|
+
deadline: string;
|
|
29
|
+
pressAgain: string;
|
|
30
|
+
badCode: string;
|
|
31
|
+
needCode: string;
|
|
32
|
+
needKey: string;
|
|
33
|
+
bothKeys: (vars: string[]) => string;
|
|
34
|
+
noKey: (keyEnv?: string) => string;
|
|
35
|
+
badKeyEnv: (v: string) => string;
|
|
36
|
+
shortTermKey: string;
|
|
37
|
+
keyTwice: (from: string | null, length: number) => string;
|
|
38
|
+
keySpaces: (from: string | null) => string;
|
|
39
|
+
node: (v: string) => string;
|
|
40
|
+
windows: string;
|
|
41
|
+
badUrl: string;
|
|
42
|
+
adapterMissing: (cmd: string, why: string) => string;
|
|
43
|
+
keyMismatch: (v: string, left: number, fleet?: string | null) => string;
|
|
44
|
+
/** §17: a run on a Fleet key provider key names that key as Fleet key does; a new test is the way to pick another. */
|
|
45
|
+
providerKeyMismatch: (from: string | null, key: string, provider: string, hint: string | null) => string;
|
|
46
|
+
lastTry: string;
|
|
47
|
+
codeInvalid: string;
|
|
48
|
+
busy: string;
|
|
49
|
+
unavailable: string;
|
|
50
|
+
unreachable: string;
|
|
51
|
+
cliOutdated: string;
|
|
52
|
+
redirected: string;
|
|
53
|
+
refused: string;
|
|
54
|
+
otherHost: string;
|
|
55
|
+
engineUpdate: (kept: number) => string;
|
|
56
|
+
endedByOwner: string;
|
|
57
|
+
endedBeforeStart: string;
|
|
58
|
+
expired: string;
|
|
59
|
+
callCap: string;
|
|
60
|
+
noModelCalls: string;
|
|
61
|
+
engineError: string;
|
|
62
|
+
finished: (verdict: unknown) => string;
|
|
63
|
+
sessionGone: string;
|
|
64
|
+
cancelled: string;
|
|
65
|
+
adapterCrashed: (code: string, tail: string[]) => string[];
|
|
66
|
+
adapterBroke: (why: string) => string;
|
|
67
|
+
keptResults: string;
|
|
68
|
+
keptUnconfirmed: string;
|
|
69
|
+
tooManyTools: string;
|
|
70
|
+
badTool: string;
|
|
71
|
+
noTerminal: string;
|
|
72
|
+
stoppedEarly: string;
|
|
73
|
+
};
|
|
74
|
+
export interface Check {
|
|
75
|
+
id: string;
|
|
76
|
+
label: string;
|
|
77
|
+
scenario?: string;
|
|
78
|
+
status: "passed" | "failed" | "not_tested" | "unsupported" | "error";
|
|
79
|
+
required: boolean;
|
|
80
|
+
testProblem?: boolean;
|
|
81
|
+
summary?: string | null;
|
|
82
|
+
fix?: string | null;
|
|
83
|
+
mode?: string | null;
|
|
84
|
+
/** Control checks: whether the rule is set up for the agent under test ("off": Off in Controls; "not_set_up": it doesn't cover the agent). */
|
|
85
|
+
setup?: "ok" | "not_set_up" | "off";
|
|
86
|
+
notCoveredAgent?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface Report {
|
|
89
|
+
verdict: "passed" | "not_passed" | "incomplete";
|
|
90
|
+
runs: number;
|
|
91
|
+
sample: boolean;
|
|
92
|
+
scope: string[] | null;
|
|
93
|
+
checks: Check[];
|
|
94
|
+
}
|
|
95
|
+
/** --require's comma list as row ids, or the usage problem (an unknown id, or none). */
|
|
96
|
+
export declare function parseRequire(value: string): string[] | {
|
|
97
|
+
problem: string;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Why a required row doesn't count as passed, or null when it does: Passed
|
|
101
|
+
* in Enforce. A row passes when every check of a rule set up for the agent
|
|
102
|
+
* passed and none failed; a guardrail must also be in Enforce on every rule
|
|
103
|
+
* that counted (Watch, Not checked and Not set up all fail, D6).
|
|
104
|
+
*/
|
|
105
|
+
export declare function requiredRowProblem(r: Report, rowId: string): string | null;
|
|
106
|
+
/** The results screen in the terminal, and its exit code: 0 Passed, 1 Didn't pass, 3 Didn't finish. With --require, a required row not Passed in Enforce turns a pass into 1. */
|
|
107
|
+
export declare function results(r: Report, require?: readonly string[]): Ending;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// What the practice commands print (spec §8, §10, Appendix D). Plain words
|
|
2
|
+
// only: no internal names, no engine reason codes. Every way a run ends
|
|
3
|
+
// names the dashboard and the button to click there. Task, status, provider
|
|
4
|
+
// and refusal words are the engine's catalog's.
|
|
5
|
+
import { CATALOG } from "./catalog.js";
|
|
6
|
+
export const DASHBOARD = "https://app.whiteroom.tech/sandbox";
|
|
7
|
+
const KEY_VARS = Object.values(CATALOG.providers).map((p) => p.keyVar);
|
|
8
|
+
/** Control, C1 and bidi characters, which could rewrite what the terminal shows. Tabs and newlines stay. */
|
|
9
|
+
const UNSAFE = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/g;
|
|
10
|
+
const secrets = new Set();
|
|
11
|
+
/** Remembers a secret (provider key, run code, session) so `clean` never prints it. */
|
|
12
|
+
export function hideSecret(s) {
|
|
13
|
+
if (s.length >= 8)
|
|
14
|
+
secrets.add(s);
|
|
15
|
+
}
|
|
16
|
+
/** Text safe to print: no terminal control characters, no known secret. */
|
|
17
|
+
export function clean(s) {
|
|
18
|
+
let out = s.replace(UNSAFE, "");
|
|
19
|
+
for (const x of secrets)
|
|
20
|
+
out = out.split(x).join("[hidden]");
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
export const say = (s) => process.stdout.write(clean(s) + "\n");
|
|
24
|
+
export const warn = (s) => process.stderr.write(clean(s) + "\n");
|
|
25
|
+
export const plural = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
26
|
+
/** "A, B and C". */
|
|
27
|
+
const list = (xs, and = "and") => (xs.length > 1 ? `${xs.slice(0, -1).join(", ")} ${and} ${xs[xs.length - 1]}` : xs.join(""));
|
|
28
|
+
const button = (name) => `In the dashboard (${DASHBOARD}), click ${name}`;
|
|
29
|
+
export const ending = (code, ...lines) => ({ code, lines });
|
|
30
|
+
export const copy = {
|
|
31
|
+
ignoringUrl: "Ignoring WHITEROOM_URL: practice tests always run on WhiteRoom.",
|
|
32
|
+
keyInUse: (v, key) => `Using the key in ${v} (ends ${key.slice(-4)}).`,
|
|
33
|
+
host: (host) => `Sending your key to ${host} to start the practice test.`,
|
|
34
|
+
/** `tasks`: the practice tasks over all runs; `controls`: whether a control check makes calls. */
|
|
35
|
+
started: (tasks, runs, controls) => {
|
|
36
|
+
const perRun = Math.round(tasks / runs);
|
|
37
|
+
const run = [perRun > 0 && plural(perRun, "practice task"), controls && "a check of your controls"].filter(Boolean).join(" and ");
|
|
38
|
+
return `Practice test started: ${runs > 1 ? `${runs} runs, each ${run}` : run}. Keep this terminal open and your computer awake.`;
|
|
39
|
+
},
|
|
40
|
+
restart: "WhiteRoom restarted this practice task, so it starts again. This doesn't count against your agent.",
|
|
41
|
+
lostTask: "Lost contact with WhiteRoom during this practice task, so it starts again. This doesn't count against your agent.",
|
|
42
|
+
offline: "Lost connection to WhiteRoom. Trying again for up to 5 minutes.",
|
|
43
|
+
deadline: "Your agent didn't finish this practice task in time, so it was stopped.",
|
|
44
|
+
pressAgain: "Press Ctrl+C again to end the practice test. Finished practice tasks are kept.",
|
|
45
|
+
badCode: "That isn't a run code. Copy it again from the dashboard (it starts with wrrt_).",
|
|
46
|
+
needCode: "Paste the run code from the dashboard (it won't show): ",
|
|
47
|
+
needKey: "Paste the model provider key your agent uses (it won't show): ",
|
|
48
|
+
bothKeys: (vars) => `${vars.length === 2 ? `Both ${vars[0]} and ${vars[1]} are` : `${list(vars)} are all`} set. Add --key-env with the one your agent uses (for example --key-env ${vars[0]}), then run the command again. Nothing was sent.`,
|
|
49
|
+
noKey: (keyEnv) => `Set the key your agent uses (${keyEnv ?? list(KEY_VARS, "or")}), then run the command again.`,
|
|
50
|
+
badKeyEnv: (v) => `--key-env must name a provider key variable (${list(KEY_VARS, "or")}), not ${v}.`,
|
|
51
|
+
shortTermKey: CATALOG.keyRefusals.short_term_key,
|
|
52
|
+
keyTwice: (from, length) => `${from ? `The key in ${from}` : "The key"} looks pasted twice (${length} characters, the same key two times). Nothing was sent. Set it again with a single paste.`,
|
|
53
|
+
keySpaces: (from) => `${from ? `The key in ${from}` : "The key"} has spaces or line breaks inside it. Nothing was sent. Copy it again in one piece.`,
|
|
54
|
+
node: (v) => `Needs Node 20 or later (you have ${v}).`,
|
|
55
|
+
windows: "Practice tests run on macOS and Linux for now. Run the command there, or in WSL.",
|
|
56
|
+
badUrl: "--url must be a WhiteRoom address (https://….whiteroom.tech) or http://localhost for local testing.",
|
|
57
|
+
adapterMissing: (cmd, why) => `Couldn't start the adapter \`${cmd}\`: ${why}. Nothing was sent or charged, and your run code still works.`,
|
|
58
|
+
keyMismatch: (v, left, fleet = null) => `This key isn't the one your agent uses with ${fleet ?? "this fleet"}. Nothing was charged, and your run code still works (${plural(left, "more try", "more tries")}). Set ${v} to the right key, then run the same command again.`,
|
|
59
|
+
/** §17: a run on a Fleet key provider key names that key as Fleet key does; a new test is the way to pick another. */
|
|
60
|
+
providerKeyMismatch: (from, key, provider, hint) => `${from ? `The key in ${from}` : "The key you pasted"} (ends ${key.slice(-4)}) isn't the ${provider} key saved on Fleet key${hint ? ` (key ending ${hint})` : ""}. Nothing was charged. If you've changed keys, add the new one on Fleet key, then start a new test in the dashboard and pick that key.`,
|
|
61
|
+
lastTry: `That was the last try, so this run code no longer works. Nothing was charged. ${button("Get a new run code")}, then set the right key and run the command again.`,
|
|
62
|
+
codeInvalid: `This run code doesn't work any more: it expired or was already used. ${button("Get a new run code")}, then run the command again.`,
|
|
63
|
+
busy: "Practice tests are busy right now. Try again in a few minutes. Your run code still works.",
|
|
64
|
+
unavailable: "Practice tests aren't available yet. Try again later.",
|
|
65
|
+
unreachable: "Couldn't reach WhiteRoom. Check your connection, then run the command again.",
|
|
66
|
+
cliOutdated: "WhiteRoom sent something this CLI doesn't understand. Update the CLI, then run the test again.",
|
|
67
|
+
redirected: "WhiteRoom's server tried to send the CLI to another address, so it stopped there. Nothing was sent anywhere else. Try again in a few minutes.",
|
|
68
|
+
refused: `WhiteRoom refused the CLI's request. ${button("Start test")} to run it again.`,
|
|
69
|
+
otherHost: "WhiteRoom sent an address on another host, so the CLI stopped before sending your key there.",
|
|
70
|
+
engineUpdate: (kept) => `WhiteRoom was updated during your practice test, so it stopped. ${kept ? `${plural(kept, "finished practice task")} kept. ` : ""}${button("Start test")} to run it again.`,
|
|
71
|
+
endedByOwner: `The practice test was ended from the dashboard. Finished practice tasks were kept. ${button("Start test")} to test again.`,
|
|
72
|
+
endedBeforeStart: `The practice test was ended from the dashboard before it started. ${button("Start test")} to test again.`,
|
|
73
|
+
expired: `This practice test has ended: it lost contact with this computer or ran out of time. ${button("Start test")} to run it again.`,
|
|
74
|
+
callCap: `Stopped at this test's model-call limit after WhiteRoom had to rerun a task (not your agent). ${button("Start test")} to run it again.`,
|
|
75
|
+
noModelCalls: `Stopped: your agent didn't make any model calls through WhiteRoom in 2 practice tasks in a row. Check your adapter sends its calls to the base_url the CLI gives it. ${button("Start test")} to run it again.`,
|
|
76
|
+
engineError: `WhiteRoom couldn't finish working out the result (not your agent). ${button("Start test")} to run a new test.`,
|
|
77
|
+
finished: (verdict) => {
|
|
78
|
+
const label = typeof verdict === "string" && Object.hasOwn(CATALOG.verdictLabels, verdict) ? `: ${CATALOG.verdictLabels[verdict]}` : "";
|
|
79
|
+
return `The practice test finished${label}. See the results in the dashboard (${DASHBOARD}), under Past tests.`;
|
|
80
|
+
},
|
|
81
|
+
sessionGone: `WhiteRoom no longer knows this practice test. ${button("Start test")} to run it again.`,
|
|
82
|
+
cancelled: `Practice test ended. Finished practice tasks were kept. ${button("Start test")} to run it again.`,
|
|
83
|
+
adapterCrashed: (code, tail) => [
|
|
84
|
+
`Your adapter stopped before it finished the practice task (${code}).`,
|
|
85
|
+
...(tail.length ? ["Its last lines:", ...tail.map((l) => ` ${l}`)] : []),
|
|
86
|
+
"Run the adapter on its own to see why.",
|
|
87
|
+
],
|
|
88
|
+
adapterBroke: (why) => `Your adapter ${why}, so it was stopped.`,
|
|
89
|
+
keptResults: `The test ended early. The practice tasks your agent finished are in the results: see the dashboard (${DASHBOARD}), under Past tests.`,
|
|
90
|
+
keptUnconfirmed: `The test ended early. WhiteRoom didn't confirm it kept the results: check Past tests in the dashboard (${DASHBOARD}).`,
|
|
91
|
+
tooManyTools: "made more test-tool calls than a practice task allows",
|
|
92
|
+
badTool: "sent a tool call WhiteRoom couldn't accept",
|
|
93
|
+
noTerminal: "There's no terminal to paste the run code into. Pipe it in with --code-stdin instead.",
|
|
94
|
+
stoppedEarly: "Stopped before the practice test started.",
|
|
95
|
+
};
|
|
96
|
+
const STATUS = CATALOG.statusLabels;
|
|
97
|
+
// ── --require (pre-flight D6): rows CI insists on ────────────────────────
|
|
98
|
+
const ROW_IDS = CATALOG.rows.map((x) => x.id);
|
|
99
|
+
/** --require's comma list as row ids, or the usage problem (an unknown id, or none). */
|
|
100
|
+
export function parseRequire(value) {
|
|
101
|
+
const ids = [...new Set(value.split(",").map((s) => s.trim()).filter(Boolean))];
|
|
102
|
+
const unknown = ids.filter((id) => !ROW_IDS.includes(id));
|
|
103
|
+
if (!ids.length || unknown.length) {
|
|
104
|
+
return { problem: `${unknown.length ? `Unknown check for --require: ${unknown.join(", ")}.` : "--require needs at least one check."} Use any of: ${ROW_IDS.join(", ")}.` };
|
|
105
|
+
}
|
|
106
|
+
return ids;
|
|
107
|
+
}
|
|
108
|
+
const isMember = (id, prefix) => (prefix.endsWith(".") ? id.startsWith(prefix) : id === prefix || id.startsWith(`${prefix}.`));
|
|
109
|
+
const setUp = (c) => (c.setup ?? "ok") === "ok" && !c.notCoveredAgent;
|
|
110
|
+
/**
|
|
111
|
+
* Why a required row doesn't count as passed, or null when it does: Passed
|
|
112
|
+
* in Enforce. A row passes when every check of a rule set up for the agent
|
|
113
|
+
* passed and none failed; a guardrail must also be in Enforce on every rule
|
|
114
|
+
* that counted (Watch, Not checked and Not set up all fail, D6).
|
|
115
|
+
*/
|
|
116
|
+
export function requiredRowProblem(r, rowId) {
|
|
117
|
+
const row = CATALOG.rows.find((x) => x.id === rowId);
|
|
118
|
+
const members = r.checks.filter((c) => row.members.some((m) => isMember(c.id, m)));
|
|
119
|
+
if (members.some((c) => c.status === "failed"))
|
|
120
|
+
return CATALOG.rowStatusLabels.failed;
|
|
121
|
+
const live = members.filter(setUp);
|
|
122
|
+
if (!live.length) {
|
|
123
|
+
// No rule (Pause and Stop need none), or its rules are Off or don't cover the agent.
|
|
124
|
+
const noRule = !members.length && row.members.every((m) => m.startsWith("ctl.")) && row.id !== "pause_stop";
|
|
125
|
+
return members.length || noRule ? CATALOG.rowStatusLabels.not_set_up : CATALOG.rowStatusLabels.not_checked;
|
|
126
|
+
}
|
|
127
|
+
if (!live.every((c) => c.status === "passed"))
|
|
128
|
+
return CATALOG.rowStatusLabels.not_checked;
|
|
129
|
+
const notEnforced = live.some((c) => c.mode != null && c.mode !== CATALOG.controls.modes.enforce);
|
|
130
|
+
return notEnforced ? `${CATALOG.rowStatusLabels.passed} in ${CATALOG.controls.modes.watch}, not ${CATALOG.controls.modes.enforce}` : null;
|
|
131
|
+
}
|
|
132
|
+
/** The results screen in the terminal, and its exit code: 0 Passed, 1 Didn't pass, 3 Didn't finish. With --require, a required row not Passed in Enforce turns a pass into 1. */
|
|
133
|
+
export function results(r, require = []) {
|
|
134
|
+
const required = r.checks.filter((c) => c.required);
|
|
135
|
+
const runs = plural(r.runs, "run");
|
|
136
|
+
const failed = required.filter((c) => c.status === "failed");
|
|
137
|
+
const open = required.filter((c) => c.status !== "passed");
|
|
138
|
+
const scope = r.scope && [...new Set(required.map((c) => c.scenario).filter(Boolean))].join(", ");
|
|
139
|
+
const lines = [""];
|
|
140
|
+
let code;
|
|
141
|
+
if (r.verdict === "passed") {
|
|
142
|
+
code = 0;
|
|
143
|
+
lines.push(`${CATALOG.verdictLabels.passed} · ${scope ? `${scope} only` : `all ${plural(required.length, "check")}`} · ${runs}`);
|
|
144
|
+
}
|
|
145
|
+
else if (r.verdict === "not_passed") {
|
|
146
|
+
code = 1;
|
|
147
|
+
lines.push(`${CATALOG.verdictLabels.not_passed} · ${plural(failed.length, "check")} failed`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
code = 3;
|
|
151
|
+
const ours = open.length > 0 && open.every((c) => c.testProblem);
|
|
152
|
+
lines.push(`${CATALOG.verdictLabels.incomplete} · ${open.length ? `${plural(open.length, "check")} couldn't run` : "no checks could run"}${ours ? " (not your agent)" : ""}`);
|
|
153
|
+
}
|
|
154
|
+
if (r.sample)
|
|
155
|
+
lines.push("This was WhiteRoom's sample agent: it checks your controls and this setup, not your own agent.");
|
|
156
|
+
else if (r.runs === 1 && code === 0)
|
|
157
|
+
lines.push("One run shows your agent can pass. Run it 3 times to see that it passes every time.");
|
|
158
|
+
lines.push("");
|
|
159
|
+
for (const c of r.checks) {
|
|
160
|
+
const name = c.mode ? `${c.label} · ${c.mode}` : c.label;
|
|
161
|
+
// A control row says what happened; a row that wasn't checked says why instead of a status.
|
|
162
|
+
if (c.status === "unsupported" && c.summary)
|
|
163
|
+
lines.push(` ${name}: ${c.summary}`);
|
|
164
|
+
else
|
|
165
|
+
lines.push(` ${STATUS[c.status]}: ${name}${c.id.startsWith("ctl") && c.summary ? ` (${c.summary})` : ""}`);
|
|
166
|
+
}
|
|
167
|
+
const fixes = (code === 1 ? failed : code === 3 ? open : []).filter((c) => c.fix);
|
|
168
|
+
if (fixes.length) {
|
|
169
|
+
lines.push("", code === 3 ? "What stopped the test" : "What to fix");
|
|
170
|
+
for (const c of fixes)
|
|
171
|
+
lines.push(` ${c.label}: ${c.fix}`);
|
|
172
|
+
}
|
|
173
|
+
const next = code === 1 ? "Rerun failed checks" : code === 3 ? "Rerun checks that didn't run" : !r.sample && r.runs === 1 ? "Run it 3 times" : "Past tests";
|
|
174
|
+
const missed = require.map((id) => ({ id, why: requiredRowProblem(r, id) })).filter((x) => x.why);
|
|
175
|
+
if (missed.length) {
|
|
176
|
+
lines.push("", "Required checks (--require) that didn't pass");
|
|
177
|
+
for (const m of missed)
|
|
178
|
+
lines.push(` ${CATALOG.rows.find((x) => x.id === m.id).name}: ${m.why}`);
|
|
179
|
+
if (code === 0)
|
|
180
|
+
code = 1;
|
|
181
|
+
}
|
|
182
|
+
lines.push("", CATALOG.disclaimer, next === "Past tests" ? `See the full result in the dashboard (${DASHBOARD}), under Past tests.` : `${button(next)}.`);
|
|
183
|
+
return { code, lines, result: true };
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/practice/text.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const SANDBOX_USAGE = "whiteroom sandbox \u2014 run your agent from the Sandbox page\n\nUsage:\n whiteroom sandbox listen --adapter \"<command>\" [--code-stdin] [--url <https url>]\n\n listen Connects this computer to your Sandbox with the helper code from\n the Sandbox page (Run agent), then runs each task sent from that\n page through your adapter until you press Ctrl+C. Your agent's\n calls go to your Sandbox URL: set its base URL first, for example\n export ANTHROPIC_BASE_URL=<Sandbox URL>.\n\nOptions:\n --adapter \"<command>\" The command that starts your agent's adapter, e.g. \"node wr-adapter.mjs\"\n (the same JSON-lines contract as practice tests: whiteroom practice adapter --lang js)\n --code-stdin Read the helper code from stdin instead of asking for it\n --url <https url> Only for testing WhiteRoom itself (a whiteroom.tech address or localhost)\n\nExit codes: 0 stopped with Ctrl+C, 2 a setup or usage problem, 3 the session ended (get a new code).\n";
|
|
2
|
+
export declare function sandbox(argv: string[]): Promise<number>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// `whiteroom sandbox`: the helper behind the Sandbox page's Run agent button.
|
|
2
|
+
// Usage problems exit 2; so does anything unexpected.
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
import { listen } from "./listen.js";
|
|
5
|
+
import { warn } from "../practice/text.js";
|
|
6
|
+
export const SANDBOX_USAGE = `whiteroom sandbox — run your agent from the Sandbox page
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
whiteroom sandbox listen --adapter "<command>" [--code-stdin] [--url <https url>]
|
|
10
|
+
|
|
11
|
+
listen Connects this computer to your Sandbox with the helper code from
|
|
12
|
+
the Sandbox page (Run agent), then runs each task sent from that
|
|
13
|
+
page through your adapter until you press Ctrl+C. Your agent's
|
|
14
|
+
calls go to your Sandbox URL: set its base URL first, for example
|
|
15
|
+
export ANTHROPIC_BASE_URL=<Sandbox URL>.
|
|
16
|
+
|
|
17
|
+
Options:
|
|
18
|
+
--adapter "<command>" The command that starts your agent's adapter, e.g. "node wr-adapter.mjs"
|
|
19
|
+
(the same JSON-lines contract as practice tests: whiteroom practice adapter --lang js)
|
|
20
|
+
--code-stdin Read the helper code from stdin instead of asking for it
|
|
21
|
+
--url <https url> Only for testing WhiteRoom itself (a whiteroom.tech address or localhost)
|
|
22
|
+
|
|
23
|
+
Exit codes: 0 stopped with Ctrl+C, 2 a setup or usage problem, 3 the session ended (get a new code).
|
|
24
|
+
`;
|
|
25
|
+
function usage(problem) {
|
|
26
|
+
if (!problem)
|
|
27
|
+
return process.stdout.write(SANDBOX_USAGE), 0;
|
|
28
|
+
warn(`${problem}\nRun whiteroom sandbox --help to see the commands.`);
|
|
29
|
+
return 2;
|
|
30
|
+
}
|
|
31
|
+
export async function sandbox(argv) {
|
|
32
|
+
const [sub, ...rest] = argv;
|
|
33
|
+
if (!sub || sub === "--help" || sub === "-h" || sub === "help")
|
|
34
|
+
return usage();
|
|
35
|
+
if (sub !== "listen")
|
|
36
|
+
return usage(`Unknown sandbox command: ${sub}`);
|
|
37
|
+
let values;
|
|
38
|
+
try {
|
|
39
|
+
({ values } = parseArgs({
|
|
40
|
+
args: rest,
|
|
41
|
+
strict: true,
|
|
42
|
+
allowPositionals: false,
|
|
43
|
+
options: { adapter: { type: "string" }, "code-stdin": { type: "boolean" }, url: { type: "string" }, help: { type: "boolean", short: "h" } },
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
return usage(err.message);
|
|
48
|
+
}
|
|
49
|
+
if (values.help)
|
|
50
|
+
return usage();
|
|
51
|
+
if (!values.adapter?.trim())
|
|
52
|
+
return usage("--adapter needs the command that starts your adapter.");
|
|
53
|
+
try {
|
|
54
|
+
return await listen({ adapter: values.adapter, codeStdin: !!values["code-stdin"], url: values.url });
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
// Any adapter still running is killed as the process exits (adapter.ts).
|
|
58
|
+
warn(`Something went wrong in the CLI: ${err?.message ?? String(err)}`);
|
|
59
|
+
return 2;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sandbox/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,sDAAsD;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;CAkB5B,CAAC;AAEF,SAAS,KAAK,CAAC,OAAgB;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAC5D,IAAI,CAAC,GAAG,OAAO,qDAAqD,CAAC,CAAC;IACtE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAc;IAC1C,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,KAAK,EAAE,CAAC;IAC/E,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,4BAA4B,GAAG,EAAE,CAAC,CAAC;IACtE,IAAI,MAAkF,CAAC;IACvF,IAAI,CAAC;QACH,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;YACtB,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,IAAI;YACZ,gBAAgB,EAAE,KAAK;YACvB,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;SAC5I,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,KAAK,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,MAAM,CAAC,IAAI;QAAE,OAAO,KAAK,EAAE,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC,uDAAuD,CAAC,CAAC;IACnG,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IACvG,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,yEAAyE;QACzE,IAAI,CAAC,oCAAqC,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnF,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type Outcome } from "../practice/adapter.js";
|
|
2
|
+
export declare const HELPER_CODE: RegExp;
|
|
3
|
+
/** How long one task may run before its adapter is stopped. */
|
|
4
|
+
export declare const TASK_MS: number;
|
|
5
|
+
export declare const sandboxCopy: {
|
|
6
|
+
connected: string;
|
|
7
|
+
needCode: string;
|
|
8
|
+
badCode: string;
|
|
9
|
+
noTerminal: string;
|
|
10
|
+
noSandboxUrl: string;
|
|
11
|
+
severalSandboxUrls: (vars: string[]) => string;
|
|
12
|
+
otherSandboxHost: (urlHost: string, host: string) => string;
|
|
13
|
+
badUrl: string;
|
|
14
|
+
adapterMissing: (cmd: string, why: string) => string;
|
|
15
|
+
windows: string;
|
|
16
|
+
codeInvalid: string;
|
|
17
|
+
keyMismatch: (left: number) => string;
|
|
18
|
+
notConnected: string;
|
|
19
|
+
unavailable: string;
|
|
20
|
+
unreachable: string;
|
|
21
|
+
redirected: string;
|
|
22
|
+
outdated: string;
|
|
23
|
+
otherHost: string;
|
|
24
|
+
sessionEnded: Record<string, string>;
|
|
25
|
+
stopped: string;
|
|
26
|
+
cancelled: string;
|
|
27
|
+
task: (n: number, prompt: string) => string;
|
|
28
|
+
taskDone: (n: number) => string;
|
|
29
|
+
taskFailed: (n: number, why: string) => string;
|
|
30
|
+
resultNotSent: (n: number) => string;
|
|
31
|
+
noTools: string;
|
|
32
|
+
};
|
|
33
|
+
export interface ListenArgs {
|
|
34
|
+
adapter: string;
|
|
35
|
+
codeStdin: boolean;
|
|
36
|
+
url?: string;
|
|
37
|
+
}
|
|
38
|
+
/** The Sandbox URL the user's agent points at, found in its environment: the variable, WhiteRoom's origin and the Sandbox key. */
|
|
39
|
+
export declare function findSandboxUrl(env: NodeJS.ProcessEnv): Array<{
|
|
40
|
+
variable: string;
|
|
41
|
+
origin: string;
|
|
42
|
+
key: string;
|
|
43
|
+
}>;
|
|
44
|
+
/** The adapter's environment: the user's own (their agent's settings and keys), without WhiteRoom's. */
|
|
45
|
+
export declare function helperEnv(parent: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
46
|
+
/** This computer's name as the Sandbox page shows it ("Helper connected · <host>"). */
|
|
47
|
+
export declare function helperHost(name?: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* What a task's adapter run reports back: ok and a summary of at most 2,000
|
|
50
|
+
* characters. Everything sent to WhiteRoom goes through clean(), so a provider
|
|
51
|
+
* key, the Sandbox key, the helper code or session the adapter echoes is never sent.
|
|
52
|
+
*/
|
|
53
|
+
export declare function taskResult(out: Outcome, taskMs?: number): {
|
|
54
|
+
ok: boolean;
|
|
55
|
+
summary: string;
|
|
56
|
+
};
|
|
57
|
+
export declare function listen(a: ListenArgs): Promise<number>;
|