@whiteroom-ai/cli 2.0.0 → 2.0.2

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.
@@ -0,0 +1,299 @@
1
+ // `whiteroom sandbox listen --adapter "<cmd>"`: the connected helper behind
2
+ // the Sandbox page's Run agent button. It claims a one-time helper code, then
3
+ // waits for tasks the owner queues there and runs each through the user's
4
+ // adapter (the practice tests' NDJSON contract), with the agent's calls going
5
+ // to the Sandbox URL. WhiteRoom sends task data only (a prompt); the command
6
+ // that runs is the one typed here, never anything from WhiteRoom.
7
+ import { hostname } from "node:os";
8
+ import { runAdapter } from "../practice/adapter.js";
9
+ import { CATALOG } from "../practice/catalog.js";
10
+ import { Engine, OFFLINE_MS, REDIRECTED, Stopped, Unreachable } from "../practice/engine.js";
11
+ import { adapterProblem, chatCompletions, firstLineOfStdin, hiddenPrompt, Interrupted, isProvider, nodeTooOld, targetOrigin } from "../practice/preflight.js";
12
+ import { clean, hideSecret, say, warn } from "../practice/text.js";
13
+ export const HELPER_CODE = /^wrhc_[A-Za-z0-9_-]{43}$/;
14
+ /** A Sandbox URL as the Sandbox page shows it: WhiteRoom's address, then the Sandbox key. */
15
+ const SANDBOX_URL = /^(https?:\/\/[^/\s?#@]+)\/(sk-wr-[0-9a-f]{40})(?:[/?#]\S*)?$/;
16
+ /** How long one task may run before its adapter is stopped. */
17
+ export const TASK_MS = 10 * 60_000;
18
+ /** While a task runs the helper doesn't poll, so it tells WhiteRoom it's still there. */
19
+ const HEARTBEAT_MS = 20_000;
20
+ /** Tests shorten the task deadline, heartbeat and offline wait (internal, not a user setting; WHITEROOM_* never reaches the adapter). */
21
+ const testMs = (name, fallback) => {
22
+ const v = Number(process.env[name]);
23
+ return Number.isInteger(v) && v > 0 ? v : fallback;
24
+ };
25
+ const SUMMARY_MAX = 2000;
26
+ const SANDBOX_PAGE = "https://app.whiteroom.tech/sandbox";
27
+ const NEW_CODE = `In the Sandbox page (${SANDBOX_PAGE}), click Run agent to get a new code, then start the helper again.`;
28
+ export const sandboxCopy = {
29
+ connected: "Helper connected · waiting for tasks from the Sandbox page (Ctrl+C to stop)",
30
+ needCode: "Paste the helper code from the Sandbox page (it won't show): ",
31
+ badCode: "That isn't a helper code. Copy it again from the Sandbox page (it starts with wrhc_).",
32
+ noTerminal: "No terminal to ask for the helper code. Pass it on stdin with --code-stdin.",
33
+ noSandboxUrl: "Point your agent at your Sandbox first: set its base URL to the Sandbox URL from the Sandbox page (for example export ANTHROPIC_BASE_URL=<Sandbox URL>), then run the command again. Nothing was sent.",
34
+ severalSandboxUrls: (vars) => `More than one Sandbox URL is set (${vars.join(", ")}). Keep the one your agent uses, then run the command again. Nothing was sent.`,
35
+ otherSandboxHost: (urlHost, host) => `Your Sandbox URL is on ${urlHost}, but the helper connects to ${host}. Use the Sandbox URL and command from the same Sandbox page. Nothing was sent.`,
36
+ badUrl: "--url must be a WhiteRoom address (https://….whiteroom.tech) or http://localhost for local testing.",
37
+ adapterMissing: (cmd, why) => `Couldn't start the adapter \`${cmd}\`: ${why}. Nothing was sent, and your helper code still works.`,
38
+ windows: "The helper runs on macOS and Linux for now. Run the command there, or in WSL.",
39
+ codeInvalid: `This helper code doesn't work any more. ${NEW_CODE}`,
40
+ keyMismatch: (left) => left > 0
41
+ ? `Your agent's Sandbox URL isn't this Sandbox's current one (was the key rotated?). Copy the Sandbox URL from the Sandbox page, set it again, then run the same command (${left} ${left === 1 ? "try" : "tries"} left on this code).`
42
+ : `Your agent's Sandbox URL isn't this Sandbox's current one, and this code has no tries left. Copy the Sandbox URL from the Sandbox page, set it again, then get a new code.`,
43
+ notConnected: "This Sandbox has no key yet. Connect a provider key in the Sandbox page first.",
44
+ unavailable: "The Sandbox helper isn't available yet. Try again later.",
45
+ unreachable: "Couldn't reach WhiteRoom. Check your connection, then start the helper again.",
46
+ redirected: "WhiteRoom's server tried to send the helper to another address, so it stopped. Nothing was sent anywhere else.",
47
+ outdated: "WhiteRoom sent something this CLI doesn't understand. Update the CLI, then start the helper again.",
48
+ otherHost: "WhiteRoom named another host for your Sandbox, so the helper stopped before running your agent.",
49
+ sessionEnded: {
50
+ session_lost: `This helper's session has ended (WhiteRoom restarted, or it expired). ${NEW_CODE}`,
51
+ replaced: "Another helper connected to this Sandbox, so this one stopped.",
52
+ disconnected: "The helper was disconnected from the Sandbox page.",
53
+ lost_contact: `WhiteRoom didn't hear from this helper for a while, so its session ended. ${NEW_CODE}`,
54
+ },
55
+ stopped: "Helper stopped. The Sandbox page shows it disconnected.",
56
+ cancelled: "Stopped before the helper connected. Your code still works until it expires.",
57
+ task: (n, prompt) => `Task ${n}: ${prompt.replace(/\s+/g, " ").slice(0, 80)}${prompt.length > 80 ? "…" : ""}`,
58
+ taskDone: (n) => `Task ${n} finished. The result is on the Sandbox page.`,
59
+ taskFailed: (n, why) => `Task ${n} didn't finish: ${why}`,
60
+ resultNotSent: (n) => `Task ${n} ran, but its result couldn't be sent to WhiteRoom. If the Sandbox page hands it out again, the helper sends it again.`,
61
+ noTools: "No tools are available in Sandbox tasks.",
62
+ };
63
+ /** The Sandbox URL the user's agent points at, found in its environment: the variable, WhiteRoom's origin and the Sandbox key. */
64
+ export function findSandboxUrl(env) {
65
+ const found = new Map();
66
+ for (const [variable, value] of Object.entries(env)) {
67
+ const m = value?.trim().match(SANDBOX_URL);
68
+ if (m && !found.has(m[2]))
69
+ found.set(m[2], { variable, origin: new URL(m[1]).origin, key: m[2] });
70
+ }
71
+ return [...found.values()];
72
+ }
73
+ /** The adapter's environment: the user's own (their agent's settings and keys), without WhiteRoom's. */
74
+ export function helperEnv(parent) {
75
+ const env = {};
76
+ for (const [k, v] of Object.entries(parent))
77
+ if (!/^WHITEROOM_/i.test(k))
78
+ env[k] = v;
79
+ return env;
80
+ }
81
+ /** This computer's name as the Sandbox page shows it ("Helper connected · <host>"). */
82
+ export function helperHost(name = hostname()) {
83
+ return name.replace(/[^A-Za-z0-9._-]/g, "-").slice(0, 64) || "computer";
84
+ }
85
+ /** How long a deadline is, in plain words ("10 minutes", "1 second"). */
86
+ const duration = (ms) => {
87
+ const [n, unit] = ms >= 60_000 && ms % 60_000 === 0 ? [ms / 60_000, "minute"] : [Math.max(1, Math.round(ms / 1000)), "second"];
88
+ return `${n} ${unit}${n === 1 ? "" : "s"}`;
89
+ };
90
+ /**
91
+ * What a task's adapter run reports back: ok and a summary of at most 2,000
92
+ * characters. Everything sent to WhiteRoom goes through clean(), so a provider
93
+ * key, the Sandbox key, the helper code or session the adapter echoes is never sent.
94
+ */
95
+ export function taskResult(out, taskMs = TASK_MS) {
96
+ const cut = (s) => clean(s).slice(0, SUMMARY_MAX);
97
+ switch (out.kind) {
98
+ case "final": return { ok: true, summary: cut(out.output) };
99
+ case "exited": return { ok: false, summary: cut(`Your adapter exited (${out.how}) before finishing.${out.tail.length ? ` Last output: ${out.tail.join(" / ")}` : ""}`) };
100
+ case "broke": return { ok: false, summary: cut(`Your adapter ${out.why}.`) };
101
+ case "deadline": return { ok: false, summary: cut(`Your agent didn't finish within ${duration(taskMs)}, so it was stopped.`) };
102
+ default: return { ok: false, summary: cut("Stopped on the helper's computer.") };
103
+ }
104
+ }
105
+ const fail = (code, line) => (warn(line), code);
106
+ /** A session refusal, in plain words. */
107
+ const sessionOver = (r) => fail(3, sandboxCopy.sessionEnded[r.body?.reason] ?? sandboxCopy.sessionEnded.session_lost);
108
+ /** A reply that ends listening: the session refused (401), or a redirect. */
109
+ const ends = (r) => r.status === 401 || r.status === REDIRECTED;
110
+ const endListening = (r) => (r.status === REDIRECTED ? fail(3, sandboxCopy.redirected) : sessionOver(r));
111
+ export async function listen(a) {
112
+ // ── Preflight: nothing is sent until every check passes ──
113
+ const old = nodeTooOld();
114
+ if (old)
115
+ return fail(2, old);
116
+ if (process.platform === "win32")
117
+ return fail(2, sandboxCopy.windows);
118
+ const origin = targetOrigin(a.url);
119
+ if (!origin)
120
+ return fail(2, sandboxCopy.badUrl);
121
+ const why = adapterProblem(a.adapter);
122
+ if (why)
123
+ return fail(2, sandboxCopy.adapterMissing(a.adapter, why));
124
+ // The user's own command runs through their shell as typed; nothing from WhiteRoom is ever put into it.
125
+ const launch = { shell: a.adapter };
126
+ // Provider keys in the environment are never printed, even in the adapter's output.
127
+ for (const p of Object.values(CATALOG.providers)) {
128
+ const v = process.env[p.keyVar];
129
+ if (v)
130
+ hideSecret(v.trim());
131
+ }
132
+ const urls = findSandboxUrl(process.env);
133
+ if (!urls.length)
134
+ return fail(2, sandboxCopy.noSandboxUrl);
135
+ if (urls.length > 1)
136
+ return fail(2, sandboxCopy.severalSandboxUrls(urls.map((u) => u.variable)));
137
+ const sandbox = urls[0];
138
+ hideSecret(sandbox.key);
139
+ if (sandbox.origin !== origin)
140
+ return fail(2, sandboxCopy.otherSandboxHost(new URL(sandbox.origin).host, new URL(origin).host));
141
+ let code = "";
142
+ try {
143
+ if (a.codeStdin)
144
+ code = await firstLineOfStdin();
145
+ else {
146
+ if (!process.stdin.isTTY)
147
+ return fail(2, sandboxCopy.noTerminal);
148
+ for (let i = 0; i < 3 && !HELPER_CODE.test(code); i++) {
149
+ if (i)
150
+ warn(sandboxCopy.badCode);
151
+ code = await hiddenPrompt(sandboxCopy.needCode);
152
+ }
153
+ }
154
+ }
155
+ catch (err) {
156
+ // Cancelled at the prompt: no session existed, so this is a plain stop (0), not an ended session (3).
157
+ if (err instanceof Interrupted)
158
+ return fail(0, sandboxCopy.cancelled);
159
+ throw err;
160
+ }
161
+ if (!HELPER_CODE.test(code))
162
+ return fail(2, sandboxCopy.badCode);
163
+ hideSecret(code);
164
+ // ── Claim: the code, and which Sandbox key this computer's agent uses (its non-secret prefix, never the key) ──
165
+ const engine = new Engine(origin, testMs("WHITEROOM_TEST_OFFLINE_MS", OFFLINE_MS));
166
+ let claim;
167
+ try {
168
+ claim = await engine.post("/api/sandbox-helper/claim", { code, keyPrefix: sandbox.key.slice(0, 22), host: helperHost() });
169
+ }
170
+ catch (err) {
171
+ // No session yet: a setup problem (2); the code is still unused.
172
+ if (err instanceof Unreachable)
173
+ return fail(2, sandboxCopy.unreachable);
174
+ throw err;
175
+ }
176
+ if (claim.status === 401 && claim.body?.reason === "key_mismatch")
177
+ return fail(2, sandboxCopy.keyMismatch(Number(claim.body.triesLeft) || 0));
178
+ if (claim.status === 410)
179
+ return fail(2, sandboxCopy.codeInvalid);
180
+ if (claim.status === 409 && claim.body?.reason === "not_connected")
181
+ return fail(2, sandboxCopy.notConnected);
182
+ if (claim.status === REDIRECTED)
183
+ return fail(2, sandboxCopy.redirected);
184
+ if (claim.status === 404)
185
+ return fail(2, sandboxCopy.unavailable);
186
+ const { session, proxyUrl, provider } = claim.body ?? {};
187
+ if (claim.status !== 200 || typeof session !== "string" || !isProvider(provider))
188
+ return fail(2, sandboxCopy.outdated);
189
+ engine.session = session;
190
+ hideSecret(session);
191
+ // The agent's calls go to this Sandbox's URL, on the host the helper claimed on, never one WhiteRoom names elsewhere.
192
+ if (proxyUrl !== sandbox.origin) {
193
+ await engine.once("/api/sandbox-helper/disconnect", {});
194
+ return fail(3, sandboxCopy.otherHost);
195
+ }
196
+ // As practice tests pass it: Azure OpenAI under /openai; OpenAI SDKs want a base URL that ends in /v1.
197
+ const sandboxBase = `${sandbox.origin}/${sandbox.key}${provider === "azure-openai" ? "/openai" : ""}`;
198
+ const baseUrl = chatCompletions(provider) ? `${sandboxBase}/v1` : sandboxBase;
199
+ say(sandboxCopy.connected);
200
+ // ── Listening: Ctrl+C (or a signal) disconnects; WhiteRoom can end the session ──
201
+ const stop = new AbortController();
202
+ engine.signal = stop.signal;
203
+ const onStop = () => stop.abort();
204
+ process.on("SIGINT", onStop);
205
+ process.on("SIGTERM", onStop);
206
+ process.on("SIGHUP", onStop);
207
+ /** Results by task: a task handed out again gets its result (re)sent, not a second run. */
208
+ const done = new Map();
209
+ const taskMs = testMs("WHITEROOM_TEST_TASK_MS", TASK_MS);
210
+ const heartbeatMs = testMs("WHITEROOM_TEST_HEARTBEAT_MS", HEARTBEAT_MS);
211
+ let n = 0;
212
+ /** Posts a task's result; announces it only once WhiteRoom has it. Returns a reply that ends listening, else null. */
213
+ const sendResult = async (taskId, entry) => {
214
+ const r = await engine.post("/api/sandbox-helper/result", { taskId, ...entry.result }, { retryNetwork: true });
215
+ if (ends(r))
216
+ return r;
217
+ const ok = r.status >= 200 && r.status < 300;
218
+ if (ok && !entry.sent)
219
+ say(entry.result.ok ? sandboxCopy.taskDone(entry.n) : sandboxCopy.taskFailed(entry.n, clean(entry.result.summary)));
220
+ else if (!ok)
221
+ warn(sandboxCopy.resultNotSent(entry.n));
222
+ entry.sent ||= ok;
223
+ return null;
224
+ };
225
+ let ended = null;
226
+ const runTask = async (task) => {
227
+ say(sandboxCopy.task(++n, task.prompt));
228
+ const taskStop = new AbortController();
229
+ const abort = () => taskStop.abort();
230
+ stop.signal.addEventListener("abort", abort, { once: true });
231
+ const beat = setInterval(() => {
232
+ void engine.once("/api/sandbox-helper/heartbeat", {}).then((r) => {
233
+ if (r?.status === 401)
234
+ (ended = r), taskStop.abort();
235
+ });
236
+ }, heartbeatMs);
237
+ beat.unref();
238
+ let out;
239
+ try {
240
+ out = await runAdapter({
241
+ launch, env: helperEnv(process.env), deadline: Date.now() + taskMs, signal: taskStop.signal,
242
+ message: { type: "task", task: task.prompt, tools: [], headers: {}, model: null, base_url: baseUrl },
243
+ tool: async () => ({ result: { error: sandboxCopy.noTools } }),
244
+ });
245
+ }
246
+ finally {
247
+ clearInterval(beat);
248
+ stop.signal.removeEventListener("abort", abort);
249
+ }
250
+ // Stopped here: disconnecting closes the task on the Sandbox page.
251
+ if (out.kind === "stopped" || ended)
252
+ return null;
253
+ const entry = { n, result: taskResult(out, taskMs), sent: false };
254
+ done.set(task.taskId, entry);
255
+ return sendResult(task.taskId, entry);
256
+ };
257
+ try {
258
+ for (;;) {
259
+ // Every request to WhiteRoom in this loop ends the same way: Ctrl+C stops (0), unreachable ends (3).
260
+ try {
261
+ const next = await engine.post("/api/sandbox-helper/next", {}, { retryNetwork: true });
262
+ if (ends(next))
263
+ return endListening(next);
264
+ if (next.status !== 200)
265
+ return fail(3, sandboxCopy.outdated);
266
+ if (next.body?.idle)
267
+ continue;
268
+ const task = next.body?.task;
269
+ if (!task || typeof task.taskId !== "string" || task.kind !== "prompt" || typeof task.prompt !== "string")
270
+ return fail(3, sandboxCopy.outdated);
271
+ // A task handed out again (WhiteRoom didn't get the result): send the result again, don't run it twice.
272
+ const sent = done.get(task.taskId);
273
+ const refused = sent ? await sendResult(task.taskId, sent) : await runTask(task);
274
+ if (refused)
275
+ return endListening(refused);
276
+ }
277
+ catch (err) {
278
+ if (err instanceof Stopped)
279
+ break;
280
+ if (err instanceof Unreachable)
281
+ return fail(3, sandboxCopy.unreachable);
282
+ throw err;
283
+ }
284
+ if (ended)
285
+ return sessionOver(ended);
286
+ if (stop.signal.aborted)
287
+ break;
288
+ }
289
+ await engine.once("/api/sandbox-helper/disconnect", {});
290
+ say(sandboxCopy.stopped);
291
+ return 0;
292
+ }
293
+ finally {
294
+ process.off("SIGINT", onStop);
295
+ process.off("SIGTERM", onStop);
296
+ process.off("SIGHUP", onStop);
297
+ }
298
+ }
299
+ //# sourceMappingURL=listen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listen.js","sourceRoot":"","sources":["../../src/sandbox/listen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /** The providers a Sandbox connects, as the dashboard names them. */
2
+ export declare const RUN_PROVIDERS: readonly ["anthropic", "openai", "azure-openai", "foundry", "bedrock-mantle"];
3
+ export type RunProvider = typeof RUN_PROVIDERS[number];
4
+ export declare const runCopy: {
5
+ needUrl: string;
6
+ badUrl: string;
7
+ noTerminal: string;
8
+ notWhiteRoom: string;
9
+ pointsAtWhiteRoom: (vars: string[]) => string;
10
+ gotUrl: (end: string) => string;
11
+ running: (name: string) => string;
12
+ cancelled: string;
13
+ notFound: (cmd: string) => string;
14
+ couldntStart: (cmd: string, why: string) => string;
15
+ };
16
+ /** The setting that points an agent at the Sandbox, as the Sandbox page's .env line has it (dashboard issuedEnvHint). */
17
+ export declare function sandboxSetting(provider: RunProvider, url: string): {
18
+ name: string;
19
+ value: string;
20
+ };
21
+ /** Every setting the agent gets: OpenAI's also under the older OPENAI_API_BASE, which some SDKs still read, so none of them bypasses the Sandbox. */
22
+ export declare function sandboxSettings(provider: RunProvider, url: string): Record<string, string>;
23
+ /** Other base-URL settings in the environment that point at WhiteRoom (whiteroom.tech; a local proxy on localhost is the user's own). */
24
+ export declare function whiteRoomBaseUrls(env: NodeJS.ProcessEnv, except: readonly string[]): string[];
25
+ /**
26
+ * The Sandbox URL, checked: a problem when it isn't one, or isn't on a
27
+ * WhiteRoom address. The Sandbox page's .env line works too
28
+ * (ANTHROPIC_BASE_URL=…, with or without export or quotes).
29
+ */
30
+ export declare function sandboxUrlOf(raw: string, env?: NodeJS.ProcessEnv): {
31
+ url: string;
32
+ } | {
33
+ problem: string;
34
+ };
35
+ export interface RunArgs {
36
+ provider: RunProvider;
37
+ command: string[];
38
+ }
39
+ /** How the Sandbox URL is asked for: a hidden prompt on the terminal (tests pass their own). */
40
+ export interface Asker {
41
+ terminal: boolean;
42
+ ask: (question: string) => Promise<string>;
43
+ }
44
+ export declare function run(a: RunArgs, env?: NodeJS.ProcessEnv, asker?: Asker): Promise<number>;
@@ -0,0 +1,139 @@
1
+ // `whiteroom sandbox run --provider <p> -- <command> [args…]`: runs the
2
+ // user's agent once with its base URL set to their Sandbox URL, so nothing
3
+ // has to be edited first. The Sandbox URL is pasted at a hidden prompt (or
4
+ // read from WHITEROOM_SANDBOX_URL), so the key never lands in shell history.
5
+ // The command runs as typed, without a shell; nothing from WhiteRoom is put
6
+ // into it. Refuses to start while another base URL in the environment points
7
+ // at WhiteRoom, so the agent's calls can't go to production by mistake.
8
+ import { spawn } from "node:child_process";
9
+ import { constants } from "node:os";
10
+ import { hiddenPrompt, Interrupted, nodeTooOld, targetOrigin } from "../practice/preflight.js";
11
+ import { say, warn } from "../practice/text.js";
12
+ import { helperEnv } from "./listen.js";
13
+ /** A Sandbox URL as the Sandbox page shows it: WhiteRoom's address, then the Sandbox key. */
14
+ const SANDBOX_URL = /^(https?:\/\/[^/\s?#@]+)\/(sk-wr-[0-9a-f]{40})(?:\/v1|\/openai)?\/?$/;
15
+ /** The providers a Sandbox connects, as the dashboard names them. */
16
+ export const RUN_PROVIDERS = ["anthropic", "openai", "azure-openai", "foundry", "bedrock-mantle"];
17
+ /** Base-URL settings agents read: one pointing at WhiteRoom other than the one this sets could send calls to production. */
18
+ const BASE_URL_VARS = ["ANTHROPIC_BASE_URL", "OPENAI_BASE_URL", "OPENAI_API_BASE", "AZURE_OPENAI_ENDPOINT"];
19
+ /** Without a shell, Windows can't start .cmd commands such as npx: WSL runs them as on macOS and Linux. */
20
+ const WINDOWS = process.platform === "win32" ? " On Windows, run this in WSL." : "";
21
+ export const runCopy = {
22
+ needUrl: "Paste your Sandbox URL from the Sandbox page (it won't show): ",
23
+ badUrl: "That isn't a Sandbox URL. Copy it again from the Sandbox page (it ends with /sk-wr-…). Nothing was run.",
24
+ noTerminal: "No terminal to ask for the Sandbox URL. Set WHITEROOM_SANDBOX_URL to it instead. Nothing was run.",
25
+ notWhiteRoom: "That Sandbox URL isn't a WhiteRoom address. Copy it again from the Sandbox page. Nothing was run.",
26
+ pointsAtWhiteRoom: (vars) => `${vars.join(" and ")} already ${vars.length === 1 ? "points" : "point"} at WhiteRoom, so your agent's calls could go to production instead of your Sandbox. Unset ${vars.length === 1 ? "it" : "them"}, then run this again. Nothing was run.`,
27
+ gotUrl: (end) => `Got your Sandbox URL (key ending …${end}).`,
28
+ running: (name) => `Running your agent with ${name} set to your Sandbox URL. The checks start on its first call; results are on the Sandbox page.`,
29
+ cancelled: "Stopped. Nothing was run.",
30
+ notFound: (cmd) => `Couldn't start \`${cmd}\`: no such command. Check the command, then run this again.${WINDOWS}`,
31
+ couldntStart: (cmd, why) => `Couldn't start \`${cmd}\`: ${why}.${WINDOWS}`,
32
+ };
33
+ /** The setting that points an agent at the Sandbox, as the Sandbox page's .env line has it (dashboard issuedEnvHint). */
34
+ export function sandboxSetting(provider, url) {
35
+ const base = url.replace(/\/+$/, "");
36
+ if (provider === "azure-openai")
37
+ return { name: "AZURE_OPENAI_ENDPOINT", value: base };
38
+ if (provider === "openai")
39
+ return { name: "OPENAI_BASE_URL", value: `${base}/v1` };
40
+ return { name: "ANTHROPIC_BASE_URL", value: base };
41
+ }
42
+ /** Every setting the agent gets: OpenAI's also under the older OPENAI_API_BASE, which some SDKs still read, so none of them bypasses the Sandbox. */
43
+ export function sandboxSettings(provider, url) {
44
+ const s = sandboxSetting(provider, url);
45
+ return provider === "openai" ? { [s.name]: s.value, OPENAI_API_BASE: s.value } : { [s.name]: s.value };
46
+ }
47
+ /** Other base-URL settings in the environment that point at WhiteRoom (whiteroom.tech; a local proxy on localhost is the user's own). */
48
+ export function whiteRoomBaseUrls(env, except) {
49
+ return BASE_URL_VARS.filter((name) => {
50
+ if (except.includes(name) || !env[name]?.trim())
51
+ return false;
52
+ try {
53
+ const host = new URL(env[name].trim()).hostname;
54
+ return host === "whiteroom.tech" || host.endsWith(".whiteroom.tech");
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ });
60
+ }
61
+ /**
62
+ * The Sandbox URL, checked: a problem when it isn't one, or isn't on a
63
+ * WhiteRoom address. The Sandbox page's .env line works too
64
+ * (ANTHROPIC_BASE_URL=…, with or without export or quotes).
65
+ */
66
+ export function sandboxUrlOf(raw, env = {}) {
67
+ const value = raw.trim().replace(/^export\s+/, "").replace(/^[A-Z][A-Z0-9_]*=/, "").replace(/^(["'])(.*)\1$/, "$2");
68
+ const m = value.trim().match(SANDBOX_URL);
69
+ if (!m)
70
+ return { problem: runCopy.badUrl };
71
+ // WHITEROOM_PRACTICE_DEV=1 allows another host, as for listen and practice (testing WhiteRoom itself, e.g. its staging engine).
72
+ if (targetOrigin(m[1], env) === null)
73
+ return { problem: runCopy.notWhiteRoom };
74
+ return { url: `${new URL(m[1]).origin}/${m[2]}` };
75
+ }
76
+ const fail = (line) => (warn(line), 2);
77
+ const TERMINAL = { get terminal() { return !!process.stdin.isTTY; }, ask: (q) => hiddenPrompt(q) };
78
+ export async function run(a, env = process.env, asker = TERMINAL) {
79
+ const old = nodeTooOld();
80
+ if (old)
81
+ return fail(old);
82
+ let raw = env.WHITEROOM_SANDBOX_URL ?? "";
83
+ if (!raw) {
84
+ if (!asker.terminal)
85
+ return fail(runCopy.noTerminal);
86
+ try {
87
+ raw = await asker.ask(runCopy.needUrl);
88
+ }
89
+ catch (err) {
90
+ if (err instanceof Interrupted)
91
+ return warn(runCopy.cancelled), 130;
92
+ throw err;
93
+ }
94
+ }
95
+ const checked = sandboxUrlOf(raw, env);
96
+ if ("problem" in checked)
97
+ return fail(checked.problem);
98
+ // The URL was hidden as it was pasted: say which one arrived (its key's last characters only).
99
+ if (!env.WHITEROOM_SANDBOX_URL)
100
+ say(runCopy.gotUrl(checked.url.slice(-6)));
101
+ const setting = sandboxSetting(a.provider, checked.url);
102
+ const settings = sandboxSettings(a.provider, checked.url);
103
+ const clash = whiteRoomBaseUrls(env, Object.keys(settings));
104
+ if (clash.length)
105
+ return fail(runCopy.pointsAtWhiteRoom(clash));
106
+ // The agent gets the user's environment (without WHITEROOM_*), with its base URL set to the Sandbox.
107
+ const childEnv = { ...helperEnv(env), ...settings };
108
+ say(runCopy.running(setting.name));
109
+ const [cmd, ...args] = a.command;
110
+ return new Promise((resolve) => {
111
+ // Ctrl+C already reaches the agent (it's in the same process group, whether or not stdin is a
112
+ // terminal): this process only waits for it, so the agent never gets a second one. A SIGINT sent
113
+ // to this process alone isn't passed on either (it can't be told apart); SIGTERM and SIGHUP are.
114
+ const handlers = new Map();
115
+ const done = (code) => {
116
+ for (const [sig, h] of handlers)
117
+ process.off(sig, h);
118
+ resolve(code);
119
+ };
120
+ let child;
121
+ try {
122
+ child = spawn(cmd, args, { stdio: "inherit", env: childEnv });
123
+ }
124
+ catch (err) {
125
+ // Windows refuses some commands (a .cmd without a shell) before starting them.
126
+ return done(fail(runCopy.couldntStart(cmd, err.message)));
127
+ }
128
+ for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) {
129
+ const h = () => { if (sig !== "SIGINT")
130
+ child.kill(sig); };
131
+ handlers.set(sig, h);
132
+ process.on(sig, h);
133
+ }
134
+ child.on("error", (err) => done(fail(err.code === "ENOENT" ? runCopy.notFound(cmd) : runCopy.couldntStart(cmd, err.message))));
135
+ // The agent's own exit code; killed by a signal, 128 + its number, as a shell reports it.
136
+ child.on("exit", (code, signal) => done(code ?? 128 + (signal ? constants.signals[signal] ?? 0 : 0)));
137
+ });
138
+ }
139
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/sandbox/run.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whiteroom-ai/cli",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "CLI for WhiteRoom — manage AI agent fleets from the terminal",
5
5
  "type": "module",
6
6
  "bin": {