@brainbase-labs/cli 0.21.2 → 0.23.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/README.md +23 -5
- package/dist/index.js +1233 -410
- 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.23.0",
|
|
36012
36012
|
description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
|
|
36013
36013
|
type: "module",
|
|
36014
36014
|
bin: {
|
|
@@ -53931,6 +53931,76 @@ function clearTokenIfMatches(prefix) {
|
|
|
53931
53931
|
});
|
|
53932
53932
|
}
|
|
53933
53933
|
|
|
53934
|
+
// src/core/credentials.ts
|
|
53935
|
+
var REGISTRY_COMMANDS = "template, skill, token";
|
|
53936
|
+
var CONTROL_PLANE_COMMANDS = "agent, orchestration, link, unlink, sync, status, team";
|
|
53937
|
+
var NOT_A_PAT = "(not a bbpat_… token)";
|
|
53938
|
+
function maskPat(token) {
|
|
53939
|
+
if (!isValidTokenFormat(token))
|
|
53940
|
+
return NOT_A_PAT;
|
|
53941
|
+
return token.slice(0, TOKEN_PREFIX_LEN);
|
|
53942
|
+
}
|
|
53943
|
+
function readEnvPat() {
|
|
53944
|
+
const value = process.env.BRAINBASE_TOKEN?.trim();
|
|
53945
|
+
if (!value)
|
|
53946
|
+
return null;
|
|
53947
|
+
return { prefix: maskPat(value), malformed: !isValidTokenFormat(value) };
|
|
53948
|
+
}
|
|
53949
|
+
function storedPatIgnoredHint(client) {
|
|
53950
|
+
const setEnv = `Set BRAINBASE_TOKEN to that token's value to authenticate with it here, ` + "or run `brainbase login` to refresh the session";
|
|
53951
|
+
switch (client) {
|
|
53952
|
+
case "control-plane":
|
|
53953
|
+
return `The PAT saved in ${TOKEN_FILE} is never used by control-plane ` + `commands (${CONTROL_PLANE_COMMANDS}). ${setEnv}.`;
|
|
53954
|
+
case "managed-task":
|
|
53955
|
+
return `The PAT saved in ${TOKEN_FILE} is not used while a login session is ` + `configured. ${setEnv} — or \`brainbase logout\`, which leaves the ` + "PAT as the only credential.";
|
|
53956
|
+
default: {
|
|
53957
|
+
const exhaustive = client;
|
|
53958
|
+
throw new Error(`unhandled credential client: ${String(exhaustive)}`);
|
|
53959
|
+
}
|
|
53960
|
+
}
|
|
53961
|
+
}
|
|
53962
|
+
function withStoredPatHint(reason, client) {
|
|
53963
|
+
if (!readToken())
|
|
53964
|
+
return reason;
|
|
53965
|
+
const trimmed = reason.trimEnd();
|
|
53966
|
+
const separator = /[.!?:]$/.test(trimmed) ? " " : ". ";
|
|
53967
|
+
return `${trimmed}${separator}${storedPatIgnoredHint(client)}`;
|
|
53968
|
+
}
|
|
53969
|
+
function withRejectedSessionHint(message, source, client) {
|
|
53970
|
+
if (source !== "session")
|
|
53971
|
+
return message;
|
|
53972
|
+
return withStoredPatHint(message, client);
|
|
53973
|
+
}
|
|
53974
|
+
function isRefreshable(session) {
|
|
53975
|
+
return Boolean(session.refresh_token && session.supabase_url && session.supabase_anon_key);
|
|
53976
|
+
}
|
|
53977
|
+
function describeCredentials() {
|
|
53978
|
+
const env3 = readEnvPat();
|
|
53979
|
+
const status = authStatus();
|
|
53980
|
+
const stored = readToken();
|
|
53981
|
+
const refreshable = Boolean(status.session && !status.ok && isRefreshable(status.session));
|
|
53982
|
+
const session = status.session ? {
|
|
53983
|
+
email: status.session.email ?? null,
|
|
53984
|
+
userId: status.session.user_id,
|
|
53985
|
+
expiresAt: status.session.expires_at ?? null,
|
|
53986
|
+
expired: !status.ok,
|
|
53987
|
+
refreshable
|
|
53988
|
+
} : null;
|
|
53989
|
+
let active = null;
|
|
53990
|
+
if (env3)
|
|
53991
|
+
active = "env_pat";
|
|
53992
|
+
else if (status.ok || refreshable)
|
|
53993
|
+
active = "session";
|
|
53994
|
+
else if (stored)
|
|
53995
|
+
active = "stored_pat";
|
|
53996
|
+
return {
|
|
53997
|
+
active,
|
|
53998
|
+
envPat: env3,
|
|
53999
|
+
session,
|
|
54000
|
+
storedPat: stored ? { name: stored.name ?? null, prefix: stored.prefix } : null
|
|
54001
|
+
};
|
|
54002
|
+
}
|
|
54003
|
+
|
|
53934
54004
|
// src/core/api.ts
|
|
53935
54005
|
var DEFAULT_CONTROL_PLANE_BASE = "https://api.brainbaselabs.com";
|
|
53936
54006
|
var DEFAULT_PROXY_BASE = "https://api.v1.brainbaselabs.com";
|
|
@@ -54005,7 +54075,7 @@ function legacyScheduleError() {
|
|
|
54005
54075
|
function legacyAgentConfigError() {
|
|
54006
54076
|
return new ApiError("Declarative machine/model config requires the MAS control plane. Set BRAINBASE_CONTROL_PLANE_URL or unset the legacy BRAINBASE_API_URL override.", 400);
|
|
54007
54077
|
}
|
|
54008
|
-
async function resolveCredential() {
|
|
54078
|
+
async function resolveCredential(storedPatHint = "control-plane") {
|
|
54009
54079
|
const envToken = process.env.BRAINBASE_TOKEN;
|
|
54010
54080
|
if (envToken && envToken.trim()) {
|
|
54011
54081
|
return {
|
|
@@ -54023,19 +54093,20 @@ async function resolveCredential() {
|
|
|
54023
54093
|
};
|
|
54024
54094
|
}
|
|
54025
54095
|
const status = authStatus();
|
|
54026
|
-
|
|
54096
|
+
const reason = status.reason ?? "not logged in";
|
|
54097
|
+
throw new ApiError(status.ok ? "CLI authentication changed while this command was starting; retry it" : storedPatHint ? withStoredPatHint(reason, storedPatHint) : reason, 401);
|
|
54027
54098
|
}
|
|
54028
54099
|
async function resolveMasCredential() {
|
|
54029
54100
|
const configuredSession = readAuth();
|
|
54030
54101
|
try {
|
|
54031
|
-
return await resolveCredential();
|
|
54102
|
+
return await resolveCredential(null);
|
|
54032
54103
|
} catch (error) {
|
|
54033
54104
|
if (!(error instanceof ApiError && error.status === 401)) {
|
|
54034
54105
|
throw error;
|
|
54035
54106
|
}
|
|
54036
54107
|
if (configuredSession || readAuth()) {
|
|
54037
54108
|
if (readToken()) {
|
|
54038
|
-
throw new ApiError(`${error.message}.
|
|
54109
|
+
throw new ApiError(`${error.message}. ${storedPatIgnoredHint("managed-task")}`, 401);
|
|
54039
54110
|
}
|
|
54040
54111
|
throw error;
|
|
54041
54112
|
}
|
|
@@ -54134,7 +54205,8 @@ async function request(pathname, init = {}) {
|
|
|
54134
54205
|
body = text2 ? JSON.parse(text2) : null;
|
|
54135
54206
|
} catch {}
|
|
54136
54207
|
if (!res.ok) {
|
|
54137
|
-
|
|
54208
|
+
const message = apiErrorMessage(body, res.status);
|
|
54209
|
+
throw new ApiError(res.status === 401 ? withRejectedSessionHint(message, credential.source, "control-plane") : message, res.status, body);
|
|
54138
54210
|
}
|
|
54139
54211
|
return body;
|
|
54140
54212
|
}
|
|
@@ -54277,7 +54349,7 @@ async function masRequest(pathname, init) {
|
|
|
54277
54349
|
}
|
|
54278
54350
|
if (!res.ok) {
|
|
54279
54351
|
const message = masApiErrorMessage(body, res.status);
|
|
54280
|
-
throw new ApiError(res.status >= 500 ? `${message} Task creation may still be processing; check your tasks before running this command again.` : message, res.status, body);
|
|
54352
|
+
throw new ApiError(res.status >= 500 ? `${message} Task creation may still be processing; check your tasks before running this command again.` : res.status === 401 ? withRejectedSessionHint(message, credential.source, "managed-task") : message, res.status, body);
|
|
54281
54353
|
}
|
|
54282
54354
|
return body;
|
|
54283
54355
|
}
|
|
@@ -54292,6 +54364,19 @@ var masApi = {
|
|
|
54292
54364
|
return parseMasTaskCreateResponse(body);
|
|
54293
54365
|
}
|
|
54294
54366
|
};
|
|
54367
|
+
function isUnroutedPath(body) {
|
|
54368
|
+
return !!body && typeof body === "object" && body.detail === "Not Found";
|
|
54369
|
+
}
|
|
54370
|
+
async function connectionsRequest(pathname, init) {
|
|
54371
|
+
try {
|
|
54372
|
+
return await request(pathname, init);
|
|
54373
|
+
} catch (err) {
|
|
54374
|
+
if (err instanceof ApiError && err.status === 404 && isUnroutedPath(err.body)) {
|
|
54375
|
+
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);
|
|
54376
|
+
}
|
|
54377
|
+
throw err;
|
|
54378
|
+
}
|
|
54379
|
+
}
|
|
54295
54380
|
var api = {
|
|
54296
54381
|
listOrgs() {
|
|
54297
54382
|
return request("/orgs");
|
|
@@ -54379,6 +54464,21 @@ var api = {
|
|
|
54379
54464
|
method: "DELETE"
|
|
54380
54465
|
});
|
|
54381
54466
|
},
|
|
54467
|
+
getAgentConnections(agentId) {
|
|
54468
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/connections`);
|
|
54469
|
+
},
|
|
54470
|
+
connectSlack(agentId, input) {
|
|
54471
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/connections/slack`, { method: "PUT", body: JSON.stringify(input) });
|
|
54472
|
+
},
|
|
54473
|
+
connectMeeting(agentId, input) {
|
|
54474
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/connections/meeting`, { method: "PUT", body: JSON.stringify(input) });
|
|
54475
|
+
},
|
|
54476
|
+
disconnectIntegration(agentId, integration) {
|
|
54477
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/connections/${encodeURIComponent(integration)}`, { method: "DELETE" });
|
|
54478
|
+
},
|
|
54479
|
+
listAgentMcpServers(agentId) {
|
|
54480
|
+
return connectionsRequest(`/agents/${encodeURIComponent(agentId)}/mcp-servers`);
|
|
54481
|
+
},
|
|
54382
54482
|
listOrchestrations(orgId, teamId) {
|
|
54383
54483
|
return request(`/orgs/${encodeURIComponent(orgId)}/teams/${encodeURIComponent(teamId)}/orchestrations`);
|
|
54384
54484
|
},
|
|
@@ -61630,12 +61730,13 @@ async function runLogin(_cwd, args) {
|
|
|
61630
61730
|
// src/ui/ink/IdentityCard.tsx
|
|
61631
61731
|
var jsx_dev_runtime15 = __toESM(require_jsx_dev_runtime(), 1);
|
|
61632
61732
|
function IdentityCard(props) {
|
|
61733
|
+
const hasRows = Boolean(props.rows?.length || props.controlPlaneUrl || props.expiresAt);
|
|
61633
61734
|
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Card, {
|
|
61634
61735
|
title: props.title,
|
|
61635
61736
|
tone: props.tone ?? "info",
|
|
61636
61737
|
children: [
|
|
61637
61738
|
props.email && /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
61638
|
-
marginBottom:
|
|
61739
|
+
marginBottom: hasRows ? 1 : 0,
|
|
61639
61740
|
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
|
|
61640
61741
|
bold: true,
|
|
61641
61742
|
children: props.email
|
|
@@ -61644,6 +61745,20 @@ function IdentityCard(props) {
|
|
|
61644
61745
|
/* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
61645
61746
|
flexDirection: "column",
|
|
61646
61747
|
children: [
|
|
61748
|
+
props.rows?.map(([label, value]) => /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
61749
|
+
children: [
|
|
61750
|
+
/* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
61751
|
+
width: 15,
|
|
61752
|
+
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
|
|
61753
|
+
dimColor: true,
|
|
61754
|
+
children: label
|
|
61755
|
+
}, undefined, false, undefined, this)
|
|
61756
|
+
}, undefined, false, undefined, this),
|
|
61757
|
+
/* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
|
|
61758
|
+
children: value
|
|
61759
|
+
}, undefined, false, undefined, this)
|
|
61760
|
+
]
|
|
61761
|
+
}, label, true, undefined, this)),
|
|
61647
61762
|
props.controlPlaneUrl && /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
61648
61763
|
children: [
|
|
61649
61764
|
/* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
@@ -61711,22 +61826,117 @@ async function runLogout() {
|
|
|
61711
61826
|
}
|
|
61712
61827
|
|
|
61713
61828
|
// src/cli/whoami.ts
|
|
61714
|
-
|
|
61715
|
-
|
|
61716
|
-
|
|
61717
|
-
|
|
61718
|
-
|
|
61719
|
-
|
|
61720
|
-
|
|
61721
|
-
|
|
61722
|
-
|
|
61829
|
+
function usableForControlPlane(report) {
|
|
61830
|
+
switch (report.active) {
|
|
61831
|
+
case "env_pat":
|
|
61832
|
+
return !report.envPat?.malformed;
|
|
61833
|
+
case "session":
|
|
61834
|
+
return true;
|
|
61835
|
+
case "stored_pat":
|
|
61836
|
+
case null:
|
|
61837
|
+
return false;
|
|
61838
|
+
default: {
|
|
61839
|
+
const exhaustive = report.active;
|
|
61840
|
+
throw new Error(`unhandled credential: ${String(exhaustive)}`);
|
|
61841
|
+
}
|
|
61842
|
+
}
|
|
61843
|
+
}
|
|
61844
|
+
function exitCodeFor(report) {
|
|
61845
|
+
return usableForControlPlane(report) ? 0 : 1;
|
|
61846
|
+
}
|
|
61847
|
+
function reasonFor(report) {
|
|
61848
|
+
switch (report.active) {
|
|
61849
|
+
case "env_pat":
|
|
61850
|
+
return report.envPat?.malformed ? "BRAINBASE_TOKEN is set to something that is not a `bbpat_…` token, " + "and it outranks every other credential — so every request will fail " + "until it is corrected or unset. Mint one with `brainbase token create`." : null;
|
|
61851
|
+
case "session":
|
|
61852
|
+
return null;
|
|
61853
|
+
case "stored_pat":
|
|
61854
|
+
return `The stored PAT authenticates registry commands (${REGISTRY_COMMANDS}) only. ` + `Set BRAINBASE_TOKEN to its value for ${CONTROL_PLANE_COMMANDS}, ` + "or run `brainbase login`.";
|
|
61855
|
+
case null:
|
|
61856
|
+
return report.session?.expired ? "Session expired. Run `brainbase login` to connect this device." : "Not logged in. Run `brainbase login` to connect this device.";
|
|
61857
|
+
default: {
|
|
61858
|
+
const exhaustive = report.active;
|
|
61859
|
+
throw new Error(`unhandled credential: ${String(exhaustive)}`);
|
|
61860
|
+
}
|
|
61861
|
+
}
|
|
61862
|
+
}
|
|
61863
|
+
function toJson(report, reason) {
|
|
61864
|
+
const usingSession = report.active === "session";
|
|
61865
|
+
return {
|
|
61866
|
+
credential: report.active,
|
|
61867
|
+
authenticated: report.active !== null && !report.envPat?.malformed,
|
|
61868
|
+
control_plane: usableForControlPlane(report),
|
|
61869
|
+
email: usingSession ? report.session?.email ?? null : null,
|
|
61870
|
+
user_id: usingSession ? report.session?.userId ?? null : null,
|
|
61871
|
+
expires_at: usingSession ? report.session?.expiresAt ?? null : null,
|
|
61872
|
+
token_prefix: report.active === "env_pat" ? report.envPat?.prefix ?? null : report.active === "stored_pat" ? report.storedPat?.prefix ?? null : null,
|
|
61873
|
+
control_plane_url: controlPlaneBaseUrl(usingSession ? readAuth() : null),
|
|
61874
|
+
session: report.session ? {
|
|
61875
|
+
present: true,
|
|
61876
|
+
expired: report.session.expired,
|
|
61877
|
+
refreshable: report.session.refreshable
|
|
61878
|
+
} : { present: false, expired: false, refreshable: false },
|
|
61879
|
+
stored_pat: report.storedPat ? { present: true, name: report.storedPat.name } : { present: false, name: null },
|
|
61880
|
+
reason
|
|
61881
|
+
};
|
|
61882
|
+
}
|
|
61883
|
+
function displayPrefix(prefix) {
|
|
61884
|
+
return prefix === NOT_A_PAT ? prefix : `${prefix}…`;
|
|
61885
|
+
}
|
|
61886
|
+
function cardRows(report) {
|
|
61887
|
+
const rows = [];
|
|
61888
|
+
switch (report.active) {
|
|
61889
|
+
case "env_pat":
|
|
61890
|
+
rows.push(["credential", "BRAINBASE_TOKEN (env PAT)"]);
|
|
61891
|
+
if (report.envPat) {
|
|
61892
|
+
rows.push(["token", displayPrefix(report.envPat.prefix)]);
|
|
61893
|
+
}
|
|
61894
|
+
break;
|
|
61895
|
+
case "session":
|
|
61896
|
+
rows.push([
|
|
61897
|
+
"credential",
|
|
61898
|
+
report.session?.refreshable ? "login session (auth.json) — expired, renews on next use" : "login session (auth.json)"
|
|
61899
|
+
]);
|
|
61900
|
+
break;
|
|
61901
|
+
case "stored_pat":
|
|
61902
|
+
rows.push(["credential", "stored PAT (token.json)"]);
|
|
61903
|
+
rows.push([
|
|
61904
|
+
"token",
|
|
61905
|
+
report.storedPat?.name ? `${displayPrefix(report.storedPat.prefix)} (${report.storedPat.name})` : displayPrefix(report.storedPat?.prefix ?? "?")
|
|
61906
|
+
]);
|
|
61907
|
+
break;
|
|
61908
|
+
case null:
|
|
61909
|
+
break;
|
|
61910
|
+
default: {
|
|
61911
|
+
const exhaustive = report.active;
|
|
61912
|
+
throw new Error(`unhandled credential: ${String(exhaustive)}`);
|
|
61913
|
+
}
|
|
61723
61914
|
}
|
|
61915
|
+
if (report.session && report.active !== "session") {
|
|
61916
|
+
rows.push([
|
|
61917
|
+
"session",
|
|
61918
|
+
`${report.session.email ?? report.session.userId} (${report.session.expired ? "expired" : "not used — env PAT wins"})`
|
|
61919
|
+
]);
|
|
61920
|
+
}
|
|
61921
|
+
return rows;
|
|
61922
|
+
}
|
|
61923
|
+
async function runWhoami(args = {}) {
|
|
61924
|
+
const report = describeCredentials();
|
|
61925
|
+
const reason = reasonFor(report);
|
|
61926
|
+
process.exitCode = exitCodeFor(report);
|
|
61927
|
+
if (args.json) {
|
|
61928
|
+
console.log(JSON.stringify(toJson(report, reason), null, 2));
|
|
61929
|
+
return;
|
|
61930
|
+
}
|
|
61931
|
+
const signedIn = report.active !== null;
|
|
61724
61932
|
await showIdentityCard({
|
|
61725
|
-
title: "WHOAMI",
|
|
61726
|
-
tone: "ok",
|
|
61727
|
-
email: session.email ?? session
|
|
61728
|
-
controlPlaneUrl: controlPlaneBaseUrl(session),
|
|
61729
|
-
expiresAt: session.
|
|
61933
|
+
title: signedIn ? "WHOAMI" : "NOT SIGNED IN",
|
|
61934
|
+
tone: process.exitCode === 0 ? "ok" : "warn",
|
|
61935
|
+
email: report.active === "session" ? report.session?.email ?? report.session?.userId ?? null : null,
|
|
61936
|
+
controlPlaneUrl: signedIn ? controlPlaneBaseUrl(report.active === "session" ? readAuth() : null) : null,
|
|
61937
|
+
expiresAt: report.active === "session" ? report.session?.expiresAt : null,
|
|
61938
|
+
rows: cardRows(report),
|
|
61939
|
+
message: reason ?? undefined
|
|
61730
61940
|
});
|
|
61731
61941
|
}
|
|
61732
61942
|
|
|
@@ -63308,7 +63518,7 @@ function runHarnessInstall(harnessId, components, opts, agentName) {
|
|
|
63308
63518
|
}
|
|
63309
63519
|
|
|
63310
63520
|
// src/cli/agent.ts
|
|
63311
|
-
var
|
|
63521
|
+
var import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
63312
63522
|
|
|
63313
63523
|
// src/cli/agent-pull.ts
|
|
63314
63524
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -66421,6 +66631,396 @@ function formatAgentList(agents, labels) {
|
|
|
66421
66631
|
`);
|
|
66422
66632
|
}
|
|
66423
66633
|
|
|
66634
|
+
// src/cli/agent-connections.ts
|
|
66635
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
66636
|
+
|
|
66637
|
+
// src/core/integrations.ts
|
|
66638
|
+
var IMPLEMENTED_INTEGRATIONS = ["slack", "meeting"];
|
|
66639
|
+
function isImplemented(name) {
|
|
66640
|
+
return IMPLEMENTED_INTEGRATIONS.includes(name);
|
|
66641
|
+
}
|
|
66642
|
+
function actionability(state) {
|
|
66643
|
+
if (!state.manageable_from_cli) {
|
|
66644
|
+
return { kind: "web-only", ...state.unmanageable_reason ? { reason: state.unmanageable_reason } : {} };
|
|
66645
|
+
}
|
|
66646
|
+
return isImplemented(state.name) ? { kind: "connectable" } : { kind: "needs-newer-cli" };
|
|
66647
|
+
}
|
|
66648
|
+
var GENERIC_WEB_ONLY_REASON = "This integration cannot be connected from the terminal. Use the web app.";
|
|
66649
|
+
var UPGRADE_HINT = "This control plane supports connecting it, but this version of the CLI does not. Upgrade the CLI.";
|
|
66650
|
+
function explain(state) {
|
|
66651
|
+
const action = actionability(state);
|
|
66652
|
+
switch (action.kind) {
|
|
66653
|
+
case "connectable":
|
|
66654
|
+
return `brainbase agent connect ${state.name}`;
|
|
66655
|
+
case "needs-newer-cli":
|
|
66656
|
+
return UPGRADE_HINT;
|
|
66657
|
+
case "web-only":
|
|
66658
|
+
return action.reason ?? GENERIC_WEB_ONLY_REASON;
|
|
66659
|
+
default: {
|
|
66660
|
+
const exhaustive = action;
|
|
66661
|
+
return exhaustive;
|
|
66662
|
+
}
|
|
66663
|
+
}
|
|
66664
|
+
}
|
|
66665
|
+
|
|
66666
|
+
// src/cli/agent-connect.ts
|
|
66667
|
+
var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
66668
|
+
|
|
66669
|
+
// src/core/secret-input.ts
|
|
66670
|
+
import fs74 from "node:fs";
|
|
66671
|
+
function clean(value) {
|
|
66672
|
+
if (typeof value !== "string")
|
|
66673
|
+
return;
|
|
66674
|
+
const trimmed = value.trim();
|
|
66675
|
+
return trimmed ? trimmed : undefined;
|
|
66676
|
+
}
|
|
66677
|
+
var STDIN_IDLE_TIMEOUT_MS = 5000;
|
|
66678
|
+
var STDIN_TIMEOUT_MIN_MS = 100;
|
|
66679
|
+
var STDIN_TIMEOUT_MAX_MS = 600000;
|
|
66680
|
+
function stdinTimeoutMs(env3) {
|
|
66681
|
+
const raw = Number(env3.BRAINBASE_STDIN_TIMEOUT_MS);
|
|
66682
|
+
if (!Number.isFinite(raw) || raw <= 0)
|
|
66683
|
+
return STDIN_IDLE_TIMEOUT_MS;
|
|
66684
|
+
return Math.min(Math.max(raw, STDIN_TIMEOUT_MIN_MS), STDIN_TIMEOUT_MAX_MS);
|
|
66685
|
+
}
|
|
66686
|
+
|
|
66687
|
+
class StdinTimeoutError extends Error {
|
|
66688
|
+
constructor(idleTimeoutMs, bytesRead) {
|
|
66689
|
+
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.");
|
|
66690
|
+
this.name = "StdinTimeoutError";
|
|
66691
|
+
}
|
|
66692
|
+
}
|
|
66693
|
+
function readPipeUntilEof(stream, idleTimeoutMs) {
|
|
66694
|
+
return new Promise((resolve, reject2) => {
|
|
66695
|
+
const chunks = [];
|
|
66696
|
+
let received = 0;
|
|
66697
|
+
let timer;
|
|
66698
|
+
const stopTimer = () => {
|
|
66699
|
+
if (timer !== undefined) {
|
|
66700
|
+
clearTimeout(timer);
|
|
66701
|
+
timer = undefined;
|
|
66702
|
+
}
|
|
66703
|
+
};
|
|
66704
|
+
const restartTimer = () => {
|
|
66705
|
+
stopTimer();
|
|
66706
|
+
timer = setTimeout(onIdle, idleTimeoutMs);
|
|
66707
|
+
};
|
|
66708
|
+
const detach = () => {
|
|
66709
|
+
stopTimer();
|
|
66710
|
+
stream.removeListener("data", onData);
|
|
66711
|
+
stream.removeListener("end", onEnd);
|
|
66712
|
+
stream.removeListener("error", onError);
|
|
66713
|
+
stream.pause();
|
|
66714
|
+
stream.unref?.();
|
|
66715
|
+
};
|
|
66716
|
+
function onIdle() {
|
|
66717
|
+
if (received > 0) {
|
|
66718
|
+
detach();
|
|
66719
|
+
reject2(new StdinTimeoutError(idleTimeoutMs, received));
|
|
66720
|
+
return;
|
|
66721
|
+
}
|
|
66722
|
+
detach();
|
|
66723
|
+
resolve("");
|
|
66724
|
+
}
|
|
66725
|
+
function onData(chunk2) {
|
|
66726
|
+
const buf = Buffer.from(chunk2);
|
|
66727
|
+
received += buf.length;
|
|
66728
|
+
chunks.push(buf);
|
|
66729
|
+
restartTimer();
|
|
66730
|
+
}
|
|
66731
|
+
function onEnd() {
|
|
66732
|
+
detach();
|
|
66733
|
+
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
66734
|
+
}
|
|
66735
|
+
function onError(err) {
|
|
66736
|
+
detach();
|
|
66737
|
+
reject2(err);
|
|
66738
|
+
}
|
|
66739
|
+
stream.on("data", onData);
|
|
66740
|
+
stream.on("end", onEnd);
|
|
66741
|
+
stream.on("error", onError);
|
|
66742
|
+
restartTimer();
|
|
66743
|
+
});
|
|
66744
|
+
}
|
|
66745
|
+
async function defaultReadStdin(env3 = process.env) {
|
|
66746
|
+
if (process.stdin.isTTY)
|
|
66747
|
+
return null;
|
|
66748
|
+
let isRegularFile = false;
|
|
66749
|
+
try {
|
|
66750
|
+
isRegularFile = fs74.fstatSync(0).isFile();
|
|
66751
|
+
} catch {
|
|
66752
|
+
return "";
|
|
66753
|
+
}
|
|
66754
|
+
if (isRegularFile) {
|
|
66755
|
+
try {
|
|
66756
|
+
return fs74.readFileSync(0, "utf8");
|
|
66757
|
+
} catch {
|
|
66758
|
+
return "";
|
|
66759
|
+
}
|
|
66760
|
+
}
|
|
66761
|
+
try {
|
|
66762
|
+
return await readPipeUntilEof(process.stdin, stdinTimeoutMs(env3));
|
|
66763
|
+
} catch (err) {
|
|
66764
|
+
if (err instanceof StdinTimeoutError)
|
|
66765
|
+
throw err;
|
|
66766
|
+
return "";
|
|
66767
|
+
}
|
|
66768
|
+
}
|
|
66769
|
+
async function defaultPrompt(field) {
|
|
66770
|
+
const answer = await re({
|
|
66771
|
+
message: field.label,
|
|
66772
|
+
validate: (v3) => v3 && v3.trim() ? undefined : "Required"
|
|
66773
|
+
});
|
|
66774
|
+
return String(ensureNotCancelled(answer)).trim();
|
|
66775
|
+
}
|
|
66776
|
+
function parseStdinSecrets(raw, missing) {
|
|
66777
|
+
const body = raw.trim();
|
|
66778
|
+
if (!body)
|
|
66779
|
+
return {};
|
|
66780
|
+
if (body.startsWith("{")) {
|
|
66781
|
+
let source;
|
|
66782
|
+
try {
|
|
66783
|
+
source = JSON.parse(body);
|
|
66784
|
+
} catch {
|
|
66785
|
+
throw new Error('stdin looked like JSON but could not be parsed. Pass an object such as {"bot_token":"…","signing_secret":"…"}.');
|
|
66786
|
+
}
|
|
66787
|
+
const out = {};
|
|
66788
|
+
for (const field of missing) {
|
|
66789
|
+
const value = clean(source[field.key]);
|
|
66790
|
+
if (value)
|
|
66791
|
+
out[field.key] = value;
|
|
66792
|
+
}
|
|
66793
|
+
return out;
|
|
66794
|
+
}
|
|
66795
|
+
if (missing.length === 1) {
|
|
66796
|
+
return { [missing[0].key]: body };
|
|
66797
|
+
}
|
|
66798
|
+
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.`);
|
|
66799
|
+
}
|
|
66800
|
+
async function resolveSecrets(fields, deps = {}) {
|
|
66801
|
+
const env3 = deps.env ?? process.env;
|
|
66802
|
+
const readStdin = deps.readStdin ?? (() => defaultReadStdin(env3));
|
|
66803
|
+
const prompt = deps.prompt ?? defaultPrompt;
|
|
66804
|
+
const interactive = deps.interactive ?? isInteractive;
|
|
66805
|
+
const resolved = {};
|
|
66806
|
+
for (const field of fields) {
|
|
66807
|
+
const value = clean(field.value) ?? clean(env3[field.envVar]);
|
|
66808
|
+
if (value)
|
|
66809
|
+
resolved[field.key] = value;
|
|
66810
|
+
}
|
|
66811
|
+
let missing = fields.filter((f4) => !resolved[f4.key]);
|
|
66812
|
+
if (missing.length > 0) {
|
|
66813
|
+
const raw = await readStdin();
|
|
66814
|
+
if (raw !== null) {
|
|
66815
|
+
Object.assign(resolved, parseStdinSecrets(raw, missing));
|
|
66816
|
+
missing = fields.filter((f4) => !resolved[f4.key]);
|
|
66817
|
+
}
|
|
66818
|
+
}
|
|
66819
|
+
for (const field of missing) {
|
|
66820
|
+
if (!interactive()) {
|
|
66821
|
+
throw new NonInteractiveError(`${field.label} is required. Pass ${field.flag}, set ${field.envVar}, or pipe it on stdin.`);
|
|
66822
|
+
}
|
|
66823
|
+
resolved[field.key] = await prompt(field);
|
|
66824
|
+
}
|
|
66825
|
+
return resolved;
|
|
66826
|
+
}
|
|
66827
|
+
|
|
66828
|
+
// src/cli/agent-connect.ts
|
|
66829
|
+
async function runAgentConnect(cwd2, target, args, deps = {}) {
|
|
66830
|
+
const json = Boolean(args.json);
|
|
66831
|
+
try {
|
|
66832
|
+
report(await connect(cwd2, target, args, deps, json), json);
|
|
66833
|
+
} catch (err) {
|
|
66834
|
+
if (!json)
|
|
66835
|
+
throw err;
|
|
66836
|
+
reportFailure(err);
|
|
66837
|
+
}
|
|
66838
|
+
}
|
|
66839
|
+
async function connect(cwd2, target, args, deps, json) {
|
|
66840
|
+
if (!target) {
|
|
66841
|
+
throw new Error(`Which integration? Try: ${IMPLEMENTED_INTEGRATIONS.join(", ")}.`);
|
|
66842
|
+
}
|
|
66843
|
+
if (!json)
|
|
66844
|
+
banner(`agent connect ${target}`);
|
|
66845
|
+
const link2 = readLink(cwd2);
|
|
66846
|
+
if (!link2) {
|
|
66847
|
+
throw new Error("This folder is not linked to any agent. Run `brainbase link` first.");
|
|
66848
|
+
}
|
|
66849
|
+
await assertConnectable(link2.agent_id, target, deps);
|
|
66850
|
+
return target === "slack" ? connectSlack(link2.agent_id, args, deps, json) : connectMeeting(link2.agent_id, args, deps, json);
|
|
66851
|
+
}
|
|
66852
|
+
async function assertConnectable(agentId, target, deps) {
|
|
66853
|
+
const fetchConnections = deps.fetchConnections ?? ((id) => api.getAgentConnections(id));
|
|
66854
|
+
const { integrations } = await fetchConnections(agentId);
|
|
66855
|
+
const state = integrations.find((i) => i.name === target);
|
|
66856
|
+
if (!state) {
|
|
66857
|
+
const known = integrations.map((i) => i.name).join(", ");
|
|
66858
|
+
throw new Error(`Unknown integration ${JSON.stringify(target)}. This agent has: ${known}.`);
|
|
66859
|
+
}
|
|
66860
|
+
const action = actionability(state);
|
|
66861
|
+
if (action.kind === "connectable")
|
|
66862
|
+
return;
|
|
66863
|
+
throw new Error(explain(state));
|
|
66864
|
+
}
|
|
66865
|
+
async function connectSlack(agentId, args, deps, json) {
|
|
66866
|
+
const secrets = await resolveSecrets([
|
|
66867
|
+
{
|
|
66868
|
+
key: "bot_token",
|
|
66869
|
+
flag: "--bot-token",
|
|
66870
|
+
envVar: "BRAINBASE_SLACK_BOT_TOKEN",
|
|
66871
|
+
label: "Slack bot token (xoxb-…)",
|
|
66872
|
+
value: args.botToken
|
|
66873
|
+
},
|
|
66874
|
+
{
|
|
66875
|
+
key: "signing_secret",
|
|
66876
|
+
flag: "--signing-secret",
|
|
66877
|
+
envVar: "BRAINBASE_SLACK_SIGNING_SECRET",
|
|
66878
|
+
label: "Slack signing secret",
|
|
66879
|
+
value: args.signingSecret
|
|
66880
|
+
}
|
|
66881
|
+
], { ...deps.secrets, ...json ? { interactive: () => false } : {} });
|
|
66882
|
+
return api.connectSlack(agentId, {
|
|
66883
|
+
bot_token: secrets.bot_token,
|
|
66884
|
+
signing_secret: secrets.signing_secret,
|
|
66885
|
+
...args.appId ? { app_id: args.appId } : {},
|
|
66886
|
+
...args.appName ? { app_name: args.appName } : {}
|
|
66887
|
+
});
|
|
66888
|
+
}
|
|
66889
|
+
async function connectMeeting(agentId, args, deps, json) {
|
|
66890
|
+
const ask = deps.askBotName ?? (() => text({
|
|
66891
|
+
message: "Name for the meeting bot",
|
|
66892
|
+
placeholder: "Notetaker",
|
|
66893
|
+
flagHint: "Pass --bot-name <name>."
|
|
66894
|
+
}));
|
|
66895
|
+
let botName = args.botName?.trim();
|
|
66896
|
+
if (!botName) {
|
|
66897
|
+
if (json) {
|
|
66898
|
+
throw new Error("A meeting bot name is required. Pass --bot-name <name>.");
|
|
66899
|
+
}
|
|
66900
|
+
botName = (await ask()).trim();
|
|
66901
|
+
}
|
|
66902
|
+
if (!botName)
|
|
66903
|
+
throw new Error("A meeting bot name is required. Pass --bot-name <name>.");
|
|
66904
|
+
return api.connectMeeting(agentId, {
|
|
66905
|
+
bot_name: botName,
|
|
66906
|
+
...args.botImageUrl ? { bot_image_url: args.botImageUrl } : {}
|
|
66907
|
+
});
|
|
66908
|
+
}
|
|
66909
|
+
function reportFailure(err) {
|
|
66910
|
+
console.log(JSON.stringify({ error: err.message }, null, 2));
|
|
66911
|
+
process.exitCode = 1;
|
|
66912
|
+
}
|
|
66913
|
+
function report(result2, json) {
|
|
66914
|
+
if (json) {
|
|
66915
|
+
console.log(JSON.stringify(result2, null, 2));
|
|
66916
|
+
return;
|
|
66917
|
+
}
|
|
66918
|
+
const detail = result2.detail ? ` ${import_picocolors34.default.dim(`(${result2.detail})`)}` : "";
|
|
66919
|
+
f2.success(`${result2.name} connected${detail}`);
|
|
66920
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase agent pull")} to pick up the built-in ${result2.name} MCP server.`);
|
|
66921
|
+
}
|
|
66922
|
+
|
|
66923
|
+
// src/cli/agent-connections.ts
|
|
66924
|
+
async function runAgentConnections(cwd2, args) {
|
|
66925
|
+
const json = Boolean(args.json);
|
|
66926
|
+
if (!json)
|
|
66927
|
+
banner("agent connections — what this agent is wired to");
|
|
66928
|
+
const link2 = readLink(cwd2);
|
|
66929
|
+
if (!link2) {
|
|
66930
|
+
if (json) {
|
|
66931
|
+
console.log(JSON.stringify({ linked: false, integrations: [] }, null, 2));
|
|
66932
|
+
process.exitCode = 1;
|
|
66933
|
+
return;
|
|
66934
|
+
}
|
|
66935
|
+
f2.warn("This folder is not linked to any agent.");
|
|
66936
|
+
f2.info(`Run ${import_picocolors35.default.cyan("brainbase link")} first.`);
|
|
66937
|
+
process.exitCode = 1;
|
|
66938
|
+
return;
|
|
66939
|
+
}
|
|
66940
|
+
let connections;
|
|
66941
|
+
try {
|
|
66942
|
+
connections = await api.getAgentConnections(link2.agent_id);
|
|
66943
|
+
} catch (err) {
|
|
66944
|
+
if (!json)
|
|
66945
|
+
throw err;
|
|
66946
|
+
reportFailure(err);
|
|
66947
|
+
return;
|
|
66948
|
+
}
|
|
66949
|
+
if (json) {
|
|
66950
|
+
console.log(JSON.stringify({ linked: true, ...connections }, null, 2));
|
|
66951
|
+
return;
|
|
66952
|
+
}
|
|
66953
|
+
console.log(formatConnections(connections));
|
|
66954
|
+
}
|
|
66955
|
+
function formatConnections(connections) {
|
|
66956
|
+
const lines = [""];
|
|
66957
|
+
for (const integration of connections.integrations) {
|
|
66958
|
+
lines.push(` ${statusMark(integration)} ${import_picocolors35.default.bold(integration.name)}${describe(integration)}`);
|
|
66959
|
+
const hint = hintFor(integration);
|
|
66960
|
+
if (hint)
|
|
66961
|
+
lines.push(` ${import_picocolors35.default.dim(hint)}`);
|
|
66962
|
+
}
|
|
66963
|
+
lines.push("");
|
|
66964
|
+
return lines.join(`
|
|
66965
|
+
`);
|
|
66966
|
+
}
|
|
66967
|
+
function statusMark(integration) {
|
|
66968
|
+
return integration.connected ? import_picocolors35.default.green("✓") : import_picocolors35.default.dim("·");
|
|
66969
|
+
}
|
|
66970
|
+
function describe(integration) {
|
|
66971
|
+
if (!integration.connected)
|
|
66972
|
+
return ` ${import_picocolors35.default.dim("not connected")}`;
|
|
66973
|
+
return integration.detail ? ` ${import_picocolors35.default.dim(integration.detail)}` : ` ${import_picocolors35.default.dim("connected")}`;
|
|
66974
|
+
}
|
|
66975
|
+
function hintFor(integration) {
|
|
66976
|
+
const action = actionability(integration);
|
|
66977
|
+
if (integration.connected) {
|
|
66978
|
+
return action.kind === "connectable" ? `brainbase agent disconnect ${integration.name}` : undefined;
|
|
66979
|
+
}
|
|
66980
|
+
return explain(integration);
|
|
66981
|
+
}
|
|
66982
|
+
|
|
66983
|
+
// src/cli/agent-disconnect.ts
|
|
66984
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
66985
|
+
async function runAgentDisconnect(cwd2, target, args) {
|
|
66986
|
+
const json = Boolean(args.json);
|
|
66987
|
+
try {
|
|
66988
|
+
await disconnect(cwd2, target, args, json);
|
|
66989
|
+
} catch (err) {
|
|
66990
|
+
if (!json)
|
|
66991
|
+
throw err;
|
|
66992
|
+
reportFailure(err);
|
|
66993
|
+
}
|
|
66994
|
+
}
|
|
66995
|
+
async function disconnect(cwd2, target, args, json) {
|
|
66996
|
+
if (!target) {
|
|
66997
|
+
throw new Error(`Which integration? Try: ${IMPLEMENTED_INTEGRATIONS.join(", ")}.`);
|
|
66998
|
+
}
|
|
66999
|
+
if (!isImplemented(target)) {
|
|
67000
|
+
throw new Error(`Cannot disconnect ${JSON.stringify(target)} from the CLI. Try: ${IMPLEMENTED_INTEGRATIONS.join(", ")}.`);
|
|
67001
|
+
}
|
|
67002
|
+
if (!json)
|
|
67003
|
+
banner(`agent disconnect ${target}`);
|
|
67004
|
+
const link2 = readLink(cwd2);
|
|
67005
|
+
if (!link2) {
|
|
67006
|
+
throw new Error("This folder is not linked to any agent. Run `brainbase link` first.");
|
|
67007
|
+
}
|
|
67008
|
+
if (!json && !autoProceed(args.yes)) {
|
|
67009
|
+
const ok = ensureNotCancelled(await se({ message: `Disconnect ${target} from ${link2.name}?` }));
|
|
67010
|
+
if (!ok) {
|
|
67011
|
+
f2.info("Nothing changed.");
|
|
67012
|
+
return;
|
|
67013
|
+
}
|
|
67014
|
+
}
|
|
67015
|
+
const result2 = await api.disconnectIntegration(link2.agent_id, target);
|
|
67016
|
+
if (json) {
|
|
67017
|
+
console.log(JSON.stringify(result2, null, 2));
|
|
67018
|
+
return;
|
|
67019
|
+
}
|
|
67020
|
+
f2.success(`${target} disconnected`);
|
|
67021
|
+
f2.info(`Run ${import_picocolors36.default.cyan("brainbase agent pull")} to drop the built-in ${target} MCP server locally.`);
|
|
67022
|
+
}
|
|
67023
|
+
|
|
66424
67024
|
// src/cli/agent.ts
|
|
66425
67025
|
async function runAgent(cwd2, sub, args, opts) {
|
|
66426
67026
|
if (args.some((arg) => arg === "--help" || arg === "-h")) {
|
|
@@ -66471,6 +67071,23 @@ async function runAgent(cwd2, sub, args, opts) {
|
|
|
66471
67071
|
case "status":
|
|
66472
67072
|
await runAgentStatus(cwd2, { json: opts.json });
|
|
66473
67073
|
return;
|
|
67074
|
+
case "connections":
|
|
67075
|
+
await runAgentConnections(cwd2, { json: opts.json });
|
|
67076
|
+
return;
|
|
67077
|
+
case "connect":
|
|
67078
|
+
await runAgentConnect(cwd2, args[0], {
|
|
67079
|
+
botToken: opts.botToken,
|
|
67080
|
+
signingSecret: opts.signingSecret,
|
|
67081
|
+
appId: opts.appId,
|
|
67082
|
+
appName: opts.appName,
|
|
67083
|
+
botName: opts.botName,
|
|
67084
|
+
botImageUrl: opts.botImageUrl,
|
|
67085
|
+
json: opts.json
|
|
67086
|
+
});
|
|
67087
|
+
return;
|
|
67088
|
+
case "disconnect":
|
|
67089
|
+
await runAgentDisconnect(cwd2, args[0], { yes: opts.yes, json: opts.json });
|
|
67090
|
+
return;
|
|
66474
67091
|
case "env":
|
|
66475
67092
|
await runAgentEnv(cwd2, { shell: opts.shell });
|
|
66476
67093
|
return;
|
|
@@ -66490,25 +67107,31 @@ async function runAgent(cwd2, sub, args, opts) {
|
|
|
66490
67107
|
function printHelp() {
|
|
66491
67108
|
const out = [];
|
|
66492
67109
|
out.push("");
|
|
66493
|
-
out.push(` ${
|
|
67110
|
+
out.push(` ${import_picocolors37.default.bold("brainbase agent")} ${import_picocolors37.default.dim("<sub> [options]")}`);
|
|
67111
|
+
out.push("");
|
|
67112
|
+
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)")}`);
|
|
67113
|
+
out.push(` ${import_picocolors37.default.cyan("create")} ${import_picocolors37.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
67114
|
+
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")}`);
|
|
67115
|
+
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)")}`);
|
|
67116
|
+
out.push(` ${import_picocolors37.default.cyan("unpack")} ${import_picocolors37.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
|
|
67117
|
+
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)")}`);
|
|
67118
|
+
out.push(` ${import_picocolors37.default.cyan("connections")} ${import_picocolors37.default.dim("show which integrations this agent is wired to (--json for scripts)")}`);
|
|
67119
|
+
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")}`);
|
|
67120
|
+
out.push(` ${import_picocolors37.default.cyan("disconnect")} ${import_picocolors37.default.dim("<name>")} ${import_picocolors37.default.dim("revoke a slack or meeting install")}`);
|
|
67121
|
+
out.push(` ${import_picocolors37.default.cyan("env")} ${import_picocolors37.default.dim('print export statements — use with `eval "$(brainbase agent env)"`')}`);
|
|
66494
67122
|
out.push("");
|
|
66495
|
-
out.push(` ${
|
|
66496
|
-
out.push(` ${
|
|
66497
|
-
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")}`);
|
|
66498
|
-
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)")}`);
|
|
66499
|
-
out.push(` ${import_picocolors34.default.cyan("unpack")} ${import_picocolors34.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
|
|
66500
|
-
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)")}`);
|
|
66501
|
-
out.push(` ${import_picocolors34.default.cyan("env")} ${import_picocolors34.default.dim('print export statements — use with `eval "$(brainbase agent env)"`')}`);
|
|
67123
|
+
out.push(` ${import_picocolors37.default.dim("Slack credentials:")} ${import_picocolors37.default.dim("--bot-token / BRAINBASE_SLACK_BOT_TOKEN, --signing-secret / BRAINBASE_SLACK_SIGNING_SECRET,")}`);
|
|
67124
|
+
out.push(` ${import_picocolors37.default.dim('or pipe {"bot_token":"…","signing_secret":"…"} on stdin to keep them out of argv.')}`);
|
|
66502
67125
|
out.push("");
|
|
66503
67126
|
console.log(out.join(`
|
|
66504
67127
|
`));
|
|
66505
67128
|
}
|
|
66506
67129
|
|
|
66507
67130
|
// src/cli/team.ts
|
|
66508
|
-
var
|
|
67131
|
+
var import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
66509
67132
|
|
|
66510
67133
|
// src/cli/team-list.ts
|
|
66511
|
-
var
|
|
67134
|
+
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
66512
67135
|
async function runTeamList(args) {
|
|
66513
67136
|
if (!args.json)
|
|
66514
67137
|
banner("team list — teams you can put agents in");
|
|
@@ -66528,25 +67151,25 @@ async function runTeamList(args) {
|
|
|
66528
67151
|
function formatTeamList(grouped) {
|
|
66529
67152
|
const lines = [""];
|
|
66530
67153
|
if (grouped.length === 0) {
|
|
66531
|
-
lines.push(` ${
|
|
67154
|
+
lines.push(` ${import_picocolors38.default.dim("You are not a member of any organization.")}`, "");
|
|
66532
67155
|
return lines.join(`
|
|
66533
67156
|
`);
|
|
66534
67157
|
}
|
|
66535
67158
|
const nameWidth = Math.max(...grouped.flatMap(({ teams }) => teams.map((t) => t.name.length)), 0);
|
|
66536
67159
|
for (const { org, teams, error } of grouped) {
|
|
66537
|
-
const slug = org.slug ? ` ${
|
|
66538
|
-
lines.push(` ${
|
|
67160
|
+
const slug = org.slug ? ` ${import_picocolors38.default.dim(org.slug)}` : "";
|
|
67161
|
+
lines.push(` ${import_picocolors38.default.bold(org.name)}${slug}`);
|
|
66539
67162
|
if (error) {
|
|
66540
|
-
lines.push(` ${
|
|
67163
|
+
lines.push(` ${import_picocolors38.default.red(`could not load teams: ${error}`)}`);
|
|
66541
67164
|
} else if (teams.length === 0) {
|
|
66542
|
-
lines.push(` ${
|
|
67165
|
+
lines.push(` ${import_picocolors38.default.dim("no teams yet — create one in the web app")}`);
|
|
66543
67166
|
}
|
|
66544
67167
|
for (const team of teams) {
|
|
66545
|
-
lines.push(` ${team.name.padEnd(nameWidth)} ${
|
|
67168
|
+
lines.push(` ${team.name.padEnd(nameWidth)} ${import_picocolors38.default.dim(team.id)}`);
|
|
66546
67169
|
}
|
|
66547
67170
|
lines.push("");
|
|
66548
67171
|
}
|
|
66549
|
-
lines.push(` ${
|
|
67172
|
+
lines.push(` ${import_picocolors38.default.dim("list a team’s agents with")} ${import_picocolors38.default.cyan("brainbase agent list --team <id>")}`, "");
|
|
66550
67173
|
return lines.join(`
|
|
66551
67174
|
`);
|
|
66552
67175
|
}
|
|
@@ -66577,28 +67200,28 @@ async function runTeam(sub, args, opts) {
|
|
|
66577
67200
|
function printHelp2() {
|
|
66578
67201
|
const out = [];
|
|
66579
67202
|
out.push("");
|
|
66580
|
-
out.push(` ${
|
|
67203
|
+
out.push(` ${import_picocolors39.default.bold("brainbase team")} ${import_picocolors39.default.dim("<sub> [options]")}`);
|
|
66581
67204
|
out.push("");
|
|
66582
|
-
out.push(` ${
|
|
67205
|
+
out.push(` ${import_picocolors39.default.cyan("list")} ${import_picocolors39.default.dim("show the teams you can create agents in, grouped by organization")}`);
|
|
66583
67206
|
out.push("");
|
|
66584
|
-
out.push(` ${
|
|
66585
|
-
out.push(` ${
|
|
67207
|
+
out.push(` ${import_picocolors39.default.dim("--org <id-or-slug>")} ${import_picocolors39.default.dim("limit to one organization")}`);
|
|
67208
|
+
out.push(` ${import_picocolors39.default.dim("--json")} ${import_picocolors39.default.dim("machine-readable output")}`);
|
|
66586
67209
|
out.push("");
|
|
66587
67210
|
console.log(out.join(`
|
|
66588
67211
|
`));
|
|
66589
67212
|
}
|
|
66590
67213
|
|
|
66591
67214
|
// src/cli/orchestration.ts
|
|
66592
|
-
var
|
|
67215
|
+
var import_picocolors46 = __toESM(require_picocolors(), 1);
|
|
66593
67216
|
|
|
66594
67217
|
// src/cli/orchestration-pull.ts
|
|
66595
67218
|
import path86 from "node:path";
|
|
66596
|
-
import
|
|
66597
|
-
var
|
|
67219
|
+
import fs78 from "node:fs";
|
|
67220
|
+
var import_picocolors40 = __toESM(require_picocolors(), 1);
|
|
66598
67221
|
|
|
66599
67222
|
// src/core/orchestration-manifest.ts
|
|
66600
67223
|
import path83 from "node:path";
|
|
66601
|
-
import
|
|
67224
|
+
import fs75 from "node:fs";
|
|
66602
67225
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
66603
67226
|
var ORCH_MANIFEST_FILE = "brainbase-orchestration.yaml";
|
|
66604
67227
|
var ORCH_MEMBERS_DIR = "agents";
|
|
@@ -66654,13 +67277,13 @@ function orchManifestPath(cwd2) {
|
|
|
66654
67277
|
return path83.join(cwd2, ORCH_MANIFEST_FILE);
|
|
66655
67278
|
}
|
|
66656
67279
|
function hasOrchManifest(cwd2) {
|
|
66657
|
-
return
|
|
67280
|
+
return fs75.existsSync(orchManifestPath(cwd2));
|
|
66658
67281
|
}
|
|
66659
67282
|
function readOrchManifest(cwd2) {
|
|
66660
67283
|
const p2 = orchManifestPath(cwd2);
|
|
66661
|
-
if (!
|
|
67284
|
+
if (!fs75.existsSync(p2))
|
|
66662
67285
|
return null;
|
|
66663
|
-
const raw =
|
|
67286
|
+
const raw = fs75.readFileSync(p2, "utf8");
|
|
66664
67287
|
let parsed;
|
|
66665
67288
|
try {
|
|
66666
67289
|
parsed = import_yaml4.default.parse(raw);
|
|
@@ -66681,7 +67304,7 @@ function writeOrchManifest(cwd2, manifest) {
|
|
|
66681
67304
|
` + " `brainbase orchestration push`. Member agents live under ./agents/." + `
|
|
66682
67305
|
Schedule triggers are writable. App/Pipedream triggers are preserved
|
|
66683
67306
|
` + " as read-only context and ignored by `orchestration push`.";
|
|
66684
|
-
|
|
67307
|
+
fs75.writeFileSync(orchManifestPath(cwd2), String(doc), "utf8");
|
|
66685
67308
|
}
|
|
66686
67309
|
function memberDir(cwd2, slug) {
|
|
66687
67310
|
return path83.join(cwd2, ORCH_MEMBERS_DIR, slug);
|
|
@@ -66719,7 +67342,7 @@ function resolveMemberSlugs(members) {
|
|
|
66719
67342
|
|
|
66720
67343
|
// src/core/orchestration-link.ts
|
|
66721
67344
|
import path84 from "node:path";
|
|
66722
|
-
import
|
|
67345
|
+
import fs76 from "node:fs";
|
|
66723
67346
|
var ORCH_LINK_FILE = "orchestration-link.json";
|
|
66724
67347
|
var ORCH_SYNC_STATE_FILE = "orchestration-sync-state.json";
|
|
66725
67348
|
var OrchestrationLinkSchema = exports_external.object({
|
|
@@ -66770,12 +67393,12 @@ function readOrchLink(cwd2) {
|
|
|
66770
67393
|
}
|
|
66771
67394
|
function writeOrchLink(cwd2, link2) {
|
|
66772
67395
|
ensureDir(path84.join(cwd2, LINK_DIR));
|
|
66773
|
-
const
|
|
67396
|
+
const clean2 = {};
|
|
66774
67397
|
for (const [k3, v3] of Object.entries(link2)) {
|
|
66775
67398
|
if (v3 !== null && v3 !== undefined)
|
|
66776
|
-
|
|
67399
|
+
clean2[k3] = v3;
|
|
66777
67400
|
}
|
|
66778
|
-
writeJson(orchLinkPath(cwd2),
|
|
67401
|
+
writeJson(orchLinkPath(cwd2), clean2);
|
|
66779
67402
|
ensureGitignore2(cwd2);
|
|
66780
67403
|
}
|
|
66781
67404
|
function readOrchSyncState(cwd2) {
|
|
@@ -66799,12 +67422,12 @@ function ensureGitignore2(cwd2) {
|
|
|
66799
67422
|
`;
|
|
66800
67423
|
try {
|
|
66801
67424
|
if (!exists(ignorePath)) {
|
|
66802
|
-
|
|
67425
|
+
fs76.writeFileSync(ignorePath, desired);
|
|
66803
67426
|
return;
|
|
66804
67427
|
}
|
|
66805
|
-
const current =
|
|
67428
|
+
const current = fs76.readFileSync(ignorePath, "utf8");
|
|
66806
67429
|
if (!current.split(/\r?\n/).some((l2) => l2.trim() === ORCH_SYNC_STATE_FILE)) {
|
|
66807
|
-
|
|
67430
|
+
fs76.writeFileSync(ignorePath, current.endsWith(`
|
|
66808
67431
|
`) ? current + desired : current + `
|
|
66809
67432
|
` + desired);
|
|
66810
67433
|
}
|
|
@@ -66813,7 +67436,7 @@ function ensureGitignore2(cwd2) {
|
|
|
66813
67436
|
|
|
66814
67437
|
// src/core/agent-fresh-install.ts
|
|
66815
67438
|
import path85 from "node:path";
|
|
66816
|
-
import
|
|
67439
|
+
import fs77 from "node:fs";
|
|
66817
67440
|
import os15 from "node:os";
|
|
66818
67441
|
async function installAgentFresh(input) {
|
|
66819
67442
|
const { cwd: cwd2, agent, cloud, harness } = input;
|
|
@@ -66904,19 +67527,19 @@ async function installAgentFresh(input) {
|
|
|
66904
67527
|
};
|
|
66905
67528
|
} finally {
|
|
66906
67529
|
try {
|
|
66907
|
-
|
|
67530
|
+
fs77.rmSync(stageRoot, { recursive: true, force: true });
|
|
66908
67531
|
} catch {}
|
|
66909
67532
|
}
|
|
66910
67533
|
}
|
|
66911
67534
|
function stageManifestComponents2(components) {
|
|
66912
|
-
const root =
|
|
67535
|
+
const root = fs77.mkdtempSync(path85.join(os15.tmpdir(), "brainbase-orch-pull-"));
|
|
66913
67536
|
for (const c2 of components) {
|
|
66914
67537
|
const compDir = path85.join(root, c2.type, c2.slug);
|
|
66915
67538
|
ensureDir(compDir);
|
|
66916
67539
|
for (const f4 of c2.files) {
|
|
66917
67540
|
const target = path85.join(compDir, f4.path);
|
|
66918
67541
|
ensureDir(path85.dirname(target));
|
|
66919
|
-
|
|
67542
|
+
fs77.writeFileSync(target, f4.content);
|
|
66920
67543
|
}
|
|
66921
67544
|
}
|
|
66922
67545
|
return root;
|
|
@@ -66951,7 +67574,7 @@ function materializeInstructions2(cwd2, cloud) {
|
|
|
66951
67574
|
continue;
|
|
66952
67575
|
const target = path85.join(cwd2, DEFAULT_INSTRUCTIONS_FILE);
|
|
66953
67576
|
ensureDir(path85.dirname(target));
|
|
66954
|
-
|
|
67577
|
+
fs77.writeFileSync(target, normalizeInstructionBody(body), "utf8");
|
|
66955
67578
|
return;
|
|
66956
67579
|
}
|
|
66957
67580
|
}
|
|
@@ -66965,7 +67588,7 @@ function materializePlaybooks2(cwd2, cloud) {
|
|
|
66965
67588
|
const { body } = stripPlaybookFrontmatter(raw);
|
|
66966
67589
|
const target = path85.join(cwd2, DEFAULT_PLAYBOOKS_DIR, `${c2.slug}.md`);
|
|
66967
67590
|
ensureDir(path85.dirname(target));
|
|
66968
|
-
|
|
67591
|
+
fs77.writeFileSync(target, body, "utf8");
|
|
66969
67592
|
}
|
|
66970
67593
|
}
|
|
66971
67594
|
function buildManifestFromCloud(cloud, agent, localOnly = {}) {
|
|
@@ -67114,8 +67737,8 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67114
67737
|
orchId = args.orchestrationId;
|
|
67115
67738
|
} else {
|
|
67116
67739
|
f2.warn("This folder is not linked to any orchestration.");
|
|
67117
|
-
f2.info(`Run ${
|
|
67118
|
-
or ${
|
|
67740
|
+
f2.info(`Run ${import_picocolors40.default.cyan("brainbase orchestration pull <id>")} with an orchestration id,
|
|
67741
|
+
or ${import_picocolors40.default.cyan("brainbase orchestration list")} to find one.`);
|
|
67119
67742
|
return;
|
|
67120
67743
|
}
|
|
67121
67744
|
const sp = de();
|
|
@@ -67134,24 +67757,24 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67134
67757
|
const slugFor = (agentId) => slugByAgent.get(agentId) ?? agentId;
|
|
67135
67758
|
const planLines = [];
|
|
67136
67759
|
planLines.push("");
|
|
67137
|
-
planLines.push(` ${
|
|
67760
|
+
planLines.push(` ${import_picocolors40.default.bold(cloud.name)} ${import_picocolors40.default.dim(`(${cloud.id})`)}`);
|
|
67138
67761
|
if (cloud.description)
|
|
67139
|
-
planLines.push(` ${
|
|
67762
|
+
planLines.push(` ${import_picocolors40.default.dim(cloud.description)}`);
|
|
67140
67763
|
planLines.push("");
|
|
67141
|
-
planLines.push(` ${
|
|
67764
|
+
planLines.push(` ${import_picocolors40.default.dim("members:")}`);
|
|
67142
67765
|
for (const m3 of cloud.members) {
|
|
67143
67766
|
const skipped = !m3.manifest;
|
|
67144
|
-
const tail2 = skipped ?
|
|
67145
|
-
planLines.push(` ${
|
|
67767
|
+
const tail2 = skipped ? import_picocolors40.default.red(" (manifest unavailable — skipped)") : "";
|
|
67768
|
+
planLines.push(` ${import_picocolors40.default.cyan("•")} ${import_picocolors40.default.bold(slugFor(m3.agent_id))} ${import_picocolors40.default.dim(`(${m3.name})`)}${tail2}`);
|
|
67146
67769
|
}
|
|
67147
67770
|
if (cloud.edges.length) {
|
|
67148
67771
|
planLines.push("");
|
|
67149
|
-
planLines.push(` ${
|
|
67772
|
+
planLines.push(` ${import_picocolors40.default.dim("edges:")}`);
|
|
67150
67773
|
for (const e2 of cloud.edges) {
|
|
67151
67774
|
const from = slugFor(e2.from_agent_id);
|
|
67152
67775
|
const to2 = slugFor(e2.to_agent_id);
|
|
67153
|
-
const desc = e2.description ? ` ${
|
|
67154
|
-
planLines.push(` ${
|
|
67776
|
+
const desc = e2.description ? ` ${import_picocolors40.default.dim("— " + e2.description)}` : "";
|
|
67777
|
+
planLines.push(` ${import_picocolors40.default.cyan(from)} ${import_picocolors40.default.dim("→")} ${import_picocolors40.default.cyan(to2)}${desc}`);
|
|
67155
67778
|
}
|
|
67156
67779
|
}
|
|
67157
67780
|
planLines.push("");
|
|
@@ -67160,7 +67783,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67160
67783
|
const isRefresh = !!existingLink;
|
|
67161
67784
|
if (!autoProceed(args.yes) && !isRefresh) {
|
|
67162
67785
|
const ok = await se({
|
|
67163
|
-
message: `Pull into ${
|
|
67786
|
+
message: `Pull into ${import_picocolors40.default.bold(cwd2)}?`,
|
|
67164
67787
|
initialValue: true
|
|
67165
67788
|
});
|
|
67166
67789
|
if (!ensureNotCancelled(ok)) {
|
|
@@ -67169,7 +67792,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67169
67792
|
}
|
|
67170
67793
|
}
|
|
67171
67794
|
const fallbackHarness = args.harness ?? "claude-code";
|
|
67172
|
-
|
|
67795
|
+
fs78.mkdirSync(cwd2, { recursive: true });
|
|
67173
67796
|
if (hasOrchManifest(cwd2) && existingLink && existingLink.orchestration_id !== orchId) {
|
|
67174
67797
|
f2.error(`This folder is linked to orchestration ${existingLink.orchestration_id}, not ${orchId}. Move to a fresh directory or unlink first.`);
|
|
67175
67798
|
return;
|
|
@@ -67204,7 +67827,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67204
67827
|
scope: "project",
|
|
67205
67828
|
pullSecrets: true
|
|
67206
67829
|
});
|
|
67207
|
-
memberSp.stop(`Installed ${
|
|
67830
|
+
memberSp.stop(`Installed ${import_picocolors40.default.bold(slug)} ${import_picocolors40.default.dim(`(${m3.manifest.components.length} components)`)}.`);
|
|
67208
67831
|
installedMembers.push({
|
|
67209
67832
|
agent_id: m3.agent_id,
|
|
67210
67833
|
slug,
|
|
@@ -67265,7 +67888,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
67265
67888
|
payload_schema: e2.payload_schema ?? {}
|
|
67266
67889
|
}))
|
|
67267
67890
|
});
|
|
67268
|
-
$e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path86.basename(cwd2)}/ ${
|
|
67891
|
+
$e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path86.basename(cwd2)}/ ${import_picocolors40.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
|
|
67269
67892
|
}
|
|
67270
67893
|
function handleApiError5(err) {
|
|
67271
67894
|
if (err instanceof ApiError) {
|
|
@@ -67282,7 +67905,7 @@ function handleApiError5(err) {
|
|
|
67282
67905
|
}
|
|
67283
67906
|
|
|
67284
67907
|
// src/cli/orchestration-push.ts
|
|
67285
|
-
var
|
|
67908
|
+
var import_picocolors41 = __toESM(require_picocolors(), 1);
|
|
67286
67909
|
|
|
67287
67910
|
// src/core/orchestration-outgoing.ts
|
|
67288
67911
|
function buildOrchestrationGraphPayload(manifest, slugToAgentId) {
|
|
@@ -67365,7 +67988,7 @@ function findUnpushableMembers(cwd2, members) {
|
|
|
67365
67988
|
continue;
|
|
67366
67989
|
}
|
|
67367
67990
|
if (!memberManifest.id) {
|
|
67368
|
-
f2.error(`${m3.slug}: ${AGENT_MANIFEST_FILE} is unclaimed (no ${
|
|
67991
|
+
f2.error(`${m3.slug}: ${AGENT_MANIFEST_FILE} is unclaimed (no ${import_picocolors41.default.cyan("id")}), so there is nothing to push to.`);
|
|
67369
67992
|
blocked.push(m3.slug);
|
|
67370
67993
|
continue;
|
|
67371
67994
|
}
|
|
@@ -67380,12 +68003,12 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
67380
68003
|
const link2 = readOrchLink(cwd2);
|
|
67381
68004
|
if (!link2) {
|
|
67382
68005
|
f2.warn("This folder is not linked to any orchestration.");
|
|
67383
|
-
f2.info(`Run ${
|
|
68006
|
+
f2.info(`Run ${import_picocolors41.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
67384
68007
|
return;
|
|
67385
68008
|
}
|
|
67386
68009
|
if (!hasOrchManifest(cwd2)) {
|
|
67387
|
-
f2.warn(`No ${
|
|
67388
|
-
f2.info(`Run ${
|
|
68010
|
+
f2.warn(`No ${import_picocolors41.default.bold(ORCH_MANIFEST_FILE)} here.`);
|
|
68011
|
+
f2.info(`Run ${import_picocolors41.default.cyan("brainbase orchestration pull")} to materialise the manifest before pushing.`);
|
|
67389
68012
|
return;
|
|
67390
68013
|
}
|
|
67391
68014
|
let manifest;
|
|
@@ -67409,7 +68032,7 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
67409
68032
|
}
|
|
67410
68033
|
if (missing.length) {
|
|
67411
68034
|
f2.error(`Missing local checkouts for: ${missing.join(", ")}.`);
|
|
67412
|
-
f2.info(`Run ${
|
|
68035
|
+
f2.info(`Run ${import_picocolors41.default.cyan("brainbase orchestration pull")} to materialise the missing folders.`);
|
|
67413
68036
|
process.exitCode = 1;
|
|
67414
68037
|
return;
|
|
67415
68038
|
}
|
|
@@ -67430,13 +68053,13 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
67430
68053
|
}
|
|
67431
68054
|
}
|
|
67432
68055
|
const plan = [""];
|
|
67433
|
-
plan.push(` ${
|
|
67434
|
-
plan.push(` ${
|
|
68056
|
+
plan.push(` ${import_picocolors41.default.bold(link2.name)} ${import_picocolors41.default.dim(`(${link2.orchestration_id})`)}`);
|
|
68057
|
+
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"}`)}`);
|
|
67435
68058
|
plan.push("");
|
|
67436
68059
|
if (!args.graphOnly) {
|
|
67437
|
-
plan.push(` ${
|
|
68060
|
+
plan.push(` ${import_picocolors41.default.dim("per-member agent push:")}`);
|
|
67438
68061
|
for (const m3 of manifest.members) {
|
|
67439
|
-
plan.push(` ${
|
|
68062
|
+
plan.push(` ${import_picocolors41.default.cyan("•")} ${import_picocolors41.default.bold(m3.slug)}`);
|
|
67440
68063
|
}
|
|
67441
68064
|
plan.push("");
|
|
67442
68065
|
}
|
|
@@ -67456,7 +68079,7 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
67456
68079
|
for (const m3 of manifest.members) {
|
|
67457
68080
|
const dir = memberDir(cwd2, m3.slug);
|
|
67458
68081
|
console.log("");
|
|
67459
|
-
console.log(`${
|
|
68082
|
+
console.log(`${import_picocolors41.default.dim("───")} ${import_picocolors41.default.bold(m3.slug)} ${import_picocolors41.default.dim("───")}`);
|
|
67460
68083
|
const exitCodeBeforePush = process.exitCode;
|
|
67461
68084
|
try {
|
|
67462
68085
|
await runAgentPush(dir, { yes: true });
|
|
@@ -67520,7 +68143,7 @@ function handleApiError6(err) {
|
|
|
67520
68143
|
f2.error("You do not have access to this orchestration.");
|
|
67521
68144
|
} else if (err.status === 409) {
|
|
67522
68145
|
f2.error(err.message);
|
|
67523
|
-
f2.info(`Run ${
|
|
68146
|
+
f2.info(`Run ${import_picocolors41.default.cyan("brainbase orchestration pull")} to reconcile, then push again.`);
|
|
67524
68147
|
} else {
|
|
67525
68148
|
f2.error(err.message);
|
|
67526
68149
|
}
|
|
@@ -67530,13 +68153,13 @@ function handleApiError6(err) {
|
|
|
67530
68153
|
}
|
|
67531
68154
|
|
|
67532
68155
|
// src/cli/orchestration-status.ts
|
|
67533
|
-
var
|
|
68156
|
+
var import_picocolors42 = __toESM(require_picocolors(), 1);
|
|
67534
68157
|
async function runOrchestrationStatus(cwd2) {
|
|
67535
68158
|
banner("orchestration status — what changed locally, remotely, both");
|
|
67536
68159
|
const link2 = readOrchLink(cwd2);
|
|
67537
68160
|
if (!link2) {
|
|
67538
68161
|
f2.warn("This folder is not linked to any orchestration.");
|
|
67539
|
-
f2.info(`Run ${
|
|
68162
|
+
f2.info(`Run ${import_picocolors42.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
67540
68163
|
return;
|
|
67541
68164
|
}
|
|
67542
68165
|
const localManifest = hasOrchManifest(cwd2) ? readOrchManifest(cwd2) : null;
|
|
@@ -67559,8 +68182,8 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67559
68182
|
}
|
|
67560
68183
|
const lines = [];
|
|
67561
68184
|
lines.push("");
|
|
67562
|
-
lines.push(` ${
|
|
67563
|
-
lines.push(` ${
|
|
68185
|
+
lines.push(` ${import_picocolors42.default.bold(link2.name)} ${import_picocolors42.default.dim(`(${link2.orchestration_id})`)}`);
|
|
68186
|
+
lines.push(` ${import_picocolors42.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
|
|
67564
68187
|
lines.push("");
|
|
67565
68188
|
const localSlugByAgentId = new Map;
|
|
67566
68189
|
for (const m3 of localManifest?.members ?? []) {
|
|
@@ -67574,12 +68197,12 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67574
68197
|
const membersAdded = [...localMemberSet].filter((s3) => !cloudMemberSet.has(s3));
|
|
67575
68198
|
const membersRemoved = [...cloudMemberSet].filter((s3) => !localMemberSet.has(s3));
|
|
67576
68199
|
if (membersAdded.length || membersRemoved.length) {
|
|
67577
|
-
lines.push(` ${
|
|
68200
|
+
lines.push(` ${import_picocolors42.default.bold("members")}`);
|
|
67578
68201
|
for (const slug of membersAdded) {
|
|
67579
|
-
lines.push(` ${
|
|
68202
|
+
lines.push(` ${import_picocolors42.default.yellow("→ push")} added in yaml: ${import_picocolors42.default.bold(slug)}`);
|
|
67580
68203
|
}
|
|
67581
68204
|
for (const slug of membersRemoved) {
|
|
67582
|
-
lines.push(` ${
|
|
68205
|
+
lines.push(` ${import_picocolors42.default.cyan("← pull")} added on cloud: ${import_picocolors42.default.bold(slug)}`);
|
|
67583
68206
|
}
|
|
67584
68207
|
lines.push("");
|
|
67585
68208
|
}
|
|
@@ -67594,11 +68217,11 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67594
68217
|
const edgesAdded = [...localEdges.keys()].filter((k3) => !cloudEdges.has(k3));
|
|
67595
68218
|
const edgesRemoved = [...cloudEdges.keys()].filter((k3) => !localEdges.has(k3));
|
|
67596
68219
|
if (edgesAdded.length || edgesRemoved.length) {
|
|
67597
|
-
lines.push(` ${
|
|
68220
|
+
lines.push(` ${import_picocolors42.default.bold("edges")}`);
|
|
67598
68221
|
for (const k3 of edgesAdded)
|
|
67599
|
-
lines.push(` ${
|
|
68222
|
+
lines.push(` ${import_picocolors42.default.yellow("→ push")} added in yaml: ${k3}`);
|
|
67600
68223
|
for (const k3 of edgesRemoved)
|
|
67601
|
-
lines.push(` ${
|
|
68224
|
+
lines.push(` ${import_picocolors42.default.cyan("← pull")} added on cloud: ${k3}`);
|
|
67602
68225
|
lines.push("");
|
|
67603
68226
|
}
|
|
67604
68227
|
const cloudTriggerKey = (t) => {
|
|
@@ -67636,11 +68259,11 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67636
68259
|
const triggersAdded = [...localTriggers.keys()].filter((k3) => !cloudTriggers.has(k3));
|
|
67637
68260
|
const triggersRemoved = [...cloudTriggers.keys()].filter((k3) => !localTriggers.has(k3));
|
|
67638
68261
|
if (triggersAdded.length || triggersRemoved.length) {
|
|
67639
|
-
lines.push(` ${
|
|
68262
|
+
lines.push(` ${import_picocolors42.default.bold("schedule triggers")}`);
|
|
67640
68263
|
for (const k3 of triggersAdded)
|
|
67641
|
-
lines.push(` ${
|
|
68264
|
+
lines.push(` ${import_picocolors42.default.yellow("→ push")} added/changed in yaml: ${localTriggers.get(k3) ?? k3}`);
|
|
67642
68265
|
for (const k3 of triggersRemoved)
|
|
67643
|
-
lines.push(` ${
|
|
68266
|
+
lines.push(` ${import_picocolors42.default.cyan("← pull")} added/changed on cloud: ${cloudTriggers.get(k3) ?? k3}`);
|
|
67644
68267
|
lines.push("");
|
|
67645
68268
|
}
|
|
67646
68269
|
const lockByAgentId = new Map((lock?.members ?? []).map((m3) => [m3.agent_id, m3]));
|
|
@@ -67663,27 +68286,27 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
67663
68286
|
}
|
|
67664
68287
|
}
|
|
67665
68288
|
if (memberDrift.length) {
|
|
67666
|
-
lines.push(` ${
|
|
68289
|
+
lines.push(` ${import_picocolors42.default.bold("member content drift")}`);
|
|
67667
68290
|
for (const d3 of memberDrift) {
|
|
67668
|
-
lines.push(` ${
|
|
68291
|
+
lines.push(` ${import_picocolors42.default.cyan("?")} ${import_picocolors42.default.bold(d3.slug)} ${import_picocolors42.default.dim("— " + d3.reason)}`);
|
|
67669
68292
|
}
|
|
67670
|
-
lines.push(` ${
|
|
68293
|
+
lines.push(` ${import_picocolors42.default.dim("cd into each member folder and run")} ${import_picocolors42.default.cyan("brainbase agent status")}`);
|
|
67671
68294
|
lines.push("");
|
|
67672
68295
|
}
|
|
67673
68296
|
const revisionDrift = lock?.revision != null && cloud.revision !== lock.revision;
|
|
67674
68297
|
if (revisionDrift) {
|
|
67675
|
-
lines.push(` ${
|
|
67676
|
-
lines.push(` ${
|
|
68298
|
+
lines.push(` ${import_picocolors42.default.bold("cloud revision")}`);
|
|
68299
|
+
lines.push(` ${import_picocolors42.default.cyan("← pull")} cloud changed since last pull: ${import_picocolors42.default.dim(`lock ${lock.revision} → cloud ${cloud.revision}`)}`);
|
|
67677
68300
|
lines.push("");
|
|
67678
68301
|
}
|
|
67679
68302
|
if (!membersAdded.length && !membersRemoved.length && !edgesAdded.length && !edgesRemoved.length && !triggersAdded.length && !triggersRemoved.length && !memberDrift.length && !revisionDrift) {
|
|
67680
|
-
lines.push(` ${
|
|
68303
|
+
lines.push(` ${import_picocolors42.default.green("✓")} everything is in sync`);
|
|
67681
68304
|
lines.push("");
|
|
67682
68305
|
console.log(lines.join(`
|
|
67683
68306
|
`));
|
|
67684
68307
|
return;
|
|
67685
68308
|
}
|
|
67686
|
-
lines.push(` ${
|
|
68309
|
+
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")}`);
|
|
67687
68310
|
lines.push("");
|
|
67688
68311
|
console.log(lines.join(`
|
|
67689
68312
|
`));
|
|
@@ -67698,7 +68321,7 @@ function stableJson(value) {
|
|
|
67698
68321
|
}
|
|
67699
68322
|
|
|
67700
68323
|
// src/cli/orchestration-list.ts
|
|
67701
|
-
var
|
|
68324
|
+
var import_picocolors43 = __toESM(require_picocolors(), 1);
|
|
67702
68325
|
async function runOrchestrationList(args) {
|
|
67703
68326
|
banner("orchestration list — orchestrations under a team");
|
|
67704
68327
|
const { org, team } = await resolveOrgAndTeam({
|
|
@@ -67722,21 +68345,21 @@ async function runOrchestrationList(args) {
|
|
|
67722
68345
|
}
|
|
67723
68346
|
const lines = [""];
|
|
67724
68347
|
for (const o2 of items) {
|
|
67725
|
-
lines.push(` ${
|
|
68348
|
+
lines.push(` ${import_picocolors43.default.bold(o2.name)} ${import_picocolors43.default.dim(o2.id)}`);
|
|
67726
68349
|
if (o2.description)
|
|
67727
|
-
lines.push(` ${
|
|
67728
|
-
lines.push(` ${
|
|
68350
|
+
lines.push(` ${import_picocolors43.default.dim(o2.description)}`);
|
|
68351
|
+
lines.push(` ${import_picocolors43.default.dim(`${o2.member_count} member${o2.member_count === 1 ? "" : "s"} · ${o2.edge_count} edge${o2.edge_count === 1 ? "" : "s"}`)}`);
|
|
67729
68352
|
lines.push("");
|
|
67730
68353
|
}
|
|
67731
|
-
lines.push(` ${
|
|
68354
|
+
lines.push(` ${import_picocolors43.default.dim("pull one with")} ${import_picocolors43.default.cyan("brainbase orchestration pull <id>")}`);
|
|
67732
68355
|
lines.push("");
|
|
67733
68356
|
console.log(lines.join(`
|
|
67734
68357
|
`));
|
|
67735
68358
|
}
|
|
67736
68359
|
|
|
67737
68360
|
// src/cli/orchestration-add-agent.ts
|
|
67738
|
-
import
|
|
67739
|
-
var
|
|
68361
|
+
import fs79 from "node:fs";
|
|
68362
|
+
var import_picocolors44 = __toESM(require_picocolors(), 1);
|
|
67740
68363
|
|
|
67741
68364
|
// src/core/orchestration-add.ts
|
|
67742
68365
|
function resolveOrgIdForGroup(groupId, orgsWithTeams) {
|
|
@@ -67801,7 +68424,7 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67801
68424
|
const link2 = readOrchLink(cwd2);
|
|
67802
68425
|
if (!link2 || !hasOrchManifest(cwd2)) {
|
|
67803
68426
|
f2.warn("This folder is not a linked orchestration.");
|
|
67804
|
-
f2.info(`Run ${
|
|
68427
|
+
f2.info(`Run ${import_picocolors44.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
67805
68428
|
return;
|
|
67806
68429
|
}
|
|
67807
68430
|
let manifest;
|
|
@@ -67821,13 +68444,13 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67821
68444
|
})).trim();
|
|
67822
68445
|
}
|
|
67823
68446
|
let slug = slugifyMemberName(name);
|
|
67824
|
-
if (manifest.members.some((m3) => m3.slug === slug) ||
|
|
68447
|
+
if (manifest.members.some((m3) => m3.slug === slug) || fs79.existsSync(memberDir(cwd2, slug))) {
|
|
67825
68448
|
let n = 2;
|
|
67826
68449
|
let candidate = `${slug}-${n}`;
|
|
67827
|
-
while (manifest.members.some((m3) => m3.slug === candidate) ||
|
|
68450
|
+
while (manifest.members.some((m3) => m3.slug === candidate) || fs79.existsSync(memberDir(cwd2, candidate))) {
|
|
67828
68451
|
candidate = `${slug}-${++n}`;
|
|
67829
68452
|
}
|
|
67830
|
-
f2.info(`Slug ${
|
|
68453
|
+
f2.info(`Slug ${import_picocolors44.default.bold(slug)} is taken — using ${import_picocolors44.default.bold(candidate)}.`);
|
|
67831
68454
|
slug = candidate;
|
|
67832
68455
|
}
|
|
67833
68456
|
let payloadSchema;
|
|
@@ -67851,7 +68474,7 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67851
68474
|
const resolved = resolveOrgIdForGroup(link2.group_id, orgsWithTeams);
|
|
67852
68475
|
if (!resolved) {
|
|
67853
68476
|
sp.stop("Failed.");
|
|
67854
|
-
f2.error(`Could not find an org that owns group ${
|
|
68477
|
+
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.`);
|
|
67855
68478
|
return;
|
|
67856
68479
|
}
|
|
67857
68480
|
orgId = resolved;
|
|
@@ -67868,14 +68491,14 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67868
68491
|
if (from.length === 0 && to2.length === 0 && isInteractive() && manifest.members.length > 0) {
|
|
67869
68492
|
const memberOptions = manifest.members.map((m3) => ({ value: m3.slug, label: m3.slug }));
|
|
67870
68493
|
const pickedFrom = await ae({
|
|
67871
|
-
message: `Connect ${
|
|
68494
|
+
message: `Connect ${import_picocolors44.default.bold(slug)} FROM which member(s)? — edges INTO ${slug} (space to select, enter to skip)`,
|
|
67872
68495
|
options: memberOptions,
|
|
67873
68496
|
required: false
|
|
67874
68497
|
});
|
|
67875
68498
|
if (Array.isArray(pickedFrom))
|
|
67876
68499
|
from = pickedFrom;
|
|
67877
68500
|
const pickedTo = await ae({
|
|
67878
|
-
message: `Connect ${
|
|
68501
|
+
message: `Connect ${import_picocolors44.default.bold(slug)} TO which member(s)? — edges OUT of ${slug} (space to select, enter to skip)`,
|
|
67879
68502
|
options: memberOptions,
|
|
67880
68503
|
required: false
|
|
67881
68504
|
});
|
|
@@ -67896,7 +68519,7 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67896
68519
|
}
|
|
67897
68520
|
const dest = memberDir(cwd2, slug);
|
|
67898
68521
|
try {
|
|
67899
|
-
|
|
68522
|
+
fs79.mkdirSync(dest, { recursive: true });
|
|
67900
68523
|
await runAgentCreate(dest, {
|
|
67901
68524
|
name,
|
|
67902
68525
|
orgId,
|
|
@@ -67907,30 +68530,30 @@ async function runOrchestrationAddAgent(cwd2, args) {
|
|
|
67907
68530
|
});
|
|
67908
68531
|
} catch (err) {
|
|
67909
68532
|
try {
|
|
67910
|
-
|
|
68533
|
+
fs79.rmSync(dest, { recursive: true, force: true });
|
|
67911
68534
|
} catch {}
|
|
67912
68535
|
f2.error(`Failed to create ${slug}: ${err.message}`);
|
|
67913
68536
|
return;
|
|
67914
68537
|
}
|
|
67915
68538
|
writeOrchManifest(cwd2, updated);
|
|
67916
68539
|
if (args.noPush) {
|
|
67917
|
-
f2.info(`Manifest updated. Run ${
|
|
68540
|
+
f2.info(`Manifest updated. Run ${import_picocolors44.default.cyan("brainbase orchestration push")} to apply.`);
|
|
67918
68541
|
return;
|
|
67919
68542
|
}
|
|
67920
68543
|
await runOrchestrationPush(cwd2, { yes: true, graphOnly: true });
|
|
67921
68544
|
}
|
|
67922
68545
|
|
|
67923
68546
|
// src/cli/orchestration-create.ts
|
|
67924
|
-
var
|
|
68547
|
+
var import_picocolors45 = __toESM(require_picocolors(), 1);
|
|
67925
68548
|
async function runOrchestrationCreate(cwd2, args) {
|
|
67926
68549
|
banner("orchestration create — claim a brainbase-orchestration.yaml");
|
|
67927
68550
|
if (readOrchLink(cwd2)) {
|
|
67928
68551
|
f2.warn("This folder is already linked to an orchestration.");
|
|
67929
|
-
f2.info(`Run ${
|
|
68552
|
+
f2.info(`Run ${import_picocolors45.default.cyan("brainbase orchestration push")} to update it.`);
|
|
67930
68553
|
return;
|
|
67931
68554
|
}
|
|
67932
68555
|
if (!hasOrchManifest(cwd2)) {
|
|
67933
|
-
f2.warn(`No ${
|
|
68556
|
+
f2.warn(`No ${import_picocolors45.default.bold(ORCH_MANIFEST_FILE)} here.`);
|
|
67934
68557
|
f2.info(`Create one, or pull an existing orchestration first.`);
|
|
67935
68558
|
return;
|
|
67936
68559
|
}
|
|
@@ -67963,10 +68586,10 @@ async function runOrchestrationCreate(cwd2, args) {
|
|
|
67963
68586
|
});
|
|
67964
68587
|
const plan = [
|
|
67965
68588
|
"",
|
|
67966
|
-
` ${
|
|
67967
|
-
` ${
|
|
67968
|
-
` ${
|
|
67969
|
-
` ${
|
|
68589
|
+
` ${import_picocolors45.default.bold(manifest.orchestration.name)}`,
|
|
68590
|
+
` ${import_picocolors45.default.dim("org")} ${import_picocolors45.default.bold(target.org.name)}`,
|
|
68591
|
+
` ${import_picocolors45.default.dim("team")} ${import_picocolors45.default.bold(target.team.name)}`,
|
|
68592
|
+
` ${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"}`,
|
|
67970
68593
|
""
|
|
67971
68594
|
];
|
|
67972
68595
|
console.log(plan.join(`
|
|
@@ -67996,7 +68619,7 @@ async function runOrchestrationCreate(cwd2, args) {
|
|
|
67996
68619
|
edges: graph.edges,
|
|
67997
68620
|
triggers: graph.triggers
|
|
67998
68621
|
});
|
|
67999
|
-
sp.stop(`Created ${
|
|
68622
|
+
sp.stop(`Created ${import_picocolors45.default.bold(created.name)}.`);
|
|
68000
68623
|
writeOrchLink(cwd2, {
|
|
68001
68624
|
schemaVersion: 1,
|
|
68002
68625
|
orchestration_id: created.id,
|
|
@@ -68109,21 +68732,21 @@ async function runOrchestration(cwd2, sub, args, opts) {
|
|
|
68109
68732
|
function printHelp3() {
|
|
68110
68733
|
const out = [];
|
|
68111
68734
|
out.push("");
|
|
68112
|
-
out.push(` ${
|
|
68735
|
+
out.push(` ${import_picocolors46.default.bold("brainbase orchestration")} ${import_picocolors46.default.dim("<sub> [options]")}`);
|
|
68113
68736
|
out.push("");
|
|
68114
|
-
out.push(` ${
|
|
68115
|
-
out.push(` ${
|
|
68116
|
-
out.push(` ${
|
|
68117
|
-
out.push(` ${
|
|
68118
|
-
out.push(` ${
|
|
68119
|
-
out.push(` ${
|
|
68737
|
+
out.push(` ${import_picocolors46.default.cyan("create")} ${import_picocolors46.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
|
|
68738
|
+
out.push(` ${import_picocolors46.default.cyan("pull")} ${import_picocolors46.default.dim("<id>")} ${import_picocolors46.default.dim("fetch orchestration + every member agent into this folder")}`);
|
|
68739
|
+
out.push(` ${import_picocolors46.default.cyan("push")} ${import_picocolors46.default.dim("push each member, then update the orchestration graph")}`);
|
|
68740
|
+
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")}`);
|
|
68741
|
+
out.push(` ${import_picocolors46.default.cyan("status")} ${import_picocolors46.default.dim("show what would push and what would pull")}`);
|
|
68742
|
+
out.push(` ${import_picocolors46.default.cyan("list")} ${import_picocolors46.default.dim("list orchestrations under a team")}`);
|
|
68120
68743
|
out.push("");
|
|
68121
|
-
out.push(` ${
|
|
68122
|
-
out.push(` ${
|
|
68123
|
-
out.push(` ${
|
|
68124
|
-
out.push(` ${
|
|
68125
|
-
out.push(` ${
|
|
68126
|
-
out.push(` ${
|
|
68744
|
+
out.push(` ${import_picocolors46.default.bold("Flags")}`);
|
|
68745
|
+
out.push(` ${import_picocolors46.default.dim("--yes, -y")} skip confirmations`);
|
|
68746
|
+
out.push(` ${import_picocolors46.default.dim("--harness <id>")} harness for newly-created member folders (default claude-code)`);
|
|
68747
|
+
out.push(` ${import_picocolors46.default.dim("--graph-only")} for push: only update members + edges, skip per-member push`);
|
|
68748
|
+
out.push(` ${import_picocolors46.default.dim("--org <id>")} for create/list: org id or slug (CLI vocab — DB teams.id)`);
|
|
68749
|
+
out.push(` ${import_picocolors46.default.dim("--team <id>")} for create/list: team id (CLI vocab — DB groups.id)`);
|
|
68127
68750
|
out.push("");
|
|
68128
68751
|
console.log(out.join(`
|
|
68129
68752
|
`));
|
|
@@ -68168,11 +68791,11 @@ async function runRun(cwd2, args) {
|
|
|
68168
68791
|
}
|
|
68169
68792
|
|
|
68170
68793
|
// src/cli/publish.ts
|
|
68171
|
-
var
|
|
68794
|
+
var import_picocolors47 = __toESM(require_picocolors(), 1);
|
|
68172
68795
|
function runPublish() {
|
|
68173
68796
|
banner("publish — moved");
|
|
68174
|
-
f2.error(`${
|
|
68175
|
-
f2.info(`Use ${
|
|
68797
|
+
f2.error(`${import_picocolors47.default.bold("brainbase publish")} does not exist.`);
|
|
68798
|
+
f2.info(`Use ${import_picocolors47.default.cyan("brainbase agent push")} to send your local changes to the cloud.`);
|
|
68176
68799
|
process.exit(1);
|
|
68177
68800
|
}
|
|
68178
68801
|
|
|
@@ -68471,7 +69094,7 @@ async function runStatus(cwd2) {
|
|
|
68471
69094
|
}
|
|
68472
69095
|
|
|
68473
69096
|
// src/cli/token.ts
|
|
68474
|
-
var
|
|
69097
|
+
var import_picocolors48 = __toESM(require_picocolors(), 1);
|
|
68475
69098
|
|
|
68476
69099
|
// src/ui/ink/TokenCards.tsx
|
|
68477
69100
|
var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
|
|
@@ -68481,14 +69104,6 @@ function TokenCreatedCard(props) {
|
|
|
68481
69104
|
tone: "warn",
|
|
68482
69105
|
subtitle: "shown ONCE — copy it now",
|
|
68483
69106
|
children: [
|
|
68484
|
-
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
68485
|
-
marginBottom: 1,
|
|
68486
|
-
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
68487
|
-
bold: true,
|
|
68488
|
-
color: "yellow",
|
|
68489
|
-
children: props.token
|
|
68490
|
-
}, undefined, false, undefined, this)
|
|
68491
|
-
}, undefined, false, undefined, this),
|
|
68492
69107
|
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
68493
69108
|
flexDirection: "column",
|
|
68494
69109
|
marginBottom: 1,
|
|
@@ -68549,20 +69164,22 @@ function TokenCreatedCard(props) {
|
|
|
68549
69164
|
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
68550
69165
|
dimColor: true,
|
|
68551
69166
|
children: [
|
|
68552
|
-
"saved
|
|
69167
|
+
"saved to ",
|
|
68553
69168
|
props.storedAt,
|
|
68554
|
-
" (mode 0600)"
|
|
69169
|
+
" (mode 0600) — covers ",
|
|
69170
|
+
REGISTRY_COMMANDS
|
|
68555
69171
|
]
|
|
68556
69172
|
}, undefined, true, undefined, this),
|
|
68557
69173
|
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
68558
69174
|
dimColor: true,
|
|
68559
69175
|
children: [
|
|
68560
|
-
|
|
69176
|
+
CONTROL_PLANE_COMMANDS,
|
|
69177
|
+
" do ",
|
|
68561
69178
|
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
68562
69179
|
bold: true,
|
|
68563
|
-
children: "
|
|
69180
|
+
children: "not"
|
|
68564
69181
|
}, undefined, false, undefined, this),
|
|
68565
|
-
"
|
|
69182
|
+
" read that file — export it instead:"
|
|
68566
69183
|
]
|
|
68567
69184
|
}, undefined, true, undefined, this)
|
|
68568
69185
|
]
|
|
@@ -68571,9 +69188,12 @@ function TokenCreatedCard(props) {
|
|
|
68571
69188
|
}, undefined, true, undefined, this);
|
|
68572
69189
|
}
|
|
68573
69190
|
async function showTokenCreatedCard(props) {
|
|
69191
|
+
const { token, ...card } = props;
|
|
68574
69192
|
await renderStatic(/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(TokenCreatedCard, {
|
|
68575
|
-
...
|
|
69193
|
+
...card
|
|
68576
69194
|
}, undefined, false, undefined, this));
|
|
69195
|
+
console.log(` export BRAINBASE_TOKEN=${token}`);
|
|
69196
|
+
console.log("");
|
|
68577
69197
|
}
|
|
68578
69198
|
function TokenListCard(props) {
|
|
68579
69199
|
if (props.active.length === 0) {
|
|
@@ -68739,11 +69359,32 @@ function isAllowedScope(value) {
|
|
|
68739
69359
|
function isExpired2(token) {
|
|
68740
69360
|
return Boolean(token.expires_at && Date.parse(token.expires_at) <= Date.now());
|
|
68741
69361
|
}
|
|
69362
|
+
function isJwtRequired(body) {
|
|
69363
|
+
if (!body || typeof body !== "object")
|
|
69364
|
+
return false;
|
|
69365
|
+
const detail = body.detail;
|
|
69366
|
+
if (!detail || typeof detail !== "object")
|
|
69367
|
+
return false;
|
|
69368
|
+
return detail.code === "jwt_required";
|
|
69369
|
+
}
|
|
69370
|
+
function sessionWouldBeUsed() {
|
|
69371
|
+
const { ok, session } = authStatus();
|
|
69372
|
+
if (ok)
|
|
69373
|
+
return true;
|
|
69374
|
+
return Boolean(session?.refresh_token && session.supabase_url && session.supabase_anon_key);
|
|
69375
|
+
}
|
|
68742
69376
|
function withLoginHint(error) {
|
|
68743
|
-
if (error instanceof ApiError
|
|
68744
|
-
return
|
|
68745
|
-
|
|
68746
|
-
|
|
69377
|
+
if (!(error instanceof ApiError) || error.status !== 403)
|
|
69378
|
+
return error;
|
|
69379
|
+
if (!isJwtRequired(error.body))
|
|
69380
|
+
return error;
|
|
69381
|
+
if (!process.env.BRAINBASE_TOKEN?.trim()) {
|
|
69382
|
+
if (sessionWouldBeUsed() || !readToken())
|
|
69383
|
+
return error;
|
|
69384
|
+
return new Error("Managing tokens needs a logged-in session; the stored PAT cannot. " + "Run `brainbase login` and try again.");
|
|
69385
|
+
}
|
|
69386
|
+
const lead = "Managing tokens needs a logged-in session, and BRAINBASE_TOKEN is set — " + "that PAT is being used instead.";
|
|
69387
|
+
return new Error(sessionWouldBeUsed() ? `${lead} Run \`unset BRAINBASE_TOKEN\` and try again.` : `${lead} Run \`unset BRAINBASE_TOKEN\`, then \`brainbase login\`.`);
|
|
68747
69388
|
}
|
|
68748
69389
|
async function runTokenCreate(args) {
|
|
68749
69390
|
banner("token create — make a long-lived CLI key");
|
|
@@ -68766,10 +69407,16 @@ async function runTokenCreate(args) {
|
|
|
68766
69407
|
}
|
|
68767
69408
|
const spinner = de();
|
|
68768
69409
|
spinner.start("Creating token…");
|
|
68769
|
-
|
|
68770
|
-
|
|
68771
|
-
|
|
68772
|
-
|
|
69410
|
+
let created;
|
|
69411
|
+
try {
|
|
69412
|
+
created = await registryApi.createCliToken({
|
|
69413
|
+
name,
|
|
69414
|
+
scopes
|
|
69415
|
+
});
|
|
69416
|
+
} catch (error) {
|
|
69417
|
+
spinner.stop("Could not create token.");
|
|
69418
|
+
throw withLoginHint(error);
|
|
69419
|
+
}
|
|
68773
69420
|
spinner.stop("Token created.");
|
|
68774
69421
|
try {
|
|
68775
69422
|
writeToken(created.token, name);
|
|
@@ -68790,7 +69437,12 @@ async function runTokenCreate(args) {
|
|
|
68790
69437
|
}
|
|
68791
69438
|
async function runTokenList() {
|
|
68792
69439
|
banner("tokens");
|
|
68793
|
-
|
|
69440
|
+
let tokens;
|
|
69441
|
+
try {
|
|
69442
|
+
tokens = await registryApi.listCliTokens();
|
|
69443
|
+
} catch (error) {
|
|
69444
|
+
throw withLoginHint(error);
|
|
69445
|
+
}
|
|
68794
69446
|
const active = tokens.filter((t) => !t.revoked_at);
|
|
68795
69447
|
const revoked = tokens.filter((t) => t.revoked_at);
|
|
68796
69448
|
const local = readToken();
|
|
@@ -68864,7 +69516,7 @@ async function runTokenRename(args) {
|
|
|
68864
69516
|
}
|
|
68865
69517
|
}
|
|
68866
69518
|
if (name === target.name.trim()) {
|
|
68867
|
-
console.log(`${sym.ok} ${
|
|
69519
|
+
console.log(`${sym.ok} ${import_picocolors48.default.bold(target.name.trim())} already has that label; nothing to do.`);
|
|
68868
69520
|
return;
|
|
68869
69521
|
}
|
|
68870
69522
|
try {
|
|
@@ -68872,7 +69524,7 @@ async function runTokenRename(args) {
|
|
|
68872
69524
|
} catch (error) {
|
|
68873
69525
|
throw withLoginHint(error);
|
|
68874
69526
|
}
|
|
68875
|
-
console.log(`${sym.ok} Renamed ${
|
|
69527
|
+
console.log(`${sym.ok} Renamed ${import_picocolors48.default.dim(target.name)} → ${import_picocolors48.default.bold(name)}`);
|
|
68876
69528
|
}
|
|
68877
69529
|
async function runTokenRevoke(args) {
|
|
68878
69530
|
if (!args.id) {
|
|
@@ -68890,14 +69542,14 @@ async function runTokenRevoke(args) {
|
|
|
68890
69542
|
throw new Error(`No token with id ${args.id}. Run \`brainbase token list\` to see yours.`);
|
|
68891
69543
|
}
|
|
68892
69544
|
if (target.revoked_at) {
|
|
68893
|
-
reconcileDeadToken(target, `${
|
|
69545
|
+
reconcileDeadToken(target, `${import_picocolors48.default.bold(target.name)} is already revoked.`);
|
|
68894
69546
|
return;
|
|
68895
69547
|
}
|
|
68896
69548
|
const stored = readToken();
|
|
68897
69549
|
const isLocalToken = Boolean(stored && stored.token.startsWith(target.prefix));
|
|
68898
69550
|
if (!autoProceed(args.yes)) {
|
|
68899
69551
|
const ok = await se({
|
|
68900
|
-
message: isLocalToken ? `Revoke ${
|
|
69552
|
+
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.`,
|
|
68901
69553
|
initialValue: false
|
|
68902
69554
|
});
|
|
68903
69555
|
if (!ensureNotCancelled(ok))
|
|
@@ -68908,14 +69560,14 @@ async function runTokenRevoke(args) {
|
|
|
68908
69560
|
} catch (error) {
|
|
68909
69561
|
if (error instanceof ApiError && error.status === 404) {
|
|
68910
69562
|
if (isExpired2(target)) {
|
|
68911
|
-
reconcileDeadToken(target, `${
|
|
69563
|
+
reconcileDeadToken(target, `${import_picocolors48.default.bold(target.name)} had already expired.`);
|
|
68912
69564
|
return;
|
|
68913
69565
|
}
|
|
68914
69566
|
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.");
|
|
68915
69567
|
}
|
|
68916
|
-
throw error;
|
|
69568
|
+
throw withLoginHint(error);
|
|
68917
69569
|
}
|
|
68918
|
-
reconcileDeadToken(target, `Revoked ${
|
|
69570
|
+
reconcileDeadToken(target, `Revoked ${import_picocolors48.default.bold(target.name)}.`);
|
|
68919
69571
|
}
|
|
68920
69572
|
function reconcileDeadToken(target, headline) {
|
|
68921
69573
|
let outcome;
|
|
@@ -68949,7 +69601,7 @@ function reportLocalToken(headline, outcome) {
|
|
|
68949
69601
|
}
|
|
68950
69602
|
async function runTokenClear() {
|
|
68951
69603
|
if (!readToken()) {
|
|
68952
|
-
console.log(
|
|
69604
|
+
console.log(import_picocolors48.default.dim("No local token stored."));
|
|
68953
69605
|
return;
|
|
68954
69606
|
}
|
|
68955
69607
|
clearToken();
|
|
@@ -69049,32 +69701,32 @@ async function runToken(sub, rest2, args) {
|
|
|
69049
69701
|
function printTokenHelp() {
|
|
69050
69702
|
const out = [];
|
|
69051
69703
|
out.push("");
|
|
69052
|
-
out.push(` ${
|
|
69704
|
+
out.push(` ${import_picocolors48.default.bold("brainbase token")} ${import_picocolors48.default.dim("<command>")}`);
|
|
69053
69705
|
out.push("");
|
|
69054
|
-
out.push(` ${
|
|
69055
|
-
out.push(` ${
|
|
69056
|
-
out.push(` ${
|
|
69057
|
-
out.push(` ${
|
|
69058
|
-
out.push(` ${
|
|
69706
|
+
out.push(` ${import_picocolors48.default.cyan("create")} ${import_picocolors48.default.dim("issue a new long-lived CLI key (PAT)")}`);
|
|
69707
|
+
out.push(` ${import_picocolors48.default.cyan("list")} ${import_picocolors48.default.dim("show your tokens")}`);
|
|
69708
|
+
out.push(` ${import_picocolors48.default.cyan("rename")} ${import_picocolors48.default.dim("<id>")} ${import_picocolors48.default.dim("relabel a token by id")}`);
|
|
69709
|
+
out.push(` ${import_picocolors48.default.cyan("revoke")} ${import_picocolors48.default.dim("<id>")} ${import_picocolors48.default.dim("revoke a token by id")}`);
|
|
69710
|
+
out.push(` ${import_picocolors48.default.cyan("clear")} ${import_picocolors48.default.dim("forget the local token (does not revoke)")}`);
|
|
69059
69711
|
out.push("");
|
|
69060
|
-
out.push(` ${
|
|
69061
|
-
out.push(` ${
|
|
69062
|
-
out.push(` ${
|
|
69063
|
-
out.push(` ${
|
|
69712
|
+
out.push(` ${import_picocolors48.default.bold("create flags")}`);
|
|
69713
|
+
out.push(` ${import_picocolors48.default.cyan("--name, -n")} ${import_picocolors48.default.dim("<label>")} ${import_picocolors48.default.dim("token label (prompted if omitted)")}`);
|
|
69714
|
+
out.push(` ${import_picocolors48.default.cyan("--scopes")} ${import_picocolors48.default.dim("<list>")} ${import_picocolors48.default.dim("comma-separated; allowed: read, publish, admin")}`);
|
|
69715
|
+
out.push(` ${import_picocolors48.default.dim("default: read,publish")}`);
|
|
69064
69716
|
out.push("");
|
|
69065
|
-
out.push(` ${
|
|
69066
|
-
out.push(` ${
|
|
69717
|
+
out.push(` ${import_picocolors48.default.bold("rename flags")}`);
|
|
69718
|
+
out.push(` ${import_picocolors48.default.cyan("--name, -n")} ${import_picocolors48.default.dim("<label>")} ${import_picocolors48.default.dim("new label (prompted if omitted)")}`);
|
|
69067
69719
|
out.push("");
|
|
69068
69720
|
console.log(out.join(`
|
|
69069
69721
|
`));
|
|
69070
69722
|
}
|
|
69071
69723
|
|
|
69072
69724
|
// src/cli/mcp.ts
|
|
69073
|
-
var
|
|
69725
|
+
var import_picocolors49 = __toESM(require_picocolors(), 1);
|
|
69074
69726
|
|
|
69075
69727
|
// src/core/mcp-check/collect-servers.ts
|
|
69076
69728
|
import path87 from "node:path";
|
|
69077
|
-
import
|
|
69729
|
+
import fs80 from "node:fs";
|
|
69078
69730
|
function collectServers(cwd2, env3 = process.env) {
|
|
69079
69731
|
const out = [];
|
|
69080
69732
|
const seen = new Set;
|
|
@@ -69128,7 +69780,7 @@ function* readResolvedMcps(cwd2) {
|
|
|
69128
69780
|
const p2 = path87.join(cwd2, ".brainbase", "resolved-mcps.json");
|
|
69129
69781
|
let raw;
|
|
69130
69782
|
try {
|
|
69131
|
-
raw =
|
|
69783
|
+
raw = fs80.readFileSync(p2, "utf-8");
|
|
69132
69784
|
} catch {
|
|
69133
69785
|
return;
|
|
69134
69786
|
}
|
|
@@ -69188,10 +69840,19 @@ function classifyError(err) {
|
|
|
69188
69840
|
}
|
|
69189
69841
|
return "protocol_error";
|
|
69190
69842
|
}
|
|
69843
|
+
var CREDENTIAL_NAMES = "(x-api-key|api[-_]?key|auth[-_]?token|access[-_]?token|private[-_]?token|secret)";
|
|
69191
69844
|
var REDACTIONS = [
|
|
69192
69845
|
[/https?:\/\/[^\s'"`]+/gi, "[url]"],
|
|
69193
69846
|
[/Bearer\s+\S+/gi, "Bearer [redacted]"],
|
|
69194
|
-
[/\bbb(?:pat|_live)_[A-Za-z0-9._-]+/g, "[redacted]"]
|
|
69847
|
+
[/\bbb(?:pat|_live)_[A-Za-z0-9._-]+/g, "[redacted]"],
|
|
69848
|
+
[
|
|
69849
|
+
new RegExp(`\\b${CREDENTIAL_NAMES}\\b([\\s:=]*)(["'])[^"']+\\3`, "gi"),
|
|
69850
|
+
"$1$2$3[redacted]$3"
|
|
69851
|
+
],
|
|
69852
|
+
[
|
|
69853
|
+
new RegExp(`\\b${CREDENTIAL_NAMES}\\b(\\s*[:=]\\s*)["']?[^\\s,;"'}]+`, "gi"),
|
|
69854
|
+
"$1$2[redacted]"
|
|
69855
|
+
]
|
|
69195
69856
|
];
|
|
69196
69857
|
function redactSecrets2(msg) {
|
|
69197
69858
|
let out = msg;
|
|
@@ -77318,11 +77979,11 @@ function withTimeout(inner, ms2, label) {
|
|
|
77318
77979
|
function isTransient(status) {
|
|
77319
77980
|
return status === "unreachable";
|
|
77320
77981
|
}
|
|
77321
|
-
async function probeWithConnector(server,
|
|
77982
|
+
async function probeWithConnector(server, connect2, opts) {
|
|
77322
77983
|
let lastErr;
|
|
77323
77984
|
for (let attempt2 = 0;attempt2 < 2; attempt2++) {
|
|
77324
77985
|
try {
|
|
77325
|
-
const { toolCount } = await
|
|
77986
|
+
const { toolCount } = await connect2(server, opts.timeoutMs);
|
|
77326
77987
|
return { name: server.name, status: "ok", tool_count: toolCount, error: null };
|
|
77327
77988
|
} catch (err) {
|
|
77328
77989
|
lastErr = err;
|
|
@@ -77398,42 +78059,177 @@ async function runMcpCheck(cwd2, options) {
|
|
|
77398
78059
|
}
|
|
77399
78060
|
}));
|
|
77400
78061
|
results.sort((a3, b4) => a3.name.localeCompare(b4.name));
|
|
77401
|
-
const
|
|
78062
|
+
const report2 = {
|
|
77402
78063
|
check_status: deriveCheckStatus(results),
|
|
77403
78064
|
servers: results
|
|
77404
78065
|
};
|
|
77405
78066
|
if (options.json) {
|
|
77406
|
-
write(JSON.stringify(
|
|
78067
|
+
write(JSON.stringify(report2) + `
|
|
77407
78068
|
`);
|
|
77408
78069
|
} else {
|
|
77409
|
-
write(renderHuman(
|
|
78070
|
+
write(renderHuman(report2));
|
|
77410
78071
|
}
|
|
77411
|
-
return { exitCode: 0, report };
|
|
78072
|
+
return { exitCode: 0, report: report2 };
|
|
77412
78073
|
} catch (err) {
|
|
77413
78074
|
writeErr(`brainbase mcp check failed to run: ${truncateError(err) ?? "unknown error"}
|
|
77414
78075
|
`);
|
|
77415
78076
|
return { exitCode: 1 };
|
|
77416
78077
|
}
|
|
77417
78078
|
}
|
|
77418
|
-
function renderHuman(
|
|
78079
|
+
function renderHuman(report2) {
|
|
77419
78080
|
const lines = [];
|
|
77420
|
-
if (
|
|
77421
|
-
lines.push(
|
|
78081
|
+
if (report2.check_status === "skipped") {
|
|
78082
|
+
lines.push(import_picocolors49.default.dim("No MCP servers configured — nothing to check."));
|
|
77422
78083
|
return lines.join(`
|
|
77423
78084
|
`) + `
|
|
77424
78085
|
`;
|
|
77425
78086
|
}
|
|
77426
|
-
for (const s3 of
|
|
77427
|
-
const mark = s3.status === "ok" ?
|
|
77428
|
-
const detail = s3.status === "ok" ?
|
|
78087
|
+
for (const s3 of report2.servers) {
|
|
78088
|
+
const mark = s3.status === "ok" ? import_picocolors49.default.green("✓") : s3.status === "auth_failed" ? import_picocolors49.default.red("✗") : import_picocolors49.default.yellow("⚠");
|
|
78089
|
+
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}` : ""));
|
|
77429
78090
|
lines.push(` ${mark} ${s3.name} ${detail}`);
|
|
77430
78091
|
}
|
|
77431
|
-
const summary =
|
|
78092
|
+
const summary = report2.check_status === "ok" ? import_picocolors49.default.green("All MCP servers connected.") : import_picocolors49.default.yellow("Some MCP servers are unhealthy.");
|
|
77432
78093
|
lines.push("", summary);
|
|
77433
78094
|
return lines.join(`
|
|
77434
78095
|
`) + `
|
|
77435
78096
|
`;
|
|
77436
78097
|
}
|
|
78098
|
+
async function runMcpList(cwd2, options) {
|
|
78099
|
+
const write = options.write ?? ((s3) => process.stdout.write(s3));
|
|
78100
|
+
const writeErr = options.writeErr ?? ((s3) => process.stderr.write(s3));
|
|
78101
|
+
const fetchServers = options.fetchServers ?? ((id) => api.listAgentMcpServers(id));
|
|
78102
|
+
const resolveAgentId = options.resolveAgentId ?? ((dir) => readLink(dir)?.agent_id ?? null);
|
|
78103
|
+
const agentId = resolveAgentId(cwd2);
|
|
78104
|
+
if (!agentId) {
|
|
78105
|
+
if (options.json) {
|
|
78106
|
+
write(JSON.stringify({ linked: false, servers: [] }) + `
|
|
78107
|
+
`);
|
|
78108
|
+
} else {
|
|
78109
|
+
writeErr("This folder is not linked to any agent. Run `brainbase link` first.\n");
|
|
78110
|
+
}
|
|
78111
|
+
return 1;
|
|
78112
|
+
}
|
|
78113
|
+
let report2;
|
|
78114
|
+
try {
|
|
78115
|
+
report2 = await fetchServers(agentId);
|
|
78116
|
+
} catch (err) {
|
|
78117
|
+
if (options.json) {
|
|
78118
|
+
write(JSON.stringify({ error: err.message }) + `
|
|
78119
|
+
`);
|
|
78120
|
+
} else {
|
|
78121
|
+
writeErr(`brainbase mcp list failed: ${err.message}
|
|
78122
|
+
`);
|
|
78123
|
+
}
|
|
78124
|
+
return 1;
|
|
78125
|
+
}
|
|
78126
|
+
if (options.json) {
|
|
78127
|
+
write(JSON.stringify({ linked: true, ...sanitizeReport(report2) }) + `
|
|
78128
|
+
`);
|
|
78129
|
+
} else {
|
|
78130
|
+
write(renderServerList(report2.servers));
|
|
78131
|
+
}
|
|
78132
|
+
return 0;
|
|
78133
|
+
}
|
|
78134
|
+
function sanitizeReport(report2) {
|
|
78135
|
+
return {
|
|
78136
|
+
...report2,
|
|
78137
|
+
servers: report2.servers.map((s3) => ({
|
|
78138
|
+
...s3,
|
|
78139
|
+
url: sanitizeUrl(s3.url),
|
|
78140
|
+
command: sanitizeCommand(s3.command),
|
|
78141
|
+
last_error: s3.last_error ? truncateError(s3.last_error) : s3.last_error
|
|
78142
|
+
}))
|
|
78143
|
+
};
|
|
78144
|
+
}
|
|
78145
|
+
function sanitizeUrl(url2) {
|
|
78146
|
+
if (!url2)
|
|
78147
|
+
return url2;
|
|
78148
|
+
try {
|
|
78149
|
+
const parsed = new URL(url2);
|
|
78150
|
+
parsed.search = "";
|
|
78151
|
+
parsed.hash = "";
|
|
78152
|
+
parsed.username = "";
|
|
78153
|
+
parsed.password = "";
|
|
78154
|
+
return parsed.toString();
|
|
78155
|
+
} catch {
|
|
78156
|
+
return null;
|
|
78157
|
+
}
|
|
78158
|
+
}
|
|
78159
|
+
function sanitizeCommand(command) {
|
|
78160
|
+
if (!command)
|
|
78161
|
+
return command;
|
|
78162
|
+
return command.trim().split(/\s+/)[0] ?? null;
|
|
78163
|
+
}
|
|
78164
|
+
var AUTH_LABEL = {
|
|
78165
|
+
none: "",
|
|
78166
|
+
oauth_required: "needs authorization",
|
|
78167
|
+
oauth_connected: "authorized",
|
|
78168
|
+
oauth_expired: "authorization expired — reconnect"
|
|
78169
|
+
};
|
|
78170
|
+
var HEALTH_LABEL = {
|
|
78171
|
+
unreachable: "unreachable",
|
|
78172
|
+
protocol_error: "connection error",
|
|
78173
|
+
auth_failed: "last check failed to authenticate",
|
|
78174
|
+
expired: "last check saw an expired token",
|
|
78175
|
+
unknown: "last check inconclusive"
|
|
78176
|
+
};
|
|
78177
|
+
function healthLabel(server) {
|
|
78178
|
+
const status = server.last_status;
|
|
78179
|
+
if (!status || status === "ok")
|
|
78180
|
+
return;
|
|
78181
|
+
return HEALTH_LABEL[status] ?? `last check: ${status}`;
|
|
78182
|
+
}
|
|
78183
|
+
function isUnhealthy(server) {
|
|
78184
|
+
return Boolean(server.last_status) && server.last_status !== "ok";
|
|
78185
|
+
}
|
|
78186
|
+
function renderServerList(servers) {
|
|
78187
|
+
if (servers.length === 0) {
|
|
78188
|
+
return import_picocolors49.default.dim("No MCP servers configured for this agent.") + `
|
|
78189
|
+
`;
|
|
78190
|
+
}
|
|
78191
|
+
const lines = [""];
|
|
78192
|
+
for (const s3 of servers) {
|
|
78193
|
+
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("✓");
|
|
78194
|
+
const bits = [s3.transport];
|
|
78195
|
+
if (!s3.is_enabled)
|
|
78196
|
+
bits.push("disabled");
|
|
78197
|
+
const label = AUTH_LABEL[s3.auth];
|
|
78198
|
+
if (label)
|
|
78199
|
+
bits.push(label);
|
|
78200
|
+
const health = healthLabel(s3);
|
|
78201
|
+
if (health)
|
|
78202
|
+
bits.push(health);
|
|
78203
|
+
const expiry = describeExpiry(s3);
|
|
78204
|
+
if (expiry)
|
|
78205
|
+
bits.push(expiry);
|
|
78206
|
+
lines.push(` ${mark} ${import_picocolors49.default.bold(s3.name)} ${import_picocolors49.default.dim(bits.join(" · "))}`);
|
|
78207
|
+
}
|
|
78208
|
+
if (servers.some((s3) => s3.auth === "oauth_required" || s3.auth === "oauth_expired")) {
|
|
78209
|
+
lines.push("", import_picocolors49.default.dim("Authorize OAuth-backed servers in the web app; the CLI cannot run that flow yet."));
|
|
78210
|
+
}
|
|
78211
|
+
lines.push("");
|
|
78212
|
+
return lines.join(`
|
|
78213
|
+
`);
|
|
78214
|
+
}
|
|
78215
|
+
var MAX_EXPIRY_DAYS = 90;
|
|
78216
|
+
function describeExpiry(server, now2 = Date.now()) {
|
|
78217
|
+
if (server.auth !== "oauth_connected" || !server.oauth_token_expires_at)
|
|
78218
|
+
return;
|
|
78219
|
+
const at3 = Date.parse(server.oauth_token_expires_at);
|
|
78220
|
+
if (!Number.isFinite(at3))
|
|
78221
|
+
return;
|
|
78222
|
+
const minutes = Math.round((at3 - now2) / 60000);
|
|
78223
|
+
if (minutes <= 0)
|
|
78224
|
+
return;
|
|
78225
|
+
if (minutes < 60)
|
|
78226
|
+
return `expires in ${minutes}m`;
|
|
78227
|
+
const hours = Math.round(minutes / 60);
|
|
78228
|
+
if (hours < 48)
|
|
78229
|
+
return `expires in ${hours}h`;
|
|
78230
|
+
const days = Math.round(hours / 24);
|
|
78231
|
+
return days > MAX_EXPIRY_DAYS ? `expires in >${MAX_EXPIRY_DAYS}d` : `expires in ${days}d`;
|
|
78232
|
+
}
|
|
77437
78233
|
async function runMcp(cwd2, sub, _argv, options) {
|
|
77438
78234
|
const writeErr = options.writeErr ?? ((s3) => process.stderr.write(s3));
|
|
77439
78235
|
switch (sub) {
|
|
@@ -77441,17 +78237,19 @@ async function runMcp(cwd2, sub, _argv, options) {
|
|
|
77441
78237
|
const { exitCode } = await runMcpCheck(cwd2, options);
|
|
77442
78238
|
return exitCode;
|
|
77443
78239
|
}
|
|
78240
|
+
case "list":
|
|
78241
|
+
return runMcpList(cwd2, options);
|
|
77444
78242
|
default:
|
|
77445
78243
|
writeErr(`Unknown mcp subcommand: ${sub ?? "(none)"}
|
|
77446
78244
|
`);
|
|
77447
|
-
writeErr(`Usage: brainbase mcp check [--json]
|
|
78245
|
+
writeErr(`Usage: brainbase mcp <check|list> [--json]
|
|
77448
78246
|
`);
|
|
77449
78247
|
return 1;
|
|
77450
78248
|
}
|
|
77451
78249
|
}
|
|
77452
78250
|
|
|
77453
78251
|
// src/cli/task.ts
|
|
77454
|
-
var
|
|
78252
|
+
var import_picocolors50 = __toESM(require_picocolors(), 1);
|
|
77455
78253
|
|
|
77456
78254
|
// src/cli/task-create.ts
|
|
77457
78255
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -77637,31 +78435,31 @@ async function runTask(cwd2, sub, args) {
|
|
|
77637
78435
|
function printHelp4() {
|
|
77638
78436
|
const out = [];
|
|
77639
78437
|
out.push("");
|
|
77640
|
-
out.push(` ${
|
|
78438
|
+
out.push(` ${import_picocolors50.default.bold("brainbase task")} ${import_picocolors50.default.dim("<sub> [options]")}`);
|
|
77641
78439
|
out.push("");
|
|
77642
|
-
out.push(` ${
|
|
78440
|
+
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")}`);
|
|
77643
78441
|
out.push("");
|
|
77644
|
-
out.push(` ${
|
|
77645
|
-
out.push(` ${
|
|
77646
|
-
out.push(` ${
|
|
77647
|
-
out.push(` ${
|
|
77648
|
-
out.push(` ${
|
|
77649
|
-
out.push(` ${
|
|
78442
|
+
out.push(` ${import_picocolors50.default.bold("create flags")}`);
|
|
78443
|
+
out.push(` ${import_picocolors50.default.dim("--message <text>")} required first user message`);
|
|
78444
|
+
out.push(` ${import_picocolors50.default.dim("--agent <id>")} override the claimed agent in brainbase.agent.yaml`);
|
|
78445
|
+
out.push(` ${import_picocolors50.default.dim("--title <text>")} optional task title`);
|
|
78446
|
+
out.push(` ${import_picocolors50.default.dim("--model <id>")} optional model override`);
|
|
78447
|
+
out.push(` ${import_picocolors50.default.dim("--json")} print task_id, agent_id, and status as JSON`);
|
|
77650
78448
|
out.push("");
|
|
77651
|
-
out.push(` ${
|
|
78449
|
+
out.push(` ${import_picocolors50.default.dim("Flag-like values:")} use ${import_picocolors50.default.cyan("--flag=value")} or ${import_picocolors50.default.cyan("--flag -- <value>")}`);
|
|
77652
78450
|
out.push("");
|
|
77653
78451
|
console.log(out.join(`
|
|
77654
78452
|
`));
|
|
77655
78453
|
}
|
|
77656
78454
|
|
|
77657
78455
|
// src/cli/benchmark.ts
|
|
77658
|
-
var
|
|
78456
|
+
var import_picocolors51 = __toESM(require_picocolors(), 1);
|
|
77659
78457
|
import {
|
|
77660
78458
|
execFileSync as execFileSync3,
|
|
77661
78459
|
spawn as spawn5
|
|
77662
78460
|
} from "node:child_process";
|
|
77663
78461
|
import crypto7 from "node:crypto";
|
|
77664
|
-
import
|
|
78462
|
+
import fs82 from "node:fs";
|
|
77665
78463
|
import os17 from "node:os";
|
|
77666
78464
|
import path89 from "node:path";
|
|
77667
78465
|
|
|
@@ -77671,7 +78469,7 @@ import {
|
|
|
77671
78469
|
spawn as spawn4
|
|
77672
78470
|
} from "node:child_process";
|
|
77673
78471
|
import crypto6 from "node:crypto";
|
|
77674
|
-
import
|
|
78472
|
+
import fs81 from "node:fs";
|
|
77675
78473
|
import os16 from "node:os";
|
|
77676
78474
|
import path88 from "node:path";
|
|
77677
78475
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
@@ -77921,19 +78719,19 @@ function canonicalFuturePath(input) {
|
|
|
77921
78719
|
const resolved = path88.resolve(input);
|
|
77922
78720
|
const suffix = [];
|
|
77923
78721
|
let current = resolved;
|
|
77924
|
-
while (!
|
|
78722
|
+
while (!fs81.existsSync(current)) {
|
|
77925
78723
|
const parent = path88.dirname(current);
|
|
77926
78724
|
if (parent === current)
|
|
77927
78725
|
break;
|
|
77928
78726
|
suffix.unshift(path88.basename(current));
|
|
77929
78727
|
current = parent;
|
|
77930
78728
|
}
|
|
77931
|
-
const canonicalBase =
|
|
78729
|
+
const canonicalBase = fs81.realpathSync(current);
|
|
77932
78730
|
return path88.join(canonicalBase, ...suffix);
|
|
77933
78731
|
}
|
|
77934
78732
|
function validateRoots(spec) {
|
|
77935
78733
|
const workspace = path88.resolve(spec.workspace_root);
|
|
77936
|
-
if (!
|
|
78734
|
+
if (!fs81.existsSync(workspace) || fs81.lstatSync(workspace).isSymbolicLink() || !fs81.lstatSync(workspace).isDirectory()) {
|
|
77937
78735
|
throw new BenchmarkPhaseError("invalid_workspace_root", "workspace_root must be an existing real directory");
|
|
77938
78736
|
}
|
|
77939
78737
|
const canonicalWorkspace = canonicalFuturePath(workspace);
|
|
@@ -77942,7 +78740,7 @@ function validateRoots(spec) {
|
|
|
77942
78740
|
if (staging !== expectedStaging) {
|
|
77943
78741
|
throw new BenchmarkPhaseError("invalid_staging_root", `staging_root must be ${expectedStaging}`);
|
|
77944
78742
|
}
|
|
77945
|
-
if (!
|
|
78743
|
+
if (!fs81.existsSync(staging) || fs81.lstatSync(staging).isSymbolicLink() || !fs81.lstatSync(staging).isDirectory() || fs81.realpathSync(staging) !== path88.join(canonicalWorkspace, ".brainbase", "benchmark", spec.attempt_id, "incoming")) {
|
|
77946
78744
|
throw new BenchmarkPhaseError("invalid_staging_root", "staging_root must be a real directory under workspace_root");
|
|
77947
78745
|
}
|
|
77948
78746
|
const canonicalLogs = validateExternalRoot("logs_root", spec.logs_root, canonicalWorkspace);
|
|
@@ -77958,7 +78756,7 @@ function validateExternalRoot(label, input, canonicalWorkspace) {
|
|
|
77958
78756
|
if (candidate === path88.parse(candidate).root) {
|
|
77959
78757
|
throw new BenchmarkPhaseError(`invalid_${label}`, `${label} cannot be a filesystem root`);
|
|
77960
78758
|
}
|
|
77961
|
-
if (
|
|
78759
|
+
if (fs81.existsSync(candidate) && fs81.lstatSync(candidate).isSymbolicLink()) {
|
|
77962
78760
|
throw new BenchmarkPhaseError(`invalid_${label}`, `${label} cannot be a symlink`);
|
|
77963
78761
|
}
|
|
77964
78762
|
const canonicalCandidate = canonicalFuturePath(candidate);
|
|
@@ -77988,9 +78786,9 @@ function assertNoSymlinkTraversal(root, relative) {
|
|
|
77988
78786
|
let current = path88.resolve(root);
|
|
77989
78787
|
for (const segment of rel.split("/").slice(0, -1)) {
|
|
77990
78788
|
current = path88.join(current, segment);
|
|
77991
|
-
if (!
|
|
78789
|
+
if (!fs81.existsSync(current))
|
|
77992
78790
|
continue;
|
|
77993
|
-
if (
|
|
78791
|
+
if (fs81.lstatSync(current).isSymbolicLink()) {
|
|
77994
78792
|
throw new BenchmarkPhaseError("unsafe_path", `path traverses symlink: ${relative}`);
|
|
77995
78793
|
}
|
|
77996
78794
|
}
|
|
@@ -78000,9 +78798,9 @@ function assertOpenedFileWithinRoot(root, filePath, openedStat, label) {
|
|
|
78000
78798
|
let canonicalFile;
|
|
78001
78799
|
let currentStat;
|
|
78002
78800
|
try {
|
|
78003
|
-
canonicalRoot =
|
|
78004
|
-
canonicalFile =
|
|
78005
|
-
currentStat =
|
|
78801
|
+
canonicalRoot = fs81.realpathSync(root);
|
|
78802
|
+
canonicalFile = fs81.realpathSync(filePath);
|
|
78803
|
+
currentStat = fs81.statSync(filePath);
|
|
78006
78804
|
} catch {
|
|
78007
78805
|
throw new BenchmarkPhaseError("unsafe_path", `${label} changed while it was opened`);
|
|
78008
78806
|
}
|
|
@@ -78011,10 +78809,10 @@ function assertOpenedFileWithinRoot(root, filePath, openedStat, label) {
|
|
|
78011
78809
|
}
|
|
78012
78810
|
}
|
|
78013
78811
|
function openRegularFileNoFollow(filePath, label, root) {
|
|
78014
|
-
const noFollow = typeof
|
|
78812
|
+
const noFollow = typeof fs81.constants.O_NOFOLLOW === "number" ? fs81.constants.O_NOFOLLOW : 0;
|
|
78015
78813
|
let fd;
|
|
78016
78814
|
try {
|
|
78017
|
-
fd =
|
|
78815
|
+
fd = fs81.openSync(filePath, fs81.constants.O_RDONLY | noFollow);
|
|
78018
78816
|
} catch (error2) {
|
|
78019
78817
|
const code = error2.code;
|
|
78020
78818
|
if (code === "ELOOP") {
|
|
@@ -78022,16 +78820,16 @@ function openRegularFileNoFollow(filePath, label, root) {
|
|
|
78022
78820
|
}
|
|
78023
78821
|
throw error2;
|
|
78024
78822
|
}
|
|
78025
|
-
const stat =
|
|
78823
|
+
const stat = fs81.fstatSync(fd);
|
|
78026
78824
|
if (!stat.isFile()) {
|
|
78027
|
-
|
|
78825
|
+
fs81.closeSync(fd);
|
|
78028
78826
|
throw new BenchmarkPhaseError("invalid_input", `${label} must be a regular file`);
|
|
78029
78827
|
}
|
|
78030
78828
|
if (root) {
|
|
78031
78829
|
try {
|
|
78032
78830
|
assertOpenedFileWithinRoot(root, filePath, stat, label);
|
|
78033
78831
|
} catch (error2) {
|
|
78034
|
-
|
|
78832
|
+
fs81.closeSync(fd);
|
|
78035
78833
|
throw error2;
|
|
78036
78834
|
}
|
|
78037
78835
|
}
|
|
@@ -78039,7 +78837,7 @@ function openRegularFileNoFollow(filePath, label, root) {
|
|
|
78039
78837
|
}
|
|
78040
78838
|
async function sha256OfDescriptor(fd) {
|
|
78041
78839
|
const hash = crypto6.createHash("sha256");
|
|
78042
|
-
const stream =
|
|
78840
|
+
const stream = fs81.createReadStream("", {
|
|
78043
78841
|
fd,
|
|
78044
78842
|
autoClose: false,
|
|
78045
78843
|
start: 0
|
|
@@ -78050,7 +78848,7 @@ async function sha256OfDescriptor(fd) {
|
|
|
78050
78848
|
return hash.digest("hex");
|
|
78051
78849
|
}
|
|
78052
78850
|
function readDescriptor(fd) {
|
|
78053
|
-
return
|
|
78851
|
+
return fs81.readFileSync(fd);
|
|
78054
78852
|
}
|
|
78055
78853
|
function assertWritableDestination(root, relative) {
|
|
78056
78854
|
const rel = normalizedRootRelative(relative);
|
|
@@ -78060,9 +78858,9 @@ function assertWritableDestination(root, relative) {
|
|
|
78060
78858
|
const segments = rel.split("/");
|
|
78061
78859
|
for (const segment of segments.slice(0, -1)) {
|
|
78062
78860
|
current = path88.join(current, segment);
|
|
78063
|
-
if (!
|
|
78861
|
+
if (!fs81.existsSync(current))
|
|
78064
78862
|
continue;
|
|
78065
|
-
const stat =
|
|
78863
|
+
const stat = fs81.lstatSync(current);
|
|
78066
78864
|
if (stat.isSymbolicLink()) {
|
|
78067
78865
|
throw new BenchmarkPhaseError("unsafe_path", `path traverses symlink: ${relative}`);
|
|
78068
78866
|
}
|
|
@@ -78071,7 +78869,7 @@ function assertWritableDestination(root, relative) {
|
|
|
78071
78869
|
}
|
|
78072
78870
|
}
|
|
78073
78871
|
const destination = path88.resolve(root, rel);
|
|
78074
|
-
if (
|
|
78872
|
+
if (fs81.existsSync(destination) && fs81.lstatSync(destination).isDirectory()) {
|
|
78075
78873
|
throw new BenchmarkPhaseError("destination_conflict", `file destination is an existing directory: ${relative}`);
|
|
78076
78874
|
}
|
|
78077
78875
|
}
|
|
@@ -78103,7 +78901,7 @@ function sourcePath(stagingRoot, relative) {
|
|
|
78103
78901
|
assertNoSymlinkTraversal(stagingRoot, rel);
|
|
78104
78902
|
let stat;
|
|
78105
78903
|
try {
|
|
78106
|
-
stat =
|
|
78904
|
+
stat = fs81.lstatSync(source);
|
|
78107
78905
|
} catch {
|
|
78108
78906
|
throw new BenchmarkPhaseError("missing_input", `staged input does not exist: ${relative}`);
|
|
78109
78907
|
}
|
|
@@ -78132,12 +78930,12 @@ async function verifyRecordsUnchanged(records, spec) {
|
|
|
78132
78930
|
const relative = safeRelPath(record3.path);
|
|
78133
78931
|
assertNoSymlinkTraversal(root, relative);
|
|
78134
78932
|
const candidate = path88.resolve(root, relative);
|
|
78135
|
-
if (!isWithin(root, candidate) || !
|
|
78933
|
+
if (!isWithin(root, candidate) || !fs81.existsSync(candidate)) {
|
|
78136
78934
|
throw new BenchmarkPhaseError("evidence_tampered", `evidence was removed during evaluation: ${record3.root}:${record3.path}`);
|
|
78137
78935
|
}
|
|
78138
|
-
const stat =
|
|
78936
|
+
const stat = fs81.lstatSync(candidate);
|
|
78139
78937
|
if (record3.kind === "symlink") {
|
|
78140
|
-
const target = stat.isSymbolicLink() ?
|
|
78938
|
+
const target = stat.isSymbolicLink() ? fs81.readlinkSync(candidate) : null;
|
|
78141
78939
|
if (target === null || Buffer.byteLength(target) !== record3.size || sha256(target) !== record3.sha256) {
|
|
78142
78940
|
throw new BenchmarkPhaseError("evidence_tampered", `evidence changed during evaluation: ${record3.root}:${record3.path}`);
|
|
78143
78941
|
}
|
|
@@ -78152,7 +78950,7 @@ async function verifyRecordsUnchanged(records, spec) {
|
|
|
78152
78950
|
throw new BenchmarkPhaseError("evidence_tampered", `evidence changed during evaluation: ${record3.root}:${record3.path}`);
|
|
78153
78951
|
}
|
|
78154
78952
|
} finally {
|
|
78155
|
-
|
|
78953
|
+
fs81.closeSync(opened.fd);
|
|
78156
78954
|
}
|
|
78157
78955
|
}
|
|
78158
78956
|
}
|
|
@@ -78168,35 +78966,35 @@ async function verifyInput(stagingRoot, material) {
|
|
|
78168
78966
|
throw new BenchmarkPhaseError("digest_mismatch", `checksum mismatch for ${material.source}`, { expected: material.sha256, actual });
|
|
78169
78967
|
}
|
|
78170
78968
|
} finally {
|
|
78171
|
-
|
|
78969
|
+
fs81.closeSync(opened.fd);
|
|
78172
78970
|
}
|
|
78173
78971
|
return source;
|
|
78174
78972
|
}
|
|
78175
78973
|
async function atomicCopy(source, destination, mode, sourceRoot) {
|
|
78176
|
-
|
|
78974
|
+
fs81.mkdirSync(path88.dirname(destination), { recursive: true });
|
|
78177
78975
|
const temporary = `${destination}.${process.pid}.${crypto6.randomBytes(6).toString("hex")}.tmp`;
|
|
78178
78976
|
const opened = openRegularFileNoFollow(source, `copy source ${source}`, sourceRoot);
|
|
78179
78977
|
try {
|
|
78180
|
-
await pipeline2(
|
|
78978
|
+
await pipeline2(fs81.createReadStream("", {
|
|
78181
78979
|
fd: opened.fd,
|
|
78182
78980
|
autoClose: false,
|
|
78183
78981
|
start: 0
|
|
78184
|
-
}),
|
|
78982
|
+
}), fs81.createWriteStream(temporary, {
|
|
78185
78983
|
flags: "wx",
|
|
78186
78984
|
mode: 384
|
|
78187
78985
|
}));
|
|
78188
|
-
|
|
78189
|
-
|
|
78986
|
+
fs81.chmodSync(temporary, mode ?? opened.stat.mode & 511);
|
|
78987
|
+
fs81.renameSync(temporary, destination);
|
|
78190
78988
|
} finally {
|
|
78191
|
-
|
|
78192
|
-
|
|
78989
|
+
fs81.closeSync(opened.fd);
|
|
78990
|
+
fs81.rmSync(temporary, { force: true });
|
|
78193
78991
|
}
|
|
78194
78992
|
}
|
|
78195
78993
|
async function recordFile(root, filePath, rootName, kind = "file") {
|
|
78196
78994
|
const relative = path88.relative(root, filePath).replace(/\\/g, "/");
|
|
78197
78995
|
if (kind === "symlink") {
|
|
78198
|
-
const stat =
|
|
78199
|
-
const target =
|
|
78996
|
+
const stat = fs81.lstatSync(filePath);
|
|
78997
|
+
const target = fs81.readlinkSync(filePath);
|
|
78200
78998
|
return {
|
|
78201
78999
|
root: rootName,
|
|
78202
79000
|
path: relative,
|
|
@@ -78216,7 +79014,7 @@ async function recordFile(root, filePath, rootName, kind = "file") {
|
|
|
78216
79014
|
mode: opened.stat.mode & 511
|
|
78217
79015
|
};
|
|
78218
79016
|
} finally {
|
|
78219
|
-
|
|
79017
|
+
fs81.closeSync(opened.fd);
|
|
78220
79018
|
}
|
|
78221
79019
|
}
|
|
78222
79020
|
async function copyMaterial(material, sourceRoot, destinationRoot, destinationRootName, protectWorkspace) {
|
|
@@ -78238,7 +79036,7 @@ async function copyMaterial(material, sourceRoot, destinationRoot, destinationRo
|
|
|
78238
79036
|
}
|
|
78239
79037
|
return [record3];
|
|
78240
79038
|
}
|
|
78241
|
-
const temporary =
|
|
79039
|
+
const temporary = fs81.mkdtempSync(path88.join(os16.tmpdir(), "brainbase-benchmark-"));
|
|
78242
79040
|
try {
|
|
78243
79041
|
const verifiedArchive = path88.join(temporary, "material.tar.gz");
|
|
78244
79042
|
await atomicCopy(source, verifiedArchive, 384, sourceRoot);
|
|
@@ -78256,7 +79054,7 @@ async function copyMaterial(material, sourceRoot, destinationRoot, destinationRo
|
|
|
78256
79054
|
const outputs = [];
|
|
78257
79055
|
for (const extractedRel of extracted.sort()) {
|
|
78258
79056
|
const sourceFile = path88.resolve(extractedRoot, safeRelPath(extractedRel));
|
|
78259
|
-
const stat =
|
|
79057
|
+
const stat = fs81.lstatSync(sourceFile);
|
|
78260
79058
|
if (!stat.isFile())
|
|
78261
79059
|
continue;
|
|
78262
79060
|
const combined = destinationRel === "." ? safeRelPath(extractedRel) : safeRelPath(path88.posix.join(destinationRel, extractedRel));
|
|
@@ -78271,7 +79069,7 @@ async function copyMaterial(material, sourceRoot, destinationRoot, destinationRo
|
|
|
78271
79069
|
}
|
|
78272
79070
|
return outputs;
|
|
78273
79071
|
} finally {
|
|
78274
|
-
|
|
79072
|
+
fs81.rmSync(temporary, { recursive: true, force: true });
|
|
78275
79073
|
}
|
|
78276
79074
|
}
|
|
78277
79075
|
async function preflightMaterial(material, sourceRoot, destinationRoot, protectWorkspace) {
|
|
@@ -78287,7 +79085,7 @@ async function preflightMaterial(material, sourceRoot, destinationRoot, protectW
|
|
|
78287
79085
|
assertWritableDestination(destinationRoot, destinationRel);
|
|
78288
79086
|
return [destinationRel];
|
|
78289
79087
|
}
|
|
78290
|
-
const temporary =
|
|
79088
|
+
const temporary = fs81.mkdtempSync(path88.join(os16.tmpdir(), "brainbase-benchmark-preflight-"));
|
|
78291
79089
|
try {
|
|
78292
79090
|
const verifiedArchive = path88.join(temporary, "material.tar.gz");
|
|
78293
79091
|
await atomicCopy(source, verifiedArchive, 384, sourceRoot);
|
|
@@ -78314,34 +79112,34 @@ async function preflightMaterial(material, sourceRoot, destinationRoot, protectW
|
|
|
78314
79112
|
}
|
|
78315
79113
|
return planned;
|
|
78316
79114
|
} finally {
|
|
78317
|
-
|
|
79115
|
+
fs81.rmSync(temporary, { recursive: true, force: true });
|
|
78318
79116
|
}
|
|
78319
79117
|
}
|
|
78320
79118
|
function ownerMarker(root) {
|
|
78321
79119
|
return path88.join(root, ".brainbase-benchmark-owner.json");
|
|
78322
79120
|
}
|
|
78323
79121
|
function verifyOwnedDirectory(root, role, spec) {
|
|
78324
|
-
if (!
|
|
79122
|
+
if (!fs81.existsSync(root) || fs81.lstatSync(root).isSymbolicLink())
|
|
78325
79123
|
return false;
|
|
78326
79124
|
try {
|
|
78327
|
-
const marker = JSON.parse(
|
|
79125
|
+
const marker = JSON.parse(fs81.readFileSync(ownerMarker(root), "utf8"));
|
|
78328
79126
|
return marker.attempt_id === spec.attempt_id && marker.phase === spec.phase && marker.phase_id === spec.phase_id && marker.role === role;
|
|
78329
79127
|
} catch {
|
|
78330
79128
|
return false;
|
|
78331
79129
|
}
|
|
78332
79130
|
}
|
|
78333
79131
|
function prepareOwnedDirectory(root, role, spec) {
|
|
78334
|
-
if (
|
|
79132
|
+
if (fs81.existsSync(root)) {
|
|
78335
79133
|
if (!verifyOwnedDirectory(root, role, spec)) {
|
|
78336
|
-
const stat =
|
|
78337
|
-
if (!stat.isDirectory() ||
|
|
79134
|
+
const stat = fs81.lstatSync(root);
|
|
79135
|
+
if (!stat.isDirectory() || fs81.readdirSync(root).length > 0) {
|
|
78338
79136
|
throw new BenchmarkPhaseError(`unowned_${role}_root`, `${role}_root exists without a matching attempt ownership marker`);
|
|
78339
79137
|
}
|
|
78340
79138
|
} else {
|
|
78341
|
-
|
|
79139
|
+
fs81.rmSync(root, { recursive: true, force: true });
|
|
78342
79140
|
}
|
|
78343
79141
|
}
|
|
78344
|
-
|
|
79142
|
+
fs81.mkdirSync(root, { recursive: true, mode: 448 });
|
|
78345
79143
|
writeJsonAtomic(ownerMarker(root), {
|
|
78346
79144
|
schema_version: SCHEMA_VERSION,
|
|
78347
79145
|
attempt_id: spec.attempt_id,
|
|
@@ -78433,7 +79231,7 @@ async function runCommand(command, root, spec, context, additions = {}) {
|
|
|
78433
79231
|
const cwd2 = path88.resolve(root, cwdRel);
|
|
78434
79232
|
let cwdStat;
|
|
78435
79233
|
try {
|
|
78436
|
-
cwdStat =
|
|
79234
|
+
cwdStat = fs81.lstatSync(cwd2);
|
|
78437
79235
|
} catch {
|
|
78438
79236
|
throw new BenchmarkPhaseError("invalid_command_cwd", `command cwd is invalid: ${command.cwd}`);
|
|
78439
79237
|
}
|
|
@@ -78505,27 +79303,27 @@ async function runCommand(command, root, spec, context, additions = {}) {
|
|
|
78505
79303
|
}
|
|
78506
79304
|
async function writeLog(root, name, data, spec) {
|
|
78507
79305
|
const destination = path88.join(root, name);
|
|
78508
|
-
|
|
79306
|
+
fs81.mkdirSync(path88.dirname(destination), { recursive: true });
|
|
78509
79307
|
const temporary = `${destination}.${process.pid}.${crypto6.randomBytes(6).toString("hex")}.tmp`;
|
|
78510
79308
|
try {
|
|
78511
|
-
|
|
79309
|
+
fs81.writeFileSync(temporary, redactCommandOutput(data, spec), {
|
|
78512
79310
|
flag: "wx",
|
|
78513
79311
|
mode: 384
|
|
78514
79312
|
});
|
|
78515
|
-
|
|
79313
|
+
fs81.renameSync(temporary, destination);
|
|
78516
79314
|
} finally {
|
|
78517
|
-
|
|
79315
|
+
fs81.rmSync(temporary, { force: true });
|
|
78518
79316
|
}
|
|
78519
79317
|
return await recordFile(root, destination, "logs");
|
|
78520
79318
|
}
|
|
78521
79319
|
function writeBufferAtomic(destination, data) {
|
|
78522
|
-
|
|
79320
|
+
fs81.mkdirSync(path88.dirname(destination), { recursive: true });
|
|
78523
79321
|
const temporary = `${destination}.${process.pid}.${crypto6.randomBytes(6).toString("hex")}.tmp`;
|
|
78524
79322
|
try {
|
|
78525
|
-
|
|
78526
|
-
|
|
79323
|
+
fs81.writeFileSync(temporary, data, { flag: "wx", mode: 384 });
|
|
79324
|
+
fs81.renameSync(temporary, destination);
|
|
78527
79325
|
} finally {
|
|
78528
|
-
|
|
79326
|
+
fs81.rmSync(temporary, { force: true });
|
|
78529
79327
|
}
|
|
78530
79328
|
}
|
|
78531
79329
|
function assertBudget(context) {
|
|
@@ -78534,7 +79332,7 @@ function assertBudget(context) {
|
|
|
78534
79332
|
}
|
|
78535
79333
|
}
|
|
78536
79334
|
async function executeHydrate(spec, context) {
|
|
78537
|
-
|
|
79335
|
+
fs81.mkdirSync(spec.workspace_root, { recursive: true });
|
|
78538
79336
|
prepareOwnedDirectory(spec.logs_root, "logs", spec);
|
|
78539
79337
|
context.logsOwned = true;
|
|
78540
79338
|
const outputs = [];
|
|
@@ -78615,9 +79413,9 @@ async function executeHydrate(spec, context) {
|
|
|
78615
79413
|
}
|
|
78616
79414
|
const candidate = path88.resolve(spec.workspace_root, safeRelPath(output.path));
|
|
78617
79415
|
assertNoSymlinkTraversal(spec.workspace_root, output.path);
|
|
78618
|
-
if (!
|
|
79416
|
+
if (!fs81.existsSync(candidate))
|
|
78619
79417
|
continue;
|
|
78620
|
-
const stat =
|
|
79418
|
+
const stat = fs81.lstatSync(candidate);
|
|
78621
79419
|
if (!stat.isFile() && !stat.isSymbolicLink())
|
|
78622
79420
|
continue;
|
|
78623
79421
|
finalOutputs.push(await recordFile(spec.workspace_root, candidate, "workspace", stat.isSymbolicLink() ? "symlink" : "file"));
|
|
@@ -78651,7 +79449,7 @@ async function readEvidence(stagingRoot, evidence) {
|
|
|
78651
79449
|
}
|
|
78652
79450
|
};
|
|
78653
79451
|
} finally {
|
|
78654
|
-
|
|
79452
|
+
fs81.closeSync(opened.fd);
|
|
78655
79453
|
}
|
|
78656
79454
|
}
|
|
78657
79455
|
async function workspaceManifest(spec, context) {
|
|
@@ -78660,7 +79458,7 @@ async function workspaceManifest(spec, context) {
|
|
|
78660
79458
|
const stack = [path88.resolve(spec.workspace_root)];
|
|
78661
79459
|
while (stack.length > 0) {
|
|
78662
79460
|
const directory = stack.pop();
|
|
78663
|
-
const entries =
|
|
79461
|
+
const entries = fs81.readdirSync(directory, { withFileTypes: true }).sort((a3, b4) => a3.name.localeCompare(b4.name));
|
|
78664
79462
|
for (const entry of entries) {
|
|
78665
79463
|
assertBudget(context);
|
|
78666
79464
|
const full = path88.join(directory, entry.name);
|
|
@@ -78769,7 +79567,7 @@ async function evaluateOne(evaluator, spec, finalOutput, trajectory, frozenEvide
|
|
|
78769
79567
|
const candidate = path88.resolve(spec.workspace_root, relative);
|
|
78770
79568
|
let stat = null;
|
|
78771
79569
|
try {
|
|
78772
|
-
stat =
|
|
79570
|
+
stat = fs81.lstatSync(candidate);
|
|
78773
79571
|
} catch (error2) {
|
|
78774
79572
|
const code = error2.code;
|
|
78775
79573
|
if (code !== "ENOENT" && code !== "ENOTDIR")
|
|
@@ -78790,7 +79588,7 @@ async function evaluateOne(evaluator, spec, finalOutput, trajectory, frozenEvide
|
|
|
78790
79588
|
try {
|
|
78791
79589
|
verdict2 = await sha256OfDescriptor(opened.fd) === evaluator.assertion.expected;
|
|
78792
79590
|
} finally {
|
|
78793
|
-
|
|
79591
|
+
fs81.closeSync(opened.fd);
|
|
78794
79592
|
}
|
|
78795
79593
|
}
|
|
78796
79594
|
}
|
|
@@ -78800,7 +79598,7 @@ async function evaluateOne(evaluator, spec, finalOutput, trajectory, frozenEvide
|
|
|
78800
79598
|
try {
|
|
78801
79599
|
verdict2 = readDescriptor(opened.fd).toString("utf8").includes(evaluator.assertion.expected);
|
|
78802
79600
|
} finally {
|
|
78803
|
-
|
|
79601
|
+
fs81.closeSync(opened.fd);
|
|
78804
79602
|
}
|
|
78805
79603
|
}
|
|
78806
79604
|
}
|
|
@@ -78881,7 +79679,7 @@ async function executeEvaluate(spec, context) {
|
|
|
78881
79679
|
assertNoSymlinkTraversal(spec.workspace_root, artifactRel);
|
|
78882
79680
|
const source = path88.resolve(spec.workspace_root, artifactRel);
|
|
78883
79681
|
const frozenArtifact = manifest.find((entry) => entry.path === artifactRel && entry.kind !== "symlink");
|
|
78884
|
-
if (!frozenArtifact || !
|
|
79682
|
+
if (!frozenArtifact || !fs81.existsSync(source) || !fs81.lstatSync(source).isFile()) {
|
|
78885
79683
|
throw new BenchmarkPhaseError("missing_artifact", `candidate artifact is missing: ${artifactRel}`);
|
|
78886
79684
|
}
|
|
78887
79685
|
const destination = path88.resolve(spec.logs_root, "candidate-artifacts", artifactRel);
|
|
@@ -78899,9 +79697,9 @@ async function executeEvaluate(spec, context) {
|
|
|
78899
79697
|
const temporary = `${archive}.${process.pid}.${crypto6.randomBytes(6).toString("hex")}.tmp`;
|
|
78900
79698
|
try {
|
|
78901
79699
|
await pack({ rootDir: spec.workspace_root, outFile: temporary, files: regularFiles });
|
|
78902
|
-
|
|
79700
|
+
fs81.renameSync(temporary, archive);
|
|
78903
79701
|
} finally {
|
|
78904
|
-
|
|
79702
|
+
fs81.rmSync(temporary, { force: true });
|
|
78905
79703
|
}
|
|
78906
79704
|
const archiveRecord = await recordFile(spec.logs_root, archive, "logs");
|
|
78907
79705
|
outputs.push(archiveRecord);
|
|
@@ -79001,21 +79799,21 @@ function rawIdentity(value) {
|
|
|
79001
79799
|
}
|
|
79002
79800
|
function readSpecBytes(specPathInput) {
|
|
79003
79801
|
const specPath = path88.resolve(specPathInput);
|
|
79004
|
-
const noFollow = typeof
|
|
79802
|
+
const noFollow = typeof fs81.constants.O_NOFOLLOW === "number" ? fs81.constants.O_NOFOLLOW : 0;
|
|
79005
79803
|
let fd;
|
|
79006
79804
|
try {
|
|
79007
|
-
fd =
|
|
79805
|
+
fd = fs81.openSync(specPath, fs81.constants.O_RDONLY | noFollow);
|
|
79008
79806
|
} catch {
|
|
79009
79807
|
throw new BenchmarkPhaseError("spec_read_failed", "spec file could not be read");
|
|
79010
79808
|
}
|
|
79011
79809
|
try {
|
|
79012
|
-
const stat =
|
|
79810
|
+
const stat = fs81.fstatSync(fd);
|
|
79013
79811
|
if (!stat.isFile() || stat.size > MAX_SPEC_BYTES) {
|
|
79014
79812
|
throw new BenchmarkPhaseError("invalid_spec_file", "spec must be a regular JSON file no larger than 20 MiB");
|
|
79015
79813
|
}
|
|
79016
79814
|
return readDescriptor(fd);
|
|
79017
79815
|
} finally {
|
|
79018
|
-
|
|
79816
|
+
fs81.closeSync(fd);
|
|
79019
79817
|
}
|
|
79020
79818
|
}
|
|
79021
79819
|
function validateBenchmarkInvocationBytes(bytes, resultPathInput, expectedPhase) {
|
|
@@ -79059,9 +79857,9 @@ function prepareBenchmarkPhaseInvocation(specPathInput, resultPathInput, expecte
|
|
|
79059
79857
|
spec_digest: digest,
|
|
79060
79858
|
timeout_ms: spec.budget.timeout_ms
|
|
79061
79859
|
};
|
|
79062
|
-
if (
|
|
79860
|
+
if (fs81.existsSync(resultPath)) {
|
|
79063
79861
|
try {
|
|
79064
|
-
const cached2 = JSON.parse(
|
|
79862
|
+
const cached2 = JSON.parse(fs81.readFileSync(resultPath, "utf8"));
|
|
79065
79863
|
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") {
|
|
79066
79864
|
return {
|
|
79067
79865
|
ok: true,
|
|
@@ -79168,9 +79966,9 @@ async function runBenchmarkPhase(specPathInput, resultPathInput, expectedPhase,
|
|
|
79168
79966
|
throw new BenchmarkPhaseError("invalid_result_path", `result path must be ${expectedResultPath}`);
|
|
79169
79967
|
}
|
|
79170
79968
|
resultPathValidated = true;
|
|
79171
|
-
if (
|
|
79969
|
+
if (fs81.existsSync(resultPath)) {
|
|
79172
79970
|
try {
|
|
79173
|
-
const cached2 = JSON.parse(
|
|
79971
|
+
const cached2 = JSON.parse(fs81.readFileSync(resultPath, "utf8"));
|
|
79174
79972
|
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") {
|
|
79175
79973
|
return { exitCode: 0, result: cached2 };
|
|
79176
79974
|
}
|
|
@@ -79367,13 +80165,13 @@ function terminatePhase(child) {
|
|
|
79367
80165
|
}
|
|
79368
80166
|
function createAnonymousSpecFd(bytes) {
|
|
79369
80167
|
const temporary = path89.join(os17.tmpdir(), `brainbase-benchmark-spec-${process.pid}-${crypto7.randomBytes(12).toString("hex")}`);
|
|
79370
|
-
|
|
80168
|
+
fs82.writeFileSync(temporary, bytes, { flag: "wx", mode: 384 });
|
|
79371
80169
|
try {
|
|
79372
|
-
const fd =
|
|
79373
|
-
|
|
80170
|
+
const fd = fs82.openSync(temporary, "r");
|
|
80171
|
+
fs82.unlinkSync(temporary);
|
|
79374
80172
|
return fd;
|
|
79375
80173
|
} catch (error2) {
|
|
79376
|
-
|
|
80174
|
+
fs82.rmSync(temporary, { force: true });
|
|
79377
80175
|
throw error2;
|
|
79378
80176
|
}
|
|
79379
80177
|
}
|
|
@@ -79442,13 +80240,13 @@ async function runSupervisedPhase(phase, parsed, write) {
|
|
|
79442
80240
|
detached: process.platform !== "win32"
|
|
79443
80241
|
});
|
|
79444
80242
|
} catch {
|
|
79445
|
-
|
|
80243
|
+
fs82.closeSync(specFd);
|
|
79446
80244
|
const failure = phaseFailure(invocation, startedAt, started, "phase_supervisor_failed", "benchmark phase child process could not be started");
|
|
79447
80245
|
write(`${JSON.stringify(failure)}
|
|
79448
80246
|
`);
|
|
79449
80247
|
return 1;
|
|
79450
80248
|
}
|
|
79451
|
-
|
|
80249
|
+
fs82.closeSync(specFd);
|
|
79452
80250
|
return await new Promise((resolve) => {
|
|
79453
80251
|
const stdout = [];
|
|
79454
80252
|
let settled = false;
|
|
@@ -79530,7 +80328,7 @@ async function runBenchmark(sub, args, write = (value) => process.stdout.write(v
|
|
|
79530
80328
|
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) {
|
|
79531
80329
|
throw new Error("Invalid internal benchmark phase invocation");
|
|
79532
80330
|
}
|
|
79533
|
-
const specBytes =
|
|
80331
|
+
const specBytes = fs82.readFileSync(specFd);
|
|
79534
80332
|
const { exitCode, result: result2 } = await runBenchmarkPhase("", resultPath, phase, specBytes);
|
|
79535
80333
|
write(`${JSON.stringify(result2)}
|
|
79536
80334
|
`);
|
|
@@ -79570,13 +80368,13 @@ async function runBenchmark(sub, args, write = (value) => process.stdout.write(v
|
|
|
79570
80368
|
function printHelp5() {
|
|
79571
80369
|
const out = [];
|
|
79572
80370
|
out.push("");
|
|
79573
|
-
out.push(` ${
|
|
80371
|
+
out.push(` ${import_picocolors51.default.bold("brainbase benchmark")} ${import_picocolors51.default.dim("<sub> [options]")}`);
|
|
79574
80372
|
out.push("");
|
|
79575
|
-
out.push(` ${
|
|
79576
|
-
out.push(` ${
|
|
79577
|
-
out.push(` ${
|
|
80373
|
+
out.push(` ${import_picocolors51.default.cyan("hydrate")} ${import_picocolors51.default.dim("--spec <path> --result <path> --json")}`);
|
|
80374
|
+
out.push(` ${import_picocolors51.default.cyan("evaluate")} ${import_picocolors51.default.dim("--spec <path> --result <path> --json")}`);
|
|
80375
|
+
out.push(` ${import_picocolors51.default.cyan("capabilities")} ${import_picocolors51.default.dim("--json")}`);
|
|
79578
80376
|
out.push("");
|
|
79579
|
-
out.push(` ${
|
|
80377
|
+
out.push(` ${import_picocolors51.default.dim("These machine-only commands execute versioned benchmark phase specs inside a task sandbox.")}`);
|
|
79580
80378
|
out.push("");
|
|
79581
80379
|
console.log(out.join(`
|
|
79582
80380
|
`));
|
|
@@ -79603,130 +80401,137 @@ var SUBCOMMAND_OWNED_FLAGS = {
|
|
|
79603
80401
|
function help() {
|
|
79604
80402
|
const out = [];
|
|
79605
80403
|
out.push("");
|
|
79606
|
-
out.push(` ${brandTint("◆")} ${
|
|
79607
|
-
out.push(` ${
|
|
80404
|
+
out.push(` ${brandTint("◆")} ${import_picocolors52.default.bold("brainbase")} ${import_picocolors52.default.dim(`v${VERSION}`)}`);
|
|
80405
|
+
out.push(` ${import_picocolors52.default.dim("connect your local agent to the brainbase platform")}`);
|
|
79608
80406
|
out.push("");
|
|
79609
80407
|
out.push(divider("USAGE"));
|
|
79610
80408
|
out.push("");
|
|
79611
|
-
out.push(` ${
|
|
80409
|
+
out.push(` ${import_picocolors52.default.bold("brainbase")} ${import_picocolors52.default.dim("<command> [options]")}`);
|
|
79612
80410
|
out.push("");
|
|
79613
80411
|
out.push(divider("AUTH"));
|
|
79614
80412
|
out.push("");
|
|
79615
|
-
out.push(` ${
|
|
79616
|
-
out.push(` ${
|
|
79617
|
-
out.push(` ${
|
|
80413
|
+
out.push(` ${import_picocolors52.default.cyan("login")} ${import_picocolors52.default.dim(" open the web app and connect this device")}`);
|
|
80414
|
+
out.push(` ${import_picocolors52.default.cyan("logout")} ${import_picocolors52.default.dim(" clear the local session")}`);
|
|
80415
|
+
out.push(` ${import_picocolors52.default.cyan("whoami")} ${import_picocolors52.default.dim("[--json]")} ${import_picocolors52.default.dim(" show which credential is in use and what it covers")}`);
|
|
79618
80416
|
out.push("");
|
|
79619
80417
|
out.push(divider("DISCOVERY"));
|
|
79620
80418
|
out.push("");
|
|
79621
|
-
out.push(` ${
|
|
79622
|
-
out.push(` ${
|
|
80419
|
+
out.push(` ${import_picocolors52.default.cyan("team list")} ${import_picocolors52.default.dim("show the teams you can create agents in")}`);
|
|
80420
|
+
out.push(` ${import_picocolors52.default.cyan("agent list")} ${import_picocolors52.default.dim("show a team's agents and their ids")}`);
|
|
79623
80421
|
out.push("");
|
|
79624
80422
|
out.push(divider("LINKED AGENT"));
|
|
79625
80423
|
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(` ${
|
|
80424
|
+
out.push(` ${import_picocolors52.default.cyan("agent create")} ${import_picocolors52.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
80425
|
+
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)")}`);
|
|
80426
|
+
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)")}`);
|
|
80427
|
+
out.push(` ${import_picocolors52.default.cyan("agent unpack")} ${import_picocolors52.default.dim("install the claimed agent into a harness layout")}`);
|
|
80428
|
+
out.push(` ${import_picocolors52.default.cyan("link")} ${import_picocolors52.default.dim("attach this folder to an existing agent")}`);
|
|
80429
|
+
out.push(` ${import_picocolors52.default.cyan("agent status")} ${import_picocolors52.default.dim("show what would pull and what would push")}`);
|
|
80430
|
+
out.push(` ${import_picocolors52.default.cyan("agent connections")} ${import_picocolors52.default.dim("show which integrations this agent is wired to (--json for CI)")}`);
|
|
80431
|
+
out.push(` ${import_picocolors52.default.cyan("agent connect")} ${import_picocolors52.default.dim("<name>")} ${import_picocolors52.default.dim("connect slack or meeting from the terminal")}`);
|
|
80432
|
+
out.push(` ${import_picocolors52.default.cyan("agent disconnect")} ${import_picocolors52.default.dim("<name>")} ${import_picocolors52.default.dim("revoke a slack or meeting install")}`);
|
|
80433
|
+
out.push(` ${import_picocolors52.default.cyan("agent env")} ${import_picocolors52.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
|
|
80434
|
+
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")}`);
|
|
80435
|
+
out.push(` ${import_picocolors52.default.cyan("status")} ${import_picocolors52.default.dim("show what this folder is linked to")}`);
|
|
80436
|
+
out.push(` ${import_picocolors52.default.cyan("unlink")} ${import_picocolors52.default.dim("disconnect this folder")}`);
|
|
79636
80437
|
out.push("");
|
|
79637
80438
|
out.push(divider("TASKS"));
|
|
79638
80439
|
out.push("");
|
|
79639
|
-
out.push(` ${
|
|
80440
|
+
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")}`);
|
|
79640
80441
|
out.push("");
|
|
79641
80442
|
out.push(divider("BENCHMARK RUNTIME"));
|
|
79642
80443
|
out.push("");
|
|
79643
|
-
out.push(` ${
|
|
79644
|
-
out.push(` ${
|
|
79645
|
-
out.push(` ${
|
|
80444
|
+
out.push(` ${import_picocolors52.default.cyan("benchmark hydrate")} ${import_picocolors52.default.dim("--spec <path> --result <path> --json")}`);
|
|
80445
|
+
out.push(` ${import_picocolors52.default.cyan("benchmark evaluate")} ${import_picocolors52.default.dim("--spec <path> --result <path> --json")}`);
|
|
80446
|
+
out.push(` ${import_picocolors52.default.cyan("benchmark capabilities")} ${import_picocolors52.default.dim("--json")}`);
|
|
79646
80447
|
out.push("");
|
|
79647
80448
|
out.push(divider("ORCHESTRATIONS"));
|
|
79648
80449
|
out.push("");
|
|
79649
|
-
out.push(` ${
|
|
79650
|
-
out.push(` ${
|
|
79651
|
-
out.push(` ${
|
|
79652
|
-
out.push(` ${
|
|
79653
|
-
out.push(` ${
|
|
80450
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration create")} ${import_picocolors52.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
|
|
80451
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration list")} ${import_picocolors52.default.dim("list orchestrations under a team")}`);
|
|
80452
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration pull")} ${import_picocolors52.default.dim("<id>")} ${import_picocolors52.default.dim("recursively fetch an orchestration + every member agent")}`);
|
|
80453
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration push")} ${import_picocolors52.default.dim("recursively push each member, then update the graph")}`);
|
|
80454
|
+
out.push(` ${import_picocolors52.default.cyan("orchestration status")} ${import_picocolors52.default.dim("show what would push and what would pull")}`);
|
|
79654
80455
|
out.push("");
|
|
79655
80456
|
out.push(divider("TEMPLATES"));
|
|
79656
80457
|
out.push("");
|
|
79657
|
-
out.push(` ${
|
|
79658
|
-
out.push(` ${
|
|
79659
|
-
out.push(` ${
|
|
79660
|
-
out.push(` ${
|
|
79661
|
-
out.push(` ${
|
|
79662
|
-
out.push(` ${
|
|
79663
|
-
out.push(` ${
|
|
80458
|
+
out.push(` ${import_picocolors52.default.cyan("template pack")} ${import_picocolors52.default.dim("bundle the current agent into a template")}`);
|
|
80459
|
+
out.push(` ${import_picocolors52.default.cyan("template publish")} ${import_picocolors52.default.dim("upload a template to the registry")}`);
|
|
80460
|
+
out.push(` ${import_picocolors52.default.cyan("template search")} ${import_picocolors52.default.dim("[query]")} ${import_picocolors52.default.dim("search the registry")}`);
|
|
80461
|
+
out.push(` ${import_picocolors52.default.cyan("template info")} ${import_picocolors52.default.dim("<creator/slug>")} ${import_picocolors52.default.dim("show registry details for a template")}`);
|
|
80462
|
+
out.push(` ${import_picocolors52.default.cyan("template onboard")} ${import_picocolors52.default.dim("<creator/slug>")} ${import_picocolors52.default.dim("install (or refresh) a template")}`);
|
|
80463
|
+
out.push(` ${import_picocolors52.default.cyan("template list")} ${import_picocolors52.default.dim("show installed templates")}`);
|
|
80464
|
+
out.push(` ${import_picocolors52.default.cyan("template remove")} ${import_picocolors52.default.dim("<creator/slug>")} ${import_picocolors52.default.dim("uninstall a template")}`);
|
|
79664
80465
|
out.push("");
|
|
79665
80466
|
out.push(divider("SKILLS"));
|
|
79666
80467
|
out.push("");
|
|
79667
|
-
out.push(` ${
|
|
79668
|
-
out.push(` ${
|
|
79669
|
-
out.push(` ${
|
|
79670
|
-
out.push(` ${
|
|
79671
|
-
out.push(` ${
|
|
79672
|
-
out.push(` ${
|
|
79673
|
-
out.push(` ${
|
|
80468
|
+
out.push(` ${import_picocolors52.default.cyan("skill add")} ${import_picocolors52.default.dim("<source>")} ${import_picocolors52.default.dim("install a skill (github / git / brainbase)")}`);
|
|
80469
|
+
out.push(` ${import_picocolors52.default.cyan("skill list")} ${import_picocolors52.default.dim("show locally installed skills + their source")}`);
|
|
80470
|
+
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")}`);
|
|
80471
|
+
out.push(` ${import_picocolors52.default.cyan("skill remove")} ${import_picocolors52.default.dim("<slug>")} ${import_picocolors52.default.dim("uninstall a skill")}`);
|
|
80472
|
+
out.push(` ${import_picocolors52.default.cyan("skill search")} ${import_picocolors52.default.dim("[query]")} ${import_picocolors52.default.dim("search the brainbase skill registry")}`);
|
|
80473
|
+
out.push(` ${import_picocolors52.default.cyan("skill info")} ${import_picocolors52.default.dim("<creator/slug>")} ${import_picocolors52.default.dim("show registry details for a skill")}`);
|
|
80474
|
+
out.push(` ${import_picocolors52.default.cyan("skill publish")} ${import_picocolors52.default.dim("[dir]")} ${import_picocolors52.default.dim("publish a SKILL.md folder (defaults to .)")}`);
|
|
79674
80475
|
out.push("");
|
|
79675
80476
|
out.push(divider("CLI TOKENS"));
|
|
79676
80477
|
out.push("");
|
|
79677
|
-
out.push(` ${
|
|
79678
|
-
out.push(` ${
|
|
79679
|
-
out.push(` ${
|
|
79680
|
-
out.push(` ${
|
|
80478
|
+
out.push(` ${import_picocolors52.default.cyan("token create")} ${import_picocolors52.default.dim("issue a long-lived CLI key for CI / scripts")}`);
|
|
80479
|
+
out.push(` ${import_picocolors52.default.cyan("token list")} ${import_picocolors52.default.dim("show your tokens")}`);
|
|
80480
|
+
out.push(` ${import_picocolors52.default.cyan("token rename")} ${import_picocolors52.default.dim("<id>")} ${import_picocolors52.default.dim("relabel a token")}`);
|
|
80481
|
+
out.push(` ${import_picocolors52.default.cyan("token revoke")} ${import_picocolors52.default.dim("<id>")} ${import_picocolors52.default.dim("revoke a token")}`);
|
|
79681
80482
|
out.push("");
|
|
79682
80483
|
out.push(divider("MCP"));
|
|
79683
80484
|
out.push("");
|
|
79684
|
-
out.push(` ${
|
|
80485
|
+
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)")}`);
|
|
80486
|
+
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")}`);
|
|
79685
80487
|
out.push("");
|
|
79686
80488
|
out.push(divider("FLAGS"));
|
|
79687
80489
|
out.push("");
|
|
79688
|
-
out.push(` ${
|
|
79689
|
-
out.push(` ${
|
|
79690
|
-
out.push(` ${
|
|
79691
|
-
out.push(` ${
|
|
79692
|
-
out.push(` ${
|
|
79693
|
-
out.push(` ${
|
|
79694
|
-
out.push(` ${
|
|
79695
|
-
out.push(` ${
|
|
79696
|
-
out.push(` ${
|
|
79697
|
-
out.push(` ${
|
|
79698
|
-
out.push(` ${
|
|
79699
|
-
out.push(` ${
|
|
79700
|
-
out.push(` ${
|
|
79701
|
-
out.push(` ${
|
|
79702
|
-
out.push(` ${
|
|
80490
|
+
out.push(` ${import_picocolors52.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
|
|
80491
|
+
out.push(` ${import_picocolors52.default.dim("--scope <s>")} force scope: global | project`);
|
|
80492
|
+
out.push(` ${import_picocolors52.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
|
|
80493
|
+
out.push(` ${import_picocolors52.default.dim("--agent <id>")} for link/task create: use this agent id explicitly`);
|
|
80494
|
+
out.push(` ${import_picocolors52.default.dim("--message <text>")} for task create: required first user message`);
|
|
80495
|
+
out.push(` ${import_picocolors52.default.dim("--title <text>")} for task create: optional task title`);
|
|
80496
|
+
out.push(` ${import_picocolors52.default.dim("--model <id>")} for task create: optional model override`);
|
|
80497
|
+
out.push(` ${import_picocolors52.default.dim("--org <id-or-slug>")} pick the organization (team/agent list, agent create, orchestration create/list)`);
|
|
80498
|
+
out.push(` ${import_picocolors52.default.dim("--team <id>")} pick the team, same commands (works without --org)`);
|
|
80499
|
+
out.push(` ${import_picocolors52.default.dim("--json")} machine-readable output for supported commands`);
|
|
80500
|
+
out.push(` ${import_picocolors52.default.dim("--no-tracking")} for link: skip routing LLM traffic through brainbase`);
|
|
80501
|
+
out.push(` ${import_picocolors52.default.dim("--track")} for agent create: enable tracking non-interactively (off without a TTY)`);
|
|
80502
|
+
out.push(` ${import_picocolors52.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
|
|
80503
|
+
out.push(` ${import_picocolors52.default.dim("--bot-token <t>")} for agent connect slack (or BRAINBASE_SLACK_BOT_TOKEN, or stdin)`);
|
|
80504
|
+
out.push(` ${import_picocolors52.default.dim("--signing-secret <s>")} for agent connect slack (or BRAINBASE_SLACK_SIGNING_SECRET, or stdin)`);
|
|
80505
|
+
out.push(` ${import_picocolors52.default.dim("--bot-name <name>")} for agent connect meeting: the bot's display name`);
|
|
80506
|
+
out.push(` ${import_picocolors52.default.dim("--all")} for template list: include installs from other folders`);
|
|
80507
|
+
out.push(` ${import_picocolors52.default.dim("--web <url>")} for login: web app URL (default https://app.brainbaselabs.com)`);
|
|
79703
80508
|
out.push("");
|
|
79704
80509
|
out.push(divider("ENV"));
|
|
79705
80510
|
out.push("");
|
|
79706
|
-
out.push(` ${
|
|
79707
|
-
out.push(` ${
|
|
79708
|
-
out.push(` ${
|
|
79709
|
-
out.push(` ${
|
|
79710
|
-
out.push(` ${
|
|
79711
|
-
out.push(` ${
|
|
79712
|
-
out.push(` ${
|
|
79713
|
-
out.push(` ${
|
|
79714
|
-
out.push(` ${
|
|
79715
|
-
out.push(` ${
|
|
79716
|
-
out.push(` ${
|
|
80511
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
|
|
80512
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_DEBUG")} print full stack traces on error (any value; unset to disable)`);
|
|
80513
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
|
|
80514
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_CONTROL_PLANE_URL")} override the MAS host (/v2/cli; task create uses /v2/tasks)`);
|
|
80515
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_API_URL")} legacy KLS host override (uses /api/cli; proxy/registry fallback)`);
|
|
80516
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_PROXY_URL")} override the model-proxy URL used by harness traffic (default https://api.v1.brainbaselabs.com)`);
|
|
80517
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL (default https://api.v1.brainbaselabs.com)`);
|
|
80518
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT; the only PAT control-plane commands accept (token.json is not read there)`);
|
|
80519
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
|
|
80520
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_NON_INTERACTIVE")} force non-interactive mode — skip/auto-default prompts (CI & agents)`);
|
|
80521
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_RUN_ENTRYPOINT")} =1 → agent pull executes the agent entrypoint (sandbox boots; or pass --run-entrypoint)`);
|
|
79717
80522
|
out.push("");
|
|
79718
|
-
out.push(` ${
|
|
79719
|
-
out.push(` ${
|
|
79720
|
-
out.push(` ${
|
|
79721
|
-
out.push(` ${
|
|
79722
|
-
out.push(` ${
|
|
79723
|
-
out.push(` ${
|
|
80523
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_MEMORY_MCP_URL")} override the built-in memory MCP host`);
|
|
80524
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_BROWSER_MCP_URL")} override the built-in browser MCP host`);
|
|
80525
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_SLACK_MCP_URL")} override the built-in Slack MCP host`);
|
|
80526
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_MEETING_MCP_URL")} override the built-in meeting MCP host`);
|
|
80527
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_GITHUB_MCP_URL")} override the built-in GitHub MCP host`);
|
|
80528
|
+
out.push(` ${import_picocolors52.default.dim("BRAINBASE_ORCHESTRATION_MCP_URL")} override the built-in orchestration MCP host`);
|
|
79724
80529
|
out.push("");
|
|
79725
80530
|
out.push(divider("HARNESSES"));
|
|
79726
80531
|
out.push("");
|
|
79727
|
-
out.push(` ${
|
|
79728
|
-
out.push(` ${
|
|
79729
|
-
out.push(` ${
|
|
80532
|
+
out.push(` ${import_picocolors52.default.dim("•")} ${import_picocolors52.default.bold("claude-code")} ${import_picocolors52.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
80533
|
+
out.push(` ${import_picocolors52.default.dim("•")} ${import_picocolors52.default.bold("codex")} ${import_picocolors52.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
|
|
80534
|
+
out.push(` ${import_picocolors52.default.dim("•")} ${import_picocolors52.default.bold("kafka")} ${import_picocolors52.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
79730
80535
|
out.push("");
|
|
79731
80536
|
console.log(out.join(`
|
|
79732
80537
|
`));
|
|
@@ -79751,7 +80556,13 @@ var VALUE_TAKING_FLAGS = new Set([
|
|
|
79751
80556
|
"--description",
|
|
79752
80557
|
"--schema",
|
|
79753
80558
|
"--from",
|
|
79754
|
-
"--to"
|
|
80559
|
+
"--to",
|
|
80560
|
+
"--bot-token",
|
|
80561
|
+
"--signing-secret",
|
|
80562
|
+
"--app-id",
|
|
80563
|
+
"--app-name",
|
|
80564
|
+
"--bot-name",
|
|
80565
|
+
"--bot-image-url"
|
|
79755
80566
|
]);
|
|
79756
80567
|
function isValueOfPriorFlag2(args, index) {
|
|
79757
80568
|
return index > 0 && VALUE_TAKING_FLAGS.has(args[index - 1]);
|
|
@@ -79872,13 +80683,13 @@ async function requireAuth(cmd) {
|
|
|
79872
80683
|
if (STORED_PAT_COMMANDS.has(cmd) && readToken())
|
|
79873
80684
|
return;
|
|
79874
80685
|
console.error("");
|
|
79875
|
-
console.error(` ${brandTint("◆")} ${
|
|
80686
|
+
console.error(` ${brandTint("◆")} ${import_picocolors52.default.bold("brainbase")}`);
|
|
79876
80687
|
console.error("");
|
|
79877
|
-
console.error(` ${
|
|
80688
|
+
console.error(` ${import_picocolors52.default.red("✗")} You need to sign in to use ${import_picocolors52.default.bold("brainbase " + cmd)}.`);
|
|
79878
80689
|
if (status.reason)
|
|
79879
|
-
console.error(` ${
|
|
80690
|
+
console.error(` ${import_picocolors52.default.dim(status.reason)}`);
|
|
79880
80691
|
console.error("");
|
|
79881
|
-
console.error(` Run ${
|
|
80692
|
+
console.error(` Run ${import_picocolors52.default.cyan("brainbase login")} to connect this device.`);
|
|
79882
80693
|
console.error("");
|
|
79883
80694
|
process14.exit(1);
|
|
79884
80695
|
}
|
|
@@ -79888,7 +80699,7 @@ async function main() {
|
|
|
79888
80699
|
const rawCwd = process14.cwd();
|
|
79889
80700
|
const cwd2 = (() => {
|
|
79890
80701
|
try {
|
|
79891
|
-
return
|
|
80702
|
+
return fs83.realpathSync(rawCwd);
|
|
79892
80703
|
} catch {
|
|
79893
80704
|
return rawCwd;
|
|
79894
80705
|
}
|
|
@@ -79937,6 +80748,12 @@ async function main() {
|
|
|
79937
80748
|
const noPushFlag = hasFlag2(sharedArgs, "--no-push");
|
|
79938
80749
|
const jsonFlag = hasFlag2(sharedArgs, "--json");
|
|
79939
80750
|
const acpFlag = hasFlag2(sharedArgs, "--acp");
|
|
80751
|
+
const botTokenFlag = getFlag(sharedArgs, "--bot-token");
|
|
80752
|
+
const signingSecretFlag = getFlag(sharedArgs, "--signing-secret");
|
|
80753
|
+
const appIdFlag = getFlag(sharedArgs, "--app-id");
|
|
80754
|
+
const appNameFlag = getFlag(sharedArgs, "--app-name");
|
|
80755
|
+
const botNameFlag = getFlag(sharedArgs, "--bot-name");
|
|
80756
|
+
const botImageUrlFlag = getFlag(sharedArgs, "--bot-image-url");
|
|
79940
80757
|
ensureSkillResolversRegistered();
|
|
79941
80758
|
await requireAuth(cmd);
|
|
79942
80759
|
try {
|
|
@@ -79950,7 +80767,7 @@ async function main() {
|
|
|
79950
80767
|
break;
|
|
79951
80768
|
}
|
|
79952
80769
|
case "whoami": {
|
|
79953
|
-
await runWhoami();
|
|
80770
|
+
await runWhoami({ json: jsonFlag });
|
|
79954
80771
|
break;
|
|
79955
80772
|
}
|
|
79956
80773
|
case "template": {
|
|
@@ -80020,7 +80837,13 @@ async function main() {
|
|
|
80020
80837
|
track,
|
|
80021
80838
|
force: forceFlag,
|
|
80022
80839
|
runEntrypoint: runEntrypointFlag,
|
|
80023
|
-
acp: acpFlag
|
|
80840
|
+
acp: acpFlag,
|
|
80841
|
+
botToken: botTokenFlag,
|
|
80842
|
+
signingSecret: signingSecretFlag,
|
|
80843
|
+
appId: appIdFlag,
|
|
80844
|
+
appName: appNameFlag,
|
|
80845
|
+
botName: botNameFlag,
|
|
80846
|
+
botImageUrl: botImageUrlFlag
|
|
80024
80847
|
});
|
|
80025
80848
|
break;
|
|
80026
80849
|
}
|
|
@@ -80079,10 +80902,10 @@ async function main() {
|
|
|
80079
80902
|
process14.exit(1);
|
|
80080
80903
|
}
|
|
80081
80904
|
} catch (err) {
|
|
80082
|
-
console.error(
|
|
80905
|
+
console.error(import_picocolors52.default.red(`
|
|
80083
80906
|
${err.message}`));
|
|
80084
80907
|
if (err instanceof ApiError && err.status === 401) {
|
|
80085
|
-
console.error(` Run ${
|
|
80908
|
+
console.error(` Run ${import_picocolors52.default.cyan("brainbase login")} to connect this device.`);
|
|
80086
80909
|
}
|
|
80087
80910
|
if (process14.env.BRAINBASE_DEBUG)
|
|
80088
80911
|
console.error(err.stack);
|