@nexusbloom/cli 0.1.5 → 0.1.7

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/package.json +1 -1
  2. package/src/index.js +129 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexusbloom/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "NexusBloom CLI — run tools and workflows from your terminal",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -165,6 +165,20 @@ program
165
165
  .action(async (slug, args, opts, cmd) => {
166
166
  const jsonMode = cmd.parent.opts().json;
167
167
 
168
+ // ── Resolve abbreviation ────────────────────────────────────────────
169
+ try {
170
+ const res = await fetch(`${API_BASE}/api/tools`);
171
+ const { tools } = await res.json();
172
+ const slugs = (tools || []).map((t) => t.slug);
173
+ const abbrMap = generateAbbreviations(slugs);
174
+ if (abbrMap[slug] && slugs.includes(abbrMap[slug])) {
175
+ if (!jsonMode) console.log(chalk.dim(` Resolved: ${slug} → ${abbrMap[slug]}`));
176
+ slug = abbrMap[slug];
177
+ }
178
+ } catch {
179
+ // Silently ignore abbreviation resolution failures
180
+ }
181
+
168
182
  // ── Build input body ────────────────────────────────────────────────
169
183
  let body = {};
170
184
 
@@ -599,6 +613,121 @@ cacheCmd
599
613
 
600
614
  program.parse(process.argv);
601
615
 
616
+ // ─── Abbreviation generator ──────────────────────────────────────────────────
617
+
618
+ function generateAbbreviations(slugs) {
619
+ const abbrMap = {};
620
+ const used = new Set();
621
+
622
+ for (const slug of slugs) {
623
+ // Try first letter of each word
624
+ const parts = slug.split("-");
625
+ let abbr = parts.map((p) => p[0]).join("").toLowerCase();
626
+
627
+ // If taken, try longer combinations
628
+ if (used.has(abbr) || abbr.length < 2) {
629
+ for (let len = 2; len <= slug.length; len++) {
630
+ abbr = slug.slice(0, len);
631
+ if (!used.has(abbr)) break;
632
+ }
633
+ }
634
+
635
+ used.add(abbr);
636
+ abbrMap[slug] = abbr;
637
+ abbrMap[abbr] = slug;
638
+ }
639
+
640
+ return abbrMap;
641
+ }
642
+
643
+ // ─── `nxb abbr` — show tool abbreviations ────────────────────────────────────
644
+
645
+ program
646
+ .command("abbr")
647
+ .description("Show tool abbreviations")
648
+ .action(async () => {
649
+ try {
650
+ const res = await fetch(`${API_BASE}/api/tools`);
651
+ const { tools } = await res.json();
652
+ const slugs = (tools || []).map((t) => t.slug);
653
+ const abbrMap = generateAbbreviations(slugs);
654
+
655
+ console.log(chalk.bold("\n Tool Abbreviations:\n"));
656
+ slugs.forEach((slug) => {
657
+ console.log(` ${chalk.cyan(abbrMap[slug].padEnd(15))} → ${chalk.dim(slug)}`);
658
+ });
659
+ console.log();
660
+ } catch (err) {
661
+ console.error(chalk.red("Failed to fetch tools:"), err.message);
662
+ }
663
+ });
664
+
665
+ // ─── `nxb json` — create JSON input for tools ───────────────────────────────
666
+
667
+ program
668
+ .command("json")
669
+ .description("Create JSON input for tools (pipe into nxb run)")
670
+ .option("-t, --template <slug>", "Generate JSON template for a specific tool")
671
+ .option("-i, --interactive", "Interactive mode - prompts for each field")
672
+ .action(async (opts, cmd) => {
673
+ const jsonMode = cmd.parent.opts().json;
674
+
675
+ if (opts.template) {
676
+ // Fetch tool schema
677
+ const res = await fetch(`${API_BASE}/api/run/${opts.template}`);
678
+ if (!res.ok) {
679
+ console.error(chalk.red(`Tool "${opts.template}" not found`));
680
+ process.exit(1);
681
+ }
682
+ const data = await res.json();
683
+ const manifest = data.data?.manifest || data.manifest || data;
684
+ const schema = manifest.input_schema || {};
685
+
686
+ if (opts.interactive) {
687
+ // Interactive mode
688
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
689
+ const ask = (q) => new Promise((r) => rl.question(q, r));
690
+ const result = {};
691
+
692
+ if (schema.properties) {
693
+ for (const [key, prop] of Object.entries(schema.properties)) {
694
+ const required = schema.required?.includes(key);
695
+ const hint = prop.description ? ` (${prop.description})` : "";
696
+ const def = prop.default ? ` [${prop.default}]` : "";
697
+ const answer = await ask(chalk.cyan(` ${key}${hint}${def}: `));
698
+ const val = answer || prop.default;
699
+ if (val) result[key] = prop.type === "number" ? Number(val) : val;
700
+ }
701
+ }
702
+ rl.close();
703
+ if (jsonMode) return console.log(JSON.stringify(result, null, 2));
704
+ console.log(JSON.stringify(result));
705
+ } else {
706
+ // Generate template with defaults
707
+ const template = {};
708
+ if (schema.properties) {
709
+ for (const [key, prop] of Object.entries(schema.properties)) {
710
+ if (prop.default !== undefined) {
711
+ template[key] = prop.default;
712
+ } else if (prop.type === "string") {
713
+ template[key] = prop.enum ? prop.enum[0] : "";
714
+ } else if (prop.type === "number" || prop.type === "integer") {
715
+ template[key] = 0;
716
+ } else if (prop.type === "boolean") {
717
+ template[key] = false;
718
+ }
719
+ }
720
+ }
721
+ if (jsonMode) return console.log(JSON.stringify(template, null, 2));
722
+ console.log(JSON.stringify(template, null, 2));
723
+ }
724
+ } else {
725
+ console.log(chalk.yellow("Usage: nxb json --template <slug> [--interactive]"));
726
+ console.log(chalk.dim(" Generate JSON input for a tool that can be piped into nxb run"));
727
+ console.log(chalk.dim(" Example: nxb json --template summarize | nxb run summarize --input @-"));
728
+ }
729
+ });
730
+
602
731
  // ─── Helpers ─────────────────────────────────────────────────────────────────
603
732
 
604
733
  function readStdin() {