@brainbase-labs/cli 0.10.0 → 0.10.1

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 +108 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -29449,7 +29449,7 @@ function padStart(s, n) {
29449
29449
  // package.json
29450
29450
  var package_default = {
29451
29451
  name: "@brainbase-labs/cli",
29452
- version: "0.10.0",
29452
+ version: "0.10.1",
29453
29453
  description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
29454
29454
  type: "module",
29455
29455
  bin: {
@@ -50413,6 +50413,7 @@ async function runSkillPublish(cwd2, args) {
50413
50413
  writeSkillMarker(skillDir, newSource);
50414
50414
  $e(`${import_picocolors16.default.bold(creator + "/" + pkgSlug)}@${version} published.`);
50415
50415
  f2.info(import_picocolors16.default.dim(`id: ${result2.id}`));
50416
+ f2.info(import_picocolors16.default.dim(`To use it on an agent: add ${import_picocolors16.default.cyan(`source: registry:${creator}/${pkgSlug}`)} under ${import_picocolors16.default.cyan("skills:")} in brainbase.agent.yaml, then ${import_picocolors16.default.cyan("brainbase agent push")}. Agents already linking it pick up ${version} on their next push.`));
50416
50417
  } finally {
50417
50418
  try {
50418
50419
  fs37.rmSync(tmp, { recursive: true, force: true });
@@ -50544,6 +50545,9 @@ async function runSkillUpdate(cwd2, args) {
50544
50545
  }
50545
50546
  writeSkillMarker(target.dir, marker.source);
50546
50547
  $e(`${import_picocolors17.default.bold(args.slug)} updated.`);
50548
+ if (marker.source.type === "brainbase") {
50549
+ f2.info(import_picocolors17.default.dim(`This refreshed your local copy only. Agents using this skill update on their next ${import_picocolors17.default.cyan("brainbase agent push")} (run it in the agent's folder).`));
50550
+ }
50547
50551
  }
50548
50552
 
50549
50553
  // src/cli/skill-search.ts
@@ -52649,7 +52653,8 @@ function threeWayDiff(input) {
52649
52653
  } else if (present.local && !present.cloud && present.lock) {
52650
52654
  status = "removed-cloud";
52651
52655
  } else {
52652
- const localChanged = localHash !== null && lockHash !== undefined && localHash !== lockHash;
52656
+ const sourceChanged = !!local && local.hash === null && !!local.declaredSource && lock?.source !== undefined && lock.source !== local.declaredSource;
52657
+ const localChanged = sourceChanged || localHash !== null && lockHash !== undefined && localHash !== lockHash;
52653
52658
  const cloudChanged = cloudHash !== undefined && lockHash !== undefined && cloudHash !== lockHash;
52654
52659
  if (localChanged && cloudChanged)
52655
52660
  status = "modified-both";
@@ -53413,7 +53418,7 @@ var import_picocolors27 = __toESM(require_picocolors(), 1);
53413
53418
 
53414
53419
  // src/core/agent-outgoing.ts
53415
53420
  var import_picocolors26 = __toESM(require_picocolors(), 1);
53416
- async function buildOutgoingComponents(cwd2, manifest, cloud) {
53421
+ async function buildOutgoingComponents(cwd2, manifest, cloud, resolvedVersions) {
53417
53422
  const out = [];
53418
53423
  if (manifest.instructions) {
53419
53424
  if (manifest.instructions.text !== undefined && manifest.instructions.file !== undefined) {
@@ -53460,6 +53465,7 @@ async function buildOutgoingComponents(cwd2, manifest, cloud) {
53460
53465
  }
53461
53466
  const slug = registrySkillComponentSlug(parsed);
53462
53467
  const cloudMatch = cloud?.components.find((c2) => c2.type === "skill" && c2.slug === slug);
53468
+ const version = parsed.version ?? resolvedVersions?.get(slug);
53463
53469
  out.push({
53464
53470
  type: "skill",
53465
53471
  slug,
@@ -53467,7 +53473,7 @@ async function buildOutgoingComponents(cwd2, manifest, cloud) {
53467
53473
  files: [],
53468
53474
  meta: {
53469
53475
  name: parsed.creator ? `${parsed.creator}/${parsed.slug}` : parsed.slug,
53470
- ...parsed.version ? { version: parsed.version } : {}
53476
+ ...version ? { version } : {}
53471
53477
  }
53472
53478
  });
53473
53479
  }
@@ -53552,6 +53558,62 @@ function yamlScalar(s3) {
53552
53558
  return JSON.stringify(s3);
53553
53559
  }
53554
53560
 
53561
+ // src/core/registry-skill-updates.ts
53562
+ function parseSemver2(v3) {
53563
+ const m3 = /^(\d+)\.(\d+)\.(\d+)$/.exec(v3);
53564
+ if (!m3)
53565
+ return null;
53566
+ return [Number(m3[1]), Number(m3[2]), Number(m3[3])];
53567
+ }
53568
+ function compareDirection(current, latest) {
53569
+ if (!current)
53570
+ return "unknown";
53571
+ const a3 = parseSemver2(current);
53572
+ const b4 = parseSemver2(latest);
53573
+ if (!a3 || !b4)
53574
+ return "unknown";
53575
+ for (let i = 0;i < 3; i++) {
53576
+ if (b4[i] > a3[i])
53577
+ return "upgrade";
53578
+ if (b4[i] < a3[i])
53579
+ return "downgrade";
53580
+ }
53581
+ return "unknown";
53582
+ }
53583
+ function planRegistrySkillUpdates(skills, cloudComponents, latestByName) {
53584
+ const out = [];
53585
+ for (const entry of skills) {
53586
+ let parsed;
53587
+ try {
53588
+ parsed = parseSkillSource2(entry.source);
53589
+ } catch {
53590
+ continue;
53591
+ }
53592
+ if (parsed.kind !== "registry" || parsed.version || !parsed.creator) {
53593
+ continue;
53594
+ }
53595
+ const name = `${parsed.creator}/${parsed.slug}`;
53596
+ const latest = latestByName.get(name);
53597
+ if (!latest)
53598
+ continue;
53599
+ const componentSlug = registrySkillComponentSlug(parsed);
53600
+ const cloud = cloudComponents.find((c2) => c2.type === "skill" && c2.slug === componentSlug);
53601
+ if (!cloud)
53602
+ continue;
53603
+ const current = cloud.meta?.["version"];
53604
+ if (current === latest)
53605
+ continue;
53606
+ out.push({
53607
+ componentSlug,
53608
+ name,
53609
+ current,
53610
+ latest,
53611
+ direction: compareDirection(current, latest)
53612
+ });
53613
+ }
53614
+ return out;
53615
+ }
53616
+
53555
53617
  // src/cli/agent-push.ts
53556
53618
  async function runAgentPush(cwd2, args) {
53557
53619
  banner("agent push — send your local changes to the cloud");
@@ -53590,6 +53652,37 @@ async function runAgentPush(cwd2, args) {
53590
53652
  lock: lock?.components ?? [],
53591
53653
  cloud: cloud.components
53592
53654
  });
53655
+ const unpinned = new Map;
53656
+ for (const entry of manifest.skills) {
53657
+ try {
53658
+ const parsed = parseSkillSource2(entry.source);
53659
+ if (parsed.kind === "registry" && !parsed.version && parsed.creator) {
53660
+ unpinned.set(`${parsed.creator}/${parsed.slug}`, {
53661
+ creator: parsed.creator,
53662
+ slug: parsed.slug
53663
+ });
53664
+ }
53665
+ } catch {}
53666
+ }
53667
+ const latestByName = new Map;
53668
+ if (unpinned.size > 0) {
53669
+ await Promise.all([...unpinned.entries()].map(async ([name, ref]) => {
53670
+ try {
53671
+ const pkg = await skillsApi.getPackage(ref.creator, ref.slug);
53672
+ if (pkg.latest_version?.version) {
53673
+ latestByName.set(name, pkg.latest_version.version);
53674
+ }
53675
+ } catch {}
53676
+ }));
53677
+ }
53678
+ const skillUpdates = planRegistrySkillUpdates(manifest.skills, cloud.components, latestByName);
53679
+ const resolvedVersions = new Map(skillUpdates.map((u2) => [u2.componentSlug, u2.latest]));
53680
+ for (const u2 of skillUpdates) {
53681
+ const row = rows.find((r2) => r2.key === compKey("skill", u2.componentSlug));
53682
+ if (row && (row.status === "in-sync" || row.status === "modified-cloud" || row.status === "added-local")) {
53683
+ row.status = "modified-local";
53684
+ }
53685
+ }
53593
53686
  let cloudMeta = lock?.agentMeta;
53594
53687
  if (!cloudMeta) {
53595
53688
  try {
@@ -53673,6 +53766,16 @@ async function runAgentPush(cwd2, args) {
53673
53766
  }
53674
53767
  f2.info(`If you push now, your push targets revision ${cloud.revision} and may race. Consider \`brainbase agent pull\` first.`);
53675
53768
  }
53769
+ const sendKeys = new Set(toSend.map((r2) => r2.key));
53770
+ for (const u2 of skillUpdates) {
53771
+ if (!sendKeys.has(compKey("skill", u2.componentSlug)))
53772
+ continue;
53773
+ if (u2.direction === "downgrade") {
53774
+ f2.warn(`Skill ${import_picocolors27.default.bold(u2.name)}: registry latest is ${import_picocolors27.default.bold(u2.latest)}, below the agent's ${import_picocolors27.default.dim(u2.current)} — the agent's version was likely yanked. Converging on latest.`);
53775
+ } else {
53776
+ f2.info(`Skill ${import_picocolors27.default.bold(u2.name)} → ${import_picocolors27.default.bold(u2.latest)} (registry latest${u2.current ? `, agent has ${u2.current}` : ""}).`);
53777
+ }
53778
+ }
53676
53779
  const resultRows = [];
53677
53780
  if (meta.localChanged) {
53678
53781
  resultRows.push({
@@ -53727,7 +53830,7 @@ async function runAgentPush(cwd2, args) {
53727
53830
  return handleApiError3(err);
53728
53831
  }
53729
53832
  }
53730
- const outgoing = await buildOutgoingComponents(cwd2, manifest, cloud);
53833
+ const outgoing = await buildOutgoingComponents(cwd2, manifest, cloud, resolvedVersions);
53731
53834
  if (outgoing === null)
53732
53835
  return;
53733
53836
  const pushSpinner = de();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainbase-labs/cli",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
5
5
  "type": "module",
6
6
  "bin": {