promptgraph-mcp 2.6.6 → 2.6.8

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.
@@ -31,8 +31,11 @@ export default async function handler(args, bin) {
31
31
  const { spinner: spin2 } = await import('../cli.js');
32
32
  const sp = spin2('Fetching marketplace...');
33
33
  sp.start();
34
- const [skills, bundles] = await Promise.all([browseMarketplace(1000), browseBundles(1000)]);
35
- sp.stop();
34
+ try {
35
+ var [skills, bundles] = await Promise.all([browseMarketplace(1000), browseBundles(1000)]);
36
+ } finally {
37
+ sp.stop();
38
+ }
36
39
 
37
40
  if (skills?.error) { error(skills.error); process.exit(1); }
38
41
 
@@ -88,6 +91,10 @@ export default async function handler(args, bin) {
88
91
  const r = await installBundle(item.id);
89
92
  if (r?.error) throw new Error(r.error);
90
93
  installedSet.add(item.id);
94
+ // Update skill count on the bundle object to reflect real survivors
95
+ const { getCachedCount: getCount } = await import('../bundle-counts.js');
96
+ const cached = getCount(item.repo_url);
97
+ if (cached !== null) item.skillCount = cached;
91
98
  } else {
92
99
  const r = await installSkill(item.code || item.id);
93
100
  if (r?.error) throw new Error(r.error);
package/github-import.js CHANGED
@@ -580,7 +580,7 @@ export async function importFromGitHub(repoUrl) {
580
580
 
581
581
  await classifierCleanup(dest);
582
582
 
583
- // Update skill count cache with real survivor count
583
+ // Count survivors after all cleanup
584
584
  const realCount = globSync(`${dest}/**/*.md`).length;
585
585
  const cacheKey = url.replace(/\.git$/, '');
586
586
  const cachePath = path.join(PROMPTGRAPH_DIR, 'skill-counts.json');
@@ -591,6 +591,11 @@ export async function importFromGitHub(repoUrl) {
591
591
  fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2));
592
592
  } catch {}
593
593
 
594
+ if (realCount < 1) {
595
+ fs.rmSync(dest, { recursive: true, force: true });
596
+ throw new Error(`No valid skills in repo — all files were filtered out`);
597
+ }
598
+
594
599
  const { dir: localDir, label: localLabel } = detectSkillsDirLocal(dest);
595
600
  // Prefer the known skillsSubdir (from API detection or sparse patterns) as the
596
601
  // canonical skills directory — it's more accurate than local heuristics for
@@ -609,8 +614,6 @@ export async function importFromGitHub(repoUrl) {
609
614
  console.log(`Full clone: scanning ${label} (${mdFiles.length} .md files)`);
610
615
  }
611
616
 
612
- if (mdFiles.length < 1) console.warn('Warning: no .md files found');
613
-
614
617
  const config = loadConfig();
615
618
  const repoSource = `github:${repoName}`;
616
619
  if (!config.sources.find(s => s.dir === skillsDir)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptgraph-mcp",
3
- "version": "2.6.6",
3
+ "version": "2.6.8",
4
4
  "files": [
5
5
  "*.js",
6
6
  "commands/",
package/tui.js CHANGED
@@ -22,8 +22,10 @@ const green = chalk.green;
22
22
  const red = chalk.red;
23
23
  const blue = chalk.blue;
24
24
  const white = chalk.white;
25
+ const magenta = chalk.magenta;
25
26
 
26
27
  const CAT_ICON = { Engineering:'🛠', 'AI Tools':'🤖', Coding:'💻', Creative:'🎨', Security:'🔒', Community:'🌐' };
28
+ const SPINNER_FRAMES = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷']; // braille spinner
27
29
 
28
30
  // ── helpers ──────────────────────────────────────────────────────────────────
29
31
 
@@ -113,8 +115,11 @@ function render(state, installedSet = new Set()) {
113
115
  : dim(query ? query : 'type / to search, Tab to switch view');
114
116
  write(searchLabel + searchVal + CLEAR_EOL + '\n');
115
117
 
116
- // Row 4: separator (with optional status inline)
117
- if (status) {
118
+ // Row 4: separator (with optional status inline or spinner)
119
+ if (state.installing) {
120
+ const frame = SPINNER_FRAMES[Math.floor(Date.now() / 120) % SPINNER_FRAMES.length];
121
+ write(dim('─'.repeat(4)) + magenta(` ${frame} Installing… `) + CLEAR_EOL + '\n');
122
+ } else if (status) {
118
123
  const msg = status.ok ? green(' ✓ ' + status.msg) : red(' ✗ ' + status.msg);
119
124
  write(dim('─'.repeat(4)) + msg + CLEAR_EOL + '\n');
120
125
  } else {
@@ -388,11 +393,15 @@ export async function runTUI(allSkills, allBundles, installFn, installedSet = ne
388
393
  const sel = state.items[state.cursor];
389
394
  if (!sel || state.installing) return;
390
395
  state.installing = true;
391
- setStatus(null, `Installing ${sel.id}…`);
396
+ // Live spinner — keeps rendering during long installs
397
+ const spinInterval = setInterval(() => render(state, installedSet), 120);
398
+ render(state, installedSet);
392
399
  try {
393
400
  await installFn(sel);
401
+ clearInterval(spinInterval);
394
402
  setStatus(true, `Installed ${sel.id}`);
395
403
  } catch (e) {
404
+ clearInterval(spinInterval);
396
405
  setStatus(false, e.message.slice(0, 60));
397
406
  } finally {
398
407
  state.installing = false;