@brainbase-labs/cli 0.4.1 → 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 +1426 -773
- 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
|
|
|
@@ -33782,7 +33782,7 @@ var BrainbaseSourceSchema = exports_external.object({
|
|
|
33782
33782
|
type: exports_external.literal("brainbase"),
|
|
33783
33783
|
creator: exports_external.string().regex(/^[a-z0-9_-]+$/i),
|
|
33784
33784
|
slug: exports_external.string().regex(/^[a-z0-9_-]+$/i),
|
|
33785
|
-
version: exports_external.string().regex(/^\d+\.\d+\.\d+$/)
|
|
33785
|
+
version: exports_external.string().regex(/^\d+\.\d+\.\d+$/).optional()
|
|
33786
33786
|
});
|
|
33787
33787
|
var InlineSourceSchema = exports_external.object({ type: exports_external.literal("inline") });
|
|
33788
33788
|
var LocalSourceSchema = exports_external.object({ type: exports_external.literal("local") });
|
|
@@ -48541,7 +48541,7 @@ function parseSkillSource(input) {
|
|
|
48541
48541
|
type: "brainbase",
|
|
48542
48542
|
creator: bb[1],
|
|
48543
48543
|
slug: bb[2],
|
|
48544
|
-
version: bb[3]
|
|
48544
|
+
version: bb[3]
|
|
48545
48545
|
};
|
|
48546
48546
|
}
|
|
48547
48547
|
if (s3.startsWith("file://") || s3.startsWith("./") || s3.startsWith("../") || s3.startsWith("/") || s3.startsWith("~")) {
|
|
@@ -48616,7 +48616,7 @@ function describeSource(source) {
|
|
|
48616
48616
|
case "git":
|
|
48617
48617
|
return `git:${source.url}${source.ref ? "@" + source.ref : ""}${source.subpath ? " (" + source.subpath + ")" : ""}`;
|
|
48618
48618
|
case "brainbase":
|
|
48619
|
-
return `brainbase://${source.creator}/${source.slug}
|
|
48619
|
+
return `brainbase://${source.creator}/${source.slug}${source.version ? "@" + source.version : " (latest)"}`;
|
|
48620
48620
|
}
|
|
48621
48621
|
}
|
|
48622
48622
|
|
|
@@ -49722,14 +49722,24 @@ var brainbaseResolver = {
|
|
|
49722
49722
|
if (source.type !== "brainbase") {
|
|
49723
49723
|
throw new Error("expected brainbase source");
|
|
49724
49724
|
}
|
|
49725
|
-
|
|
49725
|
+
let version = source.version;
|
|
49726
|
+
if (!version) {
|
|
49727
|
+
const pkg = await skillsApi.getPackage(source.creator, source.slug);
|
|
49728
|
+
const latest = pkg.latest_version;
|
|
49729
|
+
if (!latest) {
|
|
49730
|
+
throw new Error(`${source.creator}/${source.slug} has no published versions`);
|
|
49731
|
+
}
|
|
49732
|
+
version = latest.version;
|
|
49733
|
+
source.version = version;
|
|
49734
|
+
}
|
|
49735
|
+
const remoteVersion = await skillsApi.getVersion(source.creator, source.slug, version);
|
|
49726
49736
|
if (remoteVersion.yanked) {
|
|
49727
|
-
throw new Error(`${source.creator}/${source.slug}@${
|
|
49737
|
+
throw new Error(`${source.creator}/${source.slug}@${version} has been yanked${remoteVersion.yanked_reason ? ": " + remoteVersion.yanked_reason : ""}`);
|
|
49728
49738
|
}
|
|
49729
49739
|
const tmp = fs33.mkdtempSync(path36.join(os8.tmpdir(), "bb-skill-"));
|
|
49730
49740
|
const tarPath = path36.join(tmp, "skill.tgz");
|
|
49731
49741
|
try {
|
|
49732
|
-
await skillsApi.downloadTarball(source.creator, source.slug,
|
|
49742
|
+
await skillsApi.downloadTarball(source.creator, source.slug, version, tarPath);
|
|
49733
49743
|
await verifyTarball(tarPath, remoteVersion.bundle_sha256);
|
|
49734
49744
|
ensureDir(destDir);
|
|
49735
49745
|
await extract({ tarFile: tarPath, outDir: destDir });
|
|
@@ -50749,11 +50759,164 @@ async function runWhoami() {
|
|
|
50749
50759
|
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
50750
50760
|
|
|
50751
50761
|
// src/core/link.ts
|
|
50762
|
+
import path43 from "node:path";
|
|
50763
|
+
import fs40 from "node:fs";
|
|
50764
|
+
|
|
50765
|
+
// src/core/agent-manifest.ts
|
|
50752
50766
|
import path42 from "node:path";
|
|
50753
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
|
|
50754
50916
|
var LINK_DIR = ".brainbase";
|
|
50755
|
-
var
|
|
50917
|
+
var STATE_FILE = "state.json";
|
|
50756
50918
|
var SYNC_STATE_FILE = "sync-state.json";
|
|
50919
|
+
var LEGACY_LINK_FILE = "link.json";
|
|
50757
50920
|
var TrackingSchema = exports_external.object({
|
|
50758
50921
|
harness: exports_external.string(),
|
|
50759
50922
|
key_id: exports_external.string(),
|
|
@@ -50776,6 +50939,16 @@ var LinkSchema = exports_external.object({
|
|
|
50776
50939
|
harness: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
|
|
50777
50940
|
tracking: TrackingSchema.nullish().transform((v3) => v3 ?? undefined)
|
|
50778
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
|
+
});
|
|
50779
50952
|
var SyncedComponentSchema = exports_external.object({
|
|
50780
50953
|
type: exports_external.string(),
|
|
50781
50954
|
slug: exports_external.string(),
|
|
@@ -50785,7 +50958,8 @@ var SyncedComponentSchema = exports_external.object({
|
|
|
50785
50958
|
});
|
|
50786
50959
|
var AgentMetaSnapshotSchema = exports_external.object({
|
|
50787
50960
|
name: exports_external.string(),
|
|
50788
|
-
tagline: exports_external.string().optional()
|
|
50961
|
+
tagline: exports_external.string().optional(),
|
|
50962
|
+
entrypoint: exports_external.string().optional()
|
|
50789
50963
|
});
|
|
50790
50964
|
var SyncStateSchema = exports_external.object({
|
|
50791
50965
|
schemaVersion: exports_external.literal(1),
|
|
@@ -50795,39 +50969,157 @@ var SyncStateSchema = exports_external.object({
|
|
|
50795
50969
|
components: exports_external.array(SyncedComponentSchema),
|
|
50796
50970
|
agentMeta: AgentMetaSnapshotSchema.optional()
|
|
50797
50971
|
});
|
|
50798
|
-
function
|
|
50799
|
-
return
|
|
50972
|
+
function statePath(cwd2) {
|
|
50973
|
+
return path43.join(cwd2, LINK_DIR, STATE_FILE);
|
|
50800
50974
|
}
|
|
50801
50975
|
function syncStatePath(cwd2) {
|
|
50802
|
-
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);
|
|
50803
51026
|
}
|
|
50804
51027
|
function readLink(cwd2) {
|
|
50805
|
-
|
|
50806
|
-
if (!exists(p2))
|
|
50807
|
-
return null;
|
|
51028
|
+
let manifest = null;
|
|
50808
51029
|
try {
|
|
50809
|
-
|
|
51030
|
+
manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
50810
51031
|
} catch {
|
|
50811
|
-
|
|
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
|
+
}
|
|
50812
51058
|
}
|
|
51059
|
+
return null;
|
|
50813
51060
|
}
|
|
50814
51061
|
function writeLink(cwd2, link2) {
|
|
50815
|
-
|
|
50816
|
-
|
|
50817
|
-
|
|
50818
|
-
|
|
50819
|
-
|
|
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 {}
|
|
50820
51103
|
}
|
|
50821
|
-
writeJson(linkPath(cwd2), clean);
|
|
50822
|
-
ensureGitignore(cwd2);
|
|
50823
51104
|
}
|
|
50824
51105
|
function clearLink(cwd2) {
|
|
50825
|
-
|
|
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);
|
|
50826
51115
|
if (exists(p2))
|
|
50827
|
-
|
|
51116
|
+
fs40.rmSync(p2);
|
|
50828
51117
|
const sp = syncStatePath(cwd2);
|
|
50829
51118
|
if (exists(sp))
|
|
50830
|
-
|
|
51119
|
+
fs40.rmSync(sp);
|
|
51120
|
+
const legacy = legacyLinkPath(cwd2);
|
|
51121
|
+
if (exists(legacy))
|
|
51122
|
+
fs40.rmSync(legacy);
|
|
50831
51123
|
}
|
|
50832
51124
|
function readSyncState(cwd2) {
|
|
50833
51125
|
const p2 = syncStatePath(cwd2);
|
|
@@ -50840,22 +51132,22 @@ function readSyncState(cwd2) {
|
|
|
50840
51132
|
}
|
|
50841
51133
|
}
|
|
50842
51134
|
function writeSyncState(cwd2, state) {
|
|
50843
|
-
ensureDir(
|
|
51135
|
+
ensureDir(path43.join(cwd2, LINK_DIR));
|
|
50844
51136
|
writeJson(syncStatePath(cwd2), state);
|
|
50845
51137
|
ensureGitignore(cwd2);
|
|
50846
51138
|
}
|
|
50847
51139
|
function ensureGitignore(cwd2) {
|
|
50848
|
-
const ignorePath =
|
|
50849
|
-
const desired =
|
|
50850
|
-
|
|
51140
|
+
const ignorePath = path43.join(cwd2, LINK_DIR, ".gitignore");
|
|
51141
|
+
const desired = ["*", `!.gitignore`, ""].join(`
|
|
51142
|
+
`);
|
|
50851
51143
|
try {
|
|
50852
51144
|
if (!exists(ignorePath)) {
|
|
50853
|
-
|
|
51145
|
+
fs40.writeFileSync(ignorePath, desired);
|
|
50854
51146
|
return;
|
|
50855
51147
|
}
|
|
50856
|
-
const current =
|
|
50857
|
-
if (!current.split(/\r?\n/).some((l2) => l2.trim() ===
|
|
50858
|
-
|
|
51148
|
+
const current = fs40.readFileSync(ignorePath, "utf8");
|
|
51149
|
+
if (!current.split(/\r?\n/).some((l2) => l2.trim() === "*")) {
|
|
51150
|
+
fs40.writeFileSync(ignorePath, current.endsWith(`
|
|
50859
51151
|
`) ? current + desired : current + `
|
|
50860
51152
|
` + desired);
|
|
50861
51153
|
}
|
|
@@ -50863,15 +51155,15 @@ function ensureGitignore(cwd2) {
|
|
|
50863
51155
|
}
|
|
50864
51156
|
|
|
50865
51157
|
// src/core/route-adapters.ts
|
|
50866
|
-
import
|
|
51158
|
+
import path44 from "node:path";
|
|
50867
51159
|
import os10 from "node:os";
|
|
50868
|
-
import
|
|
51160
|
+
import fs41 from "node:fs";
|
|
50869
51161
|
var CLAUDE_ENV_KEYS = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN"];
|
|
50870
51162
|
function claudeSettingsPath(cwd2) {
|
|
50871
|
-
return
|
|
51163
|
+
return path44.join(cwd2, ".claude", "settings.json");
|
|
50872
51164
|
}
|
|
50873
51165
|
function claudeUserConfigPath() {
|
|
50874
|
-
return
|
|
51166
|
+
return path44.join(os10.homedir(), ".claude.json");
|
|
50875
51167
|
}
|
|
50876
51168
|
function ensureClaudeOnboarded() {
|
|
50877
51169
|
const file = claudeUserConfigPath();
|
|
@@ -50895,7 +51187,7 @@ var claudeRouteAdapter = {
|
|
|
50895
51187
|
settings.env = { ...settings.env ?? {} };
|
|
50896
51188
|
settings.env.ANTHROPIC_BASE_URL = target.apiBase;
|
|
50897
51189
|
settings.env.ANTHROPIC_AUTH_TOKEN = target.apiKey;
|
|
50898
|
-
ensureDir(
|
|
51190
|
+
ensureDir(path44.dirname(file));
|
|
50899
51191
|
writeJson(file, settings);
|
|
50900
51192
|
const notes = [];
|
|
50901
51193
|
if (ensureClaudeOnboarded()) {
|
|
@@ -50922,11 +51214,11 @@ var claudeRouteAdapter = {
|
|
|
50922
51214
|
delete settings.env;
|
|
50923
51215
|
}
|
|
50924
51216
|
if (snap && !snap.fileExisted && Object.keys(settings).length === 0) {
|
|
50925
|
-
|
|
50926
|
-
const dir =
|
|
51217
|
+
fs41.rmSync(file);
|
|
51218
|
+
const dir = path44.dirname(file);
|
|
50927
51219
|
try {
|
|
50928
|
-
if (
|
|
50929
|
-
|
|
51220
|
+
if (fs41.readdirSync(dir).length === 0)
|
|
51221
|
+
fs41.rmdirSync(dir);
|
|
50930
51222
|
} catch {}
|
|
50931
51223
|
return;
|
|
50932
51224
|
}
|
|
@@ -50936,20 +51228,20 @@ var claudeRouteAdapter = {
|
|
|
50936
51228
|
var CODEX_PROVIDER_KEY = "brainbase";
|
|
50937
51229
|
var CODEX_AUTH_HEADER = "Authorization";
|
|
50938
51230
|
function codexConfigPath(cwd2) {
|
|
50939
|
-
return
|
|
51231
|
+
return path44.join(cwd2, ".codex", "config.toml");
|
|
50940
51232
|
}
|
|
50941
51233
|
function readCodexConfig2(file) {
|
|
50942
51234
|
if (!exists(file))
|
|
50943
51235
|
return {};
|
|
50944
51236
|
try {
|
|
50945
|
-
return parse(
|
|
51237
|
+
return parse(fs41.readFileSync(file, "utf8"));
|
|
50946
51238
|
} catch {
|
|
50947
51239
|
return {};
|
|
50948
51240
|
}
|
|
50949
51241
|
}
|
|
50950
51242
|
function writeCodexConfig2(file, value) {
|
|
50951
|
-
ensureDir(
|
|
50952
|
-
|
|
51243
|
+
ensureDir(path44.dirname(file));
|
|
51244
|
+
fs41.writeFileSync(file, stringify(value) + `
|
|
50953
51245
|
`);
|
|
50954
51246
|
}
|
|
50955
51247
|
function ensureV1(base2) {
|
|
@@ -51005,11 +51297,11 @@ var codexRouteAdapter = {
|
|
|
51005
51297
|
}
|
|
51006
51298
|
}
|
|
51007
51299
|
if (snap && !snap.fileExisted && Object.keys(cfg).length === 0) {
|
|
51008
|
-
|
|
51009
|
-
const dir =
|
|
51300
|
+
fs41.rmSync(file);
|
|
51301
|
+
const dir = path44.dirname(file);
|
|
51010
51302
|
try {
|
|
51011
|
-
if (
|
|
51012
|
-
|
|
51303
|
+
if (fs41.readdirSync(dir).length === 0)
|
|
51304
|
+
fs41.rmdirSync(dir);
|
|
51013
51305
|
} catch {}
|
|
51014
51306
|
return;
|
|
51015
51307
|
}
|
|
@@ -51299,8 +51591,8 @@ async function runUnlink(cwd2, args) {
|
|
|
51299
51591
|
}
|
|
51300
51592
|
|
|
51301
51593
|
// src/cli/sync.ts
|
|
51302
|
-
import
|
|
51303
|
-
import
|
|
51594
|
+
import path45 from "node:path";
|
|
51595
|
+
import fs42 from "node:fs";
|
|
51304
51596
|
import os11 from "node:os";
|
|
51305
51597
|
import crypto3 from "node:crypto";
|
|
51306
51598
|
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
@@ -51494,7 +51786,7 @@ async function runSync(cwd2, args) {
|
|
|
51494
51786
|
type: c2.type,
|
|
51495
51787
|
slug: c2.slug,
|
|
51496
51788
|
scope,
|
|
51497
|
-
rootDir:
|
|
51789
|
+
rootDir: path45.join(stageRoot, c2.type, c2.slug),
|
|
51498
51790
|
description: c2.description,
|
|
51499
51791
|
meta: c2.meta,
|
|
51500
51792
|
payload: c2.meta?.mcp,
|
|
@@ -51543,11 +51835,11 @@ async function runSync(cwd2, args) {
|
|
|
51543
51835
|
if (!exists(filePath))
|
|
51544
51836
|
continue;
|
|
51545
51837
|
try {
|
|
51546
|
-
const stat =
|
|
51838
|
+
const stat = fs42.statSync(filePath);
|
|
51547
51839
|
if (stat.isDirectory())
|
|
51548
|
-
|
|
51840
|
+
fs42.rmSync(filePath, { recursive: true, force: true });
|
|
51549
51841
|
else
|
|
51550
|
-
|
|
51842
|
+
fs42.rmSync(filePath);
|
|
51551
51843
|
} catch (err) {
|
|
51552
51844
|
f2.warn(`Failed to remove ${filePath}: ${err.message}`);
|
|
51553
51845
|
}
|
|
@@ -51585,7 +51877,7 @@ async function runSync(cwd2, args) {
|
|
|
51585
51877
|
$e(`Synced ${link2.name} to revision ${manifest.revision}.`);
|
|
51586
51878
|
} finally {
|
|
51587
51879
|
try {
|
|
51588
|
-
|
|
51880
|
+
fs42.rmSync(stageRoot, { recursive: true, force: true });
|
|
51589
51881
|
} catch {}
|
|
51590
51882
|
}
|
|
51591
51883
|
}
|
|
@@ -51633,14 +51925,14 @@ function computeLocalHash(paths) {
|
|
|
51633
51925
|
if (!exists(filePath))
|
|
51634
51926
|
return null;
|
|
51635
51927
|
try {
|
|
51636
|
-
const stat =
|
|
51928
|
+
const stat = fs42.statSync(filePath);
|
|
51637
51929
|
if (stat.isFile()) {
|
|
51638
51930
|
h2.update("F " + filePath + " ");
|
|
51639
|
-
h2.update(
|
|
51931
|
+
h2.update(fs42.readFileSync(filePath));
|
|
51640
51932
|
h2.update(`
|
|
51641
51933
|
`);
|
|
51642
51934
|
} else if (stat.isDirectory()) {
|
|
51643
|
-
for (const name of
|
|
51935
|
+
for (const name of fs42.readdirSync(filePath).sort()) {
|
|
51644
51936
|
h2.update("E " + name + `
|
|
51645
51937
|
`);
|
|
51646
51938
|
}
|
|
@@ -51652,14 +51944,14 @@ function computeLocalHash(paths) {
|
|
|
51652
51944
|
return h2.digest("hex");
|
|
51653
51945
|
}
|
|
51654
51946
|
function stageManifest(components) {
|
|
51655
|
-
const root =
|
|
51947
|
+
const root = fs42.mkdtempSync(path45.join(os11.tmpdir(), "brainbase-sync-"));
|
|
51656
51948
|
for (const c2 of components) {
|
|
51657
|
-
const compDir =
|
|
51949
|
+
const compDir = path45.join(root, c2.type, c2.slug);
|
|
51658
51950
|
ensureDir(compDir);
|
|
51659
51951
|
for (const f4 of c2.files) {
|
|
51660
|
-
const target =
|
|
51661
|
-
ensureDir(
|
|
51662
|
-
|
|
51952
|
+
const target = path45.join(compDir, f4.path);
|
|
51953
|
+
ensureDir(path45.dirname(target));
|
|
51954
|
+
fs42.writeFileSync(target, f4.content);
|
|
51663
51955
|
}
|
|
51664
51956
|
}
|
|
51665
51957
|
return root;
|
|
@@ -51673,142 +51965,46 @@ function runHarnessInstall(harnessId, components, opts, agentName) {
|
|
|
51673
51965
|
}
|
|
51674
51966
|
|
|
51675
51967
|
// src/cli/agent.ts
|
|
51676
|
-
var
|
|
51968
|
+
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
51677
51969
|
|
|
51678
51970
|
// src/cli/agent-pull.ts
|
|
51971
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
51679
51972
|
import path48 from "node:path";
|
|
51680
51973
|
import fs45 from "node:fs";
|
|
51681
51974
|
import os12 from "node:os";
|
|
51682
51975
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
51683
51976
|
|
|
51684
|
-
// src/core/agent-
|
|
51685
|
-
import
|
|
51686
|
-
import
|
|
51687
|
-
|
|
51688
|
-
|
|
51689
|
-
|
|
51690
|
-
|
|
51691
|
-
function
|
|
51692
|
-
|
|
51693
|
-
|
|
51977
|
+
// src/core/agent-diff.ts
|
|
51978
|
+
import path46 from "node:path";
|
|
51979
|
+
import fs43 from "node:fs";
|
|
51980
|
+
import crypto4 from "node:crypto";
|
|
51981
|
+
function compKey(type, slug) {
|
|
51982
|
+
return `${type}/${slug}`;
|
|
51983
|
+
}
|
|
51984
|
+
function hashString(s3) {
|
|
51985
|
+
return crypto4.createHash("sha256").update(s3).digest("hex");
|
|
51986
|
+
}
|
|
51987
|
+
function canonicalJson(value) {
|
|
51988
|
+
if (value === null)
|
|
51989
|
+
return "null";
|
|
51990
|
+
if (typeof value === "boolean")
|
|
51991
|
+
return value ? "true" : "false";
|
|
51992
|
+
if (typeof value === "number") {
|
|
51993
|
+
if (!Number.isFinite(value))
|
|
51994
|
+
throw new Error("Non-finite numbers are not JSON");
|
|
51995
|
+
return String(value);
|
|
51694
51996
|
}
|
|
51695
|
-
|
|
51696
|
-
|
|
51697
|
-
|
|
51698
|
-
|
|
51699
|
-
...m3[1] ? { creator: m3[1] } : {},
|
|
51700
|
-
slug: m3[2],
|
|
51701
|
-
version: m3[3]
|
|
51702
|
-
};
|
|
51997
|
+
if (typeof value === "string")
|
|
51998
|
+
return JSON.stringify(value);
|
|
51999
|
+
if (Array.isArray(value)) {
|
|
52000
|
+
return "[" + value.map(canonicalJson).join(",") + "]";
|
|
51703
52001
|
}
|
|
51704
|
-
if (
|
|
51705
|
-
|
|
52002
|
+
if (typeof value === "object") {
|
|
52003
|
+
const obj = value;
|
|
52004
|
+
const keys = Object.keys(obj).sort();
|
|
52005
|
+
return "{" + keys.map((k3) => `${JSON.stringify(k3)}:${canonicalJson(obj[k3])}`).join(",") + "}";
|
|
51706
52006
|
}
|
|
51707
|
-
throw new Error(`
|
|
51708
|
-
}
|
|
51709
|
-
var AgentMetaSchema = exports_external.object({
|
|
51710
|
-
name: exports_external.string().min(1),
|
|
51711
|
-
tagline: exports_external.string().optional()
|
|
51712
|
-
});
|
|
51713
|
-
var InstructionsSchema = exports_external.object({
|
|
51714
|
-
file: exports_external.string().min(1)
|
|
51715
|
-
});
|
|
51716
|
-
var SkillEntrySchema = exports_external.object({
|
|
51717
|
-
source: exports_external.string().min(1)
|
|
51718
|
-
});
|
|
51719
|
-
var McpEntrySchema = exports_external.object({
|
|
51720
|
-
name: exports_external.string().min(1),
|
|
51721
|
-
url: exports_external.string().optional(),
|
|
51722
|
-
command: exports_external.string().optional(),
|
|
51723
|
-
args: exports_external.array(exports_external.string()).optional(),
|
|
51724
|
-
env: exports_external.record(exports_external.string()).optional(),
|
|
51725
|
-
headers: exports_external.record(exports_external.string()).optional(),
|
|
51726
|
-
is_enabled: exports_external.boolean().optional()
|
|
51727
|
-
});
|
|
51728
|
-
var AgentManifestSchema = exports_external.object({
|
|
51729
|
-
schema: exports_external.literal(1),
|
|
51730
|
-
agent: AgentMetaSchema,
|
|
51731
|
-
instructions: InstructionsSchema.optional(),
|
|
51732
|
-
skills: exports_external.array(SkillEntrySchema).default([]),
|
|
51733
|
-
mcp: exports_external.array(McpEntrySchema).default([]),
|
|
51734
|
-
commands: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
51735
|
-
hooks: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
51736
|
-
files: exports_external.array(exports_external.record(exports_external.unknown())).optional()
|
|
51737
|
-
});
|
|
51738
|
-
function manifestPath(cwd2) {
|
|
51739
|
-
return path45.join(cwd2, AGENT_MANIFEST_FILE);
|
|
51740
|
-
}
|
|
51741
|
-
function hasManifest(cwd2) {
|
|
51742
|
-
return fs42.existsSync(manifestPath(cwd2));
|
|
51743
|
-
}
|
|
51744
|
-
function readManifest(cwd2) {
|
|
51745
|
-
const p2 = manifestPath(cwd2);
|
|
51746
|
-
if (!fs42.existsSync(p2))
|
|
51747
|
-
return null;
|
|
51748
|
-
const raw = fs42.readFileSync(p2, "utf8");
|
|
51749
|
-
let parsed;
|
|
51750
|
-
try {
|
|
51751
|
-
parsed = import_yaml2.default.parse(raw);
|
|
51752
|
-
} catch (err) {
|
|
51753
|
-
throw new Error(`${AGENT_MANIFEST_FILE} is not valid YAML: ${err.message}`);
|
|
51754
|
-
}
|
|
51755
|
-
const result = AgentManifestSchema.safeParse(parsed);
|
|
51756
|
-
if (!result.success) {
|
|
51757
|
-
throw new Error(`${AGENT_MANIFEST_FILE} is invalid: ${result.error.issues.map((i) => `${i.path.join(".") || "(root)"} — ${i.message}`).join("; ")}`);
|
|
51758
|
-
}
|
|
51759
|
-
return result.data;
|
|
51760
|
-
}
|
|
51761
|
-
function writeManifest(cwd2, manifest) {
|
|
51762
|
-
const doc = new import_yaml2.default.Document;
|
|
51763
|
-
doc.contents = manifest;
|
|
51764
|
-
doc.commentBefore = ` brainbase.yaml — declarative agent manifest.
|
|
51765
|
-
` + " Committed to source control. Edit by hand, then `brainbase agent push`.";
|
|
51766
|
-
const out = String(doc);
|
|
51767
|
-
fs42.writeFileSync(manifestPath(cwd2), out, "utf8");
|
|
51768
|
-
}
|
|
51769
|
-
function resolveInstructionsPath(cwd2, manifest) {
|
|
51770
|
-
if (!manifest.instructions)
|
|
51771
|
-
return null;
|
|
51772
|
-
return path45.resolve(cwd2, manifest.instructions.file);
|
|
51773
|
-
}
|
|
51774
|
-
function readInstructions(cwd2, manifest) {
|
|
51775
|
-
const p2 = resolveInstructionsPath(cwd2, manifest);
|
|
51776
|
-
if (!p2 || !fs42.existsSync(p2))
|
|
51777
|
-
return null;
|
|
51778
|
-
return fs42.readFileSync(p2, "utf8");
|
|
51779
|
-
}
|
|
51780
|
-
|
|
51781
|
-
// src/core/agent-diff.ts
|
|
51782
|
-
import path46 from "node:path";
|
|
51783
|
-
import fs43 from "node:fs";
|
|
51784
|
-
import crypto4 from "node:crypto";
|
|
51785
|
-
function compKey(type, slug) {
|
|
51786
|
-
return `${type}/${slug}`;
|
|
51787
|
-
}
|
|
51788
|
-
function hashString(s3) {
|
|
51789
|
-
return crypto4.createHash("sha256").update(s3).digest("hex");
|
|
51790
|
-
}
|
|
51791
|
-
function canonicalJson(value) {
|
|
51792
|
-
if (value === null)
|
|
51793
|
-
return "null";
|
|
51794
|
-
if (typeof value === "boolean")
|
|
51795
|
-
return value ? "true" : "false";
|
|
51796
|
-
if (typeof value === "number") {
|
|
51797
|
-
if (!Number.isFinite(value))
|
|
51798
|
-
throw new Error("Non-finite numbers are not JSON");
|
|
51799
|
-
return String(value);
|
|
51800
|
-
}
|
|
51801
|
-
if (typeof value === "string")
|
|
51802
|
-
return JSON.stringify(value);
|
|
51803
|
-
if (Array.isArray(value)) {
|
|
51804
|
-
return "[" + value.map(canonicalJson).join(",") + "]";
|
|
51805
|
-
}
|
|
51806
|
-
if (typeof value === "object") {
|
|
51807
|
-
const obj = value;
|
|
51808
|
-
const keys = Object.keys(obj).sort();
|
|
51809
|
-
return "{" + keys.map((k3) => `${JSON.stringify(k3)}:${canonicalJson(obj[k3])}`).join(",") + "}";
|
|
51810
|
-
}
|
|
51811
|
-
throw new Error(`Unsupported value in canonicalJson: ${typeof value}`);
|
|
52007
|
+
throw new Error(`Unsupported value in canonicalJson: ${typeof value}`);
|
|
51812
52008
|
}
|
|
51813
52009
|
function hashMcpEntry(entry) {
|
|
51814
52010
|
const payload = {};
|
|
@@ -52113,26 +52309,27 @@ function diffSecrets(local, cloud) {
|
|
|
52113
52309
|
// src/cli/agent-pull.ts
|
|
52114
52310
|
async function runAgentPull(cwd2, args) {
|
|
52115
52311
|
banner("agent pull — bring cloud changes into this folder");
|
|
52116
|
-
const
|
|
52117
|
-
if (!
|
|
52118
|
-
f2.warn("This folder is not linked to any agent.");
|
|
52119
|
-
f2.info(`Run ${import_picocolors25.default.cyan("brainbase link")} first.`);
|
|
52312
|
+
const resolution = resolveTargetAgentId(cwd2, args);
|
|
52313
|
+
if (!resolution)
|
|
52120
52314
|
return;
|
|
52121
|
-
}
|
|
52315
|
+
const { agentId, override } = resolution;
|
|
52122
52316
|
const sp = de();
|
|
52123
|
-
sp.start(
|
|
52317
|
+
sp.start("Fetching agent…");
|
|
52318
|
+
let cloudAgent;
|
|
52124
52319
|
let cloud;
|
|
52125
52320
|
try {
|
|
52126
|
-
|
|
52321
|
+
cloudAgent = await api.getAgent(agentId);
|
|
52322
|
+
cloud = await api.getAgentManifest(agentId);
|
|
52127
52323
|
sp.stop(`Cloud revision ${cloud.revision}.`);
|
|
52128
52324
|
} catch (err) {
|
|
52129
52325
|
sp.stop("Failed.");
|
|
52130
52326
|
handleApiError2(err);
|
|
52131
52327
|
return;
|
|
52132
52328
|
}
|
|
52133
|
-
const
|
|
52134
|
-
const
|
|
52135
|
-
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) : [];
|
|
52136
52333
|
const rows = threeWayDiff({
|
|
52137
52334
|
local: localComponents,
|
|
52138
52335
|
lock: lock?.components ?? [],
|
|
@@ -52157,7 +52354,11 @@ async function runAgentPull(cwd2, args) {
|
|
|
52157
52354
|
break;
|
|
52158
52355
|
case "modified-both":
|
|
52159
52356
|
case "modified-local":
|
|
52160
|
-
|
|
52357
|
+
if (override) {
|
|
52358
|
+
toInstallKeys.add(r2.key);
|
|
52359
|
+
} else {
|
|
52360
|
+
conflicts.push(r2);
|
|
52361
|
+
}
|
|
52161
52362
|
break;
|
|
52162
52363
|
}
|
|
52163
52364
|
}
|
|
@@ -52181,11 +52382,12 @@ async function runAgentPull(cwd2, args) {
|
|
|
52181
52382
|
const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
|
|
52182
52383
|
const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
|
|
52183
52384
|
const needMemoryMcpInstall = !cloudHasMemoryMcp;
|
|
52184
|
-
if (toInstallKeys.size === 0 && toRemoveKeys.size === 0 && !needOrchestrationMcpInstall && !needMemoryMcpInstall) {
|
|
52385
|
+
if (toInstallKeys.size === 0 && toRemoveKeys.size === 0 && !needOrchestrationMcpInstall && !needMemoryMcpInstall && !override) {
|
|
52185
52386
|
f2.info(`You're up to date.`);
|
|
52186
|
-
|
|
52187
|
-
|
|
52188
|
-
|
|
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));
|
|
52189
52391
|
f2.info(`Wrote ${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)}.`);
|
|
52190
52392
|
}
|
|
52191
52393
|
return;
|
|
@@ -52215,20 +52417,20 @@ async function runAgentPull(cwd2, args) {
|
|
|
52215
52417
|
});
|
|
52216
52418
|
}
|
|
52217
52419
|
await showResultCard({
|
|
52218
|
-
title: "PULL",
|
|
52219
|
-
tone: "info",
|
|
52220
|
-
subtitle: `updates for ${
|
|
52420
|
+
title: override ? "PULL (FORCE)" : "PULL",
|
|
52421
|
+
tone: override ? "warn" : "info",
|
|
52422
|
+
subtitle: `updates for ${cloudAgent.name}`,
|
|
52221
52423
|
rows: resultRows
|
|
52222
52424
|
});
|
|
52223
52425
|
if (!args.yes) {
|
|
52224
|
-
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 });
|
|
52225
52428
|
if (!ensureNotCancelled(ok)) {
|
|
52226
52429
|
$e("Aborted.");
|
|
52227
52430
|
return;
|
|
52228
52431
|
}
|
|
52229
52432
|
}
|
|
52230
|
-
const
|
|
52231
|
-
const adapter = getAdapter(adapterId);
|
|
52433
|
+
const adapter = getAdapter(harness);
|
|
52232
52434
|
const scope = args.scope ?? "project";
|
|
52233
52435
|
const installComponents = cloud.components.filter((c2) => toInstallKeys.has(`${c2.type}/${c2.slug}`));
|
|
52234
52436
|
const stageRoot = stageManifestComponents(installComponents);
|
|
@@ -52260,7 +52462,7 @@ async function runAgentPull(cwd2, args) {
|
|
|
52260
52462
|
resolveConflict: async (_c) => "overwrite",
|
|
52261
52463
|
resolveSecret: async () => null
|
|
52262
52464
|
};
|
|
52263
|
-
const result = await runHarnessInstall2(adapter.id, toInstall, opts,
|
|
52465
|
+
const result = await runHarnessInstall2(adapter.id, toInstall, opts, cloudAgent.name);
|
|
52264
52466
|
installSpinner.stop("Applied.");
|
|
52265
52467
|
for (const o2 of result.installed) {
|
|
52266
52468
|
justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
|
|
@@ -52288,8 +52490,10 @@ async function runAgentPull(cwd2, args) {
|
|
|
52288
52490
|
}
|
|
52289
52491
|
}
|
|
52290
52492
|
materializeInstructions(cwd2, cloud, toInstallKeys, keepLocalKeys);
|
|
52291
|
-
|
|
52493
|
+
materializeEntrypoint(cwd2, cloudAgent.entrypoint ?? "", existingManifest);
|
|
52494
|
+
const yaml = mergeManifest(cwd2, existingManifest, cloud, cloudAgent, harness);
|
|
52292
52495
|
writeManifest(cwd2, yaml);
|
|
52496
|
+
writeLink(cwd2, buildLinkFromAgent(cloudAgent, harness, readLink(cwd2)));
|
|
52293
52497
|
const lockComponents = buildLockComponents({
|
|
52294
52498
|
cloud,
|
|
52295
52499
|
prevLock: lock,
|
|
@@ -52299,21 +52503,64 @@ async function runAgentPull(cwd2, args) {
|
|
|
52299
52503
|
});
|
|
52300
52504
|
const newState = {
|
|
52301
52505
|
schemaVersion: 1,
|
|
52302
|
-
agent_id:
|
|
52506
|
+
agent_id: agentId,
|
|
52303
52507
|
revision: cloud.revision,
|
|
52304
52508
|
synced_at: new Date().toISOString(),
|
|
52305
52509
|
components: lockComponents,
|
|
52306
|
-
agentMeta: {
|
|
52510
|
+
agentMeta: {
|
|
52511
|
+
name: cloudAgent.name,
|
|
52512
|
+
tagline: cloudAgent.tagline,
|
|
52513
|
+
...cloudAgent.entrypoint ? { entrypoint: cloudAgent.entrypoint } : {}
|
|
52514
|
+
}
|
|
52307
52515
|
};
|
|
52308
52516
|
writeSyncState(cwd2, newState);
|
|
52309
|
-
await pullSecrets(cwd2,
|
|
52310
|
-
|
|
52517
|
+
await pullSecrets(cwd2, agentId);
|
|
52518
|
+
await runEntrypointIfPresent(cwd2, yaml);
|
|
52519
|
+
$e(`Pulled ${cloudAgent.name} at revision ${cloud.revision}.`);
|
|
52311
52520
|
} finally {
|
|
52312
52521
|
try {
|
|
52313
52522
|
fs45.rmSync(stageRoot, { recursive: true, force: true });
|
|
52314
52523
|
} catch {}
|
|
52315
52524
|
}
|
|
52316
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
|
+
}
|
|
52317
52564
|
function skillSourceFromMeta(c2) {
|
|
52318
52565
|
if (c2.type !== "skill")
|
|
52319
52566
|
return;
|
|
@@ -52363,7 +52610,7 @@ function materializeInstructions(cwd2, cloud, toInstall, keepLocal) {
|
|
|
52363
52610
|
fs45.writeFileSync(path48.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
|
|
52364
52611
|
}
|
|
52365
52612
|
}
|
|
52366
|
-
function mergeManifest(cwd2, prev, cloud,
|
|
52613
|
+
function mergeManifest(cwd2, prev, cloud, cloudAgent, harness) {
|
|
52367
52614
|
const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
|
|
52368
52615
|
const localDecl = prev?.skills.find((s3) => {
|
|
52369
52616
|
try {
|
|
@@ -52386,7 +52633,18 @@ function mergeManifest(cwd2, prev, cloud, link2) {
|
|
|
52386
52633
|
}
|
|
52387
52634
|
return { source: `registry:${c2.slug}` };
|
|
52388
52635
|
});
|
|
52389
|
-
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
|
+
}
|
|
52390
52648
|
const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
|
|
52391
52649
|
const payload = (c2.meta ?? {}).mcp ?? {};
|
|
52392
52650
|
const entry = { name: c2.slug };
|
|
@@ -52406,17 +52664,32 @@ function mergeManifest(cwd2, prev, cloud, link2) {
|
|
|
52406
52664
|
});
|
|
52407
52665
|
return {
|
|
52408
52666
|
schema: 1,
|
|
52667
|
+
id: cloudAgent.id,
|
|
52668
|
+
harness,
|
|
52409
52669
|
agent: {
|
|
52410
|
-
name:
|
|
52411
|
-
...
|
|
52670
|
+
name: cloudAgent.name,
|
|
52671
|
+
...cloudAgent.tagline ? { tagline: cloudAgent.tagline } : {}
|
|
52412
52672
|
},
|
|
52413
|
-
...
|
|
52414
|
-
|
|
52415
|
-
} : {},
|
|
52673
|
+
...instructions ? { instructions } : {},
|
|
52674
|
+
...entrypoint ? { entrypoint } : {},
|
|
52416
52675
|
skills,
|
|
52417
52676
|
mcp
|
|
52418
52677
|
};
|
|
52419
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
|
+
}
|
|
52420
52693
|
function parseSourceLoose(raw) {
|
|
52421
52694
|
const m3 = raw.match(/^registry:[a-z0-9_-]+\/([a-z0-9_-]+)/i);
|
|
52422
52695
|
if (m3)
|
|
@@ -52458,7 +52731,7 @@ function buildLockComponents(input) {
|
|
|
52458
52731
|
}
|
|
52459
52732
|
return out;
|
|
52460
52733
|
}
|
|
52461
|
-
function buildLockFromCloud(agent_id, cloud, prev) {
|
|
52734
|
+
function buildLockFromCloud(agent_id, cloud, prev, cloudAgent) {
|
|
52462
52735
|
return {
|
|
52463
52736
|
schemaVersion: 1,
|
|
52464
52737
|
agent_id,
|
|
@@ -52470,11 +52743,73 @@ function buildLockFromCloud(agent_id, cloud, prev) {
|
|
|
52470
52743
|
hash: c2.hash,
|
|
52471
52744
|
installedPaths: []
|
|
52472
52745
|
})),
|
|
52473
|
-
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
|
|
52474
52767
|
};
|
|
52475
52768
|
}
|
|
52476
|
-
function
|
|
52477
|
-
|
|
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
|
+
}
|
|
52478
52813
|
}
|
|
52479
52814
|
async function pullSecrets(cwd2, agentId) {
|
|
52480
52815
|
let cloudSecrets;
|
|
@@ -52508,6 +52843,8 @@ function handleApiError2(err) {
|
|
|
52508
52843
|
if (err instanceof ApiError) {
|
|
52509
52844
|
if (err.status === 401) {
|
|
52510
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.`);
|
|
52511
52848
|
} else {
|
|
52512
52849
|
f2.error(err.message);
|
|
52513
52850
|
}
|
|
@@ -52517,18 +52854,96 @@ function handleApiError2(err) {
|
|
|
52517
52854
|
}
|
|
52518
52855
|
|
|
52519
52856
|
// src/cli/agent-push.ts
|
|
52857
|
+
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
52858
|
+
|
|
52859
|
+
// src/core/agent-outgoing.ts
|
|
52520
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
|
|
52521
52942
|
async function runAgentPush(cwd2, args) {
|
|
52522
52943
|
banner("agent push — send your local changes to the cloud");
|
|
52523
|
-
const link2 = readLink(cwd2);
|
|
52524
|
-
if (!link2) {
|
|
52525
|
-
f2.warn("This folder is not linked to any agent.");
|
|
52526
|
-
f2.info(`Run ${import_picocolors26.default.cyan("brainbase link")} first.`);
|
|
52527
|
-
return;
|
|
52528
|
-
}
|
|
52529
52944
|
if (!hasManifest(cwd2)) {
|
|
52530
|
-
f2.warn(`No ${
|
|
52531
|
-
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.`);
|
|
52532
52947
|
return;
|
|
52533
52948
|
}
|
|
52534
52949
|
let manifest;
|
|
@@ -52538,11 +52953,17 @@ async function runAgentPush(cwd2, args) {
|
|
|
52538
52953
|
f2.error(err.message);
|
|
52539
52954
|
return;
|
|
52540
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;
|
|
52541
52962
|
const sp = de();
|
|
52542
|
-
sp.start(`Fetching cloud state
|
|
52963
|
+
sp.start(`Fetching cloud state…`);
|
|
52543
52964
|
let cloud;
|
|
52544
52965
|
try {
|
|
52545
|
-
cloud = await api.getAgentManifest(
|
|
52966
|
+
cloud = await api.getAgentManifest(agentId);
|
|
52546
52967
|
sp.stop(`Cloud revision ${cloud.revision}.`);
|
|
52547
52968
|
} catch (err) {
|
|
52548
52969
|
sp.stop("Failed.");
|
|
@@ -52555,17 +52976,42 @@ async function runAgentPush(cwd2, args) {
|
|
|
52555
52976
|
lock: lock?.components ?? [],
|
|
52556
52977
|
cloud: cloud.components
|
|
52557
52978
|
});
|
|
52558
|
-
|
|
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 ?? "");
|
|
52559
53005
|
for (const r2 of rows) {
|
|
52560
53006
|
if (r2.type !== "instruction" && r2.type !== "skill" && r2.type !== "mcp") {
|
|
52561
|
-
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.`);
|
|
52562
53008
|
return;
|
|
52563
53009
|
}
|
|
52564
53010
|
}
|
|
52565
53011
|
for (const entry of manifest.skills) {
|
|
52566
53012
|
const parsed = parseSkillSource2(entry.source);
|
|
52567
53013
|
if (parsed.kind === "local") {
|
|
52568
|
-
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\`).`);
|
|
52569
53015
|
return;
|
|
52570
53016
|
}
|
|
52571
53017
|
}
|
|
@@ -52589,22 +53035,22 @@ async function runAgentPush(cwd2, args) {
|
|
|
52589
53035
|
break;
|
|
52590
53036
|
}
|
|
52591
53037
|
}
|
|
52592
|
-
if (!meta.localChanged && toSend.length === 0 && conflicts.length === 0) {
|
|
53038
|
+
if (!meta.localChanged && !entrypointChanged && toSend.length === 0 && conflicts.length === 0) {
|
|
52593
53039
|
f2.info("Nothing to push — local is in sync with the cloud.");
|
|
52594
53040
|
return;
|
|
52595
53041
|
}
|
|
52596
53042
|
if (conflicts.length > 0) {
|
|
52597
53043
|
f2.error(`Cannot push: ${conflicts.length} component${conflicts.length === 1 ? "" : "s"} changed both locally and on the cloud:`);
|
|
52598
53044
|
for (const r2 of conflicts) {
|
|
52599
|
-
console.error(` ${
|
|
53045
|
+
console.error(` ${import_picocolors27.default.red("!")} ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)}`);
|
|
52600
53046
|
}
|
|
52601
|
-
f2.info(`Run ${
|
|
53047
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent pull")} first to reconcile, then push again.`);
|
|
52602
53048
|
return;
|
|
52603
53049
|
}
|
|
52604
53050
|
if (upstreamOnly.length > 0 && !args.yes) {
|
|
52605
53051
|
f2.warn(`Cloud has ${upstreamOnly.length} change${upstreamOnly.length === 1 ? "" : "s"} you don't have locally:`);
|
|
52606
53052
|
for (const r2 of upstreamOnly) {
|
|
52607
|
-
console.warn(` ${
|
|
53053
|
+
console.warn(` ${import_picocolors27.default.cyan("←")} ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)} ${import_picocolors27.default.dim(`(${r2.status})`)}`);
|
|
52608
53054
|
}
|
|
52609
53055
|
f2.info(`If you push now, your push targets revision ${cloud.revision} and may race. Consider \`brainbase agent pull\` first.`);
|
|
52610
53056
|
}
|
|
@@ -52616,6 +53062,13 @@ async function runAgentPush(cwd2, args) {
|
|
|
52616
53062
|
text: "name/tagline"
|
|
52617
53063
|
});
|
|
52618
53064
|
}
|
|
53065
|
+
if (entrypointChanged) {
|
|
53066
|
+
resultRows.push({
|
|
53067
|
+
type: "upd",
|
|
53068
|
+
label: "entrypoint",
|
|
53069
|
+
text: resolvedEntrypoint === "" ? "cleared" : "updated"
|
|
53070
|
+
});
|
|
53071
|
+
}
|
|
52619
53072
|
if (toSend.length) {
|
|
52620
53073
|
resultRows.push({
|
|
52621
53074
|
type: "add",
|
|
@@ -52626,7 +53079,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
52626
53079
|
await showResultCard({
|
|
52627
53080
|
title: "PUSH",
|
|
52628
53081
|
tone: "info",
|
|
52629
|
-
subtitle: `${
|
|
53082
|
+
subtitle: `${manifest.agent.name} ← local`,
|
|
52630
53083
|
rows: resultRows
|
|
52631
53084
|
});
|
|
52632
53085
|
if (!args.yes) {
|
|
@@ -52636,14 +53089,19 @@ async function runAgentPush(cwd2, args) {
|
|
|
52636
53089
|
return;
|
|
52637
53090
|
}
|
|
52638
53091
|
}
|
|
52639
|
-
if (meta.localChanged) {
|
|
53092
|
+
if (meta.localChanged || entrypointChanged) {
|
|
52640
53093
|
const metaSpinner = de();
|
|
52641
53094
|
metaSpinner.start("Updating agent metadata…");
|
|
52642
53095
|
try {
|
|
52643
|
-
|
|
52644
|
-
|
|
52645
|
-
|
|
52646
|
-
|
|
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);
|
|
52647
53105
|
metaSpinner.stop("Metadata updated.");
|
|
52648
53106
|
} catch (err) {
|
|
52649
53107
|
metaSpinner.stop("Failed.");
|
|
@@ -52657,7 +53115,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
52657
53115
|
pushSpinner.start("Pushing…");
|
|
52658
53116
|
let updatedCloud;
|
|
52659
53117
|
try {
|
|
52660
|
-
updatedCloud = await api.pushAgentManifest(
|
|
53118
|
+
updatedCloud = await api.pushAgentManifest(agentId, {
|
|
52661
53119
|
components: outgoing,
|
|
52662
53120
|
base_revision: cloud.revision
|
|
52663
53121
|
});
|
|
@@ -52666,14 +53124,22 @@ async function runAgentPush(cwd2, args) {
|
|
|
52666
53124
|
pushSpinner.stop("Failed.");
|
|
52667
53125
|
if (err instanceof ApiError && err.status === 409) {
|
|
52668
53126
|
f2.error(err.message);
|
|
52669
|
-
f2.info(`Run ${
|
|
53127
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent pull")} and try again.`);
|
|
52670
53128
|
return;
|
|
52671
53129
|
}
|
|
52672
53130
|
return handleApiError3(err);
|
|
52673
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
|
+
}
|
|
52674
53140
|
const newLock = {
|
|
52675
53141
|
schemaVersion: 1,
|
|
52676
|
-
agent_id:
|
|
53142
|
+
agent_id: agentId,
|
|
52677
53143
|
revision: updatedCloud.revision,
|
|
52678
53144
|
synced_at: new Date().toISOString(),
|
|
52679
53145
|
components: updatedCloud.components.map((c2) => {
|
|
@@ -52685,7 +53151,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
52685
53151
|
return false;
|
|
52686
53152
|
}
|
|
52687
53153
|
})?.source;
|
|
52688
|
-
const prior = lock?.components.find((
|
|
53154
|
+
const prior = lock?.components.find((pc26) => pc26.type === c2.type && pc26.slug === c2.slug);
|
|
52689
53155
|
return {
|
|
52690
53156
|
type: c2.type,
|
|
52691
53157
|
slug: c2.slug,
|
|
@@ -52694,11 +53160,15 @@ async function runAgentPush(cwd2, args) {
|
|
|
52694
53160
|
...decl ? { source: decl } : {}
|
|
52695
53161
|
};
|
|
52696
53162
|
}),
|
|
52697
|
-
agentMeta: {
|
|
53163
|
+
agentMeta: {
|
|
53164
|
+
name: manifest.agent.name,
|
|
53165
|
+
tagline: manifest.agent.tagline,
|
|
53166
|
+
entrypoint: resolvedEntrypoint !== undefined ? resolvedEntrypoint : lock?.agentMeta?.entrypoint
|
|
53167
|
+
}
|
|
52698
53168
|
};
|
|
52699
53169
|
writeSyncState(cwd2, newLock);
|
|
52700
|
-
await pushSecrets(cwd2,
|
|
52701
|
-
$e(`Pushed ${
|
|
53170
|
+
await pushSecrets(cwd2, agentId);
|
|
53171
|
+
$e(`Pushed ${manifest.agent.name} at revision ${updatedCloud.revision}.`);
|
|
52702
53172
|
}
|
|
52703
53173
|
async function pushSecrets(cwd2, agentId) {
|
|
52704
53174
|
const localSecrets = readLocalSecrets(cwd2);
|
|
@@ -52726,80 +53196,12 @@ async function pushSecrets(cwd2, agentId) {
|
|
|
52726
53196
|
handleApiError3(err);
|
|
52727
53197
|
}
|
|
52728
53198
|
}
|
|
52729
|
-
|
|
52730
|
-
|
|
52731
|
-
|
|
52732
|
-
|
|
52733
|
-
|
|
52734
|
-
f2.error(
|
|
52735
|
-
return null;
|
|
52736
|
-
}
|
|
52737
|
-
if (body.trim()) {
|
|
52738
|
-
const fileHash2 = hashString(body);
|
|
52739
|
-
const file = {
|
|
52740
|
-
path: manifest.instructions.file,
|
|
52741
|
-
content: body,
|
|
52742
|
-
hash: fileHash2
|
|
52743
|
-
};
|
|
52744
|
-
out.push({
|
|
52745
|
-
type: "instruction",
|
|
52746
|
-
slug: "agent-instructions",
|
|
52747
|
-
description: "Agent instructions",
|
|
52748
|
-
hash: componentHashFromFileHashes([fileHash2]),
|
|
52749
|
-
files: [file],
|
|
52750
|
-
meta: { source: "global_prompt" }
|
|
52751
|
-
});
|
|
52752
|
-
}
|
|
52753
|
-
}
|
|
52754
|
-
for (const entry of manifest.skills) {
|
|
52755
|
-
const parsed = parseSkillSource2(entry.source);
|
|
52756
|
-
if (parsed.kind !== "registry")
|
|
52757
|
-
continue;
|
|
52758
|
-
const cloudMatch = cloud.components.find((c2) => c2.type === "skill" && c2.slug === parsed.slug);
|
|
52759
|
-
out.push({
|
|
52760
|
-
type: "skill",
|
|
52761
|
-
slug: parsed.slug,
|
|
52762
|
-
hash: cloudMatch?.hash ?? "",
|
|
52763
|
-
files: [],
|
|
52764
|
-
meta: {
|
|
52765
|
-
name: parsed.creator ? `${parsed.creator}/${parsed.slug}` : parsed.slug,
|
|
52766
|
-
...parsed.version ? { version: parsed.version } : {}
|
|
52767
|
-
}
|
|
52768
|
-
});
|
|
52769
|
-
}
|
|
52770
|
-
for (const entry of manifest.mcp ?? []) {
|
|
52771
|
-
if (!entry.url && !entry.command) {
|
|
52772
|
-
f2.error(`MCP ${import_picocolors26.default.bold(entry.name)} needs either ${import_picocolors26.default.cyan("url")} or ${import_picocolors26.default.cyan("command")}.`);
|
|
52773
|
-
return null;
|
|
52774
|
-
}
|
|
52775
|
-
const payload = {};
|
|
52776
|
-
if (entry.url !== undefined)
|
|
52777
|
-
payload.url = entry.url;
|
|
52778
|
-
if (entry.command !== undefined)
|
|
52779
|
-
payload.command = entry.command;
|
|
52780
|
-
if (entry.args !== undefined)
|
|
52781
|
-
payload.args = entry.args;
|
|
52782
|
-
if (entry.env !== undefined)
|
|
52783
|
-
payload.env = entry.env;
|
|
52784
|
-
if (entry.headers !== undefined)
|
|
52785
|
-
payload.headers = entry.headers;
|
|
52786
|
-
payload.is_enabled = entry.is_enabled ?? true;
|
|
52787
|
-
out.push({
|
|
52788
|
-
type: "mcp",
|
|
52789
|
-
slug: entry.name,
|
|
52790
|
-
hash: "",
|
|
52791
|
-
files: [],
|
|
52792
|
-
meta: { mcp: payload }
|
|
52793
|
-
});
|
|
52794
|
-
}
|
|
52795
|
-
return out;
|
|
52796
|
-
}
|
|
52797
|
-
function handleApiError3(err) {
|
|
52798
|
-
if (err instanceof ApiError) {
|
|
52799
|
-
if (err.status === 401) {
|
|
52800
|
-
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
52801
|
-
} else {
|
|
52802
|
-
f2.error(err.message);
|
|
53199
|
+
function handleApiError3(err) {
|
|
53200
|
+
if (err instanceof ApiError) {
|
|
53201
|
+
if (err.status === 401) {
|
|
53202
|
+
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
53203
|
+
} else {
|
|
53204
|
+
f2.error(err.message);
|
|
52803
53205
|
}
|
|
52804
53206
|
} else {
|
|
52805
53207
|
f2.error(err.message);
|
|
@@ -52807,13 +53209,13 @@ function handleApiError3(err) {
|
|
|
52807
53209
|
}
|
|
52808
53210
|
|
|
52809
53211
|
// src/cli/agent-status.ts
|
|
52810
|
-
var
|
|
53212
|
+
var import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
52811
53213
|
async function runAgentStatus(cwd2) {
|
|
52812
53214
|
banner("agent status — what changed locally, remotely, both");
|
|
52813
53215
|
const link2 = readLink(cwd2);
|
|
52814
53216
|
if (!link2) {
|
|
52815
53217
|
f2.warn("This folder is not linked to any agent.");
|
|
52816
|
-
f2.info(`Run ${
|
|
53218
|
+
f2.info(`Run ${import_picocolors28.default.cyan("brainbase link")} first.`);
|
|
52817
53219
|
return;
|
|
52818
53220
|
}
|
|
52819
53221
|
const manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
@@ -52834,8 +53236,8 @@ async function runAgentStatus(cwd2) {
|
|
|
52834
53236
|
return;
|
|
52835
53237
|
}
|
|
52836
53238
|
if (!manifest) {
|
|
52837
|
-
f2.info(`${
|
|
52838
|
-
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}.`);
|
|
52839
53241
|
return;
|
|
52840
53242
|
}
|
|
52841
53243
|
const localComponents = readLocalComponents(cwd2, manifest);
|
|
@@ -52874,17 +53276,17 @@ async function runAgentStatus(cwd2) {
|
|
|
52874
53276
|
}
|
|
52875
53277
|
const lines = [];
|
|
52876
53278
|
lines.push("");
|
|
52877
|
-
lines.push(` ${
|
|
52878
|
-
lines.push(` ${
|
|
52879
|
-
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"}`);
|
|
52880
53282
|
lines.push("");
|
|
52881
53283
|
if (meta.localChanged || meta.cloudChanged) {
|
|
52882
|
-
lines.push(` ${
|
|
53284
|
+
lines.push(` ${import_picocolors28.default.bold("agent metadata")}`);
|
|
52883
53285
|
if (meta.localChanged) {
|
|
52884
|
-
lines.push(` ${
|
|
53286
|
+
lines.push(` ${import_picocolors28.default.yellow("→ push")} name/tagline edited in brainbase.agent.yaml`);
|
|
52885
53287
|
}
|
|
52886
53288
|
if (meta.cloudChanged) {
|
|
52887
|
-
lines.push(` ${
|
|
53289
|
+
lines.push(` ${import_picocolors28.default.cyan("← pull")} name/tagline changed on cloud`);
|
|
52888
53290
|
}
|
|
52889
53291
|
lines.push("");
|
|
52890
53292
|
}
|
|
@@ -52894,65 +53296,65 @@ async function runAgentStatus(cwd2) {
|
|
|
52894
53296
|
const cloudSecrets = cloudRes.secrets ?? {};
|
|
52895
53297
|
const sd = diffSecrets(localSecrets, cloudSecrets);
|
|
52896
53298
|
if (sd.localOnly.length || sd.cloudOnly.length || sd.changed.length) {
|
|
52897
|
-
lines.push(` ${
|
|
53299
|
+
lines.push(` ${import_picocolors28.default.bold("secrets")}`);
|
|
52898
53300
|
if (sd.localOnly.length)
|
|
52899
|
-
lines.push(` ${
|
|
53301
|
+
lines.push(` ${import_picocolors28.default.yellow("→ push")} new locally: ${sd.localOnly.join(", ")}`);
|
|
52900
53302
|
if (sd.changed.length)
|
|
52901
|
-
lines.push(` ${
|
|
53303
|
+
lines.push(` ${import_picocolors28.default.yellow("→ push")} values changed: ${sd.changed.join(", ")}`);
|
|
52902
53304
|
if (sd.cloudOnly.length)
|
|
52903
|
-
lines.push(` ${
|
|
53305
|
+
lines.push(` ${import_picocolors28.default.cyan("← pull")} new on cloud: ${sd.cloudOnly.join(", ")}`);
|
|
52904
53306
|
lines.push("");
|
|
52905
53307
|
}
|
|
52906
53308
|
} catch {}
|
|
52907
53309
|
if (conflicts.length === 0 && toPush.length === 0 && toPull.length === 0) {
|
|
52908
|
-
lines.push(` ${
|
|
53310
|
+
lines.push(` ${import_picocolors28.default.green("✓")} everything is in sync`);
|
|
52909
53311
|
lines.push("");
|
|
52910
53312
|
console.log(lines.join(`
|
|
52911
53313
|
`));
|
|
52912
53314
|
return;
|
|
52913
53315
|
}
|
|
52914
53316
|
if (toPush.length) {
|
|
52915
|
-
lines.push(` ${
|
|
53317
|
+
lines.push(` ${import_picocolors28.default.bold("changes to push")} ${import_picocolors28.default.dim(`(${toPush.length})`)}`);
|
|
52916
53318
|
for (const r2 of toPush)
|
|
52917
|
-
lines.push(` ${
|
|
53319
|
+
lines.push(` ${import_picocolors28.default.yellow("→")} ${fmtRow(r2)}`);
|
|
52918
53320
|
lines.push("");
|
|
52919
53321
|
}
|
|
52920
53322
|
if (toPull.length) {
|
|
52921
|
-
lines.push(` ${
|
|
53323
|
+
lines.push(` ${import_picocolors28.default.bold("changes to pull")} ${import_picocolors28.default.dim(`(${toPull.length})`)}`);
|
|
52922
53324
|
for (const r2 of toPull)
|
|
52923
|
-
lines.push(` ${
|
|
53325
|
+
lines.push(` ${import_picocolors28.default.cyan("←")} ${fmtRow(r2)}`);
|
|
52924
53326
|
lines.push("");
|
|
52925
53327
|
}
|
|
52926
53328
|
if (conflicts.length) {
|
|
52927
|
-
lines.push(` ${
|
|
53329
|
+
lines.push(` ${import_picocolors28.default.bold(import_picocolors28.default.red("conflicts"))} ${import_picocolors28.default.dim(`(${conflicts.length})`)}`);
|
|
52928
53330
|
for (const r2 of conflicts)
|
|
52929
|
-
lines.push(` ${
|
|
53331
|
+
lines.push(` ${import_picocolors28.default.red("!")} ${fmtRow(r2)}`);
|
|
52930
53332
|
lines.push("");
|
|
52931
53333
|
}
|
|
52932
|
-
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")}`);
|
|
52933
53335
|
lines.push("");
|
|
52934
53336
|
console.log(lines.join(`
|
|
52935
53337
|
`));
|
|
52936
53338
|
}
|
|
52937
53339
|
function fmtRow(r2) {
|
|
52938
|
-
const head = `${fmtType(r2.type)} ${
|
|
53340
|
+
const head = `${fmtType(r2.type)} ${import_picocolors28.default.bold(r2.slug)}`;
|
|
52939
53341
|
switch (r2.status) {
|
|
52940
53342
|
case "added-only-local":
|
|
52941
|
-
return `${head} ${
|
|
53343
|
+
return `${head} ${import_picocolors28.default.dim("(new — only in brainbase.agent.yaml)")}`;
|
|
52942
53344
|
case "added-cloud":
|
|
52943
|
-
return `${head} ${
|
|
53345
|
+
return `${head} ${import_picocolors28.default.dim("(new on cloud)")}`;
|
|
52944
53346
|
case "added-local":
|
|
52945
|
-
return `${head} ${
|
|
53347
|
+
return `${head} ${import_picocolors28.default.dim("(present locally and on cloud, never synced here)")}`;
|
|
52946
53348
|
case "removed-local":
|
|
52947
|
-
return `${head} ${
|
|
53349
|
+
return `${head} ${import_picocolors28.default.dim("(removed from brainbase.agent.yaml)")}`;
|
|
52948
53350
|
case "removed-cloud":
|
|
52949
|
-
return `${head} ${
|
|
53351
|
+
return `${head} ${import_picocolors28.default.dim("(removed on cloud)")}`;
|
|
52950
53352
|
case "modified-local":
|
|
52951
|
-
return `${head} ${
|
|
53353
|
+
return `${head} ${import_picocolors28.default.dim("(you edited it)")}`;
|
|
52952
53354
|
case "modified-cloud":
|
|
52953
|
-
return `${head} ${
|
|
53355
|
+
return `${head} ${import_picocolors28.default.dim("(cloud was updated)")}`;
|
|
52954
53356
|
case "modified-both":
|
|
52955
|
-
return `${head} ${
|
|
53357
|
+
return `${head} ${import_picocolors28.default.dim("(both diverged — needs resolution)")}`;
|
|
52956
53358
|
default:
|
|
52957
53359
|
return head;
|
|
52958
53360
|
}
|
|
@@ -52989,10 +53391,11 @@ function formatExport(shell, key2, value) {
|
|
|
52989
53391
|
}
|
|
52990
53392
|
|
|
52991
53393
|
// src/cli/agent-create.ts
|
|
52992
|
-
|
|
53394
|
+
import path49 from "node:path";
|
|
53395
|
+
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
52993
53396
|
|
|
52994
53397
|
// src/ui/box.ts
|
|
52995
|
-
var
|
|
53398
|
+
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
52996
53399
|
var H3 = "─";
|
|
52997
53400
|
var TINT = {
|
|
52998
53401
|
ok: COLOR.ok,
|
|
@@ -53004,20 +53407,28 @@ var TINT = {
|
|
|
53004
53407
|
function divider(label, width = 56, indent = 2) {
|
|
53005
53408
|
const ind = " ".repeat(indent);
|
|
53006
53409
|
if (!label)
|
|
53007
|
-
return `${ind}${
|
|
53410
|
+
return `${ind}${import_picocolors29.default.dim(H3.repeat(width))}`;
|
|
53008
53411
|
const labelText = ` ${label} `;
|
|
53009
53412
|
const labelLen = visibleLength(labelText);
|
|
53010
|
-
const left =
|
|
53011
|
-
const right =
|
|
53012
|
-
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}`;
|
|
53013
53416
|
}
|
|
53014
53417
|
function tip(text, indent = 2) {
|
|
53015
|
-
return " ".repeat(indent) +
|
|
53418
|
+
return " ".repeat(indent) + import_picocolors29.default.dim("›") + " " + import_picocolors29.default.dim(text);
|
|
53016
53419
|
}
|
|
53017
53420
|
|
|
53018
53421
|
// src/cli/agent-create.ts
|
|
53019
53422
|
async function runAgentCreate(cwd2, args) {
|
|
53020
|
-
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
|
+
}
|
|
53021
53432
|
const orgsSpinner = de();
|
|
53022
53433
|
orgsSpinner.start("Loading your organizations…");
|
|
53023
53434
|
let orgs;
|
|
@@ -53044,7 +53455,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53044
53455
|
org = found;
|
|
53045
53456
|
} else if (orgs.length === 1) {
|
|
53046
53457
|
org = orgs[0];
|
|
53047
|
-
f2.info(`Using organization ${
|
|
53458
|
+
f2.info(`Using organization ${import_picocolors30.default.bold(org.name)}.`);
|
|
53048
53459
|
} else {
|
|
53049
53460
|
const orgChoice = await ie({
|
|
53050
53461
|
message: "Pick an organization",
|
|
@@ -53092,7 +53503,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53092
53503
|
createSpinner2.start("Creating team…");
|
|
53093
53504
|
try {
|
|
53094
53505
|
team = await api.createTeam(org.id, teamName.trim());
|
|
53095
|
-
createSpinner2.stop(`Created team ${
|
|
53506
|
+
createSpinner2.stop(`Created team ${import_picocolors30.default.bold(team.name)}.`);
|
|
53096
53507
|
} catch (err) {
|
|
53097
53508
|
createSpinner2.stop("Failed.");
|
|
53098
53509
|
handleApiError4(err);
|
|
@@ -53102,8 +53513,8 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53102
53513
|
team = teams.find((t) => t.id === picked);
|
|
53103
53514
|
}
|
|
53104
53515
|
}
|
|
53105
|
-
const harness = normalizeHarnessId(args.harness ?? await pickHarness(cwd2));
|
|
53106
|
-
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();
|
|
53107
53518
|
if (!agentName) {
|
|
53108
53519
|
const ans = await te({
|
|
53109
53520
|
message: "Agent name",
|
|
@@ -53112,7 +53523,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53112
53523
|
});
|
|
53113
53524
|
agentName = ensureNotCancelled(ans).trim();
|
|
53114
53525
|
}
|
|
53115
|
-
let tagline = args.tagline?.trim() || undefined;
|
|
53526
|
+
let tagline = (args.tagline ?? manifest.agent.tagline)?.trim() || undefined;
|
|
53116
53527
|
if (tagline === undefined && !args.yes) {
|
|
53117
53528
|
const ans = await te({
|
|
53118
53529
|
message: "Tagline",
|
|
@@ -53124,11 +53535,11 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53124
53535
|
}
|
|
53125
53536
|
if (!args.yes) {
|
|
53126
53537
|
le([
|
|
53127
|
-
`${
|
|
53128
|
-
`${
|
|
53129
|
-
`${
|
|
53130
|
-
`${
|
|
53131
|
-
...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}`] : []
|
|
53132
53543
|
].join(`
|
|
53133
53544
|
`), "Will create");
|
|
53134
53545
|
const confirmed = await se({ message: "Create this agent?", initialValue: true });
|
|
@@ -53137,6 +53548,19 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53137
53548
|
return;
|
|
53138
53549
|
}
|
|
53139
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
|
+
}
|
|
53140
53564
|
const createSpinner = de();
|
|
53141
53565
|
createSpinner.start("Creating agent…");
|
|
53142
53566
|
let agent;
|
|
@@ -53146,9 +53570,10 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53146
53570
|
team_id: team.id,
|
|
53147
53571
|
name: agentName,
|
|
53148
53572
|
tagline,
|
|
53149
|
-
harness
|
|
53573
|
+
harness,
|
|
53574
|
+
...resolvedEntrypoint !== undefined ? { entrypoint: resolvedEntrypoint } : {}
|
|
53150
53575
|
});
|
|
53151
|
-
createSpinner.stop(`Created ${
|
|
53576
|
+
createSpinner.stop(`Created ${import_picocolors30.default.bold(agent.name)}.`);
|
|
53152
53577
|
} catch (err) {
|
|
53153
53578
|
createSpinner.stop("Failed.");
|
|
53154
53579
|
handleApiError4(err);
|
|
@@ -53161,7 +53586,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53161
53586
|
let wantsTracking = true;
|
|
53162
53587
|
if (!args.yes) {
|
|
53163
53588
|
const ans = await se({
|
|
53164
|
-
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)")}`,
|
|
53165
53590
|
initialValue: true
|
|
53166
53591
|
});
|
|
53167
53592
|
wantsTracking = ensureNotCancelled(ans);
|
|
@@ -53200,71 +53625,455 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53200
53625
|
}
|
|
53201
53626
|
}
|
|
53202
53627
|
}
|
|
53203
|
-
const link2 = {
|
|
53204
|
-
schemaVersion: 1,
|
|
53205
|
-
agent_id: agent.id,
|
|
53206
|
-
org_id: agent.org_id,
|
|
53207
|
-
team_id: agent.team_id,
|
|
53208
|
-
slug: agent.slug,
|
|
53209
|
-
name: agent.name,
|
|
53210
|
-
tagline: agent.tagline,
|
|
53211
|
-
url: agent.url,
|
|
53212
|
-
linked_at: new Date().toISOString(),
|
|
53213
|
-
linked_by: session?.email ?? session?.user_id,
|
|
53214
|
-
harness,
|
|
53215
|
-
tracking
|
|
53216
|
-
};
|
|
53217
|
-
writeLink(cwd2, link2);
|
|
53218
|
-
|
|
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)}.`);
|
|
53219
54037
|
await showResultCard({
|
|
53220
|
-
title: "
|
|
54038
|
+
title: "UNPACKED",
|
|
53221
54039
|
tone: "ok",
|
|
53222
|
-
subtitle:
|
|
54040
|
+
subtitle: cloudAgent.name,
|
|
53223
54041
|
meta: [
|
|
53224
|
-
["
|
|
53225
|
-
["agent",
|
|
53226
|
-
...
|
|
54042
|
+
["harness", harness],
|
|
54043
|
+
["agent", cloudAgent.id],
|
|
54044
|
+
...cloudAgent.url ? [["url", cloudAgent.url]] : []
|
|
53227
54045
|
]
|
|
53228
54046
|
});
|
|
53229
|
-
console.log();
|
|
53230
|
-
if (tracking && harness === "codex") {
|
|
53231
|
-
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.")}`));
|
|
53232
|
-
}
|
|
53233
|
-
console.log(tip(`brainbase agent pull ${import_picocolors29.default.dim("— pull the agent contents into this folder")}`));
|
|
53234
|
-
console.log();
|
|
53235
54047
|
}
|
|
53236
|
-
async function
|
|
53237
|
-
const
|
|
53238
|
-
const detected = detections.filter((d3) => d3.detection.detected);
|
|
53239
|
-
if (detected.length === 1) {
|
|
53240
|
-
f2.info(`Detected harness: ${import_picocolors29.default.bold(detected[0].adapter.displayName)}.`);
|
|
53241
|
-
return detected[0].adapter.id;
|
|
53242
|
-
}
|
|
54048
|
+
async function pickHarness2(current) {
|
|
54049
|
+
const initial = current ? normalizeHarnessId(current) : undefined;
|
|
53243
54050
|
const choice = await ie({
|
|
53244
|
-
message:
|
|
53245
|
-
options:
|
|
53246
|
-
value:
|
|
53247
|
-
label:
|
|
53248
|
-
hint:
|
|
53249
|
-
}))
|
|
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
|
|
53250
54058
|
});
|
|
53251
54059
|
return ensureNotCancelled(choice);
|
|
53252
54060
|
}
|
|
53253
|
-
function
|
|
54061
|
+
function handleApiError5(err) {
|
|
53254
54062
|
if (err instanceof ApiError) {
|
|
53255
54063
|
if (err.status === 401) {
|
|
53256
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.`);
|
|
53257
54067
|
} else {
|
|
53258
54068
|
f2.error(err.message);
|
|
53259
54069
|
}
|
|
53260
54070
|
} else {
|
|
53261
54071
|
f2.error(err.message);
|
|
53262
54072
|
}
|
|
53263
|
-
$e("Aborted.");
|
|
53264
54073
|
}
|
|
53265
54074
|
|
|
53266
54075
|
// src/cli/agent.ts
|
|
53267
|
-
async function runAgent(cwd2, sub,
|
|
54076
|
+
async function runAgent(cwd2, sub, args, opts) {
|
|
53268
54077
|
switch (sub) {
|
|
53269
54078
|
case "create":
|
|
53270
54079
|
await runAgentCreate(cwd2, {
|
|
@@ -53278,10 +54087,22 @@ async function runAgent(cwd2, sub, _args, opts) {
|
|
|
53278
54087
|
});
|
|
53279
54088
|
return;
|
|
53280
54089
|
case "pull":
|
|
53281
|
-
await runAgentPull(cwd2,
|
|
54090
|
+
await runAgentPull(cwd2, {
|
|
54091
|
+
yes: opts.yes,
|
|
54092
|
+
scope: opts.scope,
|
|
54093
|
+
agentIdArg: args[0],
|
|
54094
|
+
force: opts.force
|
|
54095
|
+
});
|
|
53282
54096
|
return;
|
|
53283
54097
|
case "push":
|
|
53284
|
-
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
|
+
});
|
|
53285
54106
|
return;
|
|
53286
54107
|
case "status":
|
|
53287
54108
|
await runAgentStatus(cwd2);
|
|
@@ -53305,29 +54126,30 @@ async function runAgent(cwd2, sub, _args, opts) {
|
|
|
53305
54126
|
function printHelp() {
|
|
53306
54127
|
const out = [];
|
|
53307
54128
|
out.push("");
|
|
53308
|
-
out.push(` ${
|
|
54129
|
+
out.push(` ${import_picocolors32.default.bold("brainbase agent")} ${import_picocolors32.default.dim("<sub> [options]")}`);
|
|
53309
54130
|
out.push("");
|
|
53310
|
-
out.push(` ${
|
|
53311
|
-
out.push(` ${
|
|
53312
|
-
out.push(` ${
|
|
53313
|
-
out.push(` ${
|
|
53314
|
-
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)"`')}`);
|
|
53315
54137
|
out.push("");
|
|
53316
54138
|
console.log(out.join(`
|
|
53317
54139
|
`));
|
|
53318
54140
|
}
|
|
53319
54141
|
|
|
53320
54142
|
// src/cli/orchestration.ts
|
|
53321
|
-
var
|
|
54143
|
+
var import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
53322
54144
|
|
|
53323
54145
|
// src/cli/orchestration-pull.ts
|
|
53324
|
-
import
|
|
54146
|
+
import path53 from "node:path";
|
|
53325
54147
|
import fs49 from "node:fs";
|
|
53326
|
-
var
|
|
54148
|
+
var import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
53327
54149
|
|
|
53328
54150
|
// src/core/orchestration-manifest.ts
|
|
53329
|
-
import
|
|
53330
|
-
import
|
|
54151
|
+
import path51 from "node:path";
|
|
54152
|
+
import fs47 from "node:fs";
|
|
53331
54153
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
53332
54154
|
var ORCH_MANIFEST_FILE = "brainbase-orchestration.yaml";
|
|
53333
54155
|
var ORCH_MEMBERS_DIR = "agents";
|
|
@@ -53355,16 +54177,16 @@ var OrchestrationManifestSchema = exports_external.object({
|
|
|
53355
54177
|
edges: exports_external.array(EdgeSchema).default([])
|
|
53356
54178
|
});
|
|
53357
54179
|
function orchManifestPath(cwd2) {
|
|
53358
|
-
return
|
|
54180
|
+
return path51.join(cwd2, ORCH_MANIFEST_FILE);
|
|
53359
54181
|
}
|
|
53360
54182
|
function hasOrchManifest(cwd2) {
|
|
53361
|
-
return
|
|
54183
|
+
return fs47.existsSync(orchManifestPath(cwd2));
|
|
53362
54184
|
}
|
|
53363
54185
|
function readOrchManifest(cwd2) {
|
|
53364
54186
|
const p2 = orchManifestPath(cwd2);
|
|
53365
|
-
if (!
|
|
54187
|
+
if (!fs47.existsSync(p2))
|
|
53366
54188
|
return null;
|
|
53367
|
-
const raw =
|
|
54189
|
+
const raw = fs47.readFileSync(p2, "utf8");
|
|
53368
54190
|
let parsed;
|
|
53369
54191
|
try {
|
|
53370
54192
|
parsed = import_yaml3.default.parse(raw);
|
|
@@ -53383,15 +54205,15 @@ function writeOrchManifest(cwd2, manifest) {
|
|
|
53383
54205
|
doc.commentBefore = ` brainbase-orchestration.yaml — declarative orchestration manifest.
|
|
53384
54206
|
` + ` Committed to source control. Edit by hand, then
|
|
53385
54207
|
` + " `brainbase orchestration push`. Member agents live under ./agents/.";
|
|
53386
|
-
|
|
54208
|
+
fs47.writeFileSync(orchManifestPath(cwd2), String(doc), "utf8");
|
|
53387
54209
|
}
|
|
53388
54210
|
function memberDir(cwd2, slug) {
|
|
53389
|
-
return
|
|
54211
|
+
return path51.join(cwd2, ORCH_MEMBERS_DIR, slug);
|
|
53390
54212
|
}
|
|
53391
54213
|
|
|
53392
54214
|
// src/core/orchestration-link.ts
|
|
53393
|
-
import
|
|
53394
|
-
import
|
|
54215
|
+
import path52 from "node:path";
|
|
54216
|
+
import fs48 from "node:fs";
|
|
53395
54217
|
var ORCH_LINK_FILE = "orchestration-link.json";
|
|
53396
54218
|
var ORCH_SYNC_STATE_FILE = "orchestration-sync-state.json";
|
|
53397
54219
|
var OrchestrationLinkSchema = exports_external.object({
|
|
@@ -53425,10 +54247,10 @@ var OrchestrationSyncStateSchema = exports_external.object({
|
|
|
53425
54247
|
edges: exports_external.array(SyncedEdgeSchema)
|
|
53426
54248
|
});
|
|
53427
54249
|
function orchLinkPath(cwd2) {
|
|
53428
|
-
return
|
|
54250
|
+
return path52.join(cwd2, LINK_DIR, ORCH_LINK_FILE);
|
|
53429
54251
|
}
|
|
53430
54252
|
function orchSyncStatePath(cwd2) {
|
|
53431
|
-
return
|
|
54253
|
+
return path52.join(cwd2, LINK_DIR, ORCH_SYNC_STATE_FILE);
|
|
53432
54254
|
}
|
|
53433
54255
|
function readOrchLink(cwd2) {
|
|
53434
54256
|
const p2 = orchLinkPath(cwd2);
|
|
@@ -53441,7 +54263,7 @@ function readOrchLink(cwd2) {
|
|
|
53441
54263
|
}
|
|
53442
54264
|
}
|
|
53443
54265
|
function writeOrchLink(cwd2, link2) {
|
|
53444
|
-
ensureDir(
|
|
54266
|
+
ensureDir(path52.join(cwd2, LINK_DIR));
|
|
53445
54267
|
const clean = {};
|
|
53446
54268
|
for (const [k3, v3] of Object.entries(link2)) {
|
|
53447
54269
|
if (v3 !== null && v3 !== undefined)
|
|
@@ -53461,200 +54283,28 @@ function readOrchSyncState(cwd2) {
|
|
|
53461
54283
|
}
|
|
53462
54284
|
}
|
|
53463
54285
|
function writeOrchSyncState(cwd2, state) {
|
|
53464
|
-
ensureDir(
|
|
54286
|
+
ensureDir(path52.join(cwd2, LINK_DIR));
|
|
53465
54287
|
writeJson(orchSyncStatePath(cwd2), state);
|
|
53466
54288
|
ensureGitignore2(cwd2);
|
|
53467
54289
|
}
|
|
53468
54290
|
function ensureGitignore2(cwd2) {
|
|
53469
|
-
const ignorePath =
|
|
54291
|
+
const ignorePath = path52.join(cwd2, LINK_DIR, ".gitignore");
|
|
53470
54292
|
const desired = `${ORCH_SYNC_STATE_FILE}
|
|
53471
54293
|
`;
|
|
53472
54294
|
try {
|
|
53473
54295
|
if (!exists(ignorePath)) {
|
|
53474
|
-
|
|
54296
|
+
fs48.writeFileSync(ignorePath, desired);
|
|
53475
54297
|
return;
|
|
53476
54298
|
}
|
|
53477
|
-
const current =
|
|
54299
|
+
const current = fs48.readFileSync(ignorePath, "utf8");
|
|
53478
54300
|
if (!current.split(/\r?\n/).some((l2) => l2.trim() === ORCH_SYNC_STATE_FILE)) {
|
|
53479
|
-
|
|
54301
|
+
fs48.writeFileSync(ignorePath, current.endsWith(`
|
|
53480
54302
|
`) ? current + desired : current + `
|
|
53481
54303
|
` + desired);
|
|
53482
54304
|
}
|
|
53483
54305
|
} catch {}
|
|
53484
54306
|
}
|
|
53485
54307
|
|
|
53486
|
-
// src/core/agent-fresh-install.ts
|
|
53487
|
-
import path51 from "node:path";
|
|
53488
|
-
import fs48 from "node:fs";
|
|
53489
|
-
import os13 from "node:os";
|
|
53490
|
-
async function installAgentFresh(input) {
|
|
53491
|
-
const { cwd: cwd2, agent, cloud, harness } = input;
|
|
53492
|
-
const scope = input.scope ?? "project";
|
|
53493
|
-
ensureDir(cwd2);
|
|
53494
|
-
const stageRoot = stageManifestComponents2(cloud.components);
|
|
53495
|
-
const justInstalledPaths = new Map;
|
|
53496
|
-
const cloudHasOrchestrationMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === ORCHESTRATION_MCP_SLUG);
|
|
53497
|
-
const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
|
|
53498
|
-
const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
|
|
53499
|
-
const needMemoryMcpInstall = !cloudHasMemoryMcp;
|
|
53500
|
-
try {
|
|
53501
|
-
if (cloud.components.length > 0 || needOrchestrationMcpInstall || needMemoryMcpInstall) {
|
|
53502
|
-
const toInstall = cloud.components.map((c2) => ({
|
|
53503
|
-
type: c2.type,
|
|
53504
|
-
slug: c2.slug,
|
|
53505
|
-
scope,
|
|
53506
|
-
rootDir: path51.join(stageRoot, c2.type, c2.slug),
|
|
53507
|
-
description: c2.description,
|
|
53508
|
-
meta: c2.meta,
|
|
53509
|
-
payload: c2.meta?.mcp,
|
|
53510
|
-
checksum: c2.hash
|
|
53511
|
-
}));
|
|
53512
|
-
if (needOrchestrationMcpInstall) {
|
|
53513
|
-
toInstall.push(buildOrchestrationMcpComponent(scope));
|
|
53514
|
-
}
|
|
53515
|
-
if (needMemoryMcpInstall) {
|
|
53516
|
-
toInstall.push(buildMemoryMcpComponent(scope));
|
|
53517
|
-
}
|
|
53518
|
-
const installOpts = {
|
|
53519
|
-
cwd: cwd2,
|
|
53520
|
-
scope,
|
|
53521
|
-
resolveConflict: async (_c) => "overwrite",
|
|
53522
|
-
resolveSecret: async () => null
|
|
53523
|
-
};
|
|
53524
|
-
const result = await runHarnessInstall3(harness, toInstall, installOpts, agent.name);
|
|
53525
|
-
for (const o2 of result.installed) {
|
|
53526
|
-
justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
|
|
53527
|
-
}
|
|
53528
|
-
}
|
|
53529
|
-
materializeInstructions2(cwd2, cloud);
|
|
53530
|
-
const manifest = buildManifestFromCloud(cloud, agent);
|
|
53531
|
-
writeManifest(cwd2, manifest);
|
|
53532
|
-
writeLink(cwd2, {
|
|
53533
|
-
schemaVersion: 1,
|
|
53534
|
-
agent_id: agent.id,
|
|
53535
|
-
org_id: agent.org_id,
|
|
53536
|
-
team_id: agent.team_id,
|
|
53537
|
-
slug: agent.slug,
|
|
53538
|
-
name: agent.name,
|
|
53539
|
-
tagline: agent.tagline,
|
|
53540
|
-
url: agent.url,
|
|
53541
|
-
linked_at: new Date().toISOString(),
|
|
53542
|
-
harness
|
|
53543
|
-
});
|
|
53544
|
-
const syncedComponents = cloud.components.map((c2) => ({
|
|
53545
|
-
type: c2.type,
|
|
53546
|
-
slug: c2.slug,
|
|
53547
|
-
hash: c2.hash,
|
|
53548
|
-
installedPaths: justInstalledPaths.get(`${c2.type}/${c2.slug}`) ?? []
|
|
53549
|
-
}));
|
|
53550
|
-
writeSyncState(cwd2, {
|
|
53551
|
-
schemaVersion: 1,
|
|
53552
|
-
agent_id: agent.id,
|
|
53553
|
-
revision: cloud.revision,
|
|
53554
|
-
synced_at: new Date().toISOString(),
|
|
53555
|
-
components: syncedComponents,
|
|
53556
|
-
agentMeta: { name: agent.name, tagline: agent.tagline }
|
|
53557
|
-
});
|
|
53558
|
-
if (input.pullSecrets !== false) {
|
|
53559
|
-
await pullAgentSecrets(cwd2, agent.id);
|
|
53560
|
-
}
|
|
53561
|
-
return {
|
|
53562
|
-
installedPaths: justInstalledPaths,
|
|
53563
|
-
manifest,
|
|
53564
|
-
syncedComponents
|
|
53565
|
-
};
|
|
53566
|
-
} finally {
|
|
53567
|
-
try {
|
|
53568
|
-
fs48.rmSync(stageRoot, { recursive: true, force: true });
|
|
53569
|
-
} catch {}
|
|
53570
|
-
}
|
|
53571
|
-
}
|
|
53572
|
-
function stageManifestComponents2(components) {
|
|
53573
|
-
const root = fs48.mkdtempSync(path51.join(os13.tmpdir(), "brainbase-orch-pull-"));
|
|
53574
|
-
for (const c2 of components) {
|
|
53575
|
-
const compDir = path51.join(root, c2.type, c2.slug);
|
|
53576
|
-
ensureDir(compDir);
|
|
53577
|
-
for (const f4 of c2.files) {
|
|
53578
|
-
const target = path51.join(compDir, f4.path);
|
|
53579
|
-
ensureDir(path51.dirname(target));
|
|
53580
|
-
fs48.writeFileSync(target, f4.content);
|
|
53581
|
-
}
|
|
53582
|
-
}
|
|
53583
|
-
return root;
|
|
53584
|
-
}
|
|
53585
|
-
function runHarnessInstall3(harnessId, components, opts, agentName) {
|
|
53586
|
-
if (harnessId === "claude-code")
|
|
53587
|
-
return installClaudeCodeWithCtx(components, opts, agentName);
|
|
53588
|
-
if (harnessId === "codex")
|
|
53589
|
-
return installCodexWithCtx(components, opts, agentName);
|
|
53590
|
-
if (harnessId === "kafka")
|
|
53591
|
-
return installKafkaWithCtx(components, opts, agentName);
|
|
53592
|
-
return getAdapter(harnessId).install(components, opts);
|
|
53593
|
-
}
|
|
53594
|
-
function materializeInstructions2(cwd2, cloud) {
|
|
53595
|
-
for (const c2 of cloud.components) {
|
|
53596
|
-
if (c2.type !== "instruction")
|
|
53597
|
-
continue;
|
|
53598
|
-
const body = c2.files[0]?.content ?? "";
|
|
53599
|
-
if (!body.trim())
|
|
53600
|
-
continue;
|
|
53601
|
-
fs48.writeFileSync(path51.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
|
|
53602
|
-
return;
|
|
53603
|
-
}
|
|
53604
|
-
}
|
|
53605
|
-
function buildManifestFromCloud(cloud, agent) {
|
|
53606
|
-
const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
|
|
53607
|
-
const meta = c2.meta ?? {};
|
|
53608
|
-
if (meta.name && meta.name.includes("/")) {
|
|
53609
|
-
return {
|
|
53610
|
-
source: meta.version ? `registry:${meta.name}@${meta.version}` : `registry:${meta.name}`
|
|
53611
|
-
};
|
|
53612
|
-
}
|
|
53613
|
-
return { source: `registry:${c2.slug}` };
|
|
53614
|
-
});
|
|
53615
|
-
const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
|
|
53616
|
-
const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
|
|
53617
|
-
const payload = (c2.meta ?? {}).mcp ?? {};
|
|
53618
|
-
const entry = { name: c2.slug };
|
|
53619
|
-
if (typeof payload.url === "string")
|
|
53620
|
-
entry.url = payload.url;
|
|
53621
|
-
if (typeof payload.command === "string")
|
|
53622
|
-
entry.command = payload.command;
|
|
53623
|
-
if (Array.isArray(payload.args))
|
|
53624
|
-
entry.args = payload.args.map(String);
|
|
53625
|
-
if (payload.env && typeof payload.env === "object")
|
|
53626
|
-
entry.env = payload.env;
|
|
53627
|
-
if (payload.headers && typeof payload.headers === "object")
|
|
53628
|
-
entry.headers = payload.headers;
|
|
53629
|
-
if (typeof payload.is_enabled === "boolean")
|
|
53630
|
-
entry.is_enabled = payload.is_enabled;
|
|
53631
|
-
return entry;
|
|
53632
|
-
});
|
|
53633
|
-
return {
|
|
53634
|
-
schema: 1,
|
|
53635
|
-
agent: {
|
|
53636
|
-
name: agent.name,
|
|
53637
|
-
...agent.tagline ? { tagline: agent.tagline } : {}
|
|
53638
|
-
},
|
|
53639
|
-
...hasInstructions ? { instructions: { file: DEFAULT_INSTRUCTIONS_FILE } } : {},
|
|
53640
|
-
skills,
|
|
53641
|
-
mcp
|
|
53642
|
-
};
|
|
53643
|
-
}
|
|
53644
|
-
async function pullAgentSecrets(cwd2, agentId) {
|
|
53645
|
-
try {
|
|
53646
|
-
const res = await api.getAgentSecrets(agentId);
|
|
53647
|
-
const secrets = res.secrets ?? {};
|
|
53648
|
-
if (Object.keys(secrets).length > 0) {
|
|
53649
|
-
writeLocalSecrets(cwd2, secrets);
|
|
53650
|
-
}
|
|
53651
|
-
} catch (err) {
|
|
53652
|
-
if (err instanceof ApiError && err.status !== 404) {
|
|
53653
|
-
f2.warn(`Skipped secrets for agent ${agentId}: ${err.message}`);
|
|
53654
|
-
}
|
|
53655
|
-
}
|
|
53656
|
-
}
|
|
53657
|
-
|
|
53658
54308
|
// src/cli/orchestration-pull.ts
|
|
53659
54309
|
async function runOrchestrationPull(cwd2, args) {
|
|
53660
54310
|
banner("orchestration pull — fetch orchestration + all member agents");
|
|
@@ -53666,8 +54316,8 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53666
54316
|
orchId = args.orchestrationId;
|
|
53667
54317
|
} else {
|
|
53668
54318
|
f2.warn("This folder is not linked to any orchestration.");
|
|
53669
|
-
f2.info(`Run ${
|
|
53670
|
-
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.`);
|
|
53671
54321
|
return;
|
|
53672
54322
|
}
|
|
53673
54323
|
const sp = de();
|
|
@@ -53678,29 +54328,29 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53678
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"}.`);
|
|
53679
54329
|
} catch (err) {
|
|
53680
54330
|
sp.stop("Failed.");
|
|
53681
|
-
|
|
54331
|
+
handleApiError6(err);
|
|
53682
54332
|
return;
|
|
53683
54333
|
}
|
|
53684
54334
|
const planLines = [];
|
|
53685
54335
|
planLines.push("");
|
|
53686
|
-
planLines.push(` ${
|
|
54336
|
+
planLines.push(` ${import_picocolors33.default.bold(cloud.name)} ${import_picocolors33.default.dim(`(${cloud.id})`)}`);
|
|
53687
54337
|
if (cloud.description)
|
|
53688
|
-
planLines.push(` ${
|
|
54338
|
+
planLines.push(` ${import_picocolors33.default.dim(cloud.description)}`);
|
|
53689
54339
|
planLines.push("");
|
|
53690
|
-
planLines.push(` ${
|
|
54340
|
+
planLines.push(` ${import_picocolors33.default.dim("members:")}`);
|
|
53691
54341
|
for (const m3 of cloud.members) {
|
|
53692
54342
|
const skipped = !m3.manifest;
|
|
53693
|
-
const tail = skipped ?
|
|
53694
|
-
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}`);
|
|
53695
54345
|
}
|
|
53696
54346
|
if (cloud.edges.length) {
|
|
53697
54347
|
planLines.push("");
|
|
53698
|
-
planLines.push(` ${
|
|
54348
|
+
planLines.push(` ${import_picocolors33.default.dim("edges:")}`);
|
|
53699
54349
|
for (const e2 of cloud.edges) {
|
|
53700
54350
|
const from = e2.from_slug ?? e2.from_agent_id;
|
|
53701
54351
|
const to2 = e2.to_slug ?? e2.to_agent_id;
|
|
53702
|
-
const desc = e2.description ? ` ${
|
|
53703
|
-
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}`);
|
|
53704
54354
|
}
|
|
53705
54355
|
}
|
|
53706
54356
|
planLines.push("");
|
|
@@ -53709,7 +54359,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53709
54359
|
const isRefresh = !!existingLink;
|
|
53710
54360
|
if (!args.yes && !isRefresh) {
|
|
53711
54361
|
const ok = await se({
|
|
53712
|
-
message: `Pull into ${
|
|
54362
|
+
message: `Pull into ${import_picocolors33.default.bold(cwd2)}?`,
|
|
53713
54363
|
initialValue: true
|
|
53714
54364
|
});
|
|
53715
54365
|
if (!ensureNotCancelled(ok)) {
|
|
@@ -53750,7 +54400,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53750
54400
|
scope: "project",
|
|
53751
54401
|
pullSecrets: true
|
|
53752
54402
|
});
|
|
53753
|
-
memberSp.stop(`Installed ${
|
|
54403
|
+
memberSp.stop(`Installed ${import_picocolors33.default.bold(m3.slug)} ${import_picocolors33.default.dim(`(${m3.manifest.components.length} components)`)}.`);
|
|
53754
54404
|
installedMembers.push({
|
|
53755
54405
|
agent_id: m3.agent_id,
|
|
53756
54406
|
slug: m3.slug,
|
|
@@ -53805,9 +54455,9 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53805
54455
|
payload_schema: e2.payload_schema ?? {}
|
|
53806
54456
|
}))
|
|
53807
54457
|
});
|
|
53808
|
-
$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)`)}.`);
|
|
53809
54459
|
}
|
|
53810
|
-
function
|
|
54460
|
+
function handleApiError6(err) {
|
|
53811
54461
|
if (err instanceof ApiError) {
|
|
53812
54462
|
if (err.status === 401) {
|
|
53813
54463
|
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
@@ -53822,18 +54472,18 @@ function handleApiError5(err) {
|
|
|
53822
54472
|
}
|
|
53823
54473
|
|
|
53824
54474
|
// src/cli/orchestration-push.ts
|
|
53825
|
-
var
|
|
54475
|
+
var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
53826
54476
|
async function runOrchestrationPush(cwd2, args) {
|
|
53827
54477
|
banner("orchestration push — recursively push each member, then update the graph");
|
|
53828
54478
|
const link2 = readOrchLink(cwd2);
|
|
53829
54479
|
if (!link2) {
|
|
53830
54480
|
f2.warn("This folder is not linked to any orchestration.");
|
|
53831
|
-
f2.info(`Run ${
|
|
54481
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
53832
54482
|
return;
|
|
53833
54483
|
}
|
|
53834
54484
|
if (!hasOrchManifest(cwd2)) {
|
|
53835
|
-
f2.warn(`No ${
|
|
53836
|
-
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.`);
|
|
53837
54487
|
return;
|
|
53838
54488
|
}
|
|
53839
54489
|
let manifest;
|
|
@@ -53846,15 +54496,15 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53846
54496
|
const memberSlugs = new Set(manifest.members.map((m3) => m3.slug));
|
|
53847
54497
|
for (const e2 of manifest.edges) {
|
|
53848
54498
|
if (!memberSlugs.has(e2.from)) {
|
|
53849
|
-
f2.error(`Edge from "${
|
|
54499
|
+
f2.error(`Edge from "${import_picocolors34.default.bold(e2.from)}" references a slug that isn't in members.`);
|
|
53850
54500
|
return;
|
|
53851
54501
|
}
|
|
53852
54502
|
if (!memberSlugs.has(e2.to)) {
|
|
53853
|
-
f2.error(`Edge to "${
|
|
54503
|
+
f2.error(`Edge to "${import_picocolors34.default.bold(e2.to)}" references a slug that isn't in members.`);
|
|
53854
54504
|
return;
|
|
53855
54505
|
}
|
|
53856
54506
|
if (e2.from === e2.to) {
|
|
53857
|
-
f2.error(`Edge ${
|
|
54507
|
+
f2.error(`Edge ${import_picocolors34.default.bold(e2.from)} → ${import_picocolors34.default.bold(e2.to)}: self-loops are not allowed.`);
|
|
53858
54508
|
return;
|
|
53859
54509
|
}
|
|
53860
54510
|
}
|
|
@@ -53871,17 +54521,17 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53871
54521
|
}
|
|
53872
54522
|
if (missing.length) {
|
|
53873
54523
|
f2.error(`These members have no local checkout (expected at agents/<slug>/.brainbase/link.json): ${missing.join(", ")}.`);
|
|
53874
|
-
f2.info(`Run ${
|
|
54524
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to materialise the missing folders.`);
|
|
53875
54525
|
return;
|
|
53876
54526
|
}
|
|
53877
54527
|
const plan = [""];
|
|
53878
|
-
plan.push(` ${
|
|
53879
|
-
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"}`)}`);
|
|
53880
54530
|
plan.push("");
|
|
53881
54531
|
if (!args.graphOnly) {
|
|
53882
|
-
plan.push(` ${
|
|
54532
|
+
plan.push(` ${import_picocolors34.default.dim("per-member agent push:")}`);
|
|
53883
54533
|
for (const m3 of manifest.members) {
|
|
53884
|
-
plan.push(` ${
|
|
54534
|
+
plan.push(` ${import_picocolors34.default.cyan("•")} ${import_picocolors34.default.bold(m3.slug)}`);
|
|
53885
54535
|
}
|
|
53886
54536
|
plan.push("");
|
|
53887
54537
|
}
|
|
@@ -53901,7 +54551,7 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53901
54551
|
for (const m3 of manifest.members) {
|
|
53902
54552
|
const dir = memberDir(cwd2, m3.slug);
|
|
53903
54553
|
console.log("");
|
|
53904
|
-
console.log(`${
|
|
54554
|
+
console.log(`${import_picocolors34.default.dim("───")} ${import_picocolors34.default.bold(m3.slug)} ${import_picocolors34.default.dim("───")}`);
|
|
53905
54555
|
try {
|
|
53906
54556
|
await runAgentPush(dir, { yes: true });
|
|
53907
54557
|
} catch (err) {
|
|
@@ -53952,10 +54602,10 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53952
54602
|
$e(`Pushed ${link2.name} at revision ${updated.revision}.`);
|
|
53953
54603
|
} catch (err) {
|
|
53954
54604
|
sp.stop("Failed.");
|
|
53955
|
-
|
|
54605
|
+
handleApiError7(err);
|
|
53956
54606
|
}
|
|
53957
54607
|
}
|
|
53958
|
-
function
|
|
54608
|
+
function handleApiError7(err) {
|
|
53959
54609
|
if (err instanceof ApiError) {
|
|
53960
54610
|
if (err.status === 401) {
|
|
53961
54611
|
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
@@ -53963,7 +54613,7 @@ function handleApiError6(err) {
|
|
|
53963
54613
|
f2.error("You do not have access to this orchestration.");
|
|
53964
54614
|
} else if (err.status === 409) {
|
|
53965
54615
|
f2.error(err.message);
|
|
53966
|
-
f2.info(`Run ${
|
|
54616
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to reconcile, then push again.`);
|
|
53967
54617
|
} else {
|
|
53968
54618
|
f2.error(err.message);
|
|
53969
54619
|
}
|
|
@@ -53973,13 +54623,13 @@ function handleApiError6(err) {
|
|
|
53973
54623
|
}
|
|
53974
54624
|
|
|
53975
54625
|
// src/cli/orchestration-status.ts
|
|
53976
|
-
var
|
|
54626
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
53977
54627
|
async function runOrchestrationStatus(cwd2) {
|
|
53978
54628
|
banner("orchestration status — what changed locally, remotely, both");
|
|
53979
54629
|
const link2 = readOrchLink(cwd2);
|
|
53980
54630
|
if (!link2) {
|
|
53981
54631
|
f2.warn("This folder is not linked to any orchestration.");
|
|
53982
|
-
f2.info(`Run ${
|
|
54632
|
+
f2.info(`Run ${import_picocolors35.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
53983
54633
|
return;
|
|
53984
54634
|
}
|
|
53985
54635
|
const localManifest = hasOrchManifest(cwd2) ? readOrchManifest(cwd2) : null;
|
|
@@ -54001,20 +54651,20 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
54001
54651
|
}
|
|
54002
54652
|
const lines = [];
|
|
54003
54653
|
lines.push("");
|
|
54004
|
-
lines.push(` ${
|
|
54005
|
-
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"}`);
|
|
54006
54656
|
lines.push("");
|
|
54007
54657
|
const cloudMemberSet = new Set(cloud.members.map((m3) => m3.slug));
|
|
54008
54658
|
const localMemberSet = new Set((localManifest?.members ?? []).map((m3) => m3.slug));
|
|
54009
54659
|
const membersAdded = [...localMemberSet].filter((s3) => !cloudMemberSet.has(s3));
|
|
54010
54660
|
const membersRemoved = [...cloudMemberSet].filter((s3) => !localMemberSet.has(s3));
|
|
54011
54661
|
if (membersAdded.length || membersRemoved.length) {
|
|
54012
|
-
lines.push(` ${
|
|
54662
|
+
lines.push(` ${import_picocolors35.default.bold("members")}`);
|
|
54013
54663
|
for (const slug of membersAdded) {
|
|
54014
|
-
lines.push(` ${
|
|
54664
|
+
lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${import_picocolors35.default.bold(slug)}`);
|
|
54015
54665
|
}
|
|
54016
54666
|
for (const slug of membersRemoved) {
|
|
54017
|
-
lines.push(` ${
|
|
54667
|
+
lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${import_picocolors35.default.bold(slug)}`);
|
|
54018
54668
|
}
|
|
54019
54669
|
lines.push("");
|
|
54020
54670
|
}
|
|
@@ -54029,11 +54679,11 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
54029
54679
|
const edgesAdded = [...localEdges.keys()].filter((k3) => !cloudEdges.has(k3));
|
|
54030
54680
|
const edgesRemoved = [...cloudEdges.keys()].filter((k3) => !localEdges.has(k3));
|
|
54031
54681
|
if (edgesAdded.length || edgesRemoved.length) {
|
|
54032
|
-
lines.push(` ${
|
|
54682
|
+
lines.push(` ${import_picocolors35.default.bold("edges")}`);
|
|
54033
54683
|
for (const k3 of edgesAdded)
|
|
54034
|
-
lines.push(` ${
|
|
54684
|
+
lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${k3}`);
|
|
54035
54685
|
for (const k3 of edgesRemoved)
|
|
54036
|
-
lines.push(` ${
|
|
54686
|
+
lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${k3}`);
|
|
54037
54687
|
lines.push("");
|
|
54038
54688
|
}
|
|
54039
54689
|
const lockByAgentId = new Map((lock?.members ?? []).map((m3) => [m3.agent_id, m3]));
|
|
@@ -54055,28 +54705,28 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
54055
54705
|
}
|
|
54056
54706
|
}
|
|
54057
54707
|
if (memberDrift.length) {
|
|
54058
|
-
lines.push(` ${
|
|
54708
|
+
lines.push(` ${import_picocolors35.default.bold("member content drift")}`);
|
|
54059
54709
|
for (const d3 of memberDrift) {
|
|
54060
|
-
lines.push(` ${
|
|
54710
|
+
lines.push(` ${import_picocolors35.default.cyan("?")} ${import_picocolors35.default.bold(d3.slug)} ${import_picocolors35.default.dim("— " + d3.reason)}`);
|
|
54061
54711
|
}
|
|
54062
|
-
lines.push(` ${
|
|
54712
|
+
lines.push(` ${import_picocolors35.default.dim("cd into each member folder and run")} ${import_picocolors35.default.cyan("brainbase agent status")}`);
|
|
54063
54713
|
lines.push("");
|
|
54064
54714
|
}
|
|
54065
54715
|
if (!membersAdded.length && !membersRemoved.length && !edgesAdded.length && !edgesRemoved.length && !memberDrift.length) {
|
|
54066
|
-
lines.push(` ${
|
|
54716
|
+
lines.push(` ${import_picocolors35.default.green("✓")} everything is in sync`);
|
|
54067
54717
|
lines.push("");
|
|
54068
54718
|
console.log(lines.join(`
|
|
54069
54719
|
`));
|
|
54070
54720
|
return;
|
|
54071
54721
|
}
|
|
54072
|
-
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")}`);
|
|
54073
54723
|
lines.push("");
|
|
54074
54724
|
console.log(lines.join(`
|
|
54075
54725
|
`));
|
|
54076
54726
|
}
|
|
54077
54727
|
|
|
54078
54728
|
// src/cli/orchestration-list.ts
|
|
54079
|
-
var
|
|
54729
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
54080
54730
|
async function runOrchestrationList(args) {
|
|
54081
54731
|
banner("orchestration list — orchestrations under a team");
|
|
54082
54732
|
let orgId = args.orgId;
|
|
@@ -54086,7 +54736,7 @@ async function runOrchestrationList(args) {
|
|
|
54086
54736
|
try {
|
|
54087
54737
|
orgs = await api.listOrgs();
|
|
54088
54738
|
} catch (err) {
|
|
54089
|
-
|
|
54739
|
+
handleApiError8(err);
|
|
54090
54740
|
return;
|
|
54091
54741
|
}
|
|
54092
54742
|
if (orgs.length === 0) {
|
|
@@ -54108,7 +54758,7 @@ async function runOrchestrationList(args) {
|
|
|
54108
54758
|
try {
|
|
54109
54759
|
teams = await api.listTeams(orgId);
|
|
54110
54760
|
} catch (err) {
|
|
54111
|
-
|
|
54761
|
+
handleApiError8(err);
|
|
54112
54762
|
return;
|
|
54113
54763
|
}
|
|
54114
54764
|
if (teams.length === 0) {
|
|
@@ -54133,7 +54783,7 @@ async function runOrchestrationList(args) {
|
|
|
54133
54783
|
sp.stop(`${items.length} orchestration${items.length === 1 ? "" : "s"}.`);
|
|
54134
54784
|
} catch (err) {
|
|
54135
54785
|
sp.stop("Failed.");
|
|
54136
|
-
|
|
54786
|
+
handleApiError8(err);
|
|
54137
54787
|
return;
|
|
54138
54788
|
}
|
|
54139
54789
|
if (items.length === 0) {
|
|
@@ -54142,18 +54792,18 @@ async function runOrchestrationList(args) {
|
|
|
54142
54792
|
}
|
|
54143
54793
|
const lines = [""];
|
|
54144
54794
|
for (const o2 of items) {
|
|
54145
|
-
lines.push(` ${
|
|
54795
|
+
lines.push(` ${import_picocolors36.default.bold(o2.name)} ${import_picocolors36.default.dim(o2.id)}`);
|
|
54146
54796
|
if (o2.description)
|
|
54147
|
-
lines.push(` ${
|
|
54148
|
-
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"}`)}`);
|
|
54149
54799
|
lines.push("");
|
|
54150
54800
|
}
|
|
54151
|
-
lines.push(` ${
|
|
54801
|
+
lines.push(` ${import_picocolors36.default.dim("pull one with")} ${import_picocolors36.default.cyan("brainbase orchestration pull <id>")}`);
|
|
54152
54802
|
lines.push("");
|
|
54153
54803
|
console.log(lines.join(`
|
|
54154
54804
|
`));
|
|
54155
54805
|
}
|
|
54156
|
-
function
|
|
54806
|
+
function handleApiError8(err) {
|
|
54157
54807
|
if (err instanceof ApiError) {
|
|
54158
54808
|
if (err.status === 401) {
|
|
54159
54809
|
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
@@ -54204,26 +54854,26 @@ async function runOrchestration(cwd2, sub, args, opts) {
|
|
|
54204
54854
|
function printHelp2() {
|
|
54205
54855
|
const out = [];
|
|
54206
54856
|
out.push("");
|
|
54207
|
-
out.push(` ${
|
|
54857
|
+
out.push(` ${import_picocolors37.default.bold("brainbase orchestration")} ${import_picocolors37.default.dim("<sub> [options]")}`);
|
|
54208
54858
|
out.push("");
|
|
54209
|
-
out.push(` ${
|
|
54210
|
-
out.push(` ${
|
|
54211
|
-
out.push(` ${
|
|
54212
|
-
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")}`);
|
|
54213
54863
|
out.push("");
|
|
54214
|
-
out.push(` ${
|
|
54215
|
-
out.push(` ${
|
|
54216
|
-
out.push(` ${
|
|
54217
|
-
out.push(` ${
|
|
54218
|
-
out.push(` ${
|
|
54219
|
-
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)`);
|
|
54220
54870
|
out.push("");
|
|
54221
54871
|
console.log(out.join(`
|
|
54222
54872
|
`));
|
|
54223
54873
|
}
|
|
54224
54874
|
|
|
54225
54875
|
// src/cli/run.ts
|
|
54226
|
-
import { spawn as
|
|
54876
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
54227
54877
|
async function runRun(cwd2, args) {
|
|
54228
54878
|
const cleaned = args[0] === "--" ? args.slice(1) : args;
|
|
54229
54879
|
if (cleaned.length === 0) {
|
|
@@ -54235,7 +54885,7 @@ async function runRun(cwd2, args) {
|
|
|
54235
54885
|
const [cmd, ...cmdArgs] = cleaned;
|
|
54236
54886
|
const secrets = readLocalSecrets(cwd2);
|
|
54237
54887
|
const env3 = { ...process.env, ...secrets };
|
|
54238
|
-
const child =
|
|
54888
|
+
const child = spawn3(cmd, cmdArgs, {
|
|
54239
54889
|
cwd: cwd2,
|
|
54240
54890
|
env: env3,
|
|
54241
54891
|
stdio: "inherit",
|
|
@@ -54261,16 +54911,16 @@ async function runRun(cwd2, args) {
|
|
|
54261
54911
|
}
|
|
54262
54912
|
|
|
54263
54913
|
// src/cli/publish.ts
|
|
54264
|
-
var
|
|
54914
|
+
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
54265
54915
|
async function runPublish(cwd2, _args) {
|
|
54266
54916
|
banner("publish — send your changes to the team");
|
|
54267
54917
|
const link2 = readLink(cwd2);
|
|
54268
54918
|
if (!link2) {
|
|
54269
54919
|
f2.warn("This folder is not linked to any agent.");
|
|
54270
|
-
f2.info(`Run ${
|
|
54920
|
+
f2.info(`Run ${import_picocolors38.default.cyan("brainbase link")} first.`);
|
|
54271
54921
|
return;
|
|
54272
54922
|
}
|
|
54273
|
-
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.`);
|
|
54274
54924
|
}
|
|
54275
54925
|
|
|
54276
54926
|
// src/ui/ink/StatusCard.tsx
|
|
@@ -54568,7 +55218,7 @@ async function runStatus(cwd2) {
|
|
|
54568
55218
|
}
|
|
54569
55219
|
|
|
54570
55220
|
// src/cli/token.ts
|
|
54571
|
-
var
|
|
55221
|
+
var import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
54572
55222
|
|
|
54573
55223
|
// src/ui/ink/TokenCards.tsx
|
|
54574
55224
|
var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
|
|
@@ -54862,7 +55512,7 @@ async function runTokenRevoke(args) {
|
|
|
54862
55512
|
}
|
|
54863
55513
|
if (!args.yes) {
|
|
54864
55514
|
const ok = await se({
|
|
54865
|
-
message: `Revoke token ${
|
|
55515
|
+
message: `Revoke token ${import_picocolors39.default.bold(args.id)}? CIs and machines using it will stop working.`,
|
|
54866
55516
|
initialValue: false
|
|
54867
55517
|
});
|
|
54868
55518
|
if (!ensureNotCancelled(ok))
|
|
@@ -54877,7 +55527,7 @@ async function runTokenRevoke(args) {
|
|
|
54877
55527
|
}
|
|
54878
55528
|
async function runTokenClear() {
|
|
54879
55529
|
if (!readToken()) {
|
|
54880
|
-
console.log(
|
|
55530
|
+
console.log(import_picocolors39.default.dim("No local token stored."));
|
|
54881
55531
|
return;
|
|
54882
55532
|
}
|
|
54883
55533
|
clearToken();
|
|
@@ -54928,17 +55578,17 @@ async function runToken(sub, rest, args) {
|
|
|
54928
55578
|
function printTokenHelp() {
|
|
54929
55579
|
const out = [];
|
|
54930
55580
|
out.push("");
|
|
54931
|
-
out.push(` ${
|
|
55581
|
+
out.push(` ${import_picocolors39.default.bold("brainbase token")} ${import_picocolors39.default.dim("<command>")}`);
|
|
54932
55582
|
out.push("");
|
|
54933
|
-
out.push(` ${
|
|
54934
|
-
out.push(` ${
|
|
54935
|
-
out.push(` ${
|
|
54936
|
-
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)")}`);
|
|
54937
55587
|
out.push("");
|
|
54938
|
-
out.push(` ${
|
|
54939
|
-
out.push(` ${
|
|
54940
|
-
out.push(` ${
|
|
54941
|
-
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")}`);
|
|
54942
55592
|
out.push("");
|
|
54943
55593
|
console.log(out.join(`
|
|
54944
55594
|
`));
|
|
@@ -54958,89 +55608,90 @@ var PROTECTED = new Set([
|
|
|
54958
55608
|
function help() {
|
|
54959
55609
|
const out = [];
|
|
54960
55610
|
out.push("");
|
|
54961
|
-
out.push(` ${brandTint("◆")} ${
|
|
54962
|
-
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")}`);
|
|
54963
55613
|
out.push("");
|
|
54964
55614
|
out.push(divider("USAGE"));
|
|
54965
55615
|
out.push("");
|
|
54966
|
-
out.push(` ${
|
|
55616
|
+
out.push(` ${import_picocolors40.default.bold("brainbase")} ${import_picocolors40.default.dim("<command> [options]")}`);
|
|
54967
55617
|
out.push("");
|
|
54968
55618
|
out.push(divider("AUTH"));
|
|
54969
55619
|
out.push("");
|
|
54970
|
-
out.push(` ${
|
|
54971
|
-
out.push(` ${
|
|
54972
|
-
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")}`);
|
|
54973
55623
|
out.push("");
|
|
54974
55624
|
out.push(divider("LINKED AGENT"));
|
|
54975
55625
|
out.push("");
|
|
54976
|
-
out.push(` ${
|
|
54977
|
-
out.push(` ${
|
|
54978
|
-
out.push(` ${
|
|
54979
|
-
out.push(` ${
|
|
54980
|
-
out.push(` ${
|
|
54981
|
-
out.push(` ${
|
|
54982
|
-
out.push(` ${
|
|
54983
|
-
out.push(` ${
|
|
54984
|
-
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")}`);
|
|
54985
55636
|
out.push("");
|
|
54986
55637
|
out.push(divider("ORCHESTRATIONS"));
|
|
54987
55638
|
out.push("");
|
|
54988
|
-
out.push(` ${
|
|
54989
|
-
out.push(` ${
|
|
54990
|
-
out.push(` ${
|
|
54991
|
-
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")}`);
|
|
54992
55643
|
out.push("");
|
|
54993
55644
|
out.push(divider("TEMPLATES"));
|
|
54994
55645
|
out.push("");
|
|
54995
|
-
out.push(` ${
|
|
54996
|
-
out.push(` ${
|
|
54997
|
-
out.push(` ${
|
|
54998
|
-
out.push(` ${
|
|
54999
|
-
out.push(` ${
|
|
55000
|
-
out.push(` ${
|
|
55001
|
-
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")}`);
|
|
55002
55653
|
out.push("");
|
|
55003
55654
|
out.push(divider("SKILLS"));
|
|
55004
55655
|
out.push("");
|
|
55005
|
-
out.push(` ${
|
|
55006
|
-
out.push(` ${
|
|
55007
|
-
out.push(` ${
|
|
55008
|
-
out.push(` ${
|
|
55009
|
-
out.push(` ${
|
|
55010
|
-
out.push(` ${
|
|
55011
|
-
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 .)")}`);
|
|
55012
55663
|
out.push("");
|
|
55013
55664
|
out.push(divider("CLI TOKENS"));
|
|
55014
55665
|
out.push("");
|
|
55015
|
-
out.push(` ${
|
|
55016
|
-
out.push(` ${
|
|
55017
|
-
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")}`);
|
|
55018
55669
|
out.push("");
|
|
55019
55670
|
out.push(divider("FLAGS"));
|
|
55020
55671
|
out.push("");
|
|
55021
|
-
out.push(` ${
|
|
55022
|
-
out.push(` ${
|
|
55023
|
-
out.push(` ${
|
|
55024
|
-
out.push(` ${
|
|
55025
|
-
out.push(` ${
|
|
55026
|
-
out.push(` ${
|
|
55027
|
-
out.push(` ${
|
|
55028
|
-
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)`);
|
|
55029
55680
|
out.push("");
|
|
55030
55681
|
out.push(divider("ENV"));
|
|
55031
55682
|
out.push("");
|
|
55032
|
-
out.push(` ${
|
|
55033
|
-
out.push(` ${
|
|
55034
|
-
out.push(` ${
|
|
55035
|
-
out.push(` ${
|
|
55036
|
-
out.push(` ${
|
|
55037
|
-
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`);
|
|
55038
55689
|
out.push("");
|
|
55039
55690
|
out.push(divider("HARNESSES"));
|
|
55040
55691
|
out.push("");
|
|
55041
|
-
out.push(` ${
|
|
55042
|
-
out.push(` ${
|
|
55043
|
-
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")}`);
|
|
55044
55695
|
out.push("");
|
|
55045
55696
|
console.log(out.join(`
|
|
55046
55697
|
`));
|
|
@@ -55084,13 +55735,13 @@ async function requireAuth(cmd) {
|
|
|
55084
55735
|
if (status.ok)
|
|
55085
55736
|
return;
|
|
55086
55737
|
console.error("");
|
|
55087
|
-
console.error(` ${brandTint("◆")} ${
|
|
55738
|
+
console.error(` ${brandTint("◆")} ${import_picocolors40.default.bold("brainbase")}`);
|
|
55088
55739
|
console.error("");
|
|
55089
|
-
console.error(` ${
|
|
55740
|
+
console.error(` ${import_picocolors40.default.red("✗")} You need to sign in to use ${import_picocolors40.default.bold("brainbase " + cmd)}.`);
|
|
55090
55741
|
if (status.reason)
|
|
55091
|
-
console.error(` ${
|
|
55742
|
+
console.error(` ${import_picocolors40.default.dim(status.reason)}`);
|
|
55092
55743
|
console.error("");
|
|
55093
|
-
console.error(` Run ${
|
|
55744
|
+
console.error(` Run ${import_picocolors40.default.cyan("brainbase login")} to connect this device.`);
|
|
55094
55745
|
console.error("");
|
|
55095
55746
|
process13.exit(1);
|
|
55096
55747
|
}
|
|
@@ -55127,6 +55778,7 @@ async function main() {
|
|
|
55127
55778
|
const agentFlag = getFlag(argv, "--agent");
|
|
55128
55779
|
const shellFlag = getFlag(argv, "--shell");
|
|
55129
55780
|
const noTracking = hasFlag2(argv, "--no-tracking");
|
|
55781
|
+
const forceFlag = hasFlag2(argv, "--force");
|
|
55130
55782
|
const graphOnlyFlag = hasFlag2(argv, "--graph-only");
|
|
55131
55783
|
const nameFlag = getFlag(argv, "--name");
|
|
55132
55784
|
const skillVersionFlag = getFlag(argv, "--skill-version");
|
|
@@ -55211,7 +55863,8 @@ async function main() {
|
|
|
55211
55863
|
tagline: taglineFlag,
|
|
55212
55864
|
orgId: orgIdFlag,
|
|
55213
55865
|
teamId: teamIdFlag,
|
|
55214
|
-
noTracking
|
|
55866
|
+
noTracking,
|
|
55867
|
+
force: forceFlag
|
|
55215
55868
|
});
|
|
55216
55869
|
break;
|
|
55217
55870
|
}
|
|
@@ -55242,7 +55895,7 @@ async function main() {
|
|
|
55242
55895
|
process13.exit(1);
|
|
55243
55896
|
}
|
|
55244
55897
|
} catch (err) {
|
|
55245
|
-
console.error(
|
|
55898
|
+
console.error(import_picocolors40.default.red(`
|
|
55246
55899
|
${err.message}`));
|
|
55247
55900
|
if (process13.env.BRAINBASE_DEBUG)
|
|
55248
55901
|
console.error(err.stack);
|