promptgraph-mcp 2.6.7 → 2.6.9

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.
@@ -91,6 +91,10 @@ export default async function handler(args, bin) {
91
91
  const r = await installBundle(item.id);
92
92
  if (r?.error) throw new Error(r.error);
93
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;
94
98
  } else {
95
99
  const r = await installSkill(item.code || item.id);
96
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/marketplace.js CHANGED
@@ -13,6 +13,7 @@ import { isSkillFile } from './parser.js';
13
13
 
14
14
  const REGISTRY_URL = 'https://raw.githubusercontent.com/NeiP4n/promptgraph-registry/main/registry.json';
15
15
  const SKILL_COUNT_CACHE = path.join(PROMPTGRAPH_DIR, 'skill-counts.json');
16
+ const DEAD_REPOS_FILE = path.join(PROMPTGRAPH_DIR, 'dead-repos.json');
16
17
  const SKILLS_DIR = path.join(SKILLS_STORE_DIR, 'marketplace');
17
18
 
18
19
  // Atomically write content to dest via tmp — cleans up on failure
@@ -143,6 +144,21 @@ function writeSkillCountCache(data) {
143
144
  } catch {}
144
145
  }
145
146
 
147
+ function readDeadRepos() {
148
+ try { return JSON.parse(fs.readFileSync(DEAD_REPOS_FILE, 'utf8')); } catch { return []; }
149
+ }
150
+
151
+ function markDeadRepo(repoUrl) {
152
+ try {
153
+ const dead = readDeadRepos();
154
+ if (!dead.includes(repoUrl)) {
155
+ dead.push(repoUrl);
156
+ fs.mkdirSync(path.dirname(DEAD_REPOS_FILE), { recursive: true });
157
+ fs.writeFileSync(DEAD_REPOS_FILE, JSON.stringify(dead, null, 2));
158
+ }
159
+ } catch {}
160
+ }
161
+
146
162
  async function fetchText(url) {
147
163
  const cacheFile = path.join(PROMPTGRAPH_DIR, 'registry-cache.json');
148
164
  const isRegistry = url === REGISTRY_URL;
@@ -275,7 +291,10 @@ export async function browseBundles(topK = 20) {
275
291
  try {
276
292
  const text = await fetchText(REGISTRY_URL);
277
293
  const registry = JSON.parse(text);
278
- const bundles = (registry.bundles || []).filter(b => validateRegistryEntry(b).ok);
294
+ const deadRepos = new Set(readDeadRepos());
295
+ const bundles = (registry.bundles || []).filter(b =>
296
+ validateRegistryEntry(b).ok && !deadRepos.has(b.repo_url)
297
+ );
279
298
  const cache = readSkillCountCache();
280
299
  const now = Date.now();
281
300
  let changed = false;
@@ -346,7 +365,14 @@ export async function installBundle(bundleId) {
346
365
  if (!bundle) return { error: `No bundle matching "${bundleId}"` };
347
366
 
348
367
  if (bundle.repo_url) {
349
- await importFromGitHub(bundle.repo_url);
368
+ try {
369
+ await importFromGitHub(bundle.repo_url);
370
+ } catch (e) {
371
+ if (e.message && e.message.includes('No valid skills')) {
372
+ markDeadRepo(bundle.repo_url);
373
+ }
374
+ throw e;
375
+ }
350
376
  return { success: true, bundle: bundle.name, type: 'repo_import', repo_url: bundle.repo_url };
351
377
  }
352
378
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptgraph-mcp",
3
- "version": "2.6.7",
3
+ "version": "2.6.9",
4
4
  "files": [
5
5
  "*.js",
6
6
  "commands/",