@brainbase-labs/cli 0.9.0 → 0.10.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 +299 -137
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -29449,7 +29449,7 @@ function padStart(s, n) {
|
|
|
29449
29449
|
// package.json
|
|
29450
29450
|
var package_default = {
|
|
29451
29451
|
name: "@brainbase-labs/cli",
|
|
29452
|
-
version: "0.
|
|
29452
|
+
version: "0.10.0",
|
|
29453
29453
|
description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
|
|
29454
29454
|
type: "module",
|
|
29455
29455
|
bin: {
|
|
@@ -29921,6 +29921,73 @@ function scopePaths(cwd, scope) {
|
|
|
29921
29921
|
return scope === "global" ? globalPaths() : projectPaths(cwd);
|
|
29922
29922
|
}
|
|
29923
29923
|
|
|
29924
|
+
// src/harnesses/claude-code/settings.ts
|
|
29925
|
+
function readSettings(file) {
|
|
29926
|
+
return readJsonOr(file, {});
|
|
29927
|
+
}
|
|
29928
|
+
function writeSettings(file, settings) {
|
|
29929
|
+
writeJson(file, settings);
|
|
29930
|
+
}
|
|
29931
|
+
function setMcpServer(file, name, entry) {
|
|
29932
|
+
const s = readSettings(file);
|
|
29933
|
+
if (!s.mcpServers)
|
|
29934
|
+
s.mcpServers = {};
|
|
29935
|
+
s.mcpServers[name] = entry;
|
|
29936
|
+
writeSettings(file, s);
|
|
29937
|
+
}
|
|
29938
|
+
function removeMcpServer(file, name) {
|
|
29939
|
+
if (!exists(file))
|
|
29940
|
+
return;
|
|
29941
|
+
const s = readSettings(file);
|
|
29942
|
+
if (s.mcpServers && name in s.mcpServers) {
|
|
29943
|
+
delete s.mcpServers[name];
|
|
29944
|
+
writeSettings(file, s);
|
|
29945
|
+
}
|
|
29946
|
+
}
|
|
29947
|
+
function getMcpServer(file, name) {
|
|
29948
|
+
const s = readSettings(file);
|
|
29949
|
+
return s.mcpServers?.[name];
|
|
29950
|
+
}
|
|
29951
|
+
function listMcpServers(file) {
|
|
29952
|
+
return readSettings(file).mcpServers ?? {};
|
|
29953
|
+
}
|
|
29954
|
+
function normalizeMcpPayload(payload) {
|
|
29955
|
+
const out = { ...payload };
|
|
29956
|
+
delete out.is_enabled;
|
|
29957
|
+
const hasUrl = typeof out.url === "string" && out.url.length > 0;
|
|
29958
|
+
const hasCommand = typeof out.command === "string" && out.command.length > 0;
|
|
29959
|
+
if (!out.type) {
|
|
29960
|
+
if (hasUrl)
|
|
29961
|
+
out.type = "http";
|
|
29962
|
+
else if (hasCommand)
|
|
29963
|
+
out.type = "stdio";
|
|
29964
|
+
}
|
|
29965
|
+
if (out.type === "http" || out.type === "sse") {
|
|
29966
|
+
if (Array.isArray(out.args) && out.args.length === 0)
|
|
29967
|
+
delete out.args;
|
|
29968
|
+
if (out.env && typeof out.env === "object" && Object.keys(out.env).length === 0) {
|
|
29969
|
+
delete out.env;
|
|
29970
|
+
}
|
|
29971
|
+
if (out.headers && typeof out.headers === "object" && Object.keys(out.headers).length === 0) {
|
|
29972
|
+
delete out.headers;
|
|
29973
|
+
}
|
|
29974
|
+
}
|
|
29975
|
+
if (out.type === "stdio") {
|
|
29976
|
+
delete out.url;
|
|
29977
|
+
delete out.headers;
|
|
29978
|
+
}
|
|
29979
|
+
return out;
|
|
29980
|
+
}
|
|
29981
|
+
function listMcpServersFromMcpJson(file) {
|
|
29982
|
+
return readJsonOr(file, {}).mcpServers ?? {};
|
|
29983
|
+
}
|
|
29984
|
+
function listMcpServersFromClaudeJson(file, projectKey) {
|
|
29985
|
+
const data = readJsonOr(file, {});
|
|
29986
|
+
if (projectKey)
|
|
29987
|
+
return data.projects?.[projectKey]?.mcpServers ?? {};
|
|
29988
|
+
return data.mcpServers ?? {};
|
|
29989
|
+
}
|
|
29990
|
+
|
|
29924
29991
|
// src/harnesses/claude-code/inventory.ts
|
|
29925
29992
|
import fs4 from "node:fs";
|
|
29926
29993
|
import path6 from "node:path";
|
|
@@ -33961,73 +34028,6 @@ function manifestSourceForPack(source) {
|
|
|
33961
34028
|
return source.type === "local" ? { type: "inline" } : source;
|
|
33962
34029
|
}
|
|
33963
34030
|
|
|
33964
|
-
// src/harnesses/claude-code/settings.ts
|
|
33965
|
-
function readSettings(file) {
|
|
33966
|
-
return readJsonOr(file, {});
|
|
33967
|
-
}
|
|
33968
|
-
function writeSettings(file, settings) {
|
|
33969
|
-
writeJson(file, settings);
|
|
33970
|
-
}
|
|
33971
|
-
function setMcpServer(file, name, entry) {
|
|
33972
|
-
const s = readSettings(file);
|
|
33973
|
-
if (!s.mcpServers)
|
|
33974
|
-
s.mcpServers = {};
|
|
33975
|
-
s.mcpServers[name] = entry;
|
|
33976
|
-
writeSettings(file, s);
|
|
33977
|
-
}
|
|
33978
|
-
function removeMcpServer(file, name) {
|
|
33979
|
-
if (!exists(file))
|
|
33980
|
-
return;
|
|
33981
|
-
const s = readSettings(file);
|
|
33982
|
-
if (s.mcpServers && name in s.mcpServers) {
|
|
33983
|
-
delete s.mcpServers[name];
|
|
33984
|
-
writeSettings(file, s);
|
|
33985
|
-
}
|
|
33986
|
-
}
|
|
33987
|
-
function getMcpServer(file, name) {
|
|
33988
|
-
const s = readSettings(file);
|
|
33989
|
-
return s.mcpServers?.[name];
|
|
33990
|
-
}
|
|
33991
|
-
function listMcpServers(file) {
|
|
33992
|
-
return readSettings(file).mcpServers ?? {};
|
|
33993
|
-
}
|
|
33994
|
-
function normalizeMcpPayload(payload) {
|
|
33995
|
-
const out = { ...payload };
|
|
33996
|
-
delete out.is_enabled;
|
|
33997
|
-
const hasUrl = typeof out.url === "string" && out.url.length > 0;
|
|
33998
|
-
const hasCommand = typeof out.command === "string" && out.command.length > 0;
|
|
33999
|
-
if (!out.type) {
|
|
34000
|
-
if (hasUrl)
|
|
34001
|
-
out.type = "http";
|
|
34002
|
-
else if (hasCommand)
|
|
34003
|
-
out.type = "stdio";
|
|
34004
|
-
}
|
|
34005
|
-
if (out.type === "http" || out.type === "sse") {
|
|
34006
|
-
if (Array.isArray(out.args) && out.args.length === 0)
|
|
34007
|
-
delete out.args;
|
|
34008
|
-
if (out.env && typeof out.env === "object" && Object.keys(out.env).length === 0) {
|
|
34009
|
-
delete out.env;
|
|
34010
|
-
}
|
|
34011
|
-
if (out.headers && typeof out.headers === "object" && Object.keys(out.headers).length === 0) {
|
|
34012
|
-
delete out.headers;
|
|
34013
|
-
}
|
|
34014
|
-
}
|
|
34015
|
-
if (out.type === "stdio") {
|
|
34016
|
-
delete out.url;
|
|
34017
|
-
delete out.headers;
|
|
34018
|
-
}
|
|
34019
|
-
return out;
|
|
34020
|
-
}
|
|
34021
|
-
function listMcpServersFromMcpJson(file) {
|
|
34022
|
-
return readJsonOr(file, {}).mcpServers ?? {};
|
|
34023
|
-
}
|
|
34024
|
-
function listMcpServersFromClaudeJson(file, projectKey) {
|
|
34025
|
-
const data = readJsonOr(file, {});
|
|
34026
|
-
if (projectKey)
|
|
34027
|
-
return data.projects?.[projectKey]?.mcpServers ?? {};
|
|
34028
|
-
return data.mcpServers ?? {};
|
|
34029
|
-
}
|
|
34030
|
-
|
|
34031
34031
|
// src/harnesses/claude-code/inventory.ts
|
|
34032
34032
|
function firstLine(file, max = 200) {
|
|
34033
34033
|
try {
|
|
@@ -35070,6 +35070,11 @@ var claudeCode = {
|
|
|
35070
35070
|
async function installClaudeCodeWithCtx(components, opts, templateName) {
|
|
35071
35071
|
return installClaudeCode(components, opts, { templateName });
|
|
35072
35072
|
}
|
|
35073
|
+
function removeClaudeCodeMcp(slugs, opts) {
|
|
35074
|
+
const { mcpStore } = scopePaths(opts.cwd, opts.scope);
|
|
35075
|
+
for (const slug of slugs)
|
|
35076
|
+
removeMcpServer(mcpStore, slug);
|
|
35077
|
+
}
|
|
35073
35078
|
|
|
35074
35079
|
// src/harnesses/codex/paths.ts
|
|
35075
35080
|
import path13 from "node:path";
|
|
@@ -35101,10 +35106,6 @@ function isBundledSkillDir(name) {
|
|
|
35101
35106
|
return name === ".system" || name.startsWith(".");
|
|
35102
35107
|
}
|
|
35103
35108
|
|
|
35104
|
-
// src/harnesses/codex/inventory.ts
|
|
35105
|
-
import fs12 from "node:fs";
|
|
35106
|
-
import path15 from "node:path";
|
|
35107
|
-
|
|
35108
35109
|
// src/harnesses/codex/config-toml.ts
|
|
35109
35110
|
import fs11 from "node:fs";
|
|
35110
35111
|
|
|
@@ -36269,6 +36270,8 @@ function listMcpServers2(file) {
|
|
|
36269
36270
|
}
|
|
36270
36271
|
|
|
36271
36272
|
// src/harnesses/codex/inventory.ts
|
|
36273
|
+
import fs12 from "node:fs";
|
|
36274
|
+
import path15 from "node:path";
|
|
36272
36275
|
function firstLine2(file, max = 200) {
|
|
36273
36276
|
try {
|
|
36274
36277
|
const head = fs12.readFileSync(file, "utf8").slice(0, 2000);
|
|
@@ -36882,6 +36885,11 @@ var codex = {
|
|
|
36882
36885
|
async function installCodexWithCtx(components, opts, templateName) {
|
|
36883
36886
|
return installCodex(components, opts, { templateName });
|
|
36884
36887
|
}
|
|
36888
|
+
function removeCodexMcp(slugs, opts) {
|
|
36889
|
+
const { config } = scopePaths2(opts.cwd, opts.scope);
|
|
36890
|
+
for (const slug of slugs)
|
|
36891
|
+
removeMcpServer2(config, slug);
|
|
36892
|
+
}
|
|
36885
36893
|
|
|
36886
36894
|
// src/harnesses/kafka/paths.ts
|
|
36887
36895
|
import path19 from "node:path";
|
|
@@ -36919,10 +36927,6 @@ function scopePaths3(cwd, scope) {
|
|
|
36919
36927
|
return scope === "global" ? globalPaths3() : projectPaths3(cwd);
|
|
36920
36928
|
}
|
|
36921
36929
|
|
|
36922
|
-
// src/harnesses/kafka/inventory.ts
|
|
36923
|
-
import fs15 from "node:fs";
|
|
36924
|
-
import path20 from "node:path";
|
|
36925
|
-
|
|
36926
36930
|
// src/harnesses/kafka/settings.ts
|
|
36927
36931
|
function readSettings2(file) {
|
|
36928
36932
|
return readJsonOr(file, {});
|
|
@@ -36972,6 +36976,22 @@ function setMcpServer3(file, name, entry) {
|
|
|
36972
36976
|
}
|
|
36973
36977
|
writeSettings2(file, s);
|
|
36974
36978
|
}
|
|
36979
|
+
function removeMcpServer3(file, name) {
|
|
36980
|
+
if (!exists(file))
|
|
36981
|
+
return;
|
|
36982
|
+
const s = readSettings2(file);
|
|
36983
|
+
const raw = s.mcp_servers ?? s.mcpServers;
|
|
36984
|
+
if (!raw)
|
|
36985
|
+
return;
|
|
36986
|
+
if (Array.isArray(raw)) {
|
|
36987
|
+
s.mcp_servers = raw.filter((e2) => e2.name !== name);
|
|
36988
|
+
} else {
|
|
36989
|
+
delete raw[name];
|
|
36990
|
+
s.mcp_servers = raw;
|
|
36991
|
+
}
|
|
36992
|
+
delete s.mcpServers;
|
|
36993
|
+
writeSettings2(file, s);
|
|
36994
|
+
}
|
|
36975
36995
|
function normalizeMcpPayload2(payload) {
|
|
36976
36996
|
const out = { ...payload };
|
|
36977
36997
|
delete out.is_enabled;
|
|
@@ -37001,6 +37021,8 @@ function normalizeMcpPayload2(payload) {
|
|
|
37001
37021
|
}
|
|
37002
37022
|
|
|
37003
37023
|
// src/harnesses/kafka/inventory.ts
|
|
37024
|
+
import fs15 from "node:fs";
|
|
37025
|
+
import path20 from "node:path";
|
|
37004
37026
|
function firstLine3(file, max = 200) {
|
|
37005
37027
|
try {
|
|
37006
37028
|
const head = fs15.readFileSync(file, "utf8").slice(0, 2000);
|
|
@@ -37650,6 +37672,11 @@ var kafka = {
|
|
|
37650
37672
|
async function installKafkaWithCtx(components, opts, templateName) {
|
|
37651
37673
|
return installKafka(components, opts, { templateName });
|
|
37652
37674
|
}
|
|
37675
|
+
function removeKafkaMcp(slugs, opts) {
|
|
37676
|
+
const { mcpStore } = scopePaths3(opts.cwd, opts.scope);
|
|
37677
|
+
for (const slug of slugs)
|
|
37678
|
+
removeMcpServer3(mcpStore, slug);
|
|
37679
|
+
}
|
|
37653
37680
|
|
|
37654
37681
|
// src/harnesses/index.ts
|
|
37655
37682
|
var adapters = [claudeCode, codex, kafka];
|
|
@@ -37679,6 +37706,17 @@ async function detectHarnesses(cwd) {
|
|
|
37679
37706
|
}
|
|
37680
37707
|
return out;
|
|
37681
37708
|
}
|
|
37709
|
+
function runHarnessRemoveMcp(harnessId, slugs, opts) {
|
|
37710
|
+
if (slugs.length === 0)
|
|
37711
|
+
return;
|
|
37712
|
+
const canonical = normalizeHarnessId(harnessId);
|
|
37713
|
+
if (canonical === "claude-code")
|
|
37714
|
+
return removeClaudeCodeMcp(slugs, opts);
|
|
37715
|
+
if (canonical === "codex")
|
|
37716
|
+
return removeCodexMcp(slugs, opts);
|
|
37717
|
+
if (canonical === "kafka")
|
|
37718
|
+
return removeKafkaMcp(slugs, opts);
|
|
37719
|
+
}
|
|
37682
37720
|
|
|
37683
37721
|
// src/core/registry.ts
|
|
37684
37722
|
import fs18 from "node:fs";
|
|
@@ -48632,6 +48670,8 @@ async function runRemove(cwd2, args) {
|
|
|
48632
48670
|
if (c2.type === "mcp" && c2.settingsFile && c2.embeddedKey) {
|
|
48633
48671
|
if (inst.harness === "codex")
|
|
48634
48672
|
removeMcpServer2(c2.settingsFile, c2.embeddedKey);
|
|
48673
|
+
else if (inst.harness === "kafka")
|
|
48674
|
+
removeMcpServer3(c2.settingsFile, c2.embeddedKey);
|
|
48635
48675
|
else
|
|
48636
48676
|
removeMcpServer(c2.settingsFile, c2.embeddedKey);
|
|
48637
48677
|
} else if (c2.type === "instruction") {
|
|
@@ -51098,6 +51138,11 @@ var McpEntrySchema = exports_external.object({
|
|
|
51098
51138
|
headers: exports_external.record(exports_external.string()).optional(),
|
|
51099
51139
|
is_enabled: exports_external.boolean().optional()
|
|
51100
51140
|
});
|
|
51141
|
+
var CapabilitiesSchema = exports_external.object({
|
|
51142
|
+
memory: exports_external.boolean().optional(),
|
|
51143
|
+
browser: exports_external.boolean().optional(),
|
|
51144
|
+
slack: exports_external.boolean().optional()
|
|
51145
|
+
});
|
|
51101
51146
|
var AgentManifestSchema = exports_external.object({
|
|
51102
51147
|
schema: exports_external.literal(1),
|
|
51103
51148
|
id: exports_external.string().min(1).optional(),
|
|
@@ -51108,6 +51153,7 @@ var AgentManifestSchema = exports_external.object({
|
|
|
51108
51153
|
playbooks: exports_external.array(PlaybookSchema).default([]),
|
|
51109
51154
|
skills: exports_external.array(SkillEntrySchema).default([]),
|
|
51110
51155
|
mcp: exports_external.array(McpEntrySchema).default([]),
|
|
51156
|
+
capabilities: CapabilitiesSchema.optional(),
|
|
51111
51157
|
commands: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
51112
51158
|
hooks: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
51113
51159
|
files: exports_external.array(exports_external.record(exports_external.unknown())).optional()
|
|
@@ -51894,6 +51940,39 @@ import os11 from "node:os";
|
|
|
51894
51940
|
import crypto3 from "node:crypto";
|
|
51895
51941
|
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
51896
51942
|
|
|
51943
|
+
// src/core/memory-mcp.ts
|
|
51944
|
+
var DEFAULT_MEMORY_MCP_BASE = "https://brainbase-memory-mcp.onrender.com";
|
|
51945
|
+
var MEMORY_MCP_SLUG = "brainbase-memory";
|
|
51946
|
+
function memoryMcpBaseUrl() {
|
|
51947
|
+
const envOverride = process.env.BRAINBASE_MEMORY_MCP_URL;
|
|
51948
|
+
if (envOverride)
|
|
51949
|
+
return envOverride.replace(/\/+$/, "");
|
|
51950
|
+
return DEFAULT_MEMORY_MCP_BASE;
|
|
51951
|
+
}
|
|
51952
|
+
function memoryMcpUrl() {
|
|
51953
|
+
return `${memoryMcpBaseUrl()}/t/\${BRAINBASE_THREAD_ID}/mcp`;
|
|
51954
|
+
}
|
|
51955
|
+
function memoryMcpPayload() {
|
|
51956
|
+
return {
|
|
51957
|
+
url: memoryMcpUrl(),
|
|
51958
|
+
headers: {
|
|
51959
|
+
Authorization: "Bearer ${BRAINBASE_TOKEN}"
|
|
51960
|
+
}
|
|
51961
|
+
};
|
|
51962
|
+
}
|
|
51963
|
+
function buildMemoryMcpComponent(scope) {
|
|
51964
|
+
return {
|
|
51965
|
+
type: "mcp",
|
|
51966
|
+
slug: MEMORY_MCP_SLUG,
|
|
51967
|
+
scope,
|
|
51968
|
+
rootDir: "",
|
|
51969
|
+
description: "This agent's persistent SQL memory database (provision, query, " + "inspect schema). Scoped to this agent only.",
|
|
51970
|
+
meta: { mcp: memoryMcpPayload() },
|
|
51971
|
+
payload: memoryMcpPayload(),
|
|
51972
|
+
checksum: "builtin:brainbase-memory:v1"
|
|
51973
|
+
};
|
|
51974
|
+
}
|
|
51975
|
+
|
|
51897
51976
|
// src/core/orchestration-mcp.ts
|
|
51898
51977
|
var DEFAULT_ORCHESTRATION_MCP_BASE = "https://brainbase-orchestration-mcp.onrender.com";
|
|
51899
51978
|
var ORCHESTRATION_MCP_SLUG = "brainbase-orchestration";
|
|
@@ -51927,39 +52006,109 @@ function buildOrchestrationMcpComponent(scope) {
|
|
|
51927
52006
|
};
|
|
51928
52007
|
}
|
|
51929
52008
|
|
|
51930
|
-
// src/core/
|
|
51931
|
-
var
|
|
51932
|
-
var
|
|
51933
|
-
function
|
|
51934
|
-
const envOverride = process.env.
|
|
52009
|
+
// src/core/slack-mcp.ts
|
|
52010
|
+
var DEFAULT_SLACK_MCP_BASE = "https://brainbase-slack-mcp.onrender.com";
|
|
52011
|
+
var SLACK_MCP_SLUG = "brainbase-slack";
|
|
52012
|
+
function slackMcpBaseUrl() {
|
|
52013
|
+
const envOverride = process.env.BRAINBASE_SLACK_MCP_URL;
|
|
51935
52014
|
if (envOverride)
|
|
51936
52015
|
return envOverride.replace(/\/+$/, "");
|
|
51937
|
-
return
|
|
52016
|
+
return DEFAULT_SLACK_MCP_BASE;
|
|
51938
52017
|
}
|
|
51939
|
-
function
|
|
51940
|
-
return `${
|
|
52018
|
+
function slackMcpUrl() {
|
|
52019
|
+
return `${slackMcpBaseUrl()}/t/\${BRAINBASE_THREAD_ID}/mcp`;
|
|
51941
52020
|
}
|
|
51942
|
-
function
|
|
52021
|
+
function slackMcpPayload() {
|
|
51943
52022
|
return {
|
|
51944
|
-
url:
|
|
52023
|
+
url: slackMcpUrl(),
|
|
51945
52024
|
headers: {
|
|
51946
52025
|
Authorization: "Bearer ${BRAINBASE_TOKEN}"
|
|
51947
52026
|
}
|
|
51948
52027
|
};
|
|
51949
52028
|
}
|
|
51950
|
-
function
|
|
52029
|
+
function buildSlackMcpComponent(scope) {
|
|
51951
52030
|
return {
|
|
51952
52031
|
type: "mcp",
|
|
51953
|
-
slug:
|
|
52032
|
+
slug: SLACK_MCP_SLUG,
|
|
51954
52033
|
scope,
|
|
51955
52034
|
rootDir: "",
|
|
51956
|
-
description: "This agent's
|
|
51957
|
-
meta: { mcp:
|
|
51958
|
-
payload:
|
|
51959
|
-
checksum: "builtin:brainbase-
|
|
52035
|
+
description: "This agent's Slack connector (read channels, send messages, manage " + "the workspace it is installed in). Scoped to this agent only.",
|
|
52036
|
+
meta: { mcp: slackMcpPayload() },
|
|
52037
|
+
payload: slackMcpPayload(),
|
|
52038
|
+
checksum: "builtin:brainbase-slack:v1"
|
|
52039
|
+
};
|
|
52040
|
+
}
|
|
52041
|
+
|
|
52042
|
+
// src/core/browser-mcp.ts
|
|
52043
|
+
var DEFAULT_BROWSER_MCP_BASE = "https://brainbase-browser-mcp.onrender.com";
|
|
52044
|
+
var BROWSER_MCP_SLUG = "brainbase-browser";
|
|
52045
|
+
function browserMcpBaseUrl() {
|
|
52046
|
+
const envOverride = process.env.BRAINBASE_BROWSER_MCP_URL;
|
|
52047
|
+
if (envOverride)
|
|
52048
|
+
return envOverride.replace(/\/+$/, "");
|
|
52049
|
+
return DEFAULT_BROWSER_MCP_BASE;
|
|
52050
|
+
}
|
|
52051
|
+
function browserMcpUrl() {
|
|
52052
|
+
return `${browserMcpBaseUrl()}/t/\${BRAINBASE_THREAD_ID}/mcp`;
|
|
52053
|
+
}
|
|
52054
|
+
function browserMcpPayload() {
|
|
52055
|
+
return {
|
|
52056
|
+
url: browserMcpUrl(),
|
|
52057
|
+
headers: {
|
|
52058
|
+
Authorization: "Bearer ${BRAINBASE_TOKEN}"
|
|
52059
|
+
}
|
|
52060
|
+
};
|
|
52061
|
+
}
|
|
52062
|
+
function buildBrowserMcpComponent(scope) {
|
|
52063
|
+
return {
|
|
52064
|
+
type: "mcp",
|
|
52065
|
+
slug: BROWSER_MCP_SLUG,
|
|
52066
|
+
scope,
|
|
52067
|
+
rootDir: "",
|
|
52068
|
+
description: "This agent's headless browser (navigate, read pages, fill forms). " + "Scoped to this agent only.",
|
|
52069
|
+
meta: { mcp: browserMcpPayload() },
|
|
52070
|
+
payload: browserMcpPayload(),
|
|
52071
|
+
checksum: "builtin:brainbase-browser:v1"
|
|
51960
52072
|
};
|
|
51961
52073
|
}
|
|
51962
52074
|
|
|
52075
|
+
// src/core/builtin-mcps.ts
|
|
52076
|
+
function capabilitiesFromAgent(agent) {
|
|
52077
|
+
return {
|
|
52078
|
+
memory: agent.memory_enabled !== false,
|
|
52079
|
+
browser: agent.browser_enabled !== false,
|
|
52080
|
+
slack: agent.slack_connected === true
|
|
52081
|
+
};
|
|
52082
|
+
}
|
|
52083
|
+
function capabilitiesFromManifest(manifest) {
|
|
52084
|
+
const c2 = manifest?.capabilities ?? {};
|
|
52085
|
+
return {
|
|
52086
|
+
memory: c2.memory !== false,
|
|
52087
|
+
browser: c2.browser !== false,
|
|
52088
|
+
slack: c2.slack === true
|
|
52089
|
+
};
|
|
52090
|
+
}
|
|
52091
|
+
function resolveBuiltinMcps(input) {
|
|
52092
|
+
const { caps, declaredSlugs, scope } = input;
|
|
52093
|
+
const gated = [
|
|
52094
|
+
{ slug: ORCHESTRATION_MCP_SLUG, enabled: true, build: buildOrchestrationMcpComponent },
|
|
52095
|
+
{ slug: MEMORY_MCP_SLUG, enabled: caps.memory, build: buildMemoryMcpComponent },
|
|
52096
|
+
{ slug: BROWSER_MCP_SLUG, enabled: caps.browser, build: buildBrowserMcpComponent },
|
|
52097
|
+
{ slug: SLACK_MCP_SLUG, enabled: caps.slack, build: buildSlackMcpComponent }
|
|
52098
|
+
];
|
|
52099
|
+
const install = [];
|
|
52100
|
+
const removeSlugs = [];
|
|
52101
|
+
for (const g3 of gated) {
|
|
52102
|
+
if (declaredSlugs.has(g3.slug))
|
|
52103
|
+
continue;
|
|
52104
|
+
if (g3.enabled)
|
|
52105
|
+
install.push(g3.build(scope));
|
|
52106
|
+
else
|
|
52107
|
+
removeSlugs.push(g3.slug);
|
|
52108
|
+
}
|
|
52109
|
+
return { install, removeSlugs };
|
|
52110
|
+
}
|
|
52111
|
+
|
|
51963
52112
|
// src/cli/sync.ts
|
|
51964
52113
|
async function runSync(cwd2, args) {
|
|
51965
52114
|
banner("sync — bring in the latest changes from your team");
|
|
@@ -51986,11 +52135,21 @@ async function runSync(cwd2, args) {
|
|
|
51986
52135
|
}
|
|
51987
52136
|
const prevState = readSyncState(cwd2);
|
|
51988
52137
|
const diff2 = computeDiff(manifest.components, prevState);
|
|
51989
|
-
const
|
|
51990
|
-
|
|
51991
|
-
|
|
51992
|
-
|
|
51993
|
-
|
|
52138
|
+
const scope = args.scope ?? "project";
|
|
52139
|
+
let caps;
|
|
52140
|
+
try {
|
|
52141
|
+
caps = capabilitiesFromManifest(readManifest(cwd2));
|
|
52142
|
+
} catch (err) {
|
|
52143
|
+
f2.error(err.message);
|
|
52144
|
+
return;
|
|
52145
|
+
}
|
|
52146
|
+
const declaredMcpSlugs = new Set(manifest.components.filter((c2) => c2.type === "mcp").map((c2) => c2.slug));
|
|
52147
|
+
const { install: builtinInstall, removeSlugs: builtinRemoveSlugs } = resolveBuiltinMcps({
|
|
52148
|
+
caps,
|
|
52149
|
+
declaredSlugs: declaredMcpSlugs,
|
|
52150
|
+
scope
|
|
52151
|
+
});
|
|
52152
|
+
if (diff2.added.length === 0 && diff2.upstreamUpdated.length === 0 && diff2.localModified.length === 0 && diff2.deletedUpstream.length === 0 && builtinInstall.length === 0 && builtinRemoveSlugs.length === 0) {
|
|
51994
52153
|
f2.info(`${sym.same} You're up to date.`);
|
|
51995
52154
|
writeSyncState(cwd2, {
|
|
51996
52155
|
schemaVersion: 1,
|
|
@@ -52054,7 +52213,6 @@ async function runSync(cwd2, args) {
|
|
|
52054
52213
|
});
|
|
52055
52214
|
}
|
|
52056
52215
|
const adapter = getAdapter(adapterId);
|
|
52057
|
-
const scope = args.scope ?? "project";
|
|
52058
52216
|
const keepLocal = new Set;
|
|
52059
52217
|
if (diff2.localModified.length > 0) {
|
|
52060
52218
|
requireInteractive(`${diff2.localModified.length} component(s) changed both locally and in the cloud — run \`brainbase sync\` in an interactive terminal to resolve them (or revert your local changes).`);
|
|
@@ -52092,14 +52250,7 @@ async function runSync(cwd2, args) {
|
|
|
52092
52250
|
payload: proxifyMcpPayload(c2.meta?.mcp),
|
|
52093
52251
|
checksum: c2.hash
|
|
52094
52252
|
}));
|
|
52095
|
-
|
|
52096
|
-
if (!hasUserOrchestrationMcp) {
|
|
52097
|
-
toInstall.push(buildOrchestrationMcpComponent(scope));
|
|
52098
|
-
}
|
|
52099
|
-
const hasUserMemoryMcp = toInstall.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
|
|
52100
|
-
if (!hasUserMemoryMcp) {
|
|
52101
|
-
toInstall.push(buildMemoryMcpComponent(scope));
|
|
52102
|
-
}
|
|
52253
|
+
toInstall.push(...builtinInstall);
|
|
52103
52254
|
const justInstalledPaths = new Map;
|
|
52104
52255
|
if (toInstall.length > 0) {
|
|
52105
52256
|
const installSpinner = de();
|
|
@@ -52119,6 +52270,9 @@ async function runSync(cwd2, args) {
|
|
|
52119
52270
|
f2.warn(`Skipped: ${result2.skipped.map((s3) => `${s3.type}/${s3.slug} (${s3.reason})`).join(", ")}`);
|
|
52120
52271
|
}
|
|
52121
52272
|
}
|
|
52273
|
+
if (builtinRemoveSlugs.length > 0) {
|
|
52274
|
+
runHarnessRemoveMcp(adapter.id, builtinRemoveSlugs, { cwd: cwd2, scope });
|
|
52275
|
+
}
|
|
52122
52276
|
if (diff2.deletedUpstream.length > 0) {
|
|
52123
52277
|
for (const removed of diff2.deletedUpstream) {
|
|
52124
52278
|
let goAhead = autoProceed(args.yes);
|
|
@@ -52708,11 +52862,14 @@ async function runAgentPull(cwd2, args) {
|
|
|
52708
52862
|
else
|
|
52709
52863
|
toInstallKeys.add(r2.key);
|
|
52710
52864
|
}
|
|
52711
|
-
const
|
|
52712
|
-
const
|
|
52713
|
-
const
|
|
52714
|
-
|
|
52715
|
-
|
|
52865
|
+
const caps = capabilitiesFromAgent(cloudAgent);
|
|
52866
|
+
const declaredMcpSlugs = new Set(cloud.components.filter((c2) => c2.type === "mcp").map((c2) => c2.slug));
|
|
52867
|
+
const { install: builtinInstall, removeSlugs: builtinRemoveSlugs } = resolveBuiltinMcps({
|
|
52868
|
+
caps,
|
|
52869
|
+
declaredSlugs: declaredMcpSlugs,
|
|
52870
|
+
scope: args.scope ?? "project"
|
|
52871
|
+
});
|
|
52872
|
+
if (toInstallKeys.size === 0 && toRemoveKeys.size === 0 && builtinInstall.length === 0 && builtinRemoveSlugs.length === 0 && !override) {
|
|
52716
52873
|
f2.info(`You're up to date.`);
|
|
52717
52874
|
writeLink(cwd2, buildLinkFromAgent(cloudAgent, harness, readLink(cwd2)));
|
|
52718
52875
|
writeSyncState(cwd2, buildLockFromCloud(agentId, cloud, lock, cloudAgent));
|
|
@@ -52766,7 +52923,7 @@ async function runAgentPull(cwd2, args) {
|
|
|
52766
52923
|
const stageRoot = stageManifestComponents(installComponents);
|
|
52767
52924
|
const justInstalledPaths = new Map;
|
|
52768
52925
|
try {
|
|
52769
|
-
if (installComponents.length > 0 ||
|
|
52926
|
+
if (installComponents.length > 0 || builtinInstall.length > 0) {
|
|
52770
52927
|
const installSpinner = de();
|
|
52771
52928
|
installSpinner.start("Applying updates…");
|
|
52772
52929
|
const toInstall = installComponents.map((c2) => ({
|
|
@@ -52780,12 +52937,7 @@ async function runAgentPull(cwd2, args) {
|
|
|
52780
52937
|
checksum: c2.hash,
|
|
52781
52938
|
source: skillSourceFromMeta(c2)
|
|
52782
52939
|
}));
|
|
52783
|
-
|
|
52784
|
-
toInstall.push(buildOrchestrationMcpComponent(scope));
|
|
52785
|
-
}
|
|
52786
|
-
if (needMemoryMcpInstall) {
|
|
52787
|
-
toInstall.push(buildMemoryMcpComponent(scope));
|
|
52788
|
-
}
|
|
52940
|
+
toInstall.push(...builtinInstall);
|
|
52789
52941
|
const opts = {
|
|
52790
52942
|
cwd: cwd2,
|
|
52791
52943
|
scope,
|
|
@@ -52801,6 +52953,9 @@ async function runAgentPull(cwd2, args) {
|
|
|
52801
52953
|
f2.warn(`Skipped: ${result2.skipped.map((s3) => `${s3.type}/${s3.slug} (${s3.reason})`).join(", ")}`);
|
|
52802
52954
|
}
|
|
52803
52955
|
}
|
|
52956
|
+
if (builtinRemoveSlugs.length > 0) {
|
|
52957
|
+
runHarnessRemoveMcp(harness, builtinRemoveSlugs, { cwd: cwd2, scope });
|
|
52958
|
+
}
|
|
52804
52959
|
for (const r2 of removeRows) {
|
|
52805
52960
|
const prior = lock?.components.find((c2) => c2.type === r2.type && c2.slug === r2.slug);
|
|
52806
52961
|
if (!prior)
|
|
@@ -53053,6 +53208,7 @@ function mergeManifest(cwd2, prev, cloud, cloudAgent, harness) {
|
|
|
53053
53208
|
entry.is_enabled = payload.is_enabled;
|
|
53054
53209
|
return entry;
|
|
53055
53210
|
});
|
|
53211
|
+
const caps = capabilitiesFromAgent(cloudAgent);
|
|
53056
53212
|
return {
|
|
53057
53213
|
schema: 1,
|
|
53058
53214
|
id: cloudAgent.id,
|
|
@@ -53065,7 +53221,8 @@ function mergeManifest(cwd2, prev, cloud, cloudAgent, harness) {
|
|
|
53065
53221
|
...entrypoint ? { entrypoint } : {},
|
|
53066
53222
|
playbooks,
|
|
53067
53223
|
skills,
|
|
53068
|
-
mcp
|
|
53224
|
+
mcp,
|
|
53225
|
+
capabilities: { memory: caps.memory, browser: caps.browser, slack: caps.slack }
|
|
53069
53226
|
};
|
|
53070
53227
|
}
|
|
53071
53228
|
function materializeEntrypoint(cwd2, cloudEntrypoint, prev) {
|
|
@@ -54366,12 +54523,14 @@ async function runAgentUnpack(cwd2, args) {
|
|
|
54366
54523
|
checksum: ""
|
|
54367
54524
|
});
|
|
54368
54525
|
}
|
|
54369
|
-
const
|
|
54370
|
-
const
|
|
54371
|
-
|
|
54372
|
-
|
|
54373
|
-
|
|
54374
|
-
|
|
54526
|
+
const caps = capabilitiesFromManifest(manifest);
|
|
54527
|
+
const declaredMcpSlugs = new Set((manifest.mcp ?? []).map((m3) => m3.name));
|
|
54528
|
+
const { install: builtinInstall, removeSlugs: builtinRemoveSlugs } = resolveBuiltinMcps({
|
|
54529
|
+
caps,
|
|
54530
|
+
declaredSlugs: declaredMcpSlugs,
|
|
54531
|
+
scope
|
|
54532
|
+
});
|
|
54533
|
+
toInstall.push(...builtinInstall);
|
|
54375
54534
|
const opts = {
|
|
54376
54535
|
cwd: cwd2,
|
|
54377
54536
|
scope,
|
|
@@ -54385,6 +54544,9 @@ async function runAgentUnpack(cwd2, args) {
|
|
|
54385
54544
|
if (result2.skipped.length) {
|
|
54386
54545
|
f2.warn(`Skipped: ${result2.skipped.map((s3) => `${s3.type}/${s3.slug} (${s3.reason})`).join(", ")}`);
|
|
54387
54546
|
}
|
|
54547
|
+
if (builtinRemoveSlugs.length > 0) {
|
|
54548
|
+
runHarnessRemoveMcp(harness, builtinRemoveSlugs, { cwd: cwd2, scope });
|
|
54549
|
+
}
|
|
54388
54550
|
} catch (err) {
|
|
54389
54551
|
f2.error(`Install failed: ${err.message}`);
|
|
54390
54552
|
return;
|
|
@@ -54813,12 +54975,15 @@ async function installAgentFresh(input) {
|
|
|
54813
54975
|
ensureDir(cwd2);
|
|
54814
54976
|
const stageRoot = stageManifestComponents2(cloud.components);
|
|
54815
54977
|
const justInstalledPaths = new Map;
|
|
54816
|
-
const
|
|
54817
|
-
const
|
|
54818
|
-
const
|
|
54819
|
-
|
|
54978
|
+
const caps = capabilitiesFromAgent(agent);
|
|
54979
|
+
const declaredMcpSlugs = new Set(cloud.components.filter((c2) => c2.type === "mcp").map((c2) => c2.slug));
|
|
54980
|
+
const { install: builtinInstall } = resolveBuiltinMcps({
|
|
54981
|
+
caps,
|
|
54982
|
+
declaredSlugs: declaredMcpSlugs,
|
|
54983
|
+
scope
|
|
54984
|
+
});
|
|
54820
54985
|
try {
|
|
54821
|
-
if (cloud.components.length > 0 ||
|
|
54986
|
+
if (cloud.components.length > 0 || builtinInstall.length > 0) {
|
|
54822
54987
|
const toInstall = cloud.components.map((c2) => ({
|
|
54823
54988
|
type: c2.type,
|
|
54824
54989
|
slug: c2.slug,
|
|
@@ -54829,12 +54994,7 @@ async function installAgentFresh(input) {
|
|
|
54829
54994
|
payload: proxifyMcpPayload(c2.meta?.mcp),
|
|
54830
54995
|
checksum: c2.hash
|
|
54831
54996
|
}));
|
|
54832
|
-
|
|
54833
|
-
toInstall.push(buildOrchestrationMcpComponent(scope));
|
|
54834
|
-
}
|
|
54835
|
-
if (needMemoryMcpInstall) {
|
|
54836
|
-
toInstall.push(buildMemoryMcpComponent(scope));
|
|
54837
|
-
}
|
|
54997
|
+
toInstall.push(...builtinInstall);
|
|
54838
54998
|
const installOpts = {
|
|
54839
54999
|
cwd: cwd2,
|
|
54840
55000
|
scope,
|
|
@@ -54952,6 +55112,7 @@ function buildManifestFromCloud(cloud, agent) {
|
|
|
54952
55112
|
entry.is_enabled = payload.is_enabled;
|
|
54953
55113
|
return entry;
|
|
54954
55114
|
});
|
|
55115
|
+
const caps = capabilitiesFromAgent(agent);
|
|
54955
55116
|
return {
|
|
54956
55117
|
schema: 1,
|
|
54957
55118
|
agent: {
|
|
@@ -54961,7 +55122,8 @@ function buildManifestFromCloud(cloud, agent) {
|
|
|
54961
55122
|
...hasInstructions ? { instructions: { file: DEFAULT_INSTRUCTIONS_FILE } } : {},
|
|
54962
55123
|
playbooks: [],
|
|
54963
55124
|
skills,
|
|
54964
|
-
mcp
|
|
55125
|
+
mcp,
|
|
55126
|
+
capabilities: { memory: caps.memory, browser: caps.browser, slack: caps.slack }
|
|
54965
55127
|
};
|
|
54966
55128
|
}
|
|
54967
55129
|
async function pullAgentSecrets(cwd2, agentId) {
|