@brainbase-labs/cli 0.5.0 → 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.
Files changed (2) hide show
  1. package/dist/index.js +556 -248
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -28566,7 +28566,7 @@ var require_jsx_dev_runtime = __commonJS((exports, module) => {
28566
28566
  // src/index.ts
28567
28567
  var import_picocolors40 = __toESM(require_picocolors(), 1);
28568
28568
  import process13 from "node:process";
28569
- import fs50 from "node:fs";
28569
+ import fs51 from "node:fs";
28570
28570
 
28571
28571
  // src/cli/template.ts
28572
28572
  var import_picocolors12 = __toESM(require_picocolors(), 1);
@@ -50768,8 +50768,9 @@ import fs39 from "node:fs";
50768
50768
  var import_yaml2 = __toESM(require_dist(), 1);
50769
50769
  var AGENT_MANIFEST_FILE = "brainbase.agent.yaml";
50770
50770
  var LEGACY_AGENT_MANIFEST_FILE = "brainbase.yaml";
50771
- var DEFAULT_INSTRUCTIONS_FILE = "instructions.md";
50772
- var DEFAULT_ENTRYPOINT_FILE = "entrypoint.sh";
50771
+ var DEFAULT_INSTRUCTIONS_FILE = ".brainbase/instructions.md";
50772
+ var DEFAULT_ENTRYPOINT_FILE = ".brainbase/entrypoint.sh";
50773
+ var DEFAULT_PLAYBOOKS_DIR = ".brainbase/playbooks";
50773
50774
  var REGISTRY_SOURCE_RE = /^registry:(?:([a-z0-9_-]+)\/)?([a-z0-9_-]+)(?:@(.+))?$/i;
50774
50775
  function parseSkillSource2(raw) {
50775
50776
  if (!raw || typeof raw !== "string") {
@@ -50809,6 +50810,17 @@ var EntrypointSchema = exports_external.object({
50809
50810
  }, {
50810
50811
  message: "entrypoint must set exactly one of `file`, `commands`, or `text`"
50811
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
+ });
50812
50824
  var SkillEntrySchema = exports_external.object({
50813
50825
  source: exports_external.string().min(1)
50814
50826
  });
@@ -50828,6 +50840,7 @@ var AgentManifestSchema = exports_external.object({
50828
50840
  agent: AgentMetaSchema,
50829
50841
  instructions: InstructionsSchema.optional(),
50830
50842
  entrypoint: EntrypointSchema.optional(),
50843
+ playbooks: exports_external.array(PlaybookSchema).default([]),
50831
50844
  skills: exports_external.array(SkillEntrySchema).default([]),
50832
50845
  mcp: exports_external.array(McpEntrySchema).default([]),
50833
50846
  commands: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
@@ -50911,6 +50924,21 @@ function resolveEntrypoint(cwd2, manifest) {
50911
50924
  }
50912
50925
  return null;
50913
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
+ }
50914
50942
 
50915
50943
  // src/core/link.ts
50916
50944
  var LINK_DIR = ".brainbase";
@@ -51064,6 +51092,7 @@ function writeLink(cwd2, link2) {
51064
51092
  manifest = readManifest(cwd2) ?? {
51065
51093
  schema: 1,
51066
51094
  agent: { name: link2.name },
51095
+ playbooks: [],
51067
51096
  skills: [],
51068
51097
  mcp: []
51069
51098
  };
@@ -51071,6 +51100,7 @@ function writeLink(cwd2, link2) {
51071
51100
  manifest = {
51072
51101
  schema: 1,
51073
51102
  agent: { name: link2.name },
51103
+ playbooks: [],
51074
51104
  skills: [],
51075
51105
  mcp: []
51076
51106
  };
@@ -51973,6 +52003,7 @@ import path48 from "node:path";
51973
52003
  import fs45 from "node:fs";
51974
52004
  import os12 from "node:os";
51975
52005
  var import_picocolors25 = __toESM(require_picocolors(), 1);
52006
+ var import_yaml3 = __toESM(require_dist(), 1);
51976
52007
 
51977
52008
  // src/core/agent-diff.ts
51978
52009
  import path46 from "node:path";
@@ -52119,8 +52150,34 @@ function readLocalComponents(cwd2, manifest) {
52119
52150
  hash: hashMcpEntry(entry)
52120
52151
  });
52121
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
+ }
52122
52174
  return out;
52123
52175
  }
52176
+ function jsonOrPlain(s3) {
52177
+ if (!/[\n":#&*!|>'%@`{}[\]]/.test(s3) && s3.trim() === s3 && s3 !== "")
52178
+ return s3;
52179
+ return JSON.stringify(s3);
52180
+ }
52124
52181
  function threeWayDiff(input) {
52125
52182
  const lockMap = new Map;
52126
52183
  for (const c2 of input.lock)
@@ -52489,8 +52546,9 @@ async function runAgentPull(cwd2, args) {
52489
52546
  }
52490
52547
  }
52491
52548
  }
52492
- materializeInstructions(cwd2, cloud, toInstallKeys, keepLocalKeys);
52549
+ materializeInstructions(cwd2, cloud, toInstallKeys, keepLocalKeys, existingManifest);
52493
52550
  materializeEntrypoint(cwd2, cloudAgent.entrypoint ?? "", existingManifest);
52551
+ materializePlaybooks(cwd2, cloud, toInstallKeys, keepLocalKeys, existingManifest);
52494
52552
  const yaml = mergeManifest(cwd2, existingManifest, cloud, cloudAgent, harness);
52495
52553
  writeManifest(cwd2, yaml);
52496
52554
  writeLink(cwd2, buildLinkFromAgent(cloudAgent, harness, readLink(cwd2)));
@@ -52595,7 +52653,7 @@ function runHarnessInstall2(harnessId, components, opts, agentName) {
52595
52653
  return installKafkaWithCtx(components, opts, agentName);
52596
52654
  return getAdapter(harnessId).install(components, opts);
52597
52655
  }
52598
- function materializeInstructions(cwd2, cloud, toInstall, keepLocal) {
52656
+ function materializeInstructions(cwd2, cloud, toInstall, keepLocal, existingManifest) {
52599
52657
  for (const c2 of cloud.components) {
52600
52658
  if (c2.type !== "instruction")
52601
52659
  continue;
@@ -52607,8 +52665,52 @@ function materializeInstructions(cwd2, cloud, toInstall, keepLocal) {
52607
52665
  const body = c2.files[0]?.content ?? "";
52608
52666
  if (!body.trim())
52609
52667
  continue;
52610
- fs45.writeFileSync(path48.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
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 };
52611
52712
  }
52713
+ return { frontmatter: fm, body: raw.slice(m3[0].length) };
52612
52714
  }
52613
52715
  function mergeManifest(cwd2, prev, cloud, cloudAgent, harness) {
52614
52716
  const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
@@ -52645,6 +52747,21 @@ function mergeManifest(cwd2, prev, cloud, cloudAgent, harness) {
52645
52747
  else
52646
52748
  entrypoint = { file: prev?.entrypoint?.file ?? DEFAULT_ENTRYPOINT_FILE };
52647
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
+ });
52648
52765
  const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
52649
52766
  const payload = (c2.meta ?? {}).mcp ?? {};
52650
52767
  const entry = { name: c2.slug };
@@ -52672,6 +52789,7 @@ function mergeManifest(cwd2, prev, cloud, cloudAgent, harness) {
52672
52789
  },
52673
52790
  ...instructions ? { instructions } : {},
52674
52791
  ...entrypoint ? { entrypoint } : {},
52792
+ playbooks,
52675
52793
  skills,
52676
52794
  mcp
52677
52795
  };
@@ -52910,6 +53028,42 @@ async function buildOutgoingComponents(cwd2, manifest, cloud) {
52910
53028
  }
52911
53029
  });
52912
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
+ }
52913
53067
  for (const entry of manifest.mcp ?? []) {
52914
53068
  if (!entry.url && !entry.command) {
52915
53069
  f2.error(`MCP ${import_picocolors26.default.bold(entry.name)} needs either ${import_picocolors26.default.cyan("url")} or ${import_picocolors26.default.cyan("command")}.`);
@@ -52937,6 +53091,23 @@ async function buildOutgoingComponents(cwd2, manifest, cloud) {
52937
53091
  }
52938
53092
  return out;
52939
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
+ }
52940
53111
 
52941
53112
  // src/cli/agent-push.ts
52942
53113
  async function runAgentPush(cwd2, args) {
@@ -53003,8 +53174,8 @@ async function runAgentPush(cwd2, args) {
53003
53174
  }
53004
53175
  const entrypointChanged = resolvedEntrypoint !== undefined && resolvedEntrypoint !== (lock?.agentMeta?.entrypoint ?? "");
53005
53176
  for (const r2 of rows) {
53006
- if (r2.type !== "instruction" && r2.type !== "skill" && r2.type !== "mcp") {
53007
- f2.error(`Component ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)} can't be pushed yet — the server accepts instructions, skills, and mcps in this version.`);
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.`);
53008
53179
  return;
53009
53180
  }
53010
53181
  }
@@ -53731,6 +53902,7 @@ async function loadOrScaffoldManifest(cwd2, args) {
53731
53902
  schema: 1,
53732
53903
  ...seedHarness ? { harness: seedHarness } : {},
53733
53904
  agent: { name: seedName, ...args.tagline ? { tagline: args.tagline } : {} },
53905
+ playbooks: [],
53734
53906
  skills: [],
53735
53907
  mcp: []
53736
53908
  };
@@ -53774,183 +53946,10 @@ function handleApiError4(err) {
53774
53946
  }
53775
53947
 
53776
53948
  // src/cli/agent-unpack.ts
53777
- var import_picocolors31 = __toESM(require_picocolors(), 1);
53778
-
53779
- // src/core/agent-fresh-install.ts
53780
53949
  import path50 from "node:path";
53781
53950
  import fs46 from "node:fs";
53782
53951
  import os13 from "node:os";
53783
- async function installAgentFresh(input) {
53784
- const { cwd: cwd2, agent, cloud, harness } = input;
53785
- const scope = input.scope ?? "project";
53786
- ensureDir(cwd2);
53787
- const stageRoot = stageManifestComponents2(cloud.components);
53788
- const justInstalledPaths = new Map;
53789
- const cloudHasOrchestrationMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === ORCHESTRATION_MCP_SLUG);
53790
- const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
53791
- const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
53792
- const needMemoryMcpInstall = !cloudHasMemoryMcp;
53793
- try {
53794
- if (cloud.components.length > 0 || needOrchestrationMcpInstall || needMemoryMcpInstall) {
53795
- const toInstall = cloud.components.map((c2) => ({
53796
- type: c2.type,
53797
- slug: c2.slug,
53798
- scope,
53799
- rootDir: path50.join(stageRoot, c2.type, c2.slug),
53800
- description: c2.description,
53801
- meta: c2.meta,
53802
- payload: c2.meta?.mcp,
53803
- checksum: c2.hash
53804
- }));
53805
- if (needOrchestrationMcpInstall) {
53806
- toInstall.push(buildOrchestrationMcpComponent(scope));
53807
- }
53808
- if (needMemoryMcpInstall) {
53809
- toInstall.push(buildMemoryMcpComponent(scope));
53810
- }
53811
- const installOpts = {
53812
- cwd: cwd2,
53813
- scope,
53814
- resolveConflict: async (_c) => "overwrite",
53815
- resolveSecret: async () => null
53816
- };
53817
- const result = await runHarnessInstall3(harness, toInstall, installOpts, agent.name);
53818
- for (const o2 of result.installed) {
53819
- justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
53820
- }
53821
- }
53822
- materializeInstructions2(cwd2, cloud);
53823
- const manifest = input.preserveManifest ? null : buildManifestFromCloud(cloud, agent);
53824
- if (manifest)
53825
- writeManifest(cwd2, manifest);
53826
- writeLink(cwd2, {
53827
- schemaVersion: 1,
53828
- agent_id: agent.id,
53829
- org_id: agent.org_id,
53830
- team_id: agent.team_id,
53831
- slug: agent.slug,
53832
- name: agent.name,
53833
- tagline: agent.tagline,
53834
- url: agent.url,
53835
- linked_at: new Date().toISOString(),
53836
- harness
53837
- });
53838
- const syncedComponents = cloud.components.map((c2) => ({
53839
- type: c2.type,
53840
- slug: c2.slug,
53841
- hash: c2.hash,
53842
- installedPaths: justInstalledPaths.get(`${c2.type}/${c2.slug}`) ?? []
53843
- }));
53844
- writeSyncState(cwd2, {
53845
- schemaVersion: 1,
53846
- agent_id: agent.id,
53847
- revision: cloud.revision,
53848
- synced_at: new Date().toISOString(),
53849
- components: syncedComponents,
53850
- agentMeta: { name: agent.name, tagline: agent.tagline }
53851
- });
53852
- if (input.pullSecrets !== false) {
53853
- await pullAgentSecrets(cwd2, agent.id);
53854
- }
53855
- const returnedManifest = manifest ?? buildManifestFromCloud(cloud, agent);
53856
- return {
53857
- installedPaths: justInstalledPaths,
53858
- manifest: returnedManifest,
53859
- syncedComponents
53860
- };
53861
- } finally {
53862
- try {
53863
- fs46.rmSync(stageRoot, { recursive: true, force: true });
53864
- } catch {}
53865
- }
53866
- }
53867
- function stageManifestComponents2(components) {
53868
- const root = fs46.mkdtempSync(path50.join(os13.tmpdir(), "brainbase-orch-pull-"));
53869
- for (const c2 of components) {
53870
- const compDir = path50.join(root, c2.type, c2.slug);
53871
- ensureDir(compDir);
53872
- for (const f4 of c2.files) {
53873
- const target = path50.join(compDir, f4.path);
53874
- ensureDir(path50.dirname(target));
53875
- fs46.writeFileSync(target, f4.content);
53876
- }
53877
- }
53878
- return root;
53879
- }
53880
- function runHarnessInstall3(harnessId, components, opts, agentName) {
53881
- if (harnessId === "claude-code")
53882
- return installClaudeCodeWithCtx(components, opts, agentName);
53883
- if (harnessId === "codex")
53884
- return installCodexWithCtx(components, opts, agentName);
53885
- if (harnessId === "kafka")
53886
- return installKafkaWithCtx(components, opts, agentName);
53887
- return getAdapter(harnessId).install(components, opts);
53888
- }
53889
- function materializeInstructions2(cwd2, cloud) {
53890
- for (const c2 of cloud.components) {
53891
- if (c2.type !== "instruction")
53892
- continue;
53893
- const body = c2.files[0]?.content ?? "";
53894
- if (!body.trim())
53895
- continue;
53896
- fs46.writeFileSync(path50.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
53897
- return;
53898
- }
53899
- }
53900
- function buildManifestFromCloud(cloud, agent) {
53901
- const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
53902
- const meta = c2.meta ?? {};
53903
- if (meta.name && meta.name.includes("/")) {
53904
- return {
53905
- source: meta.version ? `registry:${meta.name}@${meta.version}` : `registry:${meta.name}`
53906
- };
53907
- }
53908
- return { source: `registry:${c2.slug}` };
53909
- });
53910
- const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
53911
- const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
53912
- const payload = (c2.meta ?? {}).mcp ?? {};
53913
- const entry = { name: c2.slug };
53914
- if (typeof payload.url === "string")
53915
- entry.url = payload.url;
53916
- if (typeof payload.command === "string")
53917
- entry.command = payload.command;
53918
- if (Array.isArray(payload.args))
53919
- entry.args = payload.args.map(String);
53920
- if (payload.env && typeof payload.env === "object")
53921
- entry.env = payload.env;
53922
- if (payload.headers && typeof payload.headers === "object")
53923
- entry.headers = payload.headers;
53924
- if (typeof payload.is_enabled === "boolean")
53925
- entry.is_enabled = payload.is_enabled;
53926
- return entry;
53927
- });
53928
- return {
53929
- schema: 1,
53930
- agent: {
53931
- name: agent.name,
53932
- ...agent.tagline ? { tagline: agent.tagline } : {}
53933
- },
53934
- ...hasInstructions ? { instructions: { file: DEFAULT_INSTRUCTIONS_FILE } } : {},
53935
- skills,
53936
- mcp
53937
- };
53938
- }
53939
- async function pullAgentSecrets(cwd2, agentId) {
53940
- try {
53941
- const res = await api.getAgentSecrets(agentId);
53942
- const secrets = res.secrets ?? {};
53943
- if (Object.keys(secrets).length > 0) {
53944
- writeLocalSecrets(cwd2, secrets);
53945
- }
53946
- } catch (err) {
53947
- if (err instanceof ApiError && err.status !== 404) {
53948
- f2.warn(`Skipped secrets for agent ${agentId}: ${err.message}`);
53949
- }
53950
- }
53951
- }
53952
-
53953
- // src/cli/agent-unpack.ts
53952
+ var import_picocolors31 = __toESM(require_picocolors(), 1);
53954
53953
  async function runAgentUnpack(cwd2, args) {
53955
53954
  banner("agent unpack — install this agent into a harness layout");
53956
53955
  if (!hasManifest(cwd2)) {
@@ -53982,22 +53981,9 @@ async function runAgentUnpack(cwd2, args) {
53982
53981
  } else {
53983
53982
  harness = await pickHarness2(manifest.harness);
53984
53983
  }
53985
- const sp = de();
53986
- sp.start("Fetching agent…");
53987
- let cloudAgent;
53988
- let cloud;
53989
- try {
53990
- cloudAgent = await api.getAgent(manifest.id);
53991
- cloud = await api.getAgentManifest(manifest.id);
53992
- sp.stop(`Cloud revision ${cloud.revision}.`);
53993
- } catch (err) {
53994
- sp.stop("Failed.");
53995
- handleApiError5(err);
53996
- return;
53997
- }
53998
53984
  if (!args.yes) {
53999
53985
  const ok = await se({
54000
- message: `Install ${import_picocolors31.default.bold(cloudAgent.name)} as ${import_picocolors31.default.bold(harness)} here?`,
53986
+ message: `Install ${import_picocolors31.default.bold(manifest.agent.name)} as ${import_picocolors31.default.bold(harness)} here?`,
54001
53987
  initialValue: true
54002
53988
  });
54003
53989
  if (!ensureNotCancelled(ok)) {
@@ -54005,46 +53991,206 @@ async function runAgentUnpack(cwd2, args) {
54005
53991
  return;
54006
53992
  }
54007
53993
  }
54008
- const prevLink = readLink(cwd2);
53994
+ const scope = args.scope ?? "project";
53995
+ const stageRoot = fs46.mkdtempSync(path50.join(os13.tmpdir(), "brainbase-unpack-"));
54009
53996
  try {
54010
- await installAgentFresh({
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 = {
54011
54055
  cwd: cwd2,
54012
- agent: {
54013
- id: cloudAgent.id,
54014
- name: cloudAgent.name,
54015
- slug: cloudAgent.slug,
54016
- tagline: cloudAgent.tagline,
54017
- org_id: cloudAgent.org_id ?? prevLink?.org_id ?? "",
54018
- team_id: cloudAgent.team_id ?? prevLink?.team_id ?? "",
54019
- url: cloudAgent.url,
54020
- harness
54021
- },
54022
- cloud,
54023
- harness,
54024
- scope: args.scope ?? "project",
54025
- preserveManifest: true
54026
- });
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
+ }
54027
54067
  } catch (err) {
54028
54068
  f2.error(`Install failed: ${err.message}`);
54029
54069
  return;
54070
+ } finally {
54071
+ try {
54072
+ fs46.rmSync(stageRoot, { recursive: true, force: true });
54073
+ } catch {}
54030
54074
  }
54031
- manifest = readManifest(cwd2);
54032
54075
  if (manifest.harness !== harness) {
54033
54076
  manifest.harness = harness;
54034
54077
  writeManifest(cwd2, manifest);
54035
54078
  }
54036
- $e(`Unpacked ${import_picocolors31.default.bold(cloudAgent.name)} as ${import_picocolors31.default.bold(harness)}.`);
54079
+ $e(`Unpacked ${import_picocolors31.default.bold(manifest.agent.name)} as ${import_picocolors31.default.bold(harness)}.`);
54037
54080
  await showResultCard({
54038
54081
  title: "UNPACKED",
54039
54082
  tone: "ok",
54040
- subtitle: cloudAgent.name,
54083
+ subtitle: manifest.agent.name,
54041
54084
  meta: [
54042
54085
  ["harness", harness],
54043
- ["agent", cloudAgent.id],
54044
- ...cloudAgent.url ? [["url", cloudAgent.url]] : []
54086
+ ["agent", manifest.id]
54045
54087
  ]
54046
54088
  });
54047
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
+ }
54048
54194
  async function pickHarness2(current) {
54049
54195
  const initial = current ? normalizeHarnessId(current) : undefined;
54050
54196
  const choice = await ie({
@@ -54058,19 +54204,6 @@ async function pickHarness2(current) {
54058
54204
  });
54059
54205
  return ensureNotCancelled(choice);
54060
54206
  }
54061
- function handleApiError5(err) {
54062
- if (err instanceof ApiError) {
54063
- if (err.status === 401) {
54064
- f2.error("Your session is invalid. Run `brainbase login` and try again.");
54065
- } else if (err.status === 404) {
54066
- f2.error(`Agent not found, or you don't have access. The id in ${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} may be stale.`);
54067
- } else {
54068
- f2.error(err.message);
54069
- }
54070
- } else {
54071
- f2.error(err.message);
54072
- }
54073
- }
54074
54207
 
54075
54208
  // src/cli/agent.ts
54076
54209
  async function runAgent(cwd2, sub, args, opts) {
@@ -54143,14 +54276,14 @@ function printHelp() {
54143
54276
  var import_picocolors37 = __toESM(require_picocolors(), 1);
54144
54277
 
54145
54278
  // src/cli/orchestration-pull.ts
54146
- import path53 from "node:path";
54147
- import fs49 from "node:fs";
54279
+ import path54 from "node:path";
54280
+ import fs50 from "node:fs";
54148
54281
  var import_picocolors33 = __toESM(require_picocolors(), 1);
54149
54282
 
54150
54283
  // src/core/orchestration-manifest.ts
54151
54284
  import path51 from "node:path";
54152
54285
  import fs47 from "node:fs";
54153
- var import_yaml3 = __toESM(require_dist(), 1);
54286
+ var import_yaml4 = __toESM(require_dist(), 1);
54154
54287
  var ORCH_MANIFEST_FILE = "brainbase-orchestration.yaml";
54155
54288
  var ORCH_MEMBERS_DIR = "agents";
54156
54289
  var OrchMetaSchema = exports_external.object({
@@ -54189,7 +54322,7 @@ function readOrchManifest(cwd2) {
54189
54322
  const raw = fs47.readFileSync(p2, "utf8");
54190
54323
  let parsed;
54191
54324
  try {
54192
- parsed = import_yaml3.default.parse(raw);
54325
+ parsed = import_yaml4.default.parse(raw);
54193
54326
  } catch (err) {
54194
54327
  throw new Error(`${ORCH_MANIFEST_FILE} is not valid YAML: ${err.message}`);
54195
54328
  }
@@ -54200,7 +54333,7 @@ function readOrchManifest(cwd2) {
54200
54333
  return result.data;
54201
54334
  }
54202
54335
  function writeOrchManifest(cwd2, manifest) {
54203
- const doc = new import_yaml3.default.Document;
54336
+ const doc = new import_yaml4.default.Document;
54204
54337
  doc.contents = manifest;
54205
54338
  doc.commentBefore = ` brainbase-orchestration.yaml — declarative orchestration manifest.
54206
54339
  ` + ` Committed to source control. Edit by hand, then
@@ -54305,6 +54438,181 @@ function ensureGitignore2(cwd2) {
54305
54438
  } catch {}
54306
54439
  }
54307
54440
 
54441
+ // src/core/agent-fresh-install.ts
54442
+ import path53 from "node:path";
54443
+ import fs49 from "node:fs";
54444
+ import os14 from "node:os";
54445
+ async function installAgentFresh(input) {
54446
+ const { cwd: cwd2, agent, cloud, harness } = input;
54447
+ const scope = input.scope ?? "project";
54448
+ ensureDir(cwd2);
54449
+ const stageRoot = stageManifestComponents2(cloud.components);
54450
+ const justInstalledPaths = new Map;
54451
+ const cloudHasOrchestrationMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === ORCHESTRATION_MCP_SLUG);
54452
+ const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
54453
+ const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
54454
+ const needMemoryMcpInstall = !cloudHasMemoryMcp;
54455
+ try {
54456
+ if (cloud.components.length > 0 || needOrchestrationMcpInstall || needMemoryMcpInstall) {
54457
+ const toInstall = cloud.components.map((c2) => ({
54458
+ type: c2.type,
54459
+ slug: c2.slug,
54460
+ scope,
54461
+ rootDir: path53.join(stageRoot, c2.type, c2.slug),
54462
+ description: c2.description,
54463
+ meta: c2.meta,
54464
+ payload: c2.meta?.mcp,
54465
+ checksum: c2.hash
54466
+ }));
54467
+ if (needOrchestrationMcpInstall) {
54468
+ toInstall.push(buildOrchestrationMcpComponent(scope));
54469
+ }
54470
+ if (needMemoryMcpInstall) {
54471
+ toInstall.push(buildMemoryMcpComponent(scope));
54472
+ }
54473
+ const installOpts = {
54474
+ cwd: cwd2,
54475
+ scope,
54476
+ resolveConflict: async (_c) => "overwrite",
54477
+ resolveSecret: async () => null
54478
+ };
54479
+ const result = await runHarnessInstall4(harness, toInstall, installOpts, agent.name);
54480
+ for (const o2 of result.installed) {
54481
+ justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
54482
+ }
54483
+ }
54484
+ materializeInstructions2(cwd2, cloud);
54485
+ const manifest = input.preserveManifest ? null : buildManifestFromCloud(cloud, agent);
54486
+ if (manifest)
54487
+ writeManifest(cwd2, manifest);
54488
+ writeLink(cwd2, {
54489
+ schemaVersion: 1,
54490
+ agent_id: agent.id,
54491
+ org_id: agent.org_id,
54492
+ team_id: agent.team_id,
54493
+ slug: agent.slug,
54494
+ name: agent.name,
54495
+ tagline: agent.tagline,
54496
+ url: agent.url,
54497
+ linked_at: new Date().toISOString(),
54498
+ harness
54499
+ });
54500
+ const syncedComponents = cloud.components.map((c2) => ({
54501
+ type: c2.type,
54502
+ slug: c2.slug,
54503
+ hash: c2.hash,
54504
+ installedPaths: justInstalledPaths.get(`${c2.type}/${c2.slug}`) ?? []
54505
+ }));
54506
+ writeSyncState(cwd2, {
54507
+ schemaVersion: 1,
54508
+ agent_id: agent.id,
54509
+ revision: cloud.revision,
54510
+ synced_at: new Date().toISOString(),
54511
+ components: syncedComponents,
54512
+ agentMeta: { name: agent.name, tagline: agent.tagline }
54513
+ });
54514
+ if (input.pullSecrets !== false) {
54515
+ await pullAgentSecrets(cwd2, agent.id);
54516
+ }
54517
+ const returnedManifest = manifest ?? buildManifestFromCloud(cloud, agent);
54518
+ return {
54519
+ installedPaths: justInstalledPaths,
54520
+ manifest: returnedManifest,
54521
+ syncedComponents
54522
+ };
54523
+ } finally {
54524
+ try {
54525
+ fs49.rmSync(stageRoot, { recursive: true, force: true });
54526
+ } catch {}
54527
+ }
54528
+ }
54529
+ function stageManifestComponents2(components) {
54530
+ const root = fs49.mkdtempSync(path53.join(os14.tmpdir(), "brainbase-orch-pull-"));
54531
+ for (const c2 of components) {
54532
+ const compDir = path53.join(root, c2.type, c2.slug);
54533
+ ensureDir(compDir);
54534
+ for (const f4 of c2.files) {
54535
+ const target = path53.join(compDir, f4.path);
54536
+ ensureDir(path53.dirname(target));
54537
+ fs49.writeFileSync(target, f4.content);
54538
+ }
54539
+ }
54540
+ return root;
54541
+ }
54542
+ function runHarnessInstall4(harnessId, components, opts, agentName) {
54543
+ if (harnessId === "claude-code")
54544
+ return installClaudeCodeWithCtx(components, opts, agentName);
54545
+ if (harnessId === "codex")
54546
+ return installCodexWithCtx(components, opts, agentName);
54547
+ if (harnessId === "kafka")
54548
+ return installKafkaWithCtx(components, opts, agentName);
54549
+ return getAdapter(harnessId).install(components, opts);
54550
+ }
54551
+ function materializeInstructions2(cwd2, cloud) {
54552
+ for (const c2 of cloud.components) {
54553
+ if (c2.type !== "instruction")
54554
+ continue;
54555
+ const body = c2.files[0]?.content ?? "";
54556
+ if (!body.trim())
54557
+ continue;
54558
+ fs49.writeFileSync(path53.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
54559
+ return;
54560
+ }
54561
+ }
54562
+ function buildManifestFromCloud(cloud, agent) {
54563
+ const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
54564
+ const meta = c2.meta ?? {};
54565
+ if (meta.name && meta.name.includes("/")) {
54566
+ return {
54567
+ source: meta.version ? `registry:${meta.name}@${meta.version}` : `registry:${meta.name}`
54568
+ };
54569
+ }
54570
+ return { source: `registry:${c2.slug}` };
54571
+ });
54572
+ const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
54573
+ const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
54574
+ const payload = (c2.meta ?? {}).mcp ?? {};
54575
+ const entry = { name: c2.slug };
54576
+ if (typeof payload.url === "string")
54577
+ entry.url = payload.url;
54578
+ if (typeof payload.command === "string")
54579
+ entry.command = payload.command;
54580
+ if (Array.isArray(payload.args))
54581
+ entry.args = payload.args.map(String);
54582
+ if (payload.env && typeof payload.env === "object")
54583
+ entry.env = payload.env;
54584
+ if (payload.headers && typeof payload.headers === "object")
54585
+ entry.headers = payload.headers;
54586
+ if (typeof payload.is_enabled === "boolean")
54587
+ entry.is_enabled = payload.is_enabled;
54588
+ return entry;
54589
+ });
54590
+ return {
54591
+ schema: 1,
54592
+ agent: {
54593
+ name: agent.name,
54594
+ ...agent.tagline ? { tagline: agent.tagline } : {}
54595
+ },
54596
+ ...hasInstructions ? { instructions: { file: DEFAULT_INSTRUCTIONS_FILE } } : {},
54597
+ playbooks: [],
54598
+ skills,
54599
+ mcp
54600
+ };
54601
+ }
54602
+ async function pullAgentSecrets(cwd2, agentId) {
54603
+ try {
54604
+ const res = await api.getAgentSecrets(agentId);
54605
+ const secrets = res.secrets ?? {};
54606
+ if (Object.keys(secrets).length > 0) {
54607
+ writeLocalSecrets(cwd2, secrets);
54608
+ }
54609
+ } catch (err) {
54610
+ if (err instanceof ApiError && err.status !== 404) {
54611
+ f2.warn(`Skipped secrets for agent ${agentId}: ${err.message}`);
54612
+ }
54613
+ }
54614
+ }
54615
+
54308
54616
  // src/cli/orchestration-pull.ts
54309
54617
  async function runOrchestrationPull(cwd2, args) {
54310
54618
  banner("orchestration pull — fetch orchestration + all member agents");
@@ -54328,7 +54636,7 @@ async function runOrchestrationPull(cwd2, args) {
54328
54636
  sp.stop(`Cloud revision ${cloud.revision} — ${cloud.members.length} member${cloud.members.length === 1 ? "" : "s"}, ${cloud.edges.length} edge${cloud.edges.length === 1 ? "" : "s"}.`);
54329
54637
  } catch (err) {
54330
54638
  sp.stop("Failed.");
54331
- handleApiError6(err);
54639
+ handleApiError5(err);
54332
54640
  return;
54333
54641
  }
54334
54642
  const planLines = [];
@@ -54368,7 +54676,7 @@ async function runOrchestrationPull(cwd2, args) {
54368
54676
  }
54369
54677
  }
54370
54678
  const fallbackHarness = args.harness ?? "claude-code";
54371
- fs49.mkdirSync(cwd2, { recursive: true });
54679
+ fs50.mkdirSync(cwd2, { recursive: true });
54372
54680
  if (hasOrchManifest(cwd2) && existingLink && existingLink.orchestration_id !== orchId) {
54373
54681
  f2.error(`This folder is linked to orchestration ${existingLink.orchestration_id}, not ${orchId}. Move to a fresh directory or unlink first.`);
54374
54682
  return;
@@ -54455,9 +54763,9 @@ async function runOrchestrationPull(cwd2, args) {
54455
54763
  payload_schema: e2.payload_schema ?? {}
54456
54764
  }))
54457
54765
  });
54458
- $e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path53.basename(cwd2)}/ ${import_picocolors33.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
54766
+ $e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path54.basename(cwd2)}/ ${import_picocolors33.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
54459
54767
  }
54460
- function handleApiError6(err) {
54768
+ function handleApiError5(err) {
54461
54769
  if (err instanceof ApiError) {
54462
54770
  if (err.status === 401) {
54463
54771
  f2.error("Your session is invalid. Run `brainbase login` and try again.");
@@ -54602,10 +54910,10 @@ async function runOrchestrationPush(cwd2, args) {
54602
54910
  $e(`Pushed ${link2.name} at revision ${updated.revision}.`);
54603
54911
  } catch (err) {
54604
54912
  sp.stop("Failed.");
54605
- handleApiError7(err);
54913
+ handleApiError6(err);
54606
54914
  }
54607
54915
  }
54608
- function handleApiError7(err) {
54916
+ function handleApiError6(err) {
54609
54917
  if (err instanceof ApiError) {
54610
54918
  if (err.status === 401) {
54611
54919
  f2.error("Your session is invalid. Run `brainbase login` and try again.");
@@ -54736,7 +55044,7 @@ async function runOrchestrationList(args) {
54736
55044
  try {
54737
55045
  orgs = await api.listOrgs();
54738
55046
  } catch (err) {
54739
- handleApiError8(err);
55047
+ handleApiError7(err);
54740
55048
  return;
54741
55049
  }
54742
55050
  if (orgs.length === 0) {
@@ -54758,7 +55066,7 @@ async function runOrchestrationList(args) {
54758
55066
  try {
54759
55067
  teams = await api.listTeams(orgId);
54760
55068
  } catch (err) {
54761
- handleApiError8(err);
55069
+ handleApiError7(err);
54762
55070
  return;
54763
55071
  }
54764
55072
  if (teams.length === 0) {
@@ -54783,7 +55091,7 @@ async function runOrchestrationList(args) {
54783
55091
  sp.stop(`${items.length} orchestration${items.length === 1 ? "" : "s"}.`);
54784
55092
  } catch (err) {
54785
55093
  sp.stop("Failed.");
54786
- handleApiError8(err);
55094
+ handleApiError7(err);
54787
55095
  return;
54788
55096
  }
54789
55097
  if (items.length === 0) {
@@ -54803,7 +55111,7 @@ async function runOrchestrationList(args) {
54803
55111
  console.log(lines.join(`
54804
55112
  `));
54805
55113
  }
54806
- function handleApiError8(err) {
55114
+ function handleApiError7(err) {
54807
55115
  if (err instanceof ApiError) {
54808
55116
  if (err.status === 401) {
54809
55117
  f2.error("Your session is invalid. Run `brainbase login` and try again.");
@@ -55608,7 +55916,7 @@ var PROTECTED = new Set([
55608
55916
  function help() {
55609
55917
  const out = [];
55610
55918
  out.push("");
55611
- out.push(` ${brandTint("◆")} ${import_picocolors40.default.bold("brainbase")} ${import_picocolors40.default.dim("v0.5.0")}`);
55919
+ out.push(` ${brandTint("◆")} ${import_picocolors40.default.bold("brainbase")} ${import_picocolors40.default.dim("v0.6.0")}`);
55612
55920
  out.push(` ${import_picocolors40.default.dim("connect your local agent to the brainbase platform")}`);
55613
55921
  out.push("");
55614
55922
  out.push(divider("USAGE"));
@@ -55751,7 +56059,7 @@ async function main() {
55751
56059
  const rawCwd = process13.cwd();
55752
56060
  const cwd2 = (() => {
55753
56061
  try {
55754
- return fs50.realpathSync(rawCwd);
56062
+ return fs51.realpathSync(rawCwd);
55755
56063
  } catch {
55756
56064
  return rawCwd;
55757
56065
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainbase-labs/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
5
5
  "type": "module",
6
6
  "bin": {