promptgraph-mcp 1.5.19 → 1.5.20
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/marketplace.js +15 -5
- package/package.json +1 -1
package/marketplace.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import os from 'os';
|
|
4
4
|
import https from 'https';
|
|
5
|
+
import { createHash } from 'crypto';
|
|
5
6
|
import { spawnSync } from 'child_process';
|
|
6
7
|
import { getDb } from './db.js';
|
|
7
8
|
import { validateSkill } from './validator.js';
|
|
@@ -9,6 +10,12 @@ import { validateSkill } from './validator.js';
|
|
|
9
10
|
const REGISTRY_URL = 'https://raw.githubusercontent.com/NeiP4n/promptgraph-registry/main/registry.json';
|
|
10
11
|
const SKILLS_DIR = path.join(os.homedir(), '.claude', 'skills-store', 'marketplace');
|
|
11
12
|
|
|
13
|
+
// Deterministic short code from an id. Same id always yields the same code,
|
|
14
|
+
// so codes auto-generate — no need to assign them by hand.
|
|
15
|
+
export function codeFor(id) {
|
|
16
|
+
return 'pg-' + createHash('md5').update(String(id)).digest('hex').slice(0, 6);
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
// Robust fetch: try undici fetch, fall back to node:https (works where undici fails on Windows)
|
|
13
20
|
function httpGet(url) {
|
|
14
21
|
return new Promise((resolve, reject) => {
|
|
@@ -44,6 +51,7 @@ export async function browseMarketplace(topK = 20) {
|
|
|
44
51
|
const registry = JSON.parse(text);
|
|
45
52
|
if (!Array.isArray(registry.skills)) return { error: 'Invalid registry format' };
|
|
46
53
|
return registry.skills
|
|
54
|
+
.map(s => ({ ...s, code: s.code || codeFor(s.id) })) // auto-fill code
|
|
47
55
|
.sort((a, b) => (b.stars || 0) - (a.stars || 0))
|
|
48
56
|
.slice(0, topK);
|
|
49
57
|
} catch (e) {
|
|
@@ -56,15 +64,16 @@ export async function installSkill(query) {
|
|
|
56
64
|
const text = await fetchText(REGISTRY_URL);
|
|
57
65
|
const registry = JSON.parse(text);
|
|
58
66
|
const q = String(query).trim().toLowerCase();
|
|
59
|
-
// match by code, id, or name
|
|
67
|
+
// match by code (stored OR auto-generated), id, or name
|
|
60
68
|
const skill = registry.skills?.find(s =>
|
|
61
|
-
s.code
|
|
69
|
+
(s.code || codeFor(s.id)).toLowerCase() === q ||
|
|
62
70
|
s.id?.toLowerCase() === q ||
|
|
63
71
|
s.name?.toLowerCase() === q
|
|
64
72
|
);
|
|
65
73
|
if (!skill) {
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
const bundle = (registry.bundles || []).find(b =>
|
|
75
|
+
(b.code || codeFor(b.id)).toLowerCase() === q || b.id?.toLowerCase() === q
|
|
76
|
+
);
|
|
68
77
|
if (bundle) return { error: `"${query}" is a bundle. Use pg_bundle_install("${bundle.id}") instead.` };
|
|
69
78
|
return { error: `No skill matching "${query}" (try a code like pg-xxxxxx, an id, or a name)` };
|
|
70
79
|
}
|
|
@@ -89,6 +98,7 @@ export async function browseBundles(topK = 20) {
|
|
|
89
98
|
const registry = JSON.parse(text);
|
|
90
99
|
const bundles = registry.bundles || [];
|
|
91
100
|
return bundles
|
|
101
|
+
.map(b => ({ ...b, code: b.code || codeFor(b.id) }))
|
|
92
102
|
.sort((a, b) => (b.stars || 0) - (a.stars || 0))
|
|
93
103
|
.slice(0, topK);
|
|
94
104
|
} catch (e) {
|
|
@@ -102,7 +112,7 @@ export async function installBundle(bundleId) {
|
|
|
102
112
|
const registry = JSON.parse(text);
|
|
103
113
|
const q = String(bundleId).trim().toLowerCase();
|
|
104
114
|
const bundle = (registry.bundles || []).find(b =>
|
|
105
|
-
b.code
|
|
115
|
+
(b.code || codeFor(b.id)).toLowerCase() === q || b.id?.toLowerCase() === q || b.name?.toLowerCase() === q
|
|
106
116
|
);
|
|
107
117
|
if (!bundle) return { error: `No bundle matching "${bundleId}"` };
|
|
108
118
|
|