@brainbase-labs/cli 0.21.1 → 0.22.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 +1152 -392
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35128,12 +35128,12 @@ var require_dist2 = __commonJS((exports, module) => {
|
|
|
35128
35128
|
throw new Error(`Unknown format "${name}"`);
|
|
35129
35129
|
return f4;
|
|
35130
35130
|
};
|
|
35131
|
-
function addFormats(ajv, list,
|
|
35131
|
+
function addFormats(ajv, list, fs81, exportName) {
|
|
35132
35132
|
var _a;
|
|
35133
35133
|
var _b;
|
|
35134
35134
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== undefined || (_b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`);
|
|
35135
35135
|
for (const f4 of list)
|
|
35136
|
-
ajv.addFormat(f4,
|
|
35136
|
+
ajv.addFormat(f4, fs81[f4]);
|
|
35137
35137
|
}
|
|
35138
35138
|
module.exports = exports = formatsPlugin;
|
|
35139
35139
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -35141,9 +35141,9 @@ var require_dist2 = __commonJS((exports, module) => {
|
|
|
35141
35141
|
});
|
|
35142
35142
|
|
|
35143
35143
|
// src/index.ts
|
|
35144
|
-
var
|
|
35144
|
+
var import_picocolors52 = __toESM(require_picocolors(), 1);
|
|
35145
35145
|
import process14 from "node:process";
|
|
35146
|
-
import
|
|
35146
|
+
import fs83 from "node:fs";
|
|
35147
35147
|
|
|
35148
35148
|
// src/cli/template.ts
|
|
35149
35149
|
var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
@@ -36008,7 +36008,7 @@ function padStart(s, n) {
|
|
|
36008
36008
|
// package.json
|
|
36009
36009
|
var package_default = {
|
|
36010
36010
|
name: "@brainbase-labs/cli",
|
|
36011
|
-
version: "0.
|
|
36011
|
+
version: "0.22.0",
|
|
36012
36012
|
description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
|
|
36013
36013
|
type: "module",
|
|
36014
36014
|
bin: {
|
|
@@ -53969,6 +53969,7 @@ class NetworkApiError extends ApiError {
|
|
|
53969
53969
|
|
|
53970
53970
|
class TaskRecoveryDeadlineError extends ApiError {
|
|
53971
53971
|
}
|
|
53972
|
+
var GET_NETWORK_RETRY_DELAYS_MS = [100, 250];
|
|
53972
53973
|
function normalizeControlPlaneUrl(url) {
|
|
53973
53974
|
const normalized = url?.trim().replace(/\/+$/, "");
|
|
53974
53975
|
return normalized || DEFAULT_CONTROL_PLANE_BASE;
|
|
@@ -54101,9 +54102,33 @@ async function sendWithAuthRetry(session, send) {
|
|
|
54101
54102
|
}
|
|
54102
54103
|
async function request(pathname, init = {}) {
|
|
54103
54104
|
const credential = await resolveCredential();
|
|
54104
|
-
|
|
54105
|
-
|
|
54106
|
-
const
|
|
54105
|
+
let currentSession = credential.session;
|
|
54106
|
+
let refreshSessionAvailable = credential.source === "session" && !new Headers(init.headers).has("Authorization");
|
|
54107
|
+
const method2 = (init.method ?? "GET").toUpperCase();
|
|
54108
|
+
let res;
|
|
54109
|
+
let text2;
|
|
54110
|
+
for (let attempt2 = 0;; attempt2 += 1) {
|
|
54111
|
+
try {
|
|
54112
|
+
res = await sendWithAuthRetry(refreshSessionAvailable ? currentSession : null, async (refreshed) => {
|
|
54113
|
+
if (refreshed) {
|
|
54114
|
+
currentSession = refreshed;
|
|
54115
|
+
refreshSessionAvailable = false;
|
|
54116
|
+
}
|
|
54117
|
+
return await sendRequest(`${apiBase(currentSession)}${pathname}`, init, currentSession?.access_token ?? credential.bearer);
|
|
54118
|
+
});
|
|
54119
|
+
try {
|
|
54120
|
+
text2 = await res.text();
|
|
54121
|
+
} catch (error) {
|
|
54122
|
+
throw new NetworkApiError(`Network error while reading response: ${error.message}`, false);
|
|
54123
|
+
}
|
|
54124
|
+
break;
|
|
54125
|
+
} catch (error) {
|
|
54126
|
+
if (method2 !== "GET" || !(error instanceof NetworkApiError) || attempt2 >= GET_NETWORK_RETRY_DELAYS_MS.length) {
|
|
54127
|
+
throw error;
|
|
54128
|
+
}
|
|
54129
|
+
await new Promise((resolve) => setTimeout(resolve, GET_NETWORK_RETRY_DELAYS_MS[attempt2]));
|
|
54130
|
+
}
|
|
54131
|
+
}
|
|
54107
54132
|
let body = text2;
|
|
54108
54133
|
try {
|
|
54109
54134
|
body = text2 ? JSON.parse(text2) : null;
|
|
@@ -54267,6 +54292,19 @@ var masApi = {
|
|
|
54267
54292
|
return parseMasTaskCreateResponse(body);
|
|
54268
54293
|
}
|
|
54269
54294
|
};
|
|
54295
|
+
function isUnroutedPath(body) {
|
|
54296
|
+
return !!body && typeof body === "object" && body.detail === "Not Found";
|
|
54297
|
+
}
|
|
54298
|
+
async function connectionsRequest(pathname, init) {
|
|
54299
|
+
try {
|
|
54300
|
+
return await request(pathname, init);
|
|
54301
|
+
} catch (err) {
|
|
54302
|
+
if (err instanceof ApiError && err.status === 404 && isUnroutedPath(err.body)) {
|
|
54303
|
+
throw new ApiError("This control plane does not support reading or changing connections yet. Update the server, or use the web app.", 404, err.body);
|
|
54304
|
+
}
|
|
54305
|
+
throw err;
|
|
54306
|
+
}
|
|
54307
|
+
}
|
|
54270
54308
|
var api = {
|
|
54271
54309
|
listOrgs() {
|
|
54272
54310
|
return request("/orgs");
|
|
@@ -54354,6 +54392,21 @@ var api = {
|
|
|
54354
54392
|
method: "DELETE"
|
|
54355
54393
|
});
|
|
54356
54394
|
},
|
|
54395
|
+
getAgentConnections(agentId) {
|
|
54396
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/connections`);
|
|
54397
|
+
},
|
|
54398
|
+
connectSlack(agentId, input) {
|
|
54399
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/connections/slack`, { method: "PUT", body: JSON.stringify(input) });
|
|
54400
|
+
},
|
|
54401
|
+
connectMeeting(agentId, input) {
|
|
54402
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/connections/meeting`, { method: "PUT", body: JSON.stringify(input) });
|
|
54403
|
+
},
|
|
54404
|
+
disconnectIntegration(agentId, integration) {
|
|
54405
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/connections/${encodeURIComponent(integration)}`, { method: "DELETE" });
|
|
54406
|
+
},
|
|
54407
|
+
listAgentMcpServers(agentId) {
|
|
54408
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/mcp-servers`);
|
|
54409
|
+
},
|
|
54357
54410
|
listOrchestrations(orgId, teamId) {
|
|
54358
54411
|
return request(`/orgs/${encodeURIComponent(orgId)}/teams/${encodeURIComponent(teamId)}/orchestrations`);
|
|
54359
54412
|
},
|
|
@@ -63283,7 +63336,7 @@ function runHarnessInstall(harnessId, components, opts, agentName) {
|
|
|
63283
63336
|
}
|
|
63284
63337
|
|
|
63285
63338
|
// src/cli/agent.ts
|
|
63286
|
-
var
|
|
63339
|
+
var import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
63287
63340
|
|
|
63288
63341
|
// src/cli/agent-pull.ts
|
|
63289
63342
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -66396,6 +66449,396 @@ function formatAgentList(agents, labels) {
|
|
|
66396
66449
|
`);
|
|
66397
66450
|
}
|
|
66398
66451
|
|
|
66452
|
+
// src/cli/agent-connections.ts
|
|
66453
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
66454
|
+
|
|
66455
|
+
// src/core/integrations.ts
|
|
66456
|
+
var IMPLEMENTED_INTEGRATIONS = ["slack", "meeting"];
|
|
66457
|
+
function isImplemented(name) {
|
|
66458
|
+
return IMPLEMENTED_INTEGRATIONS.includes(name);
|
|
66459
|
+
}
|
|
66460
|
+
function actionability(state) {
|
|
66461
|
+
if (!state.manageable_from_cli) {
|
|
66462
|
+
return { kind: "web-only", ...state.unmanageable_reason ? { reason: state.unmanageable_reason } : {} };
|
|
66463
|
+
}
|
|
66464
|
+
return isImplemented(state.name) ? { kind: "connectable" } : { kind: "needs-newer-cli" };
|
|
66465
|
+
}
|
|
66466
|
+
var GENERIC_WEB_ONLY_REASON = "This integration cannot be connected from the terminal. Use the web app.";
|
|
66467
|
+
var UPGRADE_HINT = "This control plane supports connecting it, but this version of the CLI does not. Upgrade the CLI.";
|
|
66468
|
+
function explain(state) {
|
|
66469
|
+
const action = actionability(state);
|
|
66470
|
+
switch (action.kind) {
|
|
66471
|
+
case "connectable":
|
|
66472
|
+
return `brainbase agent connect ${state.name}`;
|
|
66473
|
+
case "needs-newer-cli":
|
|
66474
|
+
return UPGRADE_HINT;
|
|
66475
|
+
case "web-only":
|
|
66476
|
+
return action.reason ?? GENERIC_WEB_ONLY_REASON;
|
|
66477
|
+
default: {
|
|
66478
|
+
const exhaustive = action;
|
|
66479
|
+
return exhaustive;
|
|
66480
|
+
}
|
|
66481
|
+
}
|
|
66482
|
+
}
|
|
66483
|
+
|
|
66484
|
+
// src/cli/agent-connect.ts
|
|
66485
|
+
var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
66486
|
+
|
|
66487
|
+
// src/core/secret-input.ts
|
|
66488
|
+
import fs74 from "node:fs";
|
|
66489
|
+
function clean(value) {
|
|
66490
|
+
if (typeof value !== "string")
|
|
66491
|
+
return;
|
|
66492
|
+
const trimmed = value.trim();
|
|
66493
|
+
return trimmed ? trimmed : undefined;
|
|
66494
|
+
}
|
|
66495
|
+
var STDIN_IDLE_TIMEOUT_MS = 5000;
|
|
66496
|
+
var STDIN_TIMEOUT_MIN_MS = 100;
|
|
66497
|
+
var STDIN_TIMEOUT_MAX_MS = 600000;
|
|
66498
|
+
function stdinTimeoutMs(env3) {
|
|
66499
|
+
const raw = Number(env3.BRAINBASE_STDIN_TIMEOUT_MS);
|
|
66500
|
+
if (!Number.isFinite(raw) || raw <= 0)
|
|
66501
|
+
return STDIN_IDLE_TIMEOUT_MS;
|
|
66502
|
+
return Math.min(Math.max(raw, STDIN_TIMEOUT_MIN_MS), STDIN_TIMEOUT_MAX_MS);
|
|
66503
|
+
}
|
|
66504
|
+
|
|
66505
|
+
class StdinTimeoutError extends Error {
|
|
66506
|
+
constructor(idleTimeoutMs, bytesRead) {
|
|
66507
|
+
super(`stdin went quiet for ${idleTimeoutMs}ms after ${bytesRead} byte(s), before it was closed. ` + "Refusing to use a partial value. If the source is slow, raise " + "BRAINBASE_STDIN_TIMEOUT_MS; if it will not close its end of the pipe, " + "pass the value with a flag or an environment variable instead.");
|
|
66508
|
+
this.name = "StdinTimeoutError";
|
|
66509
|
+
}
|
|
66510
|
+
}
|
|
66511
|
+
function readPipeUntilEof(stream, idleTimeoutMs) {
|
|
66512
|
+
return new Promise((resolve, reject2) => {
|
|
66513
|
+
const chunks = [];
|
|
66514
|
+
let received = 0;
|
|
66515
|
+
let timer;
|
|
66516
|
+
const stopTimer = () => {
|
|
66517
|
+
if (timer !== undefined) {
|
|
66518
|
+
clearTimeout(timer);
|
|
66519
|
+
timer = undefined;
|
|
66520
|
+
}
|
|
66521
|
+
};
|
|
66522
|
+
const restartTimer = () => {
|
|
66523
|
+
stopTimer();
|
|
66524
|
+
timer = setTimeout(onIdle, idleTimeoutMs);
|
|
66525
|
+
};
|
|
66526
|
+
const detach = () => {
|
|
66527
|
+
stopTimer();
|
|
66528
|
+
stream.removeListener("data", onData);
|
|
66529
|
+
stream.removeListener("end", onEnd);
|
|
66530
|
+
stream.removeListener("error", onError);
|
|
66531
|
+
stream.pause();
|
|
66532
|
+
stream.unref?.();
|
|
66533
|
+
};
|
|
66534
|
+
function onIdle() {
|
|
66535
|
+
if (received > 0) {
|
|
66536
|
+
detach();
|
|
66537
|
+
reject2(new StdinTimeoutError(idleTimeoutMs, received));
|
|
66538
|
+
return;
|
|
66539
|
+
}
|
|
66540
|
+
detach();
|
|
66541
|
+
resolve("");
|
|
66542
|
+
}
|
|
66543
|
+
function onData(chunk2) {
|
|
66544
|
+
const buf = Buffer.from(chunk2);
|
|
66545
|
+
received += buf.length;
|
|
66546
|
+
chunks.push(buf);
|
|
66547
|
+
restartTimer();
|
|
66548
|
+
}
|
|
66549
|
+
function onEnd() {
|
|
66550
|
+
detach();
|
|
66551
|
+
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
66552
|
+
}
|
|
66553
|
+
function onError(err) {
|
|
66554
|
+
detach();
|
|
66555
|
+
reject2(err);
|
|
66556
|
+
}
|
|
66557
|
+
stream.on("data", onData);
|
|
66558
|
+
stream.on("end", onEnd);
|
|
66559
|
+
stream.on("error", onError);
|
|
66560
|
+
restartTimer();
|
|
66561
|
+
});
|
|
66562
|
+
}
|
|
66563
|
+
async function defaultReadStdin(env3 = process.env) {
|
|
66564
|
+
if (process.stdin.isTTY)
|
|
66565
|
+
return null;
|
|
66566
|
+
let isRegularFile = false;
|
|
66567
|
+
try {
|
|
66568
|
+
isRegularFile = fs74.fstatSync(0).isFile();
|
|
66569
|
+
} catch {
|
|
66570
|
+
return "";
|
|
66571
|
+
}
|
|
66572
|
+
if (isRegularFile) {
|
|
66573
|
+
try {
|
|
66574
|
+
return fs74.readFileSync(0, "utf8");
|
|
66575
|
+
} catch {
|
|
66576
|
+
return "";
|
|
66577
|
+
}
|
|
66578
|
+
}
|
|
66579
|
+
try {
|
|
66580
|
+
return await readPipeUntilEof(process.stdin, stdinTimeoutMs(env3));
|
|
66581
|
+
} catch (err) {
|
|
66582
|
+
if (err instanceof StdinTimeoutError)
|
|
66583
|
+
throw err;
|
|
66584
|
+
return "";
|
|
66585
|
+
}
|
|
66586
|
+
}
|
|
66587
|
+
async function defaultPrompt(field) {
|
|
66588
|
+
const answer = await re({
|
|
66589
|
+
message: field.label,
|
|
66590
|
+
validate: (v3) => v3 && v3.trim() ? undefined : "Required"
|
|
66591
|
+
});
|
|
66592
|
+
return String(ensureNotCancelled(answer)).trim();
|
|
66593
|
+
}
|
|
66594
|
+
function parseStdinSecrets(raw, missing) {
|
|
66595
|
+
const body = raw.trim();
|
|
66596
|
+
if (!body)
|
|
66597
|
+
return {};
|
|
66598
|
+
if (body.startsWith("{")) {
|
|
66599
|
+
let source;
|
|
66600
|
+
try {
|
|
66601
|
+
source = JSON.parse(body);
|
|
66602
|
+
} catch {
|
|
66603
|
+
throw new Error('stdin looked like JSON but could not be parsed. Pass an object such as {"bot_token":"…","signing_secret":"…"}.');
|
|
66604
|
+
}
|
|
66605
|
+
const out = {};
|
|
66606
|
+
for (const field of missing) {
|
|
66607
|
+
const value = clean(source[field.key]);
|
|
66608
|
+
if (value)
|
|
66609
|
+
out[field.key] = value;
|
|
66610
|
+
}
|
|
66611
|
+
return out;
|
|
66612
|
+
}
|
|
66613
|
+
if (missing.length === 1) {
|
|
66614
|
+
return { [missing[0].key]: body };
|
|
66615
|
+
}
|
|
66616
|
+
throw new Error(`stdin supplies one value, but ${missing.length} are still missing (${missing.map((f4) => f4.key).join(", ")}). Pipe a JSON object instead, or pass the rest as flags.`);
|
|
66617
|
+
}
|
|
66618
|
+
async function resolveSecrets(fields, deps = {}) {
|
|
66619
|
+
const env3 = deps.env ?? process.env;
|
|
66620
|
+
const readStdin = deps.readStdin ?? (() => defaultReadStdin(env3));
|
|
66621
|
+
const prompt = deps.prompt ?? defaultPrompt;
|
|
66622
|
+
const interactive = deps.interactive ?? isInteractive;
|
|
66623
|
+
const resolved = {};
|
|
66624
|
+
for (const field of fields) {
|
|
66625
|
+
const value = clean(field.value) ?? clean(env3[field.envVar]);
|
|
66626
|
+
if (value)
|
|
66627
|
+
resolved[field.key] = value;
|
|
66628
|
+
}
|
|
66629
|
+
let missing = fields.filter((f4) => !resolved[f4.key]);
|
|
66630
|
+
if (missing.length > 0) {
|
|
66631
|
+
const raw = await readStdin();
|
|
66632
|
+
if (raw !== null) {
|
|
66633
|
+
Object.assign(resolved, parseStdinSecrets(raw, missing));
|
|
66634
|
+
missing = fields.filter((f4) => !resolved[f4.key]);
|
|
66635
|
+
}
|
|
66636
|
+
}
|
|
66637
|
+
for (const field of missing) {
|
|
66638
|
+
if (!interactive()) {
|
|
66639
|
+
throw new NonInteractiveError(`${field.label} is required. Pass ${field.flag}, set ${field.envVar}, or pipe it on stdin.`);
|
|
66640
|
+
}
|
|
66641
|
+
resolved[field.key] = await prompt(field);
|
|
66642
|
+
}
|
|
66643
|
+
return resolved;
|
|
66644
|
+
}
|
|
66645
|
+
|
|
66646
|
+
// src/cli/agent-connect.ts
|
|
66647
|
+
async function runAgentConnect(cwd2, target, args, deps = {}) {
|
|
66648
|
+
const json = Boolean(args.json);
|
|
66649
|
+
try {
|
|
66650
|
+
report(await connect(cwd2, target, args, deps, json), json);
|
|
66651
|
+
} catch (err) {
|
|
66652
|
+
if (!json)
|
|
66653
|
+
throw err;
|
|
66654
|
+
reportFailure(err);
|
|
66655
|
+
}
|
|
66656
|
+
}
|
|
66657
|
+
async function connect(cwd2, target, args, deps, json) {
|
|
66658
|
+
if (!target) {
|
|
66659
|
+
throw new Error(`Which integration? Try: ${IMPLEMENTED_INTEGRATIONS.join(", ")}.`);
|
|
66660
|
+
}
|
|
66661
|
+
if (!json)
|
|
66662
|
+
banner(`agent connect ${target}`);
|
|
66663
|
+
const link2 = readLink(cwd2);
|
|
66664
|
+
if (!link2) {
|
|
66665
|
+
throw new Error("This folder is not linked to any agent. Run `brainbase link` first.");
|
|
66666
|
+
}
|
|
66667
|
+
await assertConnectable(link2.agent_id, target, deps);
|
|
66668
|
+
return target === "slack" ? connectSlack(link2.agent_id, args, deps, json) : connectMeeting(link2.agent_id, args, deps, json);
|
|
66669
|
+
}
|
|
66670
|
+
async function assertConnectable(agentId, target, deps) {
|
|
66671
|
+
const fetchConnections = deps.fetchConnections ?? ((id) => api.getAgentConnections(id));
|
|
66672
|
+
const { integrations } = await fetchConnections(agentId);
|
|
66673
|
+
const state = integrations.find((i) => i.name === target);
|
|
66674
|
+
if (!state) {
|
|
66675
|
+
const known = integrations.map((i) => i.name).join(", ");
|
|
66676
|
+
throw new Error(`Unknown integration ${JSON.stringify(target)}. This agent has: ${known}.`);
|
|
66677
|
+
}
|
|
66678
|
+
const action = actionability(state);
|
|
66679
|
+
if (action.kind === "connectable")
|
|
66680
|
+
return;
|
|
66681
|
+
throw new Error(explain(state));
|
|
66682
|
+
}
|
|
66683
|
+
async function connectSlack(agentId, args, deps, json) {
|
|
66684
|
+
const secrets = await resolveSecrets([
|
|
66685
|
+
{
|
|
66686
|
+
key: "bot_token",
|
|
66687
|
+
flag: "--bot-token",
|
|
66688
|
+
envVar: "BRAINBASE_SLACK_BOT_TOKEN",
|
|
66689
|
+
label: "Slack bot token (xoxb-…)",
|
|
66690
|
+
value: args.botToken
|
|
66691
|
+
},
|
|
66692
|
+
{
|
|
66693
|
+
key: "signing_secret",
|
|
66694
|
+
flag: "--signing-secret",
|
|
66695
|
+
envVar: "BRAINBASE_SLACK_SIGNING_SECRET",
|
|
66696
|
+
label: "Slack signing secret",
|
|
66697
|
+
value: args.signingSecret
|
|
66698
|
+
}
|
|
66699
|
+
], { ...deps.secrets, ...json ? { interactive: () => false } : {} });
|
|
66700
|
+
return api.connectSlack(agentId, {
|
|
66701
|
+
bot_token: secrets.bot_token,
|
|
66702
|
+
signing_secret: secrets.signing_secret,
|
|
66703
|
+
...args.appId ? { app_id: args.appId } : {},
|
|
66704
|
+
...args.appName ? { app_name: args.appName } : {}
|
|
66705
|
+
});
|
|
66706
|
+
}
|
|
66707
|
+
async function connectMeeting(agentId, args, deps, json) {
|
|
66708
|
+
const ask = deps.askBotName ?? (() => text({
|
|
66709
|
+
message: "Name for the meeting bot",
|
|
66710
|
+
placeholder: "Notetaker",
|
|
66711
|
+
flagHint: "Pass --bot-name <name>."
|
|
66712
|
+
}));
|
|
66713
|
+
let botName = args.botName?.trim();
|
|
66714
|
+
if (!botName) {
|
|
66715
|
+
if (json) {
|
|
66716
|
+
throw new Error("A meeting bot name is required. Pass --bot-name <name>.");
|
|
66717
|
+
}
|
|
66718
|
+
botName = (await ask()).trim();
|
|
66719
|
+
}
|
|
66720
|
+
if (!botName)
|
|
66721
|
+
throw new Error("A meeting bot name is required. Pass --bot-name <name>.");
|
|
66722
|
+
return api.connectMeeting(agentId, {
|
|
66723
|
+
bot_name: botName,
|
|
66724
|
+
...args.botImageUrl ? { bot_image_url: args.botImageUrl } : {}
|
|
66725
|
+
});
|
|
66726
|
+
}
|
|
66727
|
+
function reportFailure(err) {
|
|
66728
|
+
console.log(JSON.stringify({ error: err.message }, null, 2));
|
|
66729
|
+
process.exitCode = 1;
|
|
66730
|
+
}
|
|
66731
|
+
function report(result2, json) {
|
|
66732
|
+
if (json) {
|
|
66733
|
+
console.log(JSON.stringify(result2, null, 2));
|
|
66734
|
+
return;
|
|
66735
|
+
}
|
|
66736
|
+
const detail = result2.detail ? ` ${import_picocolors34.default.dim(`(${result2.detail})`)}` : "";
|
|
66737
|
+
f2.success(`${result2.name} connected${detail}`);
|
|
66738
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase agent pull")} to pick up the built-in ${result2.name} MCP server.`);
|
|
66739
|
+
}
|
|
66740
|
+
|
|
66741
|
+
// src/cli/agent-connections.ts
|
|
66742
|
+
async function runAgentConnections(cwd2, args) {
|
|
66743
|
+
const json = Boolean(args.json);
|
|
66744
|
+
if (!json)
|
|
66745
|
+
banner("agent connections — what this agent is wired to");
|
|
66746
|
+
const link2 = readLink(cwd2);
|
|
66747
|
+
if (!link2) {
|
|
66748
|
+
if (json) {
|
|
66749
|
+
console.log(JSON.stringify({ linked: false, integrations: [] }, null, 2));
|
|
66750
|
+
process.exitCode = 1;
|
|
66751
|
+
return;
|
|
66752
|
+
}
|
|
66753
|
+
f2.warn("This folder is not linked to any agent.");
|
|
66754
|
+
f2.info(`Run ${import_picocolors35.default.cyan("brainbase link")} first.`);
|
|
66755
|
+
process.exitCode = 1;
|
|
66756
|
+
return;
|
|
66757
|
+
}
|
|
66758
|
+
let connections;
|
|
66759
|
+
try {
|
|
66760
|
+
connections = await api.getAgentConnections(link2.agent_id);
|
|
66761
|
+
} catch (err) {
|
|
66762
|
+
if (!json)
|
|
66763
|
+
throw err;
|
|
66764
|
+
reportFailure(err);
|
|
66765
|
+
return;
|
|
66766
|
+
}
|
|
66767
|
+
if (json) {
|
|
66768
|
+
console.log(JSON.stringify({ linked: true, ...connections }, null, 2));
|
|
66769
|
+
return;
|
|
66770
|
+
}
|
|
66771
|
+
console.log(formatConnections(connections));
|
|
66772
|
+
}
|
|
66773
|
+
function formatConnections(connections) {
|
|
66774
|
+
const lines = [""];
|
|
66775
|
+
for (const integration of connections.integrations) {
|
|
66776
|
+
lines.push(` ${statusMark(integration)} ${import_picocolors35.default.bold(integration.name)}${describe(integration)}`);
|
|
66777
|
+
const hint = hintFor(integration);
|
|
66778
|
+
if (hint)
|
|
66779
|
+
lines.push(` ${import_picocolors35.default.dim(hint)}`);
|
|
66780
|
+
}
|
|
66781
|
+
lines.push("");
|
|
66782
|
+
return lines.join(`
|
|
66783
|
+
`);
|
|
66784
|
+
}
|
|
66785
|
+
function statusMark(integration) {
|
|
66786
|
+
return integration.connected ? import_picocolors35.default.green("✓") : import_picocolors35.default.dim("·");
|
|
66787
|
+
}
|
|
66788
|
+
function describe(integration) {
|
|
66789
|
+
if (!integration.connected)
|
|
66790
|
+
return ` ${import_picocolors35.default.dim("not connected")}`;
|
|
66791
|
+
return integration.detail ? ` ${import_picocolors35.default.dim(integration.detail)}` : ` ${import_picocolors35.default.dim("connected")}`;
|
|
66792
|
+
}
|
|
66793
|
+
function hintFor(integration) {
|
|
66794
|
+
const action = actionability(integration);
|
|
66795
|
+
if (integration.connected) {
|
|
66796
|
+
return action.kind === "connectable" ? `brainbase agent disconnect ${integration.name}` : undefined;
|
|
66797
|
+
}
|
|
66798
|
+
return explain(integration);
|
|
66799
|
+
}
|
|
66800
|
+
|
|
66801
|
+
// src/cli/agent-disconnect.ts
|
|
66802
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
66803
|
+
async function runAgentDisconnect(cwd2, target, args) {
|
|
66804
|
+
const json = Boolean(args.json);
|
|
66805
|
+
try {
|
|
66806
|
+
await disconnect(cwd2, target, args, json);
|
|
66807
|
+
} catch (err) {
|
|
66808
|
+
if (!json)
|
|
66809
|
+
throw err;
|
|
66810
|
+
reportFailure(err);
|
|
66811
|
+
}
|
|
66812
|
+
}
|
|
66813
|
+
async function disconnect(cwd2, target, args, json) {
|
|
66814
|
+
if (!target) {
|
|
66815
|
+
throw new Error(`Which integration? Try: ${IMPLEMENTED_INTEGRATIONS.join(", ")}.`);
|
|
66816
|
+
}
|
|
66817
|
+
if (!isImplemented(target)) {
|
|
66818
|
+
throw new Error(`Cannot disconnect ${JSON.stringify(target)} from the CLI. Try: ${IMPLEMENTED_INTEGRATIONS.join(", ")}.`);
|
|
66819
|
+
}
|
|
66820
|
+
if (!json)
|
|
66821
|
+
banner(`agent disconnect ${target}`);
|
|
66822
|
+
const link2 = readLink(cwd2);
|
|
66823
|
+
if (!link2) {
|
|
66824
|
+
throw new Error("This folder is not linked to any agent. Run `brainbase link` first.");
|
|
66825
|
+
}
|
|
66826
|
+
if (!json && !autoProceed(args.yes)) {
|
|
66827
|
+
const ok = ensureNotCancelled(await se({ message: `Disconnect ${target} from ${link2.name}?` }));
|
|
66828
|
+
if (!ok) {
|
|
66829
|
+
f2.info("Nothing changed.");
|
|
66830
|
+
return;
|
|
66831
|
+
}
|
|
66832
|
+
}
|
|
66833
|
+
const result2 = await api.disconnectIntegration(link2.agent_id, target);
|
|
66834
|
+
if (json) {
|
|
66835
|
+
console.log(JSON.stringify(result2, null, 2));
|
|
66836
|
+
return;
|
|
66837
|
+
}
|
|
66838
|
+
f2.success(`${target} disconnected`);
|
|
66839
|
+
f2.info(`Run ${import_picocolors36.default.cyan("brainbase agent pull")} to drop the built-in ${target} MCP server locally.`);
|
|
66840
|
+
}
|
|
66841
|
+
|
|
66399
66842
|
// src/cli/agent.ts
|
|
66400
66843
|
async function runAgent(cwd2, sub, args, opts) {
|
|
66401
66844
|
if (args.some((arg) => arg === "--help" || arg === "-h")) {
|
|
@@ -66446,6 +66889,23 @@ async function runAgent(cwd2, sub, args, opts) {
|
|
|
66446
66889
|
case "status":
|
|
66447
66890
|
await runAgentStatus(cwd2, { json: opts.json });
|
|
66448
66891
|
return;
|
|
66892
|
+
case "connections":
|
|
66893
|
+
await runAgentConnections(cwd2, { json: opts.json });
|
|
66894
|
+
return;
|
|
66895
|
+
case "connect":
|
|
66896
|
+
await runAgentConnect(cwd2, args[0], {
|
|
66897
|
+
botToken: opts.botToken,
|
|
66898
|
+
signingSecret: opts.signingSecret,
|
|
66899
|
+
appId: opts.appId,
|
|
66900
|
+
appName: opts.appName,
|
|
66901
|
+
botName: opts.botName,
|
|
66902
|
+
botImageUrl: opts.botImageUrl,
|
|
66903
|
+
json: opts.json
|
|
66904
|
+
});
|
|
66905
|
+
return;
|
|
66906
|
+
case "disconnect":
|
|
66907
|
+
await runAgentDisconnect(cwd2, args[0], { yes: opts.yes, json: opts.json });
|
|
66908
|
+
return;
|
|
66449
66909
|
case "env":
|
|
66450
66910
|
await runAgentEnv(cwd2, { shell: opts.shell });
|
|
66451
66911
|
return;
|
|
@@ -66465,25 +66925,31 @@ async function runAgent(cwd2, sub, args, opts) {
|
|
|
66465
66925
|
function printHelp() {
|
|
66466
66926
|
const out = [];
|
|
66467
66927
|
out.push("");
|
|
66468
|
-
out.push(` ${
|
|
66928
|
+
out.push(` ${import_picocolors37.default.bold("brainbase agent")} ${import_picocolors37.default.dim("<sub> [options]")}`);
|
|
66929
|
+
out.push("");
|
|
66930
|
+
out.push(` ${import_picocolors37.default.cyan("list")} ${import_picocolors37.default.dim("show the agents in a team, with the ids `brainbase link` takes (--json for scripts)")}`);
|
|
66931
|
+
out.push(` ${import_picocolors37.default.cyan("create")} ${import_picocolors37.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
66932
|
+
out.push(` ${import_picocolors37.default.cyan("pull")} ${import_picocolors37.default.dim("[<id>]")} ${import_picocolors37.default.dim("apply cloud changes into this folder — pass <id> to switch (--force to override); --run-entrypoint to also execute the agent entrypoint")}`);
|
|
66933
|
+
out.push(` ${import_picocolors37.default.cyan("push")} ${import_picocolors37.default.dim("send local changes to the cloud — instructions, playbooks, skills, MCPs, entrypoint (--force to overwrite cloud-side conflicts with local)")}`);
|
|
66934
|
+
out.push(` ${import_picocolors37.default.cyan("unpack")} ${import_picocolors37.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
|
|
66935
|
+
out.push(` ${import_picocolors37.default.cyan("status")} ${import_picocolors37.default.dim("show what would push, what would pull, and which manifest blocks are ignored (--json for scripts)")}`);
|
|
66936
|
+
out.push(` ${import_picocolors37.default.cyan("connections")} ${import_picocolors37.default.dim("show which integrations this agent is wired to (--json for scripts)")}`);
|
|
66937
|
+
out.push(` ${import_picocolors37.default.cyan("connect")} ${import_picocolors37.default.dim("<name>")} ${import_picocolors37.default.dim("connect slack or meeting — credentials come from flags, env, or stdin")}`);
|
|
66938
|
+
out.push(` ${import_picocolors37.default.cyan("disconnect")} ${import_picocolors37.default.dim("<name>")} ${import_picocolors37.default.dim("revoke a slack or meeting install")}`);
|
|
66939
|
+
out.push(` ${import_picocolors37.default.cyan("env")} ${import_picocolors37.default.dim('print export statements — use with `eval "$(brainbase agent env)"`')}`);
|
|
66469
66940
|
out.push("");
|
|
66470
|
-
out.push(` ${
|
|
66471
|
-
out.push(` ${
|
|
66472
|
-
out.push(` ${import_picocolors34.default.cyan("pull")} ${import_picocolors34.default.dim("[<id>]")} ${import_picocolors34.default.dim("apply cloud changes into this folder — pass <id> to switch (--force to override); --run-entrypoint to also execute the agent entrypoint")}`);
|
|
66473
|
-
out.push(` ${import_picocolors34.default.cyan("push")} ${import_picocolors34.default.dim("send local changes to the cloud — instructions, playbooks, skills, MCPs, entrypoint (--force to overwrite cloud-side conflicts with local)")}`);
|
|
66474
|
-
out.push(` ${import_picocolors34.default.cyan("unpack")} ${import_picocolors34.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
|
|
66475
|
-
out.push(` ${import_picocolors34.default.cyan("status")} ${import_picocolors34.default.dim("show what would push, what would pull, and which manifest blocks are ignored (--json for scripts)")}`);
|
|
66476
|
-
out.push(` ${import_picocolors34.default.cyan("env")} ${import_picocolors34.default.dim('print export statements — use with `eval "$(brainbase agent env)"`')}`);
|
|
66941
|
+
out.push(` ${import_picocolors37.default.dim("Slack credentials:")} ${import_picocolors37.default.dim("--bot-token / BRAINBASE_SLACK_BOT_TOKEN, --signing-secret / BRAINBASE_SLACK_SIGNING_SECRET,")}`);
|
|
66942
|
+
out.push(` ${import_picocolors37.default.dim('or pipe {"bot_token":"…","signing_secret":"…"} on stdin to keep them out of argv.')}`);
|
|
66477
66943
|
out.push("");
|
|
66478
66944
|
console.log(out.join(`
|
|
66479
66945
|
`));
|
|
66480
66946
|
}
|
|
66481
66947
|
|
|
66482
66948
|
// src/cli/team.ts
|
|
66483
|
-
var
|
|
66949
|
+
var import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
66484
66950
|
|
|
66485
66951
|
// src/cli/team-list.ts
|
|
66486
|
-
var
|
|
66952
|
+
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
66487
66953
|
async function runTeamList(args) {
|
|
66488
66954
|
if (!args.json)
|
|
66489
66955
|
banner("team list — teams you can put agents in");
|
|
@@ -66503,25 +66969,25 @@ async function runTeamList(args) {
|
|
|
66503
66969
|
function formatTeamList(grouped) {
|
|
66504
66970
|
const lines = [""];
|
|
66505
66971
|
if (grouped.length === 0) {
|
|
66506
|
-
lines.push(` ${
|
|
66972
|
+
lines.push(` ${import_picocolors38.default.dim("You are not a member of any organization.")}`, "");
|
|
66507
66973
|
return lines.join(`
|
|
66508
66974
|
`);
|
|
66509
66975
|
}
|
|
66510
66976
|
const nameWidth = Math.max(...grouped.flatMap(({ teams }) => teams.map((t) => t.name.length)), 0);
|
|
66511
66977
|
for (const { org, teams, error } of grouped) {
|
|
66512
|
-
const slug = org.slug ? ` ${
|
|
66513
|
-
lines.push(` ${
|
|
66978
|
+
const slug = org.slug ? ` ${import_picocolors38.default.dim(org.slug)}` : "";
|
|
66979
|
+
lines.push(` ${import_picocolors38.default.bold(org.name)}${slug}`);
|
|
66514
66980
|
if (error) {
|
|
66515
|
-
lines.push(` ${
|
|
66981
|
+
lines.push(` ${import_picocolors38.default.red(`could not load teams: ${error}`)}`);
|
|
66516
66982
|
} else if (teams.length === 0) {
|
|
66517
|
-
lines.push(` ${
|
|
66983
|
+
lines.push(` ${import_picocolors38.default.dim("no teams yet — create one in the web app")}`);
|
|
66518
66984
|
}
|
|
66519
66985
|
for (const team of teams) {
|
|
66520
|
-
lines.push(` ${team.name.padEnd(nameWidth)} ${
|
|
66986
|
+
lines.push(` ${team.name.padEnd(nameWidth)} ${import_picocolors38.default.dim(team.id)}`);
|
|
66521
66987
|
}
|
|
66522
66988
|
lines.push("");
|
|
66523
66989
|
}
|
|
66524
|
-
lines.push(` ${
|
|
66990
|
+
lines.push(` ${import_picocolors38.default.dim("list a team’s agents with")} ${import_picocolors38.default.cyan("brainbase agent list --team <id>")}`, "");
|
|
66525
66991
|
return lines.join(`
|
|
66526
66992
|
`);
|
|
66527
66993
|
}
|
|
@@ -66552,28 +67018,28 @@ async function runTeam(sub, args, opts) {
|
|
|
66552
67018
|
function printHelp2() {
|
|
66553
67019
|
const out = [];
|
|
66554
67020
|
out.push("");
|
|
66555
|
-
out.push(` ${
|
|
67021
|
+
out.push(` ${import_picocolors39.default.bold("brainbase team")} ${import_picocolors39.default.dim("<sub> [options]")}`);
|
|
66556
67022
|
out.push("");
|
|
66557
|
-
out.push(` ${
|
|
67023
|
+
out.push(` ${import_picocolors39.default.cyan("list")} ${import_picocolors39.default.dim("show the teams you can create agents in, grouped by organization")}`);
|
|
66558
67024
|
out.push("");
|
|
66559
|
-
out.push(` ${
|
|
66560
|
-
out.push(` ${
|
|
67025
|
+
out.push(` ${import_picocolors39.default.dim("--org <id-or-slug>")} ${import_picocolors39.default.dim("limit to one organization")}`);
|
|
67026
|
+
out.push(` ${import_picocolors39.default.dim("--json")} ${import_picocolors39.default.dim("machine-readable output")}`);
|
|
66561
67027
|
out.push("");
|
|
66562
67028
|
console.log(out.join(`
|
|
66563
67029
|
`));
|
|
66564
67030
|
}
|
|
66565
67031
|
|
|
66566
67032
|
// src/cli/orchestration.ts
|
|
66567
|
-
var
|
|
67033
|
+
var import_picocolors46 = __toESM(require_picocolors(), 1);
|
|
66568
67034
|
|
|
66569
67035
|
// src/cli/orchestration-pull.ts
|
|
66570
67036
|
import path86 from "node:path";
|
|
66571
|
-
import
|
|
66572
|
-
var
|
|
67037
|
+
import fs78 from "node:fs";
|
|
67038
|
+
var import_picocolors40 = __toESM(require_picocolors(), 1);
|
|
66573
67039
|
|
|
66574
67040
|
// src/core/orchestration-manifest.ts
|
|
66575
67041
|
import path83 from "node:path";
|
|
66576
|
-
import
|
|
67042
|
+
import fs75 from "node:fs";
|
|
66577
67043
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
66578
67044
|
var ORCH_MANIFEST_FILE = "brainbase-orchestration.yaml";
|
|
66579
67045
|
var ORCH_MEMBERS_DIR = "agents";
|
|
@@ -66629,13 +67095,13 @@ function orchManifestPath(cwd2) {
|
|
|
66629
67095
|
return path83.join(cwd2, ORCH_MANIFEST_FILE);
|
|
66630
67096
|
}
|
|
66631
67097
|
function hasOrchManifest(cwd2) {
|
|
66632
|
-
return
|
|
67098
|
+
return fs75.existsSync(orchManifestPath(cwd2));
|
|
66633
67099
|
}
|
|
66634
67100
|
function readOrchManifest(cwd2) {
|
|
66635
67101
|
const p2 = orchManifestPath(cwd2);
|
|
66636
|
-
if (!
|
|
67102
|
+
if (!fs75.existsSync(p2))
|
|
66637
67103
|
return null;
|
|
66638
|
-
const raw =
|
|
67104
|
+
const raw = fs75.readFileSync(p2, "utf8");
|
|
66639
67105
|
let parsed;
|
|
66640
67106
|
try {
|
|
66641
67107
|
parsed = import_yaml4.default.parse(raw);
|
|
@@ -66656,7 +67122,7 @@ function writeOrchManifest(cwd2, manifest) {
|
|
|
66656
67122
|
` + " `brainbase orchestration push`. Member agents live under ./agents/." + `
|
|
66657
67123
|
Schedule triggers are writable. App/Pipedream triggers are preserved
|
|
66658
67124
|
` + " as read-only context and ignored by `orchestration push`.";
|
|
66659
|
-
|
|
67125
|
+
fs75.writeFileSync(orchManifestPath(cwd2), String(doc), "utf8");
|
|
66660
67126
|
}
|
|
66661
67127
|
function memberDir(cwd2, slug) {
|
|
66662
67128
|
return path83.join(cwd2, ORCH_MEMBERS_DIR, slug);
|
|
@@ -66694,7 +67160,7 @@ function resolveMemberSlugs(members) {
|
|
|
66694
67160
|
|
|
66695
67161
|
// src/core/orchestration-link.ts
|
|
66696
67162
|
import path84 from "node:path";
|
|
66697
|
-
import
|
|
67163
|
+
import fs76 from "node:fs";
|
|
66698
67164
|
var ORCH_LINK_FILE = "orchestration-link.json";
|
|
66699
67165
|
var ORCH_SYNC_STATE_FILE = "orchestration-sync-state.json";
|
|
66700
67166
|
var OrchestrationLinkSchema = exports_external.object({
|
|
@@ -66745,12 +67211,12 @@ function readOrchLink(cwd2) {
|
|
|
66745
67211
|
}
|
|
66746
67212
|
function writeOrchLink(cwd2, link2) {
|
|
66747
67213
|
ensureDir(path84.join(cwd2, LINK_DIR));
|
|
66748
|
-
const
|
|
67214
|
+
const clean2 = {};
|
|
66749
67215
|
for (const [k3, v3] of Object.entries(link2)) {
|
|
66750
67216
|
if (v3 !== null && v3 !== undefined)
|
|
66751
|
-
|
|
67217
|
+
clean2[k3] = v3;
|
|
66752
67218
|
}
|
|
66753
|
-
writeJson(orchLinkPath(cwd2),
|
|
67219
|
+
writeJson(orchLinkPath(cwd2), clean2);
|
|
66754
67220
|
ensureGitignore2(cwd2);
|
|
66755
67221
|
}
|
|
66756
67222
|
function readOrchSyncState(cwd2) {
|
|
@@ -66774,12 +67240,12 @@ function ensureGitignore2(cwd2) {
|
|
|
66774
67240
|
`;
|
|
66775
67241
|
try {
|
|
66776
67242
|
if (!exists(ignorePath)) {
|
|
66777
|
-
|
|
67243
|
+
fs76.writeFileSync(ignorePath, desired);
|
|
66778
67244
|
return;
|
|
66779
67245
|
}
|
|
66780
|
-
const current =
|
|
67246
|
+
const current = fs76.readFileSync(ignorePath, "utf8");
|
|
66781
67247
|
if (!current.split(/\r?\n/).some((l2) => l2.trim() === ORCH_SYNC_STATE_FILE)) {
|
|
66782
|
-
|
|
67248
|
+
fs76.writeFileSync(ignorePath, current.endsWith(`
|
|
66783
67249
|
`) ? current + desired : current + `
|
|
66784
67250
|
` + desired);
|
|
66785
67251
|
}
|
|
@@ -66788,7 +67254,7 @@ function ensureGitignore2(cwd2) {
|
|
|
66788
67254
|
|
|
66789
67255
|
// src/core/agent-fresh-install.ts
|
|
66790
67256
|
import path85 from "node:path";
|
|
66791
|
-
import
|
|
67257
|
+
import fs77 from "node:fs";
|
|
66792
67258
|
import os15 from "node:os";
|
|
66793
67259
|
async function installAgentFresh(input) {
|
|
66794
67260
|
const { cwd: cwd2, agent, cloud, harness } = input;
|
|
@@ -66879,19 +67345,19 @@ async function installAgentFresh(input) {
|
|
|
66879
67345
|
};
|
|
66880
67346
|
} finally {
|
|
66881
67347
|
try {
|
|
66882
|
-
|
|
67348
|
+
fs77.rmSync(stageRoot, { recursive: true, force: true });
|
|
66883
67349
|
} catch {}
|
|
66884
67350
|
}
|
|
66885
67351
|
}
|
|
66886
67352
|
function stageManifestComponents2(components) {
|
|
66887
|
-
const root =
|
|
67353
|
+
const root = fs77.mkdtempSync(path85.join(os15.tmpdir(), "brainbase-orch-pull-"));
|
|
66888
67354
|
for (const c2 of components) {
|
|
66889
67355
|
const compDir = path85.join(root, c2.type, c2.slug);
|
|
66890
67356
|
ensureDir(compDir);
|
|
66891
67357
|
for (const f4 of c2.files) {
|
|
66892
67358
|
const target = path85.join(compDir, f4.path);
|
|
66893
67359
|
ensureDir(path85.dirname(target));
|
|
66894
|
-
|
|
67360
|
+
fs77.writeFileSync(target, f4.content);
|
|
66895
67361
|
}
|
|
66896
67362
|
}
|
|
66897
67363
|
return root;
|
|
@@ -66926,7 +67392,7 @@ function materializeInstructions2(cwd2, cloud) {
|
|
|
66926
67392
|
continue;
|
|
66927
67393
|
const target = path85.join(cwd2, DEFAULT_INSTRUCTIONS_FILE);
|
|
66928
67394
|
ensureDir(path85.dirname(target));
|
|
66929
|
-
|
|
67395
|
+
fs77.writeFileSync(target, normalizeInstructionBody(body), "utf8");
|
|
66930
67396
|
return;
|
|
66931
67397
|
}
|
|
66932
67398
|
}
|
|
@@ -66940,7 +67406,7 @@ function materializePlaybooks2(cwd2, cloud) {
|
|
|
66940
67406
|
const { body } = stripPlaybookFrontmatter(raw);
|
|
66941
67407
|
const target = path85.join(cwd2, DEFAULT_PLAYBOOKS_DIR, `${c2.slug}.md`);
|
|
66942
67408
|
ensureDir(path85.dirname(target));
|
|
66943
|
-
|
|
67409
|
+
fs77.writeFileSync(target, body, "utf8");
|
|
66944
67410
|
}
|
|
66945
67411
|
}
|
|
66946
67412
|
function buildManifestFromCloud(cloud, agent, localOnly = {}) {
|
|
@@ -67089,8 +67555,8 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67089
67555
|
orchId = args.orchestrationId;
|
|
67090
67556
|
} else {
|
|
67091
67557
|
f2.warn("This folder is not linked to any orchestration.");
|
|
67092
|
-
f2.info(`Run ${
|
|
67093
|
-
or ${
|
|
67558
|
+
f2.info(`Run ${import_picocolors40.default.cyan("brainbase orchestration pull <id>")} with an orchestration id,
|
|
67559
|
+
or ${import_picocolors40.default.cyan("brainbase orchestration list")} to find one.`);
|
|
67094
67560
|
return;
|
|
67095
67561
|
}
|
|
67096
67562
|
const sp = de();
|
|
@@ -67109,24 +67575,24 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67109
67575
|
const slugFor = (agentId) => slugByAgent.get(agentId) ?? agentId;
|
|
67110
67576
|
const planLines = [];
|
|
67111
67577
|
planLines.push("");
|
|
67112
|
-
planLines.push(` ${
|
|
67578
|
+
planLines.push(` ${import_picocolors40.default.bold(cloud.name)} ${import_picocolors40.default.dim(`(${cloud.id})`)}`);
|
|
67113
67579
|
if (cloud.description)
|
|
67114
|
-
planLines.push(` ${
|
|
67580
|
+
planLines.push(` ${import_picocolors40.default.dim(cloud.description)}`);
|
|
67115
67581
|
planLines.push("");
|
|
67116
|
-
planLines.push(` ${
|
|
67582
|
+
planLines.push(` ${import_picocolors40.default.dim("members:")}`);
|
|
67117
67583
|
for (const m3 of cloud.members) {
|
|
67118
67584
|
const skipped = !m3.manifest;
|
|
67119
|
-
const tail2 = skipped ?
|
|
67120
|
-
planLines.push(` ${
|
|
67585
|
+
const tail2 = skipped ? import_picocolors40.default.red(" (manifest unavailable — skipped)") : "";
|
|
67586
|
+
planLines.push(` ${import_picocolors40.default.cyan("•")} ${import_picocolors40.default.bold(slugFor(m3.agent_id))} ${import_picocolors40.default.dim(`(${m3.name})`)}${tail2}`);
|
|
67121
67587
|
}
|
|
67122
67588
|
if (cloud.edges.length) {
|
|
67123
67589
|
planLines.push("");
|
|
67124
|
-
planLines.push(` ${
|
|
67590
|
+
planLines.push(` ${import_picocolors40.default.dim("edges:")}`);
|
|
67125
67591
|
for (const e2 of cloud.edges) {
|
|
67126
67592
|
const from = slugFor(e2.from_agent_id);
|
|
67127
67593
|
const to2 = slugFor(e2.to_agent_id);
|
|
67128
|
-
const desc = e2.description ? ` ${
|
|
67129
|
-
planLines.push(` ${
|
|
67594
|
+
const desc = e2.description ? ` ${import_picocolors40.default.dim("— " + e2.description)}` : "";
|
|
67595
|
+
planLines.push(` ${import_picocolors40.default.cyan(from)} ${import_picocolors40.default.dim("→")} ${import_picocolors40.default.cyan(to2)}${desc}`);
|
|
67130
67596
|
}
|
|
67131
67597
|
}
|
|
67132
67598
|
planLines.push("");
|
|
@@ -67135,7 +67601,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67135
67601
|
const isRefresh = !!existingLink;
|
|
67136
67602
|
if (!autoProceed(args.yes) && !isRefresh) {
|
|
67137
67603
|
const ok = await se({
|
|
67138
|
-
message: `Pull into ${
|
|
67604
|
+
message: `Pull into ${import_picocolors40.default.bold(cwd2)}?`,
|
|
67139
67605
|
initialValue: true
|
|
67140
67606
|
});
|
|
67141
67607
|
if (!ensureNotCancelled(ok)) {
|
|
@@ -67144,7 +67610,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67144
67610
|
}
|
|
67145
67611
|
}
|
|
67146
67612
|
const fallbackHarness = args.harness ?? "claude-code";
|
|
67147
|
-
|
|
67613
|
+
fs78.mkdirSync(cwd2, { recursive: true });
|
|
67148
67614
|
if (hasOrchManifest(cwd2) && existingLink && existingLink.orchestration_id !== orchId) {
|
|
67149
67615
|
f2.error(`This folder is linked to orchestration ${existingLink.orchestration_id}, not ${orchId}. Move to a fresh directory or unlink first.`);
|
|
67150
67616
|
return;
|
|
@@ -67179,7 +67645,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67179
67645
|
scope: "project",
|
|
67180
67646
|
pullSecrets: true
|
|
67181
67647
|
});
|
|
67182
|
-
memberSp.stop(`Installed ${
|
|
67648
|
+
memberSp.stop(`Installed ${import_picocolors40.default.bold(slug)} ${import_picocolors40.default.dim(`(${m3.manifest.components.length} components)`)}.`);
|
|
67183
67649
|
installedMembers.push({
|
|
67184
67650
|
agent_id: m3.agent_id,
|
|
67185
67651
|
slug,
|
|
@@ -67240,7 +67706,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67240
67706
|
payload_schema: e2.payload_schema ?? {}
|
|
67241
67707
|
}))
|
|
67242
67708
|
});
|
|
67243
|
-
$e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path86.basename(cwd2)}/ ${
|
|
67709
|
+
$e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path86.basename(cwd2)}/ ${import_picocolors40.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
|
|
67244
67710
|
}
|
|
67245
67711
|
function handleApiError5(err) {
|
|
67246
67712
|
if (err instanceof ApiError) {
|
|
@@ -67257,7 +67723,7 @@ function handleApiError5(err) {
|
|
|
67257
67723
|
}
|
|
67258
67724
|
|
|
67259
67725
|
// src/cli/orchestration-push.ts
|
|
67260
|
-
var
|
|
67726
|
+
var import_picocolors41 = __toESM(require_picocolors(), 1);
|
|
67261
67727
|
|
|
67262
67728
|
// src/core/orchestration-outgoing.ts
|
|
67263
67729
|
function buildOrchestrationGraphPayload(manifest, slugToAgentId) {
|
|
@@ -67340,7 +67806,7 @@ function findUnpushableMembers(cwd2, members) {
|
|
|
67340
67806
|
continue;
|
|
67341
67807
|
}
|
|
67342
67808
|
if (!memberManifest.id) {
|
|
67343
|
-
f2.error(`${m3.slug}: ${AGENT_MANIFEST_FILE} is unclaimed (no ${
|
|
67809
|
+
f2.error(`${m3.slug}: ${AGENT_MANIFEST_FILE} is unclaimed (no ${import_picocolors41.default.cyan("id")}), so there is nothing to push to.`);
|
|
67344
67810
|
blocked.push(m3.slug);
|
|
67345
67811
|
continue;
|
|
67346
67812
|
}
|
|
@@ -67355,12 +67821,12 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
67355
67821
|
const link2 = readOrchLink(cwd2);
|
|
67356
67822
|
if (!link2) {
|
|
67357
67823
|
f2.warn("This folder is not linked to any orchestration.");
|
|
67358
|
-
f2.info(`Run ${
|
|
67824
|
+
f2.info(`Run ${import_picocolors41.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
67359
67825
|
return;
|
|
67360
67826
|
}
|
|
67361
67827
|
if (!hasOrchManifest(cwd2)) {
|
|
67362
|
-
f2.warn(`No ${
|
|
67363
|
-
f2.info(`Run ${
|
|
67828
|
+
f2.warn(`No ${import_picocolors41.default.bold(ORCH_MANIFEST_FILE)} here.`);
|
|
67829
|
+
f2.info(`Run ${import_picocolors41.default.cyan("brainbase orchestration pull")} to materialise the manifest before pushing.`);
|
|
67364
67830
|
return;
|
|
67365
67831
|
}
|
|
67366
67832
|
let manifest;
|
|
@@ -67384,7 +67850,7 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
67384
67850
|
}
|
|
67385
67851
|
if (missing.length) {
|
|
67386
67852
|
f2.error(`Missing local checkouts for: ${missing.join(", ")}.`);
|
|
67387
|
-
f2.info(`Run ${
|
|
67853
|
+
f2.info(`Run ${import_picocolors41.default.cyan("brainbase orchestration pull")} to materialise the missing folders.`);
|
|
67388
67854
|
process.exitCode = 1;
|
|
67389
67855
|
return;
|
|
67390
67856
|
}
|
|
@@ -67405,13 +67871,13 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
67405
67871
|
}
|
|
67406
67872
|
}
|
|
67407
67873
|
const plan = [""];
|
|
67408
|
-
plan.push(` ${
|
|
67409
|
-
plan.push(` ${
|
|
67874
|
+
plan.push(` ${import_picocolors41.default.bold(link2.name)} ${import_picocolors41.default.dim(`(${link2.orchestration_id})`)}`);
|
|
67875
|
+
plan.push(` ${import_picocolors41.default.dim(`${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}, ${graph.triggers.length} trigger${graph.triggers.length === 1 ? "" : "s"}`)}`);
|
|
67410
67876
|
plan.push("");
|
|
67411
67877
|
if (!args.graphOnly) {
|
|
67412
|
-
plan.push(` ${
|
|
67878
|
+
plan.push(` ${import_picocolors41.default.dim("per-member agent push:")}`);
|
|
67413
67879
|
for (const m3 of manifest.members) {
|
|
67414
|
-
plan.push(` ${
|
|
67880
|
+
plan.push(` ${import_picocolors41.default.cyan("•")} ${import_picocolors41.default.bold(m3.slug)}`);
|
|
67415
67881
|
}
|
|
67416
67882
|
plan.push("");
|
|
67417
67883
|
}
|
|
@@ -67431,7 +67897,7 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
67431
67897
|
for (const m3 of manifest.members) {
|
|
67432
67898
|
const dir = memberDir(cwd2, m3.slug);
|
|
67433
67899
|
console.log("");
|
|
67434
|
-
console.log(`${
|
|
67900
|
+
console.log(`${import_picocolors41.default.dim("───")} ${import_picocolors41.default.bold(m3.slug)} ${import_picocolors41.default.dim("───")}`);
|
|
67435
67901
|
const exitCodeBeforePush = process.exitCode;
|
|
67436
67902
|
try {
|
|
67437
67903
|
await runAgentPush(dir, { yes: true });
|
|
@@ -67495,7 +67961,7 @@ function handleApiError6(err) {
|
|
|
67495
67961
|
f2.error("You do not have access to this orchestration.");
|
|
67496
67962
|
} else if (err.status === 409) {
|
|
67497
67963
|
f2.error(err.message);
|
|
67498
|
-
f2.info(`Run ${
|
|
67964
|
+
f2.info(`Run ${import_picocolors41.default.cyan("brainbase orchestration pull")} to reconcile, then push again.`);
|
|
67499
67965
|
} else {
|
|
67500
67966
|
f2.error(err.message);
|
|
67501
67967
|
}
|
|
@@ -67505,13 +67971,13 @@ function handleApiError6(err) {
|
|
|
67505
67971
|
}
|
|
67506
67972
|
|
|
67507
67973
|
// src/cli/orchestration-status.ts
|
|
67508
|
-
var
|
|
67974
|
+
var import_picocolors42 = __toESM(require_picocolors(), 1);
|
|
67509
67975
|
async function runOrchestrationStatus(cwd2) {
|
|
67510
67976
|
banner("orchestration status — what changed locally, remotely, both");
|
|
67511
67977
|
const link2 = readOrchLink(cwd2);
|
|
67512
67978
|
if (!link2) {
|
|
67513
67979
|
f2.warn("This folder is not linked to any orchestration.");
|
|
67514
|
-
f2.info(`Run ${
|
|
67980
|
+
f2.info(`Run ${import_picocolors42.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
67515
67981
|
return;
|
|
67516
67982
|
}
|
|
67517
67983
|
const localManifest = hasOrchManifest(cwd2) ? readOrchManifest(cwd2) : null;
|
|
@@ -67534,8 +68000,8 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67534
68000
|
}
|
|
67535
68001
|
const lines = [];
|
|
67536
68002
|
lines.push("");
|
|
67537
|
-
lines.push(` ${
|
|
67538
|
-
lines.push(` ${
|
|
68003
|
+
lines.push(` ${import_picocolors42.default.bold(link2.name)} ${import_picocolors42.default.dim(`(${link2.orchestration_id})`)}`);
|
|
68004
|
+
lines.push(` ${import_picocolors42.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
|
|
67539
68005
|
lines.push("");
|
|
67540
68006
|
const localSlugByAgentId = new Map;
|
|
67541
68007
|
for (const m3 of localManifest?.members ?? []) {
|
|
@@ -67549,12 +68015,12 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67549
68015
|
const membersAdded = [...localMemberSet].filter((s3) => !cloudMemberSet.has(s3));
|
|
67550
68016
|
const membersRemoved = [...cloudMemberSet].filter((s3) => !localMemberSet.has(s3));
|
|
67551
68017
|
if (membersAdded.length || membersRemoved.length) {
|
|
67552
|
-
lines.push(` ${
|
|
68018
|
+
lines.push(` ${import_picocolors42.default.bold("members")}`);
|
|
67553
68019
|
for (const slug of membersAdded) {
|
|
67554
|
-
lines.push(` ${
|
|
68020
|
+
lines.push(` ${import_picocolors42.default.yellow("→ push")} added in yaml: ${import_picocolors42.default.bold(slug)}`);
|
|
67555
68021
|
}
|
|
67556
68022
|
for (const slug of membersRemoved) {
|
|
67557
|
-
lines.push(` ${
|
|
68023
|
+
lines.push(` ${import_picocolors42.default.cyan("← pull")} added on cloud: ${import_picocolors42.default.bold(slug)}`);
|
|
67558
68024
|
}
|
|
67559
68025
|
lines.push("");
|
|
67560
68026
|
}
|
|
@@ -67569,11 +68035,11 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67569
68035
|
const edgesAdded = [...localEdges.keys()].filter((k3) => !cloudEdges.has(k3));
|
|
67570
68036
|
const edgesRemoved = [...cloudEdges.keys()].filter((k3) => !localEdges.has(k3));
|
|
67571
68037
|
if (edgesAdded.length || edgesRemoved.length) {
|
|
67572
|
-
lines.push(` ${
|
|
68038
|
+
lines.push(` ${import_picocolors42.default.bold("edges")}`);
|
|
67573
68039
|
for (const k3 of edgesAdded)
|
|
67574
|
-
lines.push(` ${
|
|
68040
|
+
lines.push(` ${import_picocolors42.default.yellow("→ push")} added in yaml: ${k3}`);
|
|
67575
68041
|
for (const k3 of edgesRemoved)
|
|
67576
|
-
lines.push(` ${
|
|
68042
|
+
lines.push(` ${import_picocolors42.default.cyan("← pull")} added on cloud: ${k3}`);
|
|
67577
68043
|
lines.push("");
|
|
67578
68044
|
}
|
|
67579
68045
|
const cloudTriggerKey = (t) => {
|
|
@@ -67611,11 +68077,11 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67611
68077
|
const triggersAdded = [...localTriggers.keys()].filter((k3) => !cloudTriggers.has(k3));
|
|
67612
68078
|
const triggersRemoved = [...cloudTriggers.keys()].filter((k3) => !localTriggers.has(k3));
|
|
67613
68079
|
if (triggersAdded.length || triggersRemoved.length) {
|
|
67614
|
-
lines.push(` ${
|
|
68080
|
+
lines.push(` ${import_picocolors42.default.bold("schedule triggers")}`);
|
|
67615
68081
|
for (const k3 of triggersAdded)
|
|
67616
|
-
lines.push(` ${
|
|
68082
|
+
lines.push(` ${import_picocolors42.default.yellow("→ push")} added/changed in yaml: ${localTriggers.get(k3) ?? k3}`);
|
|
67617
68083
|
for (const k3 of triggersRemoved)
|
|
67618
|
-
lines.push(` ${
|
|
68084
|
+
lines.push(` ${import_picocolors42.default.cyan("← pull")} added/changed on cloud: ${cloudTriggers.get(k3) ?? k3}`);
|
|
67619
68085
|
lines.push("");
|
|
67620
68086
|
}
|
|
67621
68087
|
const lockByAgentId = new Map((lock?.members ?? []).map((m3) => [m3.agent_id, m3]));
|
|
@@ -67638,27 +68104,27 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67638
68104
|
}
|
|
67639
68105
|
}
|
|
67640
68106
|
if (memberDrift.length) {
|
|
67641
|
-
lines.push(` ${
|
|
68107
|
+
lines.push(` ${import_picocolors42.default.bold("member content drift")}`);
|
|
67642
68108
|
for (const d3 of memberDrift) {
|
|
67643
|
-
lines.push(` ${
|
|
68109
|
+
lines.push(` ${import_picocolors42.default.cyan("?")} ${import_picocolors42.default.bold(d3.slug)} ${import_picocolors42.default.dim("— " + d3.reason)}`);
|
|
67644
68110
|
}
|
|
67645
|
-
lines.push(` ${
|
|
68111
|
+
lines.push(` ${import_picocolors42.default.dim("cd into each member folder and run")} ${import_picocolors42.default.cyan("brainbase agent status")}`);
|
|
67646
68112
|
lines.push("");
|
|
67647
68113
|
}
|
|
67648
68114
|
const revisionDrift = lock?.revision != null && cloud.revision !== lock.revision;
|
|
67649
68115
|
if (revisionDrift) {
|
|
67650
|
-
lines.push(` ${
|
|
67651
|
-
lines.push(` ${
|
|
68116
|
+
lines.push(` ${import_picocolors42.default.bold("cloud revision")}`);
|
|
68117
|
+
lines.push(` ${import_picocolors42.default.cyan("← pull")} cloud changed since last pull: ${import_picocolors42.default.dim(`lock ${lock.revision} → cloud ${cloud.revision}`)}`);
|
|
67652
68118
|
lines.push("");
|
|
67653
68119
|
}
|
|
67654
68120
|
if (!membersAdded.length && !membersRemoved.length && !edgesAdded.length && !edgesRemoved.length && !triggersAdded.length && !triggersRemoved.length && !memberDrift.length && !revisionDrift) {
|
|
67655
|
-
lines.push(` ${
|
|
68121
|
+
lines.push(` ${import_picocolors42.default.green("✓")} everything is in sync`);
|
|
67656
68122
|
lines.push("");
|
|
67657
68123
|
console.log(lines.join(`
|
|
67658
68124
|
`));
|
|
67659
68125
|
return;
|
|
67660
68126
|
}
|
|
67661
|
-
lines.push(` ${
|
|
68127
|
+
lines.push(` ${import_picocolors42.default.dim("run")} ${import_picocolors42.default.cyan("brainbase orchestration pull")} ${import_picocolors42.default.dim("to apply cloud changes,")} ${import_picocolors42.default.cyan("brainbase orchestration push")} ${import_picocolors42.default.dim("to send yours")}`);
|
|
67662
68128
|
lines.push("");
|
|
67663
68129
|
console.log(lines.join(`
|
|
67664
68130
|
`));
|
|
@@ -67673,7 +68139,7 @@ function stableJson(value) {
|
|
|
67673
68139
|
}
|
|
67674
68140
|
|
|
67675
68141
|
// src/cli/orchestration-list.ts
|
|
67676
|
-
var
|
|
68142
|
+
var import_picocolors43 = __toESM(require_picocolors(), 1);
|
|
67677
68143
|
async function runOrchestrationList(args) {
|
|
67678
68144
|
banner("orchestration list — orchestrations under a team");
|
|
67679
68145
|
const { org, team } = await resolveOrgAndTeam({
|
|
@@ -67697,21 +68163,21 @@ async function runOrchestrationList(args) {
|
|
|
67697
68163
|
}
|
|
67698
68164
|
const lines = [""];
|
|
67699
68165
|
for (const o2 of items) {
|
|
67700
|
-
lines.push(` ${
|
|
68166
|
+
lines.push(` ${import_picocolors43.default.bold(o2.name)} ${import_picocolors43.default.dim(o2.id)}`);
|
|
67701
68167
|
if (o2.description)
|
|
67702
|
-
lines.push(` ${
|
|
67703
|
-
lines.push(` ${
|
|
68168
|
+
lines.push(` ${import_picocolors43.default.dim(o2.description)}`);
|
|
68169
|
+
lines.push(` ${import_picocolors43.default.dim(`${o2.member_count} member${o2.member_count === 1 ? "" : "s"} · ${o2.edge_count} edge${o2.edge_count === 1 ? "" : "s"}`)}`);
|
|
67704
68170
|
lines.push("");
|
|
67705
68171
|
}
|
|
67706
|
-
lines.push(` ${
|
|
68172
|
+
lines.push(` ${import_picocolors43.default.dim("pull one with")} ${import_picocolors43.default.cyan("brainbase orchestration pull <id>")}`);
|
|
67707
68173
|
lines.push("");
|
|
67708
68174
|
console.log(lines.join(`
|
|
67709
68175
|
`));
|
|
67710
68176
|
}
|
|
67711
68177
|
|
|
67712
68178
|
// src/cli/orchestration-add-agent.ts
|
|
67713
|
-
import
|
|
67714
|
-
var
|
|
68179
|
+
import fs79 from "node:fs";
|
|
68180
|
+
var import_picocolors44 = __toESM(require_picocolors(), 1);
|
|
67715
68181
|
|
|
67716
68182
|
// src/core/orchestration-add.ts
|
|
67717
68183
|
function resolveOrgIdForGroup(groupId, orgsWithTeams) {
|
|
@@ -67776,7 +68242,7 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67776
68242
|
const link2 = readOrchLink(cwd2);
|
|
67777
68243
|
if (!link2 || !hasOrchManifest(cwd2)) {
|
|
67778
68244
|
f2.warn("This folder is not a linked orchestration.");
|
|
67779
|
-
f2.info(`Run ${
|
|
68245
|
+
f2.info(`Run ${import_picocolors44.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
67780
68246
|
return;
|
|
67781
68247
|
}
|
|
67782
68248
|
let manifest;
|
|
@@ -67796,13 +68262,13 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67796
68262
|
})).trim();
|
|
67797
68263
|
}
|
|
67798
68264
|
let slug = slugifyMemberName(name);
|
|
67799
|
-
if (manifest.members.some((m3) => m3.slug === slug) ||
|
|
68265
|
+
if (manifest.members.some((m3) => m3.slug === slug) || fs79.existsSync(memberDir(cwd2, slug))) {
|
|
67800
68266
|
let n = 2;
|
|
67801
68267
|
let candidate = `${slug}-${n}`;
|
|
67802
|
-
while (manifest.members.some((m3) => m3.slug === candidate) ||
|
|
68268
|
+
while (manifest.members.some((m3) => m3.slug === candidate) || fs79.existsSync(memberDir(cwd2, candidate))) {
|
|
67803
68269
|
candidate = `${slug}-${++n}`;
|
|
67804
68270
|
}
|
|
67805
|
-
f2.info(`Slug ${
|
|
68271
|
+
f2.info(`Slug ${import_picocolors44.default.bold(slug)} is taken — using ${import_picocolors44.default.bold(candidate)}.`);
|
|
67806
68272
|
slug = candidate;
|
|
67807
68273
|
}
|
|
67808
68274
|
let payloadSchema;
|
|
@@ -67826,7 +68292,7 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67826
68292
|
const resolved = resolveOrgIdForGroup(link2.group_id, orgsWithTeams);
|
|
67827
68293
|
if (!resolved) {
|
|
67828
68294
|
sp.stop("Failed.");
|
|
67829
|
-
f2.error(`Could not find an org that owns group ${
|
|
68295
|
+
f2.error(`Could not find an org that owns group ${import_picocolors44.default.bold(link2.group_id)}. ` + `Pass ${import_picocolors44.default.cyan("--org <id>")} explicitly.`);
|
|
67830
68296
|
return;
|
|
67831
68297
|
}
|
|
67832
68298
|
orgId = resolved;
|
|
@@ -67843,14 +68309,14 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67843
68309
|
if (from.length === 0 && to2.length === 0 && isInteractive() && manifest.members.length > 0) {
|
|
67844
68310
|
const memberOptions = manifest.members.map((m3) => ({ value: m3.slug, label: m3.slug }));
|
|
67845
68311
|
const pickedFrom = await ae({
|
|
67846
|
-
message: `Connect ${
|
|
68312
|
+
message: `Connect ${import_picocolors44.default.bold(slug)} FROM which member(s)? — edges INTO ${slug} (space to select, enter to skip)`,
|
|
67847
68313
|
options: memberOptions,
|
|
67848
68314
|
required: false
|
|
67849
68315
|
});
|
|
67850
68316
|
if (Array.isArray(pickedFrom))
|
|
67851
68317
|
from = pickedFrom;
|
|
67852
68318
|
const pickedTo = await ae({
|
|
67853
|
-
message: `Connect ${
|
|
68319
|
+
message: `Connect ${import_picocolors44.default.bold(slug)} TO which member(s)? — edges OUT of ${slug} (space to select, enter to skip)`,
|
|
67854
68320
|
options: memberOptions,
|
|
67855
68321
|
required: false
|
|
67856
68322
|
});
|
|
@@ -67871,7 +68337,7 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67871
68337
|
}
|
|
67872
68338
|
const dest = memberDir(cwd2, slug);
|
|
67873
68339
|
try {
|
|
67874
|
-
|
|
68340
|
+
fs79.mkdirSync(dest, { recursive: true });
|
|
67875
68341
|
await runAgentCreate(dest, {
|
|
67876
68342
|
name,
|
|
67877
68343
|
orgId,
|
|
@@ -67882,30 +68348,30 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67882
68348
|
});
|
|
67883
68349
|
} catch (err) {
|
|
67884
68350
|
try {
|
|
67885
|
-
|
|
68351
|
+
fs79.rmSync(dest, { recursive: true, force: true });
|
|
67886
68352
|
} catch {}
|
|
67887
68353
|
f2.error(`Failed to create ${slug}: ${err.message}`);
|
|
67888
68354
|
return;
|
|
67889
68355
|
}
|
|
67890
68356
|
writeOrchManifest(cwd2, updated);
|
|
67891
68357
|
if (args.noPush) {
|
|
67892
|
-
f2.info(`Manifest updated. Run ${
|
|
68358
|
+
f2.info(`Manifest updated. Run ${import_picocolors44.default.cyan("brainbase orchestration push")} to apply.`);
|
|
67893
68359
|
return;
|
|
67894
68360
|
}
|
|
67895
68361
|
await runOrchestrationPush(cwd2, { yes: true, graphOnly: true });
|
|
67896
68362
|
}
|
|
67897
68363
|
|
|
67898
68364
|
// src/cli/orchestration-create.ts
|
|
67899
|
-
var
|
|
68365
|
+
var import_picocolors45 = __toESM(require_picocolors(), 1);
|
|
67900
68366
|
async function runOrchestrationCreate(cwd2, args) {
|
|
67901
68367
|
banner("orchestration create — claim a brainbase-orchestration.yaml");
|
|
67902
68368
|
if (readOrchLink(cwd2)) {
|
|
67903
68369
|
f2.warn("This folder is already linked to an orchestration.");
|
|
67904
|
-
f2.info(`Run ${
|
|
68370
|
+
f2.info(`Run ${import_picocolors45.default.cyan("brainbase orchestration push")} to update it.`);
|
|
67905
68371
|
return;
|
|
67906
68372
|
}
|
|
67907
68373
|
if (!hasOrchManifest(cwd2)) {
|
|
67908
|
-
f2.warn(`No ${
|
|
68374
|
+
f2.warn(`No ${import_picocolors45.default.bold(ORCH_MANIFEST_FILE)} here.`);
|
|
67909
68375
|
f2.info(`Create one, or pull an existing orchestration first.`);
|
|
67910
68376
|
return;
|
|
67911
68377
|
}
|
|
@@ -67938,10 +68404,10 @@ async function runOrchestrationCreate(cwd2, args) {
|
|
|
67938
68404
|
});
|
|
67939
68405
|
const plan = [
|
|
67940
68406
|
"",
|
|
67941
|
-
` ${
|
|
67942
|
-
` ${
|
|
67943
|
-
` ${
|
|
67944
|
-
` ${
|
|
68407
|
+
` ${import_picocolors45.default.bold(manifest.orchestration.name)}`,
|
|
68408
|
+
` ${import_picocolors45.default.dim("org")} ${import_picocolors45.default.bold(target.org.name)}`,
|
|
68409
|
+
` ${import_picocolors45.default.dim("team")} ${import_picocolors45.default.bold(target.team.name)}`,
|
|
68410
|
+
` ${import_picocolors45.default.dim("graph")} ${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}, ${graph.triggers.length} trigger${graph.triggers.length === 1 ? "" : "s"}`,
|
|
67945
68411
|
""
|
|
67946
68412
|
];
|
|
67947
68413
|
console.log(plan.join(`
|
|
@@ -67971,7 +68437,7 @@ async function runOrchestrationCreate(cwd2, args) {
|
|
|
67971
68437
|
edges: graph.edges,
|
|
67972
68438
|
triggers: graph.triggers
|
|
67973
68439
|
});
|
|
67974
|
-
sp.stop(`Created ${
|
|
68440
|
+
sp.stop(`Created ${import_picocolors45.default.bold(created.name)}.`);
|
|
67975
68441
|
writeOrchLink(cwd2, {
|
|
67976
68442
|
schemaVersion: 1,
|
|
67977
68443
|
orchestration_id: created.id,
|
|
@@ -68084,21 +68550,21 @@ async function runOrchestration(cwd2, sub, args, opts) {
|
|
|
68084
68550
|
function printHelp3() {
|
|
68085
68551
|
const out = [];
|
|
68086
68552
|
out.push("");
|
|
68087
|
-
out.push(` ${
|
|
68553
|
+
out.push(` ${import_picocolors46.default.bold("brainbase orchestration")} ${import_picocolors46.default.dim("<sub> [options]")}`);
|
|
68088
68554
|
out.push("");
|
|
68089
|
-
out.push(` ${
|
|
68090
|
-
out.push(` ${
|
|
68091
|
-
out.push(` ${
|
|
68092
|
-
out.push(` ${
|
|
68093
|
-
out.push(` ${
|
|
68094
|
-
out.push(` ${
|
|
68555
|
+
out.push(` ${import_picocolors46.default.cyan("create")} ${import_picocolors46.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
|
|
68556
|
+
out.push(` ${import_picocolors46.default.cyan("pull")} ${import_picocolors46.default.dim("<id>")} ${import_picocolors46.default.dim("fetch orchestration + every member agent into this folder")}`);
|
|
68557
|
+
out.push(` ${import_picocolors46.default.cyan("push")} ${import_picocolors46.default.dim("push each member, then update the orchestration graph")}`);
|
|
68558
|
+
out.push(` ${import_picocolors46.default.cyan("add-agent")} ${import_picocolors46.default.dim("<name>")} ${import_picocolors46.default.dim("create a member agent, wire edges (--from/--to), and push")}`);
|
|
68559
|
+
out.push(` ${import_picocolors46.default.cyan("status")} ${import_picocolors46.default.dim("show what would push and what would pull")}`);
|
|
68560
|
+
out.push(` ${import_picocolors46.default.cyan("list")} ${import_picocolors46.default.dim("list orchestrations under a team")}`);
|
|
68095
68561
|
out.push("");
|
|
68096
|
-
out.push(` ${
|
|
68097
|
-
out.push(` ${
|
|
68098
|
-
out.push(` ${
|
|
68099
|
-
out.push(` ${
|
|
68100
|
-
out.push(` ${
|
|
68101
|
-
out.push(` ${
|
|
68562
|
+
out.push(` ${import_picocolors46.default.bold("Flags")}`);
|
|
68563
|
+
out.push(` ${import_picocolors46.default.dim("--yes, -y")} skip confirmations`);
|
|
68564
|
+
out.push(` ${import_picocolors46.default.dim("--harness <id>")} harness for newly-created member folders (default claude-code)`);
|
|
68565
|
+
out.push(` ${import_picocolors46.default.dim("--graph-only")} for push: only update members + edges, skip per-member push`);
|
|
68566
|
+
out.push(` ${import_picocolors46.default.dim("--org <id>")} for create/list: org id or slug (CLI vocab — DB teams.id)`);
|
|
68567
|
+
out.push(` ${import_picocolors46.default.dim("--team <id>")} for create/list: team id (CLI vocab — DB groups.id)`);
|
|
68102
68568
|
out.push("");
|
|
68103
68569
|
console.log(out.join(`
|
|
68104
68570
|
`));
|
|
@@ -68143,11 +68609,11 @@ async function runRun(cwd2, args) {
|
|
|
68143
68609
|
}
|
|
68144
68610
|
|
|
68145
68611
|
// src/cli/publish.ts
|
|
68146
|
-
var
|
|
68612
|
+
var import_picocolors47 = __toESM(require_picocolors(), 1);
|
|
68147
68613
|
function runPublish() {
|
|
68148
68614
|
banner("publish — moved");
|
|
68149
|
-
f2.error(`${
|
|
68150
|
-
f2.info(`Use ${
|
|
68615
|
+
f2.error(`${import_picocolors47.default.bold("brainbase publish")} does not exist.`);
|
|
68616
|
+
f2.info(`Use ${import_picocolors47.default.cyan("brainbase agent push")} to send your local changes to the cloud.`);
|
|
68151
68617
|
process.exit(1);
|
|
68152
68618
|
}
|
|
68153
68619
|
|
|
@@ -68446,7 +68912,7 @@ async function runStatus(cwd2) {
|
|
|
68446
68912
|
}
|
|
68447
68913
|
|
|
68448
68914
|
// src/cli/token.ts
|
|
68449
|
-
var
|
|
68915
|
+
var import_picocolors48 = __toESM(require_picocolors(), 1);
|
|
68450
68916
|
|
|
68451
68917
|
// src/ui/ink/TokenCards.tsx
|
|
68452
68918
|
var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
|
|
@@ -68707,6 +69173,10 @@ async function showTokenListCard(props) {
|
|
|
68707
69173
|
// src/cli/token.ts
|
|
68708
69174
|
var DEFAULT_SCOPES = ["read", "publish"];
|
|
68709
69175
|
var MAX_NAME_LENGTH = 128;
|
|
69176
|
+
var ALLOWED_SCOPES = ["read", "publish", "admin"];
|
|
69177
|
+
function isAllowedScope(value) {
|
|
69178
|
+
return ALLOWED_SCOPES.includes(value);
|
|
69179
|
+
}
|
|
68710
69180
|
function isExpired2(token) {
|
|
68711
69181
|
return Boolean(token.expires_at && Date.parse(token.expires_at) <= Date.now());
|
|
68712
69182
|
}
|
|
@@ -68727,7 +69197,14 @@ async function runTokenCreate(args) {
|
|
|
68727
69197
|
flagHint: "Pass --name <label>."
|
|
68728
69198
|
});
|
|
68729
69199
|
}
|
|
68730
|
-
|
|
69200
|
+
let scopes;
|
|
69201
|
+
if (args.scopes === undefined) {
|
|
69202
|
+
scopes = DEFAULT_SCOPES;
|
|
69203
|
+
} else if (args.scopes.length === 0) {
|
|
69204
|
+
throw new Error("Usage: brainbase token create --scopes <list> (allowed: read, publish, admin)");
|
|
69205
|
+
} else {
|
|
69206
|
+
scopes = args.scopes;
|
|
69207
|
+
}
|
|
68731
69208
|
const spinner = de();
|
|
68732
69209
|
spinner.start("Creating token…");
|
|
68733
69210
|
const created = await registryApi.createCliToken({
|
|
@@ -68812,7 +69289,7 @@ async function runTokenRename(args) {
|
|
|
68812
69289
|
return;
|
|
68813
69290
|
};
|
|
68814
69291
|
let name;
|
|
68815
|
-
if (args.name
|
|
69292
|
+
if (!args.name) {
|
|
68816
69293
|
const answer = await text({
|
|
68817
69294
|
message: "New label",
|
|
68818
69295
|
placeholder: target.name,
|
|
@@ -68828,7 +69305,7 @@ async function runTokenRename(args) {
|
|
|
68828
69305
|
}
|
|
68829
69306
|
}
|
|
68830
69307
|
if (name === target.name.trim()) {
|
|
68831
|
-
console.log(`${sym.ok} ${
|
|
69308
|
+
console.log(`${sym.ok} ${import_picocolors48.default.bold(target.name.trim())} already has that label; nothing to do.`);
|
|
68832
69309
|
return;
|
|
68833
69310
|
}
|
|
68834
69311
|
try {
|
|
@@ -68836,27 +69313,32 @@ async function runTokenRename(args) {
|
|
|
68836
69313
|
} catch (error) {
|
|
68837
69314
|
throw withLoginHint(error);
|
|
68838
69315
|
}
|
|
68839
|
-
console.log(`${sym.ok} Renamed ${
|
|
69316
|
+
console.log(`${sym.ok} Renamed ${import_picocolors48.default.dim(target.name)} → ${import_picocolors48.default.bold(name)}`);
|
|
68840
69317
|
}
|
|
68841
69318
|
async function runTokenRevoke(args) {
|
|
68842
69319
|
if (!args.id) {
|
|
68843
69320
|
console.error("Usage: brainbase token revoke <id>");
|
|
68844
69321
|
process.exit(1);
|
|
68845
69322
|
}
|
|
68846
|
-
|
|
69323
|
+
let tokens;
|
|
69324
|
+
try {
|
|
69325
|
+
tokens = await registryApi.listCliTokens();
|
|
69326
|
+
} catch (error) {
|
|
69327
|
+
throw withLoginHint(error);
|
|
69328
|
+
}
|
|
68847
69329
|
const target = tokens.find((t) => t.id === args.id);
|
|
68848
69330
|
if (!target) {
|
|
68849
69331
|
throw new Error(`No token with id ${args.id}. Run \`brainbase token list\` to see yours.`);
|
|
68850
69332
|
}
|
|
68851
69333
|
if (target.revoked_at) {
|
|
68852
|
-
reconcileDeadToken(target, `${
|
|
69334
|
+
reconcileDeadToken(target, `${import_picocolors48.default.bold(target.name)} is already revoked.`);
|
|
68853
69335
|
return;
|
|
68854
69336
|
}
|
|
68855
69337
|
const stored = readToken();
|
|
68856
69338
|
const isLocalToken = Boolean(stored && stored.token.startsWith(target.prefix));
|
|
68857
69339
|
if (!autoProceed(args.yes)) {
|
|
68858
69340
|
const ok = await se({
|
|
68859
|
-
message: isLocalToken ? `Revoke ${
|
|
69341
|
+
message: isLocalToken ? `Revoke ${import_picocolors48.default.bold(target.name)} (${args.id})? This is the token this CLI is using, so it will stop working here too.` : `Revoke ${import_picocolors48.default.bold(target.name)} (${args.id})? CIs and machines using it will stop working.`,
|
|
68860
69342
|
initialValue: false
|
|
68861
69343
|
});
|
|
68862
69344
|
if (!ensureNotCancelled(ok))
|
|
@@ -68866,16 +69348,15 @@ async function runTokenRevoke(args) {
|
|
|
68866
69348
|
await registryApi.revokeCliToken(args.id);
|
|
68867
69349
|
} catch (error) {
|
|
68868
69350
|
if (error instanceof ApiError && error.status === 404) {
|
|
68869
|
-
|
|
68870
|
-
|
|
68871
|
-
reconcileDeadToken(target, `${import_picocolors45.default.bold(target.name)} had already expired.`);
|
|
69351
|
+
if (isExpired2(target)) {
|
|
69352
|
+
reconcileDeadToken(target, `${import_picocolors48.default.bold(target.name)} had already expired.`);
|
|
68872
69353
|
return;
|
|
68873
69354
|
}
|
|
68874
69355
|
throw new Error(`The server reported no active token with id ${args.id}, but it listed one a moment ago. ` + "The local token has been left alone, since that key may still work. " + "If this server predates `DELETE /v1/registry/cli-tokens/{id}`, revoke from the web app instead.");
|
|
68875
69356
|
}
|
|
68876
69357
|
throw error;
|
|
68877
69358
|
}
|
|
68878
|
-
reconcileDeadToken(target, `Revoked ${
|
|
69359
|
+
reconcileDeadToken(target, `Revoked ${import_picocolors48.default.bold(target.name)}.`);
|
|
68879
69360
|
}
|
|
68880
69361
|
function reconcileDeadToken(target, headline) {
|
|
68881
69362
|
let outcome;
|
|
@@ -68909,17 +69390,35 @@ function reportLocalToken(headline, outcome) {
|
|
|
68909
69390
|
}
|
|
68910
69391
|
async function runTokenClear() {
|
|
68911
69392
|
if (!readToken()) {
|
|
68912
|
-
console.log(
|
|
69393
|
+
console.log(import_picocolors48.default.dim("No local token stored."));
|
|
68913
69394
|
return;
|
|
68914
69395
|
}
|
|
68915
69396
|
clearToken();
|
|
68916
69397
|
console.log(`${sym.ok} Cleared local token. (Server-side token still active until revoked.)`);
|
|
68917
69398
|
}
|
|
69399
|
+
var TOKEN_VALUE_FLAGS = new Set(["--name", "-n", "--scope", "--scopes"]);
|
|
69400
|
+
function isValueOfPriorFlag(rest2, index) {
|
|
69401
|
+
return index > 0 && TOKEN_VALUE_FLAGS.has(rest2[index - 1]);
|
|
69402
|
+
}
|
|
68918
69403
|
function pickFlag(rest2, ...names) {
|
|
68919
69404
|
for (const n of names) {
|
|
68920
|
-
const
|
|
68921
|
-
|
|
68922
|
-
|
|
69405
|
+
const prefix = `${n}=`;
|
|
69406
|
+
for (let i = 0;i < rest2.length; i++) {
|
|
69407
|
+
if (isValueOfPriorFlag(rest2, i))
|
|
69408
|
+
continue;
|
|
69409
|
+
const a3 = rest2[i];
|
|
69410
|
+
if (a3 === n) {
|
|
69411
|
+
const v3 = rest2[i + 1];
|
|
69412
|
+
if (v3 === undefined)
|
|
69413
|
+
return "";
|
|
69414
|
+
const label = n === "--name" || n === "-n";
|
|
69415
|
+
if (!label && v3.startsWith("-"))
|
|
69416
|
+
return "";
|
|
69417
|
+
return v3;
|
|
69418
|
+
}
|
|
69419
|
+
if (a3.startsWith(prefix))
|
|
69420
|
+
return a3.slice(prefix.length);
|
|
69421
|
+
}
|
|
68923
69422
|
}
|
|
68924
69423
|
return;
|
|
68925
69424
|
}
|
|
@@ -68938,9 +69437,17 @@ function firstPositional(rest2, ...valueFlags) {
|
|
|
68938
69437
|
return;
|
|
68939
69438
|
}
|
|
68940
69439
|
function parseScopes(raw) {
|
|
68941
|
-
if (
|
|
69440
|
+
if (raw === undefined)
|
|
68942
69441
|
return;
|
|
68943
|
-
|
|
69442
|
+
const scopes = raw.split(",").map((s3) => s3.trim().toLowerCase()).filter((s3) => s3.length > 0);
|
|
69443
|
+
if (scopes.length === 0) {
|
|
69444
|
+
throw new Error("Usage: brainbase token create --scopes <list> (allowed: read, publish, admin)");
|
|
69445
|
+
}
|
|
69446
|
+
const unknown = scopes.filter((s3) => !isAllowedScope(s3));
|
|
69447
|
+
if (unknown.length > 0) {
|
|
69448
|
+
throw new Error(`Unknown scope${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")} — allowed: read, publish, admin`);
|
|
69449
|
+
}
|
|
69450
|
+
return scopes;
|
|
68944
69451
|
}
|
|
68945
69452
|
async function runToken(sub, rest2, args) {
|
|
68946
69453
|
const nameFlag = args.name || pickFlag(rest2, "--name", "-n");
|
|
@@ -68983,32 +69490,32 @@ async function runToken(sub, rest2, args) {
|
|
|
68983
69490
|
function printTokenHelp() {
|
|
68984
69491
|
const out = [];
|
|
68985
69492
|
out.push("");
|
|
68986
|
-
out.push(` ${
|
|
69493
|
+
out.push(` ${import_picocolors48.default.bold("brainbase token")} ${import_picocolors48.default.dim("<command>")}`);
|
|
68987
69494
|
out.push("");
|
|
68988
|
-
out.push(` ${
|
|
68989
|
-
out.push(` ${
|
|
68990
|
-
out.push(` ${
|
|
68991
|
-
out.push(` ${
|
|
68992
|
-
out.push(` ${
|
|
69495
|
+
out.push(` ${import_picocolors48.default.cyan("create")} ${import_picocolors48.default.dim("issue a new long-lived CLI key (PAT)")}`);
|
|
69496
|
+
out.push(` ${import_picocolors48.default.cyan("list")} ${import_picocolors48.default.dim("show your tokens")}`);
|
|
69497
|
+
out.push(` ${import_picocolors48.default.cyan("rename")} ${import_picocolors48.default.dim("<id>")} ${import_picocolors48.default.dim("relabel a token by id")}`);
|
|
69498
|
+
out.push(` ${import_picocolors48.default.cyan("revoke")} ${import_picocolors48.default.dim("<id>")} ${import_picocolors48.default.dim("revoke a token by id")}`);
|
|
69499
|
+
out.push(` ${import_picocolors48.default.cyan("clear")} ${import_picocolors48.default.dim("forget the local token (does not revoke)")}`);
|
|
68993
69500
|
out.push("");
|
|
68994
|
-
out.push(` ${
|
|
68995
|
-
out.push(` ${
|
|
68996
|
-
out.push(` ${
|
|
68997
|
-
out.push(` ${
|
|
69501
|
+
out.push(` ${import_picocolors48.default.bold("create flags")}`);
|
|
69502
|
+
out.push(` ${import_picocolors48.default.cyan("--name, -n")} ${import_picocolors48.default.dim("<label>")} ${import_picocolors48.default.dim("token label (prompted if omitted)")}`);
|
|
69503
|
+
out.push(` ${import_picocolors48.default.cyan("--scopes")} ${import_picocolors48.default.dim("<list>")} ${import_picocolors48.default.dim("comma-separated; allowed: read, publish, admin")}`);
|
|
69504
|
+
out.push(` ${import_picocolors48.default.dim("default: read,publish")}`);
|
|
68998
69505
|
out.push("");
|
|
68999
|
-
out.push(` ${
|
|
69000
|
-
out.push(` ${
|
|
69506
|
+
out.push(` ${import_picocolors48.default.bold("rename flags")}`);
|
|
69507
|
+
out.push(` ${import_picocolors48.default.cyan("--name, -n")} ${import_picocolors48.default.dim("<label>")} ${import_picocolors48.default.dim("new label (prompted if omitted)")}`);
|
|
69001
69508
|
out.push("");
|
|
69002
69509
|
console.log(out.join(`
|
|
69003
69510
|
`));
|
|
69004
69511
|
}
|
|
69005
69512
|
|
|
69006
69513
|
// src/cli/mcp.ts
|
|
69007
|
-
var
|
|
69514
|
+
var import_picocolors49 = __toESM(require_picocolors(), 1);
|
|
69008
69515
|
|
|
69009
69516
|
// src/core/mcp-check/collect-servers.ts
|
|
69010
69517
|
import path87 from "node:path";
|
|
69011
|
-
import
|
|
69518
|
+
import fs80 from "node:fs";
|
|
69012
69519
|
function collectServers(cwd2, env3 = process.env) {
|
|
69013
69520
|
const out = [];
|
|
69014
69521
|
const seen = new Set;
|
|
@@ -69062,7 +69569,7 @@ function* readResolvedMcps(cwd2) {
|
|
|
69062
69569
|
const p2 = path87.join(cwd2, ".brainbase", "resolved-mcps.json");
|
|
69063
69570
|
let raw;
|
|
69064
69571
|
try {
|
|
69065
|
-
raw =
|
|
69572
|
+
raw = fs80.readFileSync(p2, "utf-8");
|
|
69066
69573
|
} catch {
|
|
69067
69574
|
return;
|
|
69068
69575
|
}
|
|
@@ -69122,10 +69629,19 @@ function classifyError(err) {
|
|
|
69122
69629
|
}
|
|
69123
69630
|
return "protocol_error";
|
|
69124
69631
|
}
|
|
69632
|
+
var CREDENTIAL_NAMES = "(x-api-key|api[-_]?key|auth[-_]?token|access[-_]?token|private[-_]?token|secret)";
|
|
69125
69633
|
var REDACTIONS = [
|
|
69126
69634
|
[/https?:\/\/[^\s'"`]+/gi, "[url]"],
|
|
69127
69635
|
[/Bearer\s+\S+/gi, "Bearer [redacted]"],
|
|
69128
|
-
[/\bbb(?:pat|_live)_[A-Za-z0-9._-]+/g, "[redacted]"]
|
|
69636
|
+
[/\bbb(?:pat|_live)_[A-Za-z0-9._-]+/g, "[redacted]"],
|
|
69637
|
+
[
|
|
69638
|
+
new RegExp(`\\b${CREDENTIAL_NAMES}\\b([\\s:=]*)(["'])[^"']+\\3`, "gi"),
|
|
69639
|
+
"$1$2$3[redacted]$3"
|
|
69640
|
+
],
|
|
69641
|
+
[
|
|
69642
|
+
new RegExp(`\\b${CREDENTIAL_NAMES}\\b(\\s*[:=]\\s*)["']?[^\\s,;"'}]+`, "gi"),
|
|
69643
|
+
"$1$2[redacted]"
|
|
69644
|
+
]
|
|
69129
69645
|
];
|
|
69130
69646
|
function redactSecrets2(msg) {
|
|
69131
69647
|
let out = msg;
|
|
@@ -77252,11 +77768,11 @@ function withTimeout(inner, ms2, label) {
|
|
|
77252
77768
|
function isTransient(status) {
|
|
77253
77769
|
return status === "unreachable";
|
|
77254
77770
|
}
|
|
77255
|
-
async function probeWithConnector(server,
|
|
77771
|
+
async function probeWithConnector(server, connect2, opts) {
|
|
77256
77772
|
let lastErr;
|
|
77257
77773
|
for (let attempt2 = 0;attempt2 < 2; attempt2++) {
|
|
77258
77774
|
try {
|
|
77259
|
-
const { toolCount } = await
|
|
77775
|
+
const { toolCount } = await connect2(server, opts.timeoutMs);
|
|
77260
77776
|
return { name: server.name, status: "ok", tool_count: toolCount, error: null };
|
|
77261
77777
|
} catch (err) {
|
|
77262
77778
|
lastErr = err;
|
|
@@ -77332,42 +77848,177 @@ async function runMcpCheck(cwd2, options) {
|
|
|
77332
77848
|
}
|
|
77333
77849
|
}));
|
|
77334
77850
|
results.sort((a3, b4) => a3.name.localeCompare(b4.name));
|
|
77335
|
-
const
|
|
77851
|
+
const report2 = {
|
|
77336
77852
|
check_status: deriveCheckStatus(results),
|
|
77337
77853
|
servers: results
|
|
77338
77854
|
};
|
|
77339
77855
|
if (options.json) {
|
|
77340
|
-
write(JSON.stringify(
|
|
77856
|
+
write(JSON.stringify(report2) + `
|
|
77341
77857
|
`);
|
|
77342
77858
|
} else {
|
|
77343
|
-
write(renderHuman(
|
|
77859
|
+
write(renderHuman(report2));
|
|
77344
77860
|
}
|
|
77345
|
-
return { exitCode: 0, report };
|
|
77861
|
+
return { exitCode: 0, report: report2 };
|
|
77346
77862
|
} catch (err) {
|
|
77347
77863
|
writeErr(`brainbase mcp check failed to run: ${truncateError(err) ?? "unknown error"}
|
|
77348
77864
|
`);
|
|
77349
77865
|
return { exitCode: 1 };
|
|
77350
77866
|
}
|
|
77351
77867
|
}
|
|
77352
|
-
function renderHuman(
|
|
77868
|
+
function renderHuman(report2) {
|
|
77353
77869
|
const lines = [];
|
|
77354
|
-
if (
|
|
77355
|
-
lines.push(
|
|
77870
|
+
if (report2.check_status === "skipped") {
|
|
77871
|
+
lines.push(import_picocolors49.default.dim("No MCP servers configured — nothing to check."));
|
|
77356
77872
|
return lines.join(`
|
|
77357
77873
|
`) + `
|
|
77358
77874
|
`;
|
|
77359
77875
|
}
|
|
77360
|
-
for (const s3 of
|
|
77361
|
-
const mark = s3.status === "ok" ?
|
|
77362
|
-
const detail = s3.status === "ok" ?
|
|
77876
|
+
for (const s3 of report2.servers) {
|
|
77877
|
+
const mark = s3.status === "ok" ? import_picocolors49.default.green("✓") : s3.status === "auth_failed" ? import_picocolors49.default.red("✗") : import_picocolors49.default.yellow("⚠");
|
|
77878
|
+
const detail = s3.status === "ok" ? import_picocolors49.default.dim(`${s3.tool_count} tool${s3.tool_count === 1 ? "" : "s"}`) : import_picocolors49.default.dim(s3.status + (s3.error ? ` — ${s3.error}` : ""));
|
|
77363
77879
|
lines.push(` ${mark} ${s3.name} ${detail}`);
|
|
77364
77880
|
}
|
|
77365
|
-
const summary =
|
|
77881
|
+
const summary = report2.check_status === "ok" ? import_picocolors49.default.green("All MCP servers connected.") : import_picocolors49.default.yellow("Some MCP servers are unhealthy.");
|
|
77366
77882
|
lines.push("", summary);
|
|
77367
77883
|
return lines.join(`
|
|
77368
77884
|
`) + `
|
|
77369
77885
|
`;
|
|
77370
77886
|
}
|
|
77887
|
+
async function runMcpList(cwd2, options) {
|
|
77888
|
+
const write = options.write ?? ((s3) => process.stdout.write(s3));
|
|
77889
|
+
const writeErr = options.writeErr ?? ((s3) => process.stderr.write(s3));
|
|
77890
|
+
const fetchServers = options.fetchServers ?? ((id) => api.listAgentMcpServers(id));
|
|
77891
|
+
const resolveAgentId = options.resolveAgentId ?? ((dir) => readLink(dir)?.agent_id ?? null);
|
|
77892
|
+
const agentId = resolveAgentId(cwd2);
|
|
77893
|
+
if (!agentId) {
|
|
77894
|
+
if (options.json) {
|
|
77895
|
+
write(JSON.stringify({ linked: false, servers: [] }) + `
|
|
77896
|
+
`);
|
|
77897
|
+
} else {
|
|
77898
|
+
writeErr("This folder is not linked to any agent. Run `brainbase link` first.\n");
|
|
77899
|
+
}
|
|
77900
|
+
return 1;
|
|
77901
|
+
}
|
|
77902
|
+
let report2;
|
|
77903
|
+
try {
|
|
77904
|
+
report2 = await fetchServers(agentId);
|
|
77905
|
+
} catch (err) {
|
|
77906
|
+
if (options.json) {
|
|
77907
|
+
write(JSON.stringify({ error: err.message }) + `
|
|
77908
|
+
`);
|
|
77909
|
+
} else {
|
|
77910
|
+
writeErr(`brainbase mcp list failed: ${err.message}
|
|
77911
|
+
`);
|
|
77912
|
+
}
|
|
77913
|
+
return 1;
|
|
77914
|
+
}
|
|
77915
|
+
if (options.json) {
|
|
77916
|
+
write(JSON.stringify({ linked: true, ...sanitizeReport(report2) }) + `
|
|
77917
|
+
`);
|
|
77918
|
+
} else {
|
|
77919
|
+
write(renderServerList(report2.servers));
|
|
77920
|
+
}
|
|
77921
|
+
return 0;
|
|
77922
|
+
}
|
|
77923
|
+
function sanitizeReport(report2) {
|
|
77924
|
+
return {
|
|
77925
|
+
...report2,
|
|
77926
|
+
servers: report2.servers.map((s3) => ({
|
|
77927
|
+
...s3,
|
|
77928
|
+
url: sanitizeUrl(s3.url),
|
|
77929
|
+
command: sanitizeCommand(s3.command),
|
|
77930
|
+
last_error: s3.last_error ? truncateError(s3.last_error) : s3.last_error
|
|
77931
|
+
}))
|
|
77932
|
+
};
|
|
77933
|
+
}
|
|
77934
|
+
function sanitizeUrl(url2) {
|
|
77935
|
+
if (!url2)
|
|
77936
|
+
return url2;
|
|
77937
|
+
try {
|
|
77938
|
+
const parsed = new URL(url2);
|
|
77939
|
+
parsed.search = "";
|
|
77940
|
+
parsed.hash = "";
|
|
77941
|
+
parsed.username = "";
|
|
77942
|
+
parsed.password = "";
|
|
77943
|
+
return parsed.toString();
|
|
77944
|
+
} catch {
|
|
77945
|
+
return null;
|
|
77946
|
+
}
|
|
77947
|
+
}
|
|
77948
|
+
function sanitizeCommand(command) {
|
|
77949
|
+
if (!command)
|
|
77950
|
+
return command;
|
|
77951
|
+
return command.trim().split(/\s+/)[0] ?? null;
|
|
77952
|
+
}
|
|
77953
|
+
var AUTH_LABEL = {
|
|
77954
|
+
none: "",
|
|
77955
|
+
oauth_required: "needs authorization",
|
|
77956
|
+
oauth_connected: "authorized",
|
|
77957
|
+
oauth_expired: "authorization expired — reconnect"
|
|
77958
|
+
};
|
|
77959
|
+
var HEALTH_LABEL = {
|
|
77960
|
+
unreachable: "unreachable",
|
|
77961
|
+
protocol_error: "connection error",
|
|
77962
|
+
auth_failed: "last check failed to authenticate",
|
|
77963
|
+
expired: "last check saw an expired token",
|
|
77964
|
+
unknown: "last check inconclusive"
|
|
77965
|
+
};
|
|
77966
|
+
function healthLabel(server) {
|
|
77967
|
+
const status = server.last_status;
|
|
77968
|
+
if (!status || status === "ok")
|
|
77969
|
+
return;
|
|
77970
|
+
return HEALTH_LABEL[status] ?? `last check: ${status}`;
|
|
77971
|
+
}
|
|
77972
|
+
function isUnhealthy(server) {
|
|
77973
|
+
return Boolean(server.last_status) && server.last_status !== "ok";
|
|
77974
|
+
}
|
|
77975
|
+
function renderServerList(servers) {
|
|
77976
|
+
if (servers.length === 0) {
|
|
77977
|
+
return import_picocolors49.default.dim("No MCP servers configured for this agent.") + `
|
|
77978
|
+
`;
|
|
77979
|
+
}
|
|
77980
|
+
const lines = [""];
|
|
77981
|
+
for (const s3 of servers) {
|
|
77982
|
+
const mark = s3.auth === "oauth_expired" ? import_picocolors49.default.red("✗") : s3.auth === "oauth_required" || isUnhealthy(s3) ? import_picocolors49.default.yellow("!") : !s3.is_enabled ? import_picocolors49.default.dim("·") : import_picocolors49.default.green("✓");
|
|
77983
|
+
const bits = [s3.transport];
|
|
77984
|
+
if (!s3.is_enabled)
|
|
77985
|
+
bits.push("disabled");
|
|
77986
|
+
const label = AUTH_LABEL[s3.auth];
|
|
77987
|
+
if (label)
|
|
77988
|
+
bits.push(label);
|
|
77989
|
+
const health = healthLabel(s3);
|
|
77990
|
+
if (health)
|
|
77991
|
+
bits.push(health);
|
|
77992
|
+
const expiry = describeExpiry(s3);
|
|
77993
|
+
if (expiry)
|
|
77994
|
+
bits.push(expiry);
|
|
77995
|
+
lines.push(` ${mark} ${import_picocolors49.default.bold(s3.name)} ${import_picocolors49.default.dim(bits.join(" · "))}`);
|
|
77996
|
+
}
|
|
77997
|
+
if (servers.some((s3) => s3.auth === "oauth_required" || s3.auth === "oauth_expired")) {
|
|
77998
|
+
lines.push("", import_picocolors49.default.dim("Authorize OAuth-backed servers in the web app; the CLI cannot run that flow yet."));
|
|
77999
|
+
}
|
|
78000
|
+
lines.push("");
|
|
78001
|
+
return lines.join(`
|
|
78002
|
+
`);
|
|
78003
|
+
}
|
|
78004
|
+
var MAX_EXPIRY_DAYS = 90;
|
|
78005
|
+
function describeExpiry(server, now2 = Date.now()) {
|
|
78006
|
+
if (server.auth !== "oauth_connected" || !server.oauth_token_expires_at)
|
|
78007
|
+
return;
|
|
78008
|
+
const at3 = Date.parse(server.oauth_token_expires_at);
|
|
78009
|
+
if (!Number.isFinite(at3))
|
|
78010
|
+
return;
|
|
78011
|
+
const minutes = Math.round((at3 - now2) / 60000);
|
|
78012
|
+
if (minutes <= 0)
|
|
78013
|
+
return;
|
|
78014
|
+
if (minutes < 60)
|
|
78015
|
+
return `expires in ${minutes}m`;
|
|
78016
|
+
const hours = Math.round(minutes / 60);
|
|
78017
|
+
if (hours < 48)
|
|
78018
|
+
return `expires in ${hours}h`;
|
|
78019
|
+
const days = Math.round(hours / 24);
|
|
78020
|
+
return days > MAX_EXPIRY_DAYS ? `expires in >${MAX_EXPIRY_DAYS}d` : `expires in ${days}d`;
|
|
78021
|
+
}
|
|
77371
78022
|
async function runMcp(cwd2, sub, _argv, options) {
|
|
77372
78023
|
const writeErr = options.writeErr ?? ((s3) => process.stderr.write(s3));
|
|
77373
78024
|
switch (sub) {
|
|
@@ -77375,17 +78026,19 @@ async function runMcp(cwd2, sub, _argv, options) {
|
|
|
77375
78026
|
const { exitCode } = await runMcpCheck(cwd2, options);
|
|
77376
78027
|
return exitCode;
|
|
77377
78028
|
}
|
|
78029
|
+
case "list":
|
|
78030
|
+
return runMcpList(cwd2, options);
|
|
77378
78031
|
default:
|
|
77379
78032
|
writeErr(`Unknown mcp subcommand: ${sub ?? "(none)"}
|
|
77380
78033
|
`);
|
|
77381
|
-
writeErr(`Usage: brainbase mcp check [--json]
|
|
78034
|
+
writeErr(`Usage: brainbase mcp <check|list> [--json]
|
|
77382
78035
|
`);
|
|
77383
78036
|
return 1;
|
|
77384
78037
|
}
|
|
77385
78038
|
}
|
|
77386
78039
|
|
|
77387
78040
|
// src/cli/task.ts
|
|
77388
|
-
var
|
|
78041
|
+
var import_picocolors50 = __toESM(require_picocolors(), 1);
|
|
77389
78042
|
|
|
77390
78043
|
// src/cli/task-create.ts
|
|
77391
78044
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -77571,31 +78224,31 @@ async function runTask(cwd2, sub, args) {
|
|
|
77571
78224
|
function printHelp4() {
|
|
77572
78225
|
const out = [];
|
|
77573
78226
|
out.push("");
|
|
77574
|
-
out.push(` ${
|
|
78227
|
+
out.push(` ${import_picocolors50.default.bold("brainbase task")} ${import_picocolors50.default.dim("<sub> [options]")}`);
|
|
77575
78228
|
out.push("");
|
|
77576
|
-
out.push(` ${
|
|
78229
|
+
out.push(` ${import_picocolors50.default.cyan("create")} ${import_picocolors50.default.dim("--message <text>")} ${import_picocolors50.default.dim("create a task and start its first run")}`);
|
|
77577
78230
|
out.push("");
|
|
77578
|
-
out.push(` ${
|
|
77579
|
-
out.push(` ${
|
|
77580
|
-
out.push(` ${
|
|
77581
|
-
out.push(` ${
|
|
77582
|
-
out.push(` ${
|
|
77583
|
-
out.push(` ${
|
|
78231
|
+
out.push(` ${import_picocolors50.default.bold("create flags")}`);
|
|
78232
|
+
out.push(` ${import_picocolors50.default.dim("--message <text>")} required first user message`);
|
|
78233
|
+
out.push(` ${import_picocolors50.default.dim("--agent <id>")} override the claimed agent in brainbase.agent.yaml`);
|
|
78234
|
+
out.push(` ${import_picocolors50.default.dim("--title <text>")} optional task title`);
|
|
78235
|
+
out.push(` ${import_picocolors50.default.dim("--model <id>")} optional model override`);
|
|
78236
|
+
out.push(` ${import_picocolors50.default.dim("--json")} print task_id, agent_id, and status as JSON`);
|
|
77584
78237
|
out.push("");
|
|
77585
|
-
out.push(` ${
|
|
78238
|
+
out.push(` ${import_picocolors50.default.dim("Flag-like values:")} use ${import_picocolors50.default.cyan("--flag=value")} or ${import_picocolors50.default.cyan("--flag -- <value>")}`);
|
|
77586
78239
|
out.push("");
|
|
77587
78240
|
console.log(out.join(`
|
|
77588
78241
|
`));
|
|
77589
78242
|
}
|
|
77590
78243
|
|
|
77591
78244
|
// src/cli/benchmark.ts
|
|
77592
|
-
var
|
|
78245
|
+
var import_picocolors51 = __toESM(require_picocolors(), 1);
|
|
77593
78246
|
import {
|
|
77594
78247
|
execFileSync as execFileSync3,
|
|
77595
78248
|
spawn as spawn5
|
|
77596
78249
|
} from "node:child_process";
|
|
77597
78250
|
import crypto7 from "node:crypto";
|
|
77598
|
-
import
|
|
78251
|
+
import fs82 from "node:fs";
|
|
77599
78252
|
import os17 from "node:os";
|
|
77600
78253
|
import path89 from "node:path";
|
|
77601
78254
|
|
|
@@ -77605,7 +78258,7 @@ import {
|
|
|
77605
78258
|
spawn as spawn4
|
|
77606
78259
|
} from "node:child_process";
|
|
77607
78260
|
import crypto6 from "node:crypto";
|
|
77608
|
-
import
|
|
78261
|
+
import fs81 from "node:fs";
|
|
77609
78262
|
import os16 from "node:os";
|
|
77610
78263
|
import path88 from "node:path";
|
|
77611
78264
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
@@ -77855,19 +78508,19 @@ function canonicalFuturePath(input) {
|
|
|
77855
78508
|
const resolved = path88.resolve(input);
|
|
77856
78509
|
const suffix = [];
|
|
77857
78510
|
let current = resolved;
|
|
77858
|
-
while (!
|
|
78511
|
+
while (!fs81.existsSync(current)) {
|
|
77859
78512
|
const parent = path88.dirname(current);
|
|
77860
78513
|
if (parent === current)
|
|
77861
78514
|
break;
|
|
77862
78515
|
suffix.unshift(path88.basename(current));
|
|
77863
78516
|
current = parent;
|
|
77864
78517
|
}
|
|
77865
|
-
const canonicalBase =
|
|
78518
|
+
const canonicalBase = fs81.realpathSync(current);
|
|
77866
78519
|
return path88.join(canonicalBase, ...suffix);
|
|
77867
78520
|
}
|
|
77868
78521
|
function validateRoots(spec) {
|
|
77869
78522
|
const workspace = path88.resolve(spec.workspace_root);
|
|
77870
|
-
if (!
|
|
78523
|
+
if (!fs81.existsSync(workspace) || fs81.lstatSync(workspace).isSymbolicLink() || !fs81.lstatSync(workspace).isDirectory()) {
|
|
77871
78524
|
throw new BenchmarkPhaseError("invalid_workspace_root", "workspace_root must be an existing real directory");
|
|
77872
78525
|
}
|
|
77873
78526
|
const canonicalWorkspace = canonicalFuturePath(workspace);
|
|
@@ -77876,7 +78529,7 @@ function validateRoots(spec) {
|
|
|
77876
78529
|
if (staging !== expectedStaging) {
|
|
77877
78530
|
throw new BenchmarkPhaseError("invalid_staging_root", `staging_root must be ${expectedStaging}`);
|
|
77878
78531
|
}
|
|
77879
|
-
if (!
|
|
78532
|
+
if (!fs81.existsSync(staging) || fs81.lstatSync(staging).isSymbolicLink() || !fs81.lstatSync(staging).isDirectory() || fs81.realpathSync(staging) !== path88.join(canonicalWorkspace, ".brainbase", "benchmark", spec.attempt_id, "incoming")) {
|
|
77880
78533
|
throw new BenchmarkPhaseError("invalid_staging_root", "staging_root must be a real directory under workspace_root");
|
|
77881
78534
|
}
|
|
77882
78535
|
const canonicalLogs = validateExternalRoot("logs_root", spec.logs_root, canonicalWorkspace);
|
|
@@ -77892,7 +78545,7 @@ function validateExternalRoot(label, input, canonicalWorkspace) {
|
|
|
77892
78545
|
if (candidate === path88.parse(candidate).root) {
|
|
77893
78546
|
throw new BenchmarkPhaseError(`invalid_${label}`, `${label} cannot be a filesystem root`);
|
|
77894
78547
|
}
|
|
77895
|
-
if (
|
|
78548
|
+
if (fs81.existsSync(candidate) && fs81.lstatSync(candidate).isSymbolicLink()) {
|
|
77896
78549
|
throw new BenchmarkPhaseError(`invalid_${label}`, `${label} cannot be a symlink`);
|
|
77897
78550
|
}
|
|
77898
78551
|
const canonicalCandidate = canonicalFuturePath(candidate);
|
|
@@ -77922,9 +78575,9 @@ function assertNoSymlinkTraversal(root, relative) {
|
|
|
77922
78575
|
let current = path88.resolve(root);
|
|
77923
78576
|
for (const segment of rel.split("/").slice(0, -1)) {
|
|
77924
78577
|
current = path88.join(current, segment);
|
|
77925
|
-
if (!
|
|
78578
|
+
if (!fs81.existsSync(current))
|
|
77926
78579
|
continue;
|
|
77927
|
-
if (
|
|
78580
|
+
if (fs81.lstatSync(current).isSymbolicLink()) {
|
|
77928
78581
|
throw new BenchmarkPhaseError("unsafe_path", `path traverses symlink: ${relative}`);
|
|
77929
78582
|
}
|
|
77930
78583
|
}
|
|
@@ -77934,9 +78587,9 @@ function assertOpenedFileWithinRoot(root, filePath, openedStat, label) {
|
|
|
77934
78587
|
let canonicalFile;
|
|
77935
78588
|
let currentStat;
|
|
77936
78589
|
try {
|
|
77937
|
-
canonicalRoot =
|
|
77938
|
-
canonicalFile =
|
|
77939
|
-
currentStat =
|
|
78590
|
+
canonicalRoot = fs81.realpathSync(root);
|
|
78591
|
+
canonicalFile = fs81.realpathSync(filePath);
|
|
78592
|
+
currentStat = fs81.statSync(filePath);
|
|
77940
78593
|
} catch {
|
|
77941
78594
|
throw new BenchmarkPhaseError("unsafe_path", `${label} changed while it was opened`);
|
|
77942
78595
|
}
|
|
@@ -77945,10 +78598,10 @@ function assertOpenedFileWithinRoot(root, filePath, openedStat, label) {
|
|
|
77945
78598
|
}
|
|
77946
78599
|
}
|
|
77947
78600
|
function openRegularFileNoFollow(filePath, label, root) {
|
|
77948
|
-
const noFollow = typeof
|
|
78601
|
+
const noFollow = typeof fs81.constants.O_NOFOLLOW === "number" ? fs81.constants.O_NOFOLLOW : 0;
|
|
77949
78602
|
let fd;
|
|
77950
78603
|
try {
|
|
77951
|
-
fd =
|
|
78604
|
+
fd = fs81.openSync(filePath, fs81.constants.O_RDONLY | noFollow);
|
|
77952
78605
|
} catch (error2) {
|
|
77953
78606
|
const code = error2.code;
|
|
77954
78607
|
if (code === "ELOOP") {
|
|
@@ -77956,16 +78609,16 @@ function openRegularFileNoFollow(filePath, label, root) {
|
|
|
77956
78609
|
}
|
|
77957
78610
|
throw error2;
|
|
77958
78611
|
}
|
|
77959
|
-
const stat =
|
|
78612
|
+
const stat = fs81.fstatSync(fd);
|
|
77960
78613
|
if (!stat.isFile()) {
|
|
77961
|
-
|
|
78614
|
+
fs81.closeSync(fd);
|
|
77962
78615
|
throw new BenchmarkPhaseError("invalid_input", `${label} must be a regular file`);
|
|
77963
78616
|
}
|
|
77964
78617
|
if (root) {
|
|
77965
78618
|
try {
|
|
77966
78619
|
assertOpenedFileWithinRoot(root, filePath, stat, label);
|
|
77967
78620
|
} catch (error2) {
|
|
77968
|
-
|
|
78621
|
+
fs81.closeSync(fd);
|
|
77969
78622
|
throw error2;
|
|
77970
78623
|
}
|
|
77971
78624
|
}
|
|
@@ -77973,7 +78626,7 @@ function openRegularFileNoFollow(filePath, label, root) {
|
|
|
77973
78626
|
}
|
|
77974
78627
|
async function sha256OfDescriptor(fd) {
|
|
77975
78628
|
const hash = crypto6.createHash("sha256");
|
|
77976
|
-
const stream =
|
|
78629
|
+
const stream = fs81.createReadStream("", {
|
|
77977
78630
|
fd,
|
|
77978
78631
|
autoClose: false,
|
|
77979
78632
|
start: 0
|
|
@@ -77984,7 +78637,7 @@ async function sha256OfDescriptor(fd) {
|
|
|
77984
78637
|
return hash.digest("hex");
|
|
77985
78638
|
}
|
|
77986
78639
|
function readDescriptor(fd) {
|
|
77987
|
-
return
|
|
78640
|
+
return fs81.readFileSync(fd);
|
|
77988
78641
|
}
|
|
77989
78642
|
function assertWritableDestination(root, relative) {
|
|
77990
78643
|
const rel = normalizedRootRelative(relative);
|
|
@@ -77994,9 +78647,9 @@ function assertWritableDestination(root, relative) {
|
|
|
77994
78647
|
const segments = rel.split("/");
|
|
77995
78648
|
for (const segment of segments.slice(0, -1)) {
|
|
77996
78649
|
current = path88.join(current, segment);
|
|
77997
|
-
if (!
|
|
78650
|
+
if (!fs81.existsSync(current))
|
|
77998
78651
|
continue;
|
|
77999
|
-
const stat =
|
|
78652
|
+
const stat = fs81.lstatSync(current);
|
|
78000
78653
|
if (stat.isSymbolicLink()) {
|
|
78001
78654
|
throw new BenchmarkPhaseError("unsafe_path", `path traverses symlink: ${relative}`);
|
|
78002
78655
|
}
|
|
@@ -78005,7 +78658,7 @@ function assertWritableDestination(root, relative) {
|
|
|
78005
78658
|
}
|
|
78006
78659
|
}
|
|
78007
78660
|
const destination = path88.resolve(root, rel);
|
|
78008
|
-
if (
|
|
78661
|
+
if (fs81.existsSync(destination) && fs81.lstatSync(destination).isDirectory()) {
|
|
78009
78662
|
throw new BenchmarkPhaseError("destination_conflict", `file destination is an existing directory: ${relative}`);
|
|
78010
78663
|
}
|
|
78011
78664
|
}
|
|
@@ -78037,7 +78690,7 @@ function sourcePath(stagingRoot, relative) {
|
|
|
78037
78690
|
assertNoSymlinkTraversal(stagingRoot, rel);
|
|
78038
78691
|
let stat;
|
|
78039
78692
|
try {
|
|
78040
|
-
stat =
|
|
78693
|
+
stat = fs81.lstatSync(source);
|
|
78041
78694
|
} catch {
|
|
78042
78695
|
throw new BenchmarkPhaseError("missing_input", `staged input does not exist: ${relative}`);
|
|
78043
78696
|
}
|
|
@@ -78066,12 +78719,12 @@ async function verifyRecordsUnchanged(records, spec) {
|
|
|
78066
78719
|
const relative = safeRelPath(record3.path);
|
|
78067
78720
|
assertNoSymlinkTraversal(root, relative);
|
|
78068
78721
|
const candidate = path88.resolve(root, relative);
|
|
78069
|
-
if (!isWithin(root, candidate) || !
|
|
78722
|
+
if (!isWithin(root, candidate) || !fs81.existsSync(candidate)) {
|
|
78070
78723
|
throw new BenchmarkPhaseError("evidence_tampered", `evidence was removed during evaluation: ${record3.root}:${record3.path}`);
|
|
78071
78724
|
}
|
|
78072
|
-
const stat =
|
|
78725
|
+
const stat = fs81.lstatSync(candidate);
|
|
78073
78726
|
if (record3.kind === "symlink") {
|
|
78074
|
-
const target = stat.isSymbolicLink() ?
|
|
78727
|
+
const target = stat.isSymbolicLink() ? fs81.readlinkSync(candidate) : null;
|
|
78075
78728
|
if (target === null || Buffer.byteLength(target) !== record3.size || sha256(target) !== record3.sha256) {
|
|
78076
78729
|
throw new BenchmarkPhaseError("evidence_tampered", `evidence changed during evaluation: ${record3.root}:${record3.path}`);
|
|
78077
78730
|
}
|
|
@@ -78086,7 +78739,7 @@ async function verifyRecordsUnchanged(records, spec) {
|
|
|
78086
78739
|
throw new BenchmarkPhaseError("evidence_tampered", `evidence changed during evaluation: ${record3.root}:${record3.path}`);
|
|
78087
78740
|
}
|
|
78088
78741
|
} finally {
|
|
78089
|
-
|
|
78742
|
+
fs81.closeSync(opened.fd);
|
|
78090
78743
|
}
|
|
78091
78744
|
}
|
|
78092
78745
|
}
|
|
@@ -78102,35 +78755,35 @@ async function verifyInput(stagingRoot, material) {
|
|
|
78102
78755
|
throw new BenchmarkPhaseError("digest_mismatch", `checksum mismatch for ${material.source}`, { expected: material.sha256, actual });
|
|
78103
78756
|
}
|
|
78104
78757
|
} finally {
|
|
78105
|
-
|
|
78758
|
+
fs81.closeSync(opened.fd);
|
|
78106
78759
|
}
|
|
78107
78760
|
return source;
|
|
78108
78761
|
}
|
|
78109
78762
|
async function atomicCopy(source, destination, mode, sourceRoot) {
|
|
78110
|
-
|
|
78763
|
+
fs81.mkdirSync(path88.dirname(destination), { recursive: true });
|
|
78111
78764
|
const temporary = `${destination}.${process.pid}.${crypto6.randomBytes(6).toString("hex")}.tmp`;
|
|
78112
78765
|
const opened = openRegularFileNoFollow(source, `copy source ${source}`, sourceRoot);
|
|
78113
78766
|
try {
|
|
78114
|
-
await pipeline2(
|
|
78767
|
+
await pipeline2(fs81.createReadStream("", {
|
|
78115
78768
|
fd: opened.fd,
|
|
78116
78769
|
autoClose: false,
|
|
78117
78770
|
start: 0
|
|
78118
|
-
}),
|
|
78771
|
+
}), fs81.createWriteStream(temporary, {
|
|
78119
78772
|
flags: "wx",
|
|
78120
78773
|
mode: 384
|
|
78121
78774
|
}));
|
|
78122
|
-
|
|
78123
|
-
|
|
78775
|
+
fs81.chmodSync(temporary, mode ?? opened.stat.mode & 511);
|
|
78776
|
+
fs81.renameSync(temporary, destination);
|
|
78124
78777
|
} finally {
|
|
78125
|
-
|
|
78126
|
-
|
|
78778
|
+
fs81.closeSync(opened.fd);
|
|
78779
|
+
fs81.rmSync(temporary, { force: true });
|
|
78127
78780
|
}
|
|
78128
78781
|
}
|
|
78129
78782
|
async function recordFile(root, filePath, rootName, kind = "file") {
|
|
78130
78783
|
const relative = path88.relative(root, filePath).replace(/\\/g, "/");
|
|
78131
78784
|
if (kind === "symlink") {
|
|
78132
|
-
const stat =
|
|
78133
|
-
const target =
|
|
78785
|
+
const stat = fs81.lstatSync(filePath);
|
|
78786
|
+
const target = fs81.readlinkSync(filePath);
|
|
78134
78787
|
return {
|
|
78135
78788
|
root: rootName,
|
|
78136
78789
|
path: relative,
|
|
@@ -78150,7 +78803,7 @@ async function recordFile(root, filePath, rootName, kind = "file") {
|
|
|
78150
78803
|
mode: opened.stat.mode & 511
|
|
78151
78804
|
};
|
|
78152
78805
|
} finally {
|
|
78153
|
-
|
|
78806
|
+
fs81.closeSync(opened.fd);
|
|
78154
78807
|
}
|
|
78155
78808
|
}
|
|
78156
78809
|
async function copyMaterial(material, sourceRoot, destinationRoot, destinationRootName, protectWorkspace) {
|
|
@@ -78172,7 +78825,7 @@ async function copyMaterial(material, sourceRoot, destinationRoot, destinationRo
|
|
|
78172
78825
|
}
|
|
78173
78826
|
return [record3];
|
|
78174
78827
|
}
|
|
78175
|
-
const temporary =
|
|
78828
|
+
const temporary = fs81.mkdtempSync(path88.join(os16.tmpdir(), "brainbase-benchmark-"));
|
|
78176
78829
|
try {
|
|
78177
78830
|
const verifiedArchive = path88.join(temporary, "material.tar.gz");
|
|
78178
78831
|
await atomicCopy(source, verifiedArchive, 384, sourceRoot);
|
|
@@ -78190,7 +78843,7 @@ async function copyMaterial(material, sourceRoot, destinationRoot, destinationRo
|
|
|
78190
78843
|
const outputs = [];
|
|
78191
78844
|
for (const extractedRel of extracted.sort()) {
|
|
78192
78845
|
const sourceFile = path88.resolve(extractedRoot, safeRelPath(extractedRel));
|
|
78193
|
-
const stat =
|
|
78846
|
+
const stat = fs81.lstatSync(sourceFile);
|
|
78194
78847
|
if (!stat.isFile())
|
|
78195
78848
|
continue;
|
|
78196
78849
|
const combined = destinationRel === "." ? safeRelPath(extractedRel) : safeRelPath(path88.posix.join(destinationRel, extractedRel));
|
|
@@ -78205,7 +78858,7 @@ async function copyMaterial(material, sourceRoot, destinationRoot, destinationRo
|
|
|
78205
78858
|
}
|
|
78206
78859
|
return outputs;
|
|
78207
78860
|
} finally {
|
|
78208
|
-
|
|
78861
|
+
fs81.rmSync(temporary, { recursive: true, force: true });
|
|
78209
78862
|
}
|
|
78210
78863
|
}
|
|
78211
78864
|
async function preflightMaterial(material, sourceRoot, destinationRoot, protectWorkspace) {
|
|
@@ -78221,7 +78874,7 @@ async function preflightMaterial(material, sourceRoot, destinationRoot, protectW
|
|
|
78221
78874
|
assertWritableDestination(destinationRoot, destinationRel);
|
|
78222
78875
|
return [destinationRel];
|
|
78223
78876
|
}
|
|
78224
|
-
const temporary =
|
|
78877
|
+
const temporary = fs81.mkdtempSync(path88.join(os16.tmpdir(), "brainbase-benchmark-preflight-"));
|
|
78225
78878
|
try {
|
|
78226
78879
|
const verifiedArchive = path88.join(temporary, "material.tar.gz");
|
|
78227
78880
|
await atomicCopy(source, verifiedArchive, 384, sourceRoot);
|
|
@@ -78248,34 +78901,34 @@ async function preflightMaterial(material, sourceRoot, destinationRoot, protectW
|
|
|
78248
78901
|
}
|
|
78249
78902
|
return planned;
|
|
78250
78903
|
} finally {
|
|
78251
|
-
|
|
78904
|
+
fs81.rmSync(temporary, { recursive: true, force: true });
|
|
78252
78905
|
}
|
|
78253
78906
|
}
|
|
78254
78907
|
function ownerMarker(root) {
|
|
78255
78908
|
return path88.join(root, ".brainbase-benchmark-owner.json");
|
|
78256
78909
|
}
|
|
78257
78910
|
function verifyOwnedDirectory(root, role, spec) {
|
|
78258
|
-
if (!
|
|
78911
|
+
if (!fs81.existsSync(root) || fs81.lstatSync(root).isSymbolicLink())
|
|
78259
78912
|
return false;
|
|
78260
78913
|
try {
|
|
78261
|
-
const marker = JSON.parse(
|
|
78914
|
+
const marker = JSON.parse(fs81.readFileSync(ownerMarker(root), "utf8"));
|
|
78262
78915
|
return marker.attempt_id === spec.attempt_id && marker.phase === spec.phase && marker.phase_id === spec.phase_id && marker.role === role;
|
|
78263
78916
|
} catch {
|
|
78264
78917
|
return false;
|
|
78265
78918
|
}
|
|
78266
78919
|
}
|
|
78267
78920
|
function prepareOwnedDirectory(root, role, spec) {
|
|
78268
|
-
if (
|
|
78921
|
+
if (fs81.existsSync(root)) {
|
|
78269
78922
|
if (!verifyOwnedDirectory(root, role, spec)) {
|
|
78270
|
-
const stat =
|
|
78271
|
-
if (!stat.isDirectory() ||
|
|
78923
|
+
const stat = fs81.lstatSync(root);
|
|
78924
|
+
if (!stat.isDirectory() || fs81.readdirSync(root).length > 0) {
|
|
78272
78925
|
throw new BenchmarkPhaseError(`unowned_${role}_root`, `${role}_root exists without a matching attempt ownership marker`);
|
|
78273
78926
|
}
|
|
78274
78927
|
} else {
|
|
78275
|
-
|
|
78928
|
+
fs81.rmSync(root, { recursive: true, force: true });
|
|
78276
78929
|
}
|
|
78277
78930
|
}
|
|
78278
|
-
|
|
78931
|
+
fs81.mkdirSync(root, { recursive: true, mode: 448 });
|
|
78279
78932
|
writeJsonAtomic(ownerMarker(root), {
|
|
78280
78933
|
schema_version: SCHEMA_VERSION,
|
|
78281
78934
|
attempt_id: spec.attempt_id,
|
|
@@ -78367,7 +79020,7 @@ async function runCommand(command, root, spec, context, additions = {}) {
|
|
|
78367
79020
|
const cwd2 = path88.resolve(root, cwdRel);
|
|
78368
79021
|
let cwdStat;
|
|
78369
79022
|
try {
|
|
78370
|
-
cwdStat =
|
|
79023
|
+
cwdStat = fs81.lstatSync(cwd2);
|
|
78371
79024
|
} catch {
|
|
78372
79025
|
throw new BenchmarkPhaseError("invalid_command_cwd", `command cwd is invalid: ${command.cwd}`);
|
|
78373
79026
|
}
|
|
@@ -78439,27 +79092,27 @@ async function runCommand(command, root, spec, context, additions = {}) {
|
|
|
78439
79092
|
}
|
|
78440
79093
|
async function writeLog(root, name, data, spec) {
|
|
78441
79094
|
const destination = path88.join(root, name);
|
|
78442
|
-
|
|
79095
|
+
fs81.mkdirSync(path88.dirname(destination), { recursive: true });
|
|
78443
79096
|
const temporary = `${destination}.${process.pid}.${crypto6.randomBytes(6).toString("hex")}.tmp`;
|
|
78444
79097
|
try {
|
|
78445
|
-
|
|
79098
|
+
fs81.writeFileSync(temporary, redactCommandOutput(data, spec), {
|
|
78446
79099
|
flag: "wx",
|
|
78447
79100
|
mode: 384
|
|
78448
79101
|
});
|
|
78449
|
-
|
|
79102
|
+
fs81.renameSync(temporary, destination);
|
|
78450
79103
|
} finally {
|
|
78451
|
-
|
|
79104
|
+
fs81.rmSync(temporary, { force: true });
|
|
78452
79105
|
}
|
|
78453
79106
|
return await recordFile(root, destination, "logs");
|
|
78454
79107
|
}
|
|
78455
79108
|
function writeBufferAtomic(destination, data) {
|
|
78456
|
-
|
|
79109
|
+
fs81.mkdirSync(path88.dirname(destination), { recursive: true });
|
|
78457
79110
|
const temporary = `${destination}.${process.pid}.${crypto6.randomBytes(6).toString("hex")}.tmp`;
|
|
78458
79111
|
try {
|
|
78459
|
-
|
|
78460
|
-
|
|
79112
|
+
fs81.writeFileSync(temporary, data, { flag: "wx", mode: 384 });
|
|
79113
|
+
fs81.renameSync(temporary, destination);
|
|
78461
79114
|
} finally {
|
|
78462
|
-
|
|
79115
|
+
fs81.rmSync(temporary, { force: true });
|
|
78463
79116
|
}
|
|
78464
79117
|
}
|
|
78465
79118
|
function assertBudget(context) {
|
|
@@ -78468,7 +79121,7 @@ function assertBudget(context) {
|
|
|
78468
79121
|
}
|
|
78469
79122
|
}
|
|
78470
79123
|
async function executeHydrate(spec, context) {
|
|
78471
|
-
|
|
79124
|
+
fs81.mkdirSync(spec.workspace_root, { recursive: true });
|
|
78472
79125
|
prepareOwnedDirectory(spec.logs_root, "logs", spec);
|
|
78473
79126
|
context.logsOwned = true;
|
|
78474
79127
|
const outputs = [];
|
|
@@ -78549,9 +79202,9 @@ async function executeHydrate(spec, context) {
|
|
|
78549
79202
|
}
|
|
78550
79203
|
const candidate = path88.resolve(spec.workspace_root, safeRelPath(output.path));
|
|
78551
79204
|
assertNoSymlinkTraversal(spec.workspace_root, output.path);
|
|
78552
|
-
if (!
|
|
79205
|
+
if (!fs81.existsSync(candidate))
|
|
78553
79206
|
continue;
|
|
78554
|
-
const stat =
|
|
79207
|
+
const stat = fs81.lstatSync(candidate);
|
|
78555
79208
|
if (!stat.isFile() && !stat.isSymbolicLink())
|
|
78556
79209
|
continue;
|
|
78557
79210
|
finalOutputs.push(await recordFile(spec.workspace_root, candidate, "workspace", stat.isSymbolicLink() ? "symlink" : "file"));
|
|
@@ -78585,7 +79238,7 @@ async function readEvidence(stagingRoot, evidence) {
|
|
|
78585
79238
|
}
|
|
78586
79239
|
};
|
|
78587
79240
|
} finally {
|
|
78588
|
-
|
|
79241
|
+
fs81.closeSync(opened.fd);
|
|
78589
79242
|
}
|
|
78590
79243
|
}
|
|
78591
79244
|
async function workspaceManifest(spec, context) {
|
|
@@ -78594,7 +79247,7 @@ async function workspaceManifest(spec, context) {
|
|
|
78594
79247
|
const stack = [path88.resolve(spec.workspace_root)];
|
|
78595
79248
|
while (stack.length > 0) {
|
|
78596
79249
|
const directory = stack.pop();
|
|
78597
|
-
const entries =
|
|
79250
|
+
const entries = fs81.readdirSync(directory, { withFileTypes: true }).sort((a3, b4) => a3.name.localeCompare(b4.name));
|
|
78598
79251
|
for (const entry of entries) {
|
|
78599
79252
|
assertBudget(context);
|
|
78600
79253
|
const full = path88.join(directory, entry.name);
|
|
@@ -78703,7 +79356,7 @@ async function evaluateOne(evaluator, spec, finalOutput, trajectory, frozenEvide
|
|
|
78703
79356
|
const candidate = path88.resolve(spec.workspace_root, relative);
|
|
78704
79357
|
let stat = null;
|
|
78705
79358
|
try {
|
|
78706
|
-
stat =
|
|
79359
|
+
stat = fs81.lstatSync(candidate);
|
|
78707
79360
|
} catch (error2) {
|
|
78708
79361
|
const code = error2.code;
|
|
78709
79362
|
if (code !== "ENOENT" && code !== "ENOTDIR")
|
|
@@ -78724,7 +79377,7 @@ async function evaluateOne(evaluator, spec, finalOutput, trajectory, frozenEvide
|
|
|
78724
79377
|
try {
|
|
78725
79378
|
verdict2 = await sha256OfDescriptor(opened.fd) === evaluator.assertion.expected;
|
|
78726
79379
|
} finally {
|
|
78727
|
-
|
|
79380
|
+
fs81.closeSync(opened.fd);
|
|
78728
79381
|
}
|
|
78729
79382
|
}
|
|
78730
79383
|
}
|
|
@@ -78734,7 +79387,7 @@ async function evaluateOne(evaluator, spec, finalOutput, trajectory, frozenEvide
|
|
|
78734
79387
|
try {
|
|
78735
79388
|
verdict2 = readDescriptor(opened.fd).toString("utf8").includes(evaluator.assertion.expected);
|
|
78736
79389
|
} finally {
|
|
78737
|
-
|
|
79390
|
+
fs81.closeSync(opened.fd);
|
|
78738
79391
|
}
|
|
78739
79392
|
}
|
|
78740
79393
|
}
|
|
@@ -78815,7 +79468,7 @@ async function executeEvaluate(spec, context) {
|
|
|
78815
79468
|
assertNoSymlinkTraversal(spec.workspace_root, artifactRel);
|
|
78816
79469
|
const source = path88.resolve(spec.workspace_root, artifactRel);
|
|
78817
79470
|
const frozenArtifact = manifest.find((entry) => entry.path === artifactRel && entry.kind !== "symlink");
|
|
78818
|
-
if (!frozenArtifact || !
|
|
79471
|
+
if (!frozenArtifact || !fs81.existsSync(source) || !fs81.lstatSync(source).isFile()) {
|
|
78819
79472
|
throw new BenchmarkPhaseError("missing_artifact", `candidate artifact is missing: ${artifactRel}`);
|
|
78820
79473
|
}
|
|
78821
79474
|
const destination = path88.resolve(spec.logs_root, "candidate-artifacts", artifactRel);
|
|
@@ -78833,9 +79486,9 @@ async function executeEvaluate(spec, context) {
|
|
|
78833
79486
|
const temporary = `${archive}.${process.pid}.${crypto6.randomBytes(6).toString("hex")}.tmp`;
|
|
78834
79487
|
try {
|
|
78835
79488
|
await pack({ rootDir: spec.workspace_root, outFile: temporary, files: regularFiles });
|
|
78836
|
-
|
|
79489
|
+
fs81.renameSync(temporary, archive);
|
|
78837
79490
|
} finally {
|
|
78838
|
-
|
|
79491
|
+
fs81.rmSync(temporary, { force: true });
|
|
78839
79492
|
}
|
|
78840
79493
|
const archiveRecord = await recordFile(spec.logs_root, archive, "logs");
|
|
78841
79494
|
outputs.push(archiveRecord);
|
|
@@ -78935,21 +79588,21 @@ function rawIdentity(value) {
|
|
|
78935
79588
|
}
|
|
78936
79589
|
function readSpecBytes(specPathInput) {
|
|
78937
79590
|
const specPath = path88.resolve(specPathInput);
|
|
78938
|
-
const noFollow = typeof
|
|
79591
|
+
const noFollow = typeof fs81.constants.O_NOFOLLOW === "number" ? fs81.constants.O_NOFOLLOW : 0;
|
|
78939
79592
|
let fd;
|
|
78940
79593
|
try {
|
|
78941
|
-
fd =
|
|
79594
|
+
fd = fs81.openSync(specPath, fs81.constants.O_RDONLY | noFollow);
|
|
78942
79595
|
} catch {
|
|
78943
79596
|
throw new BenchmarkPhaseError("spec_read_failed", "spec file could not be read");
|
|
78944
79597
|
}
|
|
78945
79598
|
try {
|
|
78946
|
-
const stat =
|
|
79599
|
+
const stat = fs81.fstatSync(fd);
|
|
78947
79600
|
if (!stat.isFile() || stat.size > MAX_SPEC_BYTES) {
|
|
78948
79601
|
throw new BenchmarkPhaseError("invalid_spec_file", "spec must be a regular JSON file no larger than 20 MiB");
|
|
78949
79602
|
}
|
|
78950
79603
|
return readDescriptor(fd);
|
|
78951
79604
|
} finally {
|
|
78952
|
-
|
|
79605
|
+
fs81.closeSync(fd);
|
|
78953
79606
|
}
|
|
78954
79607
|
}
|
|
78955
79608
|
function validateBenchmarkInvocationBytes(bytes, resultPathInput, expectedPhase) {
|
|
@@ -78993,9 +79646,9 @@ function prepareBenchmarkPhaseInvocation(specPathInput, resultPathInput, expecte
|
|
|
78993
79646
|
spec_digest: digest,
|
|
78994
79647
|
timeout_ms: spec.budget.timeout_ms
|
|
78995
79648
|
};
|
|
78996
|
-
if (
|
|
79649
|
+
if (fs81.existsSync(resultPath)) {
|
|
78997
79650
|
try {
|
|
78998
|
-
const cached2 = JSON.parse(
|
|
79651
|
+
const cached2 = JSON.parse(fs81.readFileSync(resultPath, "utf8"));
|
|
78999
79652
|
if (cached2.schema_version === SCHEMA_VERSION && cached2.phase === spec.phase && cached2.attempt_id === spec.attempt_id && cached2.phase_id === spec.phase_id && cached2.spec_digest === digest && cached2.status === "succeeded") {
|
|
79000
79653
|
return {
|
|
79001
79654
|
ok: true,
|
|
@@ -79102,9 +79755,9 @@ async function runBenchmarkPhase(specPathInput, resultPathInput, expectedPhase,
|
|
|
79102
79755
|
throw new BenchmarkPhaseError("invalid_result_path", `result path must be ${expectedResultPath}`);
|
|
79103
79756
|
}
|
|
79104
79757
|
resultPathValidated = true;
|
|
79105
|
-
if (
|
|
79758
|
+
if (fs81.existsSync(resultPath)) {
|
|
79106
79759
|
try {
|
|
79107
|
-
const cached2 = JSON.parse(
|
|
79760
|
+
const cached2 = JSON.parse(fs81.readFileSync(resultPath, "utf8"));
|
|
79108
79761
|
if (cached2.schema_version === SCHEMA_VERSION && cached2.phase === spec.phase && cached2.attempt_id === spec.attempt_id && cached2.phase_id === spec.phase_id && cached2.spec_digest === digest && cached2.status === "succeeded") {
|
|
79109
79762
|
return { exitCode: 0, result: cached2 };
|
|
79110
79763
|
}
|
|
@@ -79301,13 +79954,13 @@ function terminatePhase(child) {
|
|
|
79301
79954
|
}
|
|
79302
79955
|
function createAnonymousSpecFd(bytes) {
|
|
79303
79956
|
const temporary = path89.join(os17.tmpdir(), `brainbase-benchmark-spec-${process.pid}-${crypto7.randomBytes(12).toString("hex")}`);
|
|
79304
|
-
|
|
79957
|
+
fs82.writeFileSync(temporary, bytes, { flag: "wx", mode: 384 });
|
|
79305
79958
|
try {
|
|
79306
|
-
const fd =
|
|
79307
|
-
|
|
79959
|
+
const fd = fs82.openSync(temporary, "r");
|
|
79960
|
+
fs82.unlinkSync(temporary);
|
|
79308
79961
|
return fd;
|
|
79309
79962
|
} catch (error2) {
|
|
79310
|
-
|
|
79963
|
+
fs82.rmSync(temporary, { force: true });
|
|
79311
79964
|
throw error2;
|
|
79312
79965
|
}
|
|
79313
79966
|
}
|
|
@@ -79376,13 +80029,13 @@ async function runSupervisedPhase(phase, parsed, write) {
|
|
|
79376
80029
|
detached: process.platform !== "win32"
|
|
79377
80030
|
});
|
|
79378
80031
|
} catch {
|
|
79379
|
-
|
|
80032
|
+
fs82.closeSync(specFd);
|
|
79380
80033
|
const failure = phaseFailure(invocation, startedAt, started, "phase_supervisor_failed", "benchmark phase child process could not be started");
|
|
79381
80034
|
write(`${JSON.stringify(failure)}
|
|
79382
80035
|
`);
|
|
79383
80036
|
return 1;
|
|
79384
80037
|
}
|
|
79385
|
-
|
|
80038
|
+
fs82.closeSync(specFd);
|
|
79386
80039
|
return await new Promise((resolve) => {
|
|
79387
80040
|
const stdout = [];
|
|
79388
80041
|
let settled = false;
|
|
@@ -79464,7 +80117,7 @@ async function runBenchmark(sub, args, write = (value) => process.stdout.write(v
|
|
|
79464
80117
|
if (phase !== "hydrate" && phase !== "evaluate" || resultFlag !== "--result" || !resultPath || specFdFlag !== "--spec-fd" || !Number.isInteger(specFd) || specFd < 3 || tokenFlag !== "--token" || !token || token !== process.env.BRAINBASE_BENCHMARK_PHASE_CHILD_TOKEN) {
|
|
79465
80118
|
throw new Error("Invalid internal benchmark phase invocation");
|
|
79466
80119
|
}
|
|
79467
|
-
const specBytes =
|
|
80120
|
+
const specBytes = fs82.readFileSync(specFd);
|
|
79468
80121
|
const { exitCode, result: result2 } = await runBenchmarkPhase("", resultPath, phase, specBytes);
|
|
79469
80122
|
write(`${JSON.stringify(result2)}
|
|
79470
80123
|
`);
|
|
@@ -79504,13 +80157,13 @@ async function runBenchmark(sub, args, write = (value) => process.stdout.write(v
|
|
|
79504
80157
|
function printHelp5() {
|
|
79505
80158
|
const out = [];
|
|
79506
80159
|
out.push("");
|
|
79507
|
-
out.push(` ${
|
|
80160
|
+
out.push(` ${import_picocolors51.default.bold("brainbase benchmark")} ${import_picocolors51.default.dim("<sub> [options]")}`);
|
|
79508
80161
|
out.push("");
|
|
79509
|
-
out.push(` ${
|
|
79510
|
-
out.push(` ${
|
|
79511
|
-
out.push(` ${
|
|
80162
|
+
out.push(` ${import_picocolors51.default.cyan("hydrate")} ${import_picocolors51.default.dim("--spec <path> --result <path> --json")}`);
|
|
80163
|
+
out.push(` ${import_picocolors51.default.cyan("evaluate")} ${import_picocolors51.default.dim("--spec <path> --result <path> --json")}`);
|
|
80164
|
+
out.push(` ${import_picocolors51.default.cyan("capabilities")} ${import_picocolors51.default.dim("--json")}`);
|
|
79512
80165
|
out.push("");
|
|
79513
|
-
out.push(` ${
|
|
80166
|
+
out.push(` ${import_picocolors51.default.dim("These machine-only commands execute versioned benchmark phase specs inside a task sandbox.")}`);
|
|
79514
80167
|
out.push("");
|
|
79515
80168
|
console.log(out.join(`
|
|
79516
80169
|
`));
|
|
@@ -79537,164 +80190,259 @@ var SUBCOMMAND_OWNED_FLAGS = {
|
|
|
79537
80190
|
function help() {
|
|
79538
80191
|
const out = [];
|
|
79539
80192
|
out.push("");
|
|
79540
|
-
out.push(` ${brandTint("◆")} ${
|
|
79541
|
-
out.push(` ${
|
|
80193
|
+
out.push(` ${brandTint("◆")} ${import_picocolors52.default.bold("brainbase")} ${import_picocolors52.default.dim(`v${VERSION}`)}`);
|
|
80194
|
+
out.push(` ${import_picocolors52.default.dim("connect your local agent to the brainbase platform")}`);
|
|
79542
80195
|
out.push("");
|
|
79543
80196
|
out.push(divider("USAGE"));
|
|
79544
80197
|
out.push("");
|
|
79545
|
-
out.push(` ${
|
|
80198
|
+
out.push(` ${import_picocolors52.default.bold("brainbase")} ${import_picocolors52.default.dim("<command> [options]")}`);
|
|
79546
80199
|
out.push("");
|
|
79547
80200
|
out.push(divider("AUTH"));
|
|
79548
80201
|
out.push("");
|
|
79549
|
-
out.push(` ${
|
|
79550
|
-
out.push(` ${
|
|
79551
|
-
out.push(` ${
|
|
80202
|
+
out.push(` ${import_picocolors52.default.cyan("login")} ${import_picocolors52.default.dim(" open the web app and connect this device")}`);
|
|
80203
|
+
out.push(` ${import_picocolors52.default.cyan("logout")} ${import_picocolors52.default.dim(" clear the local session")}`);
|
|
80204
|
+
out.push(` ${import_picocolors52.default.cyan("whoami")} ${import_picocolors52.default.dim(" show the current user")}`);
|
|
79552
80205
|
out.push("");
|
|
79553
80206
|
out.push(divider("DISCOVERY"));
|
|
79554
80207
|
out.push("");
|
|
79555
|
-
out.push(` ${
|
|
79556
|
-
out.push(` ${
|
|
80208
|
+
out.push(` ${import_picocolors52.default.cyan("team list")} ${import_picocolors52.default.dim("show the teams you can create agents in")}`);
|
|
80209
|
+
out.push(` ${import_picocolors52.default.cyan("agent list")} ${import_picocolors52.default.dim("show a team's agents and their ids")}`);
|
|
79557
80210
|
out.push("");
|
|
79558
80211
|
out.push(divider("LINKED AGENT"));
|
|
79559
80212
|
out.push("");
|
|
79560
|
-
out.push(` ${
|
|
79561
|
-
out.push(` ${
|
|
79562
|
-
out.push(` ${
|
|
79563
|
-
out.push(` ${
|
|
79564
|
-
out.push(` ${
|
|
79565
|
-
out.push(` ${
|
|
79566
|
-
out.push(` ${
|
|
79567
|
-
out.push(` ${
|
|
79568
|
-
out.push(` ${
|
|
79569
|
-
out.push(` ${
|
|
80213
|
+
out.push(` ${import_picocolors52.default.cyan("agent create")} ${import_picocolors52.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
80214
|
+
out.push(` ${import_picocolors52.default.cyan("agent pull")} ${import_picocolors52.default.dim("[<id>]")} ${import_picocolors52.default.dim("bring cloud changes into this folder (--force to override; --run-entrypoint to also execute the agent entrypoint)")}`);
|
|
80215
|
+
out.push(` ${import_picocolors52.default.cyan("agent push")} ${import_picocolors52.default.dim("send local changes to the cloud (--force to overwrite cloud-side conflicts with local)")}`);
|
|
80216
|
+
out.push(` ${import_picocolors52.default.cyan("agent unpack")} ${import_picocolors52.default.dim("install the claimed agent into a harness layout")}`);
|
|
80217
|
+
out.push(` ${import_picocolors52.default.cyan("link")} ${import_picocolors52.default.dim("attach this folder to an existing agent")}`);
|
|
80218
|
+
out.push(` ${import_picocolors52.default.cyan("agent status")} ${import_picocolors52.default.dim("show what would pull and what would push")}`);
|
|
80219
|
+
out.push(` ${import_picocolors52.default.cyan("agent connections")} ${import_picocolors52.default.dim("show which integrations this agent is wired to (--json for CI)")}`);
|
|
80220
|
+
out.push(` ${import_picocolors52.default.cyan("agent connect")} ${import_picocolors52.default.dim("<name>")} ${import_picocolors52.default.dim("connect slack or meeting from the terminal")}`);
|
|
80221
|
+
out.push(` ${import_picocolors52.default.cyan("agent disconnect")} ${import_picocolors52.default.dim("<name>")} ${import_picocolors52.default.dim("revoke a slack or meeting install")}`);
|
|
80222
|
+
out.push(` ${import_picocolors52.default.cyan("agent env")} ${import_picocolors52.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
|
|
80223
|
+
out.push(` ${import_picocolors52.default.cyan("run")} ${import_picocolors52.default.dim("<cmd> [args...]")} ${import_picocolors52.default.dim("run <cmd> with secrets.env loaded into env")}`);
|
|
80224
|
+
out.push(` ${import_picocolors52.default.cyan("status")} ${import_picocolors52.default.dim("show what this folder is linked to")}`);
|
|
80225
|
+
out.push(` ${import_picocolors52.default.cyan("unlink")} ${import_picocolors52.default.dim("disconnect this folder")}`);
|
|
79570
80226
|
out.push("");
|
|
79571
80227
|
out.push(divider("TASKS"));
|
|
79572
80228
|
out.push("");
|
|
79573
|
-
out.push(` ${
|
|
80229
|
+
out.push(` ${import_picocolors52.default.cyan("task create")} ${import_picocolors52.default.dim("--message <text>")} ${import_picocolors52.default.dim("create a managed task and start its first run")}`);
|
|
79574
80230
|
out.push("");
|
|
79575
80231
|
out.push(divider("BENCHMARK RUNTIME"));
|
|
79576
80232
|
out.push("");
|
|
79577
|
-
out.push(` ${
|
|
79578
|
-
out.push(` ${
|
|
79579
|
-
out.push(` ${
|
|
80233
|
+
out.push(` ${import_picocolors52.default.cyan("benchmark hydrate")} ${import_picocolors52.default.dim("--spec <path> --result <path> --json")}`);
|
|
80234
|
+
out.push(` ${import_picocolors52.default.cyan("benchmark evaluate")} ${import_picocolors52.default.dim("--spec <path> --result <path> --json")}`);
|
|
80235
|
+
out.push(` ${import_picocolors52.default.cyan("benchmark capabilities")} ${import_picocolors52.default.dim("--json")}`);
|
|
79580
80236
|
out.push("");
|
|
79581
80237
|
out.push(divider("ORCHESTRATIONS"));
|
|
79582
80238
|
out.push("");
|
|
79583
|
-
out.push(` ${
|
|
79584
|
-
out.push(` ${
|
|
79585
|
-
out.push(` ${
|
|
79586
|
-
out.push(` ${
|
|
79587
|
-
out.push(` ${
|
|
80239
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration create")} ${import_picocolors52.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
|
|
80240
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration list")} ${import_picocolors52.default.dim("list orchestrations under a team")}`);
|
|
80241
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration pull")} ${import_picocolors52.default.dim("<id>")} ${import_picocolors52.default.dim("recursively fetch an orchestration + every member agent")}`);
|
|
80242
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration push")} ${import_picocolors52.default.dim("recursively push each member, then update the graph")}`);
|
|
80243
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration status")} ${import_picocolors52.default.dim("show what would push and what would pull")}`);
|
|
79588
80244
|
out.push("");
|
|
79589
80245
|
out.push(divider("TEMPLATES"));
|
|
79590
80246
|
out.push("");
|
|
79591
|
-
out.push(` ${
|
|
79592
|
-
out.push(` ${
|
|
79593
|
-
out.push(` ${
|
|
79594
|
-
out.push(` ${
|
|
79595
|
-
out.push(` ${
|
|
79596
|
-
out.push(` ${
|
|
79597
|
-
out.push(` ${
|
|
80247
|
+
out.push(` ${import_picocolors52.default.cyan("template pack")} ${import_picocolors52.default.dim("bundle the current agent into a template")}`);
|
|
80248
|
+
out.push(` ${import_picocolors52.default.cyan("template publish")} ${import_picocolors52.default.dim("upload a template to the registry")}`);
|
|
80249
|
+
out.push(` ${import_picocolors52.default.cyan("template search")} ${import_picocolors52.default.dim("[query]")} ${import_picocolors52.default.dim("search the registry")}`);
|
|
80250
|
+
out.push(` ${import_picocolors52.default.cyan("template info")} ${import_picocolors52.default.dim("<creator/slug>")} ${import_picocolors52.default.dim("show registry details for a template")}`);
|
|
80251
|
+
out.push(` ${import_picocolors52.default.cyan("template onboard")} ${import_picocolors52.default.dim("<creator/slug>")} ${import_picocolors52.default.dim("install (or refresh) a template")}`);
|
|
80252
|
+
out.push(` ${import_picocolors52.default.cyan("template list")} ${import_picocolors52.default.dim("show installed templates")}`);
|
|
80253
|
+
out.push(` ${import_picocolors52.default.cyan("template remove")} ${import_picocolors52.default.dim("<creator/slug>")} ${import_picocolors52.default.dim("uninstall a template")}`);
|
|
79598
80254
|
out.push("");
|
|
79599
80255
|
out.push(divider("SKILLS"));
|
|
79600
80256
|
out.push("");
|
|
79601
|
-
out.push(` ${
|
|
79602
|
-
out.push(` ${
|
|
79603
|
-
out.push(` ${
|
|
79604
|
-
out.push(` ${
|
|
79605
|
-
out.push(` ${
|
|
79606
|
-
out.push(` ${
|
|
79607
|
-
out.push(` ${
|
|
80257
|
+
out.push(` ${import_picocolors52.default.cyan("skill add")} ${import_picocolors52.default.dim("<source>")} ${import_picocolors52.default.dim("install a skill (github / git / brainbase)")}`);
|
|
80258
|
+
out.push(` ${import_picocolors52.default.cyan("skill list")} ${import_picocolors52.default.dim("show locally installed skills + their source")}`);
|
|
80259
|
+
out.push(` ${import_picocolors52.default.cyan("skill update")} ${import_picocolors52.default.dim("<slug>")} ${import_picocolors52.default.dim("re-fetch a skill from its recorded source")}`);
|
|
80260
|
+
out.push(` ${import_picocolors52.default.cyan("skill remove")} ${import_picocolors52.default.dim("<slug>")} ${import_picocolors52.default.dim("uninstall a skill")}`);
|
|
80261
|
+
out.push(` ${import_picocolors52.default.cyan("skill search")} ${import_picocolors52.default.dim("[query]")} ${import_picocolors52.default.dim("search the brainbase skill registry")}`);
|
|
80262
|
+
out.push(` ${import_picocolors52.default.cyan("skill info")} ${import_picocolors52.default.dim("<creator/slug>")} ${import_picocolors52.default.dim("show registry details for a skill")}`);
|
|
80263
|
+
out.push(` ${import_picocolors52.default.cyan("skill publish")} ${import_picocolors52.default.dim("[dir]")} ${import_picocolors52.default.dim("publish a SKILL.md folder (defaults to .)")}`);
|
|
79608
80264
|
out.push("");
|
|
79609
80265
|
out.push(divider("CLI TOKENS"));
|
|
79610
80266
|
out.push("");
|
|
79611
|
-
out.push(` ${
|
|
79612
|
-
out.push(` ${
|
|
79613
|
-
out.push(` ${
|
|
79614
|
-
out.push(` ${
|
|
80267
|
+
out.push(` ${import_picocolors52.default.cyan("token create")} ${import_picocolors52.default.dim("issue a long-lived CLI key for CI / scripts")}`);
|
|
80268
|
+
out.push(` ${import_picocolors52.default.cyan("token list")} ${import_picocolors52.default.dim("show your tokens")}`);
|
|
80269
|
+
out.push(` ${import_picocolors52.default.cyan("token rename")} ${import_picocolors52.default.dim("<id>")} ${import_picocolors52.default.dim("relabel a token")}`);
|
|
80270
|
+
out.push(` ${import_picocolors52.default.cyan("token revoke")} ${import_picocolors52.default.dim("<id>")} ${import_picocolors52.default.dim("revoke a token")}`);
|
|
79615
80271
|
out.push("");
|
|
79616
80272
|
out.push(divider("MCP"));
|
|
79617
80273
|
out.push("");
|
|
79618
|
-
out.push(` ${
|
|
80274
|
+
out.push(` ${import_picocolors52.default.cyan("mcp check")} ${import_picocolors52.default.dim("[--json]")} ${import_picocolors52.default.dim("verify MCP server connectivity through the brainbase proxy (runs at sandbox bootstrap)")}`);
|
|
80275
|
+
out.push(` ${import_picocolors52.default.cyan("mcp list")} ${import_picocolors52.default.dim("[--json]")} ${import_picocolors52.default.dim("show configured servers with OAuth state and expiry")}`);
|
|
79619
80276
|
out.push("");
|
|
79620
80277
|
out.push(divider("FLAGS"));
|
|
79621
80278
|
out.push("");
|
|
79622
|
-
out.push(` ${
|
|
79623
|
-
out.push(` ${
|
|
79624
|
-
out.push(` ${
|
|
79625
|
-
out.push(` ${
|
|
79626
|
-
out.push(` ${
|
|
79627
|
-
out.push(` ${
|
|
79628
|
-
out.push(` ${
|
|
79629
|
-
out.push(` ${
|
|
79630
|
-
out.push(` ${
|
|
79631
|
-
out.push(` ${
|
|
79632
|
-
out.push(` ${
|
|
79633
|
-
out.push(` ${
|
|
79634
|
-
out.push(` ${
|
|
79635
|
-
out.push(` ${
|
|
79636
|
-
out.push(` ${
|
|
80279
|
+
out.push(` ${import_picocolors52.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
|
|
80280
|
+
out.push(` ${import_picocolors52.default.dim("--scope <s>")} force scope: global | project`);
|
|
80281
|
+
out.push(` ${import_picocolors52.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
|
|
80282
|
+
out.push(` ${import_picocolors52.default.dim("--agent <id>")} for link/task create: use this agent id explicitly`);
|
|
80283
|
+
out.push(` ${import_picocolors52.default.dim("--message <text>")} for task create: required first user message`);
|
|
80284
|
+
out.push(` ${import_picocolors52.default.dim("--title <text>")} for task create: optional task title`);
|
|
80285
|
+
out.push(` ${import_picocolors52.default.dim("--model <id>")} for task create: optional model override`);
|
|
80286
|
+
out.push(` ${import_picocolors52.default.dim("--org <id-or-slug>")} pick the organization (team/agent list, agent create, orchestration create/list)`);
|
|
80287
|
+
out.push(` ${import_picocolors52.default.dim("--team <id>")} pick the team, same commands (works without --org)`);
|
|
80288
|
+
out.push(` ${import_picocolors52.default.dim("--json")} machine-readable output for supported commands`);
|
|
80289
|
+
out.push(` ${import_picocolors52.default.dim("--no-tracking")} for link: skip routing LLM traffic through brainbase`);
|
|
80290
|
+
out.push(` ${import_picocolors52.default.dim("--track")} for agent create: enable tracking non-interactively (off without a TTY)`);
|
|
80291
|
+
out.push(` ${import_picocolors52.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
|
|
80292
|
+
out.push(` ${import_picocolors52.default.dim("--bot-token <t>")} for agent connect slack (or BRAINBASE_SLACK_BOT_TOKEN, or stdin)`);
|
|
80293
|
+
out.push(` ${import_picocolors52.default.dim("--signing-secret <s>")} for agent connect slack (or BRAINBASE_SLACK_SIGNING_SECRET, or stdin)`);
|
|
80294
|
+
out.push(` ${import_picocolors52.default.dim("--bot-name <name>")} for agent connect meeting: the bot's display name`);
|
|
80295
|
+
out.push(` ${import_picocolors52.default.dim("--all")} for template list: include installs from other folders`);
|
|
80296
|
+
out.push(` ${import_picocolors52.default.dim("--web <url>")} for login: web app URL (default https://app.brainbaselabs.com)`);
|
|
79637
80297
|
out.push("");
|
|
79638
80298
|
out.push(divider("ENV"));
|
|
79639
80299
|
out.push("");
|
|
79640
|
-
out.push(` ${
|
|
79641
|
-
out.push(` ${
|
|
79642
|
-
out.push(` ${
|
|
79643
|
-
out.push(` ${
|
|
79644
|
-
out.push(` ${
|
|
79645
|
-
out.push(` ${
|
|
79646
|
-
out.push(` ${
|
|
79647
|
-
out.push(` ${
|
|
79648
|
-
out.push(` ${
|
|
79649
|
-
out.push(` ${
|
|
79650
|
-
out.push(` ${
|
|
80300
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
|
|
80301
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_DEBUG")} print full stack traces on error (any value; unset to disable)`);
|
|
80302
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
|
|
80303
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_CONTROL_PLANE_URL")} override the MAS host (/v2/cli; task create uses /v2/tasks)`);
|
|
80304
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_API_URL")} legacy KLS host override (uses /api/cli; proxy/registry fallback)`);
|
|
80305
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_PROXY_URL")} override the model-proxy URL used by harness traffic (default https://api.v1.brainbaselabs.com)`);
|
|
80306
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL (default https://api.v1.brainbaselabs.com)`);
|
|
80307
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT (overrides token.json)`);
|
|
80308
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
|
|
80309
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_NON_INTERACTIVE")} force non-interactive mode — skip/auto-default prompts (CI & agents)`);
|
|
80310
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_RUN_ENTRYPOINT")} =1 → agent pull executes the agent entrypoint (sandbox boots; or pass --run-entrypoint)`);
|
|
79651
80311
|
out.push("");
|
|
79652
|
-
out.push(` ${
|
|
79653
|
-
out.push(` ${
|
|
79654
|
-
out.push(` ${
|
|
79655
|
-
out.push(` ${
|
|
79656
|
-
out.push(` ${
|
|
79657
|
-
out.push(` ${
|
|
80312
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_MEMORY_MCP_URL")} override the built-in memory MCP host`);
|
|
80313
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_BROWSER_MCP_URL")} override the built-in browser MCP host`);
|
|
80314
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_SLACK_MCP_URL")} override the built-in Slack MCP host`);
|
|
80315
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_MEETING_MCP_URL")} override the built-in meeting MCP host`);
|
|
80316
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_GITHUB_MCP_URL")} override the built-in GitHub MCP host`);
|
|
80317
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_ORCHESTRATION_MCP_URL")} override the built-in orchestration MCP host`);
|
|
79658
80318
|
out.push("");
|
|
79659
80319
|
out.push(divider("HARNESSES"));
|
|
79660
80320
|
out.push("");
|
|
79661
|
-
out.push(` ${
|
|
79662
|
-
out.push(` ${
|
|
79663
|
-
out.push(` ${
|
|
80321
|
+
out.push(` ${import_picocolors52.default.dim("•")} ${import_picocolors52.default.bold("claude-code")} ${import_picocolors52.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
80322
|
+
out.push(` ${import_picocolors52.default.dim("•")} ${import_picocolors52.default.bold("codex")} ${import_picocolors52.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
|
|
80323
|
+
out.push(` ${import_picocolors52.default.dim("•")} ${import_picocolors52.default.bold("kafka")} ${import_picocolors52.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
79664
80324
|
out.push("");
|
|
79665
80325
|
console.log(out.join(`
|
|
79666
80326
|
`));
|
|
79667
80327
|
}
|
|
79668
|
-
|
|
80328
|
+
var VALUE_TAKING_FLAGS = new Set([
|
|
80329
|
+
"--scope",
|
|
80330
|
+
"--name",
|
|
80331
|
+
"-n",
|
|
80332
|
+
"--harness",
|
|
80333
|
+
"--web",
|
|
80334
|
+
"--visibility",
|
|
80335
|
+
"--category",
|
|
80336
|
+
"--target",
|
|
80337
|
+
"--page",
|
|
80338
|
+
"--as",
|
|
80339
|
+
"--agent",
|
|
80340
|
+
"--shell",
|
|
80341
|
+
"--skill-version",
|
|
80342
|
+
"--tagline",
|
|
80343
|
+
"--org",
|
|
80344
|
+
"--team",
|
|
80345
|
+
"--description",
|
|
80346
|
+
"--schema",
|
|
80347
|
+
"--from",
|
|
80348
|
+
"--to",
|
|
80349
|
+
"--bot-token",
|
|
80350
|
+
"--signing-secret",
|
|
80351
|
+
"--app-id",
|
|
80352
|
+
"--app-name",
|
|
80353
|
+
"--bot-name",
|
|
80354
|
+
"--bot-image-url"
|
|
80355
|
+
]);
|
|
80356
|
+
function isValueOfPriorFlag2(args, index) {
|
|
80357
|
+
return index > 0 && VALUE_TAKING_FLAGS.has(args[index - 1]);
|
|
80358
|
+
}
|
|
80359
|
+
function findFlag(args, name) {
|
|
80360
|
+
const prefix = `${name}=`;
|
|
80361
|
+
for (let i = 0;i < args.length; i++) {
|
|
80362
|
+
if (isValueOfPriorFlag2(args, i))
|
|
80363
|
+
continue;
|
|
80364
|
+
const a3 = args[i];
|
|
80365
|
+
if (a3 === name)
|
|
80366
|
+
return { index: i };
|
|
80367
|
+
if (a3.startsWith(prefix))
|
|
80368
|
+
return { index: i, joinedValue: a3.slice(prefix.length) };
|
|
80369
|
+
}
|
|
80370
|
+
return null;
|
|
80371
|
+
}
|
|
80372
|
+
function takeFlagOnce(args, names) {
|
|
80373
|
+
let best = null;
|
|
79669
80374
|
for (const n of names) {
|
|
79670
|
-
const
|
|
79671
|
-
if (
|
|
79672
|
-
|
|
79673
|
-
args.splice(i, v3 && !v3.startsWith("--") && !(n.startsWith("-") && v3.startsWith("-")) ? 2 : 1);
|
|
79674
|
-
return v3 && !v3.startsWith("--") ? v3 : "";
|
|
79675
|
-
}
|
|
80375
|
+
const hit = findFlag(args, n);
|
|
80376
|
+
if (hit && (!best || hit.index < best.index))
|
|
80377
|
+
best = hit;
|
|
79676
80378
|
}
|
|
79677
|
-
|
|
80379
|
+
if (!best)
|
|
80380
|
+
return;
|
|
80381
|
+
if (best.joinedValue !== undefined) {
|
|
80382
|
+
args.splice(best.index, 1);
|
|
80383
|
+
return best.joinedValue;
|
|
80384
|
+
}
|
|
80385
|
+
const v3 = args[best.index + 1];
|
|
80386
|
+
if (v3 && !v3.startsWith("-")) {
|
|
80387
|
+
args.splice(best.index, 2);
|
|
80388
|
+
return v3;
|
|
80389
|
+
}
|
|
80390
|
+
args.splice(best.index, 1);
|
|
80391
|
+
return "";
|
|
80392
|
+
}
|
|
80393
|
+
function getFlag(args, ...names) {
|
|
80394
|
+
const first = takeFlagOnce(args, names);
|
|
80395
|
+
if (first === undefined)
|
|
80396
|
+
return;
|
|
80397
|
+
while (takeFlagOnce(args, names) !== undefined) {}
|
|
80398
|
+
return first;
|
|
79678
80399
|
}
|
|
79679
80400
|
function getFlagAll(args, ...names) {
|
|
79680
80401
|
const out = [];
|
|
79681
|
-
let v3 =
|
|
80402
|
+
let v3 = takeFlagOnce(args, names);
|
|
79682
80403
|
while (v3 !== undefined) {
|
|
79683
80404
|
if (v3)
|
|
79684
80405
|
out.push(v3);
|
|
79685
|
-
v3 =
|
|
80406
|
+
v3 = takeFlagOnce(args, names);
|
|
79686
80407
|
}
|
|
79687
80408
|
return out;
|
|
79688
80409
|
}
|
|
79689
|
-
function
|
|
79690
|
-
|
|
79691
|
-
|
|
79692
|
-
|
|
79693
|
-
|
|
80410
|
+
function interpretJoinedBoolean(value, name) {
|
|
80411
|
+
const v3 = value.trim().toLowerCase();
|
|
80412
|
+
if (v3 === "")
|
|
80413
|
+
return false;
|
|
80414
|
+
switch (v3) {
|
|
80415
|
+
case "false":
|
|
80416
|
+
case "0":
|
|
80417
|
+
case "no":
|
|
80418
|
+
case "off":
|
|
80419
|
+
return false;
|
|
80420
|
+
case "true":
|
|
80421
|
+
case "1":
|
|
80422
|
+
case "yes":
|
|
80423
|
+
case "on":
|
|
79694
80424
|
return true;
|
|
80425
|
+
default:
|
|
80426
|
+
throw new Error(`Unrecognised value for ${name}: ${value}`);
|
|
80427
|
+
}
|
|
80428
|
+
}
|
|
80429
|
+
function hasFlag2(args, ...names) {
|
|
80430
|
+
let leftmost;
|
|
80431
|
+
while (true) {
|
|
80432
|
+
let best = null;
|
|
80433
|
+
for (const n of names) {
|
|
80434
|
+
const hit = findFlag(args, n);
|
|
80435
|
+
if (hit && (!best || hit.index < best.index))
|
|
80436
|
+
best = { ...hit, name: n };
|
|
79695
80437
|
}
|
|
80438
|
+
if (!best)
|
|
80439
|
+
break;
|
|
80440
|
+
args.splice(best.index, 1);
|
|
80441
|
+
const enabled = best.joinedValue === undefined ? true : interpretJoinedBoolean(best.joinedValue, best.name);
|
|
80442
|
+
if (leftmost === undefined)
|
|
80443
|
+
leftmost = enabled;
|
|
79696
80444
|
}
|
|
79697
|
-
return false;
|
|
80445
|
+
return leftmost ?? false;
|
|
79698
80446
|
}
|
|
79699
80447
|
async function requireAuth(cmd) {
|
|
79700
80448
|
if (!PROTECTED.has(cmd))
|
|
@@ -79724,13 +80472,13 @@ async function requireAuth(cmd) {
|
|
|
79724
80472
|
if (STORED_PAT_COMMANDS.has(cmd) && readToken())
|
|
79725
80473
|
return;
|
|
79726
80474
|
console.error("");
|
|
79727
|
-
console.error(` ${brandTint("◆")} ${
|
|
80475
|
+
console.error(` ${brandTint("◆")} ${import_picocolors52.default.bold("brainbase")}`);
|
|
79728
80476
|
console.error("");
|
|
79729
|
-
console.error(` ${
|
|
80477
|
+
console.error(` ${import_picocolors52.default.red("✗")} You need to sign in to use ${import_picocolors52.default.bold("brainbase " + cmd)}.`);
|
|
79730
80478
|
if (status.reason)
|
|
79731
|
-
console.error(` ${
|
|
80479
|
+
console.error(` ${import_picocolors52.default.dim(status.reason)}`);
|
|
79732
80480
|
console.error("");
|
|
79733
|
-
console.error(` Run ${
|
|
80481
|
+
console.error(` Run ${import_picocolors52.default.cyan("brainbase login")} to connect this device.`);
|
|
79734
80482
|
console.error("");
|
|
79735
80483
|
process14.exit(1);
|
|
79736
80484
|
}
|
|
@@ -79740,7 +80488,7 @@ async function main() {
|
|
|
79740
80488
|
const rawCwd = process14.cwd();
|
|
79741
80489
|
const cwd2 = (() => {
|
|
79742
80490
|
try {
|
|
79743
|
-
return
|
|
80491
|
+
return fs83.realpathSync(rawCwd);
|
|
79744
80492
|
} catch {
|
|
79745
80493
|
return rawCwd;
|
|
79746
80494
|
}
|
|
@@ -79789,6 +80537,12 @@ async function main() {
|
|
|
79789
80537
|
const noPushFlag = hasFlag2(sharedArgs, "--no-push");
|
|
79790
80538
|
const jsonFlag = hasFlag2(sharedArgs, "--json");
|
|
79791
80539
|
const acpFlag = hasFlag2(sharedArgs, "--acp");
|
|
80540
|
+
const botTokenFlag = getFlag(sharedArgs, "--bot-token");
|
|
80541
|
+
const signingSecretFlag = getFlag(sharedArgs, "--signing-secret");
|
|
80542
|
+
const appIdFlag = getFlag(sharedArgs, "--app-id");
|
|
80543
|
+
const appNameFlag = getFlag(sharedArgs, "--app-name");
|
|
80544
|
+
const botNameFlag = getFlag(sharedArgs, "--bot-name");
|
|
80545
|
+
const botImageUrlFlag = getFlag(sharedArgs, "--bot-image-url");
|
|
79792
80546
|
ensureSkillResolversRegistered();
|
|
79793
80547
|
await requireAuth(cmd);
|
|
79794
80548
|
try {
|
|
@@ -79872,7 +80626,13 @@ async function main() {
|
|
|
79872
80626
|
track,
|
|
79873
80627
|
force: forceFlag,
|
|
79874
80628
|
runEntrypoint: runEntrypointFlag,
|
|
79875
|
-
acp: acpFlag
|
|
80629
|
+
acp: acpFlag,
|
|
80630
|
+
botToken: botTokenFlag,
|
|
80631
|
+
signingSecret: signingSecretFlag,
|
|
80632
|
+
appId: appIdFlag,
|
|
80633
|
+
appName: appNameFlag,
|
|
80634
|
+
botName: botNameFlag,
|
|
80635
|
+
botImageUrl: botImageUrlFlag
|
|
79876
80636
|
});
|
|
79877
80637
|
break;
|
|
79878
80638
|
}
|
|
@@ -79931,10 +80691,10 @@ async function main() {
|
|
|
79931
80691
|
process14.exit(1);
|
|
79932
80692
|
}
|
|
79933
80693
|
} catch (err) {
|
|
79934
|
-
console.error(
|
|
80694
|
+
console.error(import_picocolors52.default.red(`
|
|
79935
80695
|
${err.message}`));
|
|
79936
80696
|
if (err instanceof ApiError && err.status === 401) {
|
|
79937
|
-
console.error(` Run ${
|
|
80697
|
+
console.error(` Run ${import_picocolors52.default.cyan("brainbase login")} to connect this device.`);
|
|
79938
80698
|
}
|
|
79939
80699
|
if (process14.env.BRAINBASE_DEBUG)
|
|
79940
80700
|
console.error(err.stack);
|