@brainbase-labs/cli 0.4.2 → 0.6.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 +1532 -581
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28564,9 +28564,9 @@ 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
|
-
import
|
|
28569
|
+
import fs51 from "node:fs";
|
|
28570
28570
|
|
|
28571
28571
|
// src/cli/template.ts
|
|
28572
28572
|
var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
@@ -50759,11 +50759,192 @@ async function runWhoami() {
|
|
|
50759
50759
|
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
50760
50760
|
|
|
50761
50761
|
// src/core/link.ts
|
|
50762
|
+
import path43 from "node:path";
|
|
50763
|
+
import fs40 from "node:fs";
|
|
50764
|
+
|
|
50765
|
+
// src/core/agent-manifest.ts
|
|
50762
50766
|
import path42 from "node:path";
|
|
50763
50767
|
import fs39 from "node:fs";
|
|
50768
|
+
var import_yaml2 = __toESM(require_dist(), 1);
|
|
50769
|
+
var AGENT_MANIFEST_FILE = "brainbase.agent.yaml";
|
|
50770
|
+
var LEGACY_AGENT_MANIFEST_FILE = "brainbase.yaml";
|
|
50771
|
+
var DEFAULT_INSTRUCTIONS_FILE = ".brainbase/instructions.md";
|
|
50772
|
+
var DEFAULT_ENTRYPOINT_FILE = ".brainbase/entrypoint.sh";
|
|
50773
|
+
var DEFAULT_PLAYBOOKS_DIR = ".brainbase/playbooks";
|
|
50774
|
+
var REGISTRY_SOURCE_RE = /^registry:(?:([a-z0-9_-]+)\/)?([a-z0-9_-]+)(?:@(.+))?$/i;
|
|
50775
|
+
function parseSkillSource2(raw) {
|
|
50776
|
+
if (!raw || typeof raw !== "string") {
|
|
50777
|
+
throw new Error("Skill source must be a non-empty string");
|
|
50778
|
+
}
|
|
50779
|
+
const m3 = raw.match(REGISTRY_SOURCE_RE);
|
|
50780
|
+
if (m3) {
|
|
50781
|
+
return {
|
|
50782
|
+
kind: "registry",
|
|
50783
|
+
...m3[1] ? { creator: m3[1] } : {},
|
|
50784
|
+
slug: m3[2],
|
|
50785
|
+
version: m3[3]
|
|
50786
|
+
};
|
|
50787
|
+
}
|
|
50788
|
+
if (raw.startsWith("./") || raw.startsWith("../") || raw.startsWith("/")) {
|
|
50789
|
+
return { kind: "local", path: raw };
|
|
50790
|
+
}
|
|
50791
|
+
throw new Error(`Unrecognized skill source "${raw}". Expected "registry:creator/slug[@version]", "registry:slug", or a relative path starting with "./".`);
|
|
50792
|
+
}
|
|
50793
|
+
var AgentMetaSchema = exports_external.object({
|
|
50794
|
+
name: exports_external.string().min(1),
|
|
50795
|
+
tagline: exports_external.string().optional()
|
|
50796
|
+
});
|
|
50797
|
+
var InstructionsSchema = exports_external.object({
|
|
50798
|
+
file: exports_external.string().min(1).optional(),
|
|
50799
|
+
text: exports_external.string().optional()
|
|
50800
|
+
}).refine((v3) => v3.file !== undefined || v3.text !== undefined, {
|
|
50801
|
+
message: "instructions must set either `file` or `text`"
|
|
50802
|
+
});
|
|
50803
|
+
var EntrypointSchema = exports_external.object({
|
|
50804
|
+
file: exports_external.string().min(1).optional(),
|
|
50805
|
+
commands: exports_external.array(exports_external.string().min(1)).optional(),
|
|
50806
|
+
text: exports_external.string().optional()
|
|
50807
|
+
}).refine((v3) => {
|
|
50808
|
+
const set = [v3.file, v3.commands, v3.text].filter((x3) => x3 !== undefined);
|
|
50809
|
+
return set.length === 1;
|
|
50810
|
+
}, {
|
|
50811
|
+
message: "entrypoint must set exactly one of `file`, `commands`, or `text`"
|
|
50812
|
+
});
|
|
50813
|
+
var PlaybookContentSchema = exports_external.object({
|
|
50814
|
+
file: exports_external.string().min(1).optional(),
|
|
50815
|
+
text: exports_external.string().optional()
|
|
50816
|
+
}).refine((v3) => v3.file !== undefined || v3.text !== undefined, {
|
|
50817
|
+
message: "playbook content must set either `file` or `text`"
|
|
50818
|
+
});
|
|
50819
|
+
var PlaybookSchema = exports_external.object({
|
|
50820
|
+
title: exports_external.string().min(1),
|
|
50821
|
+
description: exports_external.string().optional(),
|
|
50822
|
+
content: PlaybookContentSchema
|
|
50823
|
+
});
|
|
50824
|
+
var SkillEntrySchema = exports_external.object({
|
|
50825
|
+
source: exports_external.string().min(1)
|
|
50826
|
+
});
|
|
50827
|
+
var McpEntrySchema = exports_external.object({
|
|
50828
|
+
name: exports_external.string().min(1),
|
|
50829
|
+
url: exports_external.string().optional(),
|
|
50830
|
+
command: exports_external.string().optional(),
|
|
50831
|
+
args: exports_external.array(exports_external.string()).optional(),
|
|
50832
|
+
env: exports_external.record(exports_external.string()).optional(),
|
|
50833
|
+
headers: exports_external.record(exports_external.string()).optional(),
|
|
50834
|
+
is_enabled: exports_external.boolean().optional()
|
|
50835
|
+
});
|
|
50836
|
+
var AgentManifestSchema = exports_external.object({
|
|
50837
|
+
schema: exports_external.literal(1),
|
|
50838
|
+
id: exports_external.string().min(1).optional(),
|
|
50839
|
+
harness: exports_external.string().min(1).optional(),
|
|
50840
|
+
agent: AgentMetaSchema,
|
|
50841
|
+
instructions: InstructionsSchema.optional(),
|
|
50842
|
+
entrypoint: EntrypointSchema.optional(),
|
|
50843
|
+
playbooks: exports_external.array(PlaybookSchema).default([]),
|
|
50844
|
+
skills: exports_external.array(SkillEntrySchema).default([]),
|
|
50845
|
+
mcp: exports_external.array(McpEntrySchema).default([]),
|
|
50846
|
+
commands: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
50847
|
+
hooks: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
50848
|
+
files: exports_external.array(exports_external.record(exports_external.unknown())).optional()
|
|
50849
|
+
});
|
|
50850
|
+
function manifestPath(cwd2) {
|
|
50851
|
+
return path42.join(cwd2, AGENT_MANIFEST_FILE);
|
|
50852
|
+
}
|
|
50853
|
+
function existingManifestPath(cwd2) {
|
|
50854
|
+
const newPath = path42.join(cwd2, AGENT_MANIFEST_FILE);
|
|
50855
|
+
if (fs39.existsSync(newPath))
|
|
50856
|
+
return newPath;
|
|
50857
|
+
const legacy = path42.join(cwd2, LEGACY_AGENT_MANIFEST_FILE);
|
|
50858
|
+
if (fs39.existsSync(legacy))
|
|
50859
|
+
return legacy;
|
|
50860
|
+
return null;
|
|
50861
|
+
}
|
|
50862
|
+
function hasManifest(cwd2) {
|
|
50863
|
+
return existingManifestPath(cwd2) !== null;
|
|
50864
|
+
}
|
|
50865
|
+
function readManifest(cwd2) {
|
|
50866
|
+
const p2 = existingManifestPath(cwd2);
|
|
50867
|
+
if (!p2)
|
|
50868
|
+
return null;
|
|
50869
|
+
const raw = fs39.readFileSync(p2, "utf8");
|
|
50870
|
+
let parsed;
|
|
50871
|
+
try {
|
|
50872
|
+
parsed = import_yaml2.default.parse(raw);
|
|
50873
|
+
} catch (err) {
|
|
50874
|
+
throw new Error(`${path42.basename(p2)} is not valid YAML: ${err.message}`);
|
|
50875
|
+
}
|
|
50876
|
+
const result = AgentManifestSchema.safeParse(parsed);
|
|
50877
|
+
if (!result.success) {
|
|
50878
|
+
throw new Error(`${path42.basename(p2)} is invalid: ${result.error.issues.map((i) => `${i.path.join(".") || "(root)"} — ${i.message}`).join("; ")}`);
|
|
50879
|
+
}
|
|
50880
|
+
return result.data;
|
|
50881
|
+
}
|
|
50882
|
+
function writeManifest(cwd2, manifest) {
|
|
50883
|
+
const doc = new import_yaml2.default.Document;
|
|
50884
|
+
doc.contents = manifest;
|
|
50885
|
+
doc.commentBefore = ` brainbase.agent.yaml — declarative agent manifest.
|
|
50886
|
+
` + " Committed to source control. Edit by hand, then `brainbase agent push`.";
|
|
50887
|
+
const out = String(doc);
|
|
50888
|
+
fs39.writeFileSync(manifestPath(cwd2), out, "utf8");
|
|
50889
|
+
}
|
|
50890
|
+
function resolveInstructionsPath(cwd2, manifest) {
|
|
50891
|
+
if (!manifest.instructions?.file)
|
|
50892
|
+
return null;
|
|
50893
|
+
return path42.resolve(cwd2, manifest.instructions.file);
|
|
50894
|
+
}
|
|
50895
|
+
function readInstructions(cwd2, manifest) {
|
|
50896
|
+
if (!manifest.instructions)
|
|
50897
|
+
return null;
|
|
50898
|
+
if (typeof manifest.instructions.text === "string") {
|
|
50899
|
+
return manifest.instructions.text;
|
|
50900
|
+
}
|
|
50901
|
+
const p2 = resolveInstructionsPath(cwd2, manifest);
|
|
50902
|
+
if (!p2 || !fs39.existsSync(p2))
|
|
50903
|
+
return null;
|
|
50904
|
+
return fs39.readFileSync(p2, "utf8");
|
|
50905
|
+
}
|
|
50906
|
+
function resolveEntrypoint(cwd2, manifest) {
|
|
50907
|
+
const ep = manifest.entrypoint;
|
|
50908
|
+
if (!ep)
|
|
50909
|
+
return null;
|
|
50910
|
+
if (typeof ep.text === "string")
|
|
50911
|
+
return ep.text;
|
|
50912
|
+
if (Array.isArray(ep.commands)) {
|
|
50913
|
+
if (ep.commands.length === 0)
|
|
50914
|
+
return null;
|
|
50915
|
+
return ["set -euo pipefail", ...ep.commands].join(`
|
|
50916
|
+
`) + `
|
|
50917
|
+
`;
|
|
50918
|
+
}
|
|
50919
|
+
if (typeof ep.file === "string") {
|
|
50920
|
+
const p2 = path42.resolve(cwd2, ep.file);
|
|
50921
|
+
if (!fs39.existsSync(p2))
|
|
50922
|
+
return null;
|
|
50923
|
+
return fs39.readFileSync(p2, "utf8");
|
|
50924
|
+
}
|
|
50925
|
+
return null;
|
|
50926
|
+
}
|
|
50927
|
+
function resolvePlaybookContent(cwd2, entry) {
|
|
50928
|
+
const c2 = entry.content;
|
|
50929
|
+
if (typeof c2.text === "string")
|
|
50930
|
+
return c2.text;
|
|
50931
|
+
if (typeof c2.file === "string") {
|
|
50932
|
+
const p2 = path42.resolve(cwd2, c2.file);
|
|
50933
|
+
if (!fs39.existsSync(p2))
|
|
50934
|
+
return null;
|
|
50935
|
+
return fs39.readFileSync(p2, "utf8");
|
|
50936
|
+
}
|
|
50937
|
+
return null;
|
|
50938
|
+
}
|
|
50939
|
+
function slugifyPlaybookTitle(title) {
|
|
50940
|
+
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60) || "playbook";
|
|
50941
|
+
}
|
|
50942
|
+
|
|
50943
|
+
// src/core/link.ts
|
|
50764
50944
|
var LINK_DIR = ".brainbase";
|
|
50765
|
-
var
|
|
50945
|
+
var STATE_FILE = "state.json";
|
|
50766
50946
|
var SYNC_STATE_FILE = "sync-state.json";
|
|
50947
|
+
var LEGACY_LINK_FILE = "link.json";
|
|
50767
50948
|
var TrackingSchema = exports_external.object({
|
|
50768
50949
|
harness: exports_external.string(),
|
|
50769
50950
|
key_id: exports_external.string(),
|
|
@@ -50786,6 +50967,16 @@ var LinkSchema = exports_external.object({
|
|
|
50786
50967
|
harness: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
|
|
50787
50968
|
tracking: TrackingSchema.nullish().transform((v3) => v3 ?? undefined)
|
|
50788
50969
|
});
|
|
50970
|
+
var LinkStateSchema = exports_external.object({
|
|
50971
|
+
schemaVersion: exports_external.literal(1),
|
|
50972
|
+
org_id: exports_external.string().default(""),
|
|
50973
|
+
team_id: exports_external.string().default(""),
|
|
50974
|
+
slug: exports_external.string().default(""),
|
|
50975
|
+
url: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
|
|
50976
|
+
linked_at: exports_external.string(),
|
|
50977
|
+
linked_by: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
|
|
50978
|
+
tracking: TrackingSchema.nullish().transform((v3) => v3 ?? undefined)
|
|
50979
|
+
});
|
|
50789
50980
|
var SyncedComponentSchema = exports_external.object({
|
|
50790
50981
|
type: exports_external.string(),
|
|
50791
50982
|
slug: exports_external.string(),
|
|
@@ -50795,7 +50986,8 @@ var SyncedComponentSchema = exports_external.object({
|
|
|
50795
50986
|
});
|
|
50796
50987
|
var AgentMetaSnapshotSchema = exports_external.object({
|
|
50797
50988
|
name: exports_external.string(),
|
|
50798
|
-
tagline: exports_external.string().optional()
|
|
50989
|
+
tagline: exports_external.string().optional(),
|
|
50990
|
+
entrypoint: exports_external.string().optional()
|
|
50799
50991
|
});
|
|
50800
50992
|
var SyncStateSchema = exports_external.object({
|
|
50801
50993
|
schemaVersion: exports_external.literal(1),
|
|
@@ -50805,39 +50997,159 @@ var SyncStateSchema = exports_external.object({
|
|
|
50805
50997
|
components: exports_external.array(SyncedComponentSchema),
|
|
50806
50998
|
agentMeta: AgentMetaSnapshotSchema.optional()
|
|
50807
50999
|
});
|
|
50808
|
-
function
|
|
50809
|
-
return
|
|
51000
|
+
function statePath(cwd2) {
|
|
51001
|
+
return path43.join(cwd2, LINK_DIR, STATE_FILE);
|
|
50810
51002
|
}
|
|
50811
51003
|
function syncStatePath(cwd2) {
|
|
50812
|
-
return
|
|
51004
|
+
return path43.join(cwd2, LINK_DIR, SYNC_STATE_FILE);
|
|
51005
|
+
}
|
|
51006
|
+
function legacyLinkPath(cwd2) {
|
|
51007
|
+
return path43.join(cwd2, LINK_DIR, LEGACY_LINK_FILE);
|
|
51008
|
+
}
|
|
51009
|
+
function readState(cwd2) {
|
|
51010
|
+
const p2 = statePath(cwd2);
|
|
51011
|
+
if (exists(p2)) {
|
|
51012
|
+
try {
|
|
51013
|
+
return LinkStateSchema.parse(readJson(p2));
|
|
51014
|
+
} catch {
|
|
51015
|
+
return null;
|
|
51016
|
+
}
|
|
51017
|
+
}
|
|
51018
|
+
const legacy = legacyLinkPath(cwd2);
|
|
51019
|
+
if (exists(legacy)) {
|
|
51020
|
+
try {
|
|
51021
|
+
const raw = readJson(legacy);
|
|
51022
|
+
const lifted = {
|
|
51023
|
+
schemaVersion: 1,
|
|
51024
|
+
org_id: String(raw.org_id ?? ""),
|
|
51025
|
+
team_id: String(raw.team_id ?? ""),
|
|
51026
|
+
slug: String(raw.slug ?? ""),
|
|
51027
|
+
url: typeof raw.url === "string" ? raw.url : undefined,
|
|
51028
|
+
linked_at: typeof raw.linked_at === "string" ? raw.linked_at : new Date().toISOString(),
|
|
51029
|
+
linked_by: typeof raw.linked_by === "string" ? raw.linked_by : undefined,
|
|
51030
|
+
tracking: (() => {
|
|
51031
|
+
try {
|
|
51032
|
+
return TrackingSchema.parse(raw.tracking);
|
|
51033
|
+
} catch {
|
|
51034
|
+
return;
|
|
51035
|
+
}
|
|
51036
|
+
})()
|
|
51037
|
+
};
|
|
51038
|
+
try {
|
|
51039
|
+
ensureDir(path43.join(cwd2, LINK_DIR));
|
|
51040
|
+
writeJson(statePath(cwd2), lifted);
|
|
51041
|
+
ensureGitignore(cwd2);
|
|
51042
|
+
} catch {}
|
|
51043
|
+
return lifted;
|
|
51044
|
+
} catch {
|
|
51045
|
+
return null;
|
|
51046
|
+
}
|
|
51047
|
+
}
|
|
51048
|
+
return null;
|
|
51049
|
+
}
|
|
51050
|
+
function writeState(cwd2, state) {
|
|
51051
|
+
ensureDir(path43.join(cwd2, LINK_DIR));
|
|
51052
|
+
writeJson(statePath(cwd2), state);
|
|
51053
|
+
ensureGitignore(cwd2);
|
|
50813
51054
|
}
|
|
50814
51055
|
function readLink(cwd2) {
|
|
50815
|
-
|
|
50816
|
-
if (!exists(p2))
|
|
50817
|
-
return null;
|
|
51056
|
+
let manifest = null;
|
|
50818
51057
|
try {
|
|
50819
|
-
|
|
51058
|
+
manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
50820
51059
|
} catch {
|
|
50821
|
-
|
|
51060
|
+
manifest = null;
|
|
51061
|
+
}
|
|
51062
|
+
const state = readState(cwd2);
|
|
51063
|
+
if (manifest?.id) {
|
|
51064
|
+
return {
|
|
51065
|
+
schemaVersion: 1,
|
|
51066
|
+
agent_id: manifest.id,
|
|
51067
|
+
org_id: state?.org_id ?? "",
|
|
51068
|
+
team_id: state?.team_id ?? "",
|
|
51069
|
+
slug: state?.slug ?? "",
|
|
51070
|
+
name: manifest.agent.name,
|
|
51071
|
+
tagline: manifest.agent.tagline,
|
|
51072
|
+
url: state?.url,
|
|
51073
|
+
linked_at: state?.linked_at ?? new Date().toISOString(),
|
|
51074
|
+
linked_by: state?.linked_by,
|
|
51075
|
+
harness: manifest.harness,
|
|
51076
|
+
tracking: state?.tracking
|
|
51077
|
+
};
|
|
51078
|
+
}
|
|
51079
|
+
const legacy = legacyLinkPath(cwd2);
|
|
51080
|
+
if (exists(legacy)) {
|
|
51081
|
+
try {
|
|
51082
|
+
return LinkSchema.parse(readJson(legacy));
|
|
51083
|
+
} catch {
|
|
51084
|
+
return null;
|
|
51085
|
+
}
|
|
50822
51086
|
}
|
|
51087
|
+
return null;
|
|
50823
51088
|
}
|
|
50824
51089
|
function writeLink(cwd2, link2) {
|
|
50825
|
-
|
|
50826
|
-
|
|
50827
|
-
|
|
50828
|
-
|
|
50829
|
-
|
|
51090
|
+
let manifest;
|
|
51091
|
+
try {
|
|
51092
|
+
manifest = readManifest(cwd2) ?? {
|
|
51093
|
+
schema: 1,
|
|
51094
|
+
agent: { name: link2.name },
|
|
51095
|
+
playbooks: [],
|
|
51096
|
+
skills: [],
|
|
51097
|
+
mcp: []
|
|
51098
|
+
};
|
|
51099
|
+
} catch {
|
|
51100
|
+
manifest = {
|
|
51101
|
+
schema: 1,
|
|
51102
|
+
agent: { name: link2.name },
|
|
51103
|
+
playbooks: [],
|
|
51104
|
+
skills: [],
|
|
51105
|
+
mcp: []
|
|
51106
|
+
};
|
|
51107
|
+
}
|
|
51108
|
+
manifest.id = link2.agent_id;
|
|
51109
|
+
if (link2.harness)
|
|
51110
|
+
manifest.harness = link2.harness;
|
|
51111
|
+
manifest.agent.name = link2.name;
|
|
51112
|
+
if (link2.tagline)
|
|
51113
|
+
manifest.agent.tagline = link2.tagline;
|
|
51114
|
+
else
|
|
51115
|
+
delete manifest.agent.tagline;
|
|
51116
|
+
writeManifest(cwd2, manifest);
|
|
51117
|
+
const state = {
|
|
51118
|
+
schemaVersion: 1,
|
|
51119
|
+
org_id: link2.org_id,
|
|
51120
|
+
team_id: link2.team_id,
|
|
51121
|
+
slug: link2.slug,
|
|
51122
|
+
url: link2.url,
|
|
51123
|
+
linked_at: link2.linked_at,
|
|
51124
|
+
linked_by: link2.linked_by,
|
|
51125
|
+
tracking: link2.tracking
|
|
51126
|
+
};
|
|
51127
|
+
writeState(cwd2, state);
|
|
51128
|
+
const legacy = legacyLinkPath(cwd2);
|
|
51129
|
+
if (exists(legacy)) {
|
|
51130
|
+
try {
|
|
51131
|
+
fs40.rmSync(legacy);
|
|
51132
|
+
} catch {}
|
|
50830
51133
|
}
|
|
50831
|
-
writeJson(linkPath(cwd2), clean);
|
|
50832
|
-
ensureGitignore(cwd2);
|
|
50833
51134
|
}
|
|
50834
51135
|
function clearLink(cwd2) {
|
|
50835
|
-
|
|
51136
|
+
try {
|
|
51137
|
+
const m3 = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
51138
|
+
if (m3) {
|
|
51139
|
+
delete m3.id;
|
|
51140
|
+
delete m3.harness;
|
|
51141
|
+
writeManifest(cwd2, m3);
|
|
51142
|
+
}
|
|
51143
|
+
} catch {}
|
|
51144
|
+
const p2 = statePath(cwd2);
|
|
50836
51145
|
if (exists(p2))
|
|
50837
|
-
|
|
51146
|
+
fs40.rmSync(p2);
|
|
50838
51147
|
const sp = syncStatePath(cwd2);
|
|
50839
51148
|
if (exists(sp))
|
|
50840
|
-
|
|
51149
|
+
fs40.rmSync(sp);
|
|
51150
|
+
const legacy = legacyLinkPath(cwd2);
|
|
51151
|
+
if (exists(legacy))
|
|
51152
|
+
fs40.rmSync(legacy);
|
|
50841
51153
|
}
|
|
50842
51154
|
function readSyncState(cwd2) {
|
|
50843
51155
|
const p2 = syncStatePath(cwd2);
|
|
@@ -50850,22 +51162,22 @@ function readSyncState(cwd2) {
|
|
|
50850
51162
|
}
|
|
50851
51163
|
}
|
|
50852
51164
|
function writeSyncState(cwd2, state) {
|
|
50853
|
-
ensureDir(
|
|
51165
|
+
ensureDir(path43.join(cwd2, LINK_DIR));
|
|
50854
51166
|
writeJson(syncStatePath(cwd2), state);
|
|
50855
51167
|
ensureGitignore(cwd2);
|
|
50856
51168
|
}
|
|
50857
51169
|
function ensureGitignore(cwd2) {
|
|
50858
|
-
const ignorePath =
|
|
50859
|
-
const desired =
|
|
50860
|
-
|
|
51170
|
+
const ignorePath = path43.join(cwd2, LINK_DIR, ".gitignore");
|
|
51171
|
+
const desired = ["*", `!.gitignore`, ""].join(`
|
|
51172
|
+
`);
|
|
50861
51173
|
try {
|
|
50862
51174
|
if (!exists(ignorePath)) {
|
|
50863
|
-
|
|
51175
|
+
fs40.writeFileSync(ignorePath, desired);
|
|
50864
51176
|
return;
|
|
50865
51177
|
}
|
|
50866
|
-
const current =
|
|
50867
|
-
if (!current.split(/\r?\n/).some((l2) => l2.trim() ===
|
|
50868
|
-
|
|
51178
|
+
const current = fs40.readFileSync(ignorePath, "utf8");
|
|
51179
|
+
if (!current.split(/\r?\n/).some((l2) => l2.trim() === "*")) {
|
|
51180
|
+
fs40.writeFileSync(ignorePath, current.endsWith(`
|
|
50869
51181
|
`) ? current + desired : current + `
|
|
50870
51182
|
` + desired);
|
|
50871
51183
|
}
|
|
@@ -50873,15 +51185,15 @@ function ensureGitignore(cwd2) {
|
|
|
50873
51185
|
}
|
|
50874
51186
|
|
|
50875
51187
|
// src/core/route-adapters.ts
|
|
50876
|
-
import
|
|
51188
|
+
import path44 from "node:path";
|
|
50877
51189
|
import os10 from "node:os";
|
|
50878
|
-
import
|
|
51190
|
+
import fs41 from "node:fs";
|
|
50879
51191
|
var CLAUDE_ENV_KEYS = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN"];
|
|
50880
51192
|
function claudeSettingsPath(cwd2) {
|
|
50881
|
-
return
|
|
51193
|
+
return path44.join(cwd2, ".claude", "settings.json");
|
|
50882
51194
|
}
|
|
50883
51195
|
function claudeUserConfigPath() {
|
|
50884
|
-
return
|
|
51196
|
+
return path44.join(os10.homedir(), ".claude.json");
|
|
50885
51197
|
}
|
|
50886
51198
|
function ensureClaudeOnboarded() {
|
|
50887
51199
|
const file = claudeUserConfigPath();
|
|
@@ -50905,7 +51217,7 @@ var claudeRouteAdapter = {
|
|
|
50905
51217
|
settings.env = { ...settings.env ?? {} };
|
|
50906
51218
|
settings.env.ANTHROPIC_BASE_URL = target.apiBase;
|
|
50907
51219
|
settings.env.ANTHROPIC_AUTH_TOKEN = target.apiKey;
|
|
50908
|
-
ensureDir(
|
|
51220
|
+
ensureDir(path44.dirname(file));
|
|
50909
51221
|
writeJson(file, settings);
|
|
50910
51222
|
const notes = [];
|
|
50911
51223
|
if (ensureClaudeOnboarded()) {
|
|
@@ -50932,11 +51244,11 @@ var claudeRouteAdapter = {
|
|
|
50932
51244
|
delete settings.env;
|
|
50933
51245
|
}
|
|
50934
51246
|
if (snap && !snap.fileExisted && Object.keys(settings).length === 0) {
|
|
50935
|
-
|
|
50936
|
-
const dir =
|
|
51247
|
+
fs41.rmSync(file);
|
|
51248
|
+
const dir = path44.dirname(file);
|
|
50937
51249
|
try {
|
|
50938
|
-
if (
|
|
50939
|
-
|
|
51250
|
+
if (fs41.readdirSync(dir).length === 0)
|
|
51251
|
+
fs41.rmdirSync(dir);
|
|
50940
51252
|
} catch {}
|
|
50941
51253
|
return;
|
|
50942
51254
|
}
|
|
@@ -50946,20 +51258,20 @@ var claudeRouteAdapter = {
|
|
|
50946
51258
|
var CODEX_PROVIDER_KEY = "brainbase";
|
|
50947
51259
|
var CODEX_AUTH_HEADER = "Authorization";
|
|
50948
51260
|
function codexConfigPath(cwd2) {
|
|
50949
|
-
return
|
|
51261
|
+
return path44.join(cwd2, ".codex", "config.toml");
|
|
50950
51262
|
}
|
|
50951
51263
|
function readCodexConfig2(file) {
|
|
50952
51264
|
if (!exists(file))
|
|
50953
51265
|
return {};
|
|
50954
51266
|
try {
|
|
50955
|
-
return parse(
|
|
51267
|
+
return parse(fs41.readFileSync(file, "utf8"));
|
|
50956
51268
|
} catch {
|
|
50957
51269
|
return {};
|
|
50958
51270
|
}
|
|
50959
51271
|
}
|
|
50960
51272
|
function writeCodexConfig2(file, value) {
|
|
50961
|
-
ensureDir(
|
|
50962
|
-
|
|
51273
|
+
ensureDir(path44.dirname(file));
|
|
51274
|
+
fs41.writeFileSync(file, stringify(value) + `
|
|
50963
51275
|
`);
|
|
50964
51276
|
}
|
|
50965
51277
|
function ensureV1(base2) {
|
|
@@ -51015,11 +51327,11 @@ var codexRouteAdapter = {
|
|
|
51015
51327
|
}
|
|
51016
51328
|
}
|
|
51017
51329
|
if (snap && !snap.fileExisted && Object.keys(cfg).length === 0) {
|
|
51018
|
-
|
|
51019
|
-
const dir =
|
|
51330
|
+
fs41.rmSync(file);
|
|
51331
|
+
const dir = path44.dirname(file);
|
|
51020
51332
|
try {
|
|
51021
|
-
if (
|
|
51022
|
-
|
|
51333
|
+
if (fs41.readdirSync(dir).length === 0)
|
|
51334
|
+
fs41.rmdirSync(dir);
|
|
51023
51335
|
} catch {}
|
|
51024
51336
|
return;
|
|
51025
51337
|
}
|
|
@@ -51309,8 +51621,8 @@ async function runUnlink(cwd2, args) {
|
|
|
51309
51621
|
}
|
|
51310
51622
|
|
|
51311
51623
|
// src/cli/sync.ts
|
|
51312
|
-
import
|
|
51313
|
-
import
|
|
51624
|
+
import path45 from "node:path";
|
|
51625
|
+
import fs42 from "node:fs";
|
|
51314
51626
|
import os11 from "node:os";
|
|
51315
51627
|
import crypto3 from "node:crypto";
|
|
51316
51628
|
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
@@ -51504,7 +51816,7 @@ async function runSync(cwd2, args) {
|
|
|
51504
51816
|
type: c2.type,
|
|
51505
51817
|
slug: c2.slug,
|
|
51506
51818
|
scope,
|
|
51507
|
-
rootDir:
|
|
51819
|
+
rootDir: path45.join(stageRoot, c2.type, c2.slug),
|
|
51508
51820
|
description: c2.description,
|
|
51509
51821
|
meta: c2.meta,
|
|
51510
51822
|
payload: c2.meta?.mcp,
|
|
@@ -51553,11 +51865,11 @@ async function runSync(cwd2, args) {
|
|
|
51553
51865
|
if (!exists(filePath))
|
|
51554
51866
|
continue;
|
|
51555
51867
|
try {
|
|
51556
|
-
const stat =
|
|
51868
|
+
const stat = fs42.statSync(filePath);
|
|
51557
51869
|
if (stat.isDirectory())
|
|
51558
|
-
|
|
51870
|
+
fs42.rmSync(filePath, { recursive: true, force: true });
|
|
51559
51871
|
else
|
|
51560
|
-
|
|
51872
|
+
fs42.rmSync(filePath);
|
|
51561
51873
|
} catch (err) {
|
|
51562
51874
|
f2.warn(`Failed to remove ${filePath}: ${err.message}`);
|
|
51563
51875
|
}
|
|
@@ -51595,7 +51907,7 @@ async function runSync(cwd2, args) {
|
|
|
51595
51907
|
$e(`Synced ${link2.name} to revision ${manifest.revision}.`);
|
|
51596
51908
|
} finally {
|
|
51597
51909
|
try {
|
|
51598
|
-
|
|
51910
|
+
fs42.rmSync(stageRoot, { recursive: true, force: true });
|
|
51599
51911
|
} catch {}
|
|
51600
51912
|
}
|
|
51601
51913
|
}
|
|
@@ -51643,14 +51955,14 @@ function computeLocalHash(paths) {
|
|
|
51643
51955
|
if (!exists(filePath))
|
|
51644
51956
|
return null;
|
|
51645
51957
|
try {
|
|
51646
|
-
const stat =
|
|
51958
|
+
const stat = fs42.statSync(filePath);
|
|
51647
51959
|
if (stat.isFile()) {
|
|
51648
51960
|
h2.update("F " + filePath + " ");
|
|
51649
|
-
h2.update(
|
|
51961
|
+
h2.update(fs42.readFileSync(filePath));
|
|
51650
51962
|
h2.update(`
|
|
51651
51963
|
`);
|
|
51652
51964
|
} else if (stat.isDirectory()) {
|
|
51653
|
-
for (const name of
|
|
51965
|
+
for (const name of fs42.readdirSync(filePath).sort()) {
|
|
51654
51966
|
h2.update("E " + name + `
|
|
51655
51967
|
`);
|
|
51656
51968
|
}
|
|
@@ -51662,14 +51974,14 @@ function computeLocalHash(paths) {
|
|
|
51662
51974
|
return h2.digest("hex");
|
|
51663
51975
|
}
|
|
51664
51976
|
function stageManifest(components) {
|
|
51665
|
-
const root =
|
|
51977
|
+
const root = fs42.mkdtempSync(path45.join(os11.tmpdir(), "brainbase-sync-"));
|
|
51666
51978
|
for (const c2 of components) {
|
|
51667
|
-
const compDir =
|
|
51979
|
+
const compDir = path45.join(root, c2.type, c2.slug);
|
|
51668
51980
|
ensureDir(compDir);
|
|
51669
51981
|
for (const f4 of c2.files) {
|
|
51670
|
-
const target =
|
|
51671
|
-
ensureDir(
|
|
51672
|
-
|
|
51982
|
+
const target = path45.join(compDir, f4.path);
|
|
51983
|
+
ensureDir(path45.dirname(target));
|
|
51984
|
+
fs42.writeFileSync(target, f4.content);
|
|
51673
51985
|
}
|
|
51674
51986
|
}
|
|
51675
51987
|
return root;
|
|
@@ -51683,142 +51995,47 @@ function runHarnessInstall(harnessId, components, opts, agentName) {
|
|
|
51683
51995
|
}
|
|
51684
51996
|
|
|
51685
51997
|
// src/cli/agent.ts
|
|
51686
|
-
var
|
|
51998
|
+
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
51687
51999
|
|
|
51688
52000
|
// src/cli/agent-pull.ts
|
|
52001
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
51689
52002
|
import path48 from "node:path";
|
|
51690
52003
|
import fs45 from "node:fs";
|
|
51691
52004
|
import os12 from "node:os";
|
|
51692
52005
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
52006
|
+
var import_yaml3 = __toESM(require_dist(), 1);
|
|
51693
52007
|
|
|
51694
|
-
// src/core/agent-
|
|
51695
|
-
import
|
|
51696
|
-
import
|
|
51697
|
-
|
|
51698
|
-
|
|
51699
|
-
|
|
51700
|
-
|
|
51701
|
-
function
|
|
51702
|
-
|
|
51703
|
-
|
|
52008
|
+
// src/core/agent-diff.ts
|
|
52009
|
+
import path46 from "node:path";
|
|
52010
|
+
import fs43 from "node:fs";
|
|
52011
|
+
import crypto4 from "node:crypto";
|
|
52012
|
+
function compKey(type, slug) {
|
|
52013
|
+
return `${type}/${slug}`;
|
|
52014
|
+
}
|
|
52015
|
+
function hashString(s3) {
|
|
52016
|
+
return crypto4.createHash("sha256").update(s3).digest("hex");
|
|
52017
|
+
}
|
|
52018
|
+
function canonicalJson(value) {
|
|
52019
|
+
if (value === null)
|
|
52020
|
+
return "null";
|
|
52021
|
+
if (typeof value === "boolean")
|
|
52022
|
+
return value ? "true" : "false";
|
|
52023
|
+
if (typeof value === "number") {
|
|
52024
|
+
if (!Number.isFinite(value))
|
|
52025
|
+
throw new Error("Non-finite numbers are not JSON");
|
|
52026
|
+
return String(value);
|
|
51704
52027
|
}
|
|
51705
|
-
|
|
51706
|
-
|
|
51707
|
-
|
|
51708
|
-
|
|
51709
|
-
...m3[1] ? { creator: m3[1] } : {},
|
|
51710
|
-
slug: m3[2],
|
|
51711
|
-
version: m3[3]
|
|
51712
|
-
};
|
|
52028
|
+
if (typeof value === "string")
|
|
52029
|
+
return JSON.stringify(value);
|
|
52030
|
+
if (Array.isArray(value)) {
|
|
52031
|
+
return "[" + value.map(canonicalJson).join(",") + "]";
|
|
51713
52032
|
}
|
|
51714
|
-
if (
|
|
51715
|
-
|
|
52033
|
+
if (typeof value === "object") {
|
|
52034
|
+
const obj = value;
|
|
52035
|
+
const keys = Object.keys(obj).sort();
|
|
52036
|
+
return "{" + keys.map((k3) => `${JSON.stringify(k3)}:${canonicalJson(obj[k3])}`).join(",") + "}";
|
|
51716
52037
|
}
|
|
51717
|
-
throw new Error(`
|
|
51718
|
-
}
|
|
51719
|
-
var AgentMetaSchema = exports_external.object({
|
|
51720
|
-
name: exports_external.string().min(1),
|
|
51721
|
-
tagline: exports_external.string().optional()
|
|
51722
|
-
});
|
|
51723
|
-
var InstructionsSchema = exports_external.object({
|
|
51724
|
-
file: exports_external.string().min(1)
|
|
51725
|
-
});
|
|
51726
|
-
var SkillEntrySchema = exports_external.object({
|
|
51727
|
-
source: exports_external.string().min(1)
|
|
51728
|
-
});
|
|
51729
|
-
var McpEntrySchema = exports_external.object({
|
|
51730
|
-
name: exports_external.string().min(1),
|
|
51731
|
-
url: exports_external.string().optional(),
|
|
51732
|
-
command: exports_external.string().optional(),
|
|
51733
|
-
args: exports_external.array(exports_external.string()).optional(),
|
|
51734
|
-
env: exports_external.record(exports_external.string()).optional(),
|
|
51735
|
-
headers: exports_external.record(exports_external.string()).optional(),
|
|
51736
|
-
is_enabled: exports_external.boolean().optional()
|
|
51737
|
-
});
|
|
51738
|
-
var AgentManifestSchema = exports_external.object({
|
|
51739
|
-
schema: exports_external.literal(1),
|
|
51740
|
-
agent: AgentMetaSchema,
|
|
51741
|
-
instructions: InstructionsSchema.optional(),
|
|
51742
|
-
skills: exports_external.array(SkillEntrySchema).default([]),
|
|
51743
|
-
mcp: exports_external.array(McpEntrySchema).default([]),
|
|
51744
|
-
commands: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
51745
|
-
hooks: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
|
|
51746
|
-
files: exports_external.array(exports_external.record(exports_external.unknown())).optional()
|
|
51747
|
-
});
|
|
51748
|
-
function manifestPath(cwd2) {
|
|
51749
|
-
return path45.join(cwd2, AGENT_MANIFEST_FILE);
|
|
51750
|
-
}
|
|
51751
|
-
function hasManifest(cwd2) {
|
|
51752
|
-
return fs42.existsSync(manifestPath(cwd2));
|
|
51753
|
-
}
|
|
51754
|
-
function readManifest(cwd2) {
|
|
51755
|
-
const p2 = manifestPath(cwd2);
|
|
51756
|
-
if (!fs42.existsSync(p2))
|
|
51757
|
-
return null;
|
|
51758
|
-
const raw = fs42.readFileSync(p2, "utf8");
|
|
51759
|
-
let parsed;
|
|
51760
|
-
try {
|
|
51761
|
-
parsed = import_yaml2.default.parse(raw);
|
|
51762
|
-
} catch (err) {
|
|
51763
|
-
throw new Error(`${AGENT_MANIFEST_FILE} is not valid YAML: ${err.message}`);
|
|
51764
|
-
}
|
|
51765
|
-
const result = AgentManifestSchema.safeParse(parsed);
|
|
51766
|
-
if (!result.success) {
|
|
51767
|
-
throw new Error(`${AGENT_MANIFEST_FILE} is invalid: ${result.error.issues.map((i) => `${i.path.join(".") || "(root)"} — ${i.message}`).join("; ")}`);
|
|
51768
|
-
}
|
|
51769
|
-
return result.data;
|
|
51770
|
-
}
|
|
51771
|
-
function writeManifest(cwd2, manifest) {
|
|
51772
|
-
const doc = new import_yaml2.default.Document;
|
|
51773
|
-
doc.contents = manifest;
|
|
51774
|
-
doc.commentBefore = ` brainbase.yaml — declarative agent manifest.
|
|
51775
|
-
` + " Committed to source control. Edit by hand, then `brainbase agent push`.";
|
|
51776
|
-
const out = String(doc);
|
|
51777
|
-
fs42.writeFileSync(manifestPath(cwd2), out, "utf8");
|
|
51778
|
-
}
|
|
51779
|
-
function resolveInstructionsPath(cwd2, manifest) {
|
|
51780
|
-
if (!manifest.instructions)
|
|
51781
|
-
return null;
|
|
51782
|
-
return path45.resolve(cwd2, manifest.instructions.file);
|
|
51783
|
-
}
|
|
51784
|
-
function readInstructions(cwd2, manifest) {
|
|
51785
|
-
const p2 = resolveInstructionsPath(cwd2, manifest);
|
|
51786
|
-
if (!p2 || !fs42.existsSync(p2))
|
|
51787
|
-
return null;
|
|
51788
|
-
return fs42.readFileSync(p2, "utf8");
|
|
51789
|
-
}
|
|
51790
|
-
|
|
51791
|
-
// src/core/agent-diff.ts
|
|
51792
|
-
import path46 from "node:path";
|
|
51793
|
-
import fs43 from "node:fs";
|
|
51794
|
-
import crypto4 from "node:crypto";
|
|
51795
|
-
function compKey(type, slug) {
|
|
51796
|
-
return `${type}/${slug}`;
|
|
51797
|
-
}
|
|
51798
|
-
function hashString(s3) {
|
|
51799
|
-
return crypto4.createHash("sha256").update(s3).digest("hex");
|
|
51800
|
-
}
|
|
51801
|
-
function canonicalJson(value) {
|
|
51802
|
-
if (value === null)
|
|
51803
|
-
return "null";
|
|
51804
|
-
if (typeof value === "boolean")
|
|
51805
|
-
return value ? "true" : "false";
|
|
51806
|
-
if (typeof value === "number") {
|
|
51807
|
-
if (!Number.isFinite(value))
|
|
51808
|
-
throw new Error("Non-finite numbers are not JSON");
|
|
51809
|
-
return String(value);
|
|
51810
|
-
}
|
|
51811
|
-
if (typeof value === "string")
|
|
51812
|
-
return JSON.stringify(value);
|
|
51813
|
-
if (Array.isArray(value)) {
|
|
51814
|
-
return "[" + value.map(canonicalJson).join(",") + "]";
|
|
51815
|
-
}
|
|
51816
|
-
if (typeof value === "object") {
|
|
51817
|
-
const obj = value;
|
|
51818
|
-
const keys = Object.keys(obj).sort();
|
|
51819
|
-
return "{" + keys.map((k3) => `${JSON.stringify(k3)}:${canonicalJson(obj[k3])}`).join(",") + "}";
|
|
51820
|
-
}
|
|
51821
|
-
throw new Error(`Unsupported value in canonicalJson: ${typeof value}`);
|
|
52038
|
+
throw new Error(`Unsupported value in canonicalJson: ${typeof value}`);
|
|
51822
52039
|
}
|
|
51823
52040
|
function hashMcpEntry(entry) {
|
|
51824
52041
|
const payload = {};
|
|
@@ -51933,8 +52150,34 @@ function readLocalComponents(cwd2, manifest) {
|
|
|
51933
52150
|
hash: hashMcpEntry(entry)
|
|
51934
52151
|
});
|
|
51935
52152
|
}
|
|
52153
|
+
for (const entry of manifest.playbooks ?? []) {
|
|
52154
|
+
const body = resolvePlaybookContent(cwd2, entry);
|
|
52155
|
+
if (body === null) {
|
|
52156
|
+
out.push({
|
|
52157
|
+
type: "playbook",
|
|
52158
|
+
slug: slugifyPlaybookTitle(entry.title),
|
|
52159
|
+
hash: null
|
|
52160
|
+
});
|
|
52161
|
+
continue;
|
|
52162
|
+
}
|
|
52163
|
+
const wireBody = /^---\s*\n/.test(body) ? body : `---
|
|
52164
|
+
title: ${jsonOrPlain(entry.title)}` + (entry.description ? `
|
|
52165
|
+
description: ${jsonOrPlain(entry.description)}` : "") + `
|
|
52166
|
+
---
|
|
52167
|
+
${body.replace(/^\n+/, "")}`;
|
|
52168
|
+
out.push({
|
|
52169
|
+
type: "playbook",
|
|
52170
|
+
slug: slugifyPlaybookTitle(entry.title),
|
|
52171
|
+
hash: componentHashFromFileHashes([hashString(wireBody)])
|
|
52172
|
+
});
|
|
52173
|
+
}
|
|
51936
52174
|
return out;
|
|
51937
52175
|
}
|
|
52176
|
+
function jsonOrPlain(s3) {
|
|
52177
|
+
if (!/[\n":#&*!|>'%@`{}[\]]/.test(s3) && s3.trim() === s3 && s3 !== "")
|
|
52178
|
+
return s3;
|
|
52179
|
+
return JSON.stringify(s3);
|
|
52180
|
+
}
|
|
51938
52181
|
function threeWayDiff(input) {
|
|
51939
52182
|
const lockMap = new Map;
|
|
51940
52183
|
for (const c2 of input.lock)
|
|
@@ -52123,26 +52366,27 @@ function diffSecrets(local, cloud) {
|
|
|
52123
52366
|
// src/cli/agent-pull.ts
|
|
52124
52367
|
async function runAgentPull(cwd2, args) {
|
|
52125
52368
|
banner("agent pull — bring cloud changes into this folder");
|
|
52126
|
-
const
|
|
52127
|
-
if (!
|
|
52128
|
-
f2.warn("This folder is not linked to any agent.");
|
|
52129
|
-
f2.info(`Run ${import_picocolors25.default.cyan("brainbase link")} first.`);
|
|
52369
|
+
const resolution = resolveTargetAgentId(cwd2, args);
|
|
52370
|
+
if (!resolution)
|
|
52130
52371
|
return;
|
|
52131
|
-
}
|
|
52372
|
+
const { agentId, override } = resolution;
|
|
52132
52373
|
const sp = de();
|
|
52133
|
-
sp.start(
|
|
52374
|
+
sp.start("Fetching agent…");
|
|
52375
|
+
let cloudAgent;
|
|
52134
52376
|
let cloud;
|
|
52135
52377
|
try {
|
|
52136
|
-
|
|
52378
|
+
cloudAgent = await api.getAgent(agentId);
|
|
52379
|
+
cloud = await api.getAgentManifest(agentId);
|
|
52137
52380
|
sp.stop(`Cloud revision ${cloud.revision}.`);
|
|
52138
52381
|
} catch (err) {
|
|
52139
52382
|
sp.stop("Failed.");
|
|
52140
52383
|
handleApiError2(err);
|
|
52141
52384
|
return;
|
|
52142
52385
|
}
|
|
52143
|
-
const
|
|
52144
|
-
const
|
|
52145
|
-
const
|
|
52386
|
+
const harness = normalizeHarnessId(cloudAgent.harness ?? "claude-code");
|
|
52387
|
+
const existingManifest = !override && hasManifest(cwd2) ? safeReadManifest(cwd2) : null;
|
|
52388
|
+
const lock = override ? null : readSyncState(cwd2);
|
|
52389
|
+
const localComponents = existingManifest ? readLocalComponents(cwd2, existingManifest) : [];
|
|
52146
52390
|
const rows = threeWayDiff({
|
|
52147
52391
|
local: localComponents,
|
|
52148
52392
|
lock: lock?.components ?? [],
|
|
@@ -52167,7 +52411,11 @@ async function runAgentPull(cwd2, args) {
|
|
|
52167
52411
|
break;
|
|
52168
52412
|
case "modified-both":
|
|
52169
52413
|
case "modified-local":
|
|
52170
|
-
|
|
52414
|
+
if (override) {
|
|
52415
|
+
toInstallKeys.add(r2.key);
|
|
52416
|
+
} else {
|
|
52417
|
+
conflicts.push(r2);
|
|
52418
|
+
}
|
|
52171
52419
|
break;
|
|
52172
52420
|
}
|
|
52173
52421
|
}
|
|
@@ -52191,11 +52439,12 @@ async function runAgentPull(cwd2, args) {
|
|
|
52191
52439
|
const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
|
|
52192
52440
|
const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
|
|
52193
52441
|
const needMemoryMcpInstall = !cloudHasMemoryMcp;
|
|
52194
|
-
if (toInstallKeys.size === 0 && toRemoveKeys.size === 0 && !needOrchestrationMcpInstall && !needMemoryMcpInstall) {
|
|
52442
|
+
if (toInstallKeys.size === 0 && toRemoveKeys.size === 0 && !needOrchestrationMcpInstall && !needMemoryMcpInstall && !override) {
|
|
52195
52443
|
f2.info(`You're up to date.`);
|
|
52196
|
-
|
|
52197
|
-
|
|
52198
|
-
|
|
52444
|
+
writeLink(cwd2, buildLinkFromAgent(cloudAgent, harness, readLink(cwd2)));
|
|
52445
|
+
writeSyncState(cwd2, buildLockFromCloud(agentId, cloud, lock, cloudAgent));
|
|
52446
|
+
if (!existingManifest) {
|
|
52447
|
+
writeManifest(cwd2, mergeManifest(cwd2, null, cloud, cloudAgent, harness));
|
|
52199
52448
|
f2.info(`Wrote ${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)}.`);
|
|
52200
52449
|
}
|
|
52201
52450
|
return;
|
|
@@ -52225,20 +52474,20 @@ async function runAgentPull(cwd2, args) {
|
|
|
52225
52474
|
});
|
|
52226
52475
|
}
|
|
52227
52476
|
await showResultCard({
|
|
52228
|
-
title: "PULL",
|
|
52229
|
-
tone: "info",
|
|
52230
|
-
subtitle: `updates for ${
|
|
52477
|
+
title: override ? "PULL (FORCE)" : "PULL",
|
|
52478
|
+
tone: override ? "warn" : "info",
|
|
52479
|
+
subtitle: `updates for ${cloudAgent.name}`,
|
|
52231
52480
|
rows: resultRows
|
|
52232
52481
|
});
|
|
52233
52482
|
if (!args.yes) {
|
|
52234
|
-
const
|
|
52483
|
+
const msg = override ? "Apply these changes? Local edits to overlapping components will be discarded." : "Apply these changes?";
|
|
52484
|
+
const ok = await se({ message: msg, initialValue: true });
|
|
52235
52485
|
if (!ensureNotCancelled(ok)) {
|
|
52236
52486
|
$e("Aborted.");
|
|
52237
52487
|
return;
|
|
52238
52488
|
}
|
|
52239
52489
|
}
|
|
52240
|
-
const
|
|
52241
|
-
const adapter = getAdapter(adapterId);
|
|
52490
|
+
const adapter = getAdapter(harness);
|
|
52242
52491
|
const scope = args.scope ?? "project";
|
|
52243
52492
|
const installComponents = cloud.components.filter((c2) => toInstallKeys.has(`${c2.type}/${c2.slug}`));
|
|
52244
52493
|
const stageRoot = stageManifestComponents(installComponents);
|
|
@@ -52270,7 +52519,7 @@ async function runAgentPull(cwd2, args) {
|
|
|
52270
52519
|
resolveConflict: async (_c) => "overwrite",
|
|
52271
52520
|
resolveSecret: async () => null
|
|
52272
52521
|
};
|
|
52273
|
-
const result = await runHarnessInstall2(adapter.id, toInstall, opts,
|
|
52522
|
+
const result = await runHarnessInstall2(adapter.id, toInstall, opts, cloudAgent.name);
|
|
52274
52523
|
installSpinner.stop("Applied.");
|
|
52275
52524
|
for (const o2 of result.installed) {
|
|
52276
52525
|
justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
|
|
@@ -52297,9 +52546,12 @@ async function runAgentPull(cwd2, args) {
|
|
|
52297
52546
|
}
|
|
52298
52547
|
}
|
|
52299
52548
|
}
|
|
52300
|
-
materializeInstructions(cwd2, cloud, toInstallKeys, keepLocalKeys);
|
|
52301
|
-
|
|
52549
|
+
materializeInstructions(cwd2, cloud, toInstallKeys, keepLocalKeys, existingManifest);
|
|
52550
|
+
materializeEntrypoint(cwd2, cloudAgent.entrypoint ?? "", existingManifest);
|
|
52551
|
+
materializePlaybooks(cwd2, cloud, toInstallKeys, keepLocalKeys, existingManifest);
|
|
52552
|
+
const yaml = mergeManifest(cwd2, existingManifest, cloud, cloudAgent, harness);
|
|
52302
52553
|
writeManifest(cwd2, yaml);
|
|
52554
|
+
writeLink(cwd2, buildLinkFromAgent(cloudAgent, harness, readLink(cwd2)));
|
|
52303
52555
|
const lockComponents = buildLockComponents({
|
|
52304
52556
|
cloud,
|
|
52305
52557
|
prevLock: lock,
|
|
@@ -52309,21 +52561,64 @@ async function runAgentPull(cwd2, args) {
|
|
|
52309
52561
|
});
|
|
52310
52562
|
const newState = {
|
|
52311
52563
|
schemaVersion: 1,
|
|
52312
|
-
agent_id:
|
|
52564
|
+
agent_id: agentId,
|
|
52313
52565
|
revision: cloud.revision,
|
|
52314
52566
|
synced_at: new Date().toISOString(),
|
|
52315
52567
|
components: lockComponents,
|
|
52316
|
-
agentMeta: {
|
|
52568
|
+
agentMeta: {
|
|
52569
|
+
name: cloudAgent.name,
|
|
52570
|
+
tagline: cloudAgent.tagline,
|
|
52571
|
+
...cloudAgent.entrypoint ? { entrypoint: cloudAgent.entrypoint } : {}
|
|
52572
|
+
}
|
|
52317
52573
|
};
|
|
52318
52574
|
writeSyncState(cwd2, newState);
|
|
52319
|
-
await pullSecrets(cwd2,
|
|
52320
|
-
|
|
52575
|
+
await pullSecrets(cwd2, agentId);
|
|
52576
|
+
await runEntrypointIfPresent(cwd2, yaml);
|
|
52577
|
+
$e(`Pulled ${cloudAgent.name} at revision ${cloud.revision}.`);
|
|
52321
52578
|
} finally {
|
|
52322
52579
|
try {
|
|
52323
52580
|
fs45.rmSync(stageRoot, { recursive: true, force: true });
|
|
52324
52581
|
} catch {}
|
|
52325
52582
|
}
|
|
52326
52583
|
}
|
|
52584
|
+
function resolveTargetAgentId(cwd2, args) {
|
|
52585
|
+
const arg = args.agentIdArg?.trim() || undefined;
|
|
52586
|
+
let manifest = null;
|
|
52587
|
+
try {
|
|
52588
|
+
manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
52589
|
+
} catch (err) {
|
|
52590
|
+
f2.error(err.message);
|
|
52591
|
+
return null;
|
|
52592
|
+
}
|
|
52593
|
+
const manifestId = manifest?.id;
|
|
52594
|
+
if (arg && manifestId && arg !== manifestId) {
|
|
52595
|
+
if (!args.force) {
|
|
52596
|
+
f2.error(`This folder is already linked to a different agent (${import_picocolors25.default.dim(manifestId)}).`);
|
|
52597
|
+
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."));
|
|
52598
|
+
return null;
|
|
52599
|
+
}
|
|
52600
|
+
return { agentId: arg, override: true };
|
|
52601
|
+
}
|
|
52602
|
+
if (arg)
|
|
52603
|
+
return { agentId: arg, override: false };
|
|
52604
|
+
if (manifestId)
|
|
52605
|
+
return { agentId: manifestId, override: false };
|
|
52606
|
+
if (manifest) {
|
|
52607
|
+
f2.error(`${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)} is unclaimed (no ${import_picocolors25.default.cyan("id")}).`);
|
|
52608
|
+
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.`);
|
|
52609
|
+
} else {
|
|
52610
|
+
f2.error(`No ${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)} here and no ${import_picocolors25.default.cyan("<id>")} given.`);
|
|
52611
|
+
f2.info(`Run ${import_picocolors25.default.cyan("brainbase agent pull <id>")} to pull an existing agent into this folder.`);
|
|
52612
|
+
}
|
|
52613
|
+
return null;
|
|
52614
|
+
}
|
|
52615
|
+
function safeReadManifest(cwd2) {
|
|
52616
|
+
try {
|
|
52617
|
+
return readManifest(cwd2);
|
|
52618
|
+
} catch {
|
|
52619
|
+
return null;
|
|
52620
|
+
}
|
|
52621
|
+
}
|
|
52327
52622
|
function skillSourceFromMeta(c2) {
|
|
52328
52623
|
if (c2.type !== "skill")
|
|
52329
52624
|
return;
|
|
@@ -52358,7 +52653,7 @@ function runHarnessInstall2(harnessId, components, opts, agentName) {
|
|
|
52358
52653
|
return installKafkaWithCtx(components, opts, agentName);
|
|
52359
52654
|
return getAdapter(harnessId).install(components, opts);
|
|
52360
52655
|
}
|
|
52361
|
-
function materializeInstructions(cwd2, cloud, toInstall, keepLocal) {
|
|
52656
|
+
function materializeInstructions(cwd2, cloud, toInstall, keepLocal, existingManifest) {
|
|
52362
52657
|
for (const c2 of cloud.components) {
|
|
52363
52658
|
if (c2.type !== "instruction")
|
|
52364
52659
|
continue;
|
|
@@ -52370,10 +52665,54 @@ function materializeInstructions(cwd2, cloud, toInstall, keepLocal) {
|
|
|
52370
52665
|
const body = c2.files[0]?.content ?? "";
|
|
52371
52666
|
if (!body.trim())
|
|
52372
52667
|
continue;
|
|
52373
|
-
|
|
52668
|
+
if (existingManifest?.instructions?.text !== undefined)
|
|
52669
|
+
continue;
|
|
52670
|
+
const targetRel = existingManifest?.instructions?.file ?? DEFAULT_INSTRUCTIONS_FILE;
|
|
52671
|
+
const target = path48.resolve(cwd2, targetRel);
|
|
52672
|
+
ensureDir(path48.dirname(target));
|
|
52673
|
+
fs45.writeFileSync(target, body, "utf8");
|
|
52674
|
+
}
|
|
52675
|
+
}
|
|
52676
|
+
function materializePlaybooks(cwd2, cloud, toInstall, keepLocal, existingManifest) {
|
|
52677
|
+
for (const c2 of cloud.components) {
|
|
52678
|
+
if (c2.type !== "playbook")
|
|
52679
|
+
continue;
|
|
52680
|
+
const key2 = `${c2.type}/${c2.slug}`;
|
|
52681
|
+
if (keepLocal.has(key2))
|
|
52682
|
+
continue;
|
|
52683
|
+
if (!toInstall.has(key2))
|
|
52684
|
+
continue;
|
|
52685
|
+
const raw = c2.files[0]?.content ?? "";
|
|
52686
|
+
if (!raw.trim())
|
|
52687
|
+
continue;
|
|
52688
|
+
const { body } = stripFrontmatter(raw);
|
|
52689
|
+
const existing = existingManifest?.playbooks?.find((p2) => slugifyForCompare(p2.title) === c2.slug);
|
|
52690
|
+
if (existing?.content?.text !== undefined)
|
|
52691
|
+
continue;
|
|
52692
|
+
const targetRel = existing?.content?.file ?? path48.join(DEFAULT_PLAYBOOKS_DIR, `${c2.slug}.md`);
|
|
52693
|
+
const target = path48.resolve(cwd2, targetRel);
|
|
52694
|
+
ensureDir(path48.dirname(target));
|
|
52695
|
+
fs45.writeFileSync(target, body, "utf8");
|
|
52696
|
+
}
|
|
52697
|
+
}
|
|
52698
|
+
function slugifyForCompare(s3) {
|
|
52699
|
+
return s3.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60) || "playbook";
|
|
52700
|
+
}
|
|
52701
|
+
function stripFrontmatter(raw) {
|
|
52702
|
+
const m3 = /^---\s*\n([\s\S]*?)\n---\s*\n?/.exec(raw);
|
|
52703
|
+
if (!m3)
|
|
52704
|
+
return { frontmatter: {}, body: raw };
|
|
52705
|
+
let fm = {};
|
|
52706
|
+
try {
|
|
52707
|
+
const parsed = import_yaml3.default.parse(m3[1] ?? "");
|
|
52708
|
+
if (parsed && typeof parsed === "object")
|
|
52709
|
+
fm = parsed;
|
|
52710
|
+
} catch {
|
|
52711
|
+
return { frontmatter: {}, body: raw };
|
|
52374
52712
|
}
|
|
52713
|
+
return { frontmatter: fm, body: raw.slice(m3[0].length) };
|
|
52375
52714
|
}
|
|
52376
|
-
function mergeManifest(cwd2, prev, cloud,
|
|
52715
|
+
function mergeManifest(cwd2, prev, cloud, cloudAgent, harness) {
|
|
52377
52716
|
const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
|
|
52378
52717
|
const localDecl = prev?.skills.find((s3) => {
|
|
52379
52718
|
try {
|
|
@@ -52396,7 +52735,33 @@ function mergeManifest(cwd2, prev, cloud, link2) {
|
|
|
52396
52735
|
}
|
|
52397
52736
|
return { source: `registry:${c2.slug}` };
|
|
52398
52737
|
});
|
|
52399
|
-
const
|
|
52738
|
+
const cloudInstrComp = cloud.components.find((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
|
|
52739
|
+
const instructions = cloudInstrComp ? prev?.instructions?.text !== undefined ? { text: cloudInstrComp.files[0].content } : { file: prev?.instructions?.file ?? DEFAULT_INSTRUCTIONS_FILE } : undefined;
|
|
52740
|
+
const cloudEntrypoint = (cloudAgent.entrypoint ?? "").trim();
|
|
52741
|
+
let entrypoint;
|
|
52742
|
+
if (cloudEntrypoint.length > 0) {
|
|
52743
|
+
if (prev?.entrypoint?.commands)
|
|
52744
|
+
entrypoint = { commands: prev.entrypoint.commands };
|
|
52745
|
+
else if (prev?.entrypoint?.text !== undefined)
|
|
52746
|
+
entrypoint = { text: cloudAgent.entrypoint };
|
|
52747
|
+
else
|
|
52748
|
+
entrypoint = { file: prev?.entrypoint?.file ?? DEFAULT_ENTRYPOINT_FILE };
|
|
52749
|
+
}
|
|
52750
|
+
const playbooks = cloud.components.filter((c2) => c2.type === "playbook").map((c2) => {
|
|
52751
|
+
const raw = c2.files[0]?.content ?? "";
|
|
52752
|
+
const { frontmatter } = stripFrontmatter(raw);
|
|
52753
|
+
const local = prev?.playbooks?.find((pb) => slugifyForCompare(pb.title) === c2.slug);
|
|
52754
|
+
const title = local?.title ?? (typeof frontmatter.title === "string" && frontmatter.title || c2.slug);
|
|
52755
|
+
const description = local?.description ?? (typeof frontmatter.description === "string" ? frontmatter.description : undefined);
|
|
52756
|
+
const content = local?.content?.text !== undefined ? { text: local.content.text } : {
|
|
52757
|
+
file: local?.content?.file ?? path48.join(DEFAULT_PLAYBOOKS_DIR, `${c2.slug}.md`)
|
|
52758
|
+
};
|
|
52759
|
+
return {
|
|
52760
|
+
title,
|
|
52761
|
+
...description ? { description } : {},
|
|
52762
|
+
content
|
|
52763
|
+
};
|
|
52764
|
+
});
|
|
52400
52765
|
const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
|
|
52401
52766
|
const payload = (c2.meta ?? {}).mcp ?? {};
|
|
52402
52767
|
const entry = { name: c2.slug };
|
|
@@ -52416,17 +52781,33 @@ function mergeManifest(cwd2, prev, cloud, link2) {
|
|
|
52416
52781
|
});
|
|
52417
52782
|
return {
|
|
52418
52783
|
schema: 1,
|
|
52784
|
+
id: cloudAgent.id,
|
|
52785
|
+
harness,
|
|
52419
52786
|
agent: {
|
|
52420
|
-
name:
|
|
52421
|
-
...
|
|
52787
|
+
name: cloudAgent.name,
|
|
52788
|
+
...cloudAgent.tagline ? { tagline: cloudAgent.tagline } : {}
|
|
52422
52789
|
},
|
|
52423
|
-
...
|
|
52424
|
-
|
|
52425
|
-
|
|
52790
|
+
...instructions ? { instructions } : {},
|
|
52791
|
+
...entrypoint ? { entrypoint } : {},
|
|
52792
|
+
playbooks,
|
|
52426
52793
|
skills,
|
|
52427
52794
|
mcp
|
|
52428
52795
|
};
|
|
52429
52796
|
}
|
|
52797
|
+
function materializeEntrypoint(cwd2, cloudEntrypoint, prev) {
|
|
52798
|
+
if (!cloudEntrypoint.trim())
|
|
52799
|
+
return;
|
|
52800
|
+
if (prev?.entrypoint?.commands)
|
|
52801
|
+
return;
|
|
52802
|
+
if (prev?.entrypoint?.text !== undefined)
|
|
52803
|
+
return;
|
|
52804
|
+
const filename = prev?.entrypoint?.file ?? DEFAULT_ENTRYPOINT_FILE;
|
|
52805
|
+
const target = path48.resolve(cwd2, filename);
|
|
52806
|
+
fs45.writeFileSync(target, cloudEntrypoint, "utf8");
|
|
52807
|
+
try {
|
|
52808
|
+
fs45.chmodSync(target, 493);
|
|
52809
|
+
} catch {}
|
|
52810
|
+
}
|
|
52430
52811
|
function parseSourceLoose(raw) {
|
|
52431
52812
|
const m3 = raw.match(/^registry:[a-z0-9_-]+\/([a-z0-9_-]+)/i);
|
|
52432
52813
|
if (m3)
|
|
@@ -52468,7 +52849,7 @@ function buildLockComponents(input) {
|
|
|
52468
52849
|
}
|
|
52469
52850
|
return out;
|
|
52470
52851
|
}
|
|
52471
|
-
function buildLockFromCloud(agent_id, cloud, prev) {
|
|
52852
|
+
function buildLockFromCloud(agent_id, cloud, prev, cloudAgent) {
|
|
52472
52853
|
return {
|
|
52473
52854
|
schemaVersion: 1,
|
|
52474
52855
|
agent_id,
|
|
@@ -52480,11 +52861,73 @@ function buildLockFromCloud(agent_id, cloud, prev) {
|
|
|
52480
52861
|
hash: c2.hash,
|
|
52481
52862
|
installedPaths: []
|
|
52482
52863
|
})),
|
|
52483
|
-
agentMeta:
|
|
52864
|
+
agentMeta: cloudAgent ? {
|
|
52865
|
+
name: cloudAgent.name,
|
|
52866
|
+
tagline: cloudAgent.tagline,
|
|
52867
|
+
...cloudAgent.entrypoint ? { entrypoint: cloudAgent.entrypoint } : {}
|
|
52868
|
+
} : prev?.agentMeta
|
|
52484
52869
|
};
|
|
52485
52870
|
}
|
|
52486
|
-
function
|
|
52487
|
-
|
|
52871
|
+
function buildLinkFromAgent(agent, harness, prev) {
|
|
52872
|
+
return {
|
|
52873
|
+
schemaVersion: 1,
|
|
52874
|
+
agent_id: agent.id,
|
|
52875
|
+
org_id: agent.org_id ?? prev?.org_id ?? "",
|
|
52876
|
+
team_id: agent.team_id ?? prev?.team_id ?? "",
|
|
52877
|
+
slug: agent.slug,
|
|
52878
|
+
name: agent.name,
|
|
52879
|
+
tagline: agent.tagline,
|
|
52880
|
+
url: agent.url,
|
|
52881
|
+
linked_at: prev?.linked_at ?? new Date().toISOString(),
|
|
52882
|
+
linked_by: prev?.linked_by,
|
|
52883
|
+
harness,
|
|
52884
|
+
tracking: prev?.tracking
|
|
52885
|
+
};
|
|
52886
|
+
}
|
|
52887
|
+
async function runEntrypointIfPresent(cwd2, manifest) {
|
|
52888
|
+
if (!manifest.entrypoint)
|
|
52889
|
+
return;
|
|
52890
|
+
const body = resolveEntrypoint(cwd2, manifest);
|
|
52891
|
+
if (body === null || !body.trim())
|
|
52892
|
+
return;
|
|
52893
|
+
const stateDir = path48.join(cwd2, LINK_DIR);
|
|
52894
|
+
ensureDir(stateDir);
|
|
52895
|
+
const scriptPath = path48.join(stateDir, "entrypoint.sh");
|
|
52896
|
+
const logPath = path48.join(stateDir, "entrypoint.log");
|
|
52897
|
+
fs45.writeFileSync(scriptPath, body, "utf8");
|
|
52898
|
+
try {
|
|
52899
|
+
fs45.chmodSync(scriptPath, 493);
|
|
52900
|
+
} catch {}
|
|
52901
|
+
f2.info(`Running entrypoint ${import_picocolors25.default.dim(`(${path48.relative(cwd2, scriptPath)})`)}`);
|
|
52902
|
+
const secrets = readLocalSecrets(cwd2);
|
|
52903
|
+
const env3 = { ...process.env, ...secrets };
|
|
52904
|
+
const logStream = fs45.createWriteStream(logPath, { flags: "w" });
|
|
52905
|
+
const exitCode = await new Promise((resolve) => {
|
|
52906
|
+
const child = spawn2("bash", [scriptPath], {
|
|
52907
|
+
cwd: cwd2,
|
|
52908
|
+
env: env3,
|
|
52909
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
52910
|
+
});
|
|
52911
|
+
child.stdout?.on("data", (chunk) => {
|
|
52912
|
+
process.stdout.write(chunk);
|
|
52913
|
+
logStream.write(chunk);
|
|
52914
|
+
});
|
|
52915
|
+
child.stderr?.on("data", (chunk) => {
|
|
52916
|
+
process.stderr.write(chunk);
|
|
52917
|
+
logStream.write(chunk);
|
|
52918
|
+
});
|
|
52919
|
+
child.on("error", (err) => {
|
|
52920
|
+
f2.warn(`entrypoint failed to start: ${err.message}`);
|
|
52921
|
+
resolve(null);
|
|
52922
|
+
});
|
|
52923
|
+
child.on("exit", (code) => resolve(code));
|
|
52924
|
+
});
|
|
52925
|
+
await new Promise((resolve) => logStream.end(resolve));
|
|
52926
|
+
if (exitCode === 0) {
|
|
52927
|
+
f2.info("Entrypoint completed.");
|
|
52928
|
+
} else if (exitCode === null) {} else {
|
|
52929
|
+
f2.warn(`Entrypoint exited ${exitCode} — continuing. Log at ${import_picocolors25.default.dim(path48.relative(cwd2, logPath))}.`);
|
|
52930
|
+
}
|
|
52488
52931
|
}
|
|
52489
52932
|
async function pullSecrets(cwd2, agentId) {
|
|
52490
52933
|
let cloudSecrets;
|
|
@@ -52518,6 +52961,8 @@ function handleApiError2(err) {
|
|
|
52518
52961
|
if (err instanceof ApiError) {
|
|
52519
52962
|
if (err.status === 401) {
|
|
52520
52963
|
f2.error("Your session is invalid. Run `brainbase login` and try again.");
|
|
52964
|
+
} else if (err.status === 404) {
|
|
52965
|
+
f2.error(`Agent not found, or you don't have access. Double-check the id.`);
|
|
52521
52966
|
} else {
|
|
52522
52967
|
f2.error(err.message);
|
|
52523
52968
|
}
|
|
@@ -52527,18 +52972,149 @@ function handleApiError2(err) {
|
|
|
52527
52972
|
}
|
|
52528
52973
|
|
|
52529
52974
|
// src/cli/agent-push.ts
|
|
52975
|
+
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
52976
|
+
|
|
52977
|
+
// src/core/agent-outgoing.ts
|
|
52530
52978
|
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
52979
|
+
async function buildOutgoingComponents(cwd2, manifest, cloud) {
|
|
52980
|
+
const out = [];
|
|
52981
|
+
if (manifest.instructions) {
|
|
52982
|
+
if (manifest.instructions.text !== undefined && manifest.instructions.file !== undefined) {
|
|
52983
|
+
f2.error(`instructions block sets both ${import_picocolors26.default.cyan("text")} and ${import_picocolors26.default.cyan("file")} — pick one.`);
|
|
52984
|
+
return null;
|
|
52985
|
+
}
|
|
52986
|
+
const body = readInstructions(cwd2, manifest);
|
|
52987
|
+
if (body === null) {
|
|
52988
|
+
if (manifest.instructions.file) {
|
|
52989
|
+
f2.error(`Instructions file ${import_picocolors26.default.bold(manifest.instructions.file)} not found.`);
|
|
52990
|
+
} else {
|
|
52991
|
+
f2.error("Instructions block is empty.");
|
|
52992
|
+
}
|
|
52993
|
+
return null;
|
|
52994
|
+
}
|
|
52995
|
+
if (body.trim()) {
|
|
52996
|
+
const fileName = manifest.instructions.file ?? "instructions.md";
|
|
52997
|
+
const fileHash2 = hashString(body);
|
|
52998
|
+
const file = {
|
|
52999
|
+
path: fileName,
|
|
53000
|
+
content: body,
|
|
53001
|
+
hash: fileHash2
|
|
53002
|
+
};
|
|
53003
|
+
out.push({
|
|
53004
|
+
type: "instruction",
|
|
53005
|
+
slug: "agent-instructions",
|
|
53006
|
+
description: "Agent instructions",
|
|
53007
|
+
hash: componentHashFromFileHashes([fileHash2]),
|
|
53008
|
+
files: [file],
|
|
53009
|
+
meta: { source: "global_prompt" }
|
|
53010
|
+
});
|
|
53011
|
+
}
|
|
53012
|
+
}
|
|
53013
|
+
for (const entry of manifest.skills) {
|
|
53014
|
+
const parsed = parseSkillSource2(entry.source);
|
|
53015
|
+
if (parsed.kind === "local") {
|
|
53016
|
+
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\`).`);
|
|
53017
|
+
return null;
|
|
53018
|
+
}
|
|
53019
|
+
const cloudMatch = cloud?.components.find((c2) => c2.type === "skill" && c2.slug === parsed.slug);
|
|
53020
|
+
out.push({
|
|
53021
|
+
type: "skill",
|
|
53022
|
+
slug: parsed.slug,
|
|
53023
|
+
hash: cloudMatch?.hash ?? "",
|
|
53024
|
+
files: [],
|
|
53025
|
+
meta: {
|
|
53026
|
+
name: parsed.creator ? `${parsed.creator}/${parsed.slug}` : parsed.slug,
|
|
53027
|
+
...parsed.version ? { version: parsed.version } : {}
|
|
53028
|
+
}
|
|
53029
|
+
});
|
|
53030
|
+
}
|
|
53031
|
+
const seenPlaybookSlugs = new Set;
|
|
53032
|
+
for (const entry of manifest.playbooks ?? []) {
|
|
53033
|
+
if (entry.content.text !== undefined && entry.content.file !== undefined) {
|
|
53034
|
+
f2.error(`Playbook ${import_picocolors26.default.bold(entry.title)} sets both ${import_picocolors26.default.cyan("text")} and ${import_picocolors26.default.cyan("file")} — pick one.`);
|
|
53035
|
+
return null;
|
|
53036
|
+
}
|
|
53037
|
+
const body = resolvePlaybookContent(cwd2, entry);
|
|
53038
|
+
if (body === null) {
|
|
53039
|
+
if (entry.content.file) {
|
|
53040
|
+
f2.error(`Playbook ${import_picocolors26.default.bold(entry.title)} content file ${import_picocolors26.default.bold(entry.content.file)} not found.`);
|
|
53041
|
+
} else {
|
|
53042
|
+
f2.error(`Playbook ${import_picocolors26.default.bold(entry.title)} content is empty.`);
|
|
53043
|
+
}
|
|
53044
|
+
return null;
|
|
53045
|
+
}
|
|
53046
|
+
const slug = slugifyPlaybookTitle(entry.title);
|
|
53047
|
+
if (seenPlaybookSlugs.has(slug)) {
|
|
53048
|
+
f2.error(`Two playbooks resolve to the same slug ${import_picocolors26.default.bold(slug)} (from title ${import_picocolors26.default.bold(entry.title)}). Pick distinct titles.`);
|
|
53049
|
+
return null;
|
|
53050
|
+
}
|
|
53051
|
+
seenPlaybookSlugs.add(slug);
|
|
53052
|
+
const wireBody = assemblePlaybookBody(entry, body);
|
|
53053
|
+
const fileName = `${slug}.md`;
|
|
53054
|
+
const fileHash2 = hashString(wireBody);
|
|
53055
|
+
out.push({
|
|
53056
|
+
type: "playbook",
|
|
53057
|
+
slug,
|
|
53058
|
+
description: entry.description,
|
|
53059
|
+
hash: componentHashFromFileHashes([fileHash2]),
|
|
53060
|
+
files: [{ path: fileName, content: wireBody, hash: fileHash2 }],
|
|
53061
|
+
meta: {
|
|
53062
|
+
title: entry.title,
|
|
53063
|
+
...entry.description ? { description: entry.description } : {}
|
|
53064
|
+
}
|
|
53065
|
+
});
|
|
53066
|
+
}
|
|
53067
|
+
for (const entry of manifest.mcp ?? []) {
|
|
53068
|
+
if (!entry.url && !entry.command) {
|
|
53069
|
+
f2.error(`MCP ${import_picocolors26.default.bold(entry.name)} needs either ${import_picocolors26.default.cyan("url")} or ${import_picocolors26.default.cyan("command")}.`);
|
|
53070
|
+
return null;
|
|
53071
|
+
}
|
|
53072
|
+
const payload = {};
|
|
53073
|
+
if (entry.url !== undefined)
|
|
53074
|
+
payload.url = entry.url;
|
|
53075
|
+
if (entry.command !== undefined)
|
|
53076
|
+
payload.command = entry.command;
|
|
53077
|
+
if (entry.args !== undefined)
|
|
53078
|
+
payload.args = entry.args;
|
|
53079
|
+
if (entry.env !== undefined)
|
|
53080
|
+
payload.env = entry.env;
|
|
53081
|
+
if (entry.headers !== undefined)
|
|
53082
|
+
payload.headers = entry.headers;
|
|
53083
|
+
payload.is_enabled = entry.is_enabled ?? true;
|
|
53084
|
+
out.push({
|
|
53085
|
+
type: "mcp",
|
|
53086
|
+
slug: entry.name,
|
|
53087
|
+
hash: "",
|
|
53088
|
+
files: [],
|
|
53089
|
+
meta: { mcp: payload }
|
|
53090
|
+
});
|
|
53091
|
+
}
|
|
53092
|
+
return out;
|
|
53093
|
+
}
|
|
53094
|
+
function assemblePlaybookBody(entry, body) {
|
|
53095
|
+
if (/^---\s*\n/.test(body))
|
|
53096
|
+
return body;
|
|
53097
|
+
const lines = ["---", `title: ${yamlScalar(entry.title)}`];
|
|
53098
|
+
if (entry.description) {
|
|
53099
|
+
lines.push(`description: ${yamlScalar(entry.description)}`);
|
|
53100
|
+
}
|
|
53101
|
+
lines.push("---", "");
|
|
53102
|
+
return lines.join(`
|
|
53103
|
+
`) + body.replace(/^\n+/, "");
|
|
53104
|
+
}
|
|
53105
|
+
function yamlScalar(s3) {
|
|
53106
|
+
if (!/[\n":#&*!|>'%@`{}[\]]/.test(s3) && s3.trim() === s3 && s3 !== "") {
|
|
53107
|
+
return s3;
|
|
53108
|
+
}
|
|
53109
|
+
return JSON.stringify(s3);
|
|
53110
|
+
}
|
|
53111
|
+
|
|
53112
|
+
// src/cli/agent-push.ts
|
|
52531
53113
|
async function runAgentPush(cwd2, args) {
|
|
52532
53114
|
banner("agent push — send your local changes to the cloud");
|
|
52533
|
-
const link2 = readLink(cwd2);
|
|
52534
|
-
if (!link2) {
|
|
52535
|
-
f2.warn("This folder is not linked to any agent.");
|
|
52536
|
-
f2.info(`Run ${import_picocolors26.default.cyan("brainbase link")} first.`);
|
|
52537
|
-
return;
|
|
52538
|
-
}
|
|
52539
53115
|
if (!hasManifest(cwd2)) {
|
|
52540
|
-
f2.warn(`No ${
|
|
52541
|
-
f2.info(`Run ${
|
|
53116
|
+
f2.warn(`No ${import_picocolors27.default.bold(AGENT_MANIFEST_FILE)} here.`);
|
|
53117
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent create")} to claim a new agent from a manifest, ` + `or ${import_picocolors27.default.cyan("brainbase agent pull <id>")} to pull an existing one.`);
|
|
52542
53118
|
return;
|
|
52543
53119
|
}
|
|
52544
53120
|
let manifest;
|
|
@@ -52548,11 +53124,17 @@ async function runAgentPush(cwd2, args) {
|
|
|
52548
53124
|
f2.error(err.message);
|
|
52549
53125
|
return;
|
|
52550
53126
|
}
|
|
53127
|
+
if (!manifest.id) {
|
|
53128
|
+
f2.warn(`${import_picocolors27.default.bold(AGENT_MANIFEST_FILE)} is unclaimed (no ${import_picocolors27.default.cyan("id")}). Nothing to push to.`);
|
|
53129
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent create")} first — that creates the cloud agent and stamps an id here.`);
|
|
53130
|
+
return;
|
|
53131
|
+
}
|
|
53132
|
+
const agentId = manifest.id;
|
|
52551
53133
|
const sp = de();
|
|
52552
|
-
sp.start(`Fetching cloud state
|
|
53134
|
+
sp.start(`Fetching cloud state…`);
|
|
52553
53135
|
let cloud;
|
|
52554
53136
|
try {
|
|
52555
|
-
cloud = await api.getAgentManifest(
|
|
53137
|
+
cloud = await api.getAgentManifest(agentId);
|
|
52556
53138
|
sp.stop(`Cloud revision ${cloud.revision}.`);
|
|
52557
53139
|
} catch (err) {
|
|
52558
53140
|
sp.stop("Failed.");
|
|
@@ -52565,17 +53147,42 @@ async function runAgentPush(cwd2, args) {
|
|
|
52565
53147
|
lock: lock?.components ?? [],
|
|
52566
53148
|
cloud: cloud.components
|
|
52567
53149
|
});
|
|
52568
|
-
|
|
53150
|
+
let cloudMeta = lock?.agentMeta;
|
|
53151
|
+
if (!cloudMeta) {
|
|
53152
|
+
try {
|
|
53153
|
+
const a3 = await api.getAgent(agentId);
|
|
53154
|
+
cloudMeta = { name: a3.name, tagline: a3.tagline, entrypoint: a3.entrypoint };
|
|
53155
|
+
} catch {}
|
|
53156
|
+
}
|
|
53157
|
+
const meta = diffAgentMeta(manifest.agent, lock?.agentMeta, cloudMeta);
|
|
53158
|
+
let resolvedEntrypoint;
|
|
53159
|
+
if (manifest.entrypoint) {
|
|
53160
|
+
const body = resolveEntrypoint(cwd2, manifest);
|
|
53161
|
+
if (body === null) {
|
|
53162
|
+
if (manifest.entrypoint.file) {
|
|
53163
|
+
f2.error(`Entrypoint file ${import_picocolors27.default.bold(manifest.entrypoint.file)} not found.`);
|
|
53164
|
+
} else {
|
|
53165
|
+
f2.error("Entrypoint block is empty.");
|
|
53166
|
+
}
|
|
53167
|
+
return;
|
|
53168
|
+
}
|
|
53169
|
+
resolvedEntrypoint = body;
|
|
53170
|
+
} else {
|
|
53171
|
+
if ((lock?.agentMeta?.entrypoint ?? "") !== "") {
|
|
53172
|
+
resolvedEntrypoint = "";
|
|
53173
|
+
}
|
|
53174
|
+
}
|
|
53175
|
+
const entrypointChanged = resolvedEntrypoint !== undefined && resolvedEntrypoint !== (lock?.agentMeta?.entrypoint ?? "");
|
|
52569
53176
|
for (const r2 of rows) {
|
|
52570
|
-
if (r2.type !== "instruction" && r2.type !== "skill" && r2.type !== "mcp") {
|
|
52571
|
-
f2.error(`Component ${fmtType(r2.type)} ${
|
|
53177
|
+
if (r2.type !== "instruction" && r2.type !== "skill" && r2.type !== "mcp" && r2.type !== "playbook") {
|
|
53178
|
+
f2.error(`Component ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)} can't be pushed yet — the server accepts instructions, skills, mcps, and playbooks in this version.`);
|
|
52572
53179
|
return;
|
|
52573
53180
|
}
|
|
52574
53181
|
}
|
|
52575
53182
|
for (const entry of manifest.skills) {
|
|
52576
53183
|
const parsed = parseSkillSource2(entry.source);
|
|
52577
53184
|
if (parsed.kind === "local") {
|
|
52578
|
-
f2.error(`Skill ${
|
|
53185
|
+
f2.error(`Skill ${import_picocolors27.default.bold(entry.source)} is a local-authored skill. Local skill push isn't supported yet — publish it to the registry first (\`brainbase skill publish\`).`);
|
|
52579
53186
|
return;
|
|
52580
53187
|
}
|
|
52581
53188
|
}
|
|
@@ -52599,22 +53206,22 @@ async function runAgentPush(cwd2, args) {
|
|
|
52599
53206
|
break;
|
|
52600
53207
|
}
|
|
52601
53208
|
}
|
|
52602
|
-
if (!meta.localChanged && toSend.length === 0 && conflicts.length === 0) {
|
|
53209
|
+
if (!meta.localChanged && !entrypointChanged && toSend.length === 0 && conflicts.length === 0) {
|
|
52603
53210
|
f2.info("Nothing to push — local is in sync with the cloud.");
|
|
52604
53211
|
return;
|
|
52605
53212
|
}
|
|
52606
53213
|
if (conflicts.length > 0) {
|
|
52607
53214
|
f2.error(`Cannot push: ${conflicts.length} component${conflicts.length === 1 ? "" : "s"} changed both locally and on the cloud:`);
|
|
52608
53215
|
for (const r2 of conflicts) {
|
|
52609
|
-
console.error(` ${
|
|
53216
|
+
console.error(` ${import_picocolors27.default.red("!")} ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)}`);
|
|
52610
53217
|
}
|
|
52611
|
-
f2.info(`Run ${
|
|
53218
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent pull")} first to reconcile, then push again.`);
|
|
52612
53219
|
return;
|
|
52613
53220
|
}
|
|
52614
53221
|
if (upstreamOnly.length > 0 && !args.yes) {
|
|
52615
53222
|
f2.warn(`Cloud has ${upstreamOnly.length} change${upstreamOnly.length === 1 ? "" : "s"} you don't have locally:`);
|
|
52616
53223
|
for (const r2 of upstreamOnly) {
|
|
52617
|
-
console.warn(` ${
|
|
53224
|
+
console.warn(` ${import_picocolors27.default.cyan("←")} ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)} ${import_picocolors27.default.dim(`(${r2.status})`)}`);
|
|
52618
53225
|
}
|
|
52619
53226
|
f2.info(`If you push now, your push targets revision ${cloud.revision} and may race. Consider \`brainbase agent pull\` first.`);
|
|
52620
53227
|
}
|
|
@@ -52626,6 +53233,13 @@ async function runAgentPush(cwd2, args) {
|
|
|
52626
53233
|
text: "name/tagline"
|
|
52627
53234
|
});
|
|
52628
53235
|
}
|
|
53236
|
+
if (entrypointChanged) {
|
|
53237
|
+
resultRows.push({
|
|
53238
|
+
type: "upd",
|
|
53239
|
+
label: "entrypoint",
|
|
53240
|
+
text: resolvedEntrypoint === "" ? "cleared" : "updated"
|
|
53241
|
+
});
|
|
53242
|
+
}
|
|
52629
53243
|
if (toSend.length) {
|
|
52630
53244
|
resultRows.push({
|
|
52631
53245
|
type: "add",
|
|
@@ -52636,7 +53250,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
52636
53250
|
await showResultCard({
|
|
52637
53251
|
title: "PUSH",
|
|
52638
53252
|
tone: "info",
|
|
52639
|
-
subtitle: `${
|
|
53253
|
+
subtitle: `${manifest.agent.name} ← local`,
|
|
52640
53254
|
rows: resultRows
|
|
52641
53255
|
});
|
|
52642
53256
|
if (!args.yes) {
|
|
@@ -52646,14 +53260,19 @@ async function runAgentPush(cwd2, args) {
|
|
|
52646
53260
|
return;
|
|
52647
53261
|
}
|
|
52648
53262
|
}
|
|
52649
|
-
if (meta.localChanged) {
|
|
53263
|
+
if (meta.localChanged || entrypointChanged) {
|
|
52650
53264
|
const metaSpinner = de();
|
|
52651
53265
|
metaSpinner.start("Updating agent metadata…");
|
|
52652
53266
|
try {
|
|
52653
|
-
|
|
52654
|
-
|
|
52655
|
-
|
|
52656
|
-
|
|
53267
|
+
const update = {};
|
|
53268
|
+
if (meta.localChanged) {
|
|
53269
|
+
update.name = manifest.agent.name;
|
|
53270
|
+
update.tagline = manifest.agent.tagline ?? "";
|
|
53271
|
+
}
|
|
53272
|
+
if (entrypointChanged) {
|
|
53273
|
+
update.entrypoint = resolvedEntrypoint;
|
|
53274
|
+
}
|
|
53275
|
+
await api.updateAgent(agentId, update);
|
|
52657
53276
|
metaSpinner.stop("Metadata updated.");
|
|
52658
53277
|
} catch (err) {
|
|
52659
53278
|
metaSpinner.stop("Failed.");
|
|
@@ -52667,7 +53286,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
52667
53286
|
pushSpinner.start("Pushing…");
|
|
52668
53287
|
let updatedCloud;
|
|
52669
53288
|
try {
|
|
52670
|
-
updatedCloud = await api.pushAgentManifest(
|
|
53289
|
+
updatedCloud = await api.pushAgentManifest(agentId, {
|
|
52671
53290
|
components: outgoing,
|
|
52672
53291
|
base_revision: cloud.revision
|
|
52673
53292
|
});
|
|
@@ -52676,14 +53295,22 @@ async function runAgentPush(cwd2, args) {
|
|
|
52676
53295
|
pushSpinner.stop("Failed.");
|
|
52677
53296
|
if (err instanceof ApiError && err.status === 409) {
|
|
52678
53297
|
f2.error(err.message);
|
|
52679
|
-
f2.info(`Run ${
|
|
53298
|
+
f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent pull")} and try again.`);
|
|
52680
53299
|
return;
|
|
52681
53300
|
}
|
|
52682
53301
|
return handleApiError3(err);
|
|
52683
53302
|
}
|
|
53303
|
+
const existing = readLink(cwd2);
|
|
53304
|
+
if (existing) {
|
|
53305
|
+
writeLink(cwd2, {
|
|
53306
|
+
...existing,
|
|
53307
|
+
name: manifest.agent.name,
|
|
53308
|
+
tagline: manifest.agent.tagline
|
|
53309
|
+
});
|
|
53310
|
+
}
|
|
52684
53311
|
const newLock = {
|
|
52685
53312
|
schemaVersion: 1,
|
|
52686
|
-
agent_id:
|
|
53313
|
+
agent_id: agentId,
|
|
52687
53314
|
revision: updatedCloud.revision,
|
|
52688
53315
|
synced_at: new Date().toISOString(),
|
|
52689
53316
|
components: updatedCloud.components.map((c2) => {
|
|
@@ -52695,7 +53322,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
52695
53322
|
return false;
|
|
52696
53323
|
}
|
|
52697
53324
|
})?.source;
|
|
52698
|
-
const prior = lock?.components.find((
|
|
53325
|
+
const prior = lock?.components.find((pc26) => pc26.type === c2.type && pc26.slug === c2.slug);
|
|
52699
53326
|
return {
|
|
52700
53327
|
type: c2.type,
|
|
52701
53328
|
slug: c2.slug,
|
|
@@ -52704,11 +53331,15 @@ async function runAgentPush(cwd2, args) {
|
|
|
52704
53331
|
...decl ? { source: decl } : {}
|
|
52705
53332
|
};
|
|
52706
53333
|
}),
|
|
52707
|
-
agentMeta: {
|
|
53334
|
+
agentMeta: {
|
|
53335
|
+
name: manifest.agent.name,
|
|
53336
|
+
tagline: manifest.agent.tagline,
|
|
53337
|
+
entrypoint: resolvedEntrypoint !== undefined ? resolvedEntrypoint : lock?.agentMeta?.entrypoint
|
|
53338
|
+
}
|
|
52708
53339
|
};
|
|
52709
53340
|
writeSyncState(cwd2, newLock);
|
|
52710
|
-
await pushSecrets(cwd2,
|
|
52711
|
-
$e(`Pushed ${
|
|
53341
|
+
await pushSecrets(cwd2, agentId);
|
|
53342
|
+
$e(`Pushed ${manifest.agent.name} at revision ${updatedCloud.revision}.`);
|
|
52712
53343
|
}
|
|
52713
53344
|
async function pushSecrets(cwd2, agentId) {
|
|
52714
53345
|
const localSecrets = readLocalSecrets(cwd2);
|
|
@@ -52722,87 +53353,19 @@ async function pushSecrets(cwd2, agentId) {
|
|
|
52722
53353
|
f2.warn(`Couldn't read cloud secrets to diff: ${err.message}. Skipping secret push.`);
|
|
52723
53354
|
return;
|
|
52724
53355
|
}
|
|
52725
|
-
const diff2 = diffSecrets(localSecrets, cloudSecrets);
|
|
52726
|
-
if (diff2.localOnly.length === 0 && diff2.changed.length === 0 && diff2.cloudOnly.length === 0) {
|
|
52727
|
-
return;
|
|
52728
|
-
}
|
|
52729
|
-
const sp = de();
|
|
52730
|
-
sp.start("Pushing secrets…");
|
|
52731
|
-
try {
|
|
52732
|
-
await api.putAgentSecrets(agentId, localSecrets);
|
|
52733
|
-
sp.stop(`Secrets pushed (${diff2.localOnly.length} added, ${diff2.changed.length} updated, ${diff2.cloudOnly.length} removed).`);
|
|
52734
|
-
} catch (err) {
|
|
52735
|
-
sp.stop("Failed.");
|
|
52736
|
-
handleApiError3(err);
|
|
52737
|
-
}
|
|
52738
|
-
}
|
|
52739
|
-
async function buildOutgoingComponents(cwd2, manifest, cloud) {
|
|
52740
|
-
const out = [];
|
|
52741
|
-
if (manifest.instructions) {
|
|
52742
|
-
const body = readInstructions(cwd2, manifest);
|
|
52743
|
-
if (body === null) {
|
|
52744
|
-
f2.error(`Instructions file ${import_picocolors26.default.bold(manifest.instructions.file)} not found.`);
|
|
52745
|
-
return null;
|
|
52746
|
-
}
|
|
52747
|
-
if (body.trim()) {
|
|
52748
|
-
const fileHash2 = hashString(body);
|
|
52749
|
-
const file = {
|
|
52750
|
-
path: manifest.instructions.file,
|
|
52751
|
-
content: body,
|
|
52752
|
-
hash: fileHash2
|
|
52753
|
-
};
|
|
52754
|
-
out.push({
|
|
52755
|
-
type: "instruction",
|
|
52756
|
-
slug: "agent-instructions",
|
|
52757
|
-
description: "Agent instructions",
|
|
52758
|
-
hash: componentHashFromFileHashes([fileHash2]),
|
|
52759
|
-
files: [file],
|
|
52760
|
-
meta: { source: "global_prompt" }
|
|
52761
|
-
});
|
|
52762
|
-
}
|
|
52763
|
-
}
|
|
52764
|
-
for (const entry of manifest.skills) {
|
|
52765
|
-
const parsed = parseSkillSource2(entry.source);
|
|
52766
|
-
if (parsed.kind !== "registry")
|
|
52767
|
-
continue;
|
|
52768
|
-
const cloudMatch = cloud.components.find((c2) => c2.type === "skill" && c2.slug === parsed.slug);
|
|
52769
|
-
out.push({
|
|
52770
|
-
type: "skill",
|
|
52771
|
-
slug: parsed.slug,
|
|
52772
|
-
hash: cloudMatch?.hash ?? "",
|
|
52773
|
-
files: [],
|
|
52774
|
-
meta: {
|
|
52775
|
-
name: parsed.creator ? `${parsed.creator}/${parsed.slug}` : parsed.slug,
|
|
52776
|
-
...parsed.version ? { version: parsed.version } : {}
|
|
52777
|
-
}
|
|
52778
|
-
});
|
|
53356
|
+
const diff2 = diffSecrets(localSecrets, cloudSecrets);
|
|
53357
|
+
if (diff2.localOnly.length === 0 && diff2.changed.length === 0 && diff2.cloudOnly.length === 0) {
|
|
53358
|
+
return;
|
|
52779
53359
|
}
|
|
52780
|
-
|
|
52781
|
-
|
|
52782
|
-
|
|
52783
|
-
|
|
52784
|
-
}
|
|
52785
|
-
|
|
52786
|
-
|
|
52787
|
-
|
|
52788
|
-
if (entry.command !== undefined)
|
|
52789
|
-
payload.command = entry.command;
|
|
52790
|
-
if (entry.args !== undefined)
|
|
52791
|
-
payload.args = entry.args;
|
|
52792
|
-
if (entry.env !== undefined)
|
|
52793
|
-
payload.env = entry.env;
|
|
52794
|
-
if (entry.headers !== undefined)
|
|
52795
|
-
payload.headers = entry.headers;
|
|
52796
|
-
payload.is_enabled = entry.is_enabled ?? true;
|
|
52797
|
-
out.push({
|
|
52798
|
-
type: "mcp",
|
|
52799
|
-
slug: entry.name,
|
|
52800
|
-
hash: "",
|
|
52801
|
-
files: [],
|
|
52802
|
-
meta: { mcp: payload }
|
|
52803
|
-
});
|
|
53360
|
+
const sp = de();
|
|
53361
|
+
sp.start("Pushing secrets…");
|
|
53362
|
+
try {
|
|
53363
|
+
await api.putAgentSecrets(agentId, localSecrets);
|
|
53364
|
+
sp.stop(`Secrets pushed (${diff2.localOnly.length} added, ${diff2.changed.length} updated, ${diff2.cloudOnly.length} removed).`);
|
|
53365
|
+
} catch (err) {
|
|
53366
|
+
sp.stop("Failed.");
|
|
53367
|
+
handleApiError3(err);
|
|
52804
53368
|
}
|
|
52805
|
-
return out;
|
|
52806
53369
|
}
|
|
52807
53370
|
function handleApiError3(err) {
|
|
52808
53371
|
if (err instanceof ApiError) {
|
|
@@ -52817,13 +53380,13 @@ function handleApiError3(err) {
|
|
|
52817
53380
|
}
|
|
52818
53381
|
|
|
52819
53382
|
// src/cli/agent-status.ts
|
|
52820
|
-
var
|
|
53383
|
+
var import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
52821
53384
|
async function runAgentStatus(cwd2) {
|
|
52822
53385
|
banner("agent status — what changed locally, remotely, both");
|
|
52823
53386
|
const link2 = readLink(cwd2);
|
|
52824
53387
|
if (!link2) {
|
|
52825
53388
|
f2.warn("This folder is not linked to any agent.");
|
|
52826
|
-
f2.info(`Run ${
|
|
53389
|
+
f2.info(`Run ${import_picocolors28.default.cyan("brainbase link")} first.`);
|
|
52827
53390
|
return;
|
|
52828
53391
|
}
|
|
52829
53392
|
const manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
|
|
@@ -52844,8 +53407,8 @@ async function runAgentStatus(cwd2) {
|
|
|
52844
53407
|
return;
|
|
52845
53408
|
}
|
|
52846
53409
|
if (!manifest) {
|
|
52847
|
-
f2.info(`${
|
|
52848
|
-
f2.info(`Cloud has ${
|
|
53410
|
+
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.`);
|
|
53411
|
+
f2.info(`Cloud has ${import_picocolors28.default.bold(String(cloud.components.length))} component${cloud.components.length === 1 ? "" : "s"} at revision ${cloud.revision}.`);
|
|
52849
53412
|
return;
|
|
52850
53413
|
}
|
|
52851
53414
|
const localComponents = readLocalComponents(cwd2, manifest);
|
|
@@ -52884,17 +53447,17 @@ async function runAgentStatus(cwd2) {
|
|
|
52884
53447
|
}
|
|
52885
53448
|
const lines = [];
|
|
52886
53449
|
lines.push("");
|
|
52887
|
-
lines.push(` ${
|
|
52888
|
-
lines.push(` ${
|
|
52889
|
-
lines.push(` ${
|
|
53450
|
+
lines.push(` ${import_picocolors28.default.bold(link2.name)} ${import_picocolors28.default.dim(`(${link2.slug})`)}`);
|
|
53451
|
+
lines.push(` ${import_picocolors28.default.dim("agent_id")} ${link2.agent_id}`);
|
|
53452
|
+
lines.push(` ${import_picocolors28.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
|
|
52890
53453
|
lines.push("");
|
|
52891
53454
|
if (meta.localChanged || meta.cloudChanged) {
|
|
52892
|
-
lines.push(` ${
|
|
53455
|
+
lines.push(` ${import_picocolors28.default.bold("agent metadata")}`);
|
|
52893
53456
|
if (meta.localChanged) {
|
|
52894
|
-
lines.push(` ${
|
|
53457
|
+
lines.push(` ${import_picocolors28.default.yellow("→ push")} name/tagline edited in brainbase.agent.yaml`);
|
|
52895
53458
|
}
|
|
52896
53459
|
if (meta.cloudChanged) {
|
|
52897
|
-
lines.push(` ${
|
|
53460
|
+
lines.push(` ${import_picocolors28.default.cyan("← pull")} name/tagline changed on cloud`);
|
|
52898
53461
|
}
|
|
52899
53462
|
lines.push("");
|
|
52900
53463
|
}
|
|
@@ -52904,65 +53467,65 @@ async function runAgentStatus(cwd2) {
|
|
|
52904
53467
|
const cloudSecrets = cloudRes.secrets ?? {};
|
|
52905
53468
|
const sd = diffSecrets(localSecrets, cloudSecrets);
|
|
52906
53469
|
if (sd.localOnly.length || sd.cloudOnly.length || sd.changed.length) {
|
|
52907
|
-
lines.push(` ${
|
|
53470
|
+
lines.push(` ${import_picocolors28.default.bold("secrets")}`);
|
|
52908
53471
|
if (sd.localOnly.length)
|
|
52909
|
-
lines.push(` ${
|
|
53472
|
+
lines.push(` ${import_picocolors28.default.yellow("→ push")} new locally: ${sd.localOnly.join(", ")}`);
|
|
52910
53473
|
if (sd.changed.length)
|
|
52911
|
-
lines.push(` ${
|
|
53474
|
+
lines.push(` ${import_picocolors28.default.yellow("→ push")} values changed: ${sd.changed.join(", ")}`);
|
|
52912
53475
|
if (sd.cloudOnly.length)
|
|
52913
|
-
lines.push(` ${
|
|
53476
|
+
lines.push(` ${import_picocolors28.default.cyan("← pull")} new on cloud: ${sd.cloudOnly.join(", ")}`);
|
|
52914
53477
|
lines.push("");
|
|
52915
53478
|
}
|
|
52916
53479
|
} catch {}
|
|
52917
53480
|
if (conflicts.length === 0 && toPush.length === 0 && toPull.length === 0) {
|
|
52918
|
-
lines.push(` ${
|
|
53481
|
+
lines.push(` ${import_picocolors28.default.green("✓")} everything is in sync`);
|
|
52919
53482
|
lines.push("");
|
|
52920
53483
|
console.log(lines.join(`
|
|
52921
53484
|
`));
|
|
52922
53485
|
return;
|
|
52923
53486
|
}
|
|
52924
53487
|
if (toPush.length) {
|
|
52925
|
-
lines.push(` ${
|
|
53488
|
+
lines.push(` ${import_picocolors28.default.bold("changes to push")} ${import_picocolors28.default.dim(`(${toPush.length})`)}`);
|
|
52926
53489
|
for (const r2 of toPush)
|
|
52927
|
-
lines.push(` ${
|
|
53490
|
+
lines.push(` ${import_picocolors28.default.yellow("→")} ${fmtRow(r2)}`);
|
|
52928
53491
|
lines.push("");
|
|
52929
53492
|
}
|
|
52930
53493
|
if (toPull.length) {
|
|
52931
|
-
lines.push(` ${
|
|
53494
|
+
lines.push(` ${import_picocolors28.default.bold("changes to pull")} ${import_picocolors28.default.dim(`(${toPull.length})`)}`);
|
|
52932
53495
|
for (const r2 of toPull)
|
|
52933
|
-
lines.push(` ${
|
|
53496
|
+
lines.push(` ${import_picocolors28.default.cyan("←")} ${fmtRow(r2)}`);
|
|
52934
53497
|
lines.push("");
|
|
52935
53498
|
}
|
|
52936
53499
|
if (conflicts.length) {
|
|
52937
|
-
lines.push(` ${
|
|
53500
|
+
lines.push(` ${import_picocolors28.default.bold(import_picocolors28.default.red("conflicts"))} ${import_picocolors28.default.dim(`(${conflicts.length})`)}`);
|
|
52938
53501
|
for (const r2 of conflicts)
|
|
52939
|
-
lines.push(` ${
|
|
53502
|
+
lines.push(` ${import_picocolors28.default.red("!")} ${fmtRow(r2)}`);
|
|
52940
53503
|
lines.push("");
|
|
52941
53504
|
}
|
|
52942
|
-
lines.push(` ${
|
|
53505
|
+
lines.push(` ${import_picocolors28.default.dim("run")} ${import_picocolors28.default.cyan("brainbase agent pull")} ${import_picocolors28.default.dim("to apply cloud changes,")} ${import_picocolors28.default.cyan("brainbase agent push")} ${import_picocolors28.default.dim("to send yours")}`);
|
|
52943
53506
|
lines.push("");
|
|
52944
53507
|
console.log(lines.join(`
|
|
52945
53508
|
`));
|
|
52946
53509
|
}
|
|
52947
53510
|
function fmtRow(r2) {
|
|
52948
|
-
const head = `${fmtType(r2.type)} ${
|
|
53511
|
+
const head = `${fmtType(r2.type)} ${import_picocolors28.default.bold(r2.slug)}`;
|
|
52949
53512
|
switch (r2.status) {
|
|
52950
53513
|
case "added-only-local":
|
|
52951
|
-
return `${head} ${
|
|
53514
|
+
return `${head} ${import_picocolors28.default.dim("(new — only in brainbase.agent.yaml)")}`;
|
|
52952
53515
|
case "added-cloud":
|
|
52953
|
-
return `${head} ${
|
|
53516
|
+
return `${head} ${import_picocolors28.default.dim("(new on cloud)")}`;
|
|
52954
53517
|
case "added-local":
|
|
52955
|
-
return `${head} ${
|
|
53518
|
+
return `${head} ${import_picocolors28.default.dim("(present locally and on cloud, never synced here)")}`;
|
|
52956
53519
|
case "removed-local":
|
|
52957
|
-
return `${head} ${
|
|
53520
|
+
return `${head} ${import_picocolors28.default.dim("(removed from brainbase.agent.yaml)")}`;
|
|
52958
53521
|
case "removed-cloud":
|
|
52959
|
-
return `${head} ${
|
|
53522
|
+
return `${head} ${import_picocolors28.default.dim("(removed on cloud)")}`;
|
|
52960
53523
|
case "modified-local":
|
|
52961
|
-
return `${head} ${
|
|
53524
|
+
return `${head} ${import_picocolors28.default.dim("(you edited it)")}`;
|
|
52962
53525
|
case "modified-cloud":
|
|
52963
|
-
return `${head} ${
|
|
53526
|
+
return `${head} ${import_picocolors28.default.dim("(cloud was updated)")}`;
|
|
52964
53527
|
case "modified-both":
|
|
52965
|
-
return `${head} ${
|
|
53528
|
+
return `${head} ${import_picocolors28.default.dim("(both diverged — needs resolution)")}`;
|
|
52966
53529
|
default:
|
|
52967
53530
|
return head;
|
|
52968
53531
|
}
|
|
@@ -52999,10 +53562,11 @@ function formatExport(shell, key2, value) {
|
|
|
52999
53562
|
}
|
|
53000
53563
|
|
|
53001
53564
|
// src/cli/agent-create.ts
|
|
53002
|
-
|
|
53565
|
+
import path49 from "node:path";
|
|
53566
|
+
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
53003
53567
|
|
|
53004
53568
|
// src/ui/box.ts
|
|
53005
|
-
var
|
|
53569
|
+
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
53006
53570
|
var H3 = "─";
|
|
53007
53571
|
var TINT = {
|
|
53008
53572
|
ok: COLOR.ok,
|
|
@@ -53014,20 +53578,28 @@ var TINT = {
|
|
|
53014
53578
|
function divider(label, width = 56, indent = 2) {
|
|
53015
53579
|
const ind = " ".repeat(indent);
|
|
53016
53580
|
if (!label)
|
|
53017
|
-
return `${ind}${
|
|
53581
|
+
return `${ind}${import_picocolors29.default.dim(H3.repeat(width))}`;
|
|
53018
53582
|
const labelText = ` ${label} `;
|
|
53019
53583
|
const labelLen = visibleLength(labelText);
|
|
53020
|
-
const left =
|
|
53021
|
-
const right =
|
|
53022
|
-
return `${ind}${left}${
|
|
53584
|
+
const left = import_picocolors29.default.dim(H3.repeat(2));
|
|
53585
|
+
const right = import_picocolors29.default.dim(H3.repeat(Math.max(0, width - labelLen - 2)));
|
|
53586
|
+
return `${ind}${left}${import_picocolors29.default.bold(import_picocolors29.default.dim(labelText))}${right}`;
|
|
53023
53587
|
}
|
|
53024
53588
|
function tip(text, indent = 2) {
|
|
53025
|
-
return " ".repeat(indent) +
|
|
53589
|
+
return " ".repeat(indent) + import_picocolors29.default.dim("›") + " " + import_picocolors29.default.dim(text);
|
|
53026
53590
|
}
|
|
53027
53591
|
|
|
53028
53592
|
// src/cli/agent-create.ts
|
|
53029
53593
|
async function runAgentCreate(cwd2, args) {
|
|
53030
|
-
banner("agent create —
|
|
53594
|
+
banner("agent create — claim a brainbase.agent.yaml and link this folder");
|
|
53595
|
+
let manifest = await loadOrScaffoldManifest(cwd2, args);
|
|
53596
|
+
if (!manifest)
|
|
53597
|
+
return;
|
|
53598
|
+
if (manifest.id) {
|
|
53599
|
+
f2.warn(`This folder already belongs to an agent — ${import_picocolors30.default.bold(manifest.agent.name)} (${import_picocolors30.default.dim(manifest.id)}).`);
|
|
53600
|
+
f2.info(`If you want to detach it, run ${import_picocolors30.default.cyan("brainbase unlink")} first; or move to a different directory.`);
|
|
53601
|
+
return;
|
|
53602
|
+
}
|
|
53031
53603
|
const orgsSpinner = de();
|
|
53032
53604
|
orgsSpinner.start("Loading your organizations…");
|
|
53033
53605
|
let orgs;
|
|
@@ -53054,7 +53626,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53054
53626
|
org = found;
|
|
53055
53627
|
} else if (orgs.length === 1) {
|
|
53056
53628
|
org = orgs[0];
|
|
53057
|
-
f2.info(`Using organization ${
|
|
53629
|
+
f2.info(`Using organization ${import_picocolors30.default.bold(org.name)}.`);
|
|
53058
53630
|
} else {
|
|
53059
53631
|
const orgChoice = await ie({
|
|
53060
53632
|
message: "Pick an organization",
|
|
@@ -53102,7 +53674,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53102
53674
|
createSpinner2.start("Creating team…");
|
|
53103
53675
|
try {
|
|
53104
53676
|
team = await api.createTeam(org.id, teamName.trim());
|
|
53105
|
-
createSpinner2.stop(`Created team ${
|
|
53677
|
+
createSpinner2.stop(`Created team ${import_picocolors30.default.bold(team.name)}.`);
|
|
53106
53678
|
} catch (err) {
|
|
53107
53679
|
createSpinner2.stop("Failed.");
|
|
53108
53680
|
handleApiError4(err);
|
|
@@ -53112,8 +53684,8 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53112
53684
|
team = teams.find((t) => t.id === picked);
|
|
53113
53685
|
}
|
|
53114
53686
|
}
|
|
53115
|
-
const harness = normalizeHarnessId(args.harness ?? await pickHarness(cwd2));
|
|
53116
|
-
let agentName = args.name?.trim();
|
|
53687
|
+
const harness = normalizeHarnessId(args.harness ?? manifest.harness ?? await pickHarness(cwd2));
|
|
53688
|
+
let agentName = args.name?.trim() || manifest.agent.name.trim();
|
|
53117
53689
|
if (!agentName) {
|
|
53118
53690
|
const ans = await te({
|
|
53119
53691
|
message: "Agent name",
|
|
@@ -53122,7 +53694,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53122
53694
|
});
|
|
53123
53695
|
agentName = ensureNotCancelled(ans).trim();
|
|
53124
53696
|
}
|
|
53125
|
-
let tagline = args.tagline?.trim() || undefined;
|
|
53697
|
+
let tagline = (args.tagline ?? manifest.agent.tagline)?.trim() || undefined;
|
|
53126
53698
|
if (tagline === undefined && !args.yes) {
|
|
53127
53699
|
const ans = await te({
|
|
53128
53700
|
message: "Tagline",
|
|
@@ -53134,11 +53706,11 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53134
53706
|
}
|
|
53135
53707
|
if (!args.yes) {
|
|
53136
53708
|
le([
|
|
53137
|
-
`${
|
|
53138
|
-
`${
|
|
53139
|
-
`${
|
|
53140
|
-
`${
|
|
53141
|
-
...tagline ? [`${
|
|
53709
|
+
`${import_picocolors30.default.dim("org")} ${import_picocolors30.default.bold(org.name)}`,
|
|
53710
|
+
`${import_picocolors30.default.dim("team")} ${import_picocolors30.default.bold(team.name)}`,
|
|
53711
|
+
`${import_picocolors30.default.dim("harness")} ${import_picocolors30.default.bold(harness)}`,
|
|
53712
|
+
`${import_picocolors30.default.dim("agent")} ${import_picocolors30.default.bold(agentName)}`,
|
|
53713
|
+
...tagline ? [`${import_picocolors30.default.dim("tagline")} ${tagline}`] : []
|
|
53142
53714
|
].join(`
|
|
53143
53715
|
`), "Will create");
|
|
53144
53716
|
const confirmed = await se({ message: "Create this agent?", initialValue: true });
|
|
@@ -53147,6 +53719,19 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53147
53719
|
return;
|
|
53148
53720
|
}
|
|
53149
53721
|
}
|
|
53722
|
+
let resolvedEntrypoint;
|
|
53723
|
+
if (manifest.entrypoint) {
|
|
53724
|
+
const body = resolveEntrypoint(cwd2, manifest);
|
|
53725
|
+
if (body === null) {
|
|
53726
|
+
if (manifest.entrypoint.file) {
|
|
53727
|
+
f2.error(`Entrypoint file ${import_picocolors30.default.bold(manifest.entrypoint.file)} not found.`);
|
|
53728
|
+
} else {
|
|
53729
|
+
f2.error("Entrypoint block is empty.");
|
|
53730
|
+
}
|
|
53731
|
+
return;
|
|
53732
|
+
}
|
|
53733
|
+
resolvedEntrypoint = body;
|
|
53734
|
+
}
|
|
53150
53735
|
const createSpinner = de();
|
|
53151
53736
|
createSpinner.start("Creating agent…");
|
|
53152
53737
|
let agent;
|
|
@@ -53156,9 +53741,10 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53156
53741
|
team_id: team.id,
|
|
53157
53742
|
name: agentName,
|
|
53158
53743
|
tagline,
|
|
53159
|
-
harness
|
|
53744
|
+
harness,
|
|
53745
|
+
...resolvedEntrypoint !== undefined ? { entrypoint: resolvedEntrypoint } : {}
|
|
53160
53746
|
});
|
|
53161
|
-
createSpinner.stop(`Created ${
|
|
53747
|
+
createSpinner.stop(`Created ${import_picocolors30.default.bold(agent.name)}.`);
|
|
53162
53748
|
} catch (err) {
|
|
53163
53749
|
createSpinner.stop("Failed.");
|
|
53164
53750
|
handleApiError4(err);
|
|
@@ -53171,7 +53757,7 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53171
53757
|
let wantsTracking = true;
|
|
53172
53758
|
if (!args.yes) {
|
|
53173
53759
|
const ans = await se({
|
|
53174
|
-
message: `Track ${harness} conversations on the brainbase platform? ${
|
|
53760
|
+
message: `Track ${harness} conversations on the brainbase platform? ${import_picocolors30.default.dim("(routes LLM calls through brainbase so they appear under this agent)")}`,
|
|
53175
53761
|
initialValue: true
|
|
53176
53762
|
});
|
|
53177
53763
|
wantsTracking = ensureNotCancelled(ans);
|
|
@@ -53225,7 +53811,54 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53225
53811
|
tracking
|
|
53226
53812
|
};
|
|
53227
53813
|
writeLink(cwd2, link2);
|
|
53228
|
-
|
|
53814
|
+
manifest = readManifest(cwd2);
|
|
53815
|
+
let updatedCloud = null;
|
|
53816
|
+
const hasContent = !!manifest.instructions || manifest.skills.length > 0 || (manifest.mcp ?? []).length > 0;
|
|
53817
|
+
if (hasContent) {
|
|
53818
|
+
const outgoing = await buildOutgoingComponents(cwd2, manifest, null);
|
|
53819
|
+
if (outgoing === null) {
|
|
53820
|
+
f2.warn(`Agent created, but local content wasn't uploaded. Fix the issue above and run ${import_picocolors30.default.cyan("brainbase agent push")}.`);
|
|
53821
|
+
} else if (outgoing.length > 0) {
|
|
53822
|
+
const pushSpinner = de();
|
|
53823
|
+
pushSpinner.start("Pushing local content…");
|
|
53824
|
+
try {
|
|
53825
|
+
updatedCloud = await api.pushAgentManifest(agent.id, {
|
|
53826
|
+
components: outgoing,
|
|
53827
|
+
base_revision: 0
|
|
53828
|
+
});
|
|
53829
|
+
pushSpinner.stop(`Pushed at revision ${updatedCloud.revision}.`);
|
|
53830
|
+
} catch (err) {
|
|
53831
|
+
pushSpinner.stop("Failed.");
|
|
53832
|
+
if (err instanceof ApiError) {
|
|
53833
|
+
f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors30.default.cyan("brainbase agent push")} to retry.`);
|
|
53834
|
+
} else {
|
|
53835
|
+
f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors30.default.cyan("brainbase agent push")} to retry.`);
|
|
53836
|
+
}
|
|
53837
|
+
}
|
|
53838
|
+
}
|
|
53839
|
+
}
|
|
53840
|
+
if (updatedCloud) {
|
|
53841
|
+
const syncedComponents = updatedCloud.components.map((c2) => ({
|
|
53842
|
+
type: c2.type,
|
|
53843
|
+
slug: c2.slug,
|
|
53844
|
+
hash: c2.hash,
|
|
53845
|
+
installedPaths: []
|
|
53846
|
+
}));
|
|
53847
|
+
const state = {
|
|
53848
|
+
schemaVersion: 1,
|
|
53849
|
+
agent_id: agent.id,
|
|
53850
|
+
revision: updatedCloud.revision,
|
|
53851
|
+
synced_at: new Date().toISOString(),
|
|
53852
|
+
components: syncedComponents,
|
|
53853
|
+
agentMeta: {
|
|
53854
|
+
name: agent.name,
|
|
53855
|
+
tagline: agent.tagline,
|
|
53856
|
+
...resolvedEntrypoint ? { entrypoint: resolvedEntrypoint } : {}
|
|
53857
|
+
}
|
|
53858
|
+
};
|
|
53859
|
+
writeSyncState(cwd2, state);
|
|
53860
|
+
}
|
|
53861
|
+
$e(`Created ${import_picocolors30.default.bold(agent.name)} and linked this folder.`);
|
|
53229
53862
|
await showResultCard({
|
|
53230
53863
|
title: "CREATED",
|
|
53231
53864
|
tone: "ok",
|
|
@@ -53238,16 +53871,55 @@ async function runAgentCreate(cwd2, args) {
|
|
|
53238
53871
|
});
|
|
53239
53872
|
console.log();
|
|
53240
53873
|
if (tracking && harness === "codex") {
|
|
53241
|
-
console.log(tip(`Run ${
|
|
53874
|
+
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.")}`));
|
|
53242
53875
|
}
|
|
53243
|
-
console.log(tip(`brainbase agent
|
|
53876
|
+
console.log(tip(`brainbase agent unpack ${import_picocolors30.default.dim("— install harness files (skills/mcps) under .claude/, .codex/, …")}`));
|
|
53244
53877
|
console.log();
|
|
53245
53878
|
}
|
|
53879
|
+
async function loadOrScaffoldManifest(cwd2, args) {
|
|
53880
|
+
if (hasManifest(cwd2)) {
|
|
53881
|
+
try {
|
|
53882
|
+
return readManifest(cwd2);
|
|
53883
|
+
} catch (err) {
|
|
53884
|
+
f2.error(err.message);
|
|
53885
|
+
return null;
|
|
53886
|
+
}
|
|
53887
|
+
}
|
|
53888
|
+
f2.warn(`No ${import_picocolors30.default.bold(AGENT_MANIFEST_FILE)} here.`);
|
|
53889
|
+
if (!args.yes) {
|
|
53890
|
+
const ans = await se({
|
|
53891
|
+
message: `Scaffold a minimal ${import_picocolors30.default.bold(AGENT_MANIFEST_FILE)} and continue?`,
|
|
53892
|
+
initialValue: true
|
|
53893
|
+
});
|
|
53894
|
+
if (!ensureNotCancelled(ans)) {
|
|
53895
|
+
$e("Aborted.");
|
|
53896
|
+
return null;
|
|
53897
|
+
}
|
|
53898
|
+
}
|
|
53899
|
+
const seedName = args.name?.trim() ?? path49.basename(path49.resolve(cwd2)) ?? "My Agent";
|
|
53900
|
+
const seedHarness = args.harness ? normalizeHarnessId(args.harness) : undefined;
|
|
53901
|
+
const scaffold = {
|
|
53902
|
+
schema: 1,
|
|
53903
|
+
...seedHarness ? { harness: seedHarness } : {},
|
|
53904
|
+
agent: { name: seedName, ...args.tagline ? { tagline: args.tagline } : {} },
|
|
53905
|
+
playbooks: [],
|
|
53906
|
+
skills: [],
|
|
53907
|
+
mcp: []
|
|
53908
|
+
};
|
|
53909
|
+
try {
|
|
53910
|
+
writeManifest(cwd2, scaffold);
|
|
53911
|
+
f2.info(`Wrote ${import_picocolors30.default.bold(AGENT_MANIFEST_FILE)}.`);
|
|
53912
|
+
} catch (err) {
|
|
53913
|
+
f2.error(`Failed to write manifest: ${err.message}`);
|
|
53914
|
+
return null;
|
|
53915
|
+
}
|
|
53916
|
+
return scaffold;
|
|
53917
|
+
}
|
|
53246
53918
|
async function pickHarness(cwd2) {
|
|
53247
53919
|
const detections = await detectHarnesses(cwd2);
|
|
53248
53920
|
const detected = detections.filter((d3) => d3.detection.detected);
|
|
53249
53921
|
if (detected.length === 1) {
|
|
53250
|
-
f2.info(`Detected harness: ${
|
|
53922
|
+
f2.info(`Detected harness: ${import_picocolors30.default.bold(detected[0].adapter.displayName)}.`);
|
|
53251
53923
|
return detected[0].adapter.id;
|
|
53252
53924
|
}
|
|
53253
53925
|
const choice = await ie({
|
|
@@ -53273,8 +53945,268 @@ function handleApiError4(err) {
|
|
|
53273
53945
|
$e("Aborted.");
|
|
53274
53946
|
}
|
|
53275
53947
|
|
|
53948
|
+
// src/cli/agent-unpack.ts
|
|
53949
|
+
import path50 from "node:path";
|
|
53950
|
+
import fs46 from "node:fs";
|
|
53951
|
+
import os13 from "node:os";
|
|
53952
|
+
var import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
53953
|
+
async function runAgentUnpack(cwd2, args) {
|
|
53954
|
+
banner("agent unpack — install this agent into a harness layout");
|
|
53955
|
+
if (!hasManifest(cwd2)) {
|
|
53956
|
+
f2.error(`No ${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} here.`);
|
|
53957
|
+
f2.info(`Run ${import_picocolors31.default.cyan("brainbase agent pull <id>")} to bring an agent into this folder first.`);
|
|
53958
|
+
return;
|
|
53959
|
+
}
|
|
53960
|
+
let manifest;
|
|
53961
|
+
try {
|
|
53962
|
+
manifest = readManifest(cwd2);
|
|
53963
|
+
} catch (err) {
|
|
53964
|
+
f2.error(err.message);
|
|
53965
|
+
return;
|
|
53966
|
+
}
|
|
53967
|
+
if (!manifest.id) {
|
|
53968
|
+
f2.error(`${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} is unclaimed (no ${import_picocolors31.default.cyan("id")}).`);
|
|
53969
|
+
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.`);
|
|
53970
|
+
return;
|
|
53971
|
+
}
|
|
53972
|
+
let harness;
|
|
53973
|
+
if (args.harness) {
|
|
53974
|
+
harness = normalizeHarnessId(args.harness);
|
|
53975
|
+
} else if (args.yes) {
|
|
53976
|
+
if (!manifest.harness) {
|
|
53977
|
+
f2.error(`--yes mode but no harness — set ${import_picocolors31.default.cyan("harness")} in the manifest or pass ${import_picocolors31.default.cyan("--harness")}.`);
|
|
53978
|
+
return;
|
|
53979
|
+
}
|
|
53980
|
+
harness = normalizeHarnessId(manifest.harness);
|
|
53981
|
+
} else {
|
|
53982
|
+
harness = await pickHarness2(manifest.harness);
|
|
53983
|
+
}
|
|
53984
|
+
if (!args.yes) {
|
|
53985
|
+
const ok = await se({
|
|
53986
|
+
message: `Install ${import_picocolors31.default.bold(manifest.agent.name)} as ${import_picocolors31.default.bold(harness)} here?`,
|
|
53987
|
+
initialValue: true
|
|
53988
|
+
});
|
|
53989
|
+
if (!ensureNotCancelled(ok)) {
|
|
53990
|
+
$e("Aborted.");
|
|
53991
|
+
return;
|
|
53992
|
+
}
|
|
53993
|
+
}
|
|
53994
|
+
const scope = args.scope ?? "project";
|
|
53995
|
+
const stageRoot = fs46.mkdtempSync(path50.join(os13.tmpdir(), "brainbase-unpack-"));
|
|
53996
|
+
try {
|
|
53997
|
+
const toInstall = [];
|
|
53998
|
+
const instructionsBody = readInstructions(cwd2, manifest);
|
|
53999
|
+
if (instructionsBody && instructionsBody.trim()) {
|
|
54000
|
+
const compDir = path50.join(stageRoot, "instruction", "agent-instructions");
|
|
54001
|
+
ensureDir(compDir);
|
|
54002
|
+
fs46.writeFileSync(path50.join(compDir, "instructions.md"), instructionsBody, "utf8");
|
|
54003
|
+
toInstall.push({
|
|
54004
|
+
type: "instruction",
|
|
54005
|
+
slug: "agent-instructions",
|
|
54006
|
+
scope,
|
|
54007
|
+
rootDir: compDir,
|
|
54008
|
+
description: "Agent instructions",
|
|
54009
|
+
checksum: ""
|
|
54010
|
+
});
|
|
54011
|
+
}
|
|
54012
|
+
for (const entry of manifest.playbooks ?? []) {
|
|
54013
|
+
const issue = stageLocalPlaybook(entry, cwd2, stageRoot, scope, toInstall);
|
|
54014
|
+
if (issue) {
|
|
54015
|
+
f2.warn(issue);
|
|
54016
|
+
}
|
|
54017
|
+
}
|
|
54018
|
+
for (const entry of manifest.skills ?? []) {
|
|
54019
|
+
const issue = stageLocalSkill(entry.source, cwd2, stageRoot, scope, toInstall);
|
|
54020
|
+
if (issue) {
|
|
54021
|
+
f2.warn(issue);
|
|
54022
|
+
}
|
|
54023
|
+
}
|
|
54024
|
+
for (const entry of manifest.mcp ?? []) {
|
|
54025
|
+
const compDir = path50.join(stageRoot, "mcp", entry.name);
|
|
54026
|
+
ensureDir(compDir);
|
|
54027
|
+
const payload = {};
|
|
54028
|
+
if (entry.url !== undefined)
|
|
54029
|
+
payload.url = entry.url;
|
|
54030
|
+
if (entry.command !== undefined)
|
|
54031
|
+
payload.command = entry.command;
|
|
54032
|
+
if (entry.args !== undefined)
|
|
54033
|
+
payload.args = entry.args;
|
|
54034
|
+
if (entry.env !== undefined)
|
|
54035
|
+
payload.env = entry.env;
|
|
54036
|
+
if (entry.headers !== undefined)
|
|
54037
|
+
payload.headers = entry.headers;
|
|
54038
|
+
payload.is_enabled = entry.is_enabled ?? true;
|
|
54039
|
+
toInstall.push({
|
|
54040
|
+
type: "mcp",
|
|
54041
|
+
slug: entry.name,
|
|
54042
|
+
scope,
|
|
54043
|
+
rootDir: compDir,
|
|
54044
|
+
payload,
|
|
54045
|
+
checksum: ""
|
|
54046
|
+
});
|
|
54047
|
+
}
|
|
54048
|
+
const haveOrchMcp = (manifest.mcp ?? []).some((m3) => m3.name === ORCHESTRATION_MCP_SLUG);
|
|
54049
|
+
const haveMemoryMcp = (manifest.mcp ?? []).some((m3) => m3.name === MEMORY_MCP_SLUG);
|
|
54050
|
+
if (!haveOrchMcp)
|
|
54051
|
+
toInstall.push(buildOrchestrationMcpComponent(scope));
|
|
54052
|
+
if (!haveMemoryMcp)
|
|
54053
|
+
toInstall.push(buildMemoryMcpComponent(scope));
|
|
54054
|
+
const opts = {
|
|
54055
|
+
cwd: cwd2,
|
|
54056
|
+
scope,
|
|
54057
|
+
resolveConflict: async (_c) => "overwrite",
|
|
54058
|
+
resolveSecret: async () => null
|
|
54059
|
+
};
|
|
54060
|
+
const sp = de();
|
|
54061
|
+
sp.start("Installing harness layout…");
|
|
54062
|
+
const result = await runHarnessInstall3(harness, toInstall, opts, manifest.agent.name);
|
|
54063
|
+
sp.stop("Installed.");
|
|
54064
|
+
if (result.skipped.length) {
|
|
54065
|
+
f2.warn(`Skipped: ${result.skipped.map((s3) => `${s3.type}/${s3.slug} (${s3.reason})`).join(", ")}`);
|
|
54066
|
+
}
|
|
54067
|
+
} catch (err) {
|
|
54068
|
+
f2.error(`Install failed: ${err.message}`);
|
|
54069
|
+
return;
|
|
54070
|
+
} finally {
|
|
54071
|
+
try {
|
|
54072
|
+
fs46.rmSync(stageRoot, { recursive: true, force: true });
|
|
54073
|
+
} catch {}
|
|
54074
|
+
}
|
|
54075
|
+
if (manifest.harness !== harness) {
|
|
54076
|
+
manifest.harness = harness;
|
|
54077
|
+
writeManifest(cwd2, manifest);
|
|
54078
|
+
}
|
|
54079
|
+
$e(`Unpacked ${import_picocolors31.default.bold(manifest.agent.name)} as ${import_picocolors31.default.bold(harness)}.`);
|
|
54080
|
+
await showResultCard({
|
|
54081
|
+
title: "UNPACKED",
|
|
54082
|
+
tone: "ok",
|
|
54083
|
+
subtitle: manifest.agent.name,
|
|
54084
|
+
meta: [
|
|
54085
|
+
["harness", harness],
|
|
54086
|
+
["agent", manifest.id]
|
|
54087
|
+
]
|
|
54088
|
+
});
|
|
54089
|
+
}
|
|
54090
|
+
function stageLocalPlaybook(entry, cwd2, stageRoot, scope, toInstall) {
|
|
54091
|
+
if (entry.content.text !== undefined && entry.content.file !== undefined) {
|
|
54092
|
+
return `Playbook ${entry.title}: both text and file set — skipped.`;
|
|
54093
|
+
}
|
|
54094
|
+
const body = resolvePlaybookContent(cwd2, entry);
|
|
54095
|
+
if (body === null) {
|
|
54096
|
+
return entry.content.file ? `Playbook ${entry.title}: file ${entry.content.file} not found — skipped.` : `Playbook ${entry.title}: content empty — skipped.`;
|
|
54097
|
+
}
|
|
54098
|
+
const slug = slugifyPlaybookTitle(entry.title);
|
|
54099
|
+
const compDir = path50.join(stageRoot, "playbook", slug);
|
|
54100
|
+
ensureDir(compDir);
|
|
54101
|
+
const wireBody = /^---\s*\n/.test(body) ? body : assembleFrontmatter(entry.title, entry.description) + body.replace(/^\n+/, "");
|
|
54102
|
+
fs46.writeFileSync(path50.join(compDir, `${slug}.md`), wireBody, "utf8");
|
|
54103
|
+
toInstall.push({
|
|
54104
|
+
type: "playbook",
|
|
54105
|
+
slug,
|
|
54106
|
+
scope,
|
|
54107
|
+
rootDir: compDir,
|
|
54108
|
+
description: entry.description,
|
|
54109
|
+
checksum: ""
|
|
54110
|
+
});
|
|
54111
|
+
return null;
|
|
54112
|
+
}
|
|
54113
|
+
function stageLocalSkill(source, cwd2, stageRoot, scope, toInstall) {
|
|
54114
|
+
if (source.startsWith("./") || source.startsWith("../") || source.startsWith("/")) {
|
|
54115
|
+
const abs = path50.resolve(cwd2, source);
|
|
54116
|
+
if (!fs46.existsSync(abs)) {
|
|
54117
|
+
return `Skill ${source}: not found on disk — skipped.`;
|
|
54118
|
+
}
|
|
54119
|
+
const slug = path50.basename(abs);
|
|
54120
|
+
const compDir = path50.join(stageRoot, "skill", slug);
|
|
54121
|
+
ensureDir(compDir);
|
|
54122
|
+
copyDirRecursive(abs, compDir);
|
|
54123
|
+
toInstall.push({
|
|
54124
|
+
type: "skill",
|
|
54125
|
+
slug,
|
|
54126
|
+
scope,
|
|
54127
|
+
rootDir: compDir,
|
|
54128
|
+
checksum: ""
|
|
54129
|
+
});
|
|
54130
|
+
return null;
|
|
54131
|
+
}
|
|
54132
|
+
try {
|
|
54133
|
+
const parsed = parseSkillSource(source);
|
|
54134
|
+
if (parsed.type === "local" || parsed.type === "inline")
|
|
54135
|
+
return null;
|
|
54136
|
+
const slug = defaultSlugForSource(source);
|
|
54137
|
+
const compDir = path50.join(stageRoot, "skill", slug);
|
|
54138
|
+
ensureDir(compDir);
|
|
54139
|
+
toInstall.push({
|
|
54140
|
+
type: "skill",
|
|
54141
|
+
slug,
|
|
54142
|
+
scope,
|
|
54143
|
+
rootDir: compDir,
|
|
54144
|
+
source: parsed,
|
|
54145
|
+
checksum: ""
|
|
54146
|
+
});
|
|
54147
|
+
return null;
|
|
54148
|
+
} catch (err) {
|
|
54149
|
+
return `Skill ${source}: ${err.message} — skipped.`;
|
|
54150
|
+
}
|
|
54151
|
+
}
|
|
54152
|
+
function defaultSlugForSource(source) {
|
|
54153
|
+
const reg = /^registry:(?:[a-z0-9_-]+\/)?([a-z0-9_-]+)/i.exec(source);
|
|
54154
|
+
if (reg)
|
|
54155
|
+
return reg[1].toLowerCase();
|
|
54156
|
+
const gh = /^(?:github|git):[^/]*\/?([a-z0-9_-]+)/i.exec(source);
|
|
54157
|
+
if (gh)
|
|
54158
|
+
return gh[1].toLowerCase();
|
|
54159
|
+
return source.replace(/[^a-z0-9_-]/gi, "-").slice(0, 60) || "skill";
|
|
54160
|
+
}
|
|
54161
|
+
function copyDirRecursive(src, dest) {
|
|
54162
|
+
ensureDir(dest);
|
|
54163
|
+
for (const entry of fs46.readdirSync(src, { withFileTypes: true })) {
|
|
54164
|
+
const s3 = path50.join(src, entry.name);
|
|
54165
|
+
const d3 = path50.join(dest, entry.name);
|
|
54166
|
+
if (entry.isDirectory())
|
|
54167
|
+
copyDirRecursive(s3, d3);
|
|
54168
|
+
else if (entry.isFile())
|
|
54169
|
+
fs46.copyFileSync(s3, d3);
|
|
54170
|
+
}
|
|
54171
|
+
}
|
|
54172
|
+
function assembleFrontmatter(title, description) {
|
|
54173
|
+
const lines = ["---", `title: ${yamlScalar2(title)}`];
|
|
54174
|
+
if (description)
|
|
54175
|
+
lines.push(`description: ${yamlScalar2(description)}`);
|
|
54176
|
+
lines.push("---", "");
|
|
54177
|
+
return lines.join(`
|
|
54178
|
+
`);
|
|
54179
|
+
}
|
|
54180
|
+
function yamlScalar2(s3) {
|
|
54181
|
+
if (!/[\n":#&*!|>'%@`{}[\]]/.test(s3) && s3.trim() === s3 && s3 !== "")
|
|
54182
|
+
return s3;
|
|
54183
|
+
return JSON.stringify(s3);
|
|
54184
|
+
}
|
|
54185
|
+
function runHarnessInstall3(harnessId, components, opts, agentName) {
|
|
54186
|
+
if (harnessId === "claude-code")
|
|
54187
|
+
return installClaudeCodeWithCtx(components, opts, agentName);
|
|
54188
|
+
if (harnessId === "codex")
|
|
54189
|
+
return installCodexWithCtx(components, opts, agentName);
|
|
54190
|
+
if (harnessId === "kafka")
|
|
54191
|
+
return installKafkaWithCtx(components, opts, agentName);
|
|
54192
|
+
return getAdapter(harnessId).install(components, opts);
|
|
54193
|
+
}
|
|
54194
|
+
async function pickHarness2(current) {
|
|
54195
|
+
const initial = current ? normalizeHarnessId(current) : undefined;
|
|
54196
|
+
const choice = await ie({
|
|
54197
|
+
message: "Pick a harness to install as",
|
|
54198
|
+
options: adapters.map((a3) => ({
|
|
54199
|
+
value: a3.id,
|
|
54200
|
+
label: a3.displayName,
|
|
54201
|
+
hint: a3.id === initial ? "current" : undefined
|
|
54202
|
+
})),
|
|
54203
|
+
initialValue: initial ?? adapters[0].id
|
|
54204
|
+
});
|
|
54205
|
+
return ensureNotCancelled(choice);
|
|
54206
|
+
}
|
|
54207
|
+
|
|
53276
54208
|
// src/cli/agent.ts
|
|
53277
|
-
async function runAgent(cwd2, sub,
|
|
54209
|
+
async function runAgent(cwd2, sub, args, opts) {
|
|
53278
54210
|
switch (sub) {
|
|
53279
54211
|
case "create":
|
|
53280
54212
|
await runAgentCreate(cwd2, {
|
|
@@ -53288,10 +54220,22 @@ async function runAgent(cwd2, sub, _args, opts) {
|
|
|
53288
54220
|
});
|
|
53289
54221
|
return;
|
|
53290
54222
|
case "pull":
|
|
53291
|
-
await runAgentPull(cwd2,
|
|
54223
|
+
await runAgentPull(cwd2, {
|
|
54224
|
+
yes: opts.yes,
|
|
54225
|
+
scope: opts.scope,
|
|
54226
|
+
agentIdArg: args[0],
|
|
54227
|
+
force: opts.force
|
|
54228
|
+
});
|
|
53292
54229
|
return;
|
|
53293
54230
|
case "push":
|
|
53294
|
-
await runAgentPush(cwd2, opts);
|
|
54231
|
+
await runAgentPush(cwd2, { yes: opts.yes });
|
|
54232
|
+
return;
|
|
54233
|
+
case "unpack":
|
|
54234
|
+
await runAgentUnpack(cwd2, {
|
|
54235
|
+
yes: opts.yes,
|
|
54236
|
+
scope: opts.scope,
|
|
54237
|
+
harness: opts.harness
|
|
54238
|
+
});
|
|
53295
54239
|
return;
|
|
53296
54240
|
case "status":
|
|
53297
54241
|
await runAgentStatus(cwd2);
|
|
@@ -53315,30 +54259,31 @@ async function runAgent(cwd2, sub, _args, opts) {
|
|
|
53315
54259
|
function printHelp() {
|
|
53316
54260
|
const out = [];
|
|
53317
54261
|
out.push("");
|
|
53318
|
-
out.push(` ${
|
|
54262
|
+
out.push(` ${import_picocolors32.default.bold("brainbase agent")} ${import_picocolors32.default.dim("<sub> [options]")}`);
|
|
53319
54263
|
out.push("");
|
|
53320
|
-
out.push(` ${
|
|
53321
|
-
out.push(` ${
|
|
53322
|
-
out.push(` ${
|
|
53323
|
-
out.push(` ${
|
|
53324
|
-
out.push(` ${
|
|
54264
|
+
out.push(` ${import_picocolors32.default.cyan("create")} ${import_picocolors32.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
54265
|
+
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)")}`);
|
|
54266
|
+
out.push(` ${import_picocolors32.default.cyan("push")} ${import_picocolors32.default.dim("send local changes to the cloud")}`);
|
|
54267
|
+
out.push(` ${import_picocolors32.default.cyan("unpack")} ${import_picocolors32.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
|
|
54268
|
+
out.push(` ${import_picocolors32.default.cyan("status")} ${import_picocolors32.default.dim("show what would push and what would pull")}`);
|
|
54269
|
+
out.push(` ${import_picocolors32.default.cyan("env")} ${import_picocolors32.default.dim('print export statements — use with `eval "$(brainbase agent env)"`')}`);
|
|
53325
54270
|
out.push("");
|
|
53326
54271
|
console.log(out.join(`
|
|
53327
54272
|
`));
|
|
53328
54273
|
}
|
|
53329
54274
|
|
|
53330
54275
|
// src/cli/orchestration.ts
|
|
53331
|
-
var
|
|
54276
|
+
var import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
53332
54277
|
|
|
53333
54278
|
// src/cli/orchestration-pull.ts
|
|
53334
|
-
import
|
|
53335
|
-
import
|
|
53336
|
-
var
|
|
54279
|
+
import path54 from "node:path";
|
|
54280
|
+
import fs50 from "node:fs";
|
|
54281
|
+
var import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
53337
54282
|
|
|
53338
54283
|
// src/core/orchestration-manifest.ts
|
|
53339
|
-
import
|
|
53340
|
-
import
|
|
53341
|
-
var
|
|
54284
|
+
import path51 from "node:path";
|
|
54285
|
+
import fs47 from "node:fs";
|
|
54286
|
+
var import_yaml4 = __toESM(require_dist(), 1);
|
|
53342
54287
|
var ORCH_MANIFEST_FILE = "brainbase-orchestration.yaml";
|
|
53343
54288
|
var ORCH_MEMBERS_DIR = "agents";
|
|
53344
54289
|
var OrchMetaSchema = exports_external.object({
|
|
@@ -53365,19 +54310,19 @@ var OrchestrationManifestSchema = exports_external.object({
|
|
|
53365
54310
|
edges: exports_external.array(EdgeSchema).default([])
|
|
53366
54311
|
});
|
|
53367
54312
|
function orchManifestPath(cwd2) {
|
|
53368
|
-
return
|
|
54313
|
+
return path51.join(cwd2, ORCH_MANIFEST_FILE);
|
|
53369
54314
|
}
|
|
53370
54315
|
function hasOrchManifest(cwd2) {
|
|
53371
|
-
return
|
|
54316
|
+
return fs47.existsSync(orchManifestPath(cwd2));
|
|
53372
54317
|
}
|
|
53373
54318
|
function readOrchManifest(cwd2) {
|
|
53374
54319
|
const p2 = orchManifestPath(cwd2);
|
|
53375
|
-
if (!
|
|
54320
|
+
if (!fs47.existsSync(p2))
|
|
53376
54321
|
return null;
|
|
53377
|
-
const raw =
|
|
54322
|
+
const raw = fs47.readFileSync(p2, "utf8");
|
|
53378
54323
|
let parsed;
|
|
53379
54324
|
try {
|
|
53380
|
-
parsed =
|
|
54325
|
+
parsed = import_yaml4.default.parse(raw);
|
|
53381
54326
|
} catch (err) {
|
|
53382
54327
|
throw new Error(`${ORCH_MANIFEST_FILE} is not valid YAML: ${err.message}`);
|
|
53383
54328
|
}
|
|
@@ -53388,20 +54333,20 @@ function readOrchManifest(cwd2) {
|
|
|
53388
54333
|
return result.data;
|
|
53389
54334
|
}
|
|
53390
54335
|
function writeOrchManifest(cwd2, manifest) {
|
|
53391
|
-
const doc = new
|
|
54336
|
+
const doc = new import_yaml4.default.Document;
|
|
53392
54337
|
doc.contents = manifest;
|
|
53393
54338
|
doc.commentBefore = ` brainbase-orchestration.yaml — declarative orchestration manifest.
|
|
53394
54339
|
` + ` Committed to source control. Edit by hand, then
|
|
53395
54340
|
` + " `brainbase orchestration push`. Member agents live under ./agents/.";
|
|
53396
|
-
|
|
54341
|
+
fs47.writeFileSync(orchManifestPath(cwd2), String(doc), "utf8");
|
|
53397
54342
|
}
|
|
53398
54343
|
function memberDir(cwd2, slug) {
|
|
53399
|
-
return
|
|
54344
|
+
return path51.join(cwd2, ORCH_MEMBERS_DIR, slug);
|
|
53400
54345
|
}
|
|
53401
54346
|
|
|
53402
54347
|
// src/core/orchestration-link.ts
|
|
53403
|
-
import
|
|
53404
|
-
import
|
|
54348
|
+
import path52 from "node:path";
|
|
54349
|
+
import fs48 from "node:fs";
|
|
53405
54350
|
var ORCH_LINK_FILE = "orchestration-link.json";
|
|
53406
54351
|
var ORCH_SYNC_STATE_FILE = "orchestration-sync-state.json";
|
|
53407
54352
|
var OrchestrationLinkSchema = exports_external.object({
|
|
@@ -53435,10 +54380,10 @@ var OrchestrationSyncStateSchema = exports_external.object({
|
|
|
53435
54380
|
edges: exports_external.array(SyncedEdgeSchema)
|
|
53436
54381
|
});
|
|
53437
54382
|
function orchLinkPath(cwd2) {
|
|
53438
|
-
return
|
|
54383
|
+
return path52.join(cwd2, LINK_DIR, ORCH_LINK_FILE);
|
|
53439
54384
|
}
|
|
53440
54385
|
function orchSyncStatePath(cwd2) {
|
|
53441
|
-
return
|
|
54386
|
+
return path52.join(cwd2, LINK_DIR, ORCH_SYNC_STATE_FILE);
|
|
53442
54387
|
}
|
|
53443
54388
|
function readOrchLink(cwd2) {
|
|
53444
54389
|
const p2 = orchLinkPath(cwd2);
|
|
@@ -53451,7 +54396,7 @@ function readOrchLink(cwd2) {
|
|
|
53451
54396
|
}
|
|
53452
54397
|
}
|
|
53453
54398
|
function writeOrchLink(cwd2, link2) {
|
|
53454
|
-
ensureDir(
|
|
54399
|
+
ensureDir(path52.join(cwd2, LINK_DIR));
|
|
53455
54400
|
const clean = {};
|
|
53456
54401
|
for (const [k3, v3] of Object.entries(link2)) {
|
|
53457
54402
|
if (v3 !== null && v3 !== undefined)
|
|
@@ -53471,22 +54416,22 @@ function readOrchSyncState(cwd2) {
|
|
|
53471
54416
|
}
|
|
53472
54417
|
}
|
|
53473
54418
|
function writeOrchSyncState(cwd2, state) {
|
|
53474
|
-
ensureDir(
|
|
54419
|
+
ensureDir(path52.join(cwd2, LINK_DIR));
|
|
53475
54420
|
writeJson(orchSyncStatePath(cwd2), state);
|
|
53476
54421
|
ensureGitignore2(cwd2);
|
|
53477
54422
|
}
|
|
53478
54423
|
function ensureGitignore2(cwd2) {
|
|
53479
|
-
const ignorePath =
|
|
54424
|
+
const ignorePath = path52.join(cwd2, LINK_DIR, ".gitignore");
|
|
53480
54425
|
const desired = `${ORCH_SYNC_STATE_FILE}
|
|
53481
54426
|
`;
|
|
53482
54427
|
try {
|
|
53483
54428
|
if (!exists(ignorePath)) {
|
|
53484
|
-
|
|
54429
|
+
fs48.writeFileSync(ignorePath, desired);
|
|
53485
54430
|
return;
|
|
53486
54431
|
}
|
|
53487
|
-
const current =
|
|
54432
|
+
const current = fs48.readFileSync(ignorePath, "utf8");
|
|
53488
54433
|
if (!current.split(/\r?\n/).some((l2) => l2.trim() === ORCH_SYNC_STATE_FILE)) {
|
|
53489
|
-
|
|
54434
|
+
fs48.writeFileSync(ignorePath, current.endsWith(`
|
|
53490
54435
|
`) ? current + desired : current + `
|
|
53491
54436
|
` + desired);
|
|
53492
54437
|
}
|
|
@@ -53494,9 +54439,9 @@ function ensureGitignore2(cwd2) {
|
|
|
53494
54439
|
}
|
|
53495
54440
|
|
|
53496
54441
|
// src/core/agent-fresh-install.ts
|
|
53497
|
-
import
|
|
53498
|
-
import
|
|
53499
|
-
import
|
|
54442
|
+
import path53 from "node:path";
|
|
54443
|
+
import fs49 from "node:fs";
|
|
54444
|
+
import os14 from "node:os";
|
|
53500
54445
|
async function installAgentFresh(input) {
|
|
53501
54446
|
const { cwd: cwd2, agent, cloud, harness } = input;
|
|
53502
54447
|
const scope = input.scope ?? "project";
|
|
@@ -53513,7 +54458,7 @@ async function installAgentFresh(input) {
|
|
|
53513
54458
|
type: c2.type,
|
|
53514
54459
|
slug: c2.slug,
|
|
53515
54460
|
scope,
|
|
53516
|
-
rootDir:
|
|
54461
|
+
rootDir: path53.join(stageRoot, c2.type, c2.slug),
|
|
53517
54462
|
description: c2.description,
|
|
53518
54463
|
meta: c2.meta,
|
|
53519
54464
|
payload: c2.meta?.mcp,
|
|
@@ -53531,14 +54476,15 @@ async function installAgentFresh(input) {
|
|
|
53531
54476
|
resolveConflict: async (_c) => "overwrite",
|
|
53532
54477
|
resolveSecret: async () => null
|
|
53533
54478
|
};
|
|
53534
|
-
const result = await
|
|
54479
|
+
const result = await runHarnessInstall4(harness, toInstall, installOpts, agent.name);
|
|
53535
54480
|
for (const o2 of result.installed) {
|
|
53536
54481
|
justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
|
|
53537
54482
|
}
|
|
53538
54483
|
}
|
|
53539
54484
|
materializeInstructions2(cwd2, cloud);
|
|
53540
|
-
const manifest = buildManifestFromCloud(cloud, agent);
|
|
53541
|
-
|
|
54485
|
+
const manifest = input.preserveManifest ? null : buildManifestFromCloud(cloud, agent);
|
|
54486
|
+
if (manifest)
|
|
54487
|
+
writeManifest(cwd2, manifest);
|
|
53542
54488
|
writeLink(cwd2, {
|
|
53543
54489
|
schemaVersion: 1,
|
|
53544
54490
|
agent_id: agent.id,
|
|
@@ -53568,31 +54514,32 @@ async function installAgentFresh(input) {
|
|
|
53568
54514
|
if (input.pullSecrets !== false) {
|
|
53569
54515
|
await pullAgentSecrets(cwd2, agent.id);
|
|
53570
54516
|
}
|
|
54517
|
+
const returnedManifest = manifest ?? buildManifestFromCloud(cloud, agent);
|
|
53571
54518
|
return {
|
|
53572
54519
|
installedPaths: justInstalledPaths,
|
|
53573
|
-
manifest,
|
|
54520
|
+
manifest: returnedManifest,
|
|
53574
54521
|
syncedComponents
|
|
53575
54522
|
};
|
|
53576
54523
|
} finally {
|
|
53577
54524
|
try {
|
|
53578
|
-
|
|
54525
|
+
fs49.rmSync(stageRoot, { recursive: true, force: true });
|
|
53579
54526
|
} catch {}
|
|
53580
54527
|
}
|
|
53581
54528
|
}
|
|
53582
54529
|
function stageManifestComponents2(components) {
|
|
53583
|
-
const root =
|
|
54530
|
+
const root = fs49.mkdtempSync(path53.join(os14.tmpdir(), "brainbase-orch-pull-"));
|
|
53584
54531
|
for (const c2 of components) {
|
|
53585
|
-
const compDir =
|
|
54532
|
+
const compDir = path53.join(root, c2.type, c2.slug);
|
|
53586
54533
|
ensureDir(compDir);
|
|
53587
54534
|
for (const f4 of c2.files) {
|
|
53588
|
-
const target =
|
|
53589
|
-
ensureDir(
|
|
53590
|
-
|
|
54535
|
+
const target = path53.join(compDir, f4.path);
|
|
54536
|
+
ensureDir(path53.dirname(target));
|
|
54537
|
+
fs49.writeFileSync(target, f4.content);
|
|
53591
54538
|
}
|
|
53592
54539
|
}
|
|
53593
54540
|
return root;
|
|
53594
54541
|
}
|
|
53595
|
-
function
|
|
54542
|
+
function runHarnessInstall4(harnessId, components, opts, agentName) {
|
|
53596
54543
|
if (harnessId === "claude-code")
|
|
53597
54544
|
return installClaudeCodeWithCtx(components, opts, agentName);
|
|
53598
54545
|
if (harnessId === "codex")
|
|
@@ -53608,7 +54555,7 @@ function materializeInstructions2(cwd2, cloud) {
|
|
|
53608
54555
|
const body = c2.files[0]?.content ?? "";
|
|
53609
54556
|
if (!body.trim())
|
|
53610
54557
|
continue;
|
|
53611
|
-
|
|
54558
|
+
fs49.writeFileSync(path53.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
|
|
53612
54559
|
return;
|
|
53613
54560
|
}
|
|
53614
54561
|
}
|
|
@@ -53647,6 +54594,7 @@ function buildManifestFromCloud(cloud, agent) {
|
|
|
53647
54594
|
...agent.tagline ? { tagline: agent.tagline } : {}
|
|
53648
54595
|
},
|
|
53649
54596
|
...hasInstructions ? { instructions: { file: DEFAULT_INSTRUCTIONS_FILE } } : {},
|
|
54597
|
+
playbooks: [],
|
|
53650
54598
|
skills,
|
|
53651
54599
|
mcp
|
|
53652
54600
|
};
|
|
@@ -53676,8 +54624,8 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53676
54624
|
orchId = args.orchestrationId;
|
|
53677
54625
|
} else {
|
|
53678
54626
|
f2.warn("This folder is not linked to any orchestration.");
|
|
53679
|
-
f2.info(`Run ${
|
|
53680
|
-
or ${
|
|
54627
|
+
f2.info(`Run ${import_picocolors33.default.cyan("brainbase orchestration pull <id>")} with an orchestration id,
|
|
54628
|
+
or ${import_picocolors33.default.cyan("brainbase orchestration list")} to find one.`);
|
|
53681
54629
|
return;
|
|
53682
54630
|
}
|
|
53683
54631
|
const sp = de();
|
|
@@ -53693,24 +54641,24 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53693
54641
|
}
|
|
53694
54642
|
const planLines = [];
|
|
53695
54643
|
planLines.push("");
|
|
53696
|
-
planLines.push(` ${
|
|
54644
|
+
planLines.push(` ${import_picocolors33.default.bold(cloud.name)} ${import_picocolors33.default.dim(`(${cloud.id})`)}`);
|
|
53697
54645
|
if (cloud.description)
|
|
53698
|
-
planLines.push(` ${
|
|
54646
|
+
planLines.push(` ${import_picocolors33.default.dim(cloud.description)}`);
|
|
53699
54647
|
planLines.push("");
|
|
53700
|
-
planLines.push(` ${
|
|
54648
|
+
planLines.push(` ${import_picocolors33.default.dim("members:")}`);
|
|
53701
54649
|
for (const m3 of cloud.members) {
|
|
53702
54650
|
const skipped = !m3.manifest;
|
|
53703
|
-
const tail = skipped ?
|
|
53704
|
-
planLines.push(` ${
|
|
54651
|
+
const tail = skipped ? import_picocolors33.default.red(" (manifest unavailable — skipped)") : "";
|
|
54652
|
+
planLines.push(` ${import_picocolors33.default.cyan("•")} ${import_picocolors33.default.bold(m3.slug)} ${import_picocolors33.default.dim(`(${m3.name})`)}${tail}`);
|
|
53705
54653
|
}
|
|
53706
54654
|
if (cloud.edges.length) {
|
|
53707
54655
|
planLines.push("");
|
|
53708
|
-
planLines.push(` ${
|
|
54656
|
+
planLines.push(` ${import_picocolors33.default.dim("edges:")}`);
|
|
53709
54657
|
for (const e2 of cloud.edges) {
|
|
53710
54658
|
const from = e2.from_slug ?? e2.from_agent_id;
|
|
53711
54659
|
const to2 = e2.to_slug ?? e2.to_agent_id;
|
|
53712
|
-
const desc = e2.description ? ` ${
|
|
53713
|
-
planLines.push(` ${
|
|
54660
|
+
const desc = e2.description ? ` ${import_picocolors33.default.dim("— " + e2.description)}` : "";
|
|
54661
|
+
planLines.push(` ${import_picocolors33.default.cyan(from)} ${import_picocolors33.default.dim("→")} ${import_picocolors33.default.cyan(to2)}${desc}`);
|
|
53714
54662
|
}
|
|
53715
54663
|
}
|
|
53716
54664
|
planLines.push("");
|
|
@@ -53719,7 +54667,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53719
54667
|
const isRefresh = !!existingLink;
|
|
53720
54668
|
if (!args.yes && !isRefresh) {
|
|
53721
54669
|
const ok = await se({
|
|
53722
|
-
message: `Pull into ${
|
|
54670
|
+
message: `Pull into ${import_picocolors33.default.bold(cwd2)}?`,
|
|
53723
54671
|
initialValue: true
|
|
53724
54672
|
});
|
|
53725
54673
|
if (!ensureNotCancelled(ok)) {
|
|
@@ -53728,7 +54676,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53728
54676
|
}
|
|
53729
54677
|
}
|
|
53730
54678
|
const fallbackHarness = args.harness ?? "claude-code";
|
|
53731
|
-
|
|
54679
|
+
fs50.mkdirSync(cwd2, { recursive: true });
|
|
53732
54680
|
if (hasOrchManifest(cwd2) && existingLink && existingLink.orchestration_id !== orchId) {
|
|
53733
54681
|
f2.error(`This folder is linked to orchestration ${existingLink.orchestration_id}, not ${orchId}. Move to a fresh directory or unlink first.`);
|
|
53734
54682
|
return;
|
|
@@ -53760,7 +54708,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53760
54708
|
scope: "project",
|
|
53761
54709
|
pullSecrets: true
|
|
53762
54710
|
});
|
|
53763
|
-
memberSp.stop(`Installed ${
|
|
54711
|
+
memberSp.stop(`Installed ${import_picocolors33.default.bold(m3.slug)} ${import_picocolors33.default.dim(`(${m3.manifest.components.length} components)`)}.`);
|
|
53764
54712
|
installedMembers.push({
|
|
53765
54713
|
agent_id: m3.agent_id,
|
|
53766
54714
|
slug: m3.slug,
|
|
@@ -53815,7 +54763,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
53815
54763
|
payload_schema: e2.payload_schema ?? {}
|
|
53816
54764
|
}))
|
|
53817
54765
|
});
|
|
53818
|
-
$e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${
|
|
54766
|
+
$e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path54.basename(cwd2)}/ ${import_picocolors33.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
|
|
53819
54767
|
}
|
|
53820
54768
|
function handleApiError5(err) {
|
|
53821
54769
|
if (err instanceof ApiError) {
|
|
@@ -53832,18 +54780,18 @@ function handleApiError5(err) {
|
|
|
53832
54780
|
}
|
|
53833
54781
|
|
|
53834
54782
|
// src/cli/orchestration-push.ts
|
|
53835
|
-
var
|
|
54783
|
+
var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
53836
54784
|
async function runOrchestrationPush(cwd2, args) {
|
|
53837
54785
|
banner("orchestration push — recursively push each member, then update the graph");
|
|
53838
54786
|
const link2 = readOrchLink(cwd2);
|
|
53839
54787
|
if (!link2) {
|
|
53840
54788
|
f2.warn("This folder is not linked to any orchestration.");
|
|
53841
|
-
f2.info(`Run ${
|
|
54789
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
53842
54790
|
return;
|
|
53843
54791
|
}
|
|
53844
54792
|
if (!hasOrchManifest(cwd2)) {
|
|
53845
|
-
f2.warn(`No ${
|
|
53846
|
-
f2.info(`Run ${
|
|
54793
|
+
f2.warn(`No ${import_picocolors34.default.bold(ORCH_MANIFEST_FILE)} here.`);
|
|
54794
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to materialise the manifest before pushing.`);
|
|
53847
54795
|
return;
|
|
53848
54796
|
}
|
|
53849
54797
|
let manifest;
|
|
@@ -53856,15 +54804,15 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53856
54804
|
const memberSlugs = new Set(manifest.members.map((m3) => m3.slug));
|
|
53857
54805
|
for (const e2 of manifest.edges) {
|
|
53858
54806
|
if (!memberSlugs.has(e2.from)) {
|
|
53859
|
-
f2.error(`Edge from "${
|
|
54807
|
+
f2.error(`Edge from "${import_picocolors34.default.bold(e2.from)}" references a slug that isn't in members.`);
|
|
53860
54808
|
return;
|
|
53861
54809
|
}
|
|
53862
54810
|
if (!memberSlugs.has(e2.to)) {
|
|
53863
|
-
f2.error(`Edge to "${
|
|
54811
|
+
f2.error(`Edge to "${import_picocolors34.default.bold(e2.to)}" references a slug that isn't in members.`);
|
|
53864
54812
|
return;
|
|
53865
54813
|
}
|
|
53866
54814
|
if (e2.from === e2.to) {
|
|
53867
|
-
f2.error(`Edge ${
|
|
54815
|
+
f2.error(`Edge ${import_picocolors34.default.bold(e2.from)} → ${import_picocolors34.default.bold(e2.to)}: self-loops are not allowed.`);
|
|
53868
54816
|
return;
|
|
53869
54817
|
}
|
|
53870
54818
|
}
|
|
@@ -53881,17 +54829,17 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53881
54829
|
}
|
|
53882
54830
|
if (missing.length) {
|
|
53883
54831
|
f2.error(`These members have no local checkout (expected at agents/<slug>/.brainbase/link.json): ${missing.join(", ")}.`);
|
|
53884
|
-
f2.info(`Run ${
|
|
54832
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to materialise the missing folders.`);
|
|
53885
54833
|
return;
|
|
53886
54834
|
}
|
|
53887
54835
|
const plan = [""];
|
|
53888
|
-
plan.push(` ${
|
|
53889
|
-
plan.push(` ${
|
|
54836
|
+
plan.push(` ${import_picocolors34.default.bold(link2.name)} ${import_picocolors34.default.dim(`(${link2.orchestration_id})`)}`);
|
|
54837
|
+
plan.push(` ${import_picocolors34.default.dim(`${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}`)}`);
|
|
53890
54838
|
plan.push("");
|
|
53891
54839
|
if (!args.graphOnly) {
|
|
53892
|
-
plan.push(` ${
|
|
54840
|
+
plan.push(` ${import_picocolors34.default.dim("per-member agent push:")}`);
|
|
53893
54841
|
for (const m3 of manifest.members) {
|
|
53894
|
-
plan.push(` ${
|
|
54842
|
+
plan.push(` ${import_picocolors34.default.cyan("•")} ${import_picocolors34.default.bold(m3.slug)}`);
|
|
53895
54843
|
}
|
|
53896
54844
|
plan.push("");
|
|
53897
54845
|
}
|
|
@@ -53911,7 +54859,7 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
53911
54859
|
for (const m3 of manifest.members) {
|
|
53912
54860
|
const dir = memberDir(cwd2, m3.slug);
|
|
53913
54861
|
console.log("");
|
|
53914
|
-
console.log(`${
|
|
54862
|
+
console.log(`${import_picocolors34.default.dim("───")} ${import_picocolors34.default.bold(m3.slug)} ${import_picocolors34.default.dim("───")}`);
|
|
53915
54863
|
try {
|
|
53916
54864
|
await runAgentPush(dir, { yes: true });
|
|
53917
54865
|
} catch (err) {
|
|
@@ -53973,7 +54921,7 @@ function handleApiError6(err) {
|
|
|
53973
54921
|
f2.error("You do not have access to this orchestration.");
|
|
53974
54922
|
} else if (err.status === 409) {
|
|
53975
54923
|
f2.error(err.message);
|
|
53976
|
-
f2.info(`Run ${
|
|
54924
|
+
f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to reconcile, then push again.`);
|
|
53977
54925
|
} else {
|
|
53978
54926
|
f2.error(err.message);
|
|
53979
54927
|
}
|
|
@@ -53983,13 +54931,13 @@ function handleApiError6(err) {
|
|
|
53983
54931
|
}
|
|
53984
54932
|
|
|
53985
54933
|
// src/cli/orchestration-status.ts
|
|
53986
|
-
var
|
|
54934
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
53987
54935
|
async function runOrchestrationStatus(cwd2) {
|
|
53988
54936
|
banner("orchestration status — what changed locally, remotely, both");
|
|
53989
54937
|
const link2 = readOrchLink(cwd2);
|
|
53990
54938
|
if (!link2) {
|
|
53991
54939
|
f2.warn("This folder is not linked to any orchestration.");
|
|
53992
|
-
f2.info(`Run ${
|
|
54940
|
+
f2.info(`Run ${import_picocolors35.default.cyan("brainbase orchestration pull <id>")} first.`);
|
|
53993
54941
|
return;
|
|
53994
54942
|
}
|
|
53995
54943
|
const localManifest = hasOrchManifest(cwd2) ? readOrchManifest(cwd2) : null;
|
|
@@ -54011,20 +54959,20 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
54011
54959
|
}
|
|
54012
54960
|
const lines = [];
|
|
54013
54961
|
lines.push("");
|
|
54014
|
-
lines.push(` ${
|
|
54015
|
-
lines.push(` ${
|
|
54962
|
+
lines.push(` ${import_picocolors35.default.bold(link2.name)} ${import_picocolors35.default.dim(`(${link2.orchestration_id})`)}`);
|
|
54963
|
+
lines.push(` ${import_picocolors35.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
|
|
54016
54964
|
lines.push("");
|
|
54017
54965
|
const cloudMemberSet = new Set(cloud.members.map((m3) => m3.slug));
|
|
54018
54966
|
const localMemberSet = new Set((localManifest?.members ?? []).map((m3) => m3.slug));
|
|
54019
54967
|
const membersAdded = [...localMemberSet].filter((s3) => !cloudMemberSet.has(s3));
|
|
54020
54968
|
const membersRemoved = [...cloudMemberSet].filter((s3) => !localMemberSet.has(s3));
|
|
54021
54969
|
if (membersAdded.length || membersRemoved.length) {
|
|
54022
|
-
lines.push(` ${
|
|
54970
|
+
lines.push(` ${import_picocolors35.default.bold("members")}`);
|
|
54023
54971
|
for (const slug of membersAdded) {
|
|
54024
|
-
lines.push(` ${
|
|
54972
|
+
lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${import_picocolors35.default.bold(slug)}`);
|
|
54025
54973
|
}
|
|
54026
54974
|
for (const slug of membersRemoved) {
|
|
54027
|
-
lines.push(` ${
|
|
54975
|
+
lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${import_picocolors35.default.bold(slug)}`);
|
|
54028
54976
|
}
|
|
54029
54977
|
lines.push("");
|
|
54030
54978
|
}
|
|
@@ -54039,11 +54987,11 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
54039
54987
|
const edgesAdded = [...localEdges.keys()].filter((k3) => !cloudEdges.has(k3));
|
|
54040
54988
|
const edgesRemoved = [...cloudEdges.keys()].filter((k3) => !localEdges.has(k3));
|
|
54041
54989
|
if (edgesAdded.length || edgesRemoved.length) {
|
|
54042
|
-
lines.push(` ${
|
|
54990
|
+
lines.push(` ${import_picocolors35.default.bold("edges")}`);
|
|
54043
54991
|
for (const k3 of edgesAdded)
|
|
54044
|
-
lines.push(` ${
|
|
54992
|
+
lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${k3}`);
|
|
54045
54993
|
for (const k3 of edgesRemoved)
|
|
54046
|
-
lines.push(` ${
|
|
54994
|
+
lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${k3}`);
|
|
54047
54995
|
lines.push("");
|
|
54048
54996
|
}
|
|
54049
54997
|
const lockByAgentId = new Map((lock?.members ?? []).map((m3) => [m3.agent_id, m3]));
|
|
@@ -54065,28 +55013,28 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
54065
55013
|
}
|
|
54066
55014
|
}
|
|
54067
55015
|
if (memberDrift.length) {
|
|
54068
|
-
lines.push(` ${
|
|
55016
|
+
lines.push(` ${import_picocolors35.default.bold("member content drift")}`);
|
|
54069
55017
|
for (const d3 of memberDrift) {
|
|
54070
|
-
lines.push(` ${
|
|
55018
|
+
lines.push(` ${import_picocolors35.default.cyan("?")} ${import_picocolors35.default.bold(d3.slug)} ${import_picocolors35.default.dim("— " + d3.reason)}`);
|
|
54071
55019
|
}
|
|
54072
|
-
lines.push(` ${
|
|
55020
|
+
lines.push(` ${import_picocolors35.default.dim("cd into each member folder and run")} ${import_picocolors35.default.cyan("brainbase agent status")}`);
|
|
54073
55021
|
lines.push("");
|
|
54074
55022
|
}
|
|
54075
55023
|
if (!membersAdded.length && !membersRemoved.length && !edgesAdded.length && !edgesRemoved.length && !memberDrift.length) {
|
|
54076
|
-
lines.push(` ${
|
|
55024
|
+
lines.push(` ${import_picocolors35.default.green("✓")} everything is in sync`);
|
|
54077
55025
|
lines.push("");
|
|
54078
55026
|
console.log(lines.join(`
|
|
54079
55027
|
`));
|
|
54080
55028
|
return;
|
|
54081
55029
|
}
|
|
54082
|
-
lines.push(` ${
|
|
55030
|
+
lines.push(` ${import_picocolors35.default.dim("run")} ${import_picocolors35.default.cyan("brainbase orchestration pull")} ${import_picocolors35.default.dim("to apply cloud changes,")} ${import_picocolors35.default.cyan("brainbase orchestration push")} ${import_picocolors35.default.dim("to send yours")}`);
|
|
54083
55031
|
lines.push("");
|
|
54084
55032
|
console.log(lines.join(`
|
|
54085
55033
|
`));
|
|
54086
55034
|
}
|
|
54087
55035
|
|
|
54088
55036
|
// src/cli/orchestration-list.ts
|
|
54089
|
-
var
|
|
55037
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
54090
55038
|
async function runOrchestrationList(args) {
|
|
54091
55039
|
banner("orchestration list — orchestrations under a team");
|
|
54092
55040
|
let orgId = args.orgId;
|
|
@@ -54152,13 +55100,13 @@ async function runOrchestrationList(args) {
|
|
|
54152
55100
|
}
|
|
54153
55101
|
const lines = [""];
|
|
54154
55102
|
for (const o2 of items) {
|
|
54155
|
-
lines.push(` ${
|
|
55103
|
+
lines.push(` ${import_picocolors36.default.bold(o2.name)} ${import_picocolors36.default.dim(o2.id)}`);
|
|
54156
55104
|
if (o2.description)
|
|
54157
|
-
lines.push(` ${
|
|
54158
|
-
lines.push(` ${
|
|
55105
|
+
lines.push(` ${import_picocolors36.default.dim(o2.description)}`);
|
|
55106
|
+
lines.push(` ${import_picocolors36.default.dim(`${o2.member_count} member${o2.member_count === 1 ? "" : "s"} · ${o2.edge_count} edge${o2.edge_count === 1 ? "" : "s"}`)}`);
|
|
54159
55107
|
lines.push("");
|
|
54160
55108
|
}
|
|
54161
|
-
lines.push(` ${
|
|
55109
|
+
lines.push(` ${import_picocolors36.default.dim("pull one with")} ${import_picocolors36.default.cyan("brainbase orchestration pull <id>")}`);
|
|
54162
55110
|
lines.push("");
|
|
54163
55111
|
console.log(lines.join(`
|
|
54164
55112
|
`));
|
|
@@ -54214,26 +55162,26 @@ async function runOrchestration(cwd2, sub, args, opts) {
|
|
|
54214
55162
|
function printHelp2() {
|
|
54215
55163
|
const out = [];
|
|
54216
55164
|
out.push("");
|
|
54217
|
-
out.push(` ${
|
|
55165
|
+
out.push(` ${import_picocolors37.default.bold("brainbase orchestration")} ${import_picocolors37.default.dim("<sub> [options]")}`);
|
|
54218
55166
|
out.push("");
|
|
54219
|
-
out.push(` ${
|
|
54220
|
-
out.push(` ${
|
|
54221
|
-
out.push(` ${
|
|
54222
|
-
out.push(` ${
|
|
55167
|
+
out.push(` ${import_picocolors37.default.cyan("pull")} ${import_picocolors37.default.dim("<id>")} ${import_picocolors37.default.dim("fetch orchestration + every member agent into this folder")}`);
|
|
55168
|
+
out.push(` ${import_picocolors37.default.cyan("push")} ${import_picocolors37.default.dim("push each member, then update the orchestration graph")}`);
|
|
55169
|
+
out.push(` ${import_picocolors37.default.cyan("status")} ${import_picocolors37.default.dim("show what would push and what would pull")}`);
|
|
55170
|
+
out.push(` ${import_picocolors37.default.cyan("list")} ${import_picocolors37.default.dim("list orchestrations under a team")}`);
|
|
54223
55171
|
out.push("");
|
|
54224
|
-
out.push(` ${
|
|
54225
|
-
out.push(` ${
|
|
54226
|
-
out.push(` ${
|
|
54227
|
-
out.push(` ${
|
|
54228
|
-
out.push(` ${
|
|
54229
|
-
out.push(` ${
|
|
55172
|
+
out.push(` ${import_picocolors37.default.bold("Flags")}`);
|
|
55173
|
+
out.push(` ${import_picocolors37.default.dim("--yes, -y")} skip confirmations`);
|
|
55174
|
+
out.push(` ${import_picocolors37.default.dim("--harness <id>")} harness for newly-created member folders (default claude-code)`);
|
|
55175
|
+
out.push(` ${import_picocolors37.default.dim("--graph-only")} for push: only update members + edges, skip per-member push`);
|
|
55176
|
+
out.push(` ${import_picocolors37.default.dim("--org <id>")} for list: org id (CLI vocab — DB teams.id)`);
|
|
55177
|
+
out.push(` ${import_picocolors37.default.dim("--team <id>")} for list: team id (CLI vocab — DB groups.id)`);
|
|
54230
55178
|
out.push("");
|
|
54231
55179
|
console.log(out.join(`
|
|
54232
55180
|
`));
|
|
54233
55181
|
}
|
|
54234
55182
|
|
|
54235
55183
|
// src/cli/run.ts
|
|
54236
|
-
import { spawn as
|
|
55184
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
54237
55185
|
async function runRun(cwd2, args) {
|
|
54238
55186
|
const cleaned = args[0] === "--" ? args.slice(1) : args;
|
|
54239
55187
|
if (cleaned.length === 0) {
|
|
@@ -54245,7 +55193,7 @@ async function runRun(cwd2, args) {
|
|
|
54245
55193
|
const [cmd, ...cmdArgs] = cleaned;
|
|
54246
55194
|
const secrets = readLocalSecrets(cwd2);
|
|
54247
55195
|
const env3 = { ...process.env, ...secrets };
|
|
54248
|
-
const child =
|
|
55196
|
+
const child = spawn3(cmd, cmdArgs, {
|
|
54249
55197
|
cwd: cwd2,
|
|
54250
55198
|
env: env3,
|
|
54251
55199
|
stdio: "inherit",
|
|
@@ -54271,16 +55219,16 @@ async function runRun(cwd2, args) {
|
|
|
54271
55219
|
}
|
|
54272
55220
|
|
|
54273
55221
|
// src/cli/publish.ts
|
|
54274
|
-
var
|
|
55222
|
+
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
54275
55223
|
async function runPublish(cwd2, _args) {
|
|
54276
55224
|
banner("publish — send your changes to the team");
|
|
54277
55225
|
const link2 = readLink(cwd2);
|
|
54278
55226
|
if (!link2) {
|
|
54279
55227
|
f2.warn("This folder is not linked to any agent.");
|
|
54280
|
-
f2.info(`Run ${
|
|
55228
|
+
f2.info(`Run ${import_picocolors38.default.cyan("brainbase link")} first.`);
|
|
54281
55229
|
return;
|
|
54282
55230
|
}
|
|
54283
|
-
f2.info(`${
|
|
55231
|
+
f2.info(`${import_picocolors38.default.bold("publish")} is coming soon — for now, edit the agent on the web app and run ${import_picocolors38.default.cyan("brainbase sync")} to bring changes here.`);
|
|
54284
55232
|
}
|
|
54285
55233
|
|
|
54286
55234
|
// src/ui/ink/StatusCard.tsx
|
|
@@ -54578,7 +55526,7 @@ async function runStatus(cwd2) {
|
|
|
54578
55526
|
}
|
|
54579
55527
|
|
|
54580
55528
|
// src/cli/token.ts
|
|
54581
|
-
var
|
|
55529
|
+
var import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
54582
55530
|
|
|
54583
55531
|
// src/ui/ink/TokenCards.tsx
|
|
54584
55532
|
var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
|
|
@@ -54872,7 +55820,7 @@ async function runTokenRevoke(args) {
|
|
|
54872
55820
|
}
|
|
54873
55821
|
if (!args.yes) {
|
|
54874
55822
|
const ok = await se({
|
|
54875
|
-
message: `Revoke token ${
|
|
55823
|
+
message: `Revoke token ${import_picocolors39.default.bold(args.id)}? CIs and machines using it will stop working.`,
|
|
54876
55824
|
initialValue: false
|
|
54877
55825
|
});
|
|
54878
55826
|
if (!ensureNotCancelled(ok))
|
|
@@ -54887,7 +55835,7 @@ async function runTokenRevoke(args) {
|
|
|
54887
55835
|
}
|
|
54888
55836
|
async function runTokenClear() {
|
|
54889
55837
|
if (!readToken()) {
|
|
54890
|
-
console.log(
|
|
55838
|
+
console.log(import_picocolors39.default.dim("No local token stored."));
|
|
54891
55839
|
return;
|
|
54892
55840
|
}
|
|
54893
55841
|
clearToken();
|
|
@@ -54938,17 +55886,17 @@ async function runToken(sub, rest, args) {
|
|
|
54938
55886
|
function printTokenHelp() {
|
|
54939
55887
|
const out = [];
|
|
54940
55888
|
out.push("");
|
|
54941
|
-
out.push(` ${
|
|
55889
|
+
out.push(` ${import_picocolors39.default.bold("brainbase token")} ${import_picocolors39.default.dim("<command>")}`);
|
|
54942
55890
|
out.push("");
|
|
54943
|
-
out.push(` ${
|
|
54944
|
-
out.push(` ${
|
|
54945
|
-
out.push(` ${
|
|
54946
|
-
out.push(` ${
|
|
55891
|
+
out.push(` ${import_picocolors39.default.cyan("create")} ${import_picocolors39.default.dim("issue a new long-lived CLI key (PAT)")}`);
|
|
55892
|
+
out.push(` ${import_picocolors39.default.cyan("list")} ${import_picocolors39.default.dim("show your active tokens")}`);
|
|
55893
|
+
out.push(` ${import_picocolors39.default.cyan("revoke")} ${import_picocolors39.default.dim("<id>")} ${import_picocolors39.default.dim("revoke a token by id")}`);
|
|
55894
|
+
out.push(` ${import_picocolors39.default.cyan("clear")} ${import_picocolors39.default.dim("forget the local token (does not revoke)")}`);
|
|
54947
55895
|
out.push("");
|
|
54948
|
-
out.push(` ${
|
|
54949
|
-
out.push(` ${
|
|
54950
|
-
out.push(` ${
|
|
54951
|
-
out.push(` ${
|
|
55896
|
+
out.push(` ${import_picocolors39.default.bold("create flags")}`);
|
|
55897
|
+
out.push(` ${import_picocolors39.default.cyan("--name, -n")} ${import_picocolors39.default.dim("<label>")} ${import_picocolors39.default.dim("token label (prompted if omitted)")}`);
|
|
55898
|
+
out.push(` ${import_picocolors39.default.cyan("--scopes")} ${import_picocolors39.default.dim("<list>")} ${import_picocolors39.default.dim("comma-separated; allowed: read, publish, admin")}`);
|
|
55899
|
+
out.push(` ${import_picocolors39.default.dim("default: read,publish")}`);
|
|
54952
55900
|
out.push("");
|
|
54953
55901
|
console.log(out.join(`
|
|
54954
55902
|
`));
|
|
@@ -54968,89 +55916,90 @@ var PROTECTED = new Set([
|
|
|
54968
55916
|
function help() {
|
|
54969
55917
|
const out = [];
|
|
54970
55918
|
out.push("");
|
|
54971
|
-
out.push(` ${brandTint("◆")} ${
|
|
54972
|
-
out.push(` ${
|
|
55919
|
+
out.push(` ${brandTint("◆")} ${import_picocolors40.default.bold("brainbase")} ${import_picocolors40.default.dim("v0.6.0")}`);
|
|
55920
|
+
out.push(` ${import_picocolors40.default.dim("connect your local agent to the brainbase platform")}`);
|
|
54973
55921
|
out.push("");
|
|
54974
55922
|
out.push(divider("USAGE"));
|
|
54975
55923
|
out.push("");
|
|
54976
|
-
out.push(` ${
|
|
55924
|
+
out.push(` ${import_picocolors40.default.bold("brainbase")} ${import_picocolors40.default.dim("<command> [options]")}`);
|
|
54977
55925
|
out.push("");
|
|
54978
55926
|
out.push(divider("AUTH"));
|
|
54979
55927
|
out.push("");
|
|
54980
|
-
out.push(` ${
|
|
54981
|
-
out.push(` ${
|
|
54982
|
-
out.push(` ${
|
|
55928
|
+
out.push(` ${import_picocolors40.default.cyan("login")} ${import_picocolors40.default.dim(" open the web app and connect this device")}`);
|
|
55929
|
+
out.push(` ${import_picocolors40.default.cyan("logout")} ${import_picocolors40.default.dim(" clear the local session")}`);
|
|
55930
|
+
out.push(` ${import_picocolors40.default.cyan("whoami")} ${import_picocolors40.default.dim(" show the current user")}`);
|
|
54983
55931
|
out.push("");
|
|
54984
55932
|
out.push(divider("LINKED AGENT"));
|
|
54985
55933
|
out.push("");
|
|
54986
|
-
out.push(` ${
|
|
54987
|
-
out.push(` ${
|
|
54988
|
-
out.push(` ${
|
|
54989
|
-
out.push(` ${
|
|
54990
|
-
out.push(` ${
|
|
54991
|
-
out.push(` ${
|
|
54992
|
-
out.push(` ${
|
|
54993
|
-
out.push(` ${
|
|
54994
|
-
out.push(` ${
|
|
55934
|
+
out.push(` ${import_picocolors40.default.cyan("agent create")} ${import_picocolors40.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
55935
|
+
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)")}`);
|
|
55936
|
+
out.push(` ${import_picocolors40.default.cyan("agent push")} ${import_picocolors40.default.dim("send local changes to the cloud")}`);
|
|
55937
|
+
out.push(` ${import_picocolors40.default.cyan("agent unpack")} ${import_picocolors40.default.dim("install the claimed agent into a harness layout")}`);
|
|
55938
|
+
out.push(` ${import_picocolors40.default.cyan("link")} ${import_picocolors40.default.dim("attach this folder to an existing agent")}`);
|
|
55939
|
+
out.push(` ${import_picocolors40.default.cyan("agent status")} ${import_picocolors40.default.dim("show what would pull and what would push")}`);
|
|
55940
|
+
out.push(` ${import_picocolors40.default.cyan("agent env")} ${import_picocolors40.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
|
|
55941
|
+
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")}`);
|
|
55942
|
+
out.push(` ${import_picocolors40.default.cyan("status")} ${import_picocolors40.default.dim("show what this folder is linked to")}`);
|
|
55943
|
+
out.push(` ${import_picocolors40.default.cyan("unlink")} ${import_picocolors40.default.dim("disconnect this folder")}`);
|
|
54995
55944
|
out.push("");
|
|
54996
55945
|
out.push(divider("ORCHESTRATIONS"));
|
|
54997
55946
|
out.push("");
|
|
54998
|
-
out.push(` ${
|
|
54999
|
-
out.push(` ${
|
|
55000
|
-
out.push(` ${
|
|
55001
|
-
out.push(` ${
|
|
55947
|
+
out.push(` ${import_picocolors40.default.cyan("orchestration list")} ${import_picocolors40.default.dim("list orchestrations under a team")}`);
|
|
55948
|
+
out.push(` ${import_picocolors40.default.cyan("orchestration pull")} ${import_picocolors40.default.dim("<id>")} ${import_picocolors40.default.dim("recursively fetch an orchestration + every member agent")}`);
|
|
55949
|
+
out.push(` ${import_picocolors40.default.cyan("orchestration push")} ${import_picocolors40.default.dim("recursively push each member, then update the graph")}`);
|
|
55950
|
+
out.push(` ${import_picocolors40.default.cyan("orchestration status")} ${import_picocolors40.default.dim("show what would push and what would pull")}`);
|
|
55002
55951
|
out.push("");
|
|
55003
55952
|
out.push(divider("TEMPLATES"));
|
|
55004
55953
|
out.push("");
|
|
55005
|
-
out.push(` ${
|
|
55006
|
-
out.push(` ${
|
|
55007
|
-
out.push(` ${
|
|
55008
|
-
out.push(` ${
|
|
55009
|
-
out.push(` ${
|
|
55010
|
-
out.push(` ${
|
|
55011
|
-
out.push(` ${
|
|
55954
|
+
out.push(` ${import_picocolors40.default.cyan("template pack")} ${import_picocolors40.default.dim("bundle the current agent into a template")}`);
|
|
55955
|
+
out.push(` ${import_picocolors40.default.cyan("template publish")} ${import_picocolors40.default.dim("upload a template to the registry")}`);
|
|
55956
|
+
out.push(` ${import_picocolors40.default.cyan("template search")} ${import_picocolors40.default.dim("[query]")} ${import_picocolors40.default.dim("search the registry")}`);
|
|
55957
|
+
out.push(` ${import_picocolors40.default.cyan("template info")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("show registry details for a template")}`);
|
|
55958
|
+
out.push(` ${import_picocolors40.default.cyan("template onboard")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("install (or refresh) a template")}`);
|
|
55959
|
+
out.push(` ${import_picocolors40.default.cyan("template list")} ${import_picocolors40.default.dim("show installed templates")}`);
|
|
55960
|
+
out.push(` ${import_picocolors40.default.cyan("template remove")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("uninstall a template")}`);
|
|
55012
55961
|
out.push("");
|
|
55013
55962
|
out.push(divider("SKILLS"));
|
|
55014
55963
|
out.push("");
|
|
55015
|
-
out.push(` ${
|
|
55016
|
-
out.push(` ${
|
|
55017
|
-
out.push(` ${
|
|
55018
|
-
out.push(` ${
|
|
55019
|
-
out.push(` ${
|
|
55020
|
-
out.push(` ${
|
|
55021
|
-
out.push(` ${
|
|
55964
|
+
out.push(` ${import_picocolors40.default.cyan("skill add")} ${import_picocolors40.default.dim("<source>")} ${import_picocolors40.default.dim("install a skill (github / git / brainbase)")}`);
|
|
55965
|
+
out.push(` ${import_picocolors40.default.cyan("skill list")} ${import_picocolors40.default.dim("show locally installed skills + their source")}`);
|
|
55966
|
+
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")}`);
|
|
55967
|
+
out.push(` ${import_picocolors40.default.cyan("skill remove")} ${import_picocolors40.default.dim("<slug>")} ${import_picocolors40.default.dim("uninstall a skill")}`);
|
|
55968
|
+
out.push(` ${import_picocolors40.default.cyan("skill search")} ${import_picocolors40.default.dim("[query]")} ${import_picocolors40.default.dim("search the brainbase skill registry")}`);
|
|
55969
|
+
out.push(` ${import_picocolors40.default.cyan("skill info")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("show registry details for a skill")}`);
|
|
55970
|
+
out.push(` ${import_picocolors40.default.cyan("skill publish")} ${import_picocolors40.default.dim("[dir]")} ${import_picocolors40.default.dim("publish a SKILL.md folder (defaults to .)")}`);
|
|
55022
55971
|
out.push("");
|
|
55023
55972
|
out.push(divider("CLI TOKENS"));
|
|
55024
55973
|
out.push("");
|
|
55025
|
-
out.push(` ${
|
|
55026
|
-
out.push(` ${
|
|
55027
|
-
out.push(` ${
|
|
55974
|
+
out.push(` ${import_picocolors40.default.cyan("token create")} ${import_picocolors40.default.dim("issue a long-lived CLI key for CI / scripts")}`);
|
|
55975
|
+
out.push(` ${import_picocolors40.default.cyan("token list")} ${import_picocolors40.default.dim("show your active tokens")}`);
|
|
55976
|
+
out.push(` ${import_picocolors40.default.cyan("token revoke")} ${import_picocolors40.default.dim("<id>")} ${import_picocolors40.default.dim("revoke a token")}`);
|
|
55028
55977
|
out.push("");
|
|
55029
55978
|
out.push(divider("FLAGS"));
|
|
55030
55979
|
out.push("");
|
|
55031
|
-
out.push(` ${
|
|
55032
|
-
out.push(` ${
|
|
55033
|
-
out.push(` ${
|
|
55034
|
-
out.push(` ${
|
|
55035
|
-
out.push(` ${
|
|
55036
|
-
out.push(` ${
|
|
55037
|
-
out.push(` ${
|
|
55038
|
-
out.push(` ${
|
|
55980
|
+
out.push(` ${import_picocolors40.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
|
|
55981
|
+
out.push(` ${import_picocolors40.default.dim("--scope <s>")} force scope: global | project`);
|
|
55982
|
+
out.push(` ${import_picocolors40.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
|
|
55983
|
+
out.push(` ${import_picocolors40.default.dim("--agent <id>")} for link: attach this folder to an existing agent non-interactively`);
|
|
55984
|
+
out.push(` ${import_picocolors40.default.dim("--no-tracking")} for link: skip routing LLM traffic through brainbase`);
|
|
55985
|
+
out.push(` ${import_picocolors40.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
|
|
55986
|
+
out.push(` ${import_picocolors40.default.dim("--all")} for template list: include installs from other folders`);
|
|
55987
|
+
out.push(` ${import_picocolors40.default.dim("--web <url>")} for login: web app URL (default https://new.usekafka.com)`);
|
|
55039
55988
|
out.push("");
|
|
55040
55989
|
out.push(divider("ENV"));
|
|
55041
55990
|
out.push("");
|
|
55042
|
-
out.push(` ${
|
|
55043
|
-
out.push(` ${
|
|
55044
|
-
out.push(` ${
|
|
55045
|
-
out.push(` ${
|
|
55046
|
-
out.push(` ${
|
|
55047
|
-
out.push(` ${
|
|
55991
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
|
|
55992
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
|
|
55993
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_API_URL")} override the API URL used by link / sync`);
|
|
55994
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL`);
|
|
55995
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT (overrides token.json)`);
|
|
55996
|
+
out.push(` ${import_picocolors40.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
|
|
55048
55997
|
out.push("");
|
|
55049
55998
|
out.push(divider("HARNESSES"));
|
|
55050
55999
|
out.push("");
|
|
55051
|
-
out.push(` ${
|
|
55052
|
-
out.push(` ${
|
|
55053
|
-
out.push(` ${
|
|
56000
|
+
out.push(` ${import_picocolors40.default.dim("•")} ${import_picocolors40.default.bold("claude-code")} ${import_picocolors40.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
56001
|
+
out.push(` ${import_picocolors40.default.dim("•")} ${import_picocolors40.default.bold("codex")} ${import_picocolors40.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
|
|
56002
|
+
out.push(` ${import_picocolors40.default.dim("•")} ${import_picocolors40.default.bold("kafka")} ${import_picocolors40.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
55054
56003
|
out.push("");
|
|
55055
56004
|
console.log(out.join(`
|
|
55056
56005
|
`));
|
|
@@ -55094,13 +56043,13 @@ async function requireAuth(cmd) {
|
|
|
55094
56043
|
if (status.ok)
|
|
55095
56044
|
return;
|
|
55096
56045
|
console.error("");
|
|
55097
|
-
console.error(` ${brandTint("◆")} ${
|
|
56046
|
+
console.error(` ${brandTint("◆")} ${import_picocolors40.default.bold("brainbase")}`);
|
|
55098
56047
|
console.error("");
|
|
55099
|
-
console.error(` ${
|
|
56048
|
+
console.error(` ${import_picocolors40.default.red("✗")} You need to sign in to use ${import_picocolors40.default.bold("brainbase " + cmd)}.`);
|
|
55100
56049
|
if (status.reason)
|
|
55101
|
-
console.error(` ${
|
|
56050
|
+
console.error(` ${import_picocolors40.default.dim(status.reason)}`);
|
|
55102
56051
|
console.error("");
|
|
55103
|
-
console.error(` Run ${
|
|
56052
|
+
console.error(` Run ${import_picocolors40.default.cyan("brainbase login")} to connect this device.`);
|
|
55104
56053
|
console.error("");
|
|
55105
56054
|
process13.exit(1);
|
|
55106
56055
|
}
|
|
@@ -55110,7 +56059,7 @@ async function main() {
|
|
|
55110
56059
|
const rawCwd = process13.cwd();
|
|
55111
56060
|
const cwd2 = (() => {
|
|
55112
56061
|
try {
|
|
55113
|
-
return
|
|
56062
|
+
return fs51.realpathSync(rawCwd);
|
|
55114
56063
|
} catch {
|
|
55115
56064
|
return rawCwd;
|
|
55116
56065
|
}
|
|
@@ -55137,6 +56086,7 @@ async function main() {
|
|
|
55137
56086
|
const agentFlag = getFlag(argv, "--agent");
|
|
55138
56087
|
const shellFlag = getFlag(argv, "--shell");
|
|
55139
56088
|
const noTracking = hasFlag2(argv, "--no-tracking");
|
|
56089
|
+
const forceFlag = hasFlag2(argv, "--force");
|
|
55140
56090
|
const graphOnlyFlag = hasFlag2(argv, "--graph-only");
|
|
55141
56091
|
const nameFlag = getFlag(argv, "--name");
|
|
55142
56092
|
const skillVersionFlag = getFlag(argv, "--skill-version");
|
|
@@ -55221,7 +56171,8 @@ async function main() {
|
|
|
55221
56171
|
tagline: taglineFlag,
|
|
55222
56172
|
orgId: orgIdFlag,
|
|
55223
56173
|
teamId: teamIdFlag,
|
|
55224
|
-
noTracking
|
|
56174
|
+
noTracking,
|
|
56175
|
+
force: forceFlag
|
|
55225
56176
|
});
|
|
55226
56177
|
break;
|
|
55227
56178
|
}
|
|
@@ -55252,7 +56203,7 @@ async function main() {
|
|
|
55252
56203
|
process13.exit(1);
|
|
55253
56204
|
}
|
|
55254
56205
|
} catch (err) {
|
|
55255
|
-
console.error(
|
|
56206
|
+
console.error(import_picocolors40.default.red(`
|
|
55256
56207
|
${err.message}`));
|
|
55257
56208
|
if (process13.env.BRAINBASE_DEBUG)
|
|
55258
56209
|
console.error(err.stack);
|