@brainbase-labs/cli 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +128 -49
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -36018,7 +36018,7 @@ function padStart(s, n) {
|
|
|
36018
36018
|
// package.json
|
|
36019
36019
|
var package_default = {
|
|
36020
36020
|
name: "@brainbase-labs/cli",
|
|
36021
|
-
version: "0.
|
|
36021
|
+
version: "0.30.0",
|
|
36022
36022
|
description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
|
|
36023
36023
|
type: "module",
|
|
36024
36024
|
bin: {
|
|
@@ -40969,7 +40969,7 @@ function acquireLock(lockFile, timeoutMs) {
|
|
|
40969
40969
|
function acquireAuthLock() {
|
|
40970
40970
|
const release = acquireLock(AUTH_LOCK_FILE, AUTH_LOCK_TIMEOUT_MS);
|
|
40971
40971
|
if (!release) {
|
|
40972
|
-
throw new Error(`Timed out waiting to update CLI authentication
|
|
40972
|
+
throw new Error(`Timed out waiting to update CLI authentication.${lockHolderState(AUTH_LOCK_FILE)} Retry, or remove ${AUTH_LOCK_FILE}`);
|
|
40973
40973
|
}
|
|
40974
40974
|
return release;
|
|
40975
40975
|
}
|
|
@@ -41021,10 +41021,44 @@ class AuthSessionChangedError extends Error {
|
|
|
41021
41021
|
this.name = "AuthSessionChangedError";
|
|
41022
41022
|
}
|
|
41023
41023
|
}
|
|
41024
|
+
function heldFor(lockFile) {
|
|
41025
|
+
try {
|
|
41026
|
+
const ms = Date.now() - fs6.statSync(lockFile).mtimeMs;
|
|
41027
|
+
if (!Number.isFinite(ms) || ms < 0)
|
|
41028
|
+
return "";
|
|
41029
|
+
if (ms < 60000)
|
|
41030
|
+
return ` Held for ${Math.round(ms / 1000)}s.`;
|
|
41031
|
+
if (ms < 3600000)
|
|
41032
|
+
return ` Held for ${Math.round(ms / 60000)}m.`;
|
|
41033
|
+
return ` Held for ${Math.round(ms / 3600000)}h.`;
|
|
41034
|
+
} catch {
|
|
41035
|
+
return "";
|
|
41036
|
+
}
|
|
41037
|
+
}
|
|
41038
|
+
function lockHolderState(lockFile) {
|
|
41039
|
+
let pid;
|
|
41040
|
+
try {
|
|
41041
|
+
pid = Number.parseInt(fs6.readFileSync(lockFile, "utf8").split(":")[0] ?? "", 10);
|
|
41042
|
+
} catch {
|
|
41043
|
+
return "";
|
|
41044
|
+
}
|
|
41045
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
41046
|
+
return "";
|
|
41047
|
+
const age = heldFor(lockFile);
|
|
41048
|
+
try {
|
|
41049
|
+
process.kill(pid, 0);
|
|
41050
|
+
return ` A process with pid ${pid} is running, so this may clear on its own — but pids get reused, so if that is not a brainbase command the lock is stale.${age}`;
|
|
41051
|
+
} catch (error) {
|
|
41052
|
+
if (error.code === "EPERM") {
|
|
41053
|
+
return ` A process with pid ${pid} is running, so this may clear on its own — but pids get reused, so if that is not a brainbase command the lock is stale.${age}`;
|
|
41054
|
+
}
|
|
41055
|
+
return ` The process that held it (pid ${pid}) is gone, so this lock is stale and will not clear itself.${age}`;
|
|
41056
|
+
}
|
|
41057
|
+
}
|
|
41024
41058
|
|
|
41025
41059
|
class AuthRefreshLockTimeoutError extends Error {
|
|
41026
41060
|
constructor() {
|
|
41027
|
-
super(`Timed out waiting to refresh CLI authentication
|
|
41061
|
+
super(`Timed out waiting to refresh CLI authentication.${lockHolderState(REFRESH_LOCK_FILE)} Retry, or remove ${REFRESH_LOCK_FILE}`);
|
|
41028
41062
|
this.name = "AuthRefreshLockTimeoutError";
|
|
41029
41063
|
}
|
|
41030
41064
|
}
|
|
@@ -53890,7 +53924,7 @@ var StoredTokenSchema = exports_external.object({
|
|
|
53890
53924
|
function withTokenLock(operation) {
|
|
53891
53925
|
const release = acquireLock(TOKEN_LOCK_FILE, TOKEN_LOCK_TIMEOUT_MS);
|
|
53892
53926
|
if (!release) {
|
|
53893
|
-
throw new Error(`Timed out waiting to update the local CLI token
|
|
53927
|
+
throw new Error(`Timed out waiting to update the local CLI token.${lockHolderState(TOKEN_LOCK_FILE)} Retry, or remove ${TOKEN_LOCK_FILE}`);
|
|
53894
53928
|
}
|
|
53895
53929
|
try {
|
|
53896
53930
|
return operation();
|
|
@@ -62374,14 +62408,16 @@ var McpEntrySchema = exports_external.object({
|
|
|
62374
62408
|
args: exports_external.array(exports_external.string()).optional(),
|
|
62375
62409
|
env: exports_external.record(exports_external.string()).optional(),
|
|
62376
62410
|
headers: exports_external.record(exports_external.string()).optional(),
|
|
62377
|
-
is_enabled: exports_external.boolean().optional()
|
|
62411
|
+
is_enabled: exports_external.boolean().optional(),
|
|
62412
|
+
runtime_meta: exports_external.record(exports_external.unknown()).optional()
|
|
62378
62413
|
});
|
|
62379
62414
|
var CapabilitiesSchema = exports_external.object({
|
|
62380
62415
|
memory: exports_external.boolean().optional(),
|
|
62381
62416
|
browser: exports_external.boolean().optional(),
|
|
62382
62417
|
slack: exports_external.boolean().optional(),
|
|
62383
62418
|
meeting: exports_external.boolean().optional(),
|
|
62384
|
-
github: exports_external.boolean().optional()
|
|
62419
|
+
github: exports_external.boolean().optional(),
|
|
62420
|
+
linear: exports_external.boolean().optional()
|
|
62385
62421
|
});
|
|
62386
62422
|
var EvalOutputShape = exports_external.enum(["binary", "rating", "classification"]);
|
|
62387
62423
|
var EVAL_SLUG_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
@@ -63547,6 +63583,39 @@ function buildGithubMcpComponent(scope) {
|
|
|
63547
63583
|
};
|
|
63548
63584
|
}
|
|
63549
63585
|
|
|
63586
|
+
// src/core/linear-mcp.ts
|
|
63587
|
+
var DEFAULT_LINEAR_MCP_BASE = "https://brainbase-linear-mcp.onrender.com";
|
|
63588
|
+
var LINEAR_MCP_SLUG = "brainbase-linear";
|
|
63589
|
+
function linearMcpBaseUrl() {
|
|
63590
|
+
const envOverride = process.env.BRAINBASE_LINEAR_MCP_URL;
|
|
63591
|
+
if (envOverride)
|
|
63592
|
+
return envOverride.replace(/\/+$/, "");
|
|
63593
|
+
return DEFAULT_LINEAR_MCP_BASE;
|
|
63594
|
+
}
|
|
63595
|
+
function linearMcpUrl() {
|
|
63596
|
+
return `${linearMcpBaseUrl()}/t/\${BRAINBASE_THREAD_ID}/mcp`;
|
|
63597
|
+
}
|
|
63598
|
+
function linearMcpPayload() {
|
|
63599
|
+
return {
|
|
63600
|
+
url: linearMcpUrl(),
|
|
63601
|
+
headers: {
|
|
63602
|
+
Authorization: "Bearer ${BRAINBASE_TOKEN}"
|
|
63603
|
+
}
|
|
63604
|
+
};
|
|
63605
|
+
}
|
|
63606
|
+
function buildLinearMcpComponent(scope) {
|
|
63607
|
+
return {
|
|
63608
|
+
type: "mcp",
|
|
63609
|
+
slug: LINEAR_MCP_SLUG,
|
|
63610
|
+
scope,
|
|
63611
|
+
rootDir: "",
|
|
63612
|
+
description: "This agent's Linear connector (read and update issues, comment, and " + "report progress on delegated work). Scoped to this agent only.",
|
|
63613
|
+
meta: { mcp: linearMcpPayload() },
|
|
63614
|
+
payload: linearMcpPayload(),
|
|
63615
|
+
checksum: "builtin:brainbase-linear:v1"
|
|
63616
|
+
};
|
|
63617
|
+
}
|
|
63618
|
+
|
|
63550
63619
|
// src/core/browser-mcp.ts
|
|
63551
63620
|
var DEFAULT_BROWSER_MCP_BASE = "https://brainbase-browser-mcp.onrender.com";
|
|
63552
63621
|
var BROWSER_MCP_SLUG = "brainbase-browser";
|
|
@@ -63587,7 +63656,8 @@ function capabilitiesFromAgent(agent) {
|
|
|
63587
63656
|
browser: agent.browser_enabled !== false,
|
|
63588
63657
|
slack: agent.slack_connected === true,
|
|
63589
63658
|
meeting: agent.meeting_connected === true,
|
|
63590
|
-
github: agent.github_connected === true
|
|
63659
|
+
github: agent.github_connected === true,
|
|
63660
|
+
linear: agent.linear_connected === true
|
|
63591
63661
|
};
|
|
63592
63662
|
}
|
|
63593
63663
|
function capabilitiesFromManifest(manifest) {
|
|
@@ -63597,7 +63667,8 @@ function capabilitiesFromManifest(manifest) {
|
|
|
63597
63667
|
browser: c2.browser !== false,
|
|
63598
63668
|
slack: c2.slack === true,
|
|
63599
63669
|
meeting: c2.meeting === true,
|
|
63600
|
-
github: c2.github === true
|
|
63670
|
+
github: c2.github === true,
|
|
63671
|
+
linear: c2.linear === true
|
|
63601
63672
|
};
|
|
63602
63673
|
}
|
|
63603
63674
|
function resolveBuiltinMcps(input) {
|
|
@@ -63608,7 +63679,8 @@ function resolveBuiltinMcps(input) {
|
|
|
63608
63679
|
{ slug: BROWSER_MCP_SLUG, enabled: caps.browser, build: buildBrowserMcpComponent },
|
|
63609
63680
|
{ slug: SLACK_MCP_SLUG, enabled: caps.slack, build: buildSlackMcpComponent },
|
|
63610
63681
|
{ slug: MEETING_MCP_SLUG, enabled: caps.meeting, build: buildMeetingMcpComponent },
|
|
63611
|
-
{ slug: GITHUB_MCP_SLUG, enabled: caps.github, build: buildGithubMcpComponent }
|
|
63682
|
+
{ slug: GITHUB_MCP_SLUG, enabled: caps.github, build: buildGithubMcpComponent },
|
|
63683
|
+
{ slug: LINEAR_MCP_SLUG, enabled: caps.linear, build: buildLinearMcpComponent }
|
|
63612
63684
|
];
|
|
63613
63685
|
const install = [];
|
|
63614
63686
|
const removeSlugs = [];
|
|
@@ -64374,7 +64446,7 @@ function diffAgentMeta(manifestMeta, lockMeta, cloudMeta) {
|
|
|
64374
64446
|
};
|
|
64375
64447
|
}
|
|
64376
64448
|
var WRITABLE_CAPABILITIES = ["memory", "browser"];
|
|
64377
|
-
var MIRRORED_CAPABILITIES = ["slack", "meeting", "github"];
|
|
64449
|
+
var MIRRORED_CAPABILITIES = ["slack", "meeting", "github", "linear"];
|
|
64378
64450
|
function manifestConfigState(manifest) {
|
|
64379
64451
|
return {
|
|
64380
64452
|
...manifest.machine_kind !== undefined ? { machine_kind: manifest.machine_kind } : {},
|
|
@@ -64398,7 +64470,8 @@ function staleConnectionMirrors(manifest, cloud) {
|
|
|
64398
64470
|
const actualByName = {
|
|
64399
64471
|
slack: cloud.slack_connected,
|
|
64400
64472
|
meeting: cloud.meeting_connected,
|
|
64401
|
-
github: cloud.github_connected
|
|
64473
|
+
github: cloud.github_connected,
|
|
64474
|
+
linear: cloud.linear_connected
|
|
64402
64475
|
};
|
|
64403
64476
|
const stale = [];
|
|
64404
64477
|
for (const name of MIRRORED_CAPABILITIES) {
|
|
@@ -64561,6 +64634,41 @@ function capabilityBaselineAfterPush(cloudAgent, previous, diff2) {
|
|
|
64561
64634
|
return out;
|
|
64562
64635
|
}
|
|
64563
64636
|
|
|
64637
|
+
// src/core/mcp-merge.ts
|
|
64638
|
+
var RUNTIME_META_PREFIX = "runtime_";
|
|
64639
|
+
function runtimeMetaFromComponent(component) {
|
|
64640
|
+
const meta = component.meta ?? {};
|
|
64641
|
+
const carried = {};
|
|
64642
|
+
for (const [key2, value] of Object.entries(meta)) {
|
|
64643
|
+
if (key2.startsWith(RUNTIME_META_PREFIX) && value !== undefined) {
|
|
64644
|
+
carried[key2] = value;
|
|
64645
|
+
}
|
|
64646
|
+
}
|
|
64647
|
+
return Object.keys(carried).length > 0 ? carried : undefined;
|
|
64648
|
+
}
|
|
64649
|
+
function mcpEntriesFromCloudComponents(components) {
|
|
64650
|
+
return components.filter((c2) => c2.type === "mcp").map((c2) => {
|
|
64651
|
+
const payload = (c2.meta ?? {}).mcp ?? {};
|
|
64652
|
+
const entry = { name: c2.slug };
|
|
64653
|
+
if (typeof payload.url === "string")
|
|
64654
|
+
entry.url = payload.url;
|
|
64655
|
+
if (typeof payload.command === "string")
|
|
64656
|
+
entry.command = payload.command;
|
|
64657
|
+
if (Array.isArray(payload.args))
|
|
64658
|
+
entry.args = payload.args.map(String);
|
|
64659
|
+
if (payload.env && typeof payload.env === "object")
|
|
64660
|
+
entry.env = payload.env;
|
|
64661
|
+
if (payload.headers && typeof payload.headers === "object")
|
|
64662
|
+
entry.headers = payload.headers;
|
|
64663
|
+
if (typeof payload.is_enabled === "boolean")
|
|
64664
|
+
entry.is_enabled = payload.is_enabled;
|
|
64665
|
+
const runtimeMeta = runtimeMetaFromComponent(c2);
|
|
64666
|
+
if (runtimeMeta)
|
|
64667
|
+
entry.runtime_meta = runtimeMeta;
|
|
64668
|
+
return entry;
|
|
64669
|
+
});
|
|
64670
|
+
}
|
|
64671
|
+
|
|
64564
64672
|
// src/core/secrets-env.ts
|
|
64565
64673
|
import path78 from "node:path";
|
|
64566
64674
|
import fs71 from "node:fs";
|
|
@@ -65411,23 +65519,7 @@ function mergeManifest(cwd2, prev, cloud, cloudAgent, harness, localOnly = {}, s
|
|
|
65411
65519
|
content
|
|
65412
65520
|
};
|
|
65413
65521
|
});
|
|
65414
|
-
const mcp = cloud.components
|
|
65415
|
-
const payload = (c2.meta ?? {}).mcp ?? {};
|
|
65416
|
-
const entry = { name: c2.slug };
|
|
65417
|
-
if (typeof payload.url === "string")
|
|
65418
|
-
entry.url = payload.url;
|
|
65419
|
-
if (typeof payload.command === "string")
|
|
65420
|
-
entry.command = payload.command;
|
|
65421
|
-
if (Array.isArray(payload.args))
|
|
65422
|
-
entry.args = payload.args.map(String);
|
|
65423
|
-
if (payload.env && typeof payload.env === "object")
|
|
65424
|
-
entry.env = payload.env;
|
|
65425
|
-
if (payload.headers && typeof payload.headers === "object")
|
|
65426
|
-
entry.headers = payload.headers;
|
|
65427
|
-
if (typeof payload.is_enabled === "boolean")
|
|
65428
|
-
entry.is_enabled = payload.is_enabled;
|
|
65429
|
-
return entry;
|
|
65430
|
-
});
|
|
65522
|
+
const mcp = mcpEntriesFromCloudComponents(cloud.components);
|
|
65431
65523
|
const evals = evalsFromCloudComponents(cloud.components);
|
|
65432
65524
|
const caps = capabilitiesFromAgent(cloudAgent);
|
|
65433
65525
|
const machineKind = cloudAgent.machine_kind ?? prev?.machine_kind;
|
|
@@ -65462,7 +65554,8 @@ function mergeManifest(cwd2, prev, cloud, cloudAgent, harness, localOnly = {}, s
|
|
|
65462
65554
|
browser: caps.browser,
|
|
65463
65555
|
slack: caps.slack,
|
|
65464
65556
|
meeting: caps.meeting,
|
|
65465
|
-
github: caps.github
|
|
65557
|
+
github: caps.github,
|
|
65558
|
+
linear: caps.linear
|
|
65466
65559
|
}
|
|
65467
65560
|
};
|
|
65468
65561
|
}
|
|
@@ -65847,7 +65940,7 @@ async function buildOutgoingComponents(cwd2, manifest, cloud, resolvedVersions)
|
|
|
65847
65940
|
slug: entry.name,
|
|
65848
65941
|
hash: "",
|
|
65849
65942
|
files: [],
|
|
65850
|
-
meta: { mcp: payload }
|
|
65943
|
+
meta: { ...entry.runtime_meta ?? {}, mcp: payload }
|
|
65851
65944
|
});
|
|
65852
65945
|
}
|
|
65853
65946
|
return out;
|
|
@@ -69010,23 +69103,7 @@ function buildManifestFromCloud(cloud, agent, localOnly = {}) {
|
|
|
69010
69103
|
return { source: `registry:${c2.slug}` };
|
|
69011
69104
|
});
|
|
69012
69105
|
const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
|
|
69013
|
-
const mcp = cloud.components
|
|
69014
|
-
const payload = (c2.meta ?? {}).mcp ?? {};
|
|
69015
|
-
const entry = { name: c2.slug };
|
|
69016
|
-
if (typeof payload.url === "string")
|
|
69017
|
-
entry.url = payload.url;
|
|
69018
|
-
if (typeof payload.command === "string")
|
|
69019
|
-
entry.command = payload.command;
|
|
69020
|
-
if (Array.isArray(payload.args))
|
|
69021
|
-
entry.args = payload.args.map(String);
|
|
69022
|
-
if (payload.env && typeof payload.env === "object")
|
|
69023
|
-
entry.env = payload.env;
|
|
69024
|
-
if (payload.headers && typeof payload.headers === "object")
|
|
69025
|
-
entry.headers = payload.headers;
|
|
69026
|
-
if (typeof payload.is_enabled === "boolean")
|
|
69027
|
-
entry.is_enabled = payload.is_enabled;
|
|
69028
|
-
return entry;
|
|
69029
|
-
});
|
|
69106
|
+
const mcp = mcpEntriesFromCloudComponents(cloud.components);
|
|
69030
69107
|
const playbooks = cloud.components.filter((c2) => c2.type === "playbook").map((c2) => {
|
|
69031
69108
|
const raw = c2.files[0]?.content ?? "";
|
|
69032
69109
|
const { frontmatter } = stripPlaybookFrontmatter(raw);
|
|
@@ -69066,7 +69143,8 @@ function buildManifestFromCloud(cloud, agent, localOnly = {}) {
|
|
|
69066
69143
|
browser: caps.browser,
|
|
69067
69144
|
slack: caps.slack,
|
|
69068
69145
|
meeting: caps.meeting,
|
|
69069
|
-
github: caps.github
|
|
69146
|
+
github: caps.github,
|
|
69147
|
+
linear: caps.linear
|
|
69070
69148
|
}
|
|
69071
69149
|
};
|
|
69072
69150
|
}
|
|
@@ -89014,6 +89092,7 @@ function help() {
|
|
|
89014
89092
|
out.push(` ${import_picocolors61.default.dim("BRAINBASE_SLACK_MCP_URL")} override the built-in Slack MCP host`);
|
|
89015
89093
|
out.push(` ${import_picocolors61.default.dim("BRAINBASE_MEETING_MCP_URL")} override the built-in meeting MCP host`);
|
|
89016
89094
|
out.push(` ${import_picocolors61.default.dim("BRAINBASE_GITHUB_MCP_URL")} override the built-in GitHub MCP host`);
|
|
89095
|
+
out.push(` ${import_picocolors61.default.dim("BRAINBASE_LINEAR_MCP_URL")} override the built-in Linear MCP host`);
|
|
89017
89096
|
out.push(` ${import_picocolors61.default.dim("BRAINBASE_ORCHESTRATION_MCP_URL")} override the built-in orchestration MCP host`);
|
|
89018
89097
|
out.push("");
|
|
89019
89098
|
out.push(divider("HARNESSES"));
|
|
@@ -89253,8 +89332,8 @@ async function main() {
|
|
|
89253
89332
|
const limitFlag = Number.isInteger(limitParsed) && limitParsed >= 1 && limitParsed <= 200 ? limitParsed : undefined;
|
|
89254
89333
|
const archivedFlag = hasFlag2(sharedArgs, "--archived");
|
|
89255
89334
|
ensureSkillResolversRegistered();
|
|
89256
|
-
await requireAuth(cmd);
|
|
89257
89335
|
try {
|
|
89336
|
+
await requireAuth(cmd);
|
|
89258
89337
|
switch (cmd) {
|
|
89259
89338
|
case "login": {
|
|
89260
89339
|
await runLogin(cwd2, { web });
|