@brainbase-labs/cli 0.10.0 → 0.11.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 +130 -11
- 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.
|
|
29452
|
+
version: "0.11.0",
|
|
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
|
|
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";
|
|
@@ -52787,6 +52792,14 @@ function diffSecrets(local, cloud) {
|
|
|
52787
52792
|
};
|
|
52788
52793
|
}
|
|
52789
52794
|
|
|
52795
|
+
// src/core/entrypoint-gate.ts
|
|
52796
|
+
function entrypointExecutionAllowed(opts) {
|
|
52797
|
+
if (opts.flag)
|
|
52798
|
+
return true;
|
|
52799
|
+
const v3 = (opts.env.BRAINBASE_RUN_ENTRYPOINT ?? "").trim().toLowerCase();
|
|
52800
|
+
return v3 === "1" || v3 === "true";
|
|
52801
|
+
}
|
|
52802
|
+
|
|
52790
52803
|
// src/cli/agent-pull.ts
|
|
52791
52804
|
async function runAgentPull(cwd2, args) {
|
|
52792
52805
|
banner("agent pull — bring cloud changes into this folder");
|
|
@@ -53002,7 +53015,7 @@ async function runAgentPull(cwd2, args) {
|
|
|
53002
53015
|
};
|
|
53003
53016
|
writeSyncState(cwd2, newState);
|
|
53004
53017
|
await pullSecrets(cwd2, agentId);
|
|
53005
|
-
await runEntrypointIfPresent(cwd2, yaml);
|
|
53018
|
+
await runEntrypointIfPresent(cwd2, yaml, entrypointExecutionAllowed({ flag: args.runEntrypoint, env: process.env }));
|
|
53006
53019
|
$e(`Pulled ${cloudAgent.name} at revision ${cloud.revision}.`);
|
|
53007
53020
|
} finally {
|
|
53008
53021
|
try {
|
|
@@ -53321,7 +53334,7 @@ function buildLinkFromAgent(agent, harness, prev) {
|
|
|
53321
53334
|
tracking: prev?.tracking
|
|
53322
53335
|
};
|
|
53323
53336
|
}
|
|
53324
|
-
async function runEntrypointIfPresent(cwd2, manifest) {
|
|
53337
|
+
async function runEntrypointIfPresent(cwd2, manifest, execute) {
|
|
53325
53338
|
if (!manifest.entrypoint)
|
|
53326
53339
|
return;
|
|
53327
53340
|
const body = resolveEntrypoint(cwd2, manifest);
|
|
@@ -53335,6 +53348,10 @@ async function runEntrypointIfPresent(cwd2, manifest) {
|
|
|
53335
53348
|
try {
|
|
53336
53349
|
fs45.chmodSync(scriptPath, 493);
|
|
53337
53350
|
} catch {}
|
|
53351
|
+
if (!execute) {
|
|
53352
|
+
f2.info(`Agent has an entrypoint — written to ${import_picocolors25.default.dim(path48.relative(cwd2, scriptPath))}, not executed. ` + `Run it with ${import_picocolors25.default.cyan("brainbase run bash .brainbase/entrypoint.sh")} or re-pull with ${import_picocolors25.default.cyan("--run-entrypoint")}. Sandboxes run it automatically.`);
|
|
53353
|
+
return;
|
|
53354
|
+
}
|
|
53338
53355
|
f2.info(`Running entrypoint ${import_picocolors25.default.dim(`(${path48.relative(cwd2, scriptPath)})`)}`);
|
|
53339
53356
|
const secrets = readLocalSecrets(cwd2);
|
|
53340
53357
|
const env3 = { ...process.env, ...secrets };
|
|
@@ -53413,7 +53430,7 @@ var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
|
53413
53430
|
|
|
53414
53431
|
// src/core/agent-outgoing.ts
|
|
53415
53432
|
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
53416
|
-
async function buildOutgoingComponents(cwd2, manifest, cloud) {
|
|
53433
|
+
async function buildOutgoingComponents(cwd2, manifest, cloud, resolvedVersions) {
|
|
53417
53434
|
const out = [];
|
|
53418
53435
|
if (manifest.instructions) {
|
|
53419
53436
|
if (manifest.instructions.text !== undefined && manifest.instructions.file !== undefined) {
|
|
@@ -53460,6 +53477,7 @@ async function buildOutgoingComponents(cwd2, manifest, cloud) {
|
|
|
53460
53477
|
}
|
|
53461
53478
|
const slug = registrySkillComponentSlug(parsed);
|
|
53462
53479
|
const cloudMatch = cloud?.components.find((c2) => c2.type === "skill" && c2.slug === slug);
|
|
53480
|
+
const version = parsed.version ?? resolvedVersions?.get(slug);
|
|
53463
53481
|
out.push({
|
|
53464
53482
|
type: "skill",
|
|
53465
53483
|
slug,
|
|
@@ -53467,7 +53485,7 @@ async function buildOutgoingComponents(cwd2, manifest, cloud) {
|
|
|
53467
53485
|
files: [],
|
|
53468
53486
|
meta: {
|
|
53469
53487
|
name: parsed.creator ? `${parsed.creator}/${parsed.slug}` : parsed.slug,
|
|
53470
|
-
...
|
|
53488
|
+
...version ? { version } : {}
|
|
53471
53489
|
}
|
|
53472
53490
|
});
|
|
53473
53491
|
}
|
|
@@ -53552,6 +53570,62 @@ function yamlScalar(s3) {
|
|
|
53552
53570
|
return JSON.stringify(s3);
|
|
53553
53571
|
}
|
|
53554
53572
|
|
|
53573
|
+
// src/core/registry-skill-updates.ts
|
|
53574
|
+
function parseSemver2(v3) {
|
|
53575
|
+
const m3 = /^(\d+)\.(\d+)\.(\d+)$/.exec(v3);
|
|
53576
|
+
if (!m3)
|
|
53577
|
+
return null;
|
|
53578
|
+
return [Number(m3[1]), Number(m3[2]), Number(m3[3])];
|
|
53579
|
+
}
|
|
53580
|
+
function compareDirection(current, latest) {
|
|
53581
|
+
if (!current)
|
|
53582
|
+
return "unknown";
|
|
53583
|
+
const a3 = parseSemver2(current);
|
|
53584
|
+
const b4 = parseSemver2(latest);
|
|
53585
|
+
if (!a3 || !b4)
|
|
53586
|
+
return "unknown";
|
|
53587
|
+
for (let i = 0;i < 3; i++) {
|
|
53588
|
+
if (b4[i] > a3[i])
|
|
53589
|
+
return "upgrade";
|
|
53590
|
+
if (b4[i] < a3[i])
|
|
53591
|
+
return "downgrade";
|
|
53592
|
+
}
|
|
53593
|
+
return "unknown";
|
|
53594
|
+
}
|
|
53595
|
+
function planRegistrySkillUpdates(skills, cloudComponents, latestByName) {
|
|
53596
|
+
const out = [];
|
|
53597
|
+
for (const entry of skills) {
|
|
53598
|
+
let parsed;
|
|
53599
|
+
try {
|
|
53600
|
+
parsed = parseSkillSource2(entry.source);
|
|
53601
|
+
} catch {
|
|
53602
|
+
continue;
|
|
53603
|
+
}
|
|
53604
|
+
if (parsed.kind !== "registry" || parsed.version || !parsed.creator) {
|
|
53605
|
+
continue;
|
|
53606
|
+
}
|
|
53607
|
+
const name = `${parsed.creator}/${parsed.slug}`;
|
|
53608
|
+
const latest = latestByName.get(name);
|
|
53609
|
+
if (!latest)
|
|
53610
|
+
continue;
|
|
53611
|
+
const componentSlug = registrySkillComponentSlug(parsed);
|
|
53612
|
+
const cloud = cloudComponents.find((c2) => c2.type === "skill" && c2.slug === componentSlug);
|
|
53613
|
+
if (!cloud)
|
|
53614
|
+
continue;
|
|
53615
|
+
const current = cloud.meta?.["version"];
|
|
53616
|
+
if (current === latest)
|
|
53617
|
+
continue;
|
|
53618
|
+
out.push({
|
|
53619
|
+
componentSlug,
|
|
53620
|
+
name,
|
|
53621
|
+
current,
|
|
53622
|
+
latest,
|
|
53623
|
+
direction: compareDirection(current, latest)
|
|
53624
|
+
});
|
|
53625
|
+
}
|
|
53626
|
+
return out;
|
|
53627
|
+
}
|
|
53628
|
+
|
|
53555
53629
|
// src/cli/agent-push.ts
|
|
53556
53630
|
async function runAgentPush(cwd2, args) {
|
|
53557
53631
|
banner("agent push — send your local changes to the cloud");
|
|
@@ -53590,6 +53664,37 @@ async function runAgentPush(cwd2, args) {
|
|
|
53590
53664
|
lock: lock?.components ?? [],
|
|
53591
53665
|
cloud: cloud.components
|
|
53592
53666
|
});
|
|
53667
|
+
const unpinned = new Map;
|
|
53668
|
+
for (const entry of manifest.skills) {
|
|
53669
|
+
try {
|
|
53670
|
+
const parsed = parseSkillSource2(entry.source);
|
|
53671
|
+
if (parsed.kind === "registry" && !parsed.version && parsed.creator) {
|
|
53672
|
+
unpinned.set(`${parsed.creator}/${parsed.slug}`, {
|
|
53673
|
+
creator: parsed.creator,
|
|
53674
|
+
slug: parsed.slug
|
|
53675
|
+
});
|
|
53676
|
+
}
|
|
53677
|
+
} catch {}
|
|
53678
|
+
}
|
|
53679
|
+
const latestByName = new Map;
|
|
53680
|
+
if (unpinned.size > 0) {
|
|
53681
|
+
await Promise.all([...unpinned.entries()].map(async ([name, ref]) => {
|
|
53682
|
+
try {
|
|
53683
|
+
const pkg = await skillsApi.getPackage(ref.creator, ref.slug);
|
|
53684
|
+
if (pkg.latest_version?.version) {
|
|
53685
|
+
latestByName.set(name, pkg.latest_version.version);
|
|
53686
|
+
}
|
|
53687
|
+
} catch {}
|
|
53688
|
+
}));
|
|
53689
|
+
}
|
|
53690
|
+
const skillUpdates = planRegistrySkillUpdates(manifest.skills, cloud.components, latestByName);
|
|
53691
|
+
const resolvedVersions = new Map(skillUpdates.map((u2) => [u2.componentSlug, u2.latest]));
|
|
53692
|
+
for (const u2 of skillUpdates) {
|
|
53693
|
+
const row = rows.find((r2) => r2.key === compKey("skill", u2.componentSlug));
|
|
53694
|
+
if (row && (row.status === "in-sync" || row.status === "modified-cloud" || row.status === "added-local")) {
|
|
53695
|
+
row.status = "modified-local";
|
|
53696
|
+
}
|
|
53697
|
+
}
|
|
53593
53698
|
let cloudMeta = lock?.agentMeta;
|
|
53594
53699
|
if (!cloudMeta) {
|
|
53595
53700
|
try {
|
|
@@ -53673,6 +53778,16 @@ async function runAgentPush(cwd2, args) {
|
|
|
53673
53778
|
}
|
|
53674
53779
|
f2.info(`If you push now, your push targets revision ${cloud.revision} and may race. Consider \`brainbase agent pull\` first.`);
|
|
53675
53780
|
}
|
|
53781
|
+
const sendKeys = new Set(toSend.map((r2) => r2.key));
|
|
53782
|
+
for (const u2 of skillUpdates) {
|
|
53783
|
+
if (!sendKeys.has(compKey("skill", u2.componentSlug)))
|
|
53784
|
+
continue;
|
|
53785
|
+
if (u2.direction === "downgrade") {
|
|
53786
|
+
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.`);
|
|
53787
|
+
} else {
|
|
53788
|
+
f2.info(`Skill ${import_picocolors27.default.bold(u2.name)} → ${import_picocolors27.default.bold(u2.latest)} (registry latest${u2.current ? `, agent has ${u2.current}` : ""}).`);
|
|
53789
|
+
}
|
|
53790
|
+
}
|
|
53676
53791
|
const resultRows = [];
|
|
53677
53792
|
if (meta.localChanged) {
|
|
53678
53793
|
resultRows.push({
|
|
@@ -53727,7 +53842,7 @@ async function runAgentPush(cwd2, args) {
|
|
|
53727
53842
|
return handleApiError3(err);
|
|
53728
53843
|
}
|
|
53729
53844
|
}
|
|
53730
|
-
const outgoing = await buildOutgoingComponents(cwd2, manifest, cloud);
|
|
53845
|
+
const outgoing = await buildOutgoingComponents(cwd2, manifest, cloud, resolvedVersions);
|
|
53731
53846
|
if (outgoing === null)
|
|
53732
53847
|
return;
|
|
53733
53848
|
const pushSpinner = de();
|
|
@@ -54708,7 +54823,8 @@ async function runAgent(cwd2, sub, args, opts) {
|
|
|
54708
54823
|
yes: opts.yes,
|
|
54709
54824
|
scope: opts.scope,
|
|
54710
54825
|
agentIdArg: args[0],
|
|
54711
|
-
force: opts.force
|
|
54826
|
+
force: opts.force,
|
|
54827
|
+
runEntrypoint: opts.runEntrypoint
|
|
54712
54828
|
});
|
|
54713
54829
|
return;
|
|
54714
54830
|
case "push":
|
|
@@ -54746,7 +54862,7 @@ function printHelp() {
|
|
|
54746
54862
|
out.push(` ${import_picocolors32.default.bold("brainbase agent")} ${import_picocolors32.default.dim("<sub> [options]")}`);
|
|
54747
54863
|
out.push("");
|
|
54748
54864
|
out.push(` ${import_picocolors32.default.cyan("create")} ${import_picocolors32.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
54749
|
-
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)")}`);
|
|
54865
|
+
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); --run-entrypoint to also execute the agent entrypoint")}`);
|
|
54750
54866
|
out.push(` ${import_picocolors32.default.cyan("push")} ${import_picocolors32.default.dim("send local changes to the cloud")}`);
|
|
54751
54867
|
out.push(` ${import_picocolors32.default.cyan("unpack")} ${import_picocolors32.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
|
|
54752
54868
|
out.push(` ${import_picocolors32.default.cyan("status")} ${import_picocolors32.default.dim("show what would push and what would pull")}`);
|
|
@@ -56679,7 +56795,7 @@ function help() {
|
|
|
56679
56795
|
out.push(divider("LINKED AGENT"));
|
|
56680
56796
|
out.push("");
|
|
56681
56797
|
out.push(` ${import_picocolors41.default.cyan("agent create")} ${import_picocolors41.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
56682
|
-
out.push(` ${import_picocolors41.default.cyan("agent pull")} ${import_picocolors41.default.dim("[<id>]")} ${import_picocolors41.default.dim("bring cloud changes into this folder (--force to override)")}`);
|
|
56798
|
+
out.push(` ${import_picocolors41.default.cyan("agent pull")} ${import_picocolors41.default.dim("[<id>]")} ${import_picocolors41.default.dim("bring cloud changes into this folder (--force to override; --run-entrypoint to also execute the agent entrypoint)")}`);
|
|
56683
56799
|
out.push(` ${import_picocolors41.default.cyan("agent push")} ${import_picocolors41.default.dim("send local changes to the cloud")}`);
|
|
56684
56800
|
out.push(` ${import_picocolors41.default.cyan("agent unpack")} ${import_picocolors41.default.dim("install the claimed agent into a harness layout")}`);
|
|
56685
56801
|
out.push(` ${import_picocolors41.default.cyan("link")} ${import_picocolors41.default.dim("attach this folder to an existing agent")}`);
|
|
@@ -56743,6 +56859,7 @@ function help() {
|
|
|
56743
56859
|
out.push(` ${import_picocolors41.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT (overrides token.json)`);
|
|
56744
56860
|
out.push(` ${import_picocolors41.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
|
|
56745
56861
|
out.push(` ${import_picocolors41.default.dim("BRAINBASE_NON_INTERACTIVE")} force non-interactive mode — skip/auto-default prompts (CI & agents)`);
|
|
56862
|
+
out.push(` ${import_picocolors41.default.dim("BRAINBASE_RUN_ENTRYPOINT")} =1 → agent pull executes the agent entrypoint (sandbox boots; or pass --run-entrypoint)`);
|
|
56746
56863
|
out.push("");
|
|
56747
56864
|
out.push(divider("HARNESSES"));
|
|
56748
56865
|
out.push("");
|
|
@@ -56847,6 +56964,7 @@ async function main() {
|
|
|
56847
56964
|
const noTracking = hasFlag2(argv, "--no-tracking");
|
|
56848
56965
|
const track = hasFlag2(argv, "--track");
|
|
56849
56966
|
const forceFlag = hasFlag2(argv, "--force");
|
|
56967
|
+
const runEntrypointFlag = hasFlag2(argv, "--run-entrypoint");
|
|
56850
56968
|
const graphOnlyFlag = hasFlag2(argv, "--graph-only");
|
|
56851
56969
|
const nameFlag = getFlag(argv, "--name");
|
|
56852
56970
|
const skillVersionFlag = getFlag(argv, "--skill-version");
|
|
@@ -56938,7 +57056,8 @@ async function main() {
|
|
|
56938
57056
|
teamId: teamIdFlag,
|
|
56939
57057
|
noTracking,
|
|
56940
57058
|
track,
|
|
56941
|
-
force: forceFlag
|
|
57059
|
+
force: forceFlag,
|
|
57060
|
+
runEntrypoint: runEntrypointFlag
|
|
56942
57061
|
});
|
|
56943
57062
|
break;
|
|
56944
57063
|
}
|