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.
- package/commands/marketplace.js +4 -0
- package/github-import.js +6 -3
- package/marketplace.js +28 -2
- package/package.json +1 -1
package/commands/marketplace.js
CHANGED
|
@@ -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
|
-
//
|
|
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
|
|
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
|
-
|
|
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
|
|