@brainbase-labs/cli 0.41.1 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1035 -375
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35182,7 +35182,7 @@ var require_dist2 = __commonJS((exports, module) => {
|
|
|
35182
35182
|
});
|
|
35183
35183
|
|
|
35184
35184
|
// src/index.ts
|
|
35185
|
-
var
|
|
35185
|
+
var import_picocolors71 = __toESM(require_picocolors(), 1);
|
|
35186
35186
|
import process14 from "node:process";
|
|
35187
35187
|
import fs91 from "node:fs";
|
|
35188
35188
|
|
|
@@ -36059,7 +36059,7 @@ function padStart(s, n) {
|
|
|
36059
36059
|
// package.json
|
|
36060
36060
|
var package_default = {
|
|
36061
36061
|
name: "@brainbase-labs/cli",
|
|
36062
|
-
version: "0.
|
|
36062
|
+
version: "0.43.0",
|
|
36063
36063
|
description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
|
|
36064
36064
|
type: "module",
|
|
36065
36065
|
bin: {
|
|
@@ -55172,6 +55172,8 @@ async function request(pathname, init = {}) {
|
|
|
55172
55172
|
let res;
|
|
55173
55173
|
let text2;
|
|
55174
55174
|
for (let attempt2 = 0;; attempt2 += 1) {
|
|
55175
|
+
if (init.signal?.aborted)
|
|
55176
|
+
throw init.signal.reason;
|
|
55175
55177
|
try {
|
|
55176
55178
|
res = await sendWithAuthRetry(refreshSessionAvailable ? currentSession : null, async (refreshed) => {
|
|
55177
55179
|
if (refreshed) {
|
|
@@ -55187,7 +55189,7 @@ async function request(pathname, init = {}) {
|
|
|
55187
55189
|
}
|
|
55188
55190
|
break;
|
|
55189
55191
|
} catch (error) {
|
|
55190
|
-
if (method2 !== "GET" || !(error instanceof NetworkApiError) || attempt2 >= GET_NETWORK_RETRY_DELAYS_MS.length) {
|
|
55192
|
+
if (init.signal?.aborted || method2 !== "GET" || !(error instanceof NetworkApiError) || attempt2 >= GET_NETWORK_RETRY_DELAYS_MS.length) {
|
|
55191
55193
|
throw error;
|
|
55192
55194
|
}
|
|
55193
55195
|
await new Promise((resolve) => setTimeout(resolve, GET_NETWORK_RETRY_DELAYS_MS[attempt2]));
|
|
@@ -55591,10 +55593,33 @@ async function connectionsRequest(pathname, init) {
|
|
|
55591
55593
|
throw err;
|
|
55592
55594
|
}
|
|
55593
55595
|
}
|
|
55596
|
+
async function mcpConnectLinkRequest(pathname, init) {
|
|
55597
|
+
try {
|
|
55598
|
+
return await request(pathname, init);
|
|
55599
|
+
} catch (err) {
|
|
55600
|
+
if (!(err instanceof ApiError))
|
|
55601
|
+
throw err;
|
|
55602
|
+
if (err.status === 404 && isUnroutedPath(err.body)) {
|
|
55603
|
+
throw new ApiError("This control plane does not support `brainbase mcp connect` yet. Update the server, or authorize the server in the web app.", 404, err.body);
|
|
55604
|
+
}
|
|
55605
|
+
const detail = err.body && typeof err.body === "object" ? err.body.detail : undefined;
|
|
55606
|
+
const message = detail && typeof detail === "object" && !Array.isArray(detail) ? detail.message : undefined;
|
|
55607
|
+
if (typeof message === "string" && message.trim()) {
|
|
55608
|
+
throw new ApiError(message.trim(), err.status, err.body);
|
|
55609
|
+
}
|
|
55610
|
+
throw err;
|
|
55611
|
+
}
|
|
55612
|
+
}
|
|
55594
55613
|
var api = {
|
|
55595
55614
|
listOrgs() {
|
|
55596
55615
|
return request("/orgs");
|
|
55597
55616
|
},
|
|
55617
|
+
listOrgMembersPage(orgId, cursor2) {
|
|
55618
|
+
const query = new URLSearchParams({ limit: "200" });
|
|
55619
|
+
if (cursor2)
|
|
55620
|
+
query.set("cursor", cursor2);
|
|
55621
|
+
return request(`/orgs/${encodeURIComponent(orgId)}/members?${query.toString()}`);
|
|
55622
|
+
},
|
|
55598
55623
|
listTeams(orgId) {
|
|
55599
55624
|
return request(`/orgs/${encodeURIComponent(orgId)}/teams`);
|
|
55600
55625
|
},
|
|
@@ -55736,6 +55761,12 @@ var api = {
|
|
|
55736
55761
|
listAgentMcpServers(agentId) {
|
|
55737
55762
|
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/mcp-servers`);
|
|
55738
55763
|
},
|
|
55764
|
+
createMcpConnectLink(agentId, server) {
|
|
55765
|
+
return mcpConnectLinkRequest(`/agents/${encodeURIComponent(agentId)}/mcp-connect-links`, { method: "POST", body: JSON.stringify({ server }) });
|
|
55766
|
+
},
|
|
55767
|
+
getMcpConnectLink(linkId, options = {}) {
|
|
55768
|
+
return mcpConnectLinkRequest(`/mcp-connect-links/${encodeURIComponent(linkId)}`, { signal: options.signal });
|
|
55769
|
+
},
|
|
55739
55770
|
listOrchestrations(orgId, teamId) {
|
|
55740
55771
|
return request(`/orgs/${encodeURIComponent(orgId)}/teams/${encodeURIComponent(teamId)}/orchestrations`);
|
|
55741
55772
|
},
|
|
@@ -62743,7 +62774,6 @@ function printSkillHelp() {
|
|
|
62743
62774
|
}
|
|
62744
62775
|
|
|
62745
62776
|
// src/cli/login.ts
|
|
62746
|
-
import { spawn } from "node:child_process";
|
|
62747
62777
|
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
62748
62778
|
|
|
62749
62779
|
// src/core/login-poll.ts
|
|
@@ -62920,6 +62950,22 @@ async function awaitDeviceSession(options) {
|
|
|
62920
62950
|
throw new LoginTimeoutError(timeoutMs, lastError);
|
|
62921
62951
|
}
|
|
62922
62952
|
|
|
62953
|
+
// src/core/open-browser.ts
|
|
62954
|
+
import { spawn } from "node:child_process";
|
|
62955
|
+
function openInBrowser(url) {
|
|
62956
|
+
if (process.env.BRAINBASE_NON_INTERACTIVE)
|
|
62957
|
+
return;
|
|
62958
|
+
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["rundll32.exe", ["url.dll,FileProtocolHandler", url]] : ["xdg-open", [url]];
|
|
62959
|
+
try {
|
|
62960
|
+
const child = spawn(cmd, args, {
|
|
62961
|
+
stdio: "ignore",
|
|
62962
|
+
detached: true
|
|
62963
|
+
});
|
|
62964
|
+
child.on("error", () => {});
|
|
62965
|
+
child.unref();
|
|
62966
|
+
} catch {}
|
|
62967
|
+
}
|
|
62968
|
+
|
|
62923
62969
|
// src/ui/ink/WelcomeCard.tsx
|
|
62924
62970
|
var jsx_dev_runtime14 = __toESM(require_jsx_dev_runtime(), 1);
|
|
62925
62971
|
function WelcomeCard(props) {
|
|
@@ -63013,19 +63059,6 @@ function isInsecureWebBase(webBase) {
|
|
|
63013
63059
|
return false;
|
|
63014
63060
|
return !["127.0.0.1", "localhost", "[::1]", "::1"].includes(url.hostname);
|
|
63015
63061
|
}
|
|
63016
|
-
function openInBrowser(url) {
|
|
63017
|
-
if (process.env.BRAINBASE_NON_INTERACTIVE)
|
|
63018
|
-
return;
|
|
63019
|
-
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["rundll32.exe", ["url.dll,FileProtocolHandler", url]] : ["xdg-open", [url]];
|
|
63020
|
-
try {
|
|
63021
|
-
const child = spawn(cmd, args, {
|
|
63022
|
-
stdio: "ignore",
|
|
63023
|
-
detached: true
|
|
63024
|
-
});
|
|
63025
|
-
child.on("error", () => {});
|
|
63026
|
-
child.unref();
|
|
63027
|
-
} catch {}
|
|
63028
|
-
}
|
|
63029
63062
|
function displayUserCode(code) {
|
|
63030
63063
|
return code.replace(/[^A-Za-z0-9-]/g, "");
|
|
63031
63064
|
}
|
|
@@ -72976,7 +73009,7 @@ function printTokenHelp() {
|
|
|
72976
73009
|
}
|
|
72977
73010
|
|
|
72978
73011
|
// src/cli/mcp.ts
|
|
72979
|
-
var
|
|
73012
|
+
var import_picocolors53 = __toESM(require_picocolors(), 1);
|
|
72980
73013
|
|
|
72981
73014
|
// src/core/mcp-check/collect-servers.ts
|
|
72982
73015
|
import path96 from "node:path";
|
|
@@ -81294,6 +81327,47 @@ function probeServer(server, opts = { timeoutMs: DEFAULT_TIMEOUT_MS }) {
|
|
|
81294
81327
|
return probeWithConnector(server, sdkConnector, opts);
|
|
81295
81328
|
}
|
|
81296
81329
|
|
|
81330
|
+
// src/ui/wait-spinner.ts
|
|
81331
|
+
var import_picocolors52 = __toESM(require_picocolors(), 1);
|
|
81332
|
+
function waitSpinner(output = process.stdout) {
|
|
81333
|
+
const unicode = process.platform !== "win32" ? process.env.TERM !== "linux" : Boolean(process.env.WT_SESSION) || process.env.TERM_PROGRAM === "vscode";
|
|
81334
|
+
const frames = unicode ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"];
|
|
81335
|
+
const delay2 = unicode ? 80 : 120;
|
|
81336
|
+
const bar = unicode ? "│" : "|";
|
|
81337
|
+
const symbols = unicode ? ["◇", "■", "▲"] : ["o", "x", "x"];
|
|
81338
|
+
const showCursor = () => output.write("\x1B[?25h");
|
|
81339
|
+
let timer;
|
|
81340
|
+
let message = "";
|
|
81341
|
+
return {
|
|
81342
|
+
start(text2) {
|
|
81343
|
+
message = text2.replace(/\.+$/, "");
|
|
81344
|
+
output.write(`${import_picocolors52.default.gray(bar)}
|
|
81345
|
+
\x1B[?25l`);
|
|
81346
|
+
process.once("exit", showCursor);
|
|
81347
|
+
let frame = 0;
|
|
81348
|
+
let dots = 0;
|
|
81349
|
+
const draw = () => {
|
|
81350
|
+
output.write(`\r\x1B[J${import_picocolors52.default.magenta(frames[frame])} ${message}${".".repeat(Math.floor(dots)).slice(0, 3)}`);
|
|
81351
|
+
frame = (frame + 1) % frames.length;
|
|
81352
|
+
dots = dots < frames.length ? dots + 0.125 : 0;
|
|
81353
|
+
};
|
|
81354
|
+
draw();
|
|
81355
|
+
timer = setInterval(draw, delay2);
|
|
81356
|
+
},
|
|
81357
|
+
stop(text2, code = 0) {
|
|
81358
|
+
if (timer === undefined)
|
|
81359
|
+
return;
|
|
81360
|
+
clearInterval(timer);
|
|
81361
|
+
timer = undefined;
|
|
81362
|
+
const symbol = code === 0 ? import_picocolors52.default.green(symbols[0]) : import_picocolors52.default.red(code === 1 ? symbols[1] : symbols[2]);
|
|
81363
|
+
output.write(`\r\x1B[J${symbol} ${text2}
|
|
81364
|
+
`);
|
|
81365
|
+
showCursor();
|
|
81366
|
+
process.removeListener("exit", showCursor);
|
|
81367
|
+
}
|
|
81368
|
+
};
|
|
81369
|
+
}
|
|
81370
|
+
|
|
81297
81371
|
// src/cli/mcp.ts
|
|
81298
81372
|
function timeoutMs(env3) {
|
|
81299
81373
|
const raw = env3.BRAINBASE_MCP_CHECK_TIMEOUT_MS;
|
|
@@ -81340,17 +81414,17 @@ async function runMcpCheck(cwd2, options) {
|
|
|
81340
81414
|
function renderHuman(report2) {
|
|
81341
81415
|
const lines = [];
|
|
81342
81416
|
if (report2.check_status === "skipped") {
|
|
81343
|
-
lines.push(
|
|
81417
|
+
lines.push(import_picocolors53.default.dim("No MCP servers configured — nothing to check."));
|
|
81344
81418
|
return lines.join(`
|
|
81345
81419
|
`) + `
|
|
81346
81420
|
`;
|
|
81347
81421
|
}
|
|
81348
81422
|
for (const s3 of report2.servers) {
|
|
81349
|
-
const mark = s3.status === "ok" ?
|
|
81350
|
-
const detail = s3.status === "ok" ?
|
|
81423
|
+
const mark = s3.status === "ok" ? import_picocolors53.default.green("✓") : s3.status === "auth_failed" ? import_picocolors53.default.red("✗") : import_picocolors53.default.yellow("⚠");
|
|
81424
|
+
const detail = s3.status === "ok" ? import_picocolors53.default.dim(`${s3.tool_count} tool${s3.tool_count === 1 ? "" : "s"}`) : import_picocolors53.default.dim(s3.status + (s3.error ? ` — ${s3.error}` : ""));
|
|
81351
81425
|
lines.push(` ${mark} ${s3.name} ${detail}`);
|
|
81352
81426
|
}
|
|
81353
|
-
const summary = report2.check_status === "ok" ?
|
|
81427
|
+
const summary = report2.check_status === "ok" ? import_picocolors53.default.green("All MCP servers connected.") : import_picocolors53.default.yellow("Some MCP servers are unhealthy.");
|
|
81354
81428
|
lines.push("", summary);
|
|
81355
81429
|
return lines.join(`
|
|
81356
81430
|
`) + `
|
|
@@ -81446,12 +81520,12 @@ function isUnhealthy(server) {
|
|
|
81446
81520
|
}
|
|
81447
81521
|
function renderServerList(servers) {
|
|
81448
81522
|
if (servers.length === 0) {
|
|
81449
|
-
return
|
|
81523
|
+
return import_picocolors53.default.dim("No MCP servers configured for this agent.") + `
|
|
81450
81524
|
`;
|
|
81451
81525
|
}
|
|
81452
81526
|
const lines = [""];
|
|
81453
81527
|
for (const s3 of servers) {
|
|
81454
|
-
const mark = s3.auth === "oauth_expired" ?
|
|
81528
|
+
const mark = s3.auth === "oauth_expired" ? import_picocolors53.default.red("✗") : s3.auth === "oauth_required" || isUnhealthy(s3) ? import_picocolors53.default.yellow("!") : !s3.is_enabled ? import_picocolors53.default.dim("·") : import_picocolors53.default.green("✓");
|
|
81455
81529
|
const bits = [sanitizeLabel(s3.transport)];
|
|
81456
81530
|
if (!s3.is_enabled)
|
|
81457
81531
|
bits.push("disabled");
|
|
@@ -81467,10 +81541,10 @@ function renderServerList(servers) {
|
|
|
81467
81541
|
const expiry = describeExpiry(s3);
|
|
81468
81542
|
if (expiry)
|
|
81469
81543
|
bits.push(expiry);
|
|
81470
|
-
lines.push(` ${mark} ${
|
|
81544
|
+
lines.push(` ${mark} ${import_picocolors53.default.bold(sanitizeLabel(s3.name))} ${import_picocolors53.default.dim(bits.join(" · "))}`);
|
|
81471
81545
|
}
|
|
81472
81546
|
if (servers.some((s3) => s3.auth === "oauth_required" || s3.auth === "oauth_expired")) {
|
|
81473
|
-
lines.push("",
|
|
81547
|
+
lines.push("", import_picocolors53.default.dim("Run `brainbase mcp connect <name>` to authorize a server."));
|
|
81474
81548
|
}
|
|
81475
81549
|
lines.push("");
|
|
81476
81550
|
return lines.join(`
|
|
@@ -81494,7 +81568,255 @@ function describeExpiry(server, now2 = Date.now()) {
|
|
|
81494
81568
|
const days = Math.round(hours / 24);
|
|
81495
81569
|
return days > MAX_EXPIRY_DAYS ? `expires in >${MAX_EXPIRY_DAYS}d` : `expires in ${days}d`;
|
|
81496
81570
|
}
|
|
81497
|
-
|
|
81571
|
+
var CONNECT_USAGE = `Usage: brainbase mcp connect <name> [--json] [--no-open] [--no-wait]
|
|
81572
|
+
`;
|
|
81573
|
+
var POLL_INTERVAL_MS = 1000;
|
|
81574
|
+
function connectUsageError(options) {
|
|
81575
|
+
if (options.json) {
|
|
81576
|
+
(options.write ?? ((s3) => process.stdout.write(s3)))(JSON.stringify({ error: CONNECT_USAGE.trim() }) + `
|
|
81577
|
+
`);
|
|
81578
|
+
} else {
|
|
81579
|
+
(options.writeErr ?? ((s3) => process.stderr.write(s3)))(CONNECT_USAGE);
|
|
81580
|
+
}
|
|
81581
|
+
return 1;
|
|
81582
|
+
}
|
|
81583
|
+
var MAX_CONSECUTIVE_POLL_FAILURES = 5;
|
|
81584
|
+
var WAITING_MESSAGE = "Waiting for you to approve in the browser (Ctrl-C to cancel)";
|
|
81585
|
+
async function runMcpConnect(cwd2, name, options) {
|
|
81586
|
+
const write = options.write ?? ((s3) => process.stdout.write(s3));
|
|
81587
|
+
const writeErr = options.writeErr ?? ((s3) => process.stderr.write(s3));
|
|
81588
|
+
const fetchServers = options.fetchServers ?? ((id) => api.listAgentMcpServers(id));
|
|
81589
|
+
const resolveAgentId = options.resolveAgentId ?? ((dir) => readLink(dir)?.agent_id ?? null);
|
|
81590
|
+
const createLink = options.createLink ?? ((id, server) => api.createMcpConnectLink(id, server));
|
|
81591
|
+
const getLink = options.getLink ?? ((id, signal2) => api.getMcpConnectLink(id, { signal: signal2 }));
|
|
81592
|
+
const openUrl = options.openUrl ?? openInBrowser;
|
|
81593
|
+
const interactive = options.interactive ?? isInteractive();
|
|
81594
|
+
const fail2 = (message) => {
|
|
81595
|
+
if (options.json)
|
|
81596
|
+
write(JSON.stringify({ error: message }) + `
|
|
81597
|
+
`);
|
|
81598
|
+
else
|
|
81599
|
+
writeErr(message + `
|
|
81600
|
+
`);
|
|
81601
|
+
return 1;
|
|
81602
|
+
};
|
|
81603
|
+
if (!name || name.startsWith("-"))
|
|
81604
|
+
return connectUsageError(options);
|
|
81605
|
+
const agentId = resolveAgentId(cwd2);
|
|
81606
|
+
if (!agentId) {
|
|
81607
|
+
return fail2("This folder is not linked to any agent. Run `brainbase link` first.");
|
|
81608
|
+
}
|
|
81609
|
+
let servers;
|
|
81610
|
+
try {
|
|
81611
|
+
servers = (await fetchServers(agentId)).servers;
|
|
81612
|
+
} catch (err) {
|
|
81613
|
+
return fail2(`brainbase mcp connect failed: ${sanitizeLabel(err.message)}`);
|
|
81614
|
+
}
|
|
81615
|
+
const label = sanitizeLabel(name);
|
|
81616
|
+
const matches2 = servers.filter((s3) => s3.name === name);
|
|
81617
|
+
const own = matches2.find((s3) => s3.source_kind !== "orchestration");
|
|
81618
|
+
if (!own) {
|
|
81619
|
+
const inherited = matches2[0];
|
|
81620
|
+
if (inherited) {
|
|
81621
|
+
const source = sanitizeLabel(String(inherited.source_name ?? inherited.source_id ?? "an orchestration"));
|
|
81622
|
+
return fail2(`${label} is inherited from ${source}. Connecting an orchestration's MCP server from the CLI is not supported yet; authorize it in the web app.`);
|
|
81623
|
+
}
|
|
81624
|
+
const known = [...new Set(servers.map((s3) => sanitizeLabel(s3.name)))];
|
|
81625
|
+
return fail2(known.length > 0 ? `No MCP server named "${label}" on this agent. Known servers: ${known.join(", ")}.` : `No MCP server named "${label}" on this agent. It has no MCP servers.`);
|
|
81626
|
+
}
|
|
81627
|
+
if (own.auth === "none")
|
|
81628
|
+
return fail2(`${label} does not use OAuth.`);
|
|
81629
|
+
let link2;
|
|
81630
|
+
try {
|
|
81631
|
+
link2 = await createLink(agentId, own.name);
|
|
81632
|
+
} catch (err) {
|
|
81633
|
+
return fail2(`Could not create a connect link for ${label}: ${sanitizeLabel(err.message)}`);
|
|
81634
|
+
}
|
|
81635
|
+
const url2 = safeLinkUrl(link2?.url);
|
|
81636
|
+
if (!url2 || typeof link2.link_id !== "string" || !link2.link_id) {
|
|
81637
|
+
return fail2("The server returned an unusable connect link.");
|
|
81638
|
+
}
|
|
81639
|
+
if (options.json) {
|
|
81640
|
+
write(JSON.stringify({
|
|
81641
|
+
link_id: link2.link_id,
|
|
81642
|
+
url: url2,
|
|
81643
|
+
expires_at: link2.expires_at,
|
|
81644
|
+
server: link2.server
|
|
81645
|
+
}) + `
|
|
81646
|
+
`);
|
|
81647
|
+
return 0;
|
|
81648
|
+
}
|
|
81649
|
+
write(`Open this link to authorize ${import_picocolors53.default.bold(label)}:
|
|
81650
|
+
|
|
81651
|
+
${import_picocolors53.default.cyan(url2)}
|
|
81652
|
+
|
|
81653
|
+
`);
|
|
81654
|
+
write(import_picocolors53.default.dim(`${describeLinkLifetime(link2.expires_at)}
|
|
81655
|
+
`));
|
|
81656
|
+
if (!options.noOpen && interactive) {
|
|
81657
|
+
write(import_picocolors53.default.dim(`Opening your browser…
|
|
81658
|
+
`));
|
|
81659
|
+
openUrl(url2);
|
|
81660
|
+
}
|
|
81661
|
+
if (options.noWait) {
|
|
81662
|
+
write(import_picocolors53.default.dim("Not waiting. Run `brainbase mcp list` to see when it is authorized.\n"));
|
|
81663
|
+
return 0;
|
|
81664
|
+
}
|
|
81665
|
+
const controller = new AbortController;
|
|
81666
|
+
const onInterrupt = () => controller.abort();
|
|
81667
|
+
const signal = options.signal ?? controller.signal;
|
|
81668
|
+
const stdoutIsTTY = options.stdoutIsTTY ?? process.stdout.isTTY === true;
|
|
81669
|
+
const spinner = interactive && stdoutIsTTY ? (options.spinner ?? (() => waitSpinner()))() : null;
|
|
81670
|
+
if (spinner)
|
|
81671
|
+
spinner.start(WAITING_MESSAGE);
|
|
81672
|
+
else
|
|
81673
|
+
write(`${WAITING_MESSAGE}
|
|
81674
|
+
`);
|
|
81675
|
+
if (!options.signal)
|
|
81676
|
+
process.on("SIGINT", onInterrupt);
|
|
81677
|
+
let outcome;
|
|
81678
|
+
try {
|
|
81679
|
+
outcome = await waitForConnectLink(link2.link_id, {
|
|
81680
|
+
getLink,
|
|
81681
|
+
intervalMs: options.pollIntervalMs ?? POLL_INTERVAL_MS,
|
|
81682
|
+
signal
|
|
81683
|
+
});
|
|
81684
|
+
} finally {
|
|
81685
|
+
if (!options.signal)
|
|
81686
|
+
process.removeListener("SIGINT", onInterrupt);
|
|
81687
|
+
}
|
|
81688
|
+
const finish = (ok, message) => {
|
|
81689
|
+
if (spinner) {
|
|
81690
|
+
spinner.stop(message, ok ? 0 : 2);
|
|
81691
|
+
} else if (ok) {
|
|
81692
|
+
write(`${import_picocolors53.default.green("✔")} ${message}
|
|
81693
|
+
`);
|
|
81694
|
+
} else {
|
|
81695
|
+
writeErr(`${message}
|
|
81696
|
+
`);
|
|
81697
|
+
}
|
|
81698
|
+
};
|
|
81699
|
+
switch (outcome.kind) {
|
|
81700
|
+
case "connected":
|
|
81701
|
+
finish(true, `${label} authorized. Your agent can use it on its next turn.`);
|
|
81702
|
+
return 0;
|
|
81703
|
+
case "failed":
|
|
81704
|
+
finish(false, describeConnectFailure(label, outcome.errorCode));
|
|
81705
|
+
return 1;
|
|
81706
|
+
case "expired":
|
|
81707
|
+
finish(false, `The link expired. Run brainbase mcp connect ${label} again.`);
|
|
81708
|
+
return 1;
|
|
81709
|
+
case "cancelled":
|
|
81710
|
+
spinner?.stop("Cancelled.", 1);
|
|
81711
|
+
writeErr(`Stopped waiting. The link still works until it expires, and finishing in the browser will still authorize ${label}.
|
|
81712
|
+
`);
|
|
81713
|
+
return 130;
|
|
81714
|
+
case "error":
|
|
81715
|
+
finish(false, sanitizeLabel(outcome.message));
|
|
81716
|
+
return 1;
|
|
81717
|
+
}
|
|
81718
|
+
}
|
|
81719
|
+
function safeLinkUrl(raw) {
|
|
81720
|
+
if (typeof raw !== "string")
|
|
81721
|
+
return null;
|
|
81722
|
+
let parsed;
|
|
81723
|
+
try {
|
|
81724
|
+
parsed = new URL(raw);
|
|
81725
|
+
} catch {
|
|
81726
|
+
return null;
|
|
81727
|
+
}
|
|
81728
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:")
|
|
81729
|
+
return null;
|
|
81730
|
+
return parsed.toString();
|
|
81731
|
+
}
|
|
81732
|
+
function describeLinkLifetime(expiresAt, now2 = Date.now()) {
|
|
81733
|
+
const at3 = expiresAt ? Date.parse(expiresAt) : NaN;
|
|
81734
|
+
const minutes = Math.round((at3 - now2) / 60000);
|
|
81735
|
+
if (!Number.isFinite(minutes) || minutes < 1 || minutes > 120) {
|
|
81736
|
+
return "The link works once.";
|
|
81737
|
+
}
|
|
81738
|
+
return `The link works once and expires in ${minutes} minute${minutes === 1 ? "" : "s"}.`;
|
|
81739
|
+
}
|
|
81740
|
+
function describeConnectFailure(label, errorCode) {
|
|
81741
|
+
switch (errorCode) {
|
|
81742
|
+
case "superseded":
|
|
81743
|
+
return `Another authorization for ${label} started, so this one was cancelled.`;
|
|
81744
|
+
case "access_denied":
|
|
81745
|
+
case "authorization_cancelled":
|
|
81746
|
+
return `Authorization for ${label} was declined in the browser. Run brainbase mcp connect ${label} to try again.`;
|
|
81747
|
+
default: {
|
|
81748
|
+
const code = errorCode ? ` (${sanitizeLabel(errorCode)})` : "";
|
|
81749
|
+
return `Authorization for ${label} did not complete${code}. Run brainbase mcp connect ${label} to try again.`;
|
|
81750
|
+
}
|
|
81751
|
+
}
|
|
81752
|
+
}
|
|
81753
|
+
function isTransientPollError(err) {
|
|
81754
|
+
if (!(err instanceof ApiError))
|
|
81755
|
+
return true;
|
|
81756
|
+
const status = err.status;
|
|
81757
|
+
return status === undefined || status >= 500 || status === 408 || status === 429;
|
|
81758
|
+
}
|
|
81759
|
+
function abortableSleep(ms2, signal) {
|
|
81760
|
+
return new Promise((resolve) => {
|
|
81761
|
+
if (signal.aborted)
|
|
81762
|
+
return resolve();
|
|
81763
|
+
const done = () => {
|
|
81764
|
+
clearTimeout(timer);
|
|
81765
|
+
signal.removeEventListener("abort", done);
|
|
81766
|
+
resolve();
|
|
81767
|
+
};
|
|
81768
|
+
const timer = setTimeout(done, ms2);
|
|
81769
|
+
signal.addEventListener("abort", done, { once: true });
|
|
81770
|
+
});
|
|
81771
|
+
}
|
|
81772
|
+
async function waitForConnectLink(linkId, options) {
|
|
81773
|
+
const { getLink, intervalMs, signal } = options;
|
|
81774
|
+
const maxFailures = options.maxConsecutiveFailures ?? MAX_CONSECUTIVE_POLL_FAILURES;
|
|
81775
|
+
const aborted2 = new Promise((resolve) => {
|
|
81776
|
+
if (signal.aborted)
|
|
81777
|
+
resolve("aborted");
|
|
81778
|
+
else
|
|
81779
|
+
signal.addEventListener("abort", () => resolve("aborted"), { once: true });
|
|
81780
|
+
});
|
|
81781
|
+
let failures = 0;
|
|
81782
|
+
while (true) {
|
|
81783
|
+
await abortableSleep(intervalMs, signal);
|
|
81784
|
+
if (signal.aborted)
|
|
81785
|
+
return { kind: "cancelled" };
|
|
81786
|
+
const result2 = await Promise.race([
|
|
81787
|
+
getLink(linkId, signal).then((state) => ({ ok: true, state }), (error2) => ({ ok: false, error: error2 })),
|
|
81788
|
+
aborted2
|
|
81789
|
+
]);
|
|
81790
|
+
if (result2 === "aborted")
|
|
81791
|
+
return { kind: "cancelled" };
|
|
81792
|
+
if (!result2.ok) {
|
|
81793
|
+
const message = result2.error?.message ?? String(result2.error);
|
|
81794
|
+
if (!isTransientPollError(result2.error)) {
|
|
81795
|
+
return { kind: "error", message: `Could not check the link: ${message}` };
|
|
81796
|
+
}
|
|
81797
|
+
failures += 1;
|
|
81798
|
+
if (failures >= maxFailures) {
|
|
81799
|
+
return {
|
|
81800
|
+
kind: "error",
|
|
81801
|
+
message: `Lost contact with Brainbase while waiting (${message}). If you finished in the browser, check with \`brainbase mcp list\`.`
|
|
81802
|
+
};
|
|
81803
|
+
}
|
|
81804
|
+
continue;
|
|
81805
|
+
}
|
|
81806
|
+
failures = 0;
|
|
81807
|
+
switch (result2.state?.status) {
|
|
81808
|
+
case "connected":
|
|
81809
|
+
return { kind: "connected" };
|
|
81810
|
+
case "failed":
|
|
81811
|
+
return { kind: "failed", errorCode: result2.state.error_code ?? null };
|
|
81812
|
+
case "expired":
|
|
81813
|
+
return { kind: "expired" };
|
|
81814
|
+
default:
|
|
81815
|
+
break;
|
|
81816
|
+
}
|
|
81817
|
+
}
|
|
81818
|
+
}
|
|
81819
|
+
async function runMcp(cwd2, sub, argv, options) {
|
|
81498
81820
|
const writeErr = options.writeErr ?? ((s3) => process.stderr.write(s3));
|
|
81499
81821
|
switch (sub) {
|
|
81500
81822
|
case "check": {
|
|
@@ -81503,20 +81825,25 @@ async function runMcp(cwd2, sub, _argv, options) {
|
|
|
81503
81825
|
}
|
|
81504
81826
|
case "list":
|
|
81505
81827
|
return runMcpList(cwd2, options);
|
|
81828
|
+
case "connect": {
|
|
81829
|
+
if (argv.length > 1)
|
|
81830
|
+
return connectUsageError(options);
|
|
81831
|
+
return runMcpConnect(cwd2, argv[0], options);
|
|
81832
|
+
}
|
|
81506
81833
|
default:
|
|
81507
81834
|
writeErr(`Unknown mcp subcommand: ${sub ?? "(none)"}
|
|
81508
81835
|
`);
|
|
81509
|
-
writeErr(`Usage: brainbase mcp <check|list
|
|
81836
|
+
writeErr(`Usage: brainbase mcp <check|list|connect <name>> [--json]
|
|
81510
81837
|
`);
|
|
81511
81838
|
return 1;
|
|
81512
81839
|
}
|
|
81513
81840
|
}
|
|
81514
81841
|
|
|
81515
81842
|
// src/cli/task.ts
|
|
81516
|
-
var
|
|
81843
|
+
var import_picocolors58 = __toESM(require_picocolors(), 1);
|
|
81517
81844
|
|
|
81518
81845
|
// src/cli/task-create.ts
|
|
81519
|
-
var
|
|
81846
|
+
var import_picocolors54 = __toESM(require_picocolors(), 1);
|
|
81520
81847
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
81521
81848
|
|
|
81522
81849
|
// src/core/interfaces-api.ts
|
|
@@ -81807,7 +82134,7 @@ var REASON_HINTS = {
|
|
|
81807
82134
|
build_already_live: "That build is already live.",
|
|
81808
82135
|
nothing_live: "Nothing is live yet, so there is nothing to roll back from.",
|
|
81809
82136
|
release_already_live: "That release is already live.",
|
|
81810
|
-
audience_empty: "Nobody can open it yet. Set the audience with `brainbase interface access <id> --everyone` or `--people <
|
|
82137
|
+
audience_empty: "Nobody can open it yet. Set the audience with `brainbase interface access <id> --everyone` or `--people <emails>`.",
|
|
81811
82138
|
slug_unavailable: "Pick another address."
|
|
81812
82139
|
};
|
|
81813
82140
|
function usesPat() {
|
|
@@ -82035,6 +82362,14 @@ var interfacesApi = {
|
|
|
82035
82362
|
},
|
|
82036
82363
|
getOperation(operationId, signal) {
|
|
82037
82364
|
return read(`/operations/${encodeURIComponent(operationId)}`, signal);
|
|
82365
|
+
},
|
|
82366
|
+
startPreview(taskId, interfaceId) {
|
|
82367
|
+
return write(`/tasks/${encodeURIComponent(taskId)}/interface-preview`, "POST", {
|
|
82368
|
+
interface_id: interfaceId
|
|
82369
|
+
});
|
|
82370
|
+
},
|
|
82371
|
+
probePreview(machineId, port, signal) {
|
|
82372
|
+
return read(`/machines/${encodeURIComponent(machineId)}/preview/probe?port=${encodeURIComponent(String(port))}`, signal);
|
|
82038
82373
|
}
|
|
82039
82374
|
};
|
|
82040
82375
|
function isTransientReadError(error2) {
|
|
@@ -82425,24 +82760,24 @@ async function waitForCreatedTask(created, options, dependencies) {
|
|
|
82425
82760
|
return;
|
|
82426
82761
|
}
|
|
82427
82762
|
if (outcome.kind === "timeout") {
|
|
82428
|
-
console.log(
|
|
82763
|
+
console.log(import_picocolors54.default.yellow(`Timed out after ${options.timeoutSeconds}s with the task still ${status}.`));
|
|
82429
82764
|
return;
|
|
82430
82765
|
}
|
|
82431
82766
|
if (outcome.kind === "interrupted") {
|
|
82432
|
-
console.log(
|
|
82767
|
+
console.log(import_picocolors54.default.yellow("Interrupted. The task is still running."));
|
|
82433
82768
|
return;
|
|
82434
82769
|
}
|
|
82435
|
-
console.log(code === 0 ?
|
|
82770
|
+
console.log(code === 0 ? import_picocolors54.default.green("Task completed.") : import_picocolors54.default.red(`Task finished as ${status}.`));
|
|
82436
82771
|
} finally {
|
|
82437
82772
|
process.removeListener("SIGINT", onSigint);
|
|
82438
82773
|
}
|
|
82439
82774
|
}
|
|
82440
82775
|
|
|
82441
82776
|
// src/cli/task-get.ts
|
|
82442
|
-
var
|
|
82777
|
+
var import_picocolors56 = __toESM(require_picocolors(), 1);
|
|
82443
82778
|
|
|
82444
82779
|
// src/cli/task-list.ts
|
|
82445
|
-
var
|
|
82780
|
+
var import_picocolors55 = __toESM(require_picocolors(), 1);
|
|
82446
82781
|
var INTERFACE_THREAD_METADATA_KEY = "brainbase_interface_id";
|
|
82447
82782
|
async function runTaskList(options) {
|
|
82448
82783
|
if (!options.json)
|
|
@@ -82462,23 +82797,23 @@ function formatTaskList(tasks, agentId, interfaceId) {
|
|
|
82462
82797
|
const lines = [""];
|
|
82463
82798
|
if (tasks.length === 0 && interfaceId) {
|
|
82464
82799
|
const id = sanitizeLabel(interfaceId);
|
|
82465
|
-
lines.push(` ${
|
|
82800
|
+
lines.push(` ${import_picocolors55.default.dim(`No build conversations for interface ${id}.`)}`, "", ` ${import_picocolors55.default.dim("start one with")} ${import_picocolors55.default.cyan(`brainbase interface build ${id} "..."`)}`, "");
|
|
82466
82801
|
return lines.join(`
|
|
82467
82802
|
`);
|
|
82468
82803
|
}
|
|
82469
82804
|
if (tasks.length === 0) {
|
|
82470
|
-
lines.push(` ${
|
|
82805
|
+
lines.push(` ${import_picocolors55.default.dim(agentId ? `No tasks for agent ${agentId}.` : "No tasks yet.")}`, "", ` ${import_picocolors55.default.dim("start one with")} ${import_picocolors55.default.cyan('brainbase task create --message "..."')}`, "");
|
|
82471
82806
|
return lines.join(`
|
|
82472
82807
|
`);
|
|
82473
82808
|
}
|
|
82474
82809
|
for (const task of tasks) {
|
|
82475
|
-
const title = sanitizeLabel(task.title ?? "").trim() ||
|
|
82476
|
-
lines.push(` ${statusLabel(task.status)} ${
|
|
82477
|
-
lines.push(` ${
|
|
82478
|
-
lines.push(` ${
|
|
82810
|
+
const title = sanitizeLabel(task.title ?? "").trim() || import_picocolors55.default.dim("(untitled)");
|
|
82811
|
+
lines.push(` ${statusLabel(task.status)} ${import_picocolors55.default.bold(title)}`);
|
|
82812
|
+
lines.push(` ${import_picocolors55.default.dim(task.id)}`);
|
|
82813
|
+
lines.push(` ${import_picocolors55.default.dim(`agent ${task.agent_id} · created ${task.created_at}`)}`);
|
|
82479
82814
|
lines.push("");
|
|
82480
82815
|
}
|
|
82481
|
-
lines.push(` ${
|
|
82816
|
+
lines.push(` ${import_picocolors55.default.dim("inspect one with")} ${import_picocolors55.default.cyan("brainbase task get <id>")}`, "");
|
|
82482
82817
|
return lines.join(`
|
|
82483
82818
|
`);
|
|
82484
82819
|
}
|
|
@@ -82486,16 +82821,16 @@ function statusLabel(status) {
|
|
|
82486
82821
|
const padded = status.padEnd(14);
|
|
82487
82822
|
switch (status) {
|
|
82488
82823
|
case "success":
|
|
82489
|
-
return
|
|
82824
|
+
return import_picocolors55.default.green(padded);
|
|
82490
82825
|
case "fail":
|
|
82491
|
-
return
|
|
82826
|
+
return import_picocolors55.default.red(padded);
|
|
82492
82827
|
case "need_more_info":
|
|
82493
|
-
return
|
|
82828
|
+
return import_picocolors55.default.yellow(padded);
|
|
82494
82829
|
case "running":
|
|
82495
82830
|
case "initializing":
|
|
82496
|
-
return
|
|
82831
|
+
return import_picocolors55.default.cyan(padded);
|
|
82497
82832
|
default:
|
|
82498
|
-
return
|
|
82833
|
+
return import_picocolors55.default.dim(padded);
|
|
82499
82834
|
}
|
|
82500
82835
|
}
|
|
82501
82836
|
|
|
@@ -82529,49 +82864,49 @@ async function readEvalRuns(task) {
|
|
|
82529
82864
|
}
|
|
82530
82865
|
function format(task, evals) {
|
|
82531
82866
|
const lines = [""];
|
|
82532
|
-
const title = task.title?.trim() ||
|
|
82533
|
-
lines.push(` ${statusLabel(task.status)} ${
|
|
82867
|
+
const title = task.title?.trim() || import_picocolors56.default.dim("(untitled)");
|
|
82868
|
+
lines.push(` ${statusLabel(task.status)} ${import_picocolors56.default.bold(title)}`);
|
|
82534
82869
|
lines.push("");
|
|
82535
|
-
lines.push(` ${
|
|
82536
|
-
lines.push(` ${
|
|
82537
|
-
lines.push(` ${
|
|
82870
|
+
lines.push(` ${import_picocolors56.default.dim("task")} ${task.id}`);
|
|
82871
|
+
lines.push(` ${import_picocolors56.default.dim("agent")} ${task.agent_id}`);
|
|
82872
|
+
lines.push(` ${import_picocolors56.default.dim("created")} ${task.created_at}`);
|
|
82538
82873
|
if (task.parent_task_id) {
|
|
82539
|
-
lines.push(` ${
|
|
82874
|
+
lines.push(` ${import_picocolors56.default.dim("parent")} ${task.parent_task_id}`);
|
|
82540
82875
|
}
|
|
82541
82876
|
if (task.machine_id) {
|
|
82542
|
-
lines.push(` ${
|
|
82877
|
+
lines.push(` ${import_picocolors56.default.dim("machine")} ${task.machine_id}${task.machine_size ? ` (${task.machine_size})` : ""}`);
|
|
82543
82878
|
}
|
|
82544
82879
|
if (task.sandbox_id)
|
|
82545
|
-
lines.push(` ${
|
|
82880
|
+
lines.push(` ${import_picocolors56.default.dim("sandbox")} ${task.sandbox_id}`);
|
|
82546
82881
|
const failure = failureSummary(task);
|
|
82547
82882
|
if (failure) {
|
|
82548
82883
|
lines.push("");
|
|
82549
|
-
lines.push(` ${
|
|
82884
|
+
lines.push(` ${import_picocolors56.default.red("failure")} ${failure}`);
|
|
82550
82885
|
}
|
|
82551
82886
|
const metadata = Object.entries(task.metadata ?? {});
|
|
82552
82887
|
if (metadata.length > 0) {
|
|
82553
82888
|
lines.push("");
|
|
82554
|
-
lines.push(` ${
|
|
82889
|
+
lines.push(` ${import_picocolors56.default.bold(import_picocolors56.default.dim("METADATA"))}`);
|
|
82555
82890
|
for (const [key2, value] of metadata) {
|
|
82556
|
-
lines.push(` ${
|
|
82891
|
+
lines.push(` ${import_picocolors56.default.dim(key2)} ${value}`);
|
|
82557
82892
|
}
|
|
82558
82893
|
}
|
|
82559
82894
|
lines.push("");
|
|
82560
|
-
lines.push(` ${
|
|
82895
|
+
lines.push(` ${import_picocolors56.default.bold(import_picocolors56.default.dim("EVAL VERDICTS"))}`);
|
|
82561
82896
|
if (evals.unavailable) {
|
|
82562
|
-
lines.push(` ${
|
|
82897
|
+
lines.push(` ${import_picocolors56.default.dim(evals.unavailable)}`);
|
|
82563
82898
|
} else if (evals.runs.length === 0) {
|
|
82564
|
-
lines.push(` ${
|
|
82899
|
+
lines.push(` ${import_picocolors56.default.dim("none")}`);
|
|
82565
82900
|
} else {
|
|
82566
82901
|
for (const run of evals.runs) {
|
|
82567
|
-
const verdict = run.passed === true ?
|
|
82902
|
+
const verdict = run.passed === true ? import_picocolors56.default.green("pass") : run.passed === false ? import_picocolors56.default.red("fail") : import_picocolors56.default.dim(run.status);
|
|
82568
82903
|
lines.push(` ${verdict} ${run.eval_slug ?? run.eval_id}`);
|
|
82569
82904
|
if (run.reasoning)
|
|
82570
|
-
lines.push(` ${
|
|
82905
|
+
lines.push(` ${import_picocolors56.default.dim(run.reasoning)}`);
|
|
82571
82906
|
}
|
|
82572
82907
|
}
|
|
82573
82908
|
lines.push("");
|
|
82574
|
-
lines.push(` ${
|
|
82909
|
+
lines.push(` ${import_picocolors56.default.dim("read its transcript with")} ${import_picocolors56.default.cyan(`brainbase task logs ${task.id}`)}`, "");
|
|
82575
82910
|
return lines.join(`
|
|
82576
82911
|
`);
|
|
82577
82912
|
}
|
|
@@ -82588,7 +82923,7 @@ function failureSummary(task) {
|
|
|
82588
82923
|
}
|
|
82589
82924
|
|
|
82590
82925
|
// src/cli/task-logs.ts
|
|
82591
|
-
var
|
|
82926
|
+
var import_picocolors57 = __toESM(require_picocolors(), 1);
|
|
82592
82927
|
|
|
82593
82928
|
// src/core/task-events.ts
|
|
82594
82929
|
var DEFAULT_RETRY_BUDGET_MS = 60000;
|
|
@@ -82724,14 +83059,14 @@ async function runTaskLogs(taskId, options = {}, dependencies = {}) {
|
|
|
82724
83059
|
console.log(renderEvent(event));
|
|
82725
83060
|
}
|
|
82726
83061
|
if (ordered.length === 0) {
|
|
82727
|
-
console.log(
|
|
83062
|
+
console.log(import_picocolors57.default.dim("No events for this task yet."));
|
|
82728
83063
|
}
|
|
82729
83064
|
}
|
|
82730
83065
|
async function followTranscript(taskId, options, dependencies) {
|
|
82731
83066
|
const backfill = options.limit === undefined ? "" : `?backfill=${options.limit}`;
|
|
82732
83067
|
const { url: url2, resolveBearer } = await masStreamTarget(`/tasks/${encodeURIComponent(taskId)}/events/stream${backfill}`);
|
|
82733
83068
|
if (!options.json) {
|
|
82734
|
-
console.log(
|
|
83069
|
+
console.log(import_picocolors57.default.dim(`Following task ${taskId} — Ctrl-C to stop.`));
|
|
82735
83070
|
}
|
|
82736
83071
|
const setExitCode = dependencies.setExitCode ?? ((code) => process.exitCode = code);
|
|
82737
83072
|
const controller = new AbortController;
|
|
@@ -82759,10 +83094,10 @@ async function followTranscript(taskId, options, dependencies) {
|
|
|
82759
83094
|
} else if (options.json) {
|
|
82760
83095
|
console.log(JSON.stringify(frame));
|
|
82761
83096
|
} else {
|
|
82762
|
-
console.log(
|
|
83097
|
+
console.log(import_picocolors57.default.dim(frame.type));
|
|
82763
83098
|
}
|
|
82764
83099
|
},
|
|
82765
|
-
onReconnect: (reason) => console.error(
|
|
83100
|
+
onReconnect: (reason) => console.error(import_picocolors57.default.dim(`reconnecting — ${reason}`))
|
|
82766
83101
|
});
|
|
82767
83102
|
if (interruptCode !== undefined)
|
|
82768
83103
|
setExitCode(interruptCode);
|
|
@@ -83446,64 +83781,64 @@ async function runTask(cwd2, sub, args) {
|
|
|
83446
83781
|
function printHelp4() {
|
|
83447
83782
|
const out = [];
|
|
83448
83783
|
out.push("");
|
|
83449
|
-
out.push(` ${
|
|
83784
|
+
out.push(` ${import_picocolors58.default.bold("brainbase task")} ${import_picocolors58.default.dim("<sub> [options]")}`);
|
|
83450
83785
|
out.push("");
|
|
83451
|
-
out.push(` ${
|
|
83452
|
-
out.push(` ${
|
|
83453
|
-
out.push(` ${
|
|
83454
|
-
out.push(` ${
|
|
83455
|
-
out.push(` ${
|
|
83456
|
-
out.push(` ${
|
|
83457
|
-
out.push(` ${
|
|
83786
|
+
out.push(` ${import_picocolors58.default.cyan("create")} ${import_picocolors58.default.dim("--message <text>")} ${import_picocolors58.default.dim("create a task and start its first run")}`);
|
|
83787
|
+
out.push(` ${import_picocolors58.default.cyan("list | ls")} ${import_picocolors58.default.dim("recent tasks you can reach (--json for scripts)")}`);
|
|
83788
|
+
out.push(` ${import_picocolors58.default.cyan("get")} ${import_picocolors58.default.dim("<task-id>")} ${import_picocolors58.default.dim("one task: status, agent, machine, eval verdicts")}`);
|
|
83789
|
+
out.push(` ${import_picocolors58.default.cyan("logs")} ${import_picocolors58.default.dim("<task-id> [--follow]")} ${import_picocolors58.default.dim("one line per event in the task's transcript, or tail it live")}`);
|
|
83790
|
+
out.push(` ${import_picocolors58.default.cyan("send")} ${import_picocolors58.default.dim("<task-id> <message>")} ${import_picocolors58.default.dim("send a follow-up, including while the agent is running")}`);
|
|
83791
|
+
out.push(` ${import_picocolors58.default.cyan("stop")} ${import_picocolors58.default.dim("<task-id>")} ${import_picocolors58.default.dim("stop execution and cancel pending follow-ups, retaining their text")}`);
|
|
83792
|
+
out.push(` ${import_picocolors58.default.cyan("delete")} ${import_picocolors58.default.dim("<task-id>")} ${import_picocolors58.default.dim("permanently delete a stopped task and tear down its sandbox (--yes to skip the prompt)")}`);
|
|
83458
83793
|
out.push("");
|
|
83459
|
-
out.push(` ${
|
|
83460
|
-
out.push(` ${
|
|
83461
|
-
out.push(` ${
|
|
83462
|
-
out.push(` ${
|
|
83463
|
-
out.push(` ${
|
|
83464
|
-
out.push(` ${
|
|
83465
|
-
out.push(` ${
|
|
83466
|
-
out.push(` ${
|
|
83794
|
+
out.push(` ${import_picocolors58.default.bold("create flags")}`);
|
|
83795
|
+
out.push(` ${import_picocolors58.default.dim("--message <text>")} required first user message`);
|
|
83796
|
+
out.push(` ${import_picocolors58.default.dim("--agent <id>")} override the claimed agent in brainbase.agent.yaml`);
|
|
83797
|
+
out.push(` ${import_picocolors58.default.dim("--interface <id>")} open it as a build conversation for this interface (agent defaults to the interface's)`);
|
|
83798
|
+
out.push(` ${import_picocolors58.default.dim("--title <text>")} optional task title`);
|
|
83799
|
+
out.push(` ${import_picocolors58.default.dim("--model <id>")} optional model override`);
|
|
83800
|
+
out.push(` ${import_picocolors58.default.dim("--wait")} block until the task finishes; exit 1 unless it succeeded`);
|
|
83801
|
+
out.push(` ${import_picocolors58.default.dim("--timeout <secs>")} give up waiting after <secs> and exit 1 (needs --wait)`);
|
|
83467
83802
|
out.push("");
|
|
83468
|
-
out.push(` ${
|
|
83469
|
-
out.push(` ${
|
|
83470
|
-
out.push(` ${
|
|
83471
|
-
out.push(` ${
|
|
83803
|
+
out.push(` ${import_picocolors58.default.bold("list flags")}`);
|
|
83804
|
+
out.push(` ${import_picocolors58.default.dim("--agent <id>")} only this agent's tasks`);
|
|
83805
|
+
out.push(` ${import_picocolors58.default.dim("--interface <id>")} only this interface's build conversations (hidden from a plain list)`);
|
|
83806
|
+
out.push(` ${import_picocolors58.default.dim("--limit <n>")} cap the page (1-200, server default 50)`);
|
|
83472
83807
|
out.push("");
|
|
83473
|
-
out.push(` ${
|
|
83474
|
-
out.push(` ${
|
|
83475
|
-
out.push(` ${
|
|
83808
|
+
out.push(` ${import_picocolors58.default.bold("logs flags")}`);
|
|
83809
|
+
out.push(` ${import_picocolors58.default.dim("--limit <n>")} stop after <n> events instead of the whole transcript; with --follow, the first page size`);
|
|
83810
|
+
out.push(` ${import_picocolors58.default.dim("--follow, -f")} stay attached and print events as they land, until the task finishes`);
|
|
83476
83811
|
out.push("");
|
|
83477
|
-
out.push(` ${
|
|
83478
|
-
out.push(` ${
|
|
83479
|
-
out.push(` ${
|
|
83480
|
-
out.push(` ${
|
|
83812
|
+
out.push(` ${import_picocolors58.default.bold("send flags")}`);
|
|
83813
|
+
out.push(` ${import_picocolors58.default.dim("--input-id <uuid>")} recover the same request using its original ID and identical message`);
|
|
83814
|
+
out.push(` ${import_picocolors58.default.dim(" omit it to send a new follow-up; an unconfirmed receipt is never automatically replayed")}`);
|
|
83815
|
+
out.push(` ${import_picocolors58.default.dim(" admission disabled/recovery unavailable means no input was admitted; retry the same ID after recovery")}`);
|
|
83481
83816
|
out.push("");
|
|
83482
|
-
out.push(` ${
|
|
83483
|
-
out.push(` ${
|
|
83484
|
-
out.push(` ${
|
|
83817
|
+
out.push(` ${import_picocolors58.default.bold("send and stop flags")}`);
|
|
83818
|
+
out.push(` ${import_picocolors58.default.dim("--generation <n>")} retain the printed generation when retrying; defaults to a fresh snapshot for a new operation`);
|
|
83819
|
+
out.push(` ${import_picocolors58.default.dim(" Stop errors may follow queued-input cancellation; retry the printed command to avoid stopping newer work")}`);
|
|
83485
83820
|
out.push("");
|
|
83486
|
-
out.push(` ${
|
|
83487
|
-
out.push(` ${
|
|
83488
|
-
out.push(` ${
|
|
83489
|
-
out.push(` ${
|
|
83821
|
+
out.push(` ${import_picocolors58.default.bold("every subcommand")}`);
|
|
83822
|
+
out.push(` ${import_picocolors58.default.dim("--json")} machine-readable output — create prints task_id, agent_id and status; list, get, logs, send and stop print the raw records; delete prints id and deleted`);
|
|
83823
|
+
out.push(` ${import_picocolors58.default.dim(" send and stop include expected_generation for safe retries; send also reports idempotency_replayed when present")}`);
|
|
83824
|
+
out.push(` ${import_picocolors58.default.dim(" logs --follow --json prints one record per line, since a live stream has no end to close on")}`);
|
|
83490
83825
|
out.push("");
|
|
83491
|
-
out.push(` ${
|
|
83492
|
-
out.push(` ${
|
|
83493
|
-
out.push(` ${
|
|
83494
|
-
out.push(` ${
|
|
83826
|
+
out.push(` ${import_picocolors58.default.dim("Exit codes with --wait:")} ${import_picocolors58.default.dim("0 succeeded · 1 failed, needs input, or timed out · 130 interrupted")}`);
|
|
83827
|
+
out.push(` ${import_picocolors58.default.dim("Exit codes with --follow:")} ${import_picocolors58.default.dim("0 task reached a terminal state · 1 stream refused, or unreachable for 60s · 130 interrupted (Ctrl-C) · 143 terminated")}`);
|
|
83828
|
+
out.push(` ${import_picocolors58.default.dim("Exit codes with send:")} ${import_picocolors58.default.dim("0 queued, dispatching, submitted or completed · 1 unconfirmed, cancelled, failed or request error")}`);
|
|
83829
|
+
out.push(` ${import_picocolors58.default.dim("Ctrl-C while waiting or following logs detaches; use task stop to cancel remote work.")}`);
|
|
83495
83830
|
out.push("");
|
|
83496
|
-
out.push(` ${
|
|
83831
|
+
out.push(` ${import_picocolors58.default.dim("Flag-like values:")} use ${import_picocolors58.default.cyan("--flag=value")} or ${import_picocolors58.default.cyan("--flag -- <value>")}`);
|
|
83497
83832
|
out.push("");
|
|
83498
83833
|
console.log(out.join(`
|
|
83499
83834
|
`));
|
|
83500
83835
|
}
|
|
83501
83836
|
|
|
83502
83837
|
// src/cli/machine.ts
|
|
83503
|
-
var
|
|
83838
|
+
var import_picocolors61 = __toESM(require_picocolors(), 1);
|
|
83504
83839
|
|
|
83505
83840
|
// src/cli/machine-list.ts
|
|
83506
|
-
var
|
|
83841
|
+
var import_picocolors59 = __toESM(require_picocolors(), 1);
|
|
83507
83842
|
async function runMachineList(args = {}) {
|
|
83508
83843
|
if (!args.json)
|
|
83509
83844
|
banner("machine list — sandboxes you can reach");
|
|
@@ -83520,7 +83855,7 @@ async function runMachineList(args = {}) {
|
|
|
83520
83855
|
function formatMachineList(machines, includedDead) {
|
|
83521
83856
|
const lines = [""];
|
|
83522
83857
|
if (machines.length === 0) {
|
|
83523
|
-
lines.push(` ${
|
|
83858
|
+
lines.push(` ${import_picocolors59.default.dim(includedDead ? "No machines." : "No live machines. Pass --all to include torn-down ones.")}`, "");
|
|
83524
83859
|
return lines.join(`
|
|
83525
83860
|
`);
|
|
83526
83861
|
}
|
|
@@ -83544,21 +83879,21 @@ function formatMachineList(machines, includedDead) {
|
|
|
83544
83879
|
row.kind.padEnd(kindWidth),
|
|
83545
83880
|
row.dead ? status : statusTint(row.status, status),
|
|
83546
83881
|
row.size.padEnd(sizeWidth),
|
|
83547
|
-
|
|
83882
|
+
import_picocolors59.default.dim(row.age)
|
|
83548
83883
|
].join(" ");
|
|
83549
|
-
lines.push(` ${row.dead ?
|
|
83884
|
+
lines.push(` ${row.dead ? import_picocolors59.default.dim(cells) : cells}`);
|
|
83550
83885
|
}
|
|
83551
|
-
lines.push("", ` ${
|
|
83886
|
+
lines.push("", ` ${import_picocolors59.default.dim("tear one down with")} ${import_picocolors59.default.cyan("brainbase machine rm <id>")}`, "");
|
|
83552
83887
|
return lines.join(`
|
|
83553
83888
|
`);
|
|
83554
83889
|
}
|
|
83555
83890
|
function statusTint(status, padded) {
|
|
83556
83891
|
switch (status) {
|
|
83557
83892
|
case "running":
|
|
83558
|
-
return
|
|
83893
|
+
return import_picocolors59.default.green(padded);
|
|
83559
83894
|
case "stopped":
|
|
83560
83895
|
case "starting":
|
|
83561
|
-
return
|
|
83896
|
+
return import_picocolors59.default.yellow(padded);
|
|
83562
83897
|
default:
|
|
83563
83898
|
return padded;
|
|
83564
83899
|
}
|
|
@@ -83581,7 +83916,7 @@ function age(createdAt) {
|
|
|
83581
83916
|
}
|
|
83582
83917
|
|
|
83583
83918
|
// src/cli/machine-rm.ts
|
|
83584
|
-
var
|
|
83919
|
+
var import_picocolors60 = __toESM(require_picocolors(), 1);
|
|
83585
83920
|
async function runMachineRm(args, dependencies = {}) {
|
|
83586
83921
|
const setExitCode = dependencies.setExitCode ?? ((code) => process.exitCode = code);
|
|
83587
83922
|
const machineId = args.machineId?.trim();
|
|
@@ -83595,7 +83930,7 @@ async function runMachineRm(args, dependencies = {}) {
|
|
|
83595
83930
|
if (args.json) {
|
|
83596
83931
|
console.log(JSON.stringify({ id: machineId, torn_down: false, outcome: "declined" }, null, 2));
|
|
83597
83932
|
} else {
|
|
83598
|
-
console.log(` ${
|
|
83933
|
+
console.log(` ${import_picocolors60.default.dim("Left alone.")}`);
|
|
83599
83934
|
}
|
|
83600
83935
|
return;
|
|
83601
83936
|
}
|
|
@@ -83613,7 +83948,7 @@ async function promptForTeardown(args) {
|
|
|
83613
83948
|
return true;
|
|
83614
83949
|
if (!args.json) {
|
|
83615
83950
|
console.log(`
|
|
83616
|
-
${
|
|
83951
|
+
${import_picocolors60.default.red("This destroys the sandbox.")} ${import_picocolors60.default.dim("Anything not committed out of it is lost. The machine row is kept for cost history.")}
|
|
83617
83952
|
`);
|
|
83618
83953
|
}
|
|
83619
83954
|
const answer = await se({
|
|
@@ -83625,9 +83960,9 @@ async function promptForTeardown(args) {
|
|
|
83625
83960
|
function formatMachineRm(machine) {
|
|
83626
83961
|
const lines = [""];
|
|
83627
83962
|
if (machine.destroyed_at) {
|
|
83628
|
-
lines.push(` ${
|
|
83963
|
+
lines.push(` ${import_picocolors60.default.green("✓")} ${machine.kind} sandbox ${machine.id} is torn down.`, ` ${import_picocolors60.default.dim(`destroyed_at ${machine.destroyed_at}`)}`);
|
|
83629
83964
|
} else {
|
|
83630
|
-
lines.push(` ${
|
|
83965
|
+
lines.push(` ${import_picocolors60.default.yellow("!")} ${machine.id} came back without a teardown timestamp (status ${machine.status}).`, ` ${import_picocolors60.default.dim("Re-check with `brainbase machine ls --all` before assuming it stopped billing.")}`);
|
|
83631
83966
|
}
|
|
83632
83967
|
lines.push("");
|
|
83633
83968
|
return lines.join(`
|
|
@@ -83668,28 +84003,28 @@ async function runMachine(sub, args, opts) {
|
|
|
83668
84003
|
function printHelp5() {
|
|
83669
84004
|
const out = [];
|
|
83670
84005
|
out.push("");
|
|
83671
|
-
out.push(` ${
|
|
84006
|
+
out.push(` ${import_picocolors61.default.bold("brainbase machine")} ${import_picocolors61.default.dim("<sub> [options]")}`);
|
|
83672
84007
|
out.push("");
|
|
83673
|
-
out.push(` ${
|
|
83674
|
-
out.push(` ${
|
|
84008
|
+
out.push(` ${import_picocolors61.default.cyan("ls")} ${import_picocolors61.default.dim("list your sandboxes — live ones only unless --all")}`);
|
|
84009
|
+
out.push(` ${import_picocolors61.default.cyan("rm")} ${import_picocolors61.default.dim("<id>")} ${import_picocolors61.default.dim("tear a sandbox down (terminal; the row is kept for cost history)")}`);
|
|
83675
84010
|
out.push("");
|
|
83676
|
-
out.push(` ${
|
|
83677
|
-
out.push(` ${
|
|
83678
|
-
out.push(` ${
|
|
83679
|
-
out.push(` ${
|
|
84011
|
+
out.push(` ${import_picocolors61.default.dim("--all")} ${import_picocolors61.default.dim("for ls: include machines already torn down")}`);
|
|
84012
|
+
out.push(` ${import_picocolors61.default.dim("--limit <n>")} ${import_picocolors61.default.dim("for ls: how many to fetch (1-200, default 50)")}`);
|
|
84013
|
+
out.push(` ${import_picocolors61.default.dim("--yes, -y")} ${import_picocolors61.default.dim("for rm: skip the confirmation")}`);
|
|
84014
|
+
out.push(` ${import_picocolors61.default.dim("--json")} ${import_picocolors61.default.dim("machine-readable output")}`);
|
|
83680
84015
|
out.push("");
|
|
83681
84016
|
console.log(out.join(`
|
|
83682
84017
|
`));
|
|
83683
84018
|
}
|
|
83684
84019
|
|
|
83685
84020
|
// src/cli/interface.ts
|
|
83686
|
-
var
|
|
84021
|
+
var import_picocolors68 = __toESM(require_picocolors(), 1);
|
|
83687
84022
|
|
|
83688
84023
|
// src/cli/interface-build.ts
|
|
83689
|
-
var
|
|
84024
|
+
var import_picocolors63 = __toESM(require_picocolors(), 1);
|
|
83690
84025
|
|
|
83691
84026
|
// src/cli/interface-common.ts
|
|
83692
|
-
var
|
|
84027
|
+
var import_picocolors62 = __toESM(require_picocolors(), 1);
|
|
83693
84028
|
var JSON_FLAG = { key: "json", names: ["--json"], kind: "boolean" };
|
|
83694
84029
|
var YES_FLAG = { key: "yes", names: ["--yes", "-y"], kind: "boolean" };
|
|
83695
84030
|
var KEY_FLAG = {
|
|
@@ -83751,7 +84086,7 @@ function progress(json) {
|
|
|
83751
84086
|
return json ? (line) => console.error(line) : (line) => console.log(line);
|
|
83752
84087
|
}
|
|
83753
84088
|
function field(label, value) {
|
|
83754
|
-
return ` ${
|
|
84089
|
+
return ` ${import_picocolors62.default.dim(label.padEnd(12))}${value}`;
|
|
83755
84090
|
}
|
|
83756
84091
|
function interruption(deps) {
|
|
83757
84092
|
if (deps.signal)
|
|
@@ -83785,7 +84120,7 @@ async function confirmChange(options) {
|
|
|
83785
84120
|
const confirm = options.deps.confirm ?? promptConfirm;
|
|
83786
84121
|
const accepted = await confirm(options.question);
|
|
83787
84122
|
if (!accepted)
|
|
83788
|
-
console.log(` ${
|
|
84123
|
+
console.log(` ${import_picocolors62.default.dim("Left alone.")}`);
|
|
83789
84124
|
return accepted;
|
|
83790
84125
|
}
|
|
83791
84126
|
async function promptConfirm(message) {
|
|
@@ -83927,28 +84262,28 @@ function buildExitCode(outcome) {
|
|
|
83927
84262
|
function reportBuild(say, interfaceId, outcome, timeoutSeconds) {
|
|
83928
84263
|
switch (outcome.kind) {
|
|
83929
84264
|
case "built":
|
|
83930
|
-
say(` ${
|
|
84265
|
+
say(` ${import_picocolors63.default.dim("build")} ${safe(outcome.build.id)} ${import_picocolors63.default.green("succeeded")}`);
|
|
83931
84266
|
say("");
|
|
83932
|
-
say(` ${
|
|
84267
|
+
say(` ${import_picocolors63.default.dim("Next:")} ${import_picocolors63.default.cyan(`brainbase interface publish ${safe(interfaceId)}`)}`);
|
|
83933
84268
|
return;
|
|
83934
84269
|
case "failed": {
|
|
83935
84270
|
const reason = outcome.build?.error_summary ?? outcome.operation?.error ?? outcome.operation?.reason ?? null;
|
|
83936
|
-
say(` ${
|
|
84271
|
+
say(` ${import_picocolors63.default.dim("build")} ${outcome.build ? safe(outcome.build.id) : import_picocolors63.default.dim("none")} ${import_picocolors63.default.red("failed")}`);
|
|
83937
84272
|
if (reason)
|
|
83938
84273
|
say(` ${safeBlock(reason).split(`
|
|
83939
84274
|
`).join(`
|
|
83940
84275
|
`)}`);
|
|
83941
|
-
say(` ${
|
|
84276
|
+
say(` ${import_picocolors63.default.dim("Try again with")} ${import_picocolors63.default.cyan(`brainbase interface rebuild ${safe(interfaceId)}`)}`);
|
|
83942
84277
|
return;
|
|
83943
84278
|
}
|
|
83944
84279
|
case "busy":
|
|
83945
|
-
say(` ${
|
|
84280
|
+
say(` ${import_picocolors63.default.yellow(safe(outcome.message))}`);
|
|
83946
84281
|
return;
|
|
83947
84282
|
case "timeout":
|
|
83948
|
-
say(` ${
|
|
84283
|
+
say(` ${import_picocolors63.default.yellow(`Still building after ${timeoutSeconds}s.`)} ${import_picocolors63.default.dim(`It keeps going; check \`brainbase interface builds ${safe(interfaceId)}\`.`)}`);
|
|
83949
84284
|
return;
|
|
83950
84285
|
case "interrupted":
|
|
83951
|
-
say(` ${
|
|
84286
|
+
say(` ${import_picocolors63.default.yellow("Stopped waiting.")} ${import_picocolors63.default.dim(`The build keeps going; check \`brainbase interface builds ${safe(interfaceId)}\`.`)}`);
|
|
83952
84287
|
return;
|
|
83953
84288
|
default: {
|
|
83954
84289
|
const unreachable = outcome;
|
|
@@ -83995,8 +84330,8 @@ async function build(ctx) {
|
|
|
83995
84330
|
throw held;
|
|
83996
84331
|
}
|
|
83997
84332
|
const reattach = `brainbase task logs ${safe(taskId)} --follow`;
|
|
83998
|
-
say(` ${
|
|
83999
|
-
say(` ${
|
|
84333
|
+
say(` ${import_picocolors63.default.dim("Build conversation")} ${import_picocolors63.default.bold(safe(taskId))} ${import_picocolors63.default.dim(`on ${safe(before2.name)}`)}`);
|
|
84334
|
+
say(` ${import_picocolors63.default.dim(`If this stops early, reattach with \`${reattach}\`.`)}`);
|
|
84000
84335
|
const finish = (result2, exitCode) => {
|
|
84001
84336
|
if (json)
|
|
84002
84337
|
console.log(JSON.stringify({ type: "result", task_id: taskId, ...result2 }));
|
|
@@ -84013,13 +84348,13 @@ async function build(ctx) {
|
|
|
84013
84348
|
});
|
|
84014
84349
|
} catch (error2) {
|
|
84015
84350
|
say("");
|
|
84016
|
-
say(` ${
|
|
84017
|
-
say(` ${
|
|
84351
|
+
say(` ${import_picocolors63.default.red(`Lost the conversation's event stream: ${safe(error2.message)}`)}`);
|
|
84352
|
+
say(` ${import_picocolors63.default.dim(`Conversation ${safe(taskId)} may still be running. Reattach with`)} ${import_picocolors63.default.cyan(reattach)}`);
|
|
84018
84353
|
finish({ version_id: null, build_id: null, status: "stream_lost", task_status: null }, 1);
|
|
84019
84354
|
return;
|
|
84020
84355
|
}
|
|
84021
84356
|
if (followExit !== undefined) {
|
|
84022
|
-
say(` ${
|
|
84357
|
+
say(` ${import_picocolors63.default.yellow("Stopped following.")} ${import_picocolors63.default.dim(`The conversation keeps running. Reattach with \`${reattach}\`.`)}`);
|
|
84023
84358
|
finish({ version_id: null, build_id: null, status: "interrupted", task_status: null }, followExit);
|
|
84024
84359
|
return;
|
|
84025
84360
|
}
|
|
@@ -84034,7 +84369,7 @@ async function build(ctx) {
|
|
|
84034
84369
|
if (settled.kind !== "terminal") {
|
|
84035
84370
|
const interrupted = settled.kind === "interrupted";
|
|
84036
84371
|
const status2 = settled.task?.status ?? null;
|
|
84037
|
-
say(` ${
|
|
84372
|
+
say(` ${import_picocolors63.default.yellow(interrupted ? "Stopped." : `The conversation is still ${safe(status2 ?? "running")}.`)} ${import_picocolors63.default.dim(`Check it with \`brainbase task get ${safe(taskId)}\`.`)}`);
|
|
84038
84373
|
finish({ version_id: null, build_id: null, status: interrupted ? "interrupted" : "task_unsettled", task_status: status2 }, interrupted ? SIGINT_EXIT_CODE : 1);
|
|
84039
84374
|
return;
|
|
84040
84375
|
}
|
|
@@ -84054,36 +84389,36 @@ async function build(ctx) {
|
|
|
84054
84389
|
}
|
|
84055
84390
|
const codes = [exitCodeForTaskStatus(task.status)];
|
|
84056
84391
|
say("");
|
|
84057
|
-
say(` ${
|
|
84392
|
+
say(` ${import_picocolors63.default.dim("conversation")} ${safe(taskId)} ${import_picocolors63.default.dim("ended")} ${safe(task.status)}`);
|
|
84058
84393
|
if (mine?.status === "failed") {
|
|
84059
84394
|
codes.push(1);
|
|
84060
84395
|
const why = [mine.reason, mine.error].filter(Boolean).map((part) => safe(part)).join(": ");
|
|
84061
|
-
say(` ${
|
|
84396
|
+
say(` ${import_picocolors63.default.red(`This conversation's build work failed${why ? ` (${why})` : ""}.`)}`);
|
|
84062
84397
|
} else if (task.status !== "success" && task.status !== "need_more_info") {
|
|
84063
|
-
say(` ${
|
|
84398
|
+
say(` ${import_picocolors63.default.red(`The conversation finished as ${safe(task.status)}.`)} ${import_picocolors63.default.dim(`See \`brainbase task logs ${safe(taskId)}\`.`)}`);
|
|
84064
84399
|
}
|
|
84065
84400
|
if (task.status === "need_more_info") {
|
|
84066
84401
|
const question = await lastAgentMessage(taskId);
|
|
84067
84402
|
say("");
|
|
84068
84403
|
if (question) {
|
|
84069
|
-
say(` ${
|
|
84404
|
+
say(` ${import_picocolors63.default.bold("The agent asks:")}`);
|
|
84070
84405
|
say(` ${safeBlock(question).split(`
|
|
84071
84406
|
`).join(`
|
|
84072
84407
|
`)}`);
|
|
84073
84408
|
} else {
|
|
84074
|
-
say(` ${
|
|
84409
|
+
say(` ${import_picocolors63.default.bold("The agent needs more from you before it can go on.")}`);
|
|
84075
84410
|
}
|
|
84076
84411
|
say("");
|
|
84077
|
-
say(` ${
|
|
84078
|
-
say(` ${
|
|
84412
|
+
say(` ${import_picocolors63.default.dim("Reply with")} ${import_picocolors63.default.cyan(`brainbase task send ${safe(taskId)} "<reply>"`)}`);
|
|
84413
|
+
say(` ${import_picocolors63.default.dim("then follow it with")} ${import_picocolors63.default.cyan(reattach)}`);
|
|
84079
84414
|
}
|
|
84080
84415
|
let status;
|
|
84081
84416
|
let buildId = null;
|
|
84082
84417
|
if (versionId) {
|
|
84083
84418
|
say("");
|
|
84084
|
-
say(` ${
|
|
84419
|
+
say(` ${import_picocolors63.default.dim("version")} ${safe(versionId)}`);
|
|
84085
84420
|
if (!json)
|
|
84086
|
-
say(` ${
|
|
84421
|
+
say(` ${import_picocolors63.default.dim("Waiting for its build...")}`);
|
|
84087
84422
|
const buildKey = `${key2}-build`;
|
|
84088
84423
|
let outcome;
|
|
84089
84424
|
try {
|
|
@@ -84093,7 +84428,7 @@ async function build(ctx) {
|
|
|
84093
84428
|
signal: stop.signal,
|
|
84094
84429
|
now: deps.now,
|
|
84095
84430
|
idempotencyKey: buildKey,
|
|
84096
|
-
onStall: () => say(` ${
|
|
84431
|
+
onStall: () => say(` ${import_picocolors63.default.yellow("The build looks stalled; still waiting in case another worker picks it up.")}`)
|
|
84097
84432
|
});
|
|
84098
84433
|
} catch (error2) {
|
|
84099
84434
|
if (error2 instanceof LostResponseError) {
|
|
@@ -84109,9 +84444,9 @@ async function build(ctx) {
|
|
|
84109
84444
|
status = noVersionStatus(mine?.status === "failed", task.status);
|
|
84110
84445
|
if (status === "no_version") {
|
|
84111
84446
|
codes.push(1);
|
|
84112
|
-
say(` ${
|
|
84447
|
+
say(` ${import_picocolors63.default.red("The conversation finished without committing a version, so there is nothing to build.")}`);
|
|
84113
84448
|
} else if (task.status !== "need_more_info") {
|
|
84114
|
-
say(` ${
|
|
84449
|
+
say(` ${import_picocolors63.default.dim("This conversation produced no version, so there is nothing to build.")}`);
|
|
84115
84450
|
}
|
|
84116
84451
|
}
|
|
84117
84452
|
if (!json)
|
|
@@ -84126,10 +84461,61 @@ async function build(ctx) {
|
|
|
84126
84461
|
var buildCommands = { build };
|
|
84127
84462
|
|
|
84128
84463
|
// src/cli/interface-lifecycle.ts
|
|
84129
|
-
var
|
|
84464
|
+
var import_picocolors65 = __toESM(require_picocolors(), 1);
|
|
84465
|
+
|
|
84466
|
+
// src/core/org-members.ts
|
|
84467
|
+
async function listAllOrgMembers(orgId) {
|
|
84468
|
+
const members = [];
|
|
84469
|
+
let cursor2;
|
|
84470
|
+
for (;; ) {
|
|
84471
|
+
let page;
|
|
84472
|
+
try {
|
|
84473
|
+
page = await api.listOrgMembersPage(orgId, cursor2);
|
|
84474
|
+
} catch (error2) {
|
|
84475
|
+
if (error2 instanceof ApiError && error2.status === 404) {
|
|
84476
|
+
throw new Error("This Brainbase server cannot list organization members, so people can only be named by user id.");
|
|
84477
|
+
}
|
|
84478
|
+
throw error2;
|
|
84479
|
+
}
|
|
84480
|
+
members.push(...page.members);
|
|
84481
|
+
if (!page.next_cursor)
|
|
84482
|
+
return members;
|
|
84483
|
+
if (page.next_cursor === cursor2) {
|
|
84484
|
+
throw new Error("Could not read the member list: the page cursor stopped advancing.");
|
|
84485
|
+
}
|
|
84486
|
+
cursor2 = page.next_cursor;
|
|
84487
|
+
}
|
|
84488
|
+
}
|
|
84489
|
+
function isEmail(entry) {
|
|
84490
|
+
return entry.includes("@");
|
|
84491
|
+
}
|
|
84492
|
+
function resolveEmails(entries, members, flag) {
|
|
84493
|
+
const ids = entries.map((entry) => {
|
|
84494
|
+
if (!isEmail(entry))
|
|
84495
|
+
return entry;
|
|
84496
|
+
const wanted = entry.toLowerCase();
|
|
84497
|
+
const matches2 = members.filter((member) => member.email?.toLowerCase() === wanted);
|
|
84498
|
+
if (matches2.length === 1)
|
|
84499
|
+
return matches2[0].id;
|
|
84500
|
+
if (matches2.length === 0) {
|
|
84501
|
+
throw new Error(`${flag}: nobody you can see in this organization has the email ${entry}. ` + "`brainbase member ls` lists the people you can share with.");
|
|
84502
|
+
}
|
|
84503
|
+
throw new Error(`${flag}: more than one member has the email ${entry} (${matches2.map((m3) => m3.id).join(", ")}). Pass the user id instead.`);
|
|
84504
|
+
});
|
|
84505
|
+
return [...new Set(ids)];
|
|
84506
|
+
}
|
|
84507
|
+
function personLabel(id, members) {
|
|
84508
|
+
const member = members?.get(id);
|
|
84509
|
+
if (!member?.email)
|
|
84510
|
+
return id;
|
|
84511
|
+
return member.name ? `${member.email} (${member.name})` : member.email;
|
|
84512
|
+
}
|
|
84513
|
+
function membersById(members) {
|
|
84514
|
+
return new Map(members.map((member) => [member.id, member]));
|
|
84515
|
+
}
|
|
84130
84516
|
|
|
84131
84517
|
// src/cli/interface-read.ts
|
|
84132
|
-
var
|
|
84518
|
+
var import_picocolors64 = __toESM(require_picocolors(), 1);
|
|
84133
84519
|
function interfaceState(row) {
|
|
84134
84520
|
if (row.archived_at)
|
|
84135
84521
|
return "archived";
|
|
@@ -84148,11 +84534,11 @@ function threadsLabel(shared) {
|
|
|
84148
84534
|
function stateTint(state) {
|
|
84149
84535
|
switch (state) {
|
|
84150
84536
|
case "live":
|
|
84151
|
-
return
|
|
84537
|
+
return import_picocolors64.default.green;
|
|
84152
84538
|
case "building":
|
|
84153
|
-
return
|
|
84539
|
+
return import_picocolors64.default.yellow;
|
|
84154
84540
|
case "archived":
|
|
84155
|
-
return
|
|
84541
|
+
return import_picocolors64.default.dim;
|
|
84156
84542
|
case "draft":
|
|
84157
84543
|
return (cell) => cell;
|
|
84158
84544
|
default: {
|
|
@@ -84185,7 +84571,7 @@ async function list(ctx) {
|
|
|
84185
84571
|
banner("interface list — dashboards you can see");
|
|
84186
84572
|
if (shown.length === 0) {
|
|
84187
84573
|
console.log(`
|
|
84188
|
-
${
|
|
84574
|
+
${import_picocolors64.default.dim(onlyArchived ? "No archived interfaces." : "No interfaces. Create one with `brainbase interface create`.")}
|
|
84189
84575
|
`);
|
|
84190
84576
|
return;
|
|
84191
84577
|
}
|
|
@@ -84198,7 +84584,7 @@ async function list(ctx) {
|
|
|
84198
84584
|
row.audience_mode === "org" ? "everyone" : "chosen",
|
|
84199
84585
|
ago(row.last_edited_at ?? row.created_at, now2)
|
|
84200
84586
|
]);
|
|
84201
|
-
console.log(["", ...table(cells, [null,
|
|
84587
|
+
console.log(["", ...table(cells, [null, import_picocolors64.default.bold, null, null, null, import_picocolors64.default.dim]), ""].join(`
|
|
84202
84588
|
`));
|
|
84203
84589
|
});
|
|
84204
84590
|
}
|
|
@@ -84219,13 +84605,13 @@ async function get2(ctx) {
|
|
|
84219
84605
|
out.push(field("id", safe(row.id)));
|
|
84220
84606
|
out.push(field("agent", safe(row.agent_id)));
|
|
84221
84607
|
out.push(field("state", stateTint(state)(state)));
|
|
84222
|
-
out.push(field("address", row.live_release ? safe(row.live_release.url) : `${safe(row.slug)} ${
|
|
84608
|
+
out.push(field("address", row.live_release ? safe(row.live_release.url) : `${safe(row.slug)} ${import_picocolors64.default.dim("(nothing live yet)")}`));
|
|
84223
84609
|
out.push(field("audience", audienceLabel(row)));
|
|
84224
84610
|
out.push(field("threads", threadsLabel(row.share_agent_threads)));
|
|
84225
|
-
out.push(field("live", row.live_release ? `${safe(row.live_release.id)} ${
|
|
84226
|
-
out.push(field("draft", row.draft_version_id ? safe(row.draft_version_id) :
|
|
84611
|
+
out.push(field("live", row.live_release ? `${safe(row.live_release.id)} ${import_picocolors64.default.dim(`published ${ago(row.live_release.published_at)}`)}` : import_picocolors64.default.dim("none")));
|
|
84612
|
+
out.push(field("draft", row.draft_version_id ? safe(row.draft_version_id) : import_picocolors64.default.dim("none yet")));
|
|
84227
84613
|
if (row.running_generation) {
|
|
84228
|
-
out.push(field("building", `conversation ${safe(row.running_generation.thread_id ?? "")} ${
|
|
84614
|
+
out.push(field("building", `conversation ${safe(row.running_generation.thread_id ?? "")} ${import_picocolors64.default.dim(`(follow it with \`brainbase task logs ${safe(row.running_generation.thread_id ?? "")} --follow\`)`)}`));
|
|
84229
84615
|
}
|
|
84230
84616
|
if (row.archived_at)
|
|
84231
84617
|
out.push(field("archived", ago(row.archived_at)));
|
|
@@ -84254,7 +84640,7 @@ async function open(ctx) {
|
|
|
84254
84640
|
}
|
|
84255
84641
|
console.log(safe(url2));
|
|
84256
84642
|
if (new URL(url2).hostname.endsWith("vercel.app")) {
|
|
84257
|
-
console.error(
|
|
84643
|
+
console.error(import_picocolors64.default.yellow("This is the raw Vercel deployment address, which sits behind Vercel protection and will not open for viewers. The control plane has no public interfaces domain configured."));
|
|
84258
84644
|
}
|
|
84259
84645
|
});
|
|
84260
84646
|
}
|
|
@@ -84292,7 +84678,7 @@ async function history(ctx, name) {
|
|
|
84292
84678
|
banner(`interface ${name} — ${safe(id)}`);
|
|
84293
84679
|
if (rows.length === 0) {
|
|
84294
84680
|
console.log(`
|
|
84295
|
-
${
|
|
84681
|
+
${import_picocolors64.default.dim(`No ${name} yet.`)}
|
|
84296
84682
|
`);
|
|
84297
84683
|
return;
|
|
84298
84684
|
}
|
|
@@ -84318,7 +84704,7 @@ function sessionUserId() {
|
|
|
84318
84704
|
function parseIds(raw, flag) {
|
|
84319
84705
|
const ids = [...new Set(raw.split(",").map((id) => id.trim()).filter(Boolean))];
|
|
84320
84706
|
if (ids.length === 0)
|
|
84321
|
-
throw new Error(`${flag} takes user ids separated by commas, or \`me\`.`);
|
|
84707
|
+
throw new Error(`${flag} takes emails or user ids separated by commas, or \`me\`.`);
|
|
84322
84708
|
return ids;
|
|
84323
84709
|
}
|
|
84324
84710
|
function withMe(ids, self) {
|
|
@@ -84336,6 +84722,30 @@ function resolveMeForAccess(ids, flag) {
|
|
|
84336
84722
|
function grantIds(access) {
|
|
84337
84723
|
return access.grants.map((grant) => grant.subject_id);
|
|
84338
84724
|
}
|
|
84725
|
+
async function resolvePeople(entries, orgId, flag) {
|
|
84726
|
+
if (!entries.some(isEmail))
|
|
84727
|
+
return { ids: entries, members: null };
|
|
84728
|
+
const members = await listAllOrgMembers(await orgId());
|
|
84729
|
+
return { ids: resolveEmails(entries, members, flag), members: membersById(members) };
|
|
84730
|
+
}
|
|
84731
|
+
async function membersForDisplay(orgId, known) {
|
|
84732
|
+
if (known)
|
|
84733
|
+
return known;
|
|
84734
|
+
try {
|
|
84735
|
+
return membersById(await listAllOrgMembers(orgId));
|
|
84736
|
+
} catch {
|
|
84737
|
+
return null;
|
|
84738
|
+
}
|
|
84739
|
+
}
|
|
84740
|
+
function peopleJson(access, members) {
|
|
84741
|
+
return grantIds(access).map((id) => {
|
|
84742
|
+
const member = members?.get(id);
|
|
84743
|
+
return { id, email: member?.email ?? null, name: member?.name ?? null };
|
|
84744
|
+
});
|
|
84745
|
+
}
|
|
84746
|
+
function namesOf(ids, members) {
|
|
84747
|
+
return ids.map((id) => safe(personLabel(id, members))).join(", ");
|
|
84748
|
+
}
|
|
84339
84749
|
function exactlyOne(parsed, flags) {
|
|
84340
84750
|
const given = flags.filter(([key2]) => parsed.options[key2] !== undefined && parsed.options[key2] !== false);
|
|
84341
84751
|
if (given.length > 1) {
|
|
@@ -84343,15 +84753,15 @@ function exactlyOne(parsed, flags) {
|
|
|
84343
84753
|
}
|
|
84344
84754
|
return given[0]?.[0] ?? null;
|
|
84345
84755
|
}
|
|
84346
|
-
function peopleLine(access) {
|
|
84756
|
+
function peopleLine(access, members) {
|
|
84347
84757
|
const ids = grantIds(access);
|
|
84348
|
-
return ids.length ? ids
|
|
84758
|
+
return ids.length ? namesOf(ids, members) : import_picocolors65.default.dim("nobody named");
|
|
84349
84759
|
}
|
|
84350
|
-
function printAccess(row, access) {
|
|
84760
|
+
function printAccess(row, access, members) {
|
|
84351
84761
|
console.log([
|
|
84352
84762
|
"",
|
|
84353
84763
|
field("audience", audienceLabel(access)),
|
|
84354
|
-
field("people", peopleLine(access)),
|
|
84764
|
+
field("people", peopleLine(access, members)),
|
|
84355
84765
|
field("threads", threadsLabel(row.share_agent_threads)),
|
|
84356
84766
|
""
|
|
84357
84767
|
].join(`
|
|
@@ -84385,6 +84795,12 @@ async function create3(ctx) {
|
|
|
84385
84795
|
const self = sessionUserId();
|
|
84386
84796
|
if (audience && self)
|
|
84387
84797
|
audience.ids = withMe(audience.ids, self);
|
|
84798
|
+
let members = null;
|
|
84799
|
+
if (audience) {
|
|
84800
|
+
const resolved = await resolvePeople(audience.ids, async () => (await api.getAgent(agentId)).org_id, "--people");
|
|
84801
|
+
audience.ids = resolved.ids;
|
|
84802
|
+
members = resolved.members;
|
|
84803
|
+
}
|
|
84388
84804
|
const replayKey = stringOption(parsed, "idempotencyKey")?.trim();
|
|
84389
84805
|
const created = await interfacesApi.create({ agentId, name, slug: stringOption(parsed, "address")?.trim() || undefined }, { idempotencyKey: replayKey || newIdempotencyKey() });
|
|
84390
84806
|
let access = null;
|
|
@@ -84418,10 +84834,13 @@ async function create3(ctx) {
|
|
|
84418
84834
|
accessError = error2;
|
|
84419
84835
|
}
|
|
84420
84836
|
}
|
|
84837
|
+
if (access?.audience_mode === "users")
|
|
84838
|
+
members = await membersForDisplay(created.team_id, members);
|
|
84421
84839
|
if (json) {
|
|
84422
84840
|
printJson({
|
|
84423
84841
|
interface: created,
|
|
84424
84842
|
access,
|
|
84843
|
+
...access ? { people: peopleJson(access, members) } : {},
|
|
84425
84844
|
...note ? { note } : {},
|
|
84426
84845
|
...accessError ? { error: errorShape(accessError) } : {}
|
|
84427
84846
|
});
|
|
@@ -84432,27 +84851,27 @@ async function create3(ctx) {
|
|
|
84432
84851
|
const id = safe(created.id);
|
|
84433
84852
|
const out = [
|
|
84434
84853
|
"",
|
|
84435
|
-
` ${
|
|
84854
|
+
` ${import_picocolors65.default.green("Created")} ${import_picocolors65.default.bold(safe(created.name))}`,
|
|
84436
84855
|
"",
|
|
84437
84856
|
field("id", id),
|
|
84438
84857
|
field("agent", safe(created.agent_id)),
|
|
84439
|
-
field("address", `${safe(created.slug)} ${
|
|
84858
|
+
field("address", `${safe(created.slug)} ${import_picocolors65.default.dim("(nothing live yet)")}`),
|
|
84440
84859
|
field("threads", threadsLabel(created.share_agent_threads))
|
|
84441
84860
|
];
|
|
84442
84861
|
if (access) {
|
|
84443
84862
|
out.push(field("audience", audienceLabel(access)));
|
|
84444
84863
|
if (access.audience_mode === "users")
|
|
84445
|
-
out.push(field("people", peopleLine(access)));
|
|
84864
|
+
out.push(field("people", peopleLine(access, members)));
|
|
84446
84865
|
}
|
|
84447
84866
|
if (!audience) {
|
|
84448
|
-
out.push("", ` Nobody can open it until you choose who can: \`brainbase interface access ${id} --everyone\` or \`--people <
|
|
84867
|
+
out.push("", ` Nobody can open it until you choose who can: \`brainbase interface access ${id} --everyone\` or \`--people <emails>\`.`);
|
|
84449
84868
|
}
|
|
84450
84869
|
if (created.share_agent_threads) {
|
|
84451
|
-
out.push(` ${
|
|
84870
|
+
out.push(` ${import_picocolors65.default.dim(`To show viewers only their own conversations: \`brainbase interface threads ${id} --private\`.`)}`);
|
|
84452
84871
|
}
|
|
84453
84872
|
if (note)
|
|
84454
84873
|
out.push("", ` ${safe(note)}`);
|
|
84455
|
-
out.push("", ` ${
|
|
84874
|
+
out.push("", ` ${import_picocolors65.default.dim(`Next: \`brainbase interface build ${id} "<what to build>"\``)}`, "");
|
|
84456
84875
|
console.log(out.join(`
|
|
84457
84876
|
`));
|
|
84458
84877
|
if (readFailed) {
|
|
@@ -84460,7 +84879,7 @@ async function create3(ctx) {
|
|
|
84460
84879
|
} else if (accessError && isUnanswered(accessError)) {
|
|
84461
84880
|
fail(`Created ${id}, but the answer to setting who can open it was lost, so whether it was saved could not be confirmed. ` + `Check with \`brainbase interface access ${id}\`.`);
|
|
84462
84881
|
} else if (accessError) {
|
|
84463
|
-
fail(`Created ${id}, but setting who can open it failed, so nobody can open it yet: ${safe(errorShape(accessError).message)} ` + `Set it with \`brainbase interface access ${id} --everyone\` or \`--people <
|
|
84882
|
+
fail(`Created ${id}, but setting who can open it failed, so nobody can open it yet: ${safe(errorShape(accessError).message)} ` + `Set it with \`brainbase interface access ${id} --everyone\` or \`--people <emails>\`.`);
|
|
84464
84883
|
}
|
|
84465
84884
|
});
|
|
84466
84885
|
}
|
|
@@ -84479,27 +84898,36 @@ async function access(ctx) {
|
|
|
84479
84898
|
{ key: "remove", names: ["--remove"], kind: "value" }
|
|
84480
84899
|
]);
|
|
84481
84900
|
json = booleanOption(parsed, "json");
|
|
84482
|
-
const [id] = expectPositionals(parsed, ["id"], "brainbase interface access <id> [--everyone | --people <
|
|
84901
|
+
const [id] = expectPositionals(parsed, ["id"], "brainbase interface access <id> [--everyone | --people <emails> | --add <emails> | --remove <emails>]");
|
|
84483
84902
|
const change = exactlyOne(parsed, [
|
|
84484
84903
|
["everyone", "--everyone"],
|
|
84485
84904
|
["people", "--people"],
|
|
84486
84905
|
["add", "--add"],
|
|
84487
84906
|
["remove", "--remove"]
|
|
84488
84907
|
]);
|
|
84489
|
-
const
|
|
84908
|
+
const entries = change && change !== "everyone" ? resolveMeForAccess(parseIds(stringOption(parsed, change) ?? "", `--${change}`), `--${change}`) : [];
|
|
84490
84909
|
if (!change) {
|
|
84491
84910
|
const [row2, current2] = await Promise.all([interfacesApi.get(id), interfacesApi.getAccess(id)]);
|
|
84911
|
+
const members2 = current2.grants.length ? await membersForDisplay(row2.team_id, null) : null;
|
|
84492
84912
|
if (json) {
|
|
84493
|
-
printJson({
|
|
84913
|
+
printJson({
|
|
84914
|
+
id: row2.id,
|
|
84915
|
+
...current2,
|
|
84916
|
+
people: peopleJson(current2, members2),
|
|
84917
|
+
share_agent_threads: row2.share_agent_threads
|
|
84918
|
+
});
|
|
84494
84919
|
return;
|
|
84495
84920
|
}
|
|
84496
|
-
printAccess(row2, current2);
|
|
84921
|
+
printAccess(row2, current2, members2);
|
|
84497
84922
|
return;
|
|
84498
84923
|
}
|
|
84499
84924
|
const [row, current] = await Promise.all([
|
|
84500
84925
|
interfacesApi.get(id),
|
|
84501
84926
|
change === "add" || change === "remove" ? interfacesApi.getAccess(id) : null
|
|
84502
84927
|
]);
|
|
84928
|
+
const resolved = await resolvePeople(entries, async () => row.team_id, `--${change}`);
|
|
84929
|
+
const ids = resolved.ids;
|
|
84930
|
+
let members = resolved.members;
|
|
84503
84931
|
const label = safe(row.name);
|
|
84504
84932
|
let summary;
|
|
84505
84933
|
switch (change) {
|
|
@@ -84507,13 +84935,13 @@ async function access(ctx) {
|
|
|
84507
84935
|
summary = `Everyone in the organisation will be able to open ${label}.`;
|
|
84508
84936
|
break;
|
|
84509
84937
|
case "people":
|
|
84510
|
-
summary = `Only these people will be able to open ${label}: ${ids
|
|
84938
|
+
summary = `Only these people will be able to open ${label}: ${namesOf(ids, members)}.`;
|
|
84511
84939
|
break;
|
|
84512
84940
|
case "add":
|
|
84513
|
-
summary = `${ids
|
|
84941
|
+
summary = `${namesOf(ids, members)} will be able to open ${label}.`;
|
|
84514
84942
|
break;
|
|
84515
84943
|
case "remove":
|
|
84516
|
-
summary = `${ids
|
|
84944
|
+
summary = `${namesOf(ids, members)} will no longer be able to open ${label}.`;
|
|
84517
84945
|
break;
|
|
84518
84946
|
default: {
|
|
84519
84947
|
const unreachable = change;
|
|
@@ -84548,11 +84976,13 @@ async function access(ctx) {
|
|
|
84548
84976
|
saved = await interfacesApi.setAccess(id, "users", fresh.filter((subject) => !ids.includes(subject)));
|
|
84549
84977
|
}
|
|
84550
84978
|
}
|
|
84979
|
+
if (saved.grants.length)
|
|
84980
|
+
members = await membersForDisplay(row.team_id, members);
|
|
84551
84981
|
if (json) {
|
|
84552
|
-
printJson(saved);
|
|
84982
|
+
printJson({ ...saved, people: peopleJson(saved, members) });
|
|
84553
84983
|
return;
|
|
84554
84984
|
}
|
|
84555
|
-
printAccess(row, saved);
|
|
84985
|
+
printAccess(row, saved, members);
|
|
84556
84986
|
});
|
|
84557
84987
|
}
|
|
84558
84988
|
async function threads(ctx) {
|
|
@@ -84577,7 +85007,7 @@ async function threads(ctx) {
|
|
|
84577
85007
|
printJson({ id: row.id, share_agent_threads: row.share_agent_threads });
|
|
84578
85008
|
return;
|
|
84579
85009
|
}
|
|
84580
|
-
const already = wanted === null ? "" : ` ${
|
|
85010
|
+
const already = wanted === null ? "" : ` ${import_picocolors65.default.dim("(already set; nothing changed)")}`;
|
|
84581
85011
|
console.log(`
|
|
84582
85012
|
${field("threads", `${threadsLabel(row.share_agent_threads)}${already}`)}
|
|
84583
85013
|
`);
|
|
@@ -84616,7 +85046,7 @@ async function rename(ctx) {
|
|
|
84616
85046
|
return;
|
|
84617
85047
|
}
|
|
84618
85048
|
console.log(`
|
|
84619
|
-
Renamed ${safe(updated.id)} to ${
|
|
85049
|
+
Renamed ${safe(updated.id)} to ${import_picocolors65.default.bold(safe(updated.name))}.
|
|
84620
85050
|
`);
|
|
84621
85051
|
});
|
|
84622
85052
|
}
|
|
@@ -84652,7 +85082,7 @@ async function address(ctx) {
|
|
|
84652
85082
|
}
|
|
84653
85083
|
const where = updated.live_release ? safe(updated.live_release.url) : safe(updated.slug);
|
|
84654
85084
|
console.log(`
|
|
84655
|
-
${safe(updated.name)} is now at ${
|
|
85085
|
+
${safe(updated.name)} is now at ${import_picocolors65.default.bold(where)}.
|
|
84656
85086
|
`);
|
|
84657
85087
|
});
|
|
84658
85088
|
}
|
|
@@ -84743,14 +85173,145 @@ var lifecycleCommands = {
|
|
|
84743
85173
|
unarchive
|
|
84744
85174
|
};
|
|
84745
85175
|
|
|
85176
|
+
// src/cli/interface-preview.ts
|
|
85177
|
+
var import_picocolors66 = __toESM(require_picocolors(), 1);
|
|
85178
|
+
function warn(line) {
|
|
85179
|
+
console.error(import_picocolors66.default.yellow(line));
|
|
85180
|
+
}
|
|
85181
|
+
var PREVIEW_TIMEOUT_SECONDS = 300;
|
|
85182
|
+
var PROBE_INTERVAL_MS = 2000;
|
|
85183
|
+
async function pickConversation(row, named) {
|
|
85184
|
+
if (named)
|
|
85185
|
+
return { taskId: named, why: "the conversation you named" };
|
|
85186
|
+
const running = row.running_generation?.thread_id;
|
|
85187
|
+
if (running)
|
|
85188
|
+
return { taskId: running, why: "the build conversation running now" };
|
|
85189
|
+
const tasks = await masApi.listTasks({ metadata: { [INTERFACE_THREAD_METADATA_KEY]: row.id }, limit: 200 });
|
|
85190
|
+
const newest = [...tasks].sort((a3, b4) => Date.parse(b4.created_at) - Date.parse(a3.created_at))[0];
|
|
85191
|
+
if (!newest) {
|
|
85192
|
+
throw new Error(`No build conversation has been opened for ${safe(row.name)} yet, so there is nothing to preview. ` + `Start one with \`brainbase interface build ${safe(row.id)} "<what to build>"\`.`);
|
|
85193
|
+
}
|
|
85194
|
+
return { taskId: newest.id, why: "the most recent build conversation" };
|
|
85195
|
+
}
|
|
85196
|
+
function previewAddress(started, row) {
|
|
85197
|
+
if (started.preview_url !== undefined)
|
|
85198
|
+
return started.preview_url;
|
|
85199
|
+
const live = row.live_release?.url;
|
|
85200
|
+
if (!live)
|
|
85201
|
+
return null;
|
|
85202
|
+
const host = new URL(live).hostname;
|
|
85203
|
+
const prefix = `${started.slug}.`;
|
|
85204
|
+
return host.startsWith(prefix) ? `https://${started.slug}-preview.${host.slice(prefix.length)}` : null;
|
|
85205
|
+
}
|
|
85206
|
+
function missingAddress(started) {
|
|
85207
|
+
return started.preview_url === null ? "none: this Brainbase server has no public domain for interfaces" : "unknown: this Brainbase server does not report it, and nothing is live to work it out from";
|
|
85208
|
+
}
|
|
85209
|
+
async function waitUntilServing(started, options) {
|
|
85210
|
+
const now2 = options.deps.now ?? Date.now;
|
|
85211
|
+
const interval = options.deps.pollIntervalMs ?? PROBE_INTERVAL_MS;
|
|
85212
|
+
const deadline = now2() + options.timeoutMs;
|
|
85213
|
+
const stop = interruption(options.deps);
|
|
85214
|
+
try {
|
|
85215
|
+
for (;; ) {
|
|
85216
|
+
if (stop.signal.aborted)
|
|
85217
|
+
return "interrupted";
|
|
85218
|
+
const left = deadline - now2();
|
|
85219
|
+
if (left <= 0)
|
|
85220
|
+
return "timeout";
|
|
85221
|
+
const probeStop = new AbortController;
|
|
85222
|
+
const onStop = () => probeStop.abort(stop.signal.reason);
|
|
85223
|
+
stop.signal.addEventListener("abort", onStop, { once: true });
|
|
85224
|
+
const timer = setTimeout(() => probeStop.abort(), left);
|
|
85225
|
+
try {
|
|
85226
|
+
const probe = await interfacesApi.probePreview(started.machine_id, started.port, probeStop.signal);
|
|
85227
|
+
if (probe.serving)
|
|
85228
|
+
return "serving";
|
|
85229
|
+
} catch (error2) {
|
|
85230
|
+
if (stop.signal.aborted)
|
|
85231
|
+
return "interrupted";
|
|
85232
|
+
if (probeStop.signal.aborted)
|
|
85233
|
+
return "timeout";
|
|
85234
|
+
if (!isTransientReadError(error2))
|
|
85235
|
+
throw error2;
|
|
85236
|
+
} finally {
|
|
85237
|
+
clearTimeout(timer);
|
|
85238
|
+
stop.signal.removeEventListener("abort", onStop);
|
|
85239
|
+
}
|
|
85240
|
+
const remaining = deadline - now2();
|
|
85241
|
+
if (remaining <= 0)
|
|
85242
|
+
return "timeout";
|
|
85243
|
+
if (await pause(Math.min(interval, remaining), stop.signal))
|
|
85244
|
+
return "interrupted";
|
|
85245
|
+
}
|
|
85246
|
+
} finally {
|
|
85247
|
+
stop.dispose();
|
|
85248
|
+
}
|
|
85249
|
+
}
|
|
85250
|
+
function showing(started, taskId) {
|
|
85251
|
+
return started.source === "working_copy" ? `the working copy of conversation ${safe(taskId)}, unsaved edits included` : `the last saved version${started.commit ? ` (${safe(started.commit)})` : ""}`;
|
|
85252
|
+
}
|
|
85253
|
+
async function preview(ctx) {
|
|
85254
|
+
let json = wantsJson(ctx.args);
|
|
85255
|
+
await runReportingErrors(() => json, async () => {
|
|
85256
|
+
const parsed = parseArgv(ctx.args, [
|
|
85257
|
+
JSON_FLAG,
|
|
85258
|
+
TIMEOUT_FLAG,
|
|
85259
|
+
NO_WAIT_FLAG,
|
|
85260
|
+
{ key: "task", names: ["--task"], kind: "value" }
|
|
85261
|
+
]);
|
|
85262
|
+
json = booleanOption(parsed, "json");
|
|
85263
|
+
const [id] = expectPositionals(parsed, ["id"], "brainbase interface preview <id> [--task <task id>]");
|
|
85264
|
+
const waitMs = timeoutMs2(stringOption(parsed, "timeout"), PREVIEW_TIMEOUT_SECONDS);
|
|
85265
|
+
const noWait = booleanOption(parsed, "noWait");
|
|
85266
|
+
const say = progress(json);
|
|
85267
|
+
const row = await interfacesApi.get(id);
|
|
85268
|
+
const { taskId, why } = await pickConversation(row, stringOption(parsed, "task")?.trim() || undefined);
|
|
85269
|
+
say(import_picocolors66.default.dim(` Previewing ${why}, ${safe(taskId)}.`));
|
|
85270
|
+
const started = await interfacesApi.startPreview(taskId, row.id);
|
|
85271
|
+
const address2 = previewAddress(started, row);
|
|
85272
|
+
let outcome = started.state === "serving" ? "serving" : "not_waited";
|
|
85273
|
+
if (outcome !== "serving" && !noWait) {
|
|
85274
|
+
say(import_picocolors66.default.dim(" Starting the dev server in the sandbox…"));
|
|
85275
|
+
outcome = await waitUntilServing(started, { timeoutMs: waitMs, deps: ctx.deps });
|
|
85276
|
+
}
|
|
85277
|
+
if (json) {
|
|
85278
|
+
printJson({ task_id: taskId, ...started, preview_url: address2, serving: outcome === "serving" });
|
|
85279
|
+
} else {
|
|
85280
|
+
const out = [
|
|
85281
|
+
"",
|
|
85282
|
+
` ${outcome === "serving" ? import_picocolors66.default.green("Preview ready") : import_picocolors66.default.yellow("Preview starting")} ${import_picocolors66.default.bold(safe(started.name))}`,
|
|
85283
|
+
"",
|
|
85284
|
+
field("address", address2 ? safe(address2) : import_picocolors66.default.dim(missingAddress(started))),
|
|
85285
|
+
field("showing", showing(started, taskId)),
|
|
85286
|
+
"",
|
|
85287
|
+
` ${import_picocolors66.default.dim("Opens for people who can edit the agent, after signing in. Nothing is published.")}`,
|
|
85288
|
+
""
|
|
85289
|
+
];
|
|
85290
|
+
console.log(out.join(`
|
|
85291
|
+
`));
|
|
85292
|
+
if (started.restored) {
|
|
85293
|
+
warn("The conversation's working copy was no longer in the sandbox, so its last saved version is shown and edits that were never saved are gone.");
|
|
85294
|
+
}
|
|
85295
|
+
}
|
|
85296
|
+
if (outcome === "timeout") {
|
|
85297
|
+
if (!json)
|
|
85298
|
+
warn(`Still starting after ${Math.round(waitMs / 1000)}s. It may come up shortly: open the address, or run this again.`);
|
|
85299
|
+
process.exitCode = 1;
|
|
85300
|
+
} else if (outcome === "interrupted") {
|
|
85301
|
+
process.exitCode = SIGINT_EXIT_CODE;
|
|
85302
|
+
}
|
|
85303
|
+
});
|
|
85304
|
+
}
|
|
85305
|
+
var previewCommands = { preview };
|
|
85306
|
+
|
|
84746
85307
|
// src/cli/interface-release.ts
|
|
84747
|
-
var
|
|
85308
|
+
var import_picocolors67 = __toESM(require_picocolors(), 1);
|
|
84748
85309
|
var PUBLISH_TIMEOUT_SECONDS = 300;
|
|
84749
85310
|
var REBUILD_USAGE = "brainbase interface rebuild <id> [--version <version id>]";
|
|
84750
85311
|
var PUBLISH_USAGE = "brainbase interface publish <id> [--build <build id>]";
|
|
84751
85312
|
var ROLLBACK_USAGE = "brainbase interface rollback <id> --release <release id>";
|
|
84752
|
-
function
|
|
84753
|
-
console.error(
|
|
85313
|
+
function warn2(line) {
|
|
85314
|
+
console.error(import_picocolors67.default.yellow(line));
|
|
84754
85315
|
}
|
|
84755
85316
|
function text3(value) {
|
|
84756
85317
|
return typeof value === "string" && value.trim() ? value : null;
|
|
@@ -84767,8 +85328,8 @@ async function follow(operationId, what, options) {
|
|
|
84767
85328
|
intervalMs: options.deps.pollIntervalMs,
|
|
84768
85329
|
signal: stop.signal,
|
|
84769
85330
|
now: options.deps.now,
|
|
84770
|
-
onStatus: (operation) => say(
|
|
84771
|
-
onStall: () =>
|
|
85331
|
+
onStatus: (operation) => say(import_picocolors67.default.dim(` ${what} ${operation.status}`)),
|
|
85332
|
+
onStall: () => warn2(`The ${what} looks stalled: its worker stopped checking in. Still waiting, in case another worker picks it up.`)
|
|
84772
85333
|
});
|
|
84773
85334
|
if (outcome.kind === "settled") {
|
|
84774
85335
|
const operation = outcome.operation;
|
|
@@ -84786,12 +85347,12 @@ function reportUnsuccessful(result2, what, options) {
|
|
|
84786
85347
|
if (options.json) {
|
|
84787
85348
|
printJson({ outcome: result2.outcome, operation_id: result2.operationId, operation: result2.operation });
|
|
84788
85349
|
} else if (result2.outcome === "failed") {
|
|
84789
|
-
console.error(
|
|
85350
|
+
console.error(import_picocolors67.default.red(`The ${what} failed (operation ${id}):`));
|
|
84790
85351
|
console.error(safeBlock(result2.operation?.error ?? "Brainbase gave no reason."));
|
|
84791
85352
|
} else if (result2.outcome === "timeout") {
|
|
84792
|
-
|
|
85353
|
+
warn2(`Stopped waiting after ${Math.round(options.timeoutMs / 1000)}s. The ${what} keeps running on the server (operation ${id}).`);
|
|
84793
85354
|
} else {
|
|
84794
|
-
|
|
85355
|
+
warn2(`Stopped waiting. The ${what} keeps running on the server (operation ${id}).`);
|
|
84795
85356
|
}
|
|
84796
85357
|
process.exitCode = result2.outcome === "interrupted" ? SIGINT_EXIT_CODE : 1;
|
|
84797
85358
|
return true;
|
|
@@ -84845,7 +85406,7 @@ async function rebuild(ctx) {
|
|
|
84845
85406
|
if (json)
|
|
84846
85407
|
printJson({ outcome: "started", operation_id: operationId, operation });
|
|
84847
85408
|
else
|
|
84848
|
-
console.log(
|
|
85409
|
+
console.log(import_picocolors67.default.dim(` Follow it with \`brainbase interface builds ${safe(id)}\`.`));
|
|
84849
85410
|
return;
|
|
84850
85411
|
}
|
|
84851
85412
|
const result2 = await follow(operationId, "build", { json, timeoutMs: waitMs, deps: ctx.deps });
|
|
@@ -84857,8 +85418,8 @@ async function rebuild(ctx) {
|
|
|
84857
85418
|
}
|
|
84858
85419
|
const buildId = safe(result2.operation?.build_id ?? "");
|
|
84859
85420
|
const version2 = safe(result2.operation?.source_version_id ?? "");
|
|
84860
|
-
console.log(
|
|
84861
|
-
console.log(
|
|
85421
|
+
console.log(import_picocolors67.default.green(`✓ Build ${buildId} succeeded${version2 ? ` (version ${version2})` : ""}.`));
|
|
85422
|
+
console.log(import_picocolors67.default.dim(` Publish it with \`brainbase interface publish ${safe(id)} --build ${buildId}\`.`));
|
|
84862
85423
|
});
|
|
84863
85424
|
}
|
|
84864
85425
|
function liveBuildOf(row, releases) {
|
|
@@ -84916,7 +85477,7 @@ function describeBuild(buildId, builds) {
|
|
|
84916
85477
|
const build2 = builds.find((candidate) => candidate.id === buildId);
|
|
84917
85478
|
if (!build2)
|
|
84918
85479
|
return `build ${safe(buildId)}`;
|
|
84919
|
-
return `build ${safe(build2.id)} ${
|
|
85480
|
+
return `build ${safe(build2.id)} ${import_picocolors67.default.dim(`(version ${safe(build2.source_version_id)}, built ${ago(build2.created_at)})`)}`;
|
|
84920
85481
|
}
|
|
84921
85482
|
function reportAlreadyLive(json, buildId, releaseId, url2) {
|
|
84922
85483
|
if (json) {
|
|
@@ -84961,7 +85522,7 @@ async function publish(ctx) {
|
|
|
84961
85522
|
} else {
|
|
84962
85523
|
const picked = await pickBuild(id, row, builds, releases, liveBuildId);
|
|
84963
85524
|
if (picked.warning)
|
|
84964
|
-
|
|
85525
|
+
warn2(picked.warning);
|
|
84965
85526
|
buildId = picked.build.id;
|
|
84966
85527
|
}
|
|
84967
85528
|
if (buildId === liveBuildId) {
|
|
@@ -84970,8 +85531,8 @@ async function publish(ctx) {
|
|
|
84970
85531
|
}
|
|
84971
85532
|
if (!json) {
|
|
84972
85533
|
console.log("");
|
|
84973
|
-
console.log(` ${
|
|
84974
|
-
console.log(` ${
|
|
85534
|
+
console.log(` ${import_picocolors67.default.dim("Live now".padEnd(14))}${liveBuildId ? `${describeBuild(liveBuildId, builds)} at ${safe(row.live_release?.url)}` : row.live_release ? `release ${safe(row.live_release.id)} at ${safe(row.live_release.url)}` : import_picocolors67.default.dim("nothing")}`);
|
|
85535
|
+
console.log(` ${import_picocolors67.default.dim("Will publish".padEnd(14))}${describeBuild(buildId, builds)}`);
|
|
84975
85536
|
console.log("");
|
|
84976
85537
|
}
|
|
84977
85538
|
const proceed = await confirmChange({
|
|
@@ -85003,7 +85564,7 @@ async function publish(ctx) {
|
|
|
85003
85564
|
return;
|
|
85004
85565
|
}
|
|
85005
85566
|
if (error2.reason === "audience_empty") {
|
|
85006
|
-
throw reword(error2, `Nobody can open this interface yet, so it was not published. Choose who can with \`brainbase interface access ${safe(id)} --everyone\` or \`--people <
|
|
85567
|
+
throw reword(error2, `Nobody can open this interface yet, so it was not published. Choose who can with \`brainbase interface access ${safe(id)} --everyone\` or \`--people <emails>\`, then publish again.`);
|
|
85007
85568
|
}
|
|
85008
85569
|
if (error2.reason !== "operation_in_flight")
|
|
85009
85570
|
throw error2;
|
|
@@ -85014,7 +85575,7 @@ async function publish(ctx) {
|
|
|
85014
85575
|
if (json)
|
|
85015
85576
|
printJson({ outcome: "started", operation_id: operationId, operation });
|
|
85016
85577
|
else
|
|
85017
|
-
console.log(
|
|
85578
|
+
console.log(import_picocolors67.default.dim(` Check it with \`brainbase interface get ${safe(id)}\`.`));
|
|
85018
85579
|
return;
|
|
85019
85580
|
}
|
|
85020
85581
|
const result2 = await follow(operationId, "publish", { json, timeoutMs: waitMs, deps: ctx.deps });
|
|
@@ -85031,11 +85592,11 @@ async function publish(ctx) {
|
|
|
85031
85592
|
printJson({ outcome: "succeeded", operation_id: operationId, operation: result2.operation, url: url2 });
|
|
85032
85593
|
return;
|
|
85033
85594
|
}
|
|
85034
|
-
console.log(
|
|
85595
|
+
console.log(import_picocolors67.default.green(`✓ Build ${safe(buildId)} is live.`));
|
|
85035
85596
|
if (url2)
|
|
85036
85597
|
console.log(` ${safe(url2)}`);
|
|
85037
85598
|
if (urlUnread) {
|
|
85038
|
-
console.log(
|
|
85599
|
+
console.log(import_picocolors67.default.dim(` Its address could not be read just now; see it with \`brainbase interface open ${safe(id)}\`.`));
|
|
85039
85600
|
}
|
|
85040
85601
|
});
|
|
85041
85602
|
}
|
|
@@ -85071,8 +85632,8 @@ async function rollback(ctx) {
|
|
|
85071
85632
|
}
|
|
85072
85633
|
if (!json) {
|
|
85073
85634
|
console.log("");
|
|
85074
|
-
console.log(` ${
|
|
85075
|
-
console.log(` ${
|
|
85635
|
+
console.log(` ${import_picocolors67.default.dim("Live now".padEnd(20))}release ${safe(row.live_release.id)} at ${safe(row.live_release.url)}`);
|
|
85636
|
+
console.log(` ${import_picocolors67.default.dim("Will be live again".padEnd(20))}release ${safe(releaseId)}`);
|
|
85076
85637
|
console.log("");
|
|
85077
85638
|
}
|
|
85078
85639
|
const proceed = await confirmChange({
|
|
@@ -85105,7 +85666,7 @@ async function rollback(ctx) {
|
|
|
85105
85666
|
printJson(release);
|
|
85106
85667
|
return;
|
|
85107
85668
|
}
|
|
85108
|
-
console.log(
|
|
85669
|
+
console.log(import_picocolors67.default.green(`✓ Release ${safe(release.id)} is live again (build ${safe(release.build_id)}).`));
|
|
85109
85670
|
console.log(` ${safe(release.url)}`);
|
|
85110
85671
|
});
|
|
85111
85672
|
}
|
|
@@ -85116,7 +85677,8 @@ var COMMANDS = {
|
|
|
85116
85677
|
...readCommands,
|
|
85117
85678
|
...lifecycleCommands,
|
|
85118
85679
|
...releaseCommands,
|
|
85119
|
-
...buildCommands
|
|
85680
|
+
...buildCommands,
|
|
85681
|
+
...previewCommands
|
|
85120
85682
|
};
|
|
85121
85683
|
var ALIASES = { list: "ls", show: "get" };
|
|
85122
85684
|
async function runInterface(cwd2, sub, args, deps = {}) {
|
|
@@ -85139,22 +85701,22 @@ async function runInterface(cwd2, sub, args, deps = {}) {
|
|
|
85139
85701
|
await command({ cwd: cwd2, args, deps });
|
|
85140
85702
|
}
|
|
85141
85703
|
function line(command, args, description) {
|
|
85142
|
-
return ` ${
|
|
85143
|
-
${
|
|
85704
|
+
return ` ${import_picocolors68.default.cyan(command)}${args ? ` ${import_picocolors68.default.dim(args)}` : ""}
|
|
85705
|
+
${import_picocolors68.default.dim(description)}`;
|
|
85144
85706
|
}
|
|
85145
85707
|
function printHelp6() {
|
|
85146
85708
|
const out = [];
|
|
85147
85709
|
out.push("");
|
|
85148
|
-
out.push(` ${
|
|
85149
|
-
out.push(` ${
|
|
85710
|
+
out.push(` ${import_picocolors68.default.bold("brainbase interface")} ${import_picocolors68.default.dim("<sub> [options]")}`);
|
|
85711
|
+
out.push(` ${import_picocolors68.default.dim("Dashboards for an agent: build them in a conversation, publish them, choose who can open them.")}`);
|
|
85150
85712
|
out.push("");
|
|
85151
85713
|
out.push(line("ls", "[--agent <id>] [--archived | --only-archived]", "list interfaces you can see"));
|
|
85152
85714
|
out.push(line("get", "<id>", "one interface: address, audience, live release, draft, running build conversation"));
|
|
85153
85715
|
out.push(line("open", "<id>", "print the live address"));
|
|
85154
85716
|
out.push(line("versions | builds | releases", "<id>", "history, newest first"));
|
|
85155
85717
|
out.push("");
|
|
85156
|
-
out.push(line("create", "[--agent <id>] --name <name> [--address <slug>] [--everyone | --people <
|
|
85157
|
-
out.push(line("access", "<id> [--everyone | --people <
|
|
85718
|
+
out.push(line("create", "[--agent <id>] --name <name> [--address <slug>] [--everyone | --people <emails>]", "create an interface on an agent"));
|
|
85719
|
+
out.push(line("access", "<id> [--everyone | --people <emails> | --add <emails> | --remove <emails>]", "show or set who can open it"));
|
|
85158
85720
|
out.push(line("threads", "<id> [--shared | --private]", "show or set whether viewers see every conversation on the agent"));
|
|
85159
85721
|
out.push(line("rename", "<id> <name>", "change the name"));
|
|
85160
85722
|
out.push(line("address", "<id> <slug>", "change the address (viewers sign in again)"));
|
|
@@ -85164,15 +85726,97 @@ function printHelp6() {
|
|
|
85164
85726
|
out.push(line("rebuild", "<id> [--version <id>]", "build the draft version again, or a named one"));
|
|
85165
85727
|
out.push(line("publish", "<id> [--build <id>]", "make a build live (default: the newest succeeded build)"));
|
|
85166
85728
|
out.push(line("rollback", "<id> --release <id>", "make an earlier release live again"));
|
|
85729
|
+
out.push(line("preview", "<id> [--task <id>] [--no-wait]", "serve the unpublished draft from its build conversation and print the preview address"));
|
|
85167
85730
|
out.push("");
|
|
85168
|
-
out.push(` ${
|
|
85169
|
-
out.push(` ${
|
|
85170
|
-
out.push(` ${
|
|
85171
|
-
out.push(` ${
|
|
85172
|
-
out.push(` ${
|
|
85731
|
+
out.push(` ${import_picocolors68.default.dim("--json")} machine-readable output; never prompts`);
|
|
85732
|
+
out.push(` ${import_picocolors68.default.dim("--yes, -y")} skip confirmation (required without a terminal)`);
|
|
85733
|
+
out.push(` ${import_picocolors68.default.dim("--no-wait")} for rebuild and publish: return the operation at once; for preview: do not wait for the dev server`);
|
|
85734
|
+
out.push(` ${import_picocolors68.default.dim("--timeout <seconds>")} for build, rebuild, publish and preview: how long to wait (builds 900, publish and preview 300)`);
|
|
85735
|
+
out.push(` ${import_picocolors68.default.dim("--idempotency-key <key>")} replay a create, build, rebuild, publish or rollback whose answer was lost`);
|
|
85173
85736
|
out.push("");
|
|
85174
|
-
out.push(` ${
|
|
85175
|
-
out.push(` ${
|
|
85737
|
+
out.push(` ${import_picocolors68.default.dim("People are emails (see `brainbase member ls`), user ids, or `me`. Audience members also need access to the agent.")}`);
|
|
85738
|
+
out.push(` ${import_picocolors68.default.dim("Exit codes: 0 done, 1 refused or failed, 130 interrupted (the server keeps working).")}`);
|
|
85739
|
+
out.push("");
|
|
85740
|
+
console.log(out.join(`
|
|
85741
|
+
`));
|
|
85742
|
+
}
|
|
85743
|
+
|
|
85744
|
+
// src/cli/member.ts
|
|
85745
|
+
var import_picocolors69 = __toESM(require_picocolors(), 1);
|
|
85746
|
+
async function runMember(sub, args, opts) {
|
|
85747
|
+
if (args.some((arg) => arg === "--help" || arg === "-h")) {
|
|
85748
|
+
printHelp7();
|
|
85749
|
+
return;
|
|
85750
|
+
}
|
|
85751
|
+
switch (sub) {
|
|
85752
|
+
case "ls":
|
|
85753
|
+
case "list":
|
|
85754
|
+
if (args.length > 0) {
|
|
85755
|
+
console.error(`Unexpected argument: ${args[0]}
|
|
85756
|
+
`);
|
|
85757
|
+
printHelp7();
|
|
85758
|
+
process.exit(1);
|
|
85759
|
+
}
|
|
85760
|
+
await runMemberList(opts);
|
|
85761
|
+
return;
|
|
85762
|
+
case undefined:
|
|
85763
|
+
case "help":
|
|
85764
|
+
case "-h":
|
|
85765
|
+
case "--help":
|
|
85766
|
+
printHelp7();
|
|
85767
|
+
return;
|
|
85768
|
+
default:
|
|
85769
|
+
console.error(`Unknown member subcommand: ${sub}
|
|
85770
|
+
`);
|
|
85771
|
+
printHelp7();
|
|
85772
|
+
process.exit(1);
|
|
85773
|
+
}
|
|
85774
|
+
}
|
|
85775
|
+
async function runMemberList(opts) {
|
|
85776
|
+
const org = await resolveOrg(opts.orgId, { allowPrompt: !opts.json, announce: !opts.json });
|
|
85777
|
+
const members = await listAllOrgMembers(org.id);
|
|
85778
|
+
if (opts.json) {
|
|
85779
|
+
console.log(JSON.stringify({ org, members }, null, 2));
|
|
85780
|
+
return;
|
|
85781
|
+
}
|
|
85782
|
+
banner(`member ls — ${sanitizeLabel(org.name)}`);
|
|
85783
|
+
console.log(formatMemberList(members));
|
|
85784
|
+
}
|
|
85785
|
+
function formatMemberList(members) {
|
|
85786
|
+
if (members.length === 0)
|
|
85787
|
+
return `
|
|
85788
|
+
${import_picocolors69.default.dim("Nobody here you can see.")}
|
|
85789
|
+
`;
|
|
85790
|
+
const sorted = [...members].sort((a3, b4) => (a3.email ?? a3.id).localeCompare(b4.email ?? b4.id));
|
|
85791
|
+
const rows = sorted.map((member) => ({
|
|
85792
|
+
email: sanitizeLabel(member.email ?? "(no sign-in account)"),
|
|
85793
|
+
name: sanitizeLabel(member.name ?? ""),
|
|
85794
|
+
role: sanitizeLabel(member.role),
|
|
85795
|
+
teams: member.teams.map((team) => sanitizeLabel(team.name)).join(", ")
|
|
85796
|
+
}));
|
|
85797
|
+
const emailWidth = Math.max(...rows.map((row) => row.email.length));
|
|
85798
|
+
const nameWidth = Math.max(...rows.map((row) => row.name.length));
|
|
85799
|
+
const roleWidth = Math.max(...rows.map((row) => row.role.length));
|
|
85800
|
+
const lines = [""];
|
|
85801
|
+
for (const row of rows) {
|
|
85802
|
+
lines.push(` ${row.email.padEnd(emailWidth)} ${row.name.padEnd(nameWidth)} ${import_picocolors69.default.dim(row.role.padEnd(roleWidth))} ${import_picocolors69.default.dim(row.teams)}`.trimEnd());
|
|
85803
|
+
}
|
|
85804
|
+
lines.push("", ` ${import_picocolors69.default.dim("share a dashboard with one of them:")} ${import_picocolors69.default.cyan("brainbase interface access <id> --add <email>")}`, "");
|
|
85805
|
+
return lines.join(`
|
|
85806
|
+
`);
|
|
85807
|
+
}
|
|
85808
|
+
function printHelp7() {
|
|
85809
|
+
const out = [];
|
|
85810
|
+
out.push("");
|
|
85811
|
+
out.push(` ${import_picocolors69.default.bold("brainbase member")} ${import_picocolors69.default.dim("<sub> [options]")}`);
|
|
85812
|
+
out.push("");
|
|
85813
|
+
out.push(` ${import_picocolors69.default.cyan("ls")} ${import_picocolors69.default.dim("the people in an organization you can see, with their emails, roles and teams")}`);
|
|
85814
|
+
out.push("");
|
|
85815
|
+
out.push(` ${import_picocolors69.default.dim("--org <id-or-slug>")} ${import_picocolors69.default.dim("which organization (picked automatically when you are in one)")}`);
|
|
85816
|
+
out.push(` ${import_picocolors69.default.dim("--json")} ${import_picocolors69.default.dim("machine-readable output")}`);
|
|
85817
|
+
out.push("");
|
|
85818
|
+
out.push(` ${import_picocolors69.default.dim("Owners and admins see everyone. Anyone else sees the owners, the admins, themselves")}`);
|
|
85819
|
+
out.push(` ${import_picocolors69.default.dim("and the people who share a team with them, as in the web app.")}`);
|
|
85176
85820
|
out.push("");
|
|
85177
85821
|
console.log(out.join(`
|
|
85178
85822
|
`));
|
|
@@ -88265,7 +88909,7 @@ async function runBenchmarkPhase(specPathInput, resultPathInput, expectedPhase,
|
|
|
88265
88909
|
}
|
|
88266
88910
|
|
|
88267
88911
|
// src/cli/benchmark-control.ts
|
|
88268
|
-
var
|
|
88912
|
+
var import_picocolors70 = __toESM(require_picocolors(), 1);
|
|
88269
88913
|
import fs89 from "node:fs";
|
|
88270
88914
|
import path101 from "node:path";
|
|
88271
88915
|
|
|
@@ -91279,20 +91923,20 @@ async function emitCursorPages(output, fetchPage, options) {
|
|
|
91279
91923
|
function commandHelp() {
|
|
91280
91924
|
return [
|
|
91281
91925
|
"",
|
|
91282
|
-
` ${
|
|
91926
|
+
` ${import_picocolors70.default.bold("brainbase benchmark")} ${import_picocolors70.default.dim("<command> [options]")}`,
|
|
91283
91927
|
"",
|
|
91284
|
-
` ${
|
|
91285
|
-
` ${
|
|
91286
|
-
` ${
|
|
91287
|
-
` ${
|
|
91288
|
-
` ${
|
|
91928
|
+
` ${import_picocolors70.default.cyan("init | list | show | create | validate | pull | push")}`,
|
|
91929
|
+
` ${import_picocolors70.default.cyan("publish | revisions | import | export | archive | restore")}`,
|
|
91930
|
+
` ${import_picocolors70.default.cyan("run plan|start|watch|list|show|cancel|resume")}`,
|
|
91931
|
+
` ${import_picocolors70.default.cyan("results | diagnoses | attempt | artifacts | export-results")}`,
|
|
91932
|
+
` ${import_picocolors70.default.cyan("history | baseline show|set|clear")}`,
|
|
91289
91933
|
"",
|
|
91290
|
-
` ${
|
|
91934
|
+
` ${import_picocolors70.default.dim("Use --agent to override brainbase.agent.yaml, and --json or --jsonl for automation.")}`,
|
|
91291
91935
|
"",
|
|
91292
|
-
` ${
|
|
91293
|
-
` ${
|
|
91294
|
-
` ${
|
|
91295
|
-
` ${
|
|
91936
|
+
` ${import_picocolors70.default.bold("benchmark runtime (machine-only)")}`,
|
|
91937
|
+
` ${import_picocolors70.default.cyan("hydrate")} ${import_picocolors70.default.dim("--spec <path> --result <path> --json")}`,
|
|
91938
|
+
` ${import_picocolors70.default.cyan("evaluate")} ${import_picocolors70.default.dim("--spec <path> --result <path> --json")}`,
|
|
91939
|
+
` ${import_picocolors70.default.cyan("capabilities")} ${import_picocolors70.default.dim("--json")}`,
|
|
91296
91940
|
""
|
|
91297
91941
|
].join(`
|
|
91298
91942
|
`);
|
|
@@ -91539,17 +92183,17 @@ async function runImport(cwd2, argv, deps) {
|
|
|
91539
92183
|
const primary = optionalNonblank(options.parsed, "primaryEvaluator");
|
|
91540
92184
|
if (primary)
|
|
91541
92185
|
request2.primary_evaluator_key = primary;
|
|
91542
|
-
const
|
|
92186
|
+
const preview2 = await client.previewHuggingFaceImport(request2);
|
|
91543
92187
|
if (bool(options.parsed, "preview")) {
|
|
91544
|
-
output.result(
|
|
92188
|
+
output.result(preview2);
|
|
91545
92189
|
return;
|
|
91546
92190
|
}
|
|
91547
|
-
const provenance = requireObject(
|
|
92191
|
+
const provenance = requireObject(preview2.provenance ?? {}, "preview provenance");
|
|
91548
92192
|
const materialize = {
|
|
91549
92193
|
...request2,
|
|
91550
92194
|
expected_commit: stringField(provenance, "commit"),
|
|
91551
|
-
expected_materialization_digest: stringField(
|
|
91552
|
-
expected_content_digest: stringField(
|
|
92195
|
+
expected_materialization_digest: stringField(preview2, "materialization_digest"),
|
|
92196
|
+
expected_content_digest: stringField(preview2, "content_digest")
|
|
91553
92197
|
};
|
|
91554
92198
|
output.result(json(await client.materializeHuggingFaceImport(materialize, {
|
|
91555
92199
|
idempotencyKey: idempotencyKey(options)
|
|
@@ -92711,178 +93355,182 @@ var SUBCOMMAND_OWNED_FLAGS = {
|
|
|
92711
93355
|
function help() {
|
|
92712
93356
|
const out = [];
|
|
92713
93357
|
out.push("");
|
|
92714
|
-
out.push(` ${brandTint("◆")} ${
|
|
92715
|
-
out.push(` ${
|
|
93358
|
+
out.push(` ${brandTint("◆")} ${import_picocolors71.default.bold("brainbase")} ${import_picocolors71.default.dim(`v${VERSION}`)}`);
|
|
93359
|
+
out.push(` ${import_picocolors71.default.dim("connect your local agent to the brainbase platform")}`);
|
|
92716
93360
|
out.push("");
|
|
92717
93361
|
out.push(divider("USAGE"));
|
|
92718
93362
|
out.push("");
|
|
92719
|
-
out.push(` ${
|
|
93363
|
+
out.push(` ${import_picocolors71.default.bold("brainbase")} ${import_picocolors71.default.dim("<command> [options]")}`);
|
|
92720
93364
|
out.push("");
|
|
92721
93365
|
out.push(divider("AUTH"));
|
|
92722
93366
|
out.push("");
|
|
92723
|
-
out.push(` ${
|
|
92724
|
-
out.push(` ${
|
|
92725
|
-
out.push(` ${
|
|
93367
|
+
out.push(` ${import_picocolors71.default.cyan("login")} ${import_picocolors71.default.dim(" open the web app and connect this device")}`);
|
|
93368
|
+
out.push(` ${import_picocolors71.default.cyan("logout")} ${import_picocolors71.default.dim(" clear the local session")}`);
|
|
93369
|
+
out.push(` ${import_picocolors71.default.cyan("whoami")} ${import_picocolors71.default.dim("[--json]")} ${import_picocolors71.default.dim(" show which credential is in use and what it covers")}`);
|
|
92726
93370
|
out.push("");
|
|
92727
93371
|
out.push(divider("DISCOVERY"));
|
|
92728
93372
|
out.push("");
|
|
92729
|
-
out.push(` ${
|
|
92730
|
-
out.push(` ${
|
|
93373
|
+
out.push(` ${import_picocolors71.default.cyan("team list")} ${import_picocolors71.default.dim("show the teams you can create agents in")}`);
|
|
93374
|
+
out.push(` ${import_picocolors71.default.cyan("member ls")} ${import_picocolors71.default.dim("show the people in an organization, with the emails interface access takes")}`);
|
|
93375
|
+
out.push(` ${import_picocolors71.default.cyan("agent list")} ${import_picocolors71.default.dim("show a team's agents and their ids")}`);
|
|
92731
93376
|
out.push("");
|
|
92732
93377
|
out.push(divider("LINKED AGENT"));
|
|
92733
93378
|
out.push("");
|
|
92734
|
-
out.push(` ${
|
|
92735
|
-
out.push(` ${
|
|
92736
|
-
out.push(` ${
|
|
92737
|
-
out.push(` ${
|
|
92738
|
-
out.push(` ${
|
|
92739
|
-
out.push(` ${
|
|
92740
|
-
out.push(` ${
|
|
92741
|
-
out.push(` ${
|
|
92742
|
-
out.push(` ${
|
|
92743
|
-
out.push(` ${
|
|
92744
|
-
out.push(` ${
|
|
92745
|
-
out.push(` ${
|
|
92746
|
-
out.push(` ${
|
|
92747
|
-
out.push(` ${
|
|
92748
|
-
out.push(` ${
|
|
93379
|
+
out.push(` ${import_picocolors71.default.cyan("agent init")} ${import_picocolors71.default.dim("write a starter brainbase.agent.yaml here — offline, no login needed")}`);
|
|
93380
|
+
out.push(` ${import_picocolors71.default.cyan("agent create")} ${import_picocolors71.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
93381
|
+
out.push(` ${import_picocolors71.default.cyan("agent pull")} ${import_picocolors71.default.dim("[<id>]")} ${import_picocolors71.default.dim("bring cloud changes into this folder (--force to override; --run-entrypoint to also execute the agent entrypoint; --link to link first)")}`);
|
|
93382
|
+
out.push(` ${import_picocolors71.default.cyan("agent push")} ${import_picocolors71.default.dim("send local changes to the cloud (--force to overwrite cloud-side conflicts with local)")}`);
|
|
93383
|
+
out.push(` ${import_picocolors71.default.cyan("agent delete")} ${import_picocolors71.default.dim("<id>")} ${import_picocolors71.default.dim("permanently delete a cloud agent and every task it has run")}`);
|
|
93384
|
+
out.push(` ${import_picocolors71.default.cyan("agent unpack")} ${import_picocolors71.default.dim("install the claimed agent into a harness layout")}`);
|
|
93385
|
+
out.push(` ${import_picocolors71.default.cyan("link")} ${import_picocolors71.default.dim("attach this folder to an existing agent")}`);
|
|
93386
|
+
out.push(` ${import_picocolors71.default.cyan("agent status")} ${import_picocolors71.default.dim("show what would pull and what would push")}`);
|
|
93387
|
+
out.push(` ${import_picocolors71.default.cyan("agent connections")} ${import_picocolors71.default.dim("show which integrations this agent is wired to (--json for CI)")}`);
|
|
93388
|
+
out.push(` ${import_picocolors71.default.cyan("agent connect")} ${import_picocolors71.default.dim("<name>")} ${import_picocolors71.default.dim("connect slack or meeting from the terminal")}`);
|
|
93389
|
+
out.push(` ${import_picocolors71.default.cyan("agent disconnect")} ${import_picocolors71.default.dim("<name>")} ${import_picocolors71.default.dim("revoke a slack or meeting install")}`);
|
|
93390
|
+
out.push(` ${import_picocolors71.default.cyan("agent env")} ${import_picocolors71.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
|
|
93391
|
+
out.push(` ${import_picocolors71.default.cyan("run")} ${import_picocolors71.default.dim("<cmd> [args...]")} ${import_picocolors71.default.dim("run <cmd> with secrets.env loaded into env")}`);
|
|
93392
|
+
out.push(` ${import_picocolors71.default.cyan("status")} ${import_picocolors71.default.dim("show what this folder is linked to")}`);
|
|
93393
|
+
out.push(` ${import_picocolors71.default.cyan("unlink")} ${import_picocolors71.default.dim("disconnect this folder")}`);
|
|
92749
93394
|
out.push("");
|
|
92750
93395
|
out.push(divider("TASKS"));
|
|
92751
93396
|
out.push("");
|
|
92752
|
-
out.push(` ${
|
|
92753
|
-
out.push(` ${
|
|
92754
|
-
out.push(` ${
|
|
92755
|
-
out.push(` ${
|
|
92756
|
-
out.push(` ${
|
|
92757
|
-
out.push(` ${
|
|
92758
|
-
out.push(` ${
|
|
93397
|
+
out.push(` ${import_picocolors71.default.cyan("task create")} ${import_picocolors71.default.dim("--message <text>")} ${import_picocolors71.default.dim("create a managed task and start its first run (--wait to block on it; --interface <id> for a build conversation)")}`);
|
|
93398
|
+
out.push(` ${import_picocolors71.default.cyan("task list")} ${import_picocolors71.default.dim("recent tasks you can reach (--interface <id> for its build conversations)")}`);
|
|
93399
|
+
out.push(` ${import_picocolors71.default.cyan("task get")} ${import_picocolors71.default.dim("<task-id>")} ${import_picocolors71.default.dim("one task: status, agent, machine, eval verdicts")}`);
|
|
93400
|
+
out.push(` ${import_picocolors71.default.cyan("task logs")} ${import_picocolors71.default.dim("<task-id> [--follow]")} ${import_picocolors71.default.dim("one line per event in the task's transcript, or tail it live")}`);
|
|
93401
|
+
out.push(` ${import_picocolors71.default.cyan("task send")} ${import_picocolors71.default.dim("<task-id> <message>")} ${import_picocolors71.default.dim("send a follow-up during execution, or queue it for the next turn")}`);
|
|
93402
|
+
out.push(` ${import_picocolors71.default.cyan("task stop")} ${import_picocolors71.default.dim("<task-id>")} ${import_picocolors71.default.dim("stop execution and cancel pending follow-ups, retaining their text")}`);
|
|
93403
|
+
out.push(` ${import_picocolors71.default.cyan("task delete")} ${import_picocolors71.default.dim("<task-id>")} ${import_picocolors71.default.dim("permanently delete a stopped task and tear down its sandbox")}`);
|
|
92759
93404
|
out.push("");
|
|
92760
93405
|
out.push(divider("INTERFACES"));
|
|
92761
93406
|
out.push("");
|
|
92762
|
-
out.push(` ${
|
|
92763
|
-
out.push(` ${
|
|
92764
|
-
out.push(` ${
|
|
92765
|
-
out.push(` ${
|
|
92766
|
-
out.push(` ${
|
|
92767
|
-
out.push(` ${
|
|
92768
|
-
out.push(` ${
|
|
93407
|
+
out.push(` ${import_picocolors71.default.cyan("interface ls")} ${import_picocolors71.default.dim("dashboards you can see (--agent to narrow)")}`);
|
|
93408
|
+
out.push(` ${import_picocolors71.default.cyan("interface create")} ${import_picocolors71.default.dim("--name <n>")} ${import_picocolors71.default.dim("create one on an agent, with who can open it")}`);
|
|
93409
|
+
out.push(` ${import_picocolors71.default.cyan("interface build")} ${import_picocolors71.default.dim('<id> "<ask>"')} ${import_picocolors71.default.dim("describe a change; the agent builds it while you watch")}`);
|
|
93410
|
+
out.push(` ${import_picocolors71.default.cyan("interface publish")} ${import_picocolors71.default.dim("<id>")} ${import_picocolors71.default.dim("make the newest succeeded build live")}`);
|
|
93411
|
+
out.push(` ${import_picocolors71.default.cyan("interface rollback")} ${import_picocolors71.default.dim("<id>")} ${import_picocolors71.default.dim("make an earlier release live again (--release <id>)")}`);
|
|
93412
|
+
out.push(` ${import_picocolors71.default.cyan("interface access")} ${import_picocolors71.default.dim("<id>")} ${import_picocolors71.default.dim("show or set who can open it")}`);
|
|
93413
|
+
out.push(` ${import_picocolors71.default.cyan("interface --help")} ${import_picocolors71.default.dim("every interface subcommand")}`);
|
|
92769
93414
|
out.push("");
|
|
92770
93415
|
out.push(divider("SANDBOXES"));
|
|
92771
93416
|
out.push("");
|
|
92772
|
-
out.push(` ${
|
|
92773
|
-
out.push(` ${
|
|
93417
|
+
out.push(` ${import_picocolors71.default.cyan("machine ls")} ${import_picocolors71.default.dim("[--all]")} ${import_picocolors71.default.dim("list your sandboxes — live ones only unless --all")}`);
|
|
93418
|
+
out.push(` ${import_picocolors71.default.cyan("machine rm")} ${import_picocolors71.default.dim("<id>")} ${import_picocolors71.default.dim("tear a sandbox down (it bills until you do)")}`);
|
|
92774
93419
|
out.push("");
|
|
92775
93420
|
out.push(divider("BENCHMARKS"));
|
|
92776
93421
|
out.push("");
|
|
92777
|
-
out.push(` ${
|
|
92778
|
-
out.push(` ${
|
|
92779
|
-
out.push(` ${
|
|
92780
|
-
out.push(` ${
|
|
92781
|
-
out.push(` ${
|
|
93422
|
+
out.push(` ${import_picocolors71.default.cyan("benchmark list")} ${import_picocolors71.default.dim("list benchmarks for the linked agent")}`);
|
|
93423
|
+
out.push(` ${import_picocolors71.default.cyan("benchmark init")} ${import_picocolors71.default.dim("[directory]")} ${import_picocolors71.default.dim("scaffold a local benchmark")}`);
|
|
93424
|
+
out.push(` ${import_picocolors71.default.cyan("benchmark create")} ${import_picocolors71.default.dim("[path|-]")} ${import_picocolors71.default.dim("create a benchmark draft")}`);
|
|
93425
|
+
out.push(` ${import_picocolors71.default.cyan("benchmark run")} ${import_picocolors71.default.dim("<benchmark> --yes")} ${import_picocolors71.default.dim("plan and start a benchmark run")}`);
|
|
93426
|
+
out.push(` ${import_picocolors71.default.cyan("benchmark results")} ${import_picocolors71.default.dim("<run>")} ${import_picocolors71.default.dim("inspect normalized benchmark results")}`);
|
|
92782
93427
|
out.push("");
|
|
92783
93428
|
out.push(divider("BENCHMARK RUNTIME"));
|
|
92784
93429
|
out.push("");
|
|
92785
|
-
out.push(` ${
|
|
92786
|
-
out.push(` ${
|
|
92787
|
-
out.push(` ${
|
|
93430
|
+
out.push(` ${import_picocolors71.default.cyan("benchmark hydrate")} ${import_picocolors71.default.dim("--spec <path> --result <path> --json")}`);
|
|
93431
|
+
out.push(` ${import_picocolors71.default.cyan("benchmark evaluate")} ${import_picocolors71.default.dim("--spec <path> --result <path> --json")}`);
|
|
93432
|
+
out.push(` ${import_picocolors71.default.cyan("benchmark capabilities")} ${import_picocolors71.default.dim("--json")}`);
|
|
92788
93433
|
out.push("");
|
|
92789
93434
|
out.push(divider("ORCHESTRATIONS"));
|
|
92790
93435
|
out.push("");
|
|
92791
|
-
out.push(` ${
|
|
92792
|
-
out.push(` ${
|
|
92793
|
-
out.push(` ${
|
|
92794
|
-
out.push(` ${
|
|
92795
|
-
out.push(` ${
|
|
92796
|
-
out.push(` ${
|
|
93436
|
+
out.push(` ${import_picocolors71.default.cyan("orchestration create")} ${import_picocolors71.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
|
|
93437
|
+
out.push(` ${import_picocolors71.default.cyan("orchestration list")} ${import_picocolors71.default.dim("list orchestrations under a team")}`);
|
|
93438
|
+
out.push(` ${import_picocolors71.default.cyan("orchestration pull")} ${import_picocolors71.default.dim("<id>")} ${import_picocolors71.default.dim("recursively fetch an orchestration + every member agent")}`);
|
|
93439
|
+
out.push(` ${import_picocolors71.default.cyan("orchestration push")} ${import_picocolors71.default.dim("recursively push each member, then update the graph")}`);
|
|
93440
|
+
out.push(` ${import_picocolors71.default.cyan("orchestration status")} ${import_picocolors71.default.dim("show what would push and what would pull")}`);
|
|
93441
|
+
out.push(` ${import_picocolors71.default.cyan("orchestration delete")} ${import_picocolors71.default.dim("<id>")} ${import_picocolors71.default.dim("permanently delete an orchestration graph (member agents are kept)")}`);
|
|
92797
93442
|
out.push("");
|
|
92798
93443
|
out.push(divider("TEMPLATES"));
|
|
92799
93444
|
out.push("");
|
|
92800
|
-
out.push(` ${
|
|
92801
|
-
out.push(` ${
|
|
92802
|
-
out.push(` ${
|
|
92803
|
-
out.push(` ${
|
|
92804
|
-
out.push(` ${
|
|
92805
|
-
out.push(` ${
|
|
92806
|
-
out.push(` ${
|
|
93445
|
+
out.push(` ${import_picocolors71.default.cyan("template pack")} ${import_picocolors71.default.dim("bundle the current agent into a template")}`);
|
|
93446
|
+
out.push(` ${import_picocolors71.default.cyan("template publish")} ${import_picocolors71.default.dim("upload a template to the registry")}`);
|
|
93447
|
+
out.push(` ${import_picocolors71.default.cyan("template search")} ${import_picocolors71.default.dim("[query]")} ${import_picocolors71.default.dim("search the registry")}`);
|
|
93448
|
+
out.push(` ${import_picocolors71.default.cyan("template info")} ${import_picocolors71.default.dim("<creator/slug>")} ${import_picocolors71.default.dim("show registry details for a template")}`);
|
|
93449
|
+
out.push(` ${import_picocolors71.default.cyan("template onboard")} ${import_picocolors71.default.dim("<creator/slug>")} ${import_picocolors71.default.dim("install (or refresh) a template")}`);
|
|
93450
|
+
out.push(` ${import_picocolors71.default.cyan("template list")} ${import_picocolors71.default.dim("show installed templates")}`);
|
|
93451
|
+
out.push(` ${import_picocolors71.default.cyan("template remove")} ${import_picocolors71.default.dim("<creator/slug>")} ${import_picocolors71.default.dim("uninstall a template")}`);
|
|
92807
93452
|
out.push("");
|
|
92808
93453
|
out.push(divider("SKILLS"));
|
|
92809
93454
|
out.push("");
|
|
92810
|
-
out.push(` ${
|
|
92811
|
-
out.push(` ${
|
|
92812
|
-
out.push(` ${
|
|
92813
|
-
out.push(` ${
|
|
92814
|
-
out.push(` ${
|
|
92815
|
-
out.push(` ${
|
|
92816
|
-
out.push(` ${
|
|
93455
|
+
out.push(` ${import_picocolors71.default.cyan("skill add")} ${import_picocolors71.default.dim("<source>")} ${import_picocolors71.default.dim("install a skill (github / git / brainbase)")}`);
|
|
93456
|
+
out.push(` ${import_picocolors71.default.cyan("skill list")} ${import_picocolors71.default.dim("show locally installed skills + their source")}`);
|
|
93457
|
+
out.push(` ${import_picocolors71.default.cyan("skill update")} ${import_picocolors71.default.dim("<slug>")} ${import_picocolors71.default.dim("re-fetch a skill from its recorded source")}`);
|
|
93458
|
+
out.push(` ${import_picocolors71.default.cyan("skill remove")} ${import_picocolors71.default.dim("<slug>")} ${import_picocolors71.default.dim("uninstall a skill")}`);
|
|
93459
|
+
out.push(` ${import_picocolors71.default.cyan("skill search")} ${import_picocolors71.default.dim("[query]")} ${import_picocolors71.default.dim("search the brainbase skill registry")}`);
|
|
93460
|
+
out.push(` ${import_picocolors71.default.cyan("skill info")} ${import_picocolors71.default.dim("<creator/slug>")} ${import_picocolors71.default.dim("show registry details for a skill")}`);
|
|
93461
|
+
out.push(` ${import_picocolors71.default.cyan("skill publish")} ${import_picocolors71.default.dim("[dir]")} ${import_picocolors71.default.dim("publish a SKILL.md folder (defaults to .)")}`);
|
|
92817
93462
|
out.push("");
|
|
92818
93463
|
out.push(divider("CLI TOKENS"));
|
|
92819
93464
|
out.push("");
|
|
92820
|
-
out.push(` ${
|
|
92821
|
-
out.push(` ${
|
|
92822
|
-
out.push(` ${
|
|
92823
|
-
out.push(` ${
|
|
93465
|
+
out.push(` ${import_picocolors71.default.cyan("token create")} ${import_picocolors71.default.dim("issue a long-lived CLI key for CI / scripts")}`);
|
|
93466
|
+
out.push(` ${import_picocolors71.default.cyan("token list")} ${import_picocolors71.default.dim("show your tokens")}`);
|
|
93467
|
+
out.push(` ${import_picocolors71.default.cyan("token rename")} ${import_picocolors71.default.dim("<id>")} ${import_picocolors71.default.dim("relabel a token")}`);
|
|
93468
|
+
out.push(` ${import_picocolors71.default.cyan("token revoke")} ${import_picocolors71.default.dim("<id>")} ${import_picocolors71.default.dim("revoke a token")}`);
|
|
92824
93469
|
out.push("");
|
|
92825
93470
|
out.push(divider("MCP"));
|
|
92826
93471
|
out.push("");
|
|
92827
|
-
out.push(` ${
|
|
92828
|
-
out.push(` ${
|
|
93472
|
+
out.push(` ${import_picocolors71.default.cyan("mcp check")} ${import_picocolors71.default.dim("[--json]")} ${import_picocolors71.default.dim("verify MCP server connectivity through the brainbase proxy (runs at sandbox bootstrap)")}`);
|
|
93473
|
+
out.push(` ${import_picocolors71.default.cyan("mcp list")} ${import_picocolors71.default.dim("[--json]")} ${import_picocolors71.default.dim("show configured servers with OAuth state and expiry")}`);
|
|
93474
|
+
out.push(` ${import_picocolors71.default.cyan("mcp connect")} ${import_picocolors71.default.dim("<name>")} ${import_picocolors71.default.dim("authorize an OAuth-backed server: prints a single-use link, opens it, waits for approval")}`);
|
|
92829
93475
|
out.push("");
|
|
92830
93476
|
out.push(divider("FLAGS"));
|
|
92831
93477
|
out.push("");
|
|
92832
|
-
out.push(` ${
|
|
92833
|
-
out.push(` ${
|
|
92834
|
-
out.push(` ${
|
|
93478
|
+
out.push(` ${import_picocolors71.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
|
|
93479
|
+
out.push(` ${import_picocolors71.default.dim("--scope <s>")} force scope: global | project`);
|
|
93480
|
+
out.push(` ${import_picocolors71.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
|
|
92835
93481
|
out.push(` ${" ".repeat("--yes, -y".length)} required for destructive commands with no terminal (pipes, CI)`);
|
|
92836
|
-
out.push(` ${
|
|
92837
|
-
out.push(` ${
|
|
92838
|
-
out.push(` ${
|
|
92839
|
-
out.push(` ${
|
|
92840
|
-
out.push(` ${
|
|
92841
|
-
out.push(` ${
|
|
92842
|
-
out.push(` ${
|
|
92843
|
-
out.push(` ${
|
|
92844
|
-
out.push(` ${
|
|
92845
|
-
out.push(` ${
|
|
92846
|
-
out.push(` ${
|
|
92847
|
-
out.push(` ${
|
|
92848
|
-
out.push(` ${
|
|
92849
|
-
out.push(` ${
|
|
92850
|
-
out.push(` ${
|
|
92851
|
-
out.push(` ${
|
|
92852
|
-
out.push(` ${
|
|
92853
|
-
out.push(` ${
|
|
92854
|
-
out.push(` ${
|
|
92855
|
-
out.push(` ${
|
|
92856
|
-
out.push(` ${
|
|
92857
|
-
out.push(` ${
|
|
93482
|
+
out.push(` ${import_picocolors71.default.dim("--agent <id>")} for link/task create: use this agent id explicitly (task list: filter to it)`);
|
|
93483
|
+
out.push(` ${import_picocolors71.default.dim("--message <text>")} for task create: required first user message`);
|
|
93484
|
+
out.push(` ${import_picocolors71.default.dim("--title <text>")} for task create: optional task title`);
|
|
93485
|
+
out.push(` ${import_picocolors71.default.dim("--model <id>")} for task create: optional model override`);
|
|
93486
|
+
out.push(` ${import_picocolors71.default.dim("--wait")} for task create: block until the task finishes; exit 1 unless it succeeded`);
|
|
93487
|
+
out.push(` ${import_picocolors71.default.dim("--timeout <secs>")} for task create --wait: give up after <secs> and exit 1`);
|
|
93488
|
+
out.push(` ${import_picocolors71.default.dim("--limit <n>")} for task list (1-200), task logs (events to print; with --follow, the first page size) and machine ls`);
|
|
93489
|
+
out.push(` ${import_picocolors71.default.dim("--follow, -f")} for task logs: stay attached and print events as they land`);
|
|
93490
|
+
out.push(` ${import_picocolors71.default.dim("--org <id-or-slug>")} pick the organization (team/agent list, agent create, orchestration create/list)`);
|
|
93491
|
+
out.push(` ${import_picocolors71.default.dim("--team <id>")} pick the team, same commands (works without --org)`);
|
|
93492
|
+
out.push(` ${import_picocolors71.default.dim("--json")} machine-readable output for supported commands`);
|
|
93493
|
+
out.push(` ${import_picocolors71.default.dim("--no-tracking")} for link / agent pull --link: skip routing LLM traffic through brainbase`);
|
|
93494
|
+
out.push(` ${import_picocolors71.default.dim("--link")} for agent pull: link this folder to the agent first, as \`brainbase link --agent <id> --yes\` would, in one process`);
|
|
93495
|
+
out.push(` ${import_picocolors71.default.dim("--track")} for agent create: enable tracking non-interactively (off without a TTY)`);
|
|
93496
|
+
out.push(` ${import_picocolors71.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
|
|
93497
|
+
out.push(` ${import_picocolors71.default.dim("--bot-token <t>")} for agent connect slack (or BRAINBASE_SLACK_BOT_TOKEN, or stdin)`);
|
|
93498
|
+
out.push(` ${import_picocolors71.default.dim("--signing-secret <s>")} for agent connect slack (or BRAINBASE_SLACK_SIGNING_SECRET, or stdin)`);
|
|
93499
|
+
out.push(` ${import_picocolors71.default.dim("--bot-name <name>")} for agent connect meeting: the bot's display name`);
|
|
93500
|
+
out.push(` ${import_picocolors71.default.dim("--full")} for agent init: write a commented template covering every block`);
|
|
93501
|
+
out.push(` ${import_picocolors71.default.dim("--minimal")} for agent init: write the starter manifest (the default)`);
|
|
93502
|
+
out.push(` ${import_picocolors71.default.dim("--all")} for template list: include installs from other folders; for machine ls: include torn-down machines`);
|
|
93503
|
+
out.push(` ${import_picocolors71.default.dim("--web <url>")} for login: web app URL (default https://app.brainbaselabs.com)`);
|
|
93504
|
+
out.push(` ${import_picocolors71.default.dim("--no-open")} for mcp connect: print the link without opening a browser (implied with no terminal)`);
|
|
93505
|
+
out.push(` ${import_picocolors71.default.dim("--no-wait")} for mcp connect: print the link and exit instead of waiting for approval`);
|
|
92858
93506
|
out.push("");
|
|
92859
93507
|
out.push(divider("ENV"));
|
|
92860
93508
|
out.push("");
|
|
92861
|
-
out.push(` ${
|
|
92862
|
-
out.push(` ${
|
|
92863
|
-
out.push(` ${
|
|
92864
|
-
out.push(` ${
|
|
92865
|
-
out.push(` ${
|
|
92866
|
-
out.push(` ${
|
|
92867
|
-
out.push(` ${
|
|
92868
|
-
out.push(` ${
|
|
92869
|
-
out.push(` ${
|
|
92870
|
-
out.push(` ${
|
|
92871
|
-
out.push(` ${
|
|
93509
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
|
|
93510
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_DEBUG")} print full stack traces on error (any value; unset to disable)`);
|
|
93511
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
|
|
93512
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_CONTROL_PLANE_URL")} override the MAS host (/v2/cli; task and interface commands use /v2/tasks and /v2/interfaces)`);
|
|
93513
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_API_URL")} legacy KLS host override (uses /api/cli; proxy/registry fallback)`);
|
|
93514
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_PROXY_URL")} override the model-proxy URL used by harness traffic (default https://api.v1.brainbaselabs.com)`);
|
|
93515
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL (default https://api.v1.brainbaselabs.com)`);
|
|
93516
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT; the only PAT control-plane commands accept (token.json is not read there)`);
|
|
93517
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
|
|
93518
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_NON_INTERACTIVE")} force non-interactive mode — skip/auto-default prompts (CI & agents)`);
|
|
93519
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_RUN_ENTRYPOINT")} =1 → agent pull executes the agent entrypoint (sandbox boots; or pass --run-entrypoint)`);
|
|
92872
93520
|
out.push("");
|
|
92873
|
-
out.push(` ${
|
|
92874
|
-
out.push(` ${
|
|
92875
|
-
out.push(` ${
|
|
92876
|
-
out.push(` ${
|
|
92877
|
-
out.push(` ${
|
|
92878
|
-
out.push(` ${
|
|
92879
|
-
out.push(` ${
|
|
93521
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_MEMORY_MCP_URL")} override the built-in memory MCP host`);
|
|
93522
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_BROWSER_MCP_URL")} override the built-in browser MCP host`);
|
|
93523
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_SLACK_MCP_URL")} override the built-in Slack MCP host`);
|
|
93524
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_MEETING_MCP_URL")} override the built-in meeting MCP host`);
|
|
93525
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_GITHUB_MCP_URL")} override the built-in GitHub MCP host`);
|
|
93526
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_LINEAR_MCP_URL")} override the built-in Linear MCP host`);
|
|
93527
|
+
out.push(` ${import_picocolors71.default.dim("BRAINBASE_ORCHESTRATION_MCP_URL")} override the built-in orchestration MCP host`);
|
|
92880
93528
|
out.push("");
|
|
92881
93529
|
out.push(divider("HARNESSES"));
|
|
92882
93530
|
out.push("");
|
|
92883
|
-
out.push(` ${
|
|
92884
|
-
out.push(` ${
|
|
92885
|
-
out.push(` ${
|
|
93531
|
+
out.push(` ${import_picocolors71.default.dim("•")} ${import_picocolors71.default.bold("claude-code")} ${import_picocolors71.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
93532
|
+
out.push(` ${import_picocolors71.default.dim("•")} ${import_picocolors71.default.bold("codex")} ${import_picocolors71.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
|
|
93533
|
+
out.push(` ${import_picocolors71.default.dim("•")} ${import_picocolors71.default.bold("kafka")} ${import_picocolors71.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
92886
93534
|
out.push("");
|
|
92887
93535
|
console.log(out.join(`
|
|
92888
93536
|
`));
|
|
@@ -93036,13 +93684,13 @@ async function requireAuth(cmd) {
|
|
|
93036
93684
|
if (STORED_PAT_COMMANDS.has(cmd) && readToken())
|
|
93037
93685
|
return;
|
|
93038
93686
|
console.error("");
|
|
93039
|
-
console.error(` ${brandTint("◆")} ${
|
|
93687
|
+
console.error(` ${brandTint("◆")} ${import_picocolors71.default.bold("brainbase")}`);
|
|
93040
93688
|
console.error("");
|
|
93041
|
-
console.error(` ${
|
|
93689
|
+
console.error(` ${import_picocolors71.default.red("✗")} You need to sign in to use ${import_picocolors71.default.bold("brainbase " + cmd)}.`);
|
|
93042
93690
|
if (status.reason)
|
|
93043
|
-
console.error(` ${
|
|
93691
|
+
console.error(` ${import_picocolors71.default.dim(status.reason)}`);
|
|
93044
93692
|
console.error("");
|
|
93045
|
-
console.error(` Run ${
|
|
93693
|
+
console.error(` Run ${import_picocolors71.default.cyan("brainbase login")} to connect this device.`);
|
|
93046
93694
|
console.error("");
|
|
93047
93695
|
process14.exit(1);
|
|
93048
93696
|
}
|
|
@@ -93116,6 +93764,8 @@ async function main() {
|
|
|
93116
93764
|
const limitParsed = limitRaw === undefined ? NaN : Number(limitRaw);
|
|
93117
93765
|
const limitFlag = Number.isInteger(limitParsed) && limitParsed >= 1 && limitParsed <= 200 ? limitParsed : undefined;
|
|
93118
93766
|
const archivedFlag = hasFlag2(sharedArgs, "--archived");
|
|
93767
|
+
const noOpenFlag = hasFlag2(sharedArgs, "--no-open");
|
|
93768
|
+
const noWaitFlag = hasFlag2(sharedArgs, "--no-wait");
|
|
93119
93769
|
ensureSkillResolversRegistered();
|
|
93120
93770
|
try {
|
|
93121
93771
|
await requireAuth(cmd);
|
|
@@ -93221,6 +93871,12 @@ async function main() {
|
|
|
93221
93871
|
await runTeam(sub, argv, { orgId: orgIdFlag, json: jsonFlag });
|
|
93222
93872
|
break;
|
|
93223
93873
|
}
|
|
93874
|
+
case "member":
|
|
93875
|
+
case "members": {
|
|
93876
|
+
const sub = argv.shift();
|
|
93877
|
+
await runMember(sub, argv, { orgId: orgIdFlag, json: jsonFlag });
|
|
93878
|
+
break;
|
|
93879
|
+
}
|
|
93224
93880
|
case "task": {
|
|
93225
93881
|
const sub = argv.shift();
|
|
93226
93882
|
await runTask(cwd2, sub, argv);
|
|
@@ -93278,7 +93934,11 @@ async function main() {
|
|
|
93278
93934
|
}
|
|
93279
93935
|
case "mcp": {
|
|
93280
93936
|
const sub = argv.shift();
|
|
93281
|
-
const code = await runMcp(cwd2, sub, argv, {
|
|
93937
|
+
const code = await runMcp(cwd2, sub, argv, {
|
|
93938
|
+
json: jsonFlag,
|
|
93939
|
+
noOpen: noOpenFlag,
|
|
93940
|
+
noWait: noWaitFlag
|
|
93941
|
+
});
|
|
93282
93942
|
process14.exitCode = code;
|
|
93283
93943
|
break;
|
|
93284
93944
|
}
|
|
@@ -93289,10 +93949,10 @@ async function main() {
|
|
|
93289
93949
|
process14.exit(1);
|
|
93290
93950
|
}
|
|
93291
93951
|
} catch (err) {
|
|
93292
|
-
console.error(
|
|
93952
|
+
console.error(import_picocolors71.default.red(`
|
|
93293
93953
|
${err.message}`));
|
|
93294
93954
|
if (err instanceof ApiError && err.status === 401) {
|
|
93295
|
-
console.error(` Run ${
|
|
93955
|
+
console.error(` Run ${import_picocolors71.default.cyan("brainbase login")} to connect this device.`);
|
|
93296
93956
|
}
|
|
93297
93957
|
if (process14.env.BRAINBASE_DEBUG)
|
|
93298
93958
|
console.error(err.stack);
|