@brainbase-labs/cli 0.4.2 → 0.5.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 +1376 -733
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28564,7 +28564,7 @@ var require_jsx_dev_runtime = __commonJS((exports, module) => {
|
|
|
28564
28564
|
});
|
|
28565
28565
|
|
|
28566
28566
|
// src/index.ts
|
|
28567
|
-
var
|
|
28567
|
+
var import_picocolors40 = __toESM(require_picocolors(), 1);
|
|
28568
28568
|
import process13 from "node:process";
|
|
28569
28569
|
import fs50 from "node:fs";
|
|
28570
28570
|
|
|
@@ -50759,11 +50759,164 @@ async function runWhoami() {
|
|
|
50759
50759
|
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
50760
50760
|
|
|
50761
50761
|
// src/core/link.ts
|
|
50762
|
+
import path43 from "node:path";
|
|
50763
|
+
import fs40 from "node:fs";
|
|
50764
|
+
|
|
50765
|
+
// src/core/agent-manifest.ts
|
|
50762
50766
|
import path42 from "node:path";
|
|
50763
50767
|
import fs39 from "node:fs";
|
|
50768
|
+
var import_yaml2 = __toESM(require_dist(), 1);
|
|
50769
|
+
var AGENT_MANIFEST_FILE = "brainbase.agent.yaml";
|
|
50770
|
+
var LEGACY_AGENT_MANIFEST_FILE = "brainbase.yaml";
|
|
50771
|
+
var DEFAULT_INSTRUCTIONS_FILE = "instructions.md";
|
|
50772
|
+
var DEFAULT_ENTRYPOINT_FILE = "entrypoint.sh";
|
|
50773
|
+
var REGISTRY_SOURCE_RE = /^registry:(?:([a-z0-9_-]+)\/)?([a-z0-9_-]+)(?:@(.+))?$/i;
|
|
50774
|
+
function parseSkillSource2(raw) {
|
|
50775
|
+
if (!raw || typeof raw !== "string") {
|
|
50776
|
+
throw new Error("Skill source must be a non-empty string");
|
|
50777
|
+
}
|
|
50778
|
+
const m3 = raw.match(REGISTRY_SOURCE_RE);
|
|
50779
|
+
if (m3) {
|
|
50780
|
+
return {
|
|
50781
|
+
kind: "registry",
|
|
50782
|
+
...m3[1] ? { creator: m3[1] } : {},
|
|
50783
|
+
slug: m3[2],
|
|
50784
|
+
version: m3[3]
|
|
50785
|
+
};
|
|
50786
|
+
}
|
|
50787
|
+
if (raw.startsWith("./") || raw.startsWith("../") || raw.startsWith("/")) {
|
|
50788
|
+
return { kind: "local", path: raw };
|
|
50789
|
+
}
|
|
50790
|
+
throw new Error(`Unrecognized skill source "${raw}". Expected "registry:creator/slug[@version]", "registry:slug", or a relative path starting with "./".`);
|
|
50791
|
+
}
|
|
50792
|
+
var AgentMetaSchema = exports_external.object({
|
|
50793
|
+
name: exports_external.string().min(1),
|
|
50794
|
+
tagline: exports_external.string().optional()
|
|
50795
|
+
});
|
|
50796
|
+
var InstructionsSchema = exports_external.object({
|
|
50797
|
+
file: exports_external.string().min(1).optional(),
|
|
50798
|
+
text: exports_external.string().optional()
|
|
50799
|
+
}).refine((v3) => v3.file !== undefined || v3.text !== undefined, {
|
|
50800
|
+
message: "instructions must set either `file` or `text`"
|
|
50801
|
+
});
|
|
50802
|
+
var EntrypointSchema = exports_external.object({
|
|
50803
|
+
file: exports_external.string().min(1).optional(),
|
|
50804
|
+
commands: exports_external.array(exports_external.string().min(1)).optional(),
|
|
50805
|
+
text: exports_external.string().optional()
|
|
50806
|
+
}).refine((v3) => {
|
|
50807
|
+
const set = [v3.file, v3.commands, v3.text].filter((x3) => x3 !== undefined);
|
|
50808
|
+
return set.length === 1;
|
|
50809
|
+
}, {
|
|
50810
|
+
message: "entrypoint must set exactly one of `file`, `commands`, or `text`"
|
|
50811
|
+
});
|
|
50812
|
+
var SkillEntrySchema = exports_external.object({
|
|
50813
|
+
source: exports_external.string().min(1)
|
|
50814
|
+
});
|
|
50815
|
+
var McpEntrySchema = exports_external.object({
|
|
50816
|
+
name: exports_external.string().min(1),
|
|
50817
|
+
url: exports_external.string().optional(),
|
|
50818
|
+
command: exports_external.string().optional(),
|
|
50819
|
+
args: exports_external.array(exports_external.string()).optional(),
|
|
50820
|
+
env: exports_external.record(exports_external.string()).optional(),
|
|
50821
|
+
headers: exports_external.record(exports_external.string()).optional(),
|
|
50822
|
+
is_enabled: exports_external.boolean().optional()
|
|
50823
|
+
});
|
|
50824
|
+
var AgentManifestSchema = exports_external.object({
|
|
50825
|
+
schema: exports_external.literal(1),
|
|
50826
|
+
id: exports_external.string().min(1).optional(),
|
|
50827
|
+
harness: exports_external.string().min(1).optional(),
|
|
50828
|
+
agent: AgentMetaSchema,
|
|
50829
|
+
instructions: InstructionsSchema.optional(),
|
|
50830
|
+
entrypoint: EntrypointSchema.optional(),
|
|
50831
|
+
skills: exports_external.array(SkillEntrySchema).default([]),
|
|
50832
|
+
mcp: exports_external.array(McpEntrySchema).default([]),
|
|
50833
|
+
commands: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
50834
|
+
hooks: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
50835
|
+
files: exports_external.array(exports_external.record(exports_external.unknown())).optional()
|
|
50836
|
+
});
|
|
50837
|
+
function manifestPath(cwd2) {
|
|
50838
|
+
return path42.join(cwd2, AGENT_MANIFEST_FILE);
|
|
50839
|
+
}
|
|
50840
|
+
function existingManifestPath(cwd2) {
|
|
50841
|
+
const newPath = path42.join(cwd2, AGENT_MANIFEST_FILE);
|
|
50842
|
+
if (fs39.existsSync(newPath))
|
|
50843
|
+
return newPath;
|
|
50844
|
+
const legacy = path42.join(cwd2, LEGACY_AGENT_MANIFEST_FILE);
|
|
50845
|
+
if (fs39.existsSync(legacy))
|
|
50846
|
+
return legacy;
|
|
50847
|
+
return null;
|
|
50848
|
+
}
|
|
50849
|
+
function hasManifest(cwd2) {
|
|
50850
|
+
return existingManifestPath(cwd2) !== null;
|
|
50851
|
+
}
|
|
50852
|
+
function readManifest(cwd2) {
|
|
50853
|
+
const p2 = existingManifestPath(cwd2);
|
|
50854
|
+
if (!p2)
|
|
50855
|
+
return null;
|
|
50856
|
+
const raw = fs39.readFileSync(p2, "utf8");
|
|
50857
|
+
let parsed;
|
|
50858
|
+
try {
|
|
50859
|
+
parsed = import_yaml2.default.parse(raw);
|
|
50860
|
+
} catch (err) {
|
|
50861
|
+
throw new Error(`${path42.basename(p2)} is not valid YAML: ${err.message}`);
|
|
50862
|
+
}
|
|
50863
|
+
const result = AgentManifestSchema.safeParse(parsed);
|
|
50864
|
+
if (!result.success) {
|
|
50865
|
+
throw new Error(`${path42.basename(p2)} is invalid: ${result.error.issues.map((i) => `${i.path.join(".") || "(root)"} — ${i.message}`).join("; ")}`);
|
|
50866
|
+
}
|
|
50867
|
+
return result.data;
|
|
50868
|
+
}
|
|
50869
|
+
function writeManifest(cwd2, manifest) {
|
|
50870
|
+
const doc = new import_yaml2.default.Document;
|
|
50871
|
+
doc.contents = manifest;
|
|
50872
|
+
doc.commentBefore = ` brainbase.agent.yaml — declarative agent manifest.
|
|
50873
|
+
` + " Committed to source control. Edit by hand, then `brainbase agent push`.";
|
|
50874
|
+
const out = String(doc);
|
|
50875
|
+
fs39.writeFileSync(manifestPath(cwd2), out, "utf8");
|
|
50876
|
+
}
|
|
50877
|
+
function resolveInstructionsPath(cwd2, manifest) {
|
|
50878
|
+
if (!manifest.instructions?.file)
|
|
50879
|
+
return null;
|
|
50880
|
+
return path42.resolve(cwd2, manifest.instructions.file);
|
|
50881
|
+
}
|
|
50882
|
+
function readInstructions(cwd2, manifest) {
|
|
50883
|
+
if (!manifest.instructions)
|
|
50884
|
+
return null;
|
|
50885
|
+
if (typeof manifest.instructions.text === "string") {
|
|
50886
|
+
return manifest.instructions.text;
|
|
50887
|
+
}
|
|
50888
|
+
const p2 = resolveInstructionsPath(cwd2, manifest);
|
|
50889
|
+
if (!p2 || !fs39.existsSync(p2))
|
|
50890
|
+
return null;
|
|
50891
|
+
return fs39.readFileSync(p2, "utf8");
|
|
50892
|
+
}
|
|
50893
|
+
function resolveEntrypoint(cwd2, manifest) {
|
|
50894
|
+
const ep = manifest.entrypoint;
|
|
50895
|
+
if (!ep)
|
|
50896
|
+
return null;
|
|
50897
|
+
if (typeof ep.text === "string")
|
|
50898
|
+
return ep.text;
|
|
50899
|
+
if (Array.isArray(ep.commands)) {
|
|
50900
|
+
if (ep.commands.length === 0)
|
|
50901
|
+
return null;
|
|
50902
|
+
return ["set -euo pipefail", ...ep.commands].join(`
|
|
50903
|
+
`) + `
|
|
50904
|
+
`;
|
|
50905
|
+
}
|
|
50906
|
+
if (typeof ep.file === "string") {
|
|
50907
|
+
const p2 = path42.resolve(cwd2, ep.file);
|
|
50908
|
+
if (!fs39.existsSync(p2))
|
|
50909
|
+
return null;
|
|
50910
|
+
return fs39.readFileSync(p2, "utf8");
|
|
50911
|
+
}
|
|
50912
|
+
return null;
|
|
50913
|
+
}
|
|
50914
|
+
|
|
50915
|
+
// src/core/link.ts
|
|
50764
50916
|
var LINK_DIR = ".brainbase";
|
|
50765
|
-
var
|
|
50917
|
+
var STATE_FILE = "state.json";
|
|
50766
50918
|
var SYNC_STATE_FILE = "sync-state.json";
|
|
50919
|
+
var LEGACY_LINK_FILE = "link.json";
|
|
50767
50920
|
var TrackingSchema = exports_external.object({
|
|
50768
50921
|
harness: exports_external.string(),
|
|
50769
50922
|
key_id: exports_external.string(),
|
|
@@ -50786,6 +50939,16 @@ var LinkSchema = exports_external.object({
|
|
|
50786
50939
|
harness: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
|
|
50787
50940
|
tracking: TrackingSchema.nullish().transform((v3) => v3 ?? undefined)
|
|
50788
50941
|
});
|
|
50942
|
+
var LinkStateSchema = exports_external.object({
|
|
50943
|
+
schemaVersion: exports_external.literal(1),
|
|
50944
|
+
org_id: exports_external.string().default(""),
|
|
50945
|
+
team_id: exports_external.string().default(""),
|
|
50946
|
+
slug: exports_external.string().default(""),
|
|
50947
|
+
url: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
|
|
50948
|
+
linked_at: exports_external.string(),
|
|
50949
|
+
linked_by: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
|
|
50950
|
+
tracking: TrackingSchema.nullish().transform((v3) => v3 ?? undefined)
|
|
50951
|
+
});
|
|
50789
50952
|
var SyncedComponentSchema = exports_external.object({
|
|
50790
50953
|
type: exports_external.string(),
|
|
50791
50954
|
slug: exports_external.string(),
|
|
@@ -50795,7 +50958,8 @@ var SyncedComponentSchema = exports_external.object({
|
|
|
50795
50958
|
});
|
|
50796
50959
|
var AgentMetaSnapshotSchema = exports_external.object({
|
|
50797
50960
|
name: exports_external.string(),
|
|
50798
|
-
tagline: exports_external.string().optional()
|
|
50961
|
+
tagline: exports_external.string().optional(),
|
|
50962
|
+
entrypoint: exports_external.string().optional()
|
|
50799
50963
|
});
|
|
50800
50964
|
var SyncStateSchema = exports_external.object({
|
|
50801
50965
|
schemaVersion: exports_external.literal(1),
|
|
@@ -50805,39 +50969,157 @@ var SyncStateSchema = exports_external.object({
|
|
|
50805
50969
|
components: exports_external.array(SyncedComponentSchema),
|
|
50806
50970
|
agentMeta: AgentMetaSnapshotSchema.optional()
|
|
50807
50971
|
});
|
|
50808
|
-
function
|
|
50809
|
-
return
|
|
50972
|
+
function statePath(cwd2) {
|
|
50973
|
+
return path43.join(cwd2, LINK_DIR, STATE_FILE);
|
|
50810
50974
|
}
|
|
50811
50975
|
function syncStatePath(cwd2) {
|
|
50812
|
-
return
|
|
50976
|
+
return path43.join(cwd2, LINK_DIR, SYNC_STATE_FILE);
|
|
50977
|
+
}
|
|
50978
|
+
function legacyLinkPath(cwd2) {
|
|
50979
|
+
return path43.join(cwd2, LINK_DIR, LEGACY_LINK_FILE);
|
|
50980
|
+
}
|
|
50981
|
+
function readState(cwd2) {
|
|
50982
|
+
const p2 = statePath(cwd2);
|
|
50983
|
+
if (exists(p2)) {
|
|
50984
|
+
try {
|
|
50985
|
+
return LinkStateSchema.parse(readJson(p2));
|
|
50986
|
+
} catch {
|
|
50987
|
+
return null;
|
|
50988
|
+
}
|
|
50989
|
+
}
|
|
50990
|
+
const legacy = legacyLinkPath(cwd2);
|
|
50991
|
+
if (exists(legacy)) {
|
|
50992
|
+
try {
|
|
50993
|
+
const raw = readJson(legacy);
|
|
50994
|
+
const lifted = {
|
|
50995
|
+
schemaVersion: 1,
|
|
50996
|
+
org_id: String(raw.org_id ?? ""),
|
|
50997
|
+
team_id: String(raw.team_id ?? ""),
|
|
50998
|
+
slug: String(raw.slug ?? ""),
|
|
50999
|
+
url: typeof raw.url === "string" ? raw.url : undefined,
|
|
51000
|
+
linked_at: typeof raw.linked_at === "string" ? raw.linked_at : new Date().toISOString(),
|
|
51001
|
+
linked_by: typeof raw.linked_by === "string" ? raw.linked_by : undefined,
|
|
51002
|
+
tracking: (() => {
|
|
51003
|
+
try {
|
|
51004
|
+
return TrackingSchema.parse(raw.tracking);
|
|
51005
|
+
} catch {
|
|
51006
|
+
return;
|
|
51007
|
+
}
|
|
51008
|
+
})()
|
|
51009
|
+
};
|
|
51010
|
+
try {
|
|
51011
|
+
ensureDir(path43.join(cwd2, LINK_DIR));
|
|
51012
|
+
writeJson(statePath(cwd2), lifted);
|
|
51013
|
+
ensureGitignore(cwd2);
|
|
51014
|
+
} catch {}
|
|
51015
|
+
return lifted;
|
|
51016
|
+
} catch {
|
|
51017
|
+
return null;
|
|
51018
|
+
}
|
|
51019
|
+
}
|
|
51020
|
+
return null;
|
|
51021
|
+
}
|
|
51022
|
+
function writeState(cwd2, state) {
|
|
51023
|
+
ensureDir(path43.join(cwd2, LINK_DIR));
|
|
51024
|
+
writeJson(statePath(cwd2), state);
|
|
51025
|
+
ensureGitignore(cwd2);
|
|
50813
51026
|
}
|
|
50814
51027
|
function readLink(cwd2) {
|
|
50815
|
-
|
|
50816
|
-
if (!exists(p2))
|
|
50817
|
-
return null;
|
|
51028
|
+
let manifest = null;
|
|
50818
51029
|
try {
|
|
50819
|
-
|
|
51030
|
+
manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
50820
51031
|
} catch {
|
|
50821
|
-
|
|
51032
|
+
manifest = null;
|
|
51033
|
+
}
|
|
51034
|
+
const state = readState(cwd2);
|
|
51035
|
+
if (manifest?.id) {
|
|
51036
|
+
return {
|
|
51037
|
+
schemaVersion: 1,
|
|
51038
|
+
agent_id: manifest.id,
|
|
51039
|
+
org_id: state?.org_id ?? "",
|
|
51040
|
+
team_id: state?.team_id ?? "",
|
|
51041
|
+
slug: state?.slug ?? "",
|
|
51042
|
+
name: manifest.agent.name,
|
|
51043
|
+
tagline: manifest.agent.tagline,
|
|
51044
|
+
url: state?.url,
|
|
51045
|
+
linked_at: state?.linked_at ?? new Date().toISOString(),
|
|
51046
|
+
linked_by: state?.linked_by,
|
|
51047
|
+
harness: manifest.harness,
|
|
51048
|
+
tracking: state?.tracking
|
|
51049
|
+
};
|
|
51050
|
+
}
|
|
51051
|
+
const legacy = legacyLinkPath(cwd2);
|
|
51052
|
+
if (exists(legacy)) {
|
|
51053
|
+
try {
|
|
51054
|
+
return LinkSchema.parse(readJson(legacy));
|
|
51055
|
+
} catch {
|
|
51056
|
+
return null;
|
|
51057
|
+
}
|
|
50822
51058
|
}
|
|
51059
|
+
return null;
|
|
50823
51060
|
}
|
|
50824
51061
|
function writeLink(cwd2, link2) {
|
|
50825
|
-
|
|
50826
|
-
|
|
50827
|
-
|
|
50828
|
-
|
|
50829
|
-
|
|
51062
|
+
let manifest;
|
|
51063
|
+
try {
|
|
51064
|
+
manifest = readManifest(cwd2) ?? {
|
|
51065
|
+
schema: 1,
|
|
51066
|
+
agent: { name: link2.name },
|
|
51067
|
+
skills: [],
|
|
51068
|
+
mcp: []
|
|
51069
|
+
};
|
|
51070
|
+
} catch {
|
|
51071
|
+
manifest = {
|
|
51072
|
+
schema: 1,
|
|
51073
|
+
agent: { name: link2.name },
|
|
51074
|
+
skills: [],
|
|
51075
|
+
mcp: []
|
|
51076
|
+
};
|
|
51077
|
+
}
|
|
51078
|
+
manifest.id = link2.agent_id;
|
|
51079
|
+
if (link2.harness)
|
|
51080
|
+
manifest.harness = link2.harness;
|
|
51081
|
+
manifest.agent.name = link2.name;
|
|
51082
|
+
if (link2.tagline)
|
|
51083
|
+
manifest.agent.tagline = link2.tagline;
|
|
51084
|
+
else
|
|
51085
|
+
delete manifest.agent.tagline;
|
|
51086
|
+
writeManifest(cwd2, manifest);
|
|
51087
|
+
const state = {
|
|
51088
|
+
schemaVersion: 1,
|
|
51089
|
+
org_id: link2.org_id,
|
|
51090
|
+
team_id: link2.team_id,
|
|
51091
|
+
slug: link2.slug,
|
|
51092
|
+
url: link2.url,
|
|
51093
|
+
linked_at: link2.linked_at,
|
|
51094
|
+
linked_by: link2.linked_by,
|
|
51095
|
+
tracking: link2.tracking
|
|
51096
|
+
};
|
|
51097
|
+
writeState(cwd2, state);
|
|
51098
|
+
const legacy = legacyLinkPath(cwd2);
|
|
51099
|
+
if (exists(legacy)) {
|
|
51100
|
+
try {
|
|
51101
|
+
fs40.rmSync(legacy);
|
|
51102
|
+
} catch {}
|
|
50830
51103
|
}
|
|
50831
|
-
writeJson(linkPath(cwd2), clean);
|
|
50832
|
-
ensureGitignore(cwd2);
|
|
50833
51104
|
}
|
|
50834
51105
|
function clearLink(cwd2) {
|
|
50835
|
-
|
|
51106
|
+
try {
|
|
51107
|
+
const m3 = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
51108
|
+
if (m3) {
|
|
51109
|
+
delete m3.id;
|
|
51110
|
+
delete m3.harness;
|
|
51111
|
+
writeManifest(cwd2, m3);
|
|
51112
|
+
}
|
|
51113
|
+
} catch {}
|
|
51114
|
+
const p2 = statePath(cwd2);
|
|
50836
51115
|
if (exists(p2))
|
|
50837
|
-
|
|
51116
|
+
fs40.rmSync(p2);
|
|
50838
51117
|
const sp = syncStatePath(cwd2);
|
|
50839
51118
|
if (exists(sp))
|
|
50840
|
-
|
|
51119
|
+
fs40.rmSync(sp);
|
|
51120
|
+
const legacy = legacyLinkPath(cwd2);
|
|
51121
|
+
if (exists(legacy))
|
|
51122
|
+
fs40.rmSync(legacy);
|
|
50841
51123
|
}
|
|
50842
51124
|
function readSyncState(cwd2) {
|
|
50843
51125
|
const p2 = syncStatePath(cwd2);
|
|
@@ -50850,22 +51132,22 @@ function readSyncState(cwd2) {
|
|
|
50850
51132
|
}
|
|
50851
51133
|
}
|
|
50852
51134
|
function writeSyncState(cwd2, state) {
|
|
50853
|
-
ensureDir(
|
|
51135
|
+
ensureDir(path43.join(cwd2, LINK_DIR));
|
|
50854
51136
|
writeJson(syncStatePath(cwd2), state);
|
|
50855
51137
|
ensureGitignore(cwd2);
|
|
50856
51138
|
}
|
|
50857
51139
|
function ensureGitignore(cwd2) {
|
|
50858
|
-
const ignorePath =
|
|
50859
|
-
const desired =
|
|
50860
|
-
|
|
51140
|
+
const ignorePath = path43.join(cwd2, LINK_DIR, ".gitignore");
|
|
51141
|
+
const desired = ["*", `!.gitignore`, ""].join(`
|
|
51142
|
+
`);
|
|
50861
51143
|
try {
|
|
50862
51144
|
if (!exists(ignorePath)) {
|
|
50863
|
-
|
|
51145
|
+
fs40.writeFileSync(ignorePath, desired);
|
|
50864
51146
|
return;
|
|
50865
51147
|
}
|
|
50866
|
-
const current =
|
|
50867
|
-
if (!current.split(/\r?\n/).some((l2) => l2.trim() ===
|
|
50868
|
-
|
|
51148
|
+
const current = fs40.readFileSync(ignorePath, "utf8");
|
|
51149
|
+
if (!current.split(/\r?\n/).some((l2) => l2.trim() === "*")) {
|
|
51150
|
+
fs40.writeFileSync(ignorePath, current.endsWith(`
|
|
50869
51151
|
`) ? current + desired : current + `
|
|
50870
51152
|
` + desired);
|
|
50871
51153
|
}
|
|
@@ -50873,15 +51155,15 @@ function ensureGitignore(cwd2) {
|
|
|
50873
51155
|
}
|
|
50874
51156
|
|
|
50875
51157
|
// src/core/route-adapters.ts
|
|
50876
|
-
import
|
|
51158
|
+
import path44 from "node:path";
|
|
50877
51159
|
import os10 from "node:os";
|
|
50878
|
-
import
|
|
51160
|
+
import fs41 from "node:fs";
|
|
50879
51161
|
var CLAUDE_ENV_KEYS = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN"];
|
|
50880
51162
|
function claudeSettingsPath(cwd2) {
|
|
50881
|
-
return
|
|
51163
|
+
return path44.join(cwd2, ".claude", "settings.json");
|
|
50882
51164
|
}
|
|
50883
51165
|
function claudeUserConfigPath() {
|
|
50884
|
-
return
|
|
51166
|
+
return path44.join(os10.homedir(), ".claude.json");
|
|
50885
51167
|
}
|
|
50886
51168
|
function ensureClaudeOnboarded() {
|
|
50887
51169
|
const file = claudeUserConfigPath();
|
|
@@ -50905,7 +51187,7 @@ var claudeRouteAdapter = {
|
|
|
50905
51187
|
settings.env = { ...settings.env ?? {} };
|
|
50906
51188
|
settings.env.ANTHROPIC_BASE_URL = target.apiBase;
|
|
50907
51189
|
settings.env.ANTHROPIC_AUTH_TOKEN = target.apiKey;
|
|
50908
|
-
ensureDir(
|
|
51190
|
+
ensureDir(path44.dirname(file));
|
|
50909
51191
|
writeJson(file, settings);
|
|
50910
51192
|
const notes = [];
|
|
50911
51193
|
if (ensureClaudeOnboarded()) {
|
|
@@ -50932,11 +51214,11 @@ var claudeRouteAdapter = {
|
|
|
50932
51214
|
delete settings.env;
|
|
50933
51215
|
}
|
|
50934
51216
|
if (snap && !snap.fileExisted && Object.keys(settings).length === 0) {
|
|
50935
|
-
|
|
50936
|
-
const dir =
|
|
51217
|
+
fs41.rmSync(file);
|
|
51218
|
+
const dir = path44.dirname(file);
|
|
50937
51219
|
try {
|
|
50938
|
-
if (
|
|
50939
|
-
|
|
51220
|
+
if (fs41.readdirSync(dir).length === 0)
|
|
51221
|
+
fs41.rmdirSync(dir);
|
|
50940
51222
|
} catch {}
|
|
50941
51223
|
return;
|
|
50942
51224
|
}
|
|
@@ -50946,20 +51228,20 @@ var claudeRouteAdapter = {
|
|
|
50946
51228
|
var CODEX_PROVIDER_KEY = "brainbase";
|
|
50947
51229
|
var CODEX_AUTH_HEADER = "Authorization";
|
|
50948
51230
|
function codexConfigPath(cwd2) {
|
|
50949
|
-
return
|
|
51231
|
+
return path44.join(cwd2, ".codex", "config.toml");
|
|
50950
51232
|
}
|
|
50951
51233
|
function readCodexConfig2(file) {
|
|
50952
51234
|
if (!exists(file))
|
|
50953
51235
|
return {};
|
|
50954
51236
|
try {
|
|
50955
|
-
return parse(
|
|
51237
|
+
return parse(fs41.readFileSync(file, "utf8"));
|
|
50956
51238
|
} catch {
|
|
50957
51239
|
return {};
|
|
50958
51240
|
}
|
|
50959
51241
|
}
|
|
50960
51242
|
function writeCodexConfig2(file, value) {
|
|
50961
|
-
ensureDir(
|
|
50962
|
-
|
|
51243
|
+
ensureDir(path44.dirname(file));
|
|
51244
|
+
fs41.writeFileSync(file, stringify(value) + `
|
|
50963
51245
|
`);
|
|
50964
51246
|
}
|
|
50965
51247
|
function ensureV1(base2) {
|
|
@@ -51015,11 +51297,11 @@ var codexRouteAdapter = {
|
|
|
51015
51297
|
}
|
|
51016
51298
|
}
|
|
51017
51299
|
if (snap && !snap.fileExisted && Object.keys(cfg).length === 0) {
|
|
51018
|
-
|
|
51019
|
-
const dir =
|
|
51300
|
+
fs41.rmSync(file);
|
|
51301
|
+
const dir = path44.dirname(file);
|
|
51020
51302
|
try {
|
|
51021
|
-
if (
|
|
51022
|
-
|
|
51303
|
+
if (fs41.readdirSync(dir).length === 0)
|
|
51304
|
+
fs41.rmdirSync(dir);
|
|
51023
51305
|
} catch {}
|
|
51024
51306
|
return;
|
|
51025
51307
|
}
|
|
@@ -51309,8 +51591,8 @@ async function runUnlink(cwd2, args) {
|
|
|
51309
51591
|
}
|
|
51310
51592
|
|
|
51311
51593
|
// src/cli/sync.ts
|
|
51312
|
-
import
|
|
51313
|
-
import
|
|
51594
|
+
import path45 from "node:path";
|
|
51595
|
+
import fs42 from "node:fs";
|
|
51314
51596
|
import os11 from "node:os";
|
|
51315
51597
|
import crypto3 from "node:crypto";
|
|
51316
51598
|
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
@@ -51504,7 +51786,7 @@ async function runSync(cwd2, args) {
|
|
|
51504
51786
|
type: c2.type,
|
|
51505
51787
|
slug: c2.slug,
|
|
51506
51788
|
scope,
|
|
51507
|
-
rootDir:
|
|
51789
|
+
rootDir: path45.join(stageRoot, c2.type, c2.slug),
|
|
51508
51790
|
description: c2.description,
|
|
51509
51791
|
meta: c2.meta,
|
|
51510
51792
|
payload: c2.meta?.mcp,
|
|
@@ -51553,11 +51835,11 @@ async function runSync(cwd2, args) {
|
|
|
51553
51835
|
if (!exists(filePath))
|
|
51554
51836
|
continue;
|
|
51555
51837
|
try {
|
|
51556
|
-
const stat =
|
|
51838
|
+
const stat = fs42.statSync(filePath);
|
|
51557
51839
|
if (stat.isDirectory())
|
|
51558
|
-
|
|
51840
|
+
fs42.rmSync(filePath, { recursive: true, force: true });
|
|
51559
51841
|
else
|
|
51560
|
-
|
|
51842
|
+
fs42.rmSync(filePath);
|
|
51561
51843
|
} catch (err) {
|
|
51562
51844
|
f2.warn(`Failed to remove ${filePath}: ${err.message}`);
|
|
51563
51845
|
}
|
|
@@ -51595,7 +51877,7 @@ async function runSync(cwd2, args) {
|
|
|
51595
51877
|
$e(`Synced ${link2.name} to revision ${manifest.revision}.`);
|
|
51596
51878
|
} finally {
|
|
51597
51879
|
try {
|
|
51598
|
-
|
|
51880
|
+
fs42.rmSync(stageRoot, { recursive: true, force: true });
|
|
51599
51881
|
} catch {}
|
|
51600
51882
|
}
|
|
51601
51883
|
}
|
|
@@ -51643,14 +51925,14 @@ function computeLocalHash(paths) {
|
|
|
51643
51925
|
if (!exists(filePath))
|
|
51644
51926
|
return null;
|
|
51645
51927
|
try {
|
|
51646
|
-
const stat =
|
|
51928
|
+
const stat = fs42.statSync(filePath);
|
|
51647
51929
|
if (stat.isFile()) {
|
|
51648
51930
|
h2.update("F " + filePath + " ");
|
|
51649
|
-
h2.update(
|
|
51931
|
+
h2.update(fs42.readFileSync(filePath));
|
|
51650
51932
|
h2.update(`
|
|
51651
51933
|
`);
|
|
51652
51934
|
} else if (stat.isDirectory()) {
|
|
51653
|
-
for (const name of
|
|
51935
|
+
for (const name of fs42.readdirSync(filePath).sort()) {
|
|
51654
51936
|
h2.update("E " + name + `
|
|
51655
51937
|
`);
|
|
51656
51938
|
}
|
|
@@ -51662,14 +51944,14 @@ function computeLocalHash(paths) {
|
|
|
51662
51944
|
return h2.digest("hex");
|
|
51663
51945
|
}
|
|
51664
51946
|
function stageManifest(components) {
|
|
51665
|
-
const root =
|
|
51947
|
+
const root = fs42.mkdtempSync(path45.join(os11.tmpdir(), "brainbase-sync-"));
|
|
51666
51948
|
for (const c2 of components) {
|
|
51667
|
-
const compDir =
|
|
51949
|
+
const compDir = path45.join(root, c2.type, c2.slug);
|
|
51668
51950
|
ensureDir(compDir);
|
|
51669
51951
|
for (const f4 of c2.files) {
|
|
51670
|
-
const target =
|
|
51671
|
-
ensureDir(
|
|
51672
|
-
|
|
51952
|
+
const target = path45.join(compDir, f4.path);
|
|
51953
|
+
ensureDir(path45.dirname(target));
|
|
51954
|
+
fs42.writeFileSync(target, f4.content);
|
|
51673
51955
|
}
|
|
51674
51956
|
}
|
|
51675
51957
|
return root;
|
|
@@ -51683,111 +51965,15 @@ function runHarnessInstall(harnessId, components, opts, agentName) {
|
|
|
51683
51965
|
}
|
|
51684
51966
|
|
|
51685
51967
|
// src/cli/agent.ts
|
|
51686
|
-
var
|
|
51968
|
+
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
51687
51969
|
|
|
51688
51970
|
// src/cli/agent-pull.ts
|
|
51971
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
51689
51972
|
import path48 from "node:path";
|
|
51690
51973
|
import fs45 from "node:fs";
|
|
51691
51974
|
import os12 from "node:os";
|
|
51692
51975
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
51693
51976
|
|
|
51694
|
-
// src/core/agent-manifest.ts
|
|
51695
|
-
import path45 from "node:path";
|
|
51696
|
-
import fs42 from "node:fs";
|
|
51697
|
-
var import_yaml2 = __toESM(require_dist(), 1);
|
|
51698
|
-
var AGENT_MANIFEST_FILE = "brainbase.yaml";
|
|
51699
|
-
var DEFAULT_INSTRUCTIONS_FILE = "instructions.md";
|
|
51700
|
-
var REGISTRY_SOURCE_RE = /^registry:(?:([a-z0-9_-]+)\/)?([a-z0-9_-]+)(?:@(.+))?$/i;
|
|
51701
|
-
function parseSkillSource2(raw) {
|
|
51702
|
-
if (!raw || typeof raw !== "string") {
|
|
51703
|
-
throw new Error("Skill source must be a non-empty string");
|
|
51704
|
-
}
|
|
51705
|
-
const m3 = raw.match(REGISTRY_SOURCE_RE);
|
|
51706
|
-
if (m3) {
|
|
51707
|
-
return {
|
|
51708
|
-
kind: "registry",
|
|
51709
|
-
...m3[1] ? { creator: m3[1] } : {},
|
|
51710
|
-
slug: m3[2],
|
|
51711
|
-
version: m3[3]
|
|
51712
|
-
};
|
|
51713
|
-
}
|
|
51714
|
-
if (raw.startsWith("./") || raw.startsWith("../") || raw.startsWith("/")) {
|
|
51715
|
-
return { kind: "local", path: raw };
|
|
51716
|
-
}
|
|
51717
|
-
throw new Error(`Unrecognized skill source "${raw}". Expected "registry:creator/slug[@version]", "registry:slug", or a relative path starting with "./".`);
|
|
51718
|
-
}
|
|
51719
|
-
var AgentMetaSchema = exports_external.object({
|
|
51720
|
-
name: exports_external.string().min(1),
|
|
51721
|
-
tagline: exports_external.string().optional()
|
|
51722
|
-
});
|
|
51723
|
-
var InstructionsSchema = exports_external.object({
|
|
51724
|
-
file: exports_external.string().min(1)
|
|
51725
|
-
});
|
|
51726
|
-
var SkillEntrySchema = exports_external.object({
|
|
51727
|
-
source: exports_external.string().min(1)
|
|
51728
|
-
});
|
|
51729
|
-
var McpEntrySchema = exports_external.object({
|
|
51730
|
-
name: exports_external.string().min(1),
|
|
51731
|
-
url: exports_external.string().optional(),
|
|
51732
|
-
command: exports_external.string().optional(),
|
|
51733
|
-
args: exports_external.array(exports_external.string()).optional(),
|
|
51734
|
-
env: exports_external.record(exports_external.string()).optional(),
|
|
51735
|
-
headers: exports_external.record(exports_external.string()).optional(),
|
|
51736
|
-
is_enabled: exports_external.boolean().optional()
|
|
51737
|
-
});
|
|
51738
|
-
var AgentManifestSchema = exports_external.object({
|
|
51739
|
-
schema: exports_external.literal(1),
|
|
51740
|
-
agent: AgentMetaSchema,
|
|
51741
|
-
instructions: InstructionsSchema.optional(),
|
|
51742
|
-
skills: exports_external.array(SkillEntrySchema).default([]),
|
|
51743
|
-
mcp: exports_external.array(McpEntrySchema).default([]),
|
|
51744
|
-
commands: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
51745
|
-
hooks: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
51746
|
-
files: exports_external.array(exports_external.record(exports_external.unknown())).optional()
|
|
51747
|
-
});
|
|
51748
|
-
function manifestPath(cwd2) {
|
|
51749
|
-
return path45.join(cwd2, AGENT_MANIFEST_FILE);
|
|
51750
|
-
}
|
|
51751
|
-
function hasManifest(cwd2) {
|
|
51752
|
-
return fs42.existsSync(manifestPath(cwd2));
|
|
51753
|
-
}
|
|
51754
|
-
function readManifest(cwd2) {
|
|
51755
|
-
const p2 = manifestPath(cwd2);
|
|
51756
|
-
if (!fs42.existsSync(p2))
|
|
51757
|
-
return null;
|
|
51758
|
-
const raw = fs42.readFileSync(p2, "utf8");
|
|
51759
|
-
let parsed;
|
|
51760
|
-
try {
|
|
51761
|
-
parsed = import_yaml2.default.parse(raw);
|
|
51762
|
-
} catch (err) {
|
|
51763
|
-
throw new Error(`${AGENT_MANIFEST_FILE} is not valid YAML: ${err.message}`);
|
|
51764
|
-
}
|
|
51765
|
-
const result = AgentManifestSchema.safeParse(parsed);
|
|
51766
|
-
if (!result.success) {
|
|
51767
|
-
throw new Error(`${AGENT_MANIFEST_FILE} is invalid: ${result.error.issues.map((i) => `${i.path.join(".") || "(root)"} — ${i.message}`).join("; ")}`);
|
|
51768
|
-
}
|
|
51769
|
-
return result.data;
|
|
51770
|
-
}
|
|
51771
|
-
function writeManifest(cwd2, manifest) {
|
|
51772
|
-
const doc = new import_yaml2.default.Document;
|
|
51773
|
-
doc.contents = manifest;
|
|
51774
|
-
doc.commentBefore = ` brainbase.yaml — declarative agent manifest.
|
|
51775
|
-
` + " Committed to source control. Edit by hand, then `brainbase agent push`.";
|
|
51776
|
-
const out = String(doc);
|
|
51777
|
-
fs42.writeFileSync(manifestPath(cwd2), out, "utf8");
|
|
51778
|
-
}
|
|
51779
|
-
function resolveInstructionsPath(cwd2, manifest) {
|
|
51780
|
-
if (!manifest.instructions)
|
|
51781
|
-
return null;
|
|
51782
|
-
return path45.resolve(cwd2, manifest.instructions.file);
|
|
51783
|
-
}
|
|
51784
|
-
function readInstructions(cwd2, manifest) {
|
|
51785
|
-
const p2 = resolveInstructionsPath(cwd2, manifest);
|
|
51786
|
-
if (!p2 || !fs42.existsSync(p2))
|
|
51787
|
-
return null;
|
|
51788
|
-
return fs42.readFileSync(p2, "utf8");
|
|
51789
|
-
}
|
|
51790
|
-
|
|
51791
51977
|
// src/core/agent-diff.ts
|
|
51792
51978
|
import path46 from "node:path";
|
|
51793
51979
|
import fs43 from "node:fs";
|
|
@@ -52123,26 +52309,27 @@ function diffSecrets(local, cloud) {
|
|
|
52123
52309
|
// src/cli/agent-pull.ts
|
|
52124
52310
|
async function runAgentPull(cwd2, args) {
|
|
52125
52311
|
banner("agent pull — bring cloud changes into this folder");
|
|
52126
|
-
const
|
|
52127
|
-
if (!
|
|
52128
|
-
f2.warn("This folder is not linked to any agent.");
|
|
52129
|
-
f2.info(`Run ${import_picocolors25.default.cyan("brainbase link")} first.`);
|
|
52312
|
+
const resolution = resolveTargetAgentId(cwd2, args);
|
|
52313
|
+
if (!resolution)
|
|
52130
52314
|
return;
|
|
52131
|
-
}
|
|
52315
|
+
const { agentId, override } = resolution;
|
|
52132
52316
|
const sp = de();
|
|
52133
|
-
sp.start(
|
|
52317
|
+
sp.start("Fetching agent…");
|
|
52318
|
+
let cloudAgent;
|
|
52134
52319
|
let cloud;
|
|
52135
52320
|
try {
|
|
52136
|
-
|
|
52321
|
+
cloudAgent = await api.getAgent(agentId);
|
|
52322
|
+
cloud = await api.getAgentManifest(agentId);
|
|
52137
52323
|
sp.stop(`Cloud revision ${cloud.revision}.`);
|
|
52138
52324
|
} catch (err) {
|
|
52139
52325
|
sp.stop("Failed.");
|
|
52140
52326
|
handleApiError2(err);
|
|
52141
52327
|
return;
|
|
52142
52328
|
}
|
|
52143
|
-
const
|
|
52144
|
-
const
|
|
52145
|
-
const
|
|
52329
|
+
const harness = normalizeHarnessId(cloudAgent.harness ?? "claude-code");
|
|
52330
|
+
const existingManifest = !override && hasManifest(cwd2) ? safeReadManifest(cwd2) : null;
|
|
52331
|
+
const lock = override ? null : readSyncState(cwd2);
|
|
52332
|
+
const localComponents = existingManifest ? readLocalComponents(cwd2, existingManifest) : [];
|
|
52146
52333
|
const rows = threeWayDiff({
|
|
52147
52334
|
local: localComponents,
|
|
52148
52335
|
lock: lock?.components ?? [],
|
|
@@ -52167,7 +52354,11 @@ async function runAgentPull(cwd2, args) {
|
|
|
52167
52354
|
break;
|
|
52168
52355
|
case "modified-both":
|
|
52169
52356
|
case "modified-local":
|
|
52170
|
-
|
|
52357
|
+
if (override) {
|
|
52358
|
+
toInstallKeys.add(r2.key);
|
|
52359
|
+
} else {
|
|
52360
|
+
conflicts.push(r2);
|
|
52361
|
+
}
|
|
52171
52362
|
break;
|
|
52172
52363
|
}
|
|
52173
52364
|
}
|
|
@@ -52191,11 +52382,12 @@ async function runAgentPull(cwd2, args) {
|
|
|
52191
52382
|
const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
|
|
52192
52383
|
const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
|
|
52193
52384
|
const needMemoryMcpInstall = !cloudHasMemoryMcp;
|
|
52194
|
-
if (toInstallKeys.size === 0 && toRemoveKeys.size === 0 && !needOrchestrationMcpInstall && !needMemoryMcpInstall) {
|
|
52385
|
+
if (toInstallKeys.size === 0 && toRemoveKeys.size === 0 && !needOrchestrationMcpInstall && !needMemoryMcpInstall && !override) {
|
|
52195
52386
|
f2.info(`You're up to date.`);
|
|
52196
|
-
|
|
52197
|
-
|
|
52198
|
-
|
|
52387
|
+
writeLink(cwd2, buildLinkFromAgent(cloudAgent, harness, readLink(cwd2)));
|
|
52388
|
+
writeSyncState(cwd2, buildLockFromCloud(agentId, cloud, lock, cloudAgent));
|
|
52389
|
+
if (!existingManifest) {
|
|
52390
|
+
writeManifest(cwd2, mergeManifest(cwd2, null, cloud, cloudAgent, harness));
|
|
52199
52391
|
f2.info(`Wrote ${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)}.`);
|
|
52200
52392
|
}
|
|
52201
52393
|
return;
|
|
@@ -52225,20 +52417,20 @@ async function runAgentPull(cwd2, args) {
|
|
|
52225
52417
|
});
|
|
52226
52418
|
}
|
|
52227
52419
|
await showResultCard({
|
|
52228
|
-
title: "PULL",
|
|
52229
|
-
tone: "info",
|
|
52230
|
-
subtitle: `updates for ${
|
|
52420
|
+
title: override ? "PULL (FORCE)" : "PULL",
|
|
52421
|
+
tone: override ? "warn" : "info",
|
|
52422
|
+
subtitle: `updates for ${cloudAgent.name}`,
|
|
52231
52423
|
rows: resultRows
|
|
52232
52424
|
});
|
|
52233
52425
|
if (!args.yes) {
|
|
52234
|
-
const
|
|
52426
|
+
const msg = override ? "Apply these changes? Local edits to overlapping components will be discarded." : "Apply these changes?";
|
|
52427
|
+
const ok = await se({ message: msg, initialValue: true });
|
|
52235
52428
|
if (!ensureNotCancelled(ok)) {
|
|
52236
52429
|
$e("Aborted.");
|
|
52237
52430
|
return;
|
|
52238
52431
|
}
|
|
52239
52432
|
}
|
|
52240
|
-
const
|
|
52241
|
-
const adapter = getAdapter(adapterId);
|
|
52433
|
+
const adapter = getAdapter(harness);
|
|
52242
52434
|
const scope = args.scope ?? "project";
|
|
52243
52435
|
const installComponents = cloud.components.filter((c2) => toInstallKeys.has(`${c2.type}/${c2.slug}`));
|
|
52244
52436
|
const stageRoot = stageManifestComponents(installComponents);
|
|
@@ -52270,7 +52462,7 @@ async function runAgentPull(cwd2, args) {
|
|
|
52270
52462
|
resolveConflict: async (_c) => "overwrite",
|
|
52271
52463
|
resolveSecret: async () => null
|
|
52272
52464
|
};
|
|
52273
|
-
const result = await runHarnessInstall2(adapter.id, toInstall, opts,
|
|
52465
|
+
const result = await runHarnessInstall2(adapter.id, toInstall, opts, cloudAgent.name);
|
|
52274
52466
|
installSpinner.stop("Applied.");
|
|
52275
52467
|
for (const o2 of result.installed) {
|
|
52276
52468
|
justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
|
|
@@ -52298,8 +52490,10 @@ async function runAgentPull(cwd2, args) {
|
|
|
52298
52490
|
}
|
|
52299
52491
|
}
|
|
52300
52492
|
materializeInstructions(cwd2, cloud, toInstallKeys, keepLocalKeys);
|
|
52301
|
-
|
|
52493
|
+
materializeEntrypoint(cwd2, cloudAgent.entrypoint ?? "", existingManifest);
|
|
52494
|
+
const yaml = mergeManifest(cwd2, existingManifest, cloud, cloudAgent, harness);
|
|
52302
52495
|
writeManifest(cwd2, yaml);
|
|
52496
|
+
writeLink(cwd2, buildLinkFromAgent(cloudAgent, harness, readLink(cwd2)));
|
|
52303
52497
|
const lockComponents = buildLockComponents({
|
|
52304
52498
|
cloud,
|
|
52305
52499
|
prevLock: lock,
|
|
@@ -52309,21 +52503,64 @@ async function runAgentPull(cwd2, args) {
|
|
|
52309
52503
|
});
|
|
52310
52504
|
const newState = {
|
|
52311
52505
|
schemaVersion: 1,
|
|
52312
|
-
agent_id:
|
|
52506
|
+
agent_id: agentId,
|
|
52313
52507
|
revision: cloud.revision,
|
|
52314
52508
|
synced_at: new Date().toISOString(),
|
|
52315
52509
|
components: lockComponents,
|
|
52316
|
-
agentMeta: {
|
|
52510
|
+
agentMeta: {
|
|
52511
|
+
name: cloudAgent.name,
|
|
52512
|
+
tagline: cloudAgent.tagline,
|
|
52513
|
+
...cloudAgent.entrypoint ? { entrypoint: cloudAgent.entrypoint } : {}
|
|
52514
|
+
}
|
|
52317
52515
|
};
|
|
52318
52516
|
writeSyncState(cwd2, newState);
|
|
52319
|
-
await pullSecrets(cwd2,
|
|
52320
|
-
|
|
52517
|
+
await pullSecrets(cwd2, agentId);
|
|
52518
|
+
await runEntrypointIfPresent(cwd2, yaml);
|
|
52519
|
+
$e(`Pulled ${cloudAgent.name} at revision ${cloud.revision}.`);
|
|
52321
52520
|
} finally {
|
|
52322
52521
|
try {
|
|
52323
52522
|
fs45.rmSync(stageRoot, { recursive: true, force: true });
|
|
52324
52523
|
} catch {}
|
|
52325
52524
|
}
|
|
52326
52525
|
}
|
|
52526
|
+
function resolveTargetAgentId(cwd2, args) {
|
|
52527
|
+
const arg = args.agentIdArg?.trim() || undefined;
|
|
52528
|
+
let manifest = null;
|
|
52529
|
+
try {
|
|
52530
|
+
manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
52531
|
+
} catch (err) {
|
|
52532
|
+
f2.error(err.message);
|
|
52533
|
+
return null;
|
|
52534
|
+
}
|
|
52535
|
+
const manifestId = manifest?.id;
|
|
52536
|
+
if (arg && manifestId && arg !== manifestId) {
|
|
52537
|
+
if (!args.force) {
|
|
52538
|
+
f2.error(`This folder is already linked to a different agent (${import_picocolors25.default.dim(manifestId)}).`);
|
|
52539
|
+
f2.info(`Run ${import_picocolors25.default.cyan(`brainbase agent pull ${arg} --force`)} to override. ` + import_picocolors25.default.yellow("This will overwrite brainbase.agent.yaml and any local progress will be lost."));
|
|
52540
|
+
return null;
|
|
52541
|
+
}
|
|
52542
|
+
return { agentId: arg, override: true };
|
|
52543
|
+
}
|
|
52544
|
+
if (arg)
|
|
52545
|
+
return { agentId: arg, override: false };
|
|
52546
|
+
if (manifestId)
|
|
52547
|
+
return { agentId: manifestId, override: false };
|
|
52548
|
+
if (manifest) {
|
|
52549
|
+
f2.error(`${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)} is unclaimed (no ${import_picocolors25.default.cyan("id")}).`);
|
|
52550
|
+
f2.info(`Run ${import_picocolors25.default.cyan("brainbase agent create")} to create a new agent from this manifest, ` + `or ${import_picocolors25.default.cyan("brainbase agent pull <id>")} to pull an existing one.`);
|
|
52551
|
+
} else {
|
|
52552
|
+
f2.error(`No ${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)} here and no ${import_picocolors25.default.cyan("<id>")} given.`);
|
|
52553
|
+
f2.info(`Run ${import_picocolors25.default.cyan("brainbase agent pull <id>")} to pull an existing agent into this folder.`);
|
|
52554
|
+
}
|
|
52555
|
+
return null;
|
|
52556
|
+
}
|
|
52557
|
+
function safeReadManifest(cwd2) {
|
|
52558
|
+
try {
|
|
52559
|
+
return readManifest(cwd2);
|
|
52560
|
+
} catch {
|
|
52561
|
+
return null;
|
|
52562
|
+
}
|
|
52563
|
+
}
|
|
52327
52564
|
function skillSourceFromMeta(c2) {
|
|
52328
52565
|
if (c2.type !== "skill")
|
|
52329
52566
|
return;
|
|
@@ -52373,7 +52610,7 @@ function materializeInstructions(cwd2, cloud, toInstall, keepLocal) {
|
|
|
52373
52610
|
fs45.writeFileSync(path48.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
|
|
52374
52611
|
}
|
|
52375
52612
|
}
|
|
52376
|
-
function mergeManifest(cwd2, prev, cloud,
|
|
52613
|
+
function mergeManifest(cwd2, prev, cloud, cloudAgent, harness) {
|
|
52377
52614
|
const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
|
|
52378
52615
|
const localDecl = prev?.skills.find((s3) => {
|
|
52379
52616
|
try {
|
|
@@ -52396,7 +52633,18 @@ function mergeManifest(cwd2, prev, cloud, link2) {
|
|
|
52396
52633
|
}
|
|
52397
52634
|
return { source: `registry:${c2.slug}` };
|
|
52398
52635
|
});
|
|
52399
|
-
const
|
|
52636
|
+
const cloudInstrComp = cloud.components.find((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
|
|
52637
|
+
const instructions = cloudInstrComp ? prev?.instructions?.text !== undefined ? { text: cloudInstrComp.files[0].content } : { file: prev?.instructions?.file ?? DEFAULT_INSTRUCTIONS_FILE } : undefined;
|
|
52638
|
+
const cloudEntrypoint = (cloudAgent.entrypoint ?? "").trim();
|
|
52639
|
+
let entrypoint;
|
|
52640
|
+
if (cloudEntrypoint.length > 0) {
|
|
52641
|
+
if (prev?.entrypoint?.commands)
|
|
52642
|
+
entrypoint = { commands: prev.entrypoint.commands };
|
|
52643
|
+
else if (prev?.entrypoint?.text !== undefined)
|
|
52644
|
+
entrypoint = { text: cloudAgent.entrypoint };
|
|
52645
|
+
else
|
|
52646
|
+
entrypoint = { file: prev?.entrypoint?.file ?? DEFAULT_ENTRYPOINT_FILE };
|
|
52647
|
+
}
|
|
52400
52648
|
const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
|
|
52401
52649
|
const payload = (c2.meta ?? {}).mcp ?? {};
|
|
52402
52650
|
const entry = { name: c2.slug };
|
|
@@ -52416,17 +52664,32 @@ function mergeManifest(cwd2, prev, cloud, link2) {
|
|
|
52416
52664
|
});
|
|
52417
52665
|
return {
|
|
52418
52666
|
schema: 1,
|
|
52667
|
+
id: cloudAgent.id,
|
|
52668
|
+
harness,
|
|
52419
52669
|
agent: {
|
|
52420
|
-
name:
|
|
52421
|
-
...
|
|
52670
|
+
name: cloudAgent.name,
|
|
52671
|
+
...cloudAgent.tagline ? { tagline: cloudAgent.tagline } : {}
|
|
52422
52672
|
},
|
|
52423
|
-
...
|
|
52424
|
-
|
|
52425
|
-
} : {},
|
|
52673
|
+
...instructions ? { instructions } : {},
|
|
52674
|
+
...entrypoint ? { entrypoint } : {},
|
|
52426
52675
|
skills,
|
|
52427
52676
|
mcp
|
|
52428
52677
|
};
|
|
52429
52678
|
}
|
|
52679
|
+
function materializeEntrypoint(cwd2, cloudEntrypoint, prev) {
|
|
52680
|
+
if (!cloudEntrypoint.trim())
|
|
52681
|
+
return;
|
|
52682
|
+
if (prev?.entrypoint?.commands)
|
|
52683
|
+
return;
|
|
52684
|
+
if (prev?.entrypoint?.text !== undefined)
|
|
52685
|
+
return;
|
|
52686
|
+
const filename = prev?.entrypoint?.file ?? DEFAULT_ENTRYPOINT_FILE;
|
|
52687
|
+
const target = path48.resolve(cwd2, filename);
|
|
52688
|
+
fs45.writeFileSync(target, cloudEntrypoint, "utf8");
|
|
52689
|
+
try {
|
|
52690
|
+
fs45.chmodSync(target, 493);
|
|
52691
|
+
} catch {}
|
|
52692
|
+
}
|
|
52430
52693
|
function parseSourceLoose(raw) {
|
|
52431
52694
|
const m3 = raw.match(/^registry:[a-z0-9_-]+\/([a-z0-9_-]+)/i);
|
|
52432
52695
|
if (m3)
|
|
@@ -52468,7 +52731,7 @@ function buildLockComponents(input) {
|
|
|
52468
52731
|
}
|
|
52469
52732
|
return out;
|
|
52470
52733
|
}
|
|
52471
|
-
function buildLockFromCloud(agent_id, cloud, prev) {
|
|
52734
|
+
function buildLockFromCloud(agent_id, cloud, prev, cloudAgent) {
|
|
52472
52735
|
return {
|
|
52473
52736
|
schemaVersion: 1,
|
|
52474
52737
|
agent_id,
|
|
@@ -52480,11 +52743,73 @@ function buildLockFromCloud(agent_id, cloud, prev) {
|
|
|
52480
52743
|
hash: c2.hash,
|
|
52481
52744
|
installedPaths: []
|
|
52482
52745
|
})),
|
|
52483
|
-
agentMeta:
|
|
52746
|
+
agentMeta: cloudAgent ? {
|
|
52747
|
+
name: cloudAgent.name,
|
|
52748
|
+
tagline: cloudAgent.tagline,
|
|
52749
|
+
...cloudAgent.entrypoint ? { entrypoint: cloudAgent.entrypoint } : {}
|
|
52750
|
+
} : prev?.agentMeta
|
|
52751
|
+
};
|
|
52752
|
+
}
|
|
52753
|
+
function buildLinkFromAgent(agent, harness, prev) {
|
|
52754
|
+
return {
|
|
52755
|
+
schemaVersion: 1,
|
|
52756
|
+
agent_id: agent.id,
|
|
52757
|
+
org_id: agent.org_id ?? prev?.org_id ?? "",
|
|
52758
|
+
team_id: agent.team_id ?? prev?.team_id ?? "",
|
|
52759
|
+
slug: agent.slug,
|
|
52760
|
+
name: agent.name,
|
|
52761
|
+
tagline: agent.tagline,
|
|
52762
|
+
url: agent.url,
|
|
52763
|
+
linked_at: prev?.linked_at ?? new Date().toISOString(),
|
|
52764
|
+
linked_by: prev?.linked_by,
|
|
52765
|
+
harness,
|
|
52766
|
+
tracking: prev?.tracking
|
|
52484
52767
|
};
|
|
52485
52768
|
}
|
|
52486
|
-
function
|
|
52487
|
-
|
|
52769
|
+
async function runEntrypointIfPresent(cwd2, manifest) {
|
|
52770
|
+
if (!manifest.entrypoint)
|
|
52771
|
+
return;
|
|
52772
|
+
const body = resolveEntrypoint(cwd2, manifest);
|
|
52773
|
+
if (body === null || !body.trim())
|
|
52774
|
+
return;
|
|
52775
|
+
const stateDir = path48.join(cwd2, LINK_DIR);
|
|
52776
|
+
ensureDir(stateDir);
|
|
52777
|
+
const scriptPath = path48.join(stateDir, "entrypoint.sh");
|
|
52778
|
+
const logPath = path48.join(stateDir, "entrypoint.log");
|
|
52779
|
+
fs45.writeFileSync(scriptPath, body, "utf8");
|
|
52780
|
+
try {
|
|
52781
|
+
fs45.chmodSync(scriptPath, 493);
|
|
52782
|
+
} catch {}
|
|
52783
|
+
f2.info(`Running entrypoint ${import_picocolors25.default.dim(`(${path48.relative(cwd2, scriptPath)})`)}`);
|
|
52784
|
+
const secrets = readLocalSecrets(cwd2);
|
|
52785
|
+
const env3 = { ...process.env, ...secrets };
|
|
52786
|
+
const logStream = fs45.createWriteStream(logPath, { flags: "w" });
|
|
52787
|
+
const exitCode = await new Promise((resolve) => {
|
|
52788
|
+
const child = spawn2("bash", [scriptPath], {
|
|
52789
|
+
cwd: cwd2,
|
|
52790
|
+
env: env3,
|
|
52791
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
52792
|
+
});
|
|
52793
|
+
child.stdout?.on("data", (chunk) => {
|
|
52794
|
+
process.stdout.write(chunk);
|
|
52795
|
+
logStream.write(chunk);
|
|
52796
|
+
});
|
|
52797
|
+
child.stderr?.on("data", (chunk) => {
|
|
52798
|
+
process.stderr.write(chunk);
|
|
52799
|
+
logStream.write(chunk);
|
|
52800
|
+
});
|
|
52801
|
+
child.on("error", (err) => {
|
|
52802
|
+
f2.warn(`entrypoint failed to start: ${err.message}`);
|
|
52803
|
+
resolve(null);
|
|
52804
|
+
});
|
|
52805
|
+
child.on("exit", (code) => resolve(code));
|
|
52806
|
+
});
|
|
52807
|
+
await new Promise((resolve) => logStream.end(resolve));
|
|
52808
|
+
if (exitCode === 0) {
|
|
52809
|
+
f2.info("Entrypoint completed.");
|
|
52810
|
+
} else if (exitCode === null) {} else {
|
|
52811
|
+
f2.warn(`Entrypoint exited ${exitCode} — continuing. Log at ${import_picocolors25.default.dim(path48.relative(cwd2, logPath))}.`);
|
|
52812
|
+
}
|
|
52488
52813
|
}
|
|
52489
52814
|
async function pullSecrets(cwd2, agentId) {
|
|
52490
52815
|
let cloudSecrets;
|
|
@@ -52518,6 +52843,8 @@ function handleApiError2(err) {
|
|
|
52518
52843
|
if (err instanceof ApiError) {
|
|
52519
52844
|
if (err.status === 401) {
|
|
52520
52845
|
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
52846
|
+
} else if (err.status === 404) {
|
|
52847
|
+
f2.error(`Agent not found, or you don't have access. Double-check the id.`);
|
|
52521
52848
|
} else {
|
|
52522
52849
|
f2.error(err.message);
|
|
52523
52850
|
}
|
|
@@ -52527,18 +52854,96 @@ function handleApiError2(err) {
|
|
|
52527
52854
|
}
|
|
52528
52855
|
|
|
52529
52856
|
// src/cli/agent-push.ts
|
|
52857
|
+
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
52858
|
+
|
|
52859
|
+
// src/core/agent-outgoing.ts
|
|
52530
52860
|
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
52861
|
+
async function buildOutgoingComponents(cwd2, manifest, cloud) {
|
|
52862
|
+
const out = [];
|
|
52863
|
+
if (manifest.instructions) {
|
|
52864
|
+
if (manifest.instructions.text !== undefined && manifest.instructions.file !== undefined) {
|
|
52865
|
+
f2.error(`instructions block sets both ${import_picocolors26.default.cyan("text")} and ${import_picocolors26.default.cyan("file")} — pick one.`);
|
|
52866
|
+
return null;
|
|
52867
|
+
}
|
|
52868
|
+
const body = readInstructions(cwd2, manifest);
|
|
52869
|
+
if (body === null) {
|
|
52870
|
+
if (manifest.instructions.file) {
|
|
52871
|
+
f2.error(`Instructions file ${import_picocolors26.default.bold(manifest.instructions.file)} not found.`);
|
|
52872
|
+
} else {
|
|
52873
|
+
f2.error("Instructions block is empty.");
|
|
52874
|
+
}
|
|
52875
|
+
return null;
|
|
52876
|
+
}
|
|
52877
|
+
if (body.trim()) {
|
|
52878
|
+
const fileName = manifest.instructions.file ?? "instructions.md";
|
|
52879
|
+
const fileHash2 = hashString(body);
|
|
52880
|
+
const file = {
|
|
52881
|
+
path: fileName,
|
|
52882
|
+
content: body,
|
|
52883
|
+
hash: fileHash2
|
|
52884
|
+
};
|
|
52885
|
+
out.push({
|
|
52886
|
+
type: "instruction",
|
|
52887
|
+
slug: "agent-instructions",
|
|
52888
|
+
description: "Agent instructions",
|
|
52889
|
+
hash: componentHashFromFileHashes([fileHash2]),
|
|
52890
|
+
files: [file],
|
|
52891
|
+
meta: { source: "global_prompt" }
|
|
52892
|
+
});
|
|
52893
|
+
}
|
|
52894
|
+
}
|
|
52895
|
+
for (const entry of manifest.skills) {
|
|
52896
|
+
const parsed = parseSkillSource2(entry.source);
|
|
52897
|
+
if (parsed.kind === "local") {
|
|
52898
|
+
f2.error(`Skill ${import_picocolors26.default.bold(entry.source)} is a local-authored skill. Local skill push isn't supported yet — publish it to the registry first (\`brainbase skill publish\`).`);
|
|
52899
|
+
return null;
|
|
52900
|
+
}
|
|
52901
|
+
const cloudMatch = cloud?.components.find((c2) => c2.type === "skill" && c2.slug === parsed.slug);
|
|
52902
|
+
out.push({
|
|
52903
|
+
type: "skill",
|
|
52904
|
+
slug: parsed.slug,
|
|
52905
|
+
hash: cloudMatch?.hash ?? "",
|
|
52906
|
+
files: [],
|
|
52907
|
+
meta: {
|
|
52908
|
+
name: parsed.creator ? `${parsed.creator}/${parsed.slug}` : parsed.slug,
|
|
52909
|
+
...parsed.version ? { version: parsed.version } : {}
|
|
52910
|
+
}
|
|
52911
|
+
});
|
|
52912
|
+
}
|
|
52913
|
+
for (const entry of manifest.mcp ?? []) {
|
|
52914
|
+
if (!entry.url && !entry.command) {
|
|
52915
|
+
f2.error(`MCP ${import_picocolors26.default.bold(entry.name)} needs either ${import_picocolors26.default.cyan("url")} or ${import_picocolors26.default.cyan("command")}.`);
|
|
52916
|
+
return null;
|
|
52917
|
+
}
|
|
52918
|
+
const payload = {};
|
|
52919
|
+
if (entry.url !== undefined)
|
|
52920
|
+
payload.url = entry.url;
|
|
52921
|
+
if (entry.command !== undefined)
|
|
52922
|
+
payload.command = entry.command;
|
|
52923
|
+
if (entry.args !== undefined)
|
|
52924
|
+
payload.args = entry.args;
|
|
52925
|
+
if (entry.env !== undefined)
|
|
52926
|
+
payload.env = entry.env;
|
|
52927
|
+
if (entry.headers !== undefined)
|
|
52928
|
+
payload.headers = entry.headers;
|
|
52929
|
+
payload.is_enabled = entry.is_enabled ?? true;
|
|
52930
|
+
out.push({
|
|
52931
|
+
type: "mcp",
|
|
52932
|
+
slug: entry.name,
|
|
52933
|
+
hash: "",
|
|
52934
|
+
files: [],
|
|
52935
|
+
meta: { mcp: payload }
|
|
52936
|
+
});
|
|
52937
|
+
}
|
|
52938
|
+
return out;
|
|
52939
|
+
}
|
|
52940
|
+
|
|
52941
|
+
// src/cli/agent-push.ts
|
|
52531
52942
|
async function runAgentPush(cwd2, args) {
|
|
52532
52943
|
banner("agent push — send your local changes to the cloud");
|
|
52533
|
-
const link2 = readLink(cwd2);
|
|
52534
|
-
if (!link2) {
|
|
52535
|
-
f2.warn("This folder is not linked to any agent.");
|
|
52536
|
-
f2.info(`Run ${import_picocolors26.default.cyan("brainbase link")} first.`);
|
|
52537
|
-
return;
|
|
52538
|
-
}
|
|
52539
52944
|
if (!hasManifest(cwd2)) {
|
|
52540
|
-
f2.warn(`No ${
|
|
52541
|
-
f2.info(`Run ${
|
|
52945
|
+
f2.warn(`No ${import_picocolors27.default.bold(AGENT_MANIFEST_FILE)} here.`);
|
|
52946
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent create")} to claim a new agent from a manifest, ` + `or ${import_picocolors27.default.cyan("brainbase agent pull <id>")} to pull an existing one.`);
|
|
52542
52947
|
return;
|
|
52543
52948
|
}
|
|
52544
52949
|
let manifest;
|
|
@@ -52548,11 +52953,17 @@ async function runAgentPush(cwd2, args) {
|
|
|
52548
52953
|
f2.error(err.message);
|
|
52549
52954
|
return;
|
|
52550
52955
|
}
|
|
52956
|
+
if (!manifest.id) {
|
|
52957
|
+
f2.warn(`${import_picocolors27.default.bold(AGENT_MANIFEST_FILE)} is unclaimed (no ${import_picocolors27.default.cyan("id")}). Nothing to push to.`);
|
|
52958
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent create")} first — that creates the cloud agent and stamps an id here.`);
|
|
52959
|
+
return;
|
|
52960
|
+
}
|
|
52961
|
+
const agentId = manifest.id;
|
|
52551
52962
|
const sp = de();
|
|
52552
|
-
sp.start(`Fetching cloud state
|
|
52963
|
+
sp.start(`Fetching cloud state…`);
|
|
52553
52964
|
let cloud;
|
|
52554
52965
|
try {
|
|
52555
|
-
cloud = await api.getAgentManifest(
|
|
52966
|
+
cloud = await api.getAgentManifest(agentId);
|
|
52556
52967
|
sp.stop(`Cloud revision ${cloud.revision}.`);
|
|
52557
52968
|
} catch (err) {
|
|
52558
52969
|
sp.stop("Failed.");
|
|
@@ -52565,17 +52976,42 @@ async function runAgentPush(cwd2, args) {
|
|
|
52565
52976
|
lock: lock?.components ?? [],
|
|
52566
52977
|
cloud: cloud.components
|
|
52567
52978
|
});
|
|
52568
|
-
|
|
52979
|
+
let cloudMeta = lock?.agentMeta;
|
|
52980
|
+
if (!cloudMeta) {
|
|
52981
|
+
try {
|
|
52982
|
+
const a3 = await api.getAgent(agentId);
|
|
52983
|
+
cloudMeta = { name: a3.name, tagline: a3.tagline, entrypoint: a3.entrypoint };
|
|
52984
|
+
} catch {}
|
|
52985
|
+
}
|
|
52986
|
+
const meta = diffAgentMeta(manifest.agent, lock?.agentMeta, cloudMeta);
|
|
52987
|
+
let resolvedEntrypoint;
|
|
52988
|
+
if (manifest.entrypoint) {
|
|
52989
|
+
const body = resolveEntrypoint(cwd2, manifest);
|
|
52990
|
+
if (body === null) {
|
|
52991
|
+
if (manifest.entrypoint.file) {
|
|
52992
|
+
f2.error(`Entrypoint file ${import_picocolors27.default.bold(manifest.entrypoint.file)} not found.`);
|
|
52993
|
+
} else {
|
|
52994
|
+
f2.error("Entrypoint block is empty.");
|
|
52995
|
+
}
|
|
52996
|
+
return;
|
|
52997
|
+
}
|
|
52998
|
+
resolvedEntrypoint = body;
|
|
52999
|
+
} else {
|
|
53000
|
+
if ((lock?.agentMeta?.entrypoint ?? "") !== "") {
|
|
53001
|
+
resolvedEntrypoint = "";
|
|
53002
|
+
}
|
|
53003
|
+
}
|
|
53004
|
+
const entrypointChanged = resolvedEntrypoint !== undefined && resolvedEntrypoint !== (lock?.agentMeta?.entrypoint ?? "");
|
|
52569
53005
|
for (const r2 of rows) {
|
|
52570
53006
|
if (r2.type !== "instruction" && r2.type !== "skill" && r2.type !== "mcp") {
|
|
52571
|
-
f2.error(`Component ${fmtType(r2.type)} ${
|
|
53007
|
+
f2.error(`Component ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)} can't be pushed yet — the server accepts instructions, skills, and mcps in this version.`);
|
|
52572
53008
|
return;
|
|
52573
53009
|
}
|
|
52574
53010
|
}
|
|
52575
53011
|
for (const entry of manifest.skills) {
|
|
52576
53012
|
const parsed = parseSkillSource2(entry.source);
|
|
52577
53013
|
if (parsed.kind === "local") {
|
|
52578
|
-
f2.error(`Skill ${
|
|
53014
|
+
f2.error(`Skill ${import_picocolors27.default.bold(entry.source)} is a local-authored skill. Local skill push isn't supported yet — publish it to the registry first (\`brainbase skill publish\`).`);
|
|
52579
53015
|
return;
|
|
52580
53016
|
}
|
|
52581
53017
|
}
|
|
@@ -52599,22 +53035,22 @@ async function runAgentPush(cwd2, args) {
|
|
|
52599
53035
|
break;
|
|
52600
53036
|
}
|
|
52601
53037
|
}
|
|
52602
|
-
if (!meta.localChanged && toSend.length === 0 && conflicts.length === 0) {
|
|
53038
|
+
if (!meta.localChanged && !entrypointChanged && toSend.length === 0 && conflicts.length === 0) {
|
|
52603
53039
|
f2.info("Nothing to push — local is in sync with the cloud.");
|
|
52604
53040
|
return;
|
|
52605
53041
|
}
|
|
52606
53042
|
if (conflicts.length > 0) {
|
|
52607
53043
|
f2.error(`Cannot push: ${conflicts.length} component${conflicts.length === 1 ? "" : "s"} changed both locally and on the cloud:`);
|
|
52608
53044
|
for (const r2 of conflicts) {
|
|
52609
|
-
console.error(` ${
|
|
53045
|
+
console.error(` ${import_picocolors27.default.red("!")} ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)}`);
|
|
52610
53046
|
}
|
|
52611
|
-
f2.info(`Run ${
|
|
53047
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent pull")} first to reconcile, then push again.`);
|
|
52612
53048
|
return;
|
|
52613
53049
|
}
|
|
52614
53050
|
if (upstreamOnly.length > 0 && !args.yes) {
|
|
52615
53051
|
f2.warn(`Cloud has ${upstreamOnly.length} change${upstreamOnly.length === 1 ? "" : "s"} you don't have locally:`);
|
|
52616
53052
|
for (const r2 of upstreamOnly) {
|
|
52617
|
-
console.warn(` ${
|
|
53053
|
+
console.warn(` ${import_picocolors27.default.cyan("←")} ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)} ${import_picocolors27.default.dim(`(${r2.status})`)}`);
|
|
52618
53054
|
}
|
|
52619
53055
|
f2.info(`If you push now, your push targets revision ${cloud.revision} and may race. Consider \`brainbase agent pull\` first.`);
|
|
52620
53056
|
}
|
|
@@ -52626,6 +53062,13 @@ async function runAgentPush(cwd2, args) {
|
|
|
52626
53062
|
text: "name/tagline"
|
|
52627
53063
|
});
|
|
52628
53064
|
}
|
|
53065
|
+
if (entrypointChanged) {
|
|
53066
|
+
resultRows.push({
|
|
53067
|
+
type: "upd",
|
|
53068
|
+
label: "entrypoint",
|
|
53069
|
+
text: resolvedEntrypoint === "" ? "cleared" : "updated"
|
|
53070
|
+
});
|
|
53071
|
+
}
|
|
52629
53072
|
if (toSend.length) {
|
|
52630
53073
|
resultRows.push({
|
|
52631
53074
|
type: "add",
|
|
@@ -52636,7 +53079,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
52636
53079
|
await showResultCard({
|
|
52637
53080
|
title: "PUSH",
|
|
52638
53081
|
tone: "info",
|
|
52639
|
-
subtitle: `${
|
|
53082
|
+
subtitle: `${manifest.agent.name} ← local`,
|
|
52640
53083
|
rows: resultRows
|
|
52641
53084
|
});
|
|
52642
53085
|
if (!args.yes) {
|
|
@@ -52646,14 +53089,19 @@ async function runAgentPush(cwd2, args) {
|
|
|
52646
53089
|
return;
|
|
52647
53090
|
}
|
|
52648
53091
|
}
|
|
52649
|
-
if (meta.localChanged) {
|
|
53092
|
+
if (meta.localChanged || entrypointChanged) {
|
|
52650
53093
|
const metaSpinner = de();
|
|
52651
53094
|
metaSpinner.start("Updating agent metadata…");
|
|
52652
53095
|
try {
|
|
52653
|
-
|
|
52654
|
-
|
|
52655
|
-
|
|
52656
|
-
|
|
53096
|
+
const update = {};
|
|
53097
|
+
if (meta.localChanged) {
|
|
53098
|
+
update.name = manifest.agent.name;
|
|
53099
|
+
update.tagline = manifest.agent.tagline ?? "";
|
|
53100
|
+
}
|
|
53101
|
+
if (entrypointChanged) {
|
|
53102
|
+
update.entrypoint = resolvedEntrypoint;
|
|
53103
|
+
}
|
|
53104
|
+
await api.updateAgent(agentId, update);
|
|
52657
53105
|
metaSpinner.stop("Metadata updated.");
|
|
52658
53106
|
} catch (err) {
|
|
52659
53107
|
metaSpinner.stop("Failed.");
|
|
@@ -52667,7 +53115,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
52667
53115
|
pushSpinner.start("Pushing…");
|
|
52668
53116
|
let updatedCloud;
|
|
52669
53117
|
try {
|
|
52670
|
-
updatedCloud = await api.pushAgentManifest(
|
|
53118
|
+
updatedCloud = await api.pushAgentManifest(agentId, {
|
|
52671
53119
|
components: outgoing,
|
|
52672
53120
|
base_revision: cloud.revision
|
|
52673
53121
|
});
|
|
@@ -52676,14 +53124,22 @@ async function runAgentPush(cwd2, args) {
|
|
|
52676
53124
|
pushSpinner.stop("Failed.");
|
|
52677
53125
|
if (err instanceof ApiError && err.status === 409) {
|
|
52678
53126
|
f2.error(err.message);
|
|
52679
|
-
f2.info(`Run ${
|
|
53127
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent pull")} and try again.`);
|
|
52680
53128
|
return;
|
|
52681
53129
|
}
|
|
52682
53130
|
return handleApiError3(err);
|
|
52683
53131
|
}
|
|
53132
|
+
const existing = readLink(cwd2);
|
|
53133
|
+
if (existing) {
|
|
53134
|
+
writeLink(cwd2, {
|
|
53135
|
+
...existing,
|
|
53136
|
+
name: manifest.agent.name,
|
|
53137
|
+
tagline: manifest.agent.tagline
|
|
53138
|
+
});
|
|
53139
|
+
}
|
|
52684
53140
|
const newLock = {
|
|
52685
53141
|
schemaVersion: 1,
|
|
52686
|
-
agent_id:
|
|
53142
|
+
agent_id: agentId,
|
|
52687
53143
|
revision: updatedCloud.revision,
|
|
52688
53144
|
synced_at: new Date().toISOString(),
|
|
52689
53145
|
components: updatedCloud.components.map((c2) => {
|
|
@@ -52695,7 +53151,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
52695
53151
|
return false;
|
|
52696
53152
|
}
|
|
52697
53153
|
})?.source;
|
|
52698
|
-
const prior = lock?.components.find((
|
|
53154
|
+
const prior = lock?.components.find((pc26) => pc26.type === c2.type && pc26.slug === c2.slug);
|
|
52699
53155
|
return {
|
|
52700
53156
|
type: c2.type,
|
|
52701
53157
|
slug: c2.slug,
|
|
@@ -52704,11 +53160,15 @@ async function runAgentPush(cwd2, args) {
|
|
|
52704
53160
|
...decl ? { source: decl } : {}
|
|
52705
53161
|
};
|
|
52706
53162
|
}),
|
|
52707
|
-
agentMeta: {
|
|
53163
|
+
agentMeta: {
|
|
53164
|
+
name: manifest.agent.name,
|
|
53165
|
+
tagline: manifest.agent.tagline,
|
|
53166
|
+
entrypoint: resolvedEntrypoint !== undefined ? resolvedEntrypoint : lock?.agentMeta?.entrypoint
|
|
53167
|
+
}
|
|
52708
53168
|
};
|
|
52709
53169
|
writeSyncState(cwd2, newLock);
|
|
52710
|
-
await pushSecrets(cwd2,
|
|
52711
|
-
$e(`Pushed ${
|
|
53170
|
+
await pushSecrets(cwd2, agentId);
|
|
53171
|
+
$e(`Pushed ${manifest.agent.name} at revision ${updatedCloud.revision}.`);
|
|
52712
53172
|
}
|
|
52713
53173
|
async function pushSecrets(cwd2, agentId) {
|
|
52714
53174
|
const localSecrets = readLocalSecrets(cwd2);
|
|
@@ -52736,74 +53196,6 @@ async function pushSecrets(cwd2, agentId) {
|
|
|
52736
53196
|
handleApiError3(err);
|
|
52737
53197
|
}
|
|
52738
53198
|
}
|
|
52739
|
-
async function buildOutgoingComponents(cwd2, manifest, cloud) {
|
|
52740
|
-
const out = [];
|
|
52741
|
-
if (manifest.instructions) {
|
|
52742
|
-
const body = readInstructions(cwd2, manifest);
|
|
52743
|
-
if (body === null) {
|
|
52744
|
-
f2.error(`Instructions file ${import_picocolors26.default.bold(manifest.instructions.file)} not found.`);
|
|
52745
|
-
return null;
|
|
52746
|
-
}
|
|
52747
|
-
if (body.trim()) {
|
|
52748
|
-
const fileHash2 = hashString(body);
|
|
52749
|
-
const file = {
|
|
52750
|
-
path: manifest.instructions.file,
|
|
52751
|
-
content: body,
|
|
52752
|
-
hash: fileHash2
|
|
52753
|
-
};
|
|
52754
|
-
out.push({
|
|
52755
|
-
type: "instruction",
|
|
52756
|
-
slug: "agent-instructions",
|
|
52757
|
-
description: "Agent instructions",
|
|
52758
|
-
hash: componentHashFromFileHashes([fileHash2]),
|
|
52759
|
-
files: [file],
|
|
52760
|
-
meta: { source: "global_prompt" }
|
|
52761
|
-
});
|
|
52762
|
-
}
|
|
52763
|
-
}
|
|
52764
|
-
for (const entry of manifest.skills) {
|
|
52765
|
-
const parsed = parseSkillSource2(entry.source);
|
|
52766
|
-
if (parsed.kind !== "registry")
|
|
52767
|
-
continue;
|
|
52768
|
-
const cloudMatch = cloud.components.find((c2) => c2.type === "skill" && c2.slug === parsed.slug);
|
|
52769
|
-
out.push({
|
|
52770
|
-
type: "skill",
|
|
52771
|
-
slug: parsed.slug,
|
|
52772
|
-
hash: cloudMatch?.hash ?? "",
|
|
52773
|
-
files: [],
|
|
52774
|
-
meta: {
|
|
52775
|
-
name: parsed.creator ? `${parsed.creator}/${parsed.slug}` : parsed.slug,
|
|
52776
|
-
...parsed.version ? { version: parsed.version } : {}
|
|
52777
|
-
}
|
|
52778
|
-
});
|
|
52779
|
-
}
|
|
52780
|
-
for (const entry of manifest.mcp ?? []) {
|
|
52781
|
-
if (!entry.url && !entry.command) {
|
|
52782
|
-
f2.error(`MCP ${import_picocolors26.default.bold(entry.name)} needs either ${import_picocolors26.default.cyan("url")} or ${import_picocolors26.default.cyan("command")}.`);
|
|
52783
|
-
return null;
|
|
52784
|
-
}
|
|
52785
|
-
const payload = {};
|
|
52786
|
-
if (entry.url !== undefined)
|
|
52787
|
-
payload.url = entry.url;
|
|
52788
|
-
if (entry.command !== undefined)
|
|
52789
|
-
payload.command = entry.command;
|
|
52790
|
-
if (entry.args !== undefined)
|
|
52791
|
-
payload.args = entry.args;
|
|
52792
|
-
if (entry.env !== undefined)
|
|
52793
|
-
payload.env = entry.env;
|
|
52794
|
-
if (entry.headers !== undefined)
|
|
52795
|
-
payload.headers = entry.headers;
|
|
52796
|
-
payload.is_enabled = entry.is_enabled ?? true;
|
|
52797
|
-
out.push({
|
|
52798
|
-
type: "mcp",
|
|
52799
|
-
slug: entry.name,
|
|
52800
|
-
hash: "",
|
|
52801
|
-
files: [],
|
|
52802
|
-
meta: { mcp: payload }
|
|
52803
|
-
});
|
|
52804
|
-
}
|
|
52805
|
-
return out;
|
|
52806
|
-
}
|
|
52807
53199
|
function handleApiError3(err) {
|
|
52808
53200
|
if (err instanceof ApiError) {
|
|
52809
53201
|
if (err.status === 401) {
|
|
@@ -52817,13 +53209,13 @@ function handleApiError3(err) {
|
|
|
52817
53209
|
}
|
|
52818
53210
|
|
|
52819
53211
|
// src/cli/agent-status.ts
|
|
52820
|
-
var
|
|
53212
|
+
var import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
52821
53213
|
async function runAgentStatus(cwd2) {
|
|
52822
53214
|
banner("agent status — what changed locally, remotely, both");
|
|
52823
53215
|
const link2 = readLink(cwd2);
|
|
52824
53216
|
if (!link2) {
|
|
52825
53217
|
f2.warn("This folder is not linked to any agent.");
|
|
52826
|
-
f2.info(`Run ${
|
|
53218
|
+
f2.info(`Run ${import_picocolors28.default.cyan("brainbase link")} first.`);
|
|
52827
53219
|
return;
|
|
52828
53220
|
}
|
|
52829
53221
|
const manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
@@ -52844,8 +53236,8 @@ async function runAgentStatus(cwd2) {
|
|
|
52844
53236
|
return;
|
|
52845
53237
|
}
|
|
52846
53238
|
if (!manifest) {
|
|
52847
|
-
f2.info(`${
|
|
52848
|
-
f2.info(`Cloud has ${
|
|
53239
|
+
f2.info(`${import_picocolors28.default.dim("No")} ${import_picocolors28.default.bold("brainbase.agent.yaml")} ${import_picocolors28.default.dim("here yet.")} Run ${import_picocolors28.default.cyan("brainbase agent pull")} to populate this folder.`);
|
|
53240
|
+
f2.info(`Cloud has ${import_picocolors28.default.bold(String(cloud.components.length))} component${cloud.components.length === 1 ? "" : "s"} at revision ${cloud.revision}.`);
|
|
52849
53241
|
return;
|
|
52850
53242
|
}
|
|
52851
53243
|
const localComponents = readLocalComponents(cwd2, manifest);
|
|
@@ -52884,17 +53276,17 @@ async function runAgentStatus(cwd2) {
|
|
|
52884
53276
|
}
|
|
52885
53277
|
const lines = [];
|
|
52886
53278
|
lines.push("");
|
|
52887
|
-
lines.push(` ${
|
|
52888
|
-
lines.push(` ${
|
|
52889
|
-
lines.push(` ${
|
|
53279
|
+
lines.push(` ${import_picocolors28.default.bold(link2.name)} ${import_picocolors28.default.dim(`(${link2.slug})`)}`);
|
|
53280
|
+
lines.push(` ${import_picocolors28.default.dim("agent_id")} ${link2.agent_id}`);
|
|
53281
|
+
lines.push(` ${import_picocolors28.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
|
|
52890
53282
|
lines.push("");
|
|
52891
53283
|
if (meta.localChanged || meta.cloudChanged) {
|
|
52892
|
-
lines.push(` ${
|
|
53284
|
+
lines.push(` ${import_picocolors28.default.bold("agent metadata")}`);
|
|
52893
53285
|
if (meta.localChanged) {
|
|
52894
|
-
lines.push(` ${
|
|
53286
|
+
lines.push(` ${import_picocolors28.default.yellow("→ push")} name/tagline edited in brainbase.agent.yaml`);
|
|
52895
53287
|
}
|
|
52896
53288
|
if (meta.cloudChanged) {
|
|
52897
|
-
lines.push(` ${
|
|
53289
|
+
lines.push(` ${import_picocolors28.default.cyan("← pull")} name/tagline changed on cloud`);
|
|
52898
53290
|
}
|
|
52899
53291
|
lines.push("");
|
|
52900
53292
|
}
|
|
@@ -52904,65 +53296,65 @@ async function runAgentStatus(cwd2) {
|
|
|
52904
53296
|
const cloudSecrets = cloudRes.secrets ?? {};
|
|
52905
53297
|
const sd = diffSecrets(localSecrets, cloudSecrets);
|
|
52906
53298
|
if (sd.localOnly.length || sd.cloudOnly.length || sd.changed.length) {
|
|
52907
|
-
lines.push(` ${
|
|
53299
|
+
lines.push(` ${import_picocolors28.default.bold("secrets")}`);
|
|
52908
53300
|
if (sd.localOnly.length)
|
|
52909
|
-
lines.push(` ${
|
|
53301
|
+
lines.push(` ${import_picocolors28.default.yellow("→ push")} new locally: ${sd.localOnly.join(", ")}`);
|
|
52910
53302
|
if (sd.changed.length)
|
|
52911
|
-
lines.push(` ${
|
|
53303
|
+
lines.push(` ${import_picocolors28.default.yellow("→ push")} values changed: ${sd.changed.join(", ")}`);
|
|
52912
53304
|
if (sd.cloudOnly.length)
|
|
52913
|
-
lines.push(` ${
|
|
53305
|
+
lines.push(` ${import_picocolors28.default.cyan("← pull")} new on cloud: ${sd.cloudOnly.join(", ")}`);
|
|
52914
53306
|
lines.push("");
|
|
52915
53307
|
}
|
|
52916
53308
|
} catch {}
|
|
52917
53309
|
if (conflicts.length === 0 && toPush.length === 0 && toPull.length === 0) {
|
|
52918
|
-
lines.push(` ${
|
|
53310
|
+
lines.push(` ${import_picocolors28.default.green("✓")} everything is in sync`);
|
|
52919
53311
|
lines.push("");
|
|
52920
53312
|
console.log(lines.join(`
|
|
52921
53313
|
`));
|
|
52922
53314
|
return;
|
|
52923
53315
|
}
|
|
52924
53316
|
if (toPush.length) {
|
|
52925
|
-
lines.push(` ${
|
|
53317
|
+
lines.push(` ${import_picocolors28.default.bold("changes to push")} ${import_picocolors28.default.dim(`(${toPush.length})`)}`);
|
|
52926
53318
|
for (const r2 of toPush)
|
|
52927
|
-
lines.push(` ${
|
|
53319
|
+
lines.push(` ${import_picocolors28.default.yellow("→")} ${fmtRow(r2)}`);
|
|
52928
53320
|
lines.push("");
|
|
52929
53321
|
}
|
|
52930
53322
|
if (toPull.length) {
|
|
52931
|
-
lines.push(` ${
|
|
53323
|
+
lines.push(` ${import_picocolors28.default.bold("changes to pull")} ${import_picocolors28.default.dim(`(${toPull.length})`)}`);
|
|
52932
53324
|
for (const r2 of toPull)
|
|
52933
|
-
lines.push(` ${
|
|
53325
|
+
lines.push(` ${import_picocolors28.default.cyan("←")} ${fmtRow(r2)}`);
|
|
52934
53326
|
lines.push("");
|
|
52935
53327
|
}
|
|
52936
53328
|
if (conflicts.length) {
|
|
52937
|
-
lines.push(` ${
|
|
53329
|
+
lines.push(` ${import_picocolors28.default.bold(import_picocolors28.default.red("conflicts"))} ${import_picocolors28.default.dim(`(${conflicts.length})`)}`);
|
|
52938
53330
|
for (const r2 of conflicts)
|
|
52939
|
-
lines.push(` ${
|
|
53331
|
+
lines.push(` ${import_picocolors28.default.red("!")} ${fmtRow(r2)}`);
|
|
52940
53332
|
lines.push("");
|
|
52941
53333
|
}
|
|
52942
|
-
lines.push(` ${
|
|
53334
|
+
lines.push(` ${import_picocolors28.default.dim("run")} ${import_picocolors28.default.cyan("brainbase agent pull")} ${import_picocolors28.default.dim("to apply cloud changes,")} ${import_picocolors28.default.cyan("brainbase agent push")} ${import_picocolors28.default.dim("to send yours")}`);
|
|
52943
53335
|
lines.push("");
|
|
52944
53336
|
console.log(lines.join(`
|
|
52945
53337
|
`));
|
|
52946
53338
|
}
|
|
52947
53339
|
function fmtRow(r2) {
|
|
52948
|
-
const head = `${fmtType(r2.type)} ${
|
|
53340
|
+
const head = `${fmtType(r2.type)} ${import_picocolors28.default.bold(r2.slug)}`;
|
|
52949
53341
|
switch (r2.status) {
|
|
52950
53342
|
case "added-only-local":
|
|
52951
|
-
return `${head} ${
|
|
53343
|
+
return `${head} ${import_picocolors28.default.dim("(new — only in brainbase.agent.yaml)")}`;
|
|
52952
53344
|
case "added-cloud":
|
|
52953
|
-
return `${head} ${
|
|
53345
|
+
return `${head} ${import_picocolors28.default.dim("(new on cloud)")}`;
|
|
52954
53346
|
case "added-local":
|
|
52955
|
-
return `${head} ${
|
|
53347
|
+
return `${head} ${import_picocolors28.default.dim("(present locally and on cloud, never synced here)")}`;
|
|
52956
53348
|
case "removed-local":
|
|
52957
|
-
return `${head} ${
|
|
53349
|
+
return `${head} ${import_picocolors28.default.dim("(removed from brainbase.agent.yaml)")}`;
|
|
52958
53350
|
case "removed-cloud":
|
|
52959
|
-
return `${head} ${
|
|
53351
|
+
return `${head} ${import_picocolors28.default.dim("(removed on cloud)")}`;
|
|
52960
53352
|
case "modified-local":
|
|
52961
|
-
return `${head} ${
|
|
53353
|
+
return `${head} ${import_picocolors28.default.dim("(you edited it)")}`;
|
|
52962
53354
|
case "modified-cloud":
|
|
52963
|
-
return `${head} ${
|
|
53355
|
+
return `${head} ${import_picocolors28.default.dim("(cloud was updated)")}`;
|
|
52964
53356
|
case "modified-both":
|
|
52965
|
-
return `${head} ${
|
|
53357
|
+
return `${head} ${import_picocolors28.default.dim("(both diverged — needs resolution)")}`;
|
|
52966
53358
|
default:
|
|
52967
53359
|
return head;
|
|
52968
53360
|
}
|
|
@@ -52999,10 +53391,11 @@ function formatExport(shell, key2, value) {
|
|
|
52999
53391
|
}
|
|
53000
53392
|
|
|
53001
53393
|
// src/cli/agent-create.ts
|
|
53002
|
-
|
|
53394
|
+
import path49 from "node:path";
|
|
53395
|
+
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
53003
53396
|
|
|
53004
53397
|
// src/ui/box.ts
|
|
53005
|
-
var
|
|
53398
|
+
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
53006
53399
|
var H3 = "─";
|
|
53007
53400
|
var TINT = {
|
|
53008
53401
|
ok: COLOR.ok,
|
|
@@ -53014,20 +53407,28 @@ var TINT = {
|
|
|
53014
53407
|
function divider(label, width = 56, indent = 2) {
|
|
53015
53408
|
const ind = " ".repeat(indent);
|
|
53016
53409
|
if (!label)
|
|
53017
|
-
return `${ind}${
|
|
53410
|
+
return `${ind}${import_picocolors29.default.dim(H3.repeat(width))}`;
|
|
53018
53411
|
const labelText = ` ${label} `;
|
|
53019
53412
|
const labelLen = visibleLength(labelText);
|
|
53020
|
-
const left =
|
|
53021
|
-
const right =
|
|
53022
|
-
return `${ind}${left}${
|
|
53413
|
+
const left = import_picocolors29.default.dim(H3.repeat(2));
|
|
53414
|
+
const right = import_picocolors29.default.dim(H3.repeat(Math.max(0, width - labelLen - 2)));
|
|
53415
|
+
return `${ind}${left}${import_picocolors29.default.bold(import_picocolors29.default.dim(labelText))}${right}`;
|
|
53023
53416
|
}
|
|
53024
53417
|
function tip(text, indent = 2) {
|
|
53025
|
-
return " ".repeat(indent) +
|
|
53418
|
+
return " ".repeat(indent) + import_picocolors29.default.dim("›") + " " + import_picocolors29.default.dim(text);
|
|
53026
53419
|
}
|
|
53027
53420
|
|
|
53028
53421
|
// src/cli/agent-create.ts
|
|
53029
53422
|
async function runAgentCreate(cwd2, args) {
|
|
53030
|
-
banner("agent create —
|
|
53423
|
+
banner("agent create — claim a brainbase.agent.yaml and link this folder");
|
|
53424
|
+
let manifest = await loadOrScaffoldManifest(cwd2, args);
|
|
53425
|
+
if (!manifest)
|
|
53426
|
+
return;
|
|
53427
|
+
if (manifest.id) {
|
|
53428
|
+
f2.warn(`This folder already belongs to an agent — ${import_picocolors30.default.bold(manifest.agent.name)} (${import_picocolors30.default.dim(manifest.id)}).`);
|
|
53429
|
+
f2.info(`If you want to detach it, run ${import_picocolors30.default.cyan("brainbase unlink")} first; or move to a different directory.`);
|
|
53430
|
+
return;
|
|
53431
|
+
}
|
|
53031
53432
|
const orgsSpinner = de();
|
|
53032
53433
|
orgsSpinner.start("Loading your organizations…");
|
|
53033
53434
|
let orgs;
|
|
@@ -53054,7 +53455,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53054
53455
|
org = found;
|
|
53055
53456
|
} else if (orgs.length === 1) {
|
|
53056
53457
|
org = orgs[0];
|
|
53057
|
-
f2.info(`Using organization ${
|
|
53458
|
+
f2.info(`Using organization ${import_picocolors30.default.bold(org.name)}.`);
|
|
53058
53459
|
} else {
|
|
53059
53460
|
const orgChoice = await ie({
|
|
53060
53461
|
message: "Pick an organization",
|
|
@@ -53102,7 +53503,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53102
53503
|
createSpinner2.start("Creating team…");
|
|
53103
53504
|
try {
|
|
53104
53505
|
team = await api.createTeam(org.id, teamName.trim());
|
|
53105
|
-
createSpinner2.stop(`Created team ${
|
|
53506
|
+
createSpinner2.stop(`Created team ${import_picocolors30.default.bold(team.name)}.`);
|
|
53106
53507
|
} catch (err) {
|
|
53107
53508
|
createSpinner2.stop("Failed.");
|
|
53108
53509
|
handleApiError4(err);
|
|
@@ -53112,8 +53513,8 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53112
53513
|
team = teams.find((t) => t.id === picked);
|
|
53113
53514
|
}
|
|
53114
53515
|
}
|
|
53115
|
-
const harness = normalizeHarnessId(args.harness ?? await pickHarness(cwd2));
|
|
53116
|
-
let agentName = args.name?.trim();
|
|
53516
|
+
const harness = normalizeHarnessId(args.harness ?? manifest.harness ?? await pickHarness(cwd2));
|
|
53517
|
+
let agentName = args.name?.trim() || manifest.agent.name.trim();
|
|
53117
53518
|
if (!agentName) {
|
|
53118
53519
|
const ans = await te({
|
|
53119
53520
|
message: "Agent name",
|
|
@@ -53122,7 +53523,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53122
53523
|
});
|
|
53123
53524
|
agentName = ensureNotCancelled(ans).trim();
|
|
53124
53525
|
}
|
|
53125
|
-
let tagline = args.tagline?.trim() || undefined;
|
|
53526
|
+
let tagline = (args.tagline ?? manifest.agent.tagline)?.trim() || undefined;
|
|
53126
53527
|
if (tagline === undefined && !args.yes) {
|
|
53127
53528
|
const ans = await te({
|
|
53128
53529
|
message: "Tagline",
|
|
@@ -53134,11 +53535,11 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53134
53535
|
}
|
|
53135
53536
|
if (!args.yes) {
|
|
53136
53537
|
le([
|
|
53137
|
-
`${
|
|
53138
|
-
`${
|
|
53139
|
-
`${
|
|
53140
|
-
`${
|
|
53141
|
-
...tagline ? [`${
|
|
53538
|
+
`${import_picocolors30.default.dim("org")} ${import_picocolors30.default.bold(org.name)}`,
|
|
53539
|
+
`${import_picocolors30.default.dim("team")} ${import_picocolors30.default.bold(team.name)}`,
|
|
53540
|
+
`${import_picocolors30.default.dim("harness")} ${import_picocolors30.default.bold(harness)}`,
|
|
53541
|
+
`${import_picocolors30.default.dim("agent")} ${import_picocolors30.default.bold(agentName)}`,
|
|
53542
|
+
...tagline ? [`${import_picocolors30.default.dim("tagline")} ${tagline}`] : []
|
|
53142
53543
|
].join(`
|
|
53143
53544
|
`), "Will create");
|
|
53144
53545
|
const confirmed = await se({ message: "Create this agent?", initialValue: true });
|
|
@@ -53147,6 +53548,19 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53147
53548
|
return;
|
|
53148
53549
|
}
|
|
53149
53550
|
}
|
|
53551
|
+
let resolvedEntrypoint;
|
|
53552
|
+
if (manifest.entrypoint) {
|
|
53553
|
+
const body = resolveEntrypoint(cwd2, manifest);
|
|
53554
|
+
if (body === null) {
|
|
53555
|
+
if (manifest.entrypoint.file) {
|
|
53556
|
+
f2.error(`Entrypoint file ${import_picocolors30.default.bold(manifest.entrypoint.file)} not found.`);
|
|
53557
|
+
} else {
|
|
53558
|
+
f2.error("Entrypoint block is empty.");
|
|
53559
|
+
}
|
|
53560
|
+
return;
|
|
53561
|
+
}
|
|
53562
|
+
resolvedEntrypoint = body;
|
|
53563
|
+
}
|
|
53150
53564
|
const createSpinner = de();
|
|
53151
53565
|
createSpinner.start("Creating agent…");
|
|
53152
53566
|
let agent;
|
|
@@ -53156,9 +53570,10 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53156
53570
|
team_id: team.id,
|
|
53157
53571
|
name: agentName,
|
|
53158
53572
|
tagline,
|
|
53159
|
-
harness
|
|
53573
|
+
harness,
|
|
53574
|
+
...resolvedEntrypoint !== undefined ? { entrypoint: resolvedEntrypoint } : {}
|
|
53160
53575
|
});
|
|
53161
|
-
createSpinner.stop(`Created ${
|
|
53576
|
+
createSpinner.stop(`Created ${import_picocolors30.default.bold(agent.name)}.`);
|
|
53162
53577
|
} catch (err) {
|
|
53163
53578
|
createSpinner.stop("Failed.");
|
|
53164
53579
|
handleApiError4(err);
|
|
@@ -53171,7 +53586,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53171
53586
|
let wantsTracking = true;
|
|
53172
53587
|
if (!args.yes) {
|
|
53173
53588
|
const ans = await se({
|
|
53174
|
-
message: `Track ${harness} conversations on the brainbase platform? ${
|
|
53589
|
+
message: `Track ${harness} conversations on the brainbase platform? ${import_picocolors30.default.dim("(routes LLM calls through brainbase so they appear under this agent)")}`,
|
|
53175
53590
|
initialValue: true
|
|
53176
53591
|
});
|
|
53177
53592
|
wantsTracking = ensureNotCancelled(ans);
|
|
@@ -53210,71 +53625,455 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53210
53625
|
}
|
|
53211
53626
|
}
|
|
53212
53627
|
}
|
|
53213
|
-
const link2 = {
|
|
53214
|
-
schemaVersion: 1,
|
|
53215
|
-
agent_id: agent.id,
|
|
53216
|
-
org_id: agent.org_id,
|
|
53217
|
-
team_id: agent.team_id,
|
|
53218
|
-
slug: agent.slug,
|
|
53219
|
-
name: agent.name,
|
|
53220
|
-
tagline: agent.tagline,
|
|
53221
|
-
url: agent.url,
|
|
53222
|
-
linked_at: new Date().toISOString(),
|
|
53223
|
-
linked_by: session?.email ?? session?.user_id,
|
|
53224
|
-
harness,
|
|
53225
|
-
tracking
|
|
53226
|
-
};
|
|
53227
|
-
writeLink(cwd2, link2);
|
|
53228
|
-
|
|
53628
|
+
const link2 = {
|
|
53629
|
+
schemaVersion: 1,
|
|
53630
|
+
agent_id: agent.id,
|
|
53631
|
+
org_id: agent.org_id,
|
|
53632
|
+
team_id: agent.team_id,
|
|
53633
|
+
slug: agent.slug,
|
|
53634
|
+
name: agent.name,
|
|
53635
|
+
tagline: agent.tagline,
|
|
53636
|
+
url: agent.url,
|
|
53637
|
+
linked_at: new Date().toISOString(),
|
|
53638
|
+
linked_by: session?.email ?? session?.user_id,
|
|
53639
|
+
harness,
|
|
53640
|
+
tracking
|
|
53641
|
+
};
|
|
53642
|
+
writeLink(cwd2, link2);
|
|
53643
|
+
manifest = readManifest(cwd2);
|
|
53644
|
+
let updatedCloud = null;
|
|
53645
|
+
const hasContent = !!manifest.instructions || manifest.skills.length > 0 || (manifest.mcp ?? []).length > 0;
|
|
53646
|
+
if (hasContent) {
|
|
53647
|
+
const outgoing = await buildOutgoingComponents(cwd2, manifest, null);
|
|
53648
|
+
if (outgoing === null) {
|
|
53649
|
+
f2.warn(`Agent created, but local content wasn't uploaded. Fix the issue above and run ${import_picocolors30.default.cyan("brainbase agent push")}.`);
|
|
53650
|
+
} else if (outgoing.length > 0) {
|
|
53651
|
+
const pushSpinner = de();
|
|
53652
|
+
pushSpinner.start("Pushing local content…");
|
|
53653
|
+
try {
|
|
53654
|
+
updatedCloud = await api.pushAgentManifest(agent.id, {
|
|
53655
|
+
components: outgoing,
|
|
53656
|
+
base_revision: 0
|
|
53657
|
+
});
|
|
53658
|
+
pushSpinner.stop(`Pushed at revision ${updatedCloud.revision}.`);
|
|
53659
|
+
} catch (err) {
|
|
53660
|
+
pushSpinner.stop("Failed.");
|
|
53661
|
+
if (err instanceof ApiError) {
|
|
53662
|
+
f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors30.default.cyan("brainbase agent push")} to retry.`);
|
|
53663
|
+
} else {
|
|
53664
|
+
f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors30.default.cyan("brainbase agent push")} to retry.`);
|
|
53665
|
+
}
|
|
53666
|
+
}
|
|
53667
|
+
}
|
|
53668
|
+
}
|
|
53669
|
+
if (updatedCloud) {
|
|
53670
|
+
const syncedComponents = updatedCloud.components.map((c2) => ({
|
|
53671
|
+
type: c2.type,
|
|
53672
|
+
slug: c2.slug,
|
|
53673
|
+
hash: c2.hash,
|
|
53674
|
+
installedPaths: []
|
|
53675
|
+
}));
|
|
53676
|
+
const state = {
|
|
53677
|
+
schemaVersion: 1,
|
|
53678
|
+
agent_id: agent.id,
|
|
53679
|
+
revision: updatedCloud.revision,
|
|
53680
|
+
synced_at: new Date().toISOString(),
|
|
53681
|
+
components: syncedComponents,
|
|
53682
|
+
agentMeta: {
|
|
53683
|
+
name: agent.name,
|
|
53684
|
+
tagline: agent.tagline,
|
|
53685
|
+
...resolvedEntrypoint ? { entrypoint: resolvedEntrypoint } : {}
|
|
53686
|
+
}
|
|
53687
|
+
};
|
|
53688
|
+
writeSyncState(cwd2, state);
|
|
53689
|
+
}
|
|
53690
|
+
$e(`Created ${import_picocolors30.default.bold(agent.name)} and linked this folder.`);
|
|
53691
|
+
await showResultCard({
|
|
53692
|
+
title: "CREATED",
|
|
53693
|
+
tone: "ok",
|
|
53694
|
+
subtitle: link2.tagline ? `${link2.name} — ${link2.tagline}` : link2.name,
|
|
53695
|
+
meta: [
|
|
53696
|
+
["slug", link2.slug],
|
|
53697
|
+
["agent", link2.agent_id],
|
|
53698
|
+
...link2.url ? [["url", link2.url]] : []
|
|
53699
|
+
]
|
|
53700
|
+
});
|
|
53701
|
+
console.log();
|
|
53702
|
+
if (tracking && harness === "codex") {
|
|
53703
|
+
console.log(tip(`Run ${import_picocolors30.default.cyan("codex")} once in this folder and approve trust ${import_picocolors30.default.dim("— Codex only loads project-scope config in trusted projects.")}`));
|
|
53704
|
+
}
|
|
53705
|
+
console.log(tip(`brainbase agent unpack ${import_picocolors30.default.dim("— install harness files (skills/mcps) under .claude/, .codex/, …")}`));
|
|
53706
|
+
console.log();
|
|
53707
|
+
}
|
|
53708
|
+
async function loadOrScaffoldManifest(cwd2, args) {
|
|
53709
|
+
if (hasManifest(cwd2)) {
|
|
53710
|
+
try {
|
|
53711
|
+
return readManifest(cwd2);
|
|
53712
|
+
} catch (err) {
|
|
53713
|
+
f2.error(err.message);
|
|
53714
|
+
return null;
|
|
53715
|
+
}
|
|
53716
|
+
}
|
|
53717
|
+
f2.warn(`No ${import_picocolors30.default.bold(AGENT_MANIFEST_FILE)} here.`);
|
|
53718
|
+
if (!args.yes) {
|
|
53719
|
+
const ans = await se({
|
|
53720
|
+
message: `Scaffold a minimal ${import_picocolors30.default.bold(AGENT_MANIFEST_FILE)} and continue?`,
|
|
53721
|
+
initialValue: true
|
|
53722
|
+
});
|
|
53723
|
+
if (!ensureNotCancelled(ans)) {
|
|
53724
|
+
$e("Aborted.");
|
|
53725
|
+
return null;
|
|
53726
|
+
}
|
|
53727
|
+
}
|
|
53728
|
+
const seedName = args.name?.trim() ?? path49.basename(path49.resolve(cwd2)) ?? "My Agent";
|
|
53729
|
+
const seedHarness = args.harness ? normalizeHarnessId(args.harness) : undefined;
|
|
53730
|
+
const scaffold = {
|
|
53731
|
+
schema: 1,
|
|
53732
|
+
...seedHarness ? { harness: seedHarness } : {},
|
|
53733
|
+
agent: { name: seedName, ...args.tagline ? { tagline: args.tagline } : {} },
|
|
53734
|
+
skills: [],
|
|
53735
|
+
mcp: []
|
|
53736
|
+
};
|
|
53737
|
+
try {
|
|
53738
|
+
writeManifest(cwd2, scaffold);
|
|
53739
|
+
f2.info(`Wrote ${import_picocolors30.default.bold(AGENT_MANIFEST_FILE)}.`);
|
|
53740
|
+
} catch (err) {
|
|
53741
|
+
f2.error(`Failed to write manifest: ${err.message}`);
|
|
53742
|
+
return null;
|
|
53743
|
+
}
|
|
53744
|
+
return scaffold;
|
|
53745
|
+
}
|
|
53746
|
+
async function pickHarness(cwd2) {
|
|
53747
|
+
const detections = await detectHarnesses(cwd2);
|
|
53748
|
+
const detected = detections.filter((d3) => d3.detection.detected);
|
|
53749
|
+
if (detected.length === 1) {
|
|
53750
|
+
f2.info(`Detected harness: ${import_picocolors30.default.bold(detected[0].adapter.displayName)}.`);
|
|
53751
|
+
return detected[0].adapter.id;
|
|
53752
|
+
}
|
|
53753
|
+
const choice = await ie({
|
|
53754
|
+
message: detected.length > 1 ? "Multiple harnesses detected — which one is this agent for?" : "No harness detected here. Which harness is this agent for?",
|
|
53755
|
+
options: detections.map((d3) => ({
|
|
53756
|
+
value: d3.adapter.id,
|
|
53757
|
+
label: d3.adapter.displayName,
|
|
53758
|
+
hint: d3.detection.detected ? "detected" : undefined
|
|
53759
|
+
}))
|
|
53760
|
+
});
|
|
53761
|
+
return ensureNotCancelled(choice);
|
|
53762
|
+
}
|
|
53763
|
+
function handleApiError4(err) {
|
|
53764
|
+
if (err instanceof ApiError) {
|
|
53765
|
+
if (err.status === 401) {
|
|
53766
|
+
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
53767
|
+
} else {
|
|
53768
|
+
f2.error(err.message);
|
|
53769
|
+
}
|
|
53770
|
+
} else {
|
|
53771
|
+
f2.error(err.message);
|
|
53772
|
+
}
|
|
53773
|
+
$e("Aborted.");
|
|
53774
|
+
}
|
|
53775
|
+
|
|
53776
|
+
// src/cli/agent-unpack.ts
|
|
53777
|
+
var import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
53778
|
+
|
|
53779
|
+
// src/core/agent-fresh-install.ts
|
|
53780
|
+
import path50 from "node:path";
|
|
53781
|
+
import fs46 from "node:fs";
|
|
53782
|
+
import os13 from "node:os";
|
|
53783
|
+
async function installAgentFresh(input) {
|
|
53784
|
+
const { cwd: cwd2, agent, cloud, harness } = input;
|
|
53785
|
+
const scope = input.scope ?? "project";
|
|
53786
|
+
ensureDir(cwd2);
|
|
53787
|
+
const stageRoot = stageManifestComponents2(cloud.components);
|
|
53788
|
+
const justInstalledPaths = new Map;
|
|
53789
|
+
const cloudHasOrchestrationMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === ORCHESTRATION_MCP_SLUG);
|
|
53790
|
+
const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
|
|
53791
|
+
const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
|
|
53792
|
+
const needMemoryMcpInstall = !cloudHasMemoryMcp;
|
|
53793
|
+
try {
|
|
53794
|
+
if (cloud.components.length > 0 || needOrchestrationMcpInstall || needMemoryMcpInstall) {
|
|
53795
|
+
const toInstall = cloud.components.map((c2) => ({
|
|
53796
|
+
type: c2.type,
|
|
53797
|
+
slug: c2.slug,
|
|
53798
|
+
scope,
|
|
53799
|
+
rootDir: path50.join(stageRoot, c2.type, c2.slug),
|
|
53800
|
+
description: c2.description,
|
|
53801
|
+
meta: c2.meta,
|
|
53802
|
+
payload: c2.meta?.mcp,
|
|
53803
|
+
checksum: c2.hash
|
|
53804
|
+
}));
|
|
53805
|
+
if (needOrchestrationMcpInstall) {
|
|
53806
|
+
toInstall.push(buildOrchestrationMcpComponent(scope));
|
|
53807
|
+
}
|
|
53808
|
+
if (needMemoryMcpInstall) {
|
|
53809
|
+
toInstall.push(buildMemoryMcpComponent(scope));
|
|
53810
|
+
}
|
|
53811
|
+
const installOpts = {
|
|
53812
|
+
cwd: cwd2,
|
|
53813
|
+
scope,
|
|
53814
|
+
resolveConflict: async (_c) => "overwrite",
|
|
53815
|
+
resolveSecret: async () => null
|
|
53816
|
+
};
|
|
53817
|
+
const result = await runHarnessInstall3(harness, toInstall, installOpts, agent.name);
|
|
53818
|
+
for (const o2 of result.installed) {
|
|
53819
|
+
justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
|
|
53820
|
+
}
|
|
53821
|
+
}
|
|
53822
|
+
materializeInstructions2(cwd2, cloud);
|
|
53823
|
+
const manifest = input.preserveManifest ? null : buildManifestFromCloud(cloud, agent);
|
|
53824
|
+
if (manifest)
|
|
53825
|
+
writeManifest(cwd2, manifest);
|
|
53826
|
+
writeLink(cwd2, {
|
|
53827
|
+
schemaVersion: 1,
|
|
53828
|
+
agent_id: agent.id,
|
|
53829
|
+
org_id: agent.org_id,
|
|
53830
|
+
team_id: agent.team_id,
|
|
53831
|
+
slug: agent.slug,
|
|
53832
|
+
name: agent.name,
|
|
53833
|
+
tagline: agent.tagline,
|
|
53834
|
+
url: agent.url,
|
|
53835
|
+
linked_at: new Date().toISOString(),
|
|
53836
|
+
harness
|
|
53837
|
+
});
|
|
53838
|
+
const syncedComponents = cloud.components.map((c2) => ({
|
|
53839
|
+
type: c2.type,
|
|
53840
|
+
slug: c2.slug,
|
|
53841
|
+
hash: c2.hash,
|
|
53842
|
+
installedPaths: justInstalledPaths.get(`${c2.type}/${c2.slug}`) ?? []
|
|
53843
|
+
}));
|
|
53844
|
+
writeSyncState(cwd2, {
|
|
53845
|
+
schemaVersion: 1,
|
|
53846
|
+
agent_id: agent.id,
|
|
53847
|
+
revision: cloud.revision,
|
|
53848
|
+
synced_at: new Date().toISOString(),
|
|
53849
|
+
components: syncedComponents,
|
|
53850
|
+
agentMeta: { name: agent.name, tagline: agent.tagline }
|
|
53851
|
+
});
|
|
53852
|
+
if (input.pullSecrets !== false) {
|
|
53853
|
+
await pullAgentSecrets(cwd2, agent.id);
|
|
53854
|
+
}
|
|
53855
|
+
const returnedManifest = manifest ?? buildManifestFromCloud(cloud, agent);
|
|
53856
|
+
return {
|
|
53857
|
+
installedPaths: justInstalledPaths,
|
|
53858
|
+
manifest: returnedManifest,
|
|
53859
|
+
syncedComponents
|
|
53860
|
+
};
|
|
53861
|
+
} finally {
|
|
53862
|
+
try {
|
|
53863
|
+
fs46.rmSync(stageRoot, { recursive: true, force: true });
|
|
53864
|
+
} catch {}
|
|
53865
|
+
}
|
|
53866
|
+
}
|
|
53867
|
+
function stageManifestComponents2(components) {
|
|
53868
|
+
const root = fs46.mkdtempSync(path50.join(os13.tmpdir(), "brainbase-orch-pull-"));
|
|
53869
|
+
for (const c2 of components) {
|
|
53870
|
+
const compDir = path50.join(root, c2.type, c2.slug);
|
|
53871
|
+
ensureDir(compDir);
|
|
53872
|
+
for (const f4 of c2.files) {
|
|
53873
|
+
const target = path50.join(compDir, f4.path);
|
|
53874
|
+
ensureDir(path50.dirname(target));
|
|
53875
|
+
fs46.writeFileSync(target, f4.content);
|
|
53876
|
+
}
|
|
53877
|
+
}
|
|
53878
|
+
return root;
|
|
53879
|
+
}
|
|
53880
|
+
function runHarnessInstall3(harnessId, components, opts, agentName) {
|
|
53881
|
+
if (harnessId === "claude-code")
|
|
53882
|
+
return installClaudeCodeWithCtx(components, opts, agentName);
|
|
53883
|
+
if (harnessId === "codex")
|
|
53884
|
+
return installCodexWithCtx(components, opts, agentName);
|
|
53885
|
+
if (harnessId === "kafka")
|
|
53886
|
+
return installKafkaWithCtx(components, opts, agentName);
|
|
53887
|
+
return getAdapter(harnessId).install(components, opts);
|
|
53888
|
+
}
|
|
53889
|
+
function materializeInstructions2(cwd2, cloud) {
|
|
53890
|
+
for (const c2 of cloud.components) {
|
|
53891
|
+
if (c2.type !== "instruction")
|
|
53892
|
+
continue;
|
|
53893
|
+
const body = c2.files[0]?.content ?? "";
|
|
53894
|
+
if (!body.trim())
|
|
53895
|
+
continue;
|
|
53896
|
+
fs46.writeFileSync(path50.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
|
|
53897
|
+
return;
|
|
53898
|
+
}
|
|
53899
|
+
}
|
|
53900
|
+
function buildManifestFromCloud(cloud, agent) {
|
|
53901
|
+
const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
|
|
53902
|
+
const meta = c2.meta ?? {};
|
|
53903
|
+
if (meta.name && meta.name.includes("/")) {
|
|
53904
|
+
return {
|
|
53905
|
+
source: meta.version ? `registry:${meta.name}@${meta.version}` : `registry:${meta.name}`
|
|
53906
|
+
};
|
|
53907
|
+
}
|
|
53908
|
+
return { source: `registry:${c2.slug}` };
|
|
53909
|
+
});
|
|
53910
|
+
const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
|
|
53911
|
+
const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
|
|
53912
|
+
const payload = (c2.meta ?? {}).mcp ?? {};
|
|
53913
|
+
const entry = { name: c2.slug };
|
|
53914
|
+
if (typeof payload.url === "string")
|
|
53915
|
+
entry.url = payload.url;
|
|
53916
|
+
if (typeof payload.command === "string")
|
|
53917
|
+
entry.command = payload.command;
|
|
53918
|
+
if (Array.isArray(payload.args))
|
|
53919
|
+
entry.args = payload.args.map(String);
|
|
53920
|
+
if (payload.env && typeof payload.env === "object")
|
|
53921
|
+
entry.env = payload.env;
|
|
53922
|
+
if (payload.headers && typeof payload.headers === "object")
|
|
53923
|
+
entry.headers = payload.headers;
|
|
53924
|
+
if (typeof payload.is_enabled === "boolean")
|
|
53925
|
+
entry.is_enabled = payload.is_enabled;
|
|
53926
|
+
return entry;
|
|
53927
|
+
});
|
|
53928
|
+
return {
|
|
53929
|
+
schema: 1,
|
|
53930
|
+
agent: {
|
|
53931
|
+
name: agent.name,
|
|
53932
|
+
...agent.tagline ? { tagline: agent.tagline } : {}
|
|
53933
|
+
},
|
|
53934
|
+
...hasInstructions ? { instructions: { file: DEFAULT_INSTRUCTIONS_FILE } } : {},
|
|
53935
|
+
skills,
|
|
53936
|
+
mcp
|
|
53937
|
+
};
|
|
53938
|
+
}
|
|
53939
|
+
async function pullAgentSecrets(cwd2, agentId) {
|
|
53940
|
+
try {
|
|
53941
|
+
const res = await api.getAgentSecrets(agentId);
|
|
53942
|
+
const secrets = res.secrets ?? {};
|
|
53943
|
+
if (Object.keys(secrets).length > 0) {
|
|
53944
|
+
writeLocalSecrets(cwd2, secrets);
|
|
53945
|
+
}
|
|
53946
|
+
} catch (err) {
|
|
53947
|
+
if (err instanceof ApiError && err.status !== 404) {
|
|
53948
|
+
f2.warn(`Skipped secrets for agent ${agentId}: ${err.message}`);
|
|
53949
|
+
}
|
|
53950
|
+
}
|
|
53951
|
+
}
|
|
53952
|
+
|
|
53953
|
+
// src/cli/agent-unpack.ts
|
|
53954
|
+
async function runAgentUnpack(cwd2, args) {
|
|
53955
|
+
banner("agent unpack — install this agent into a harness layout");
|
|
53956
|
+
if (!hasManifest(cwd2)) {
|
|
53957
|
+
f2.error(`No ${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} here.`);
|
|
53958
|
+
f2.info(`Run ${import_picocolors31.default.cyan("brainbase agent pull <id>")} to bring an agent into this folder first.`);
|
|
53959
|
+
return;
|
|
53960
|
+
}
|
|
53961
|
+
let manifest;
|
|
53962
|
+
try {
|
|
53963
|
+
manifest = readManifest(cwd2);
|
|
53964
|
+
} catch (err) {
|
|
53965
|
+
f2.error(err.message);
|
|
53966
|
+
return;
|
|
53967
|
+
}
|
|
53968
|
+
if (!manifest.id) {
|
|
53969
|
+
f2.error(`${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} is unclaimed (no ${import_picocolors31.default.cyan("id")}).`);
|
|
53970
|
+
f2.info(`Run ${import_picocolors31.default.cyan("brainbase agent create")} to claim it, ` + `or ${import_picocolors31.default.cyan("brainbase agent pull <id>")} to link it to an existing agent.`);
|
|
53971
|
+
return;
|
|
53972
|
+
}
|
|
53973
|
+
let harness;
|
|
53974
|
+
if (args.harness) {
|
|
53975
|
+
harness = normalizeHarnessId(args.harness);
|
|
53976
|
+
} else if (args.yes) {
|
|
53977
|
+
if (!manifest.harness) {
|
|
53978
|
+
f2.error(`--yes mode but no harness — set ${import_picocolors31.default.cyan("harness")} in the manifest or pass ${import_picocolors31.default.cyan("--harness")}.`);
|
|
53979
|
+
return;
|
|
53980
|
+
}
|
|
53981
|
+
harness = normalizeHarnessId(manifest.harness);
|
|
53982
|
+
} else {
|
|
53983
|
+
harness = await pickHarness2(manifest.harness);
|
|
53984
|
+
}
|
|
53985
|
+
const sp = de();
|
|
53986
|
+
sp.start("Fetching agent…");
|
|
53987
|
+
let cloudAgent;
|
|
53988
|
+
let cloud;
|
|
53989
|
+
try {
|
|
53990
|
+
cloudAgent = await api.getAgent(manifest.id);
|
|
53991
|
+
cloud = await api.getAgentManifest(manifest.id);
|
|
53992
|
+
sp.stop(`Cloud revision ${cloud.revision}.`);
|
|
53993
|
+
} catch (err) {
|
|
53994
|
+
sp.stop("Failed.");
|
|
53995
|
+
handleApiError5(err);
|
|
53996
|
+
return;
|
|
53997
|
+
}
|
|
53998
|
+
if (!args.yes) {
|
|
53999
|
+
const ok = await se({
|
|
54000
|
+
message: `Install ${import_picocolors31.default.bold(cloudAgent.name)} as ${import_picocolors31.default.bold(harness)} here?`,
|
|
54001
|
+
initialValue: true
|
|
54002
|
+
});
|
|
54003
|
+
if (!ensureNotCancelled(ok)) {
|
|
54004
|
+
$e("Aborted.");
|
|
54005
|
+
return;
|
|
54006
|
+
}
|
|
54007
|
+
}
|
|
54008
|
+
const prevLink = readLink(cwd2);
|
|
54009
|
+
try {
|
|
54010
|
+
await installAgentFresh({
|
|
54011
|
+
cwd: cwd2,
|
|
54012
|
+
agent: {
|
|
54013
|
+
id: cloudAgent.id,
|
|
54014
|
+
name: cloudAgent.name,
|
|
54015
|
+
slug: cloudAgent.slug,
|
|
54016
|
+
tagline: cloudAgent.tagline,
|
|
54017
|
+
org_id: cloudAgent.org_id ?? prevLink?.org_id ?? "",
|
|
54018
|
+
team_id: cloudAgent.team_id ?? prevLink?.team_id ?? "",
|
|
54019
|
+
url: cloudAgent.url,
|
|
54020
|
+
harness
|
|
54021
|
+
},
|
|
54022
|
+
cloud,
|
|
54023
|
+
harness,
|
|
54024
|
+
scope: args.scope ?? "project",
|
|
54025
|
+
preserveManifest: true
|
|
54026
|
+
});
|
|
54027
|
+
} catch (err) {
|
|
54028
|
+
f2.error(`Install failed: ${err.message}`);
|
|
54029
|
+
return;
|
|
54030
|
+
}
|
|
54031
|
+
manifest = readManifest(cwd2);
|
|
54032
|
+
if (manifest.harness !== harness) {
|
|
54033
|
+
manifest.harness = harness;
|
|
54034
|
+
writeManifest(cwd2, manifest);
|
|
54035
|
+
}
|
|
54036
|
+
$e(`Unpacked ${import_picocolors31.default.bold(cloudAgent.name)} as ${import_picocolors31.default.bold(harness)}.`);
|
|
53229
54037
|
await showResultCard({
|
|
53230
|
-
title: "
|
|
54038
|
+
title: "UNPACKED",
|
|
53231
54039
|
tone: "ok",
|
|
53232
|
-
subtitle:
|
|
54040
|
+
subtitle: cloudAgent.name,
|
|
53233
54041
|
meta: [
|
|
53234
|
-
["
|
|
53235
|
-
["agent",
|
|
53236
|
-
...
|
|
54042
|
+
["harness", harness],
|
|
54043
|
+
["agent", cloudAgent.id],
|
|
54044
|
+
...cloudAgent.url ? [["url", cloudAgent.url]] : []
|
|
53237
54045
|
]
|
|
53238
54046
|
});
|
|
53239
|
-
console.log();
|
|
53240
|
-
if (tracking && harness === "codex") {
|
|
53241
|
-
console.log(tip(`Run ${import_picocolors29.default.cyan("codex")} once in this folder and approve trust ${import_picocolors29.default.dim("— Codex only loads project-scope config in trusted projects.")}`));
|
|
53242
|
-
}
|
|
53243
|
-
console.log(tip(`brainbase agent pull ${import_picocolors29.default.dim("— pull the agent contents into this folder")}`));
|
|
53244
|
-
console.log();
|
|
53245
54047
|
}
|
|
53246
|
-
async function
|
|
53247
|
-
const
|
|
53248
|
-
const detected = detections.filter((d3) => d3.detection.detected);
|
|
53249
|
-
if (detected.length === 1) {
|
|
53250
|
-
f2.info(`Detected harness: ${import_picocolors29.default.bold(detected[0].adapter.displayName)}.`);
|
|
53251
|
-
return detected[0].adapter.id;
|
|
53252
|
-
}
|
|
54048
|
+
async function pickHarness2(current) {
|
|
54049
|
+
const initial = current ? normalizeHarnessId(current) : undefined;
|
|
53253
54050
|
const choice = await ie({
|
|
53254
|
-
message:
|
|
53255
|
-
options:
|
|
53256
|
-
value:
|
|
53257
|
-
label:
|
|
53258
|
-
hint:
|
|
53259
|
-
}))
|
|
54051
|
+
message: "Pick a harness to install as",
|
|
54052
|
+
options: adapters.map((a3) => ({
|
|
54053
|
+
value: a3.id,
|
|
54054
|
+
label: a3.displayName,
|
|
54055
|
+
hint: a3.id === initial ? "current" : undefined
|
|
54056
|
+
})),
|
|
54057
|
+
initialValue: initial ?? adapters[0].id
|
|
53260
54058
|
});
|
|
53261
54059
|
return ensureNotCancelled(choice);
|
|
53262
54060
|
}
|
|
53263
|
-
function
|
|
54061
|
+
function handleApiError5(err) {
|
|
53264
54062
|
if (err instanceof ApiError) {
|
|
53265
54063
|
if (err.status === 401) {
|
|
53266
54064
|
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
54065
|
+
} else if (err.status === 404) {
|
|
54066
|
+
f2.error(`Agent not found, or you don't have access. The id in ${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} may be stale.`);
|
|
53267
54067
|
} else {
|
|
53268
54068
|
f2.error(err.message);
|
|
53269
54069
|
}
|
|
53270
54070
|
} else {
|
|
53271
54071
|
f2.error(err.message);
|
|
53272
54072
|
}
|
|
53273
|
-
$e("Aborted.");
|
|
53274
54073
|
}
|
|
53275
54074
|
|
|
53276
54075
|
// src/cli/agent.ts
|
|
53277
|
-
async function runAgent(cwd2, sub,
|
|
54076
|
+
async function runAgent(cwd2, sub, args, opts) {
|
|
53278
54077
|
switch (sub) {
|
|
53279
54078
|
case "create":
|
|
53280
54079
|
await runAgentCreate(cwd2, {
|
|
@@ -53288,10 +54087,22 @@ async function runAgent(cwd2, sub, _args, opts) {
|
|
|
53288
54087
|
});
|
|
53289
54088
|
return;
|
|
53290
54089
|
case "pull":
|
|
53291
|
-
await runAgentPull(cwd2,
|
|
54090
|
+
await runAgentPull(cwd2, {
|
|
54091
|
+
yes: opts.yes,
|
|
54092
|
+
scope: opts.scope,
|
|
54093
|
+
agentIdArg: args[0],
|
|
54094
|
+
force: opts.force
|
|
54095
|
+
});
|
|
53292
54096
|
return;
|
|
53293
54097
|
case "push":
|
|
53294
|
-
await runAgentPush(cwd2, opts);
|
|
54098
|
+
await runAgentPush(cwd2, { yes: opts.yes });
|
|
54099
|
+
return;
|
|
54100
|
+
case "unpack":
|
|
54101
|
+
await runAgentUnpack(cwd2, {
|
|
54102
|
+
yes: opts.yes,
|
|
54103
|
+
scope: opts.scope,
|
|
54104
|
+
harness: opts.harness
|
|
54105
|
+
});
|
|
53295
54106
|
return;
|
|
53296
54107
|
case "status":
|
|
53297
54108
|
await runAgentStatus(cwd2);
|
|
@@ -53315,29 +54126,30 @@ async function runAgent(cwd2, sub, _args, opts) {
|
|
|
53315
54126
|
function printHelp() {
|
|
53316
54127
|
const out = [];
|
|
53317
54128
|
out.push("");
|
|
53318
|
-
out.push(` ${
|
|
54129
|
+
out.push(` ${import_picocolors32.default.bold("brainbase agent")} ${import_picocolors32.default.dim("<sub> [options]")}`);
|
|
53319
54130
|
out.push("");
|
|
53320
|
-
out.push(` ${
|
|
53321
|
-
out.push(` ${
|
|
53322
|
-
out.push(` ${
|
|
53323
|
-
out.push(` ${
|
|
53324
|
-
out.push(` ${
|
|
54131
|
+
out.push(` ${import_picocolors32.default.cyan("create")} ${import_picocolors32.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
54132
|
+
out.push(` ${import_picocolors32.default.cyan("pull")} ${import_picocolors32.default.dim("[<id>]")} ${import_picocolors32.default.dim("apply cloud changes into this folder — pass <id> to switch (--force to override)")}`);
|
|
54133
|
+
out.push(` ${import_picocolors32.default.cyan("push")} ${import_picocolors32.default.dim("send local changes to the cloud")}`);
|
|
54134
|
+
out.push(` ${import_picocolors32.default.cyan("unpack")} ${import_picocolors32.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
|
|
54135
|
+
out.push(` ${import_picocolors32.default.cyan("status")} ${import_picocolors32.default.dim("show what would push and what would pull")}`);
|
|
54136
|
+
out.push(` ${import_picocolors32.default.cyan("env")} ${import_picocolors32.default.dim('print export statements — use with `eval "$(brainbase agent env)"`')}`);
|
|
53325
54137
|
out.push("");
|
|
53326
54138
|
console.log(out.join(`
|
|
53327
54139
|
`));
|
|
53328
54140
|
}
|
|
53329
54141
|
|
|
53330
54142
|
// src/cli/orchestration.ts
|
|
53331
|
-
var
|
|
54143
|
+
var import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
53332
54144
|
|
|
53333
54145
|
// src/cli/orchestration-pull.ts
|
|
53334
|
-
import
|
|
54146
|
+
import path53 from "node:path";
|
|
53335
54147
|
import fs49 from "node:fs";
|
|
53336
|
-
var
|
|
54148
|
+
var import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
53337
54149
|
|
|
53338
54150
|
// src/core/orchestration-manifest.ts
|
|
53339
|
-
import
|
|
53340
|
-
import
|
|
54151
|
+
import path51 from "node:path";
|
|
54152
|
+
import fs47 from "node:fs";
|
|
53341
54153
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
53342
54154
|
var ORCH_MANIFEST_FILE = "brainbase-orchestration.yaml";
|
|
53343
54155
|
var ORCH_MEMBERS_DIR = "agents";
|
|
@@ -53365,16 +54177,16 @@ var OrchestrationManifestSchema = exports_external.object({
|
|
|
53365
54177
|
edges: exports_external.array(EdgeSchema).default([])
|
|
53366
54178
|
});
|
|
53367
54179
|
function orchManifestPath(cwd2) {
|
|
53368
|
-
return
|
|
54180
|
+
return path51.join(cwd2, ORCH_MANIFEST_FILE);
|
|
53369
54181
|
}
|
|
53370
54182
|
function hasOrchManifest(cwd2) {
|
|
53371
|
-
return
|
|
54183
|
+
return fs47.existsSync(orchManifestPath(cwd2));
|
|
53372
54184
|
}
|
|
53373
54185
|
function readOrchManifest(cwd2) {
|
|
53374
54186
|
const p2 = orchManifestPath(cwd2);
|
|
53375
|
-
if (!
|
|
54187
|
+
if (!fs47.existsSync(p2))
|
|
53376
54188
|
return null;
|
|
53377
|
-
const raw =
|
|
54189
|
+
const raw = fs47.readFileSync(p2, "utf8");
|
|
53378
54190
|
let parsed;
|
|
53379
54191
|
try {
|
|
53380
54192
|
parsed = import_yaml3.default.parse(raw);
|
|
@@ -53393,15 +54205,15 @@ function writeOrchManifest(cwd2, manifest) {
|
|
|
53393
54205
|
doc.commentBefore = ` brainbase-orchestration.yaml — declarative orchestration manifest.
|
|
53394
54206
|
` + ` Committed to source control. Edit by hand, then
|
|
53395
54207
|
` + " `brainbase orchestration push`. Member agents live under ./agents/.";
|
|
53396
|
-
|
|
54208
|
+
fs47.writeFileSync(orchManifestPath(cwd2), String(doc), "utf8");
|
|
53397
54209
|
}
|
|
53398
54210
|
function memberDir(cwd2, slug) {
|
|
53399
|
-
return
|
|
54211
|
+
return path51.join(cwd2, ORCH_MEMBERS_DIR, slug);
|
|
53400
54212
|
}
|
|
53401
54213
|
|
|
53402
54214
|
// src/core/orchestration-link.ts
|
|
53403
|
-
import
|
|
53404
|
-
import
|
|
54215
|
+
import path52 from "node:path";
|
|
54216
|
+
import fs48 from "node:fs";
|
|
53405
54217
|
var ORCH_LINK_FILE = "orchestration-link.json";
|
|
53406
54218
|
var ORCH_SYNC_STATE_FILE = "orchestration-sync-state.json";
|
|
53407
54219
|
var OrchestrationLinkSchema = exports_external.object({
|
|
@@ -53435,10 +54247,10 @@ var OrchestrationSyncStateSchema = exports_external.object({
|
|
|
53435
54247
|
edges: exports_external.array(SyncedEdgeSchema)
|
|
53436
54248
|
});
|
|
53437
54249
|
function orchLinkPath(cwd2) {
|
|
53438
|
-
return
|
|
54250
|
+
return path52.join(cwd2, LINK_DIR, ORCH_LINK_FILE);
|
|
53439
54251
|
}
|
|
53440
54252
|
function orchSyncStatePath(cwd2) {
|
|
53441
|
-
return
|
|
54253
|
+
return path52.join(cwd2, LINK_DIR, ORCH_SYNC_STATE_FILE);
|
|
53442
54254
|
}
|
|
53443
54255
|
function readOrchLink(cwd2) {
|
|
53444
54256
|
const p2 = orchLinkPath(cwd2);
|
|
@@ -53451,7 +54263,7 @@ function readOrchLink(cwd2) {
|
|
|
53451
54263
|
}
|
|
53452
54264
|
}
|
|
53453
54265
|
function writeOrchLink(cwd2, link2) {
|
|
53454
|
-
ensureDir(
|
|
54266
|
+
ensureDir(path52.join(cwd2, LINK_DIR));
|
|
53455
54267
|
const clean = {};
|
|
53456
54268
|
for (const [k3, v3] of Object.entries(link2)) {
|
|
53457
54269
|
if (v3 !== null && v3 !== undefined)
|
|
@@ -53471,200 +54283,28 @@ function readOrchSyncState(cwd2) {
|
|
|
53471
54283
|
}
|
|
53472
54284
|
}
|
|
53473
54285
|
function writeOrchSyncState(cwd2, state) {
|
|
53474
|
-
ensureDir(
|
|
54286
|
+
ensureDir(path52.join(cwd2, LINK_DIR));
|
|
53475
54287
|
writeJson(orchSyncStatePath(cwd2), state);
|
|
53476
54288
|
ensureGitignore2(cwd2);
|
|
53477
54289
|
}
|
|
53478
54290
|
function ensureGitignore2(cwd2) {
|
|
53479
|
-
const ignorePath =
|
|
54291
|
+
const ignorePath = path52.join(cwd2, LINK_DIR, ".gitignore");
|
|
53480
54292
|
const desired = `${ORCH_SYNC_STATE_FILE}
|
|
53481
54293
|
`;
|
|
53482
54294
|
try {
|
|
53483
54295
|
if (!exists(ignorePath)) {
|
|
53484
|
-
|
|
54296
|
+
fs48.writeFileSync(ignorePath, desired);
|
|
53485
54297
|
return;
|
|
53486
54298
|
}
|
|
53487
|
-
const current =
|
|
54299
|
+
const current = fs48.readFileSync(ignorePath, "utf8");
|
|
53488
54300
|
if (!current.split(/\r?\n/).some((l2) => l2.trim() === ORCH_SYNC_STATE_FILE)) {
|
|
53489
|
-
|
|
54301
|
+
fs48.writeFileSync(ignorePath, current.endsWith(`
|
|
53490
54302
|
`) ? current + desired : current + `
|
|
53491
54303
|
` + desired);
|
|
53492
54304
|
}
|
|
53493
54305
|
} catch {}
|
|
53494
54306
|
}
|
|
53495
54307
|
|
|
53496
|
-
// src/core/agent-fresh-install.ts
|
|
53497
|
-
import path51 from "node:path";
|
|
53498
|
-
import fs48 from "node:fs";
|
|
53499
|
-
import os13 from "node:os";
|
|
53500
|
-
async function installAgentFresh(input) {
|
|
53501
|
-
const { cwd: cwd2, agent, cloud, harness } = input;
|
|
53502
|
-
const scope = input.scope ?? "project";
|
|
53503
|
-
ensureDir(cwd2);
|
|
53504
|
-
const stageRoot = stageManifestComponents2(cloud.components);
|
|
53505
|
-
const justInstalledPaths = new Map;
|
|
53506
|
-
const cloudHasOrchestrationMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === ORCHESTRATION_MCP_SLUG);
|
|
53507
|
-
const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
|
|
53508
|
-
const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
|
|
53509
|
-
const needMemoryMcpInstall = !cloudHasMemoryMcp;
|
|
53510
|
-
try {
|
|
53511
|
-
if (cloud.components.length > 0 || needOrchestrationMcpInstall || needMemoryMcpInstall) {
|
|
53512
|
-
const toInstall = cloud.components.map((c2) => ({
|
|
53513
|
-
type: c2.type,
|
|
53514
|
-
slug: c2.slug,
|
|
53515
|
-
scope,
|
|
53516
|
-
rootDir: path51.join(stageRoot, c2.type, c2.slug),
|
|
53517
|
-
description: c2.description,
|
|
53518
|
-
meta: c2.meta,
|
|
53519
|
-
payload: c2.meta?.mcp,
|
|
53520
|
-
checksum: c2.hash
|
|
53521
|
-
}));
|
|
53522
|
-
if (needOrchestrationMcpInstall) {
|
|
53523
|
-
toInstall.push(buildOrchestrationMcpComponent(scope));
|
|
53524
|
-
}
|
|
53525
|
-
if (needMemoryMcpInstall) {
|
|
53526
|
-
toInstall.push(buildMemoryMcpComponent(scope));
|
|
53527
|
-
}
|
|
53528
|
-
const installOpts = {
|
|
53529
|
-
cwd: cwd2,
|
|
53530
|
-
scope,
|
|
53531
|
-
resolveConflict: async (_c) => "overwrite",
|
|
53532
|
-
resolveSecret: async () => null
|
|
53533
|
-
};
|
|
53534
|
-
const result = await runHarnessInstall3(harness, toInstall, installOpts, agent.name);
|
|
53535
|
-
for (const o2 of result.installed) {
|
|
53536
|
-
justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
|
|
53537
|
-
}
|
|
53538
|
-
}
|
|
53539
|
-
materializeInstructions2(cwd2, cloud);
|
|
53540
|
-
const manifest = buildManifestFromCloud(cloud, agent);
|
|
53541
|
-
writeManifest(cwd2, manifest);
|
|
53542
|
-
writeLink(cwd2, {
|
|
53543
|
-
schemaVersion: 1,
|
|
53544
|
-
agent_id: agent.id,
|
|
53545
|
-
org_id: agent.org_id,
|
|
53546
|
-
team_id: agent.team_id,
|
|
53547
|
-
slug: agent.slug,
|
|
53548
|
-
name: agent.name,
|
|
53549
|
-
tagline: agent.tagline,
|
|
53550
|
-
url: agent.url,
|
|
53551
|
-
linked_at: new Date().toISOString(),
|
|
53552
|
-
harness
|
|
53553
|
-
});
|
|
53554
|
-
const syncedComponents = cloud.components.map((c2) => ({
|
|
53555
|
-
type: c2.type,
|
|
53556
|
-
slug: c2.slug,
|
|
53557
|
-
hash: c2.hash,
|
|
53558
|
-
installedPaths: justInstalledPaths.get(`${c2.type}/${c2.slug}`) ?? []
|
|
53559
|
-
}));
|
|
53560
|
-
writeSyncState(cwd2, {
|
|
53561
|
-
schemaVersion: 1,
|
|
53562
|
-
agent_id: agent.id,
|
|
53563
|
-
revision: cloud.revision,
|
|
53564
|
-
synced_at: new Date().toISOString(),
|
|
53565
|
-
components: syncedComponents,
|
|
53566
|
-
agentMeta: { name: agent.name, tagline: agent.tagline }
|
|
53567
|
-
});
|
|
53568
|
-
if (input.pullSecrets !== false) {
|
|
53569
|
-
await pullAgentSecrets(cwd2, agent.id);
|
|
53570
|
-
}
|
|
53571
|
-
return {
|
|
53572
|
-
installedPaths: justInstalledPaths,
|
|
53573
|
-
manifest,
|
|
53574
|
-
syncedComponents
|
|
53575
|
-
};
|
|
53576
|
-
} finally {
|
|
53577
|
-
try {
|
|
53578
|
-
fs48.rmSync(stageRoot, { recursive: true, force: true });
|
|
53579
|
-
} catch {}
|
|
53580
|
-
}
|
|
53581
|
-
}
|
|
53582
|
-
function stageManifestComponents2(components) {
|
|
53583
|
-
const root = fs48.mkdtempSync(path51.join(os13.tmpdir(), "brainbase-orch-pull-"));
|
|
53584
|
-
for (const c2 of components) {
|
|
53585
|
-
const compDir = path51.join(root, c2.type, c2.slug);
|
|
53586
|
-
ensureDir(compDir);
|
|
53587
|
-
for (const f4 of c2.files) {
|
|
53588
|
-
const target = path51.join(compDir, f4.path);
|
|
53589
|
-
ensureDir(path51.dirname(target));
|
|
53590
|
-
fs48.writeFileSync(target, f4.content);
|
|
53591
|
-
}
|
|
53592
|
-
}
|
|
53593
|
-
return root;
|
|
53594
|
-
}
|
|
53595
|
-
function runHarnessInstall3(harnessId, components, opts, agentName) {
|
|
53596
|
-
if (harnessId === "claude-code")
|
|
53597
|
-
return installClaudeCodeWithCtx(components, opts, agentName);
|
|
53598
|
-
if (harnessId === "codex")
|
|
53599
|
-
return installCodexWithCtx(components, opts, agentName);
|
|
53600
|
-
if (harnessId === "kafka")
|
|
53601
|
-
return installKafkaWithCtx(components, opts, agentName);
|
|
53602
|
-
return getAdapter(harnessId).install(components, opts);
|
|
53603
|
-
}
|
|
53604
|
-
function materializeInstructions2(cwd2, cloud) {
|
|
53605
|
-
for (const c2 of cloud.components) {
|
|
53606
|
-
if (c2.type !== "instruction")
|
|
53607
|
-
continue;
|
|
53608
|
-
const body = c2.files[0]?.content ?? "";
|
|
53609
|
-
if (!body.trim())
|
|
53610
|
-
continue;
|
|
53611
|
-
fs48.writeFileSync(path51.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
|
|
53612
|
-
return;
|
|
53613
|
-
}
|
|
53614
|
-
}
|
|
53615
|
-
function buildManifestFromCloud(cloud, agent) {
|
|
53616
|
-
const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
|
|
53617
|
-
const meta = c2.meta ?? {};
|
|
53618
|
-
if (meta.name && meta.name.includes("/")) {
|
|
53619
|
-
return {
|
|
53620
|
-
source: meta.version ? `registry:${meta.name}@${meta.version}` : `registry:${meta.name}`
|
|
53621
|
-
};
|
|
53622
|
-
}
|
|
53623
|
-
return { source: `registry:${c2.slug}` };
|
|
53624
|
-
});
|
|
53625
|
-
const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
|
|
53626
|
-
const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
|
|
53627
|
-
const payload = (c2.meta ?? {}).mcp ?? {};
|
|
53628
|
-
const entry = { name: c2.slug };
|
|
53629
|
-
if (typeof payload.url === "string")
|
|
53630
|
-
entry.url = payload.url;
|
|
53631
|
-
if (typeof payload.command === "string")
|
|
53632
|
-
entry.command = payload.command;
|
|
53633
|
-
if (Array.isArray(payload.args))
|
|
53634
|
-
entry.args = payload.args.map(String);
|
|
53635
|
-
if (payload.env && typeof payload.env === "object")
|
|
53636
|
-
entry.env = payload.env;
|
|
53637
|
-
if (payload.headers && typeof payload.headers === "object")
|
|
53638
|
-
entry.headers = payload.headers;
|
|
53639
|
-
if (typeof payload.is_enabled === "boolean")
|
|
53640
|
-
entry.is_enabled = payload.is_enabled;
|
|
53641
|
-
return entry;
|
|
53642
|
-
});
|
|
53643
|
-
return {
|
|
53644
|
-
schema: 1,
|
|
53645
|
-
agent: {
|
|
53646
|
-
name: agent.name,
|
|
53647
|
-
...agent.tagline ? { tagline: agent.tagline } : {}
|
|
53648
|
-
},
|
|
53649
|
-
...hasInstructions ? { instructions: { file: DEFAULT_INSTRUCTIONS_FILE } } : {},
|
|
53650
|
-
skills,
|
|
53651
|
-
mcp
|
|
53652
|
-
};
|
|
53653
|
-
}
|
|
53654
|
-
async function pullAgentSecrets(cwd2, agentId) {
|
|
53655
|
-
try {
|
|
53656
|
-
const res = await api.getAgentSecrets(agentId);
|
|
53657
|
-
const secrets = res.secrets ?? {};
|
|
53658
|
-
if (Object.keys(secrets).length > 0) {
|
|
53659
|
-
writeLocalSecrets(cwd2, secrets);
|
|
53660
|
-
}
|
|
53661
|
-
} catch (err) {
|
|
53662
|
-
if (err instanceof ApiError && err.status !== 404) {
|
|
53663
|
-
f2.warn(`Skipped secrets for agent ${agentId}: ${err.message}`);
|
|
53664
|
-
}
|
|
53665
|
-
}
|
|
53666
|
-
}
|
|
53667
|
-
|
|
53668
54308
|
// src/cli/orchestration-pull.ts
|
|
53669
54309
|
async function runOrchestrationPull(cwd2, args) {
|
|
53670
54310
|
banner("orchestration pull — fetch orchestration + all member agents");
|
|
@@ -53676,8 +54316,8 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53676
54316
|
orchId = args.orchestrationId;
|
|
53677
54317
|
} else {
|
|
53678
54318
|
f2.warn("This folder is not linked to any orchestration.");
|
|
53679
|
-
f2.info(`Run ${
|
|
53680
|
-
or ${
|
|
54319
|
+
f2.info(`Run ${import_picocolors33.default.cyan("brainbase orchestration pull <id>")} with an orchestration id,
|
|
54320
|
+
or ${import_picocolors33.default.cyan("brainbase orchestration list")} to find one.`);
|
|
53681
54321
|
return;
|
|
53682
54322
|
}
|
|
53683
54323
|
const sp = de();
|
|
@@ -53688,29 +54328,29 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53688
54328
|
sp.stop(`Cloud revision ${cloud.revision} — ${cloud.members.length} member${cloud.members.length === 1 ? "" : "s"}, ${cloud.edges.length} edge${cloud.edges.length === 1 ? "" : "s"}.`);
|
|
53689
54329
|
} catch (err) {
|
|
53690
54330
|
sp.stop("Failed.");
|
|
53691
|
-
|
|
54331
|
+
handleApiError6(err);
|
|
53692
54332
|
return;
|
|
53693
54333
|
}
|
|
53694
54334
|
const planLines = [];
|
|
53695
54335
|
planLines.push("");
|
|
53696
|
-
planLines.push(` ${
|
|
54336
|
+
planLines.push(` ${import_picocolors33.default.bold(cloud.name)} ${import_picocolors33.default.dim(`(${cloud.id})`)}`);
|
|
53697
54337
|
if (cloud.description)
|
|
53698
|
-
planLines.push(` ${
|
|
54338
|
+
planLines.push(` ${import_picocolors33.default.dim(cloud.description)}`);
|
|
53699
54339
|
planLines.push("");
|
|
53700
|
-
planLines.push(` ${
|
|
54340
|
+
planLines.push(` ${import_picocolors33.default.dim("members:")}`);
|
|
53701
54341
|
for (const m3 of cloud.members) {
|
|
53702
54342
|
const skipped = !m3.manifest;
|
|
53703
|
-
const tail = skipped ?
|
|
53704
|
-
planLines.push(` ${
|
|
54343
|
+
const tail = skipped ? import_picocolors33.default.red(" (manifest unavailable — skipped)") : "";
|
|
54344
|
+
planLines.push(` ${import_picocolors33.default.cyan("•")} ${import_picocolors33.default.bold(m3.slug)} ${import_picocolors33.default.dim(`(${m3.name})`)}${tail}`);
|
|
53705
54345
|
}
|
|
53706
54346
|
if (cloud.edges.length) {
|
|
53707
54347
|
planLines.push("");
|
|
53708
|
-
planLines.push(` ${
|
|
54348
|
+
planLines.push(` ${import_picocolors33.default.dim("edges:")}`);
|
|
53709
54349
|
for (const e2 of cloud.edges) {
|
|
53710
54350
|
const from = e2.from_slug ?? e2.from_agent_id;
|
|
53711
54351
|
const to2 = e2.to_slug ?? e2.to_agent_id;
|
|
53712
|
-
const desc = e2.description ? ` ${
|
|
53713
|
-
planLines.push(` ${
|
|
54352
|
+
const desc = e2.description ? ` ${import_picocolors33.default.dim("— " + e2.description)}` : "";
|
|
54353
|
+
planLines.push(` ${import_picocolors33.default.cyan(from)} ${import_picocolors33.default.dim("→")} ${import_picocolors33.default.cyan(to2)}${desc}`);
|
|
53714
54354
|
}
|
|
53715
54355
|
}
|
|
53716
54356
|
planLines.push("");
|
|
@@ -53719,7 +54359,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53719
54359
|
const isRefresh = !!existingLink;
|
|
53720
54360
|
if (!args.yes && !isRefresh) {
|
|
53721
54361
|
const ok = await se({
|
|
53722
|
-
message: `Pull into ${
|
|
54362
|
+
message: `Pull into ${import_picocolors33.default.bold(cwd2)}?`,
|
|
53723
54363
|
initialValue: true
|
|
53724
54364
|
});
|
|
53725
54365
|
if (!ensureNotCancelled(ok)) {
|
|
@@ -53760,7 +54400,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53760
54400
|
scope: "project",
|
|
53761
54401
|
pullSecrets: true
|
|
53762
54402
|
});
|
|
53763
|
-
memberSp.stop(`Installed ${
|
|
54403
|
+
memberSp.stop(`Installed ${import_picocolors33.default.bold(m3.slug)} ${import_picocolors33.default.dim(`(${m3.manifest.components.length} components)`)}.`);
|
|
53764
54404
|
installedMembers.push({
|
|
53765
54405
|
agent_id: m3.agent_id,
|
|
53766
54406
|
slug: m3.slug,
|
|
@@ -53815,9 +54455,9 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53815
54455
|
payload_schema: e2.payload_schema ?? {}
|
|
53816
54456
|
}))
|
|
53817
54457
|
});
|
|
53818
|
-
$e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${
|
|
54458
|
+
$e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path53.basename(cwd2)}/ ${import_picocolors33.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
|
|
53819
54459
|
}
|
|
53820
|
-
function
|
|
54460
|
+
function handleApiError6(err) {
|
|
53821
54461
|
if (err instanceof ApiError) {
|
|
53822
54462
|
if (err.status === 401) {
|
|
53823
54463
|
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
@@ -53832,18 +54472,18 @@ function handleApiError5(err) {
|
|
|
53832
54472
|
}
|
|
53833
54473
|
|
|
53834
54474
|
// src/cli/orchestration-push.ts
|
|
53835
|
-
var
|
|
54475
|
+
var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
53836
54476
|
async function runOrchestrationPush(cwd2, args) {
|
|
53837
54477
|
banner("orchestration push — recursively push each member, then update the graph");
|
|
53838
54478
|
const link2 = readOrchLink(cwd2);
|
|
53839
54479
|
if (!link2) {
|
|
53840
54480
|
f2.warn("This folder is not linked to any orchestration.");
|
|
53841
|
-
f2.info(`Run ${
|
|
54481
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
53842
54482
|
return;
|
|
53843
54483
|
}
|
|
53844
54484
|
if (!hasOrchManifest(cwd2)) {
|
|
53845
|
-
f2.warn(`No ${
|
|
53846
|
-
f2.info(`Run ${
|
|
54485
|
+
f2.warn(`No ${import_picocolors34.default.bold(ORCH_MANIFEST_FILE)} here.`);
|
|
54486
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to materialise the manifest before pushing.`);
|
|
53847
54487
|
return;
|
|
53848
54488
|
}
|
|
53849
54489
|
let manifest;
|
|
@@ -53856,15 +54496,15 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53856
54496
|
const memberSlugs = new Set(manifest.members.map((m3) => m3.slug));
|
|
53857
54497
|
for (const e2 of manifest.edges) {
|
|
53858
54498
|
if (!memberSlugs.has(e2.from)) {
|
|
53859
|
-
f2.error(`Edge from "${
|
|
54499
|
+
f2.error(`Edge from "${import_picocolors34.default.bold(e2.from)}" references a slug that isn't in members.`);
|
|
53860
54500
|
return;
|
|
53861
54501
|
}
|
|
53862
54502
|
if (!memberSlugs.has(e2.to)) {
|
|
53863
|
-
f2.error(`Edge to "${
|
|
54503
|
+
f2.error(`Edge to "${import_picocolors34.default.bold(e2.to)}" references a slug that isn't in members.`);
|
|
53864
54504
|
return;
|
|
53865
54505
|
}
|
|
53866
54506
|
if (e2.from === e2.to) {
|
|
53867
|
-
f2.error(`Edge ${
|
|
54507
|
+
f2.error(`Edge ${import_picocolors34.default.bold(e2.from)} → ${import_picocolors34.default.bold(e2.to)}: self-loops are not allowed.`);
|
|
53868
54508
|
return;
|
|
53869
54509
|
}
|
|
53870
54510
|
}
|
|
@@ -53881,17 +54521,17 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53881
54521
|
}
|
|
53882
54522
|
if (missing.length) {
|
|
53883
54523
|
f2.error(`These members have no local checkout (expected at agents/<slug>/.brainbase/link.json): ${missing.join(", ")}.`);
|
|
53884
|
-
f2.info(`Run ${
|
|
54524
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to materialise the missing folders.`);
|
|
53885
54525
|
return;
|
|
53886
54526
|
}
|
|
53887
54527
|
const plan = [""];
|
|
53888
|
-
plan.push(` ${
|
|
53889
|
-
plan.push(` ${
|
|
54528
|
+
plan.push(` ${import_picocolors34.default.bold(link2.name)} ${import_picocolors34.default.dim(`(${link2.orchestration_id})`)}`);
|
|
54529
|
+
plan.push(` ${import_picocolors34.default.dim(`${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}`)}`);
|
|
53890
54530
|
plan.push("");
|
|
53891
54531
|
if (!args.graphOnly) {
|
|
53892
|
-
plan.push(` ${
|
|
54532
|
+
plan.push(` ${import_picocolors34.default.dim("per-member agent push:")}`);
|
|
53893
54533
|
for (const m3 of manifest.members) {
|
|
53894
|
-
plan.push(` ${
|
|
54534
|
+
plan.push(` ${import_picocolors34.default.cyan("•")} ${import_picocolors34.default.bold(m3.slug)}`);
|
|
53895
54535
|
}
|
|
53896
54536
|
plan.push("");
|
|
53897
54537
|
}
|
|
@@ -53911,7 +54551,7 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53911
54551
|
for (const m3 of manifest.members) {
|
|
53912
54552
|
const dir = memberDir(cwd2, m3.slug);
|
|
53913
54553
|
console.log("");
|
|
53914
|
-
console.log(`${
|
|
54554
|
+
console.log(`${import_picocolors34.default.dim("───")} ${import_picocolors34.default.bold(m3.slug)} ${import_picocolors34.default.dim("───")}`);
|
|
53915
54555
|
try {
|
|
53916
54556
|
await runAgentPush(dir, { yes: true });
|
|
53917
54557
|
} catch (err) {
|
|
@@ -53962,10 +54602,10 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53962
54602
|
$e(`Pushed ${link2.name} at revision ${updated.revision}.`);
|
|
53963
54603
|
} catch (err) {
|
|
53964
54604
|
sp.stop("Failed.");
|
|
53965
|
-
|
|
54605
|
+
handleApiError7(err);
|
|
53966
54606
|
}
|
|
53967
54607
|
}
|
|
53968
|
-
function
|
|
54608
|
+
function handleApiError7(err) {
|
|
53969
54609
|
if (err instanceof ApiError) {
|
|
53970
54610
|
if (err.status === 401) {
|
|
53971
54611
|
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
@@ -53973,7 +54613,7 @@ function handleApiError6(err) {
|
|
|
53973
54613
|
f2.error("You do not have access to this orchestration.");
|
|
53974
54614
|
} else if (err.status === 409) {
|
|
53975
54615
|
f2.error(err.message);
|
|
53976
|
-
f2.info(`Run ${
|
|
54616
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to reconcile, then push again.`);
|
|
53977
54617
|
} else {
|
|
53978
54618
|
f2.error(err.message);
|
|
53979
54619
|
}
|
|
@@ -53983,13 +54623,13 @@ function handleApiError6(err) {
|
|
|
53983
54623
|
}
|
|
53984
54624
|
|
|
53985
54625
|
// src/cli/orchestration-status.ts
|
|
53986
|
-
var
|
|
54626
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
53987
54627
|
async function runOrchestrationStatus(cwd2) {
|
|
53988
54628
|
banner("orchestration status — what changed locally, remotely, both");
|
|
53989
54629
|
const link2 = readOrchLink(cwd2);
|
|
53990
54630
|
if (!link2) {
|
|
53991
54631
|
f2.warn("This folder is not linked to any orchestration.");
|
|
53992
|
-
f2.info(`Run ${
|
|
54632
|
+
f2.info(`Run ${import_picocolors35.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
53993
54633
|
return;
|
|
53994
54634
|
}
|
|
53995
54635
|
const localManifest = hasOrchManifest(cwd2) ? readOrchManifest(cwd2) : null;
|
|
@@ -54011,20 +54651,20 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
54011
54651
|
}
|
|
54012
54652
|
const lines = [];
|
|
54013
54653
|
lines.push("");
|
|
54014
|
-
lines.push(` ${
|
|
54015
|
-
lines.push(` ${
|
|
54654
|
+
lines.push(` ${import_picocolors35.default.bold(link2.name)} ${import_picocolors35.default.dim(`(${link2.orchestration_id})`)}`);
|
|
54655
|
+
lines.push(` ${import_picocolors35.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
|
|
54016
54656
|
lines.push("");
|
|
54017
54657
|
const cloudMemberSet = new Set(cloud.members.map((m3) => m3.slug));
|
|
54018
54658
|
const localMemberSet = new Set((localManifest?.members ?? []).map((m3) => m3.slug));
|
|
54019
54659
|
const membersAdded = [...localMemberSet].filter((s3) => !cloudMemberSet.has(s3));
|
|
54020
54660
|
const membersRemoved = [...cloudMemberSet].filter((s3) => !localMemberSet.has(s3));
|
|
54021
54661
|
if (membersAdded.length || membersRemoved.length) {
|
|
54022
|
-
lines.push(` ${
|
|
54662
|
+
lines.push(` ${import_picocolors35.default.bold("members")}`);
|
|
54023
54663
|
for (const slug of membersAdded) {
|
|
54024
|
-
lines.push(` ${
|
|
54664
|
+
lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${import_picocolors35.default.bold(slug)}`);
|
|
54025
54665
|
}
|
|
54026
54666
|
for (const slug of membersRemoved) {
|
|
54027
|
-
lines.push(` ${
|
|
54667
|
+
lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${import_picocolors35.default.bold(slug)}`);
|
|
54028
54668
|
}
|
|
54029
54669
|
lines.push("");
|
|
54030
54670
|
}
|
|
@@ -54039,11 +54679,11 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
54039
54679
|
const edgesAdded = [...localEdges.keys()].filter((k3) => !cloudEdges.has(k3));
|
|
54040
54680
|
const edgesRemoved = [...cloudEdges.keys()].filter((k3) => !localEdges.has(k3));
|
|
54041
54681
|
if (edgesAdded.length || edgesRemoved.length) {
|
|
54042
|
-
lines.push(` ${
|
|
54682
|
+
lines.push(` ${import_picocolors35.default.bold("edges")}`);
|
|
54043
54683
|
for (const k3 of edgesAdded)
|
|
54044
|
-
lines.push(` ${
|
|
54684
|
+
lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${k3}`);
|
|
54045
54685
|
for (const k3 of edgesRemoved)
|
|
54046
|
-
lines.push(` ${
|
|
54686
|
+
lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${k3}`);
|
|
54047
54687
|
lines.push("");
|
|
54048
54688
|
}
|
|
54049
54689
|
const lockByAgentId = new Map((lock?.members ?? []).map((m3) => [m3.agent_id, m3]));
|
|
@@ -54065,28 +54705,28 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
54065
54705
|
}
|
|
54066
54706
|
}
|
|
54067
54707
|
if (memberDrift.length) {
|
|
54068
|
-
lines.push(` ${
|
|
54708
|
+
lines.push(` ${import_picocolors35.default.bold("member content drift")}`);
|
|
54069
54709
|
for (const d3 of memberDrift) {
|
|
54070
|
-
lines.push(` ${
|
|
54710
|
+
lines.push(` ${import_picocolors35.default.cyan("?")} ${import_picocolors35.default.bold(d3.slug)} ${import_picocolors35.default.dim("— " + d3.reason)}`);
|
|
54071
54711
|
}
|
|
54072
|
-
lines.push(` ${
|
|
54712
|
+
lines.push(` ${import_picocolors35.default.dim("cd into each member folder and run")} ${import_picocolors35.default.cyan("brainbase agent status")}`);
|
|
54073
54713
|
lines.push("");
|
|
54074
54714
|
}
|
|
54075
54715
|
if (!membersAdded.length && !membersRemoved.length && !edgesAdded.length && !edgesRemoved.length && !memberDrift.length) {
|
|
54076
|
-
lines.push(` ${
|
|
54716
|
+
lines.push(` ${import_picocolors35.default.green("✓")} everything is in sync`);
|
|
54077
54717
|
lines.push("");
|
|
54078
54718
|
console.log(lines.join(`
|
|
54079
54719
|
`));
|
|
54080
54720
|
return;
|
|
54081
54721
|
}
|
|
54082
|
-
lines.push(` ${
|
|
54722
|
+
lines.push(` ${import_picocolors35.default.dim("run")} ${import_picocolors35.default.cyan("brainbase orchestration pull")} ${import_picocolors35.default.dim("to apply cloud changes,")} ${import_picocolors35.default.cyan("brainbase orchestration push")} ${import_picocolors35.default.dim("to send yours")}`);
|
|
54083
54723
|
lines.push("");
|
|
54084
54724
|
console.log(lines.join(`
|
|
54085
54725
|
`));
|
|
54086
54726
|
}
|
|
54087
54727
|
|
|
54088
54728
|
// src/cli/orchestration-list.ts
|
|
54089
|
-
var
|
|
54729
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
54090
54730
|
async function runOrchestrationList(args) {
|
|
54091
54731
|
banner("orchestration list — orchestrations under a team");
|
|
54092
54732
|
let orgId = args.orgId;
|
|
@@ -54096,7 +54736,7 @@ async function runOrchestrationList(args) {
|
|
|
54096
54736
|
try {
|
|
54097
54737
|
orgs = await api.listOrgs();
|
|
54098
54738
|
} catch (err) {
|
|
54099
|
-
|
|
54739
|
+
handleApiError8(err);
|
|
54100
54740
|
return;
|
|
54101
54741
|
}
|
|
54102
54742
|
if (orgs.length === 0) {
|
|
@@ -54118,7 +54758,7 @@ async function runOrchestrationList(args) {
|
|
|
54118
54758
|
try {
|
|
54119
54759
|
teams = await api.listTeams(orgId);
|
|
54120
54760
|
} catch (err) {
|
|
54121
|
-
|
|
54761
|
+
handleApiError8(err);
|
|
54122
54762
|
return;
|
|
54123
54763
|
}
|
|
54124
54764
|
if (teams.length === 0) {
|
|
@@ -54143,7 +54783,7 @@ async function runOrchestrationList(args) {
|
|
|
54143
54783
|
sp.stop(`${items.length} orchestration${items.length === 1 ? "" : "s"}.`);
|
|
54144
54784
|
} catch (err) {
|
|
54145
54785
|
sp.stop("Failed.");
|
|
54146
|
-
|
|
54786
|
+
handleApiError8(err);
|
|
54147
54787
|
return;
|
|
54148
54788
|
}
|
|
54149
54789
|
if (items.length === 0) {
|
|
@@ -54152,18 +54792,18 @@ async function runOrchestrationList(args) {
|
|
|
54152
54792
|
}
|
|
54153
54793
|
const lines = [""];
|
|
54154
54794
|
for (const o2 of items) {
|
|
54155
|
-
lines.push(` ${
|
|
54795
|
+
lines.push(` ${import_picocolors36.default.bold(o2.name)} ${import_picocolors36.default.dim(o2.id)}`);
|
|
54156
54796
|
if (o2.description)
|
|
54157
|
-
lines.push(` ${
|
|
54158
|
-
lines.push(` ${
|
|
54797
|
+
lines.push(` ${import_picocolors36.default.dim(o2.description)}`);
|
|
54798
|
+
lines.push(` ${import_picocolors36.default.dim(`${o2.member_count} member${o2.member_count === 1 ? "" : "s"} · ${o2.edge_count} edge${o2.edge_count === 1 ? "" : "s"}`)}`);
|
|
54159
54799
|
lines.push("");
|
|
54160
54800
|
}
|
|
54161
|
-
lines.push(` ${
|
|
54801
|
+
lines.push(` ${import_picocolors36.default.dim("pull one with")} ${import_picocolors36.default.cyan("brainbase orchestration pull <id>")}`);
|
|
54162
54802
|
lines.push("");
|
|
54163
54803
|
console.log(lines.join(`
|
|
54164
54804
|
`));
|
|
54165
54805
|
}
|
|
54166
|
-
function
|
|
54806
|
+
function handleApiError8(err) {
|
|
54167
54807
|
if (err instanceof ApiError) {
|
|
54168
54808
|
if (err.status === 401) {
|
|
54169
54809
|
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
@@ -54214,26 +54854,26 @@ async function runOrchestration(cwd2, sub, args, opts) {
|
|
|
54214
54854
|
function printHelp2() {
|
|
54215
54855
|
const out = [];
|
|
54216
54856
|
out.push("");
|
|
54217
|
-
out.push(` ${
|
|
54857
|
+
out.push(` ${import_picocolors37.default.bold("brainbase orchestration")} ${import_picocolors37.default.dim("<sub> [options]")}`);
|
|
54218
54858
|
out.push("");
|
|
54219
|
-
out.push(` ${
|
|
54220
|
-
out.push(` ${
|
|
54221
|
-
out.push(` ${
|
|
54222
|
-
out.push(` ${
|
|
54859
|
+
out.push(` ${import_picocolors37.default.cyan("pull")} ${import_picocolors37.default.dim("<id>")} ${import_picocolors37.default.dim("fetch orchestration + every member agent into this folder")}`);
|
|
54860
|
+
out.push(` ${import_picocolors37.default.cyan("push")} ${import_picocolors37.default.dim("push each member, then update the orchestration graph")}`);
|
|
54861
|
+
out.push(` ${import_picocolors37.default.cyan("status")} ${import_picocolors37.default.dim("show what would push and what would pull")}`);
|
|
54862
|
+
out.push(` ${import_picocolors37.default.cyan("list")} ${import_picocolors37.default.dim("list orchestrations under a team")}`);
|
|
54223
54863
|
out.push("");
|
|
54224
|
-
out.push(` ${
|
|
54225
|
-
out.push(` ${
|
|
54226
|
-
out.push(` ${
|
|
54227
|
-
out.push(` ${
|
|
54228
|
-
out.push(` ${
|
|
54229
|
-
out.push(` ${
|
|
54864
|
+
out.push(` ${import_picocolors37.default.bold("Flags")}`);
|
|
54865
|
+
out.push(` ${import_picocolors37.default.dim("--yes, -y")} skip confirmations`);
|
|
54866
|
+
out.push(` ${import_picocolors37.default.dim("--harness <id>")} harness for newly-created member folders (default claude-code)`);
|
|
54867
|
+
out.push(` ${import_picocolors37.default.dim("--graph-only")} for push: only update members + edges, skip per-member push`);
|
|
54868
|
+
out.push(` ${import_picocolors37.default.dim("--org <id>")} for list: org id (CLI vocab — DB teams.id)`);
|
|
54869
|
+
out.push(` ${import_picocolors37.default.dim("--team <id>")} for list: team id (CLI vocab — DB groups.id)`);
|
|
54230
54870
|
out.push("");
|
|
54231
54871
|
console.log(out.join(`
|
|
54232
54872
|
`));
|
|
54233
54873
|
}
|
|
54234
54874
|
|
|
54235
54875
|
// src/cli/run.ts
|
|
54236
|
-
import { spawn as
|
|
54876
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
54237
54877
|
async function runRun(cwd2, args) {
|
|
54238
54878
|
const cleaned = args[0] === "--" ? args.slice(1) : args;
|
|
54239
54879
|
if (cleaned.length === 0) {
|
|
@@ -54245,7 +54885,7 @@ async function runRun(cwd2, args) {
|
|
|
54245
54885
|
const [cmd, ...cmdArgs] = cleaned;
|
|
54246
54886
|
const secrets = readLocalSecrets(cwd2);
|
|
54247
54887
|
const env3 = { ...process.env, ...secrets };
|
|
54248
|
-
const child =
|
|
54888
|
+
const child = spawn3(cmd, cmdArgs, {
|
|
54249
54889
|
cwd: cwd2,
|
|
54250
54890
|
env: env3,
|
|
54251
54891
|
stdio: "inherit",
|
|
@@ -54271,16 +54911,16 @@ async function runRun(cwd2, args) {
|
|
|
54271
54911
|
}
|
|
54272
54912
|
|
|
54273
54913
|
// src/cli/publish.ts
|
|
54274
|
-
var
|
|
54914
|
+
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
54275
54915
|
async function runPublish(cwd2, _args) {
|
|
54276
54916
|
banner("publish — send your changes to the team");
|
|
54277
54917
|
const link2 = readLink(cwd2);
|
|
54278
54918
|
if (!link2) {
|
|
54279
54919
|
f2.warn("This folder is not linked to any agent.");
|
|
54280
|
-
f2.info(`Run ${
|
|
54920
|
+
f2.info(`Run ${import_picocolors38.default.cyan("brainbase link")} first.`);
|
|
54281
54921
|
return;
|
|
54282
54922
|
}
|
|
54283
|
-
f2.info(`${
|
|
54923
|
+
f2.info(`${import_picocolors38.default.bold("publish")} is coming soon — for now, edit the agent on the web app and run ${import_picocolors38.default.cyan("brainbase sync")} to bring changes here.`);
|
|
54284
54924
|
}
|
|
54285
54925
|
|
|
54286
54926
|
// src/ui/ink/StatusCard.tsx
|
|
@@ -54578,7 +55218,7 @@ async function runStatus(cwd2) {
|
|
|
54578
55218
|
}
|
|
54579
55219
|
|
|
54580
55220
|
// src/cli/token.ts
|
|
54581
|
-
var
|
|
55221
|
+
var import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
54582
55222
|
|
|
54583
55223
|
// src/ui/ink/TokenCards.tsx
|
|
54584
55224
|
var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
|
|
@@ -54872,7 +55512,7 @@ async function runTokenRevoke(args) {
|
|
|
54872
55512
|
}
|
|
54873
55513
|
if (!args.yes) {
|
|
54874
55514
|
const ok = await se({
|
|
54875
|
-
message: `Revoke token ${
|
|
55515
|
+
message: `Revoke token ${import_picocolors39.default.bold(args.id)}? CIs and machines using it will stop working.`,
|
|
54876
55516
|
initialValue: false
|
|
54877
55517
|
});
|
|
54878
55518
|
if (!ensureNotCancelled(ok))
|
|
@@ -54887,7 +55527,7 @@ async function runTokenRevoke(args) {
|
|
|
54887
55527
|
}
|
|
54888
55528
|
async function runTokenClear() {
|
|
54889
55529
|
if (!readToken()) {
|
|
54890
|
-
console.log(
|
|
55530
|
+
console.log(import_picocolors39.default.dim("No local token stored."));
|
|
54891
55531
|
return;
|
|
54892
55532
|
}
|
|
54893
55533
|
clearToken();
|
|
@@ -54938,17 +55578,17 @@ async function runToken(sub, rest, args) {
|
|
|
54938
55578
|
function printTokenHelp() {
|
|
54939
55579
|
const out = [];
|
|
54940
55580
|
out.push("");
|
|
54941
|
-
out.push(` ${
|
|
55581
|
+
out.push(` ${import_picocolors39.default.bold("brainbase token")} ${import_picocolors39.default.dim("<command>")}`);
|
|
54942
55582
|
out.push("");
|
|
54943
|
-
out.push(` ${
|
|
54944
|
-
out.push(` ${
|
|
54945
|
-
out.push(` ${
|
|
54946
|
-
out.push(` ${
|
|
55583
|
+
out.push(` ${import_picocolors39.default.cyan("create")} ${import_picocolors39.default.dim("issue a new long-lived CLI key (PAT)")}`);
|
|
55584
|
+
out.push(` ${import_picocolors39.default.cyan("list")} ${import_picocolors39.default.dim("show your active tokens")}`);
|
|
55585
|
+
out.push(` ${import_picocolors39.default.cyan("revoke")} ${import_picocolors39.default.dim("<id>")} ${import_picocolors39.default.dim("revoke a token by id")}`);
|
|
55586
|
+
out.push(` ${import_picocolors39.default.cyan("clear")} ${import_picocolors39.default.dim("forget the local token (does not revoke)")}`);
|
|
54947
55587
|
out.push("");
|
|
54948
|
-
out.push(` ${
|
|
54949
|
-
out.push(` ${
|
|
54950
|
-
out.push(` ${
|
|
54951
|
-
out.push(` ${
|
|
55588
|
+
out.push(` ${import_picocolors39.default.bold("create flags")}`);
|
|
55589
|
+
out.push(` ${import_picocolors39.default.cyan("--name, -n")} ${import_picocolors39.default.dim("<label>")} ${import_picocolors39.default.dim("token label (prompted if omitted)")}`);
|
|
55590
|
+
out.push(` ${import_picocolors39.default.cyan("--scopes")} ${import_picocolors39.default.dim("<list>")} ${import_picocolors39.default.dim("comma-separated; allowed: read, publish, admin")}`);
|
|
55591
|
+
out.push(` ${import_picocolors39.default.dim("default: read,publish")}`);
|
|
54952
55592
|
out.push("");
|
|
54953
55593
|
console.log(out.join(`
|
|
54954
55594
|
`));
|
|
@@ -54968,89 +55608,90 @@ var PROTECTED = new Set([
|
|
|
54968
55608
|
function help() {
|
|
54969
55609
|
const out = [];
|
|
54970
55610
|
out.push("");
|
|
54971
|
-
out.push(` ${brandTint("◆")} ${
|
|
54972
|
-
out.push(` ${
|
|
55611
|
+
out.push(` ${brandTint("◆")} ${import_picocolors40.default.bold("brainbase")} ${import_picocolors40.default.dim("v0.5.0")}`);
|
|
55612
|
+
out.push(` ${import_picocolors40.default.dim("connect your local agent to the brainbase platform")}`);
|
|
54973
55613
|
out.push("");
|
|
54974
55614
|
out.push(divider("USAGE"));
|
|
54975
55615
|
out.push("");
|
|
54976
|
-
out.push(` ${
|
|
55616
|
+
out.push(` ${import_picocolors40.default.bold("brainbase")} ${import_picocolors40.default.dim("<command> [options]")}`);
|
|
54977
55617
|
out.push("");
|
|
54978
55618
|
out.push(divider("AUTH"));
|
|
54979
55619
|
out.push("");
|
|
54980
|
-
out.push(` ${
|
|
54981
|
-
out.push(` ${
|
|
54982
|
-
out.push(` ${
|
|
55620
|
+
out.push(` ${import_picocolors40.default.cyan("login")} ${import_picocolors40.default.dim(" open the web app and connect this device")}`);
|
|
55621
|
+
out.push(` ${import_picocolors40.default.cyan("logout")} ${import_picocolors40.default.dim(" clear the local session")}`);
|
|
55622
|
+
out.push(` ${import_picocolors40.default.cyan("whoami")} ${import_picocolors40.default.dim(" show the current user")}`);
|
|
54983
55623
|
out.push("");
|
|
54984
55624
|
out.push(divider("LINKED AGENT"));
|
|
54985
55625
|
out.push("");
|
|
54986
|
-
out.push(` ${
|
|
54987
|
-
out.push(` ${
|
|
54988
|
-
out.push(` ${
|
|
54989
|
-
out.push(` ${
|
|
54990
|
-
out.push(` ${
|
|
54991
|
-
out.push(` ${
|
|
54992
|
-
out.push(` ${
|
|
54993
|
-
out.push(` ${
|
|
54994
|
-
out.push(` ${
|
|
55626
|
+
out.push(` ${import_picocolors40.default.cyan("agent create")} ${import_picocolors40.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
55627
|
+
out.push(` ${import_picocolors40.default.cyan("agent pull")} ${import_picocolors40.default.dim("[<id>]")} ${import_picocolors40.default.dim("bring cloud changes into this folder (--force to override)")}`);
|
|
55628
|
+
out.push(` ${import_picocolors40.default.cyan("agent push")} ${import_picocolors40.default.dim("send local changes to the cloud")}`);
|
|
55629
|
+
out.push(` ${import_picocolors40.default.cyan("agent unpack")} ${import_picocolors40.default.dim("install the claimed agent into a harness layout")}`);
|
|
55630
|
+
out.push(` ${import_picocolors40.default.cyan("link")} ${import_picocolors40.default.dim("attach this folder to an existing agent")}`);
|
|
55631
|
+
out.push(` ${import_picocolors40.default.cyan("agent status")} ${import_picocolors40.default.dim("show what would pull and what would push")}`);
|
|
55632
|
+
out.push(` ${import_picocolors40.default.cyan("agent env")} ${import_picocolors40.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
|
|
55633
|
+
out.push(` ${import_picocolors40.default.cyan("run")} ${import_picocolors40.default.dim("<cmd> [args...]")} ${import_picocolors40.default.dim("run <cmd> with secrets.env loaded into env")}`);
|
|
55634
|
+
out.push(` ${import_picocolors40.default.cyan("status")} ${import_picocolors40.default.dim("show what this folder is linked to")}`);
|
|
55635
|
+
out.push(` ${import_picocolors40.default.cyan("unlink")} ${import_picocolors40.default.dim("disconnect this folder")}`);
|
|
54995
55636
|
out.push("");
|
|
54996
55637
|
out.push(divider("ORCHESTRATIONS"));
|
|
54997
55638
|
out.push("");
|
|
54998
|
-
out.push(` ${
|
|
54999
|
-
out.push(` ${
|
|
55000
|
-
out.push(` ${
|
|
55001
|
-
out.push(` ${
|
|
55639
|
+
out.push(` ${import_picocolors40.default.cyan("orchestration list")} ${import_picocolors40.default.dim("list orchestrations under a team")}`);
|
|
55640
|
+
out.push(` ${import_picocolors40.default.cyan("orchestration pull")} ${import_picocolors40.default.dim("<id>")} ${import_picocolors40.default.dim("recursively fetch an orchestration + every member agent")}`);
|
|
55641
|
+
out.push(` ${import_picocolors40.default.cyan("orchestration push")} ${import_picocolors40.default.dim("recursively push each member, then update the graph")}`);
|
|
55642
|
+
out.push(` ${import_picocolors40.default.cyan("orchestration status")} ${import_picocolors40.default.dim("show what would push and what would pull")}`);
|
|
55002
55643
|
out.push("");
|
|
55003
55644
|
out.push(divider("TEMPLATES"));
|
|
55004
55645
|
out.push("");
|
|
55005
|
-
out.push(` ${
|
|
55006
|
-
out.push(` ${
|
|
55007
|
-
out.push(` ${
|
|
55008
|
-
out.push(` ${
|
|
55009
|
-
out.push(` ${
|
|
55010
|
-
out.push(` ${
|
|
55011
|
-
out.push(` ${
|
|
55646
|
+
out.push(` ${import_picocolors40.default.cyan("template pack")} ${import_picocolors40.default.dim("bundle the current agent into a template")}`);
|
|
55647
|
+
out.push(` ${import_picocolors40.default.cyan("template publish")} ${import_picocolors40.default.dim("upload a template to the registry")}`);
|
|
55648
|
+
out.push(` ${import_picocolors40.default.cyan("template search")} ${import_picocolors40.default.dim("[query]")} ${import_picocolors40.default.dim("search the registry")}`);
|
|
55649
|
+
out.push(` ${import_picocolors40.default.cyan("template info")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("show registry details for a template")}`);
|
|
55650
|
+
out.push(` ${import_picocolors40.default.cyan("template onboard")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("install (or refresh) a template")}`);
|
|
55651
|
+
out.push(` ${import_picocolors40.default.cyan("template list")} ${import_picocolors40.default.dim("show installed templates")}`);
|
|
55652
|
+
out.push(` ${import_picocolors40.default.cyan("template remove")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("uninstall a template")}`);
|
|
55012
55653
|
out.push("");
|
|
55013
55654
|
out.push(divider("SKILLS"));
|
|
55014
55655
|
out.push("");
|
|
55015
|
-
out.push(` ${
|
|
55016
|
-
out.push(` ${
|
|
55017
|
-
out.push(` ${
|
|
55018
|
-
out.push(` ${
|
|
55019
|
-
out.push(` ${
|
|
55020
|
-
out.push(` ${
|
|
55021
|
-
out.push(` ${
|
|
55656
|
+
out.push(` ${import_picocolors40.default.cyan("skill add")} ${import_picocolors40.default.dim("<source>")} ${import_picocolors40.default.dim("install a skill (github / git / brainbase)")}`);
|
|
55657
|
+
out.push(` ${import_picocolors40.default.cyan("skill list")} ${import_picocolors40.default.dim("show locally installed skills + their source")}`);
|
|
55658
|
+
out.push(` ${import_picocolors40.default.cyan("skill update")} ${import_picocolors40.default.dim("<slug>")} ${import_picocolors40.default.dim("re-fetch a skill from its recorded source")}`);
|
|
55659
|
+
out.push(` ${import_picocolors40.default.cyan("skill remove")} ${import_picocolors40.default.dim("<slug>")} ${import_picocolors40.default.dim("uninstall a skill")}`);
|
|
55660
|
+
out.push(` ${import_picocolors40.default.cyan("skill search")} ${import_picocolors40.default.dim("[query]")} ${import_picocolors40.default.dim("search the brainbase skill registry")}`);
|
|
55661
|
+
out.push(` ${import_picocolors40.default.cyan("skill info")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("show registry details for a skill")}`);
|
|
55662
|
+
out.push(` ${import_picocolors40.default.cyan("skill publish")} ${import_picocolors40.default.dim("[dir]")} ${import_picocolors40.default.dim("publish a SKILL.md folder (defaults to .)")}`);
|
|
55022
55663
|
out.push("");
|
|
55023
55664
|
out.push(divider("CLI TOKENS"));
|
|
55024
55665
|
out.push("");
|
|
55025
|
-
out.push(` ${
|
|
55026
|
-
out.push(` ${
|
|
55027
|
-
out.push(` ${
|
|
55666
|
+
out.push(` ${import_picocolors40.default.cyan("token create")} ${import_picocolors40.default.dim("issue a long-lived CLI key for CI / scripts")}`);
|
|
55667
|
+
out.push(` ${import_picocolors40.default.cyan("token list")} ${import_picocolors40.default.dim("show your active tokens")}`);
|
|
55668
|
+
out.push(` ${import_picocolors40.default.cyan("token revoke")} ${import_picocolors40.default.dim("<id>")} ${import_picocolors40.default.dim("revoke a token")}`);
|
|
55028
55669
|
out.push("");
|
|
55029
55670
|
out.push(divider("FLAGS"));
|
|
55030
55671
|
out.push("");
|
|
55031
|
-
out.push(` ${
|
|
55032
|
-
out.push(` ${
|
|
55033
|
-
out.push(` ${
|
|
55034
|
-
out.push(` ${
|
|
55035
|
-
out.push(` ${
|
|
55036
|
-
out.push(` ${
|
|
55037
|
-
out.push(` ${
|
|
55038
|
-
out.push(` ${
|
|
55672
|
+
out.push(` ${import_picocolors40.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
|
|
55673
|
+
out.push(` ${import_picocolors40.default.dim("--scope <s>")} force scope: global | project`);
|
|
55674
|
+
out.push(` ${import_picocolors40.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
|
|
55675
|
+
out.push(` ${import_picocolors40.default.dim("--agent <id>")} for link: attach this folder to an existing agent non-interactively`);
|
|
55676
|
+
out.push(` ${import_picocolors40.default.dim("--no-tracking")} for link: skip routing LLM traffic through brainbase`);
|
|
55677
|
+
out.push(` ${import_picocolors40.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
|
|
55678
|
+
out.push(` ${import_picocolors40.default.dim("--all")} for template list: include installs from other folders`);
|
|
55679
|
+
out.push(` ${import_picocolors40.default.dim("--web <url>")} for login: web app URL (default https://new.usekafka.com)`);
|
|
55039
55680
|
out.push("");
|
|
55040
55681
|
out.push(divider("ENV"));
|
|
55041
55682
|
out.push("");
|
|
55042
|
-
out.push(` ${
|
|
55043
|
-
out.push(` ${
|
|
55044
|
-
out.push(` ${
|
|
55045
|
-
out.push(` ${
|
|
55046
|
-
out.push(` ${
|
|
55047
|
-
out.push(` ${
|
|
55683
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
|
|
55684
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
|
|
55685
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_API_URL")} override the API URL used by link / sync`);
|
|
55686
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL`);
|
|
55687
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT (overrides token.json)`);
|
|
55688
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
|
|
55048
55689
|
out.push("");
|
|
55049
55690
|
out.push(divider("HARNESSES"));
|
|
55050
55691
|
out.push("");
|
|
55051
|
-
out.push(` ${
|
|
55052
|
-
out.push(` ${
|
|
55053
|
-
out.push(` ${
|
|
55692
|
+
out.push(` ${import_picocolors40.default.dim("•")} ${import_picocolors40.default.bold("claude-code")} ${import_picocolors40.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
55693
|
+
out.push(` ${import_picocolors40.default.dim("•")} ${import_picocolors40.default.bold("codex")} ${import_picocolors40.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
|
|
55694
|
+
out.push(` ${import_picocolors40.default.dim("•")} ${import_picocolors40.default.bold("kafka")} ${import_picocolors40.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
55054
55695
|
out.push("");
|
|
55055
55696
|
console.log(out.join(`
|
|
55056
55697
|
`));
|
|
@@ -55094,13 +55735,13 @@ async function requireAuth(cmd) {
|
|
|
55094
55735
|
if (status.ok)
|
|
55095
55736
|
return;
|
|
55096
55737
|
console.error("");
|
|
55097
|
-
console.error(` ${brandTint("◆")} ${
|
|
55738
|
+
console.error(` ${brandTint("◆")} ${import_picocolors40.default.bold("brainbase")}`);
|
|
55098
55739
|
console.error("");
|
|
55099
|
-
console.error(` ${
|
|
55740
|
+
console.error(` ${import_picocolors40.default.red("✗")} You need to sign in to use ${import_picocolors40.default.bold("brainbase " + cmd)}.`);
|
|
55100
55741
|
if (status.reason)
|
|
55101
|
-
console.error(` ${
|
|
55742
|
+
console.error(` ${import_picocolors40.default.dim(status.reason)}`);
|
|
55102
55743
|
console.error("");
|
|
55103
|
-
console.error(` Run ${
|
|
55744
|
+
console.error(` Run ${import_picocolors40.default.cyan("brainbase login")} to connect this device.`);
|
|
55104
55745
|
console.error("");
|
|
55105
55746
|
process13.exit(1);
|
|
55106
55747
|
}
|
|
@@ -55137,6 +55778,7 @@ async function main() {
|
|
|
55137
55778
|
const agentFlag = getFlag(argv, "--agent");
|
|
55138
55779
|
const shellFlag = getFlag(argv, "--shell");
|
|
55139
55780
|
const noTracking = hasFlag2(argv, "--no-tracking");
|
|
55781
|
+
const forceFlag = hasFlag2(argv, "--force");
|
|
55140
55782
|
const graphOnlyFlag = hasFlag2(argv, "--graph-only");
|
|
55141
55783
|
const nameFlag = getFlag(argv, "--name");
|
|
55142
55784
|
const skillVersionFlag = getFlag(argv, "--skill-version");
|
|
@@ -55221,7 +55863,8 @@ async function main() {
|
|
|
55221
55863
|
tagline: taglineFlag,
|
|
55222
55864
|
orgId: orgIdFlag,
|
|
55223
55865
|
teamId: teamIdFlag,
|
|
55224
|
-
noTracking
|
|
55866
|
+
noTracking,
|
|
55867
|
+
force: forceFlag
|
|
55225
55868
|
});
|
|
55226
55869
|
break;
|
|
55227
55870
|
}
|
|
@@ -55252,7 +55895,7 @@ async function main() {
|
|
|
55252
55895
|
process13.exit(1);
|
|
55253
55896
|
}
|
|
55254
55897
|
} catch (err) {
|
|
55255
|
-
console.error(
|
|
55898
|
+
console.error(import_picocolors40.default.red(`
|
|
55256
55899
|
${err.message}`));
|
|
55257
55900
|
if (process13.env.BRAINBASE_DEBUG)
|
|
55258
55901
|
console.error(err.stack);
|