promptgraph-mcp 1.5.21 → 1.5.22
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/README.md +1 -1
- package/github-import.js +5 -6
- package/indexer.js +10 -0
- package/marketplace.js +16 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ When you ask Claude a question, it calls `pg_search("your task")` → finds the
|
|
|
24
24
|
## Features
|
|
25
25
|
|
|
26
26
|
- **Vector search** via `fastembed` (`BGE-Small-EN`, 23MB, runs locally, no API needed)
|
|
27
|
-
- **Semantic matching** —
|
|
27
|
+
- **Semantic matching** — synonyms and paraphrases work; queries should be in English (model is English-only)
|
|
28
28
|
- **Auto-reindex** via file watcher when skills change
|
|
29
29
|
- **Graph edges** — tracks which skills call other skills
|
|
30
30
|
- **MCP server** — integrates directly into Claude Code and Claude Desktop
|
package/github-import.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawnSync } from 'child_process';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import os from 'os';
|
|
4
4
|
import fs from 'fs';
|
|
@@ -22,13 +22,12 @@ export async function importFromGitHub(repoUrl) {
|
|
|
22
22
|
|
|
23
23
|
if (fs.existsSync(dest)) {
|
|
24
24
|
console.log(`Updating ${repoName}...`);
|
|
25
|
-
|
|
25
|
+
const pullResult = spawnSync('git', ['-C', dest, 'pull', '--depth=1'], { stdio: 'inherit' });
|
|
26
|
+
if (pullResult.status !== 0) throw new Error(`git pull failed for ${repoName}`);
|
|
26
27
|
} else {
|
|
27
28
|
console.log(`Cloning ${url}...`);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const result = spawnSync('git', ['clone', '--depth=1', url, dest], { stdio: 'inherit' });
|
|
31
|
-
if (result.status !== 0) throw new Error(`git clone failed for ${url}`);
|
|
29
|
+
const cloneResult = spawnSync('git', ['clone', '--depth=1', url, dest], { stdio: 'inherit' });
|
|
30
|
+
if (cloneResult.status !== 0) throw new Error(`git clone failed for ${url}`);
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
const mdFiles = globSync(`${dest}/**/*.md`);
|
package/indexer.js
CHANGED
|
@@ -149,6 +149,16 @@ export async function indexAll() {
|
|
|
149
149
|
}
|
|
150
150
|
} catch {
|
|
151
151
|
errors++;
|
|
152
|
+
// Remove stale record if the file was previously indexed but now fails to parse
|
|
153
|
+
try {
|
|
154
|
+
const stale = db.prepare('SELECT id FROM skills WHERE path = ?').get(file);
|
|
155
|
+
if (stale) {
|
|
156
|
+
db.prepare('DELETE FROM skills WHERE id = ?').run(stale.id);
|
|
157
|
+
db.prepare('DELETE FROM chunks WHERE skill_id = ?').run(stale.id);
|
|
158
|
+
db.prepare('DELETE FROM edges WHERE from_skill = ? OR to_skill = ?').run(stale.id, stale.id);
|
|
159
|
+
db.prepare('DELETE FROM ratings WHERE skill_id = ?').run(stale.id);
|
|
160
|
+
}
|
|
161
|
+
} catch {}
|
|
152
162
|
}
|
|
153
163
|
}
|
|
154
164
|
|
package/marketplace.js
CHANGED
|
@@ -115,7 +115,16 @@ export async function installSkill(query) {
|
|
|
115
115
|
const dest = path.join(SKILLS_DIR, `${skillId}.md`);
|
|
116
116
|
|
|
117
117
|
const content = await fetchText(skill.raw_url);
|
|
118
|
-
|
|
118
|
+
|
|
119
|
+
// Validate before writing — reject malicious or junk downloads
|
|
120
|
+
const tmpPath = dest + '.tmp';
|
|
121
|
+
fs.writeFileSync(tmpPath, content);
|
|
122
|
+
const validation = validateSkill(tmpPath);
|
|
123
|
+
if (!validation.ok) {
|
|
124
|
+
fs.unlinkSync(tmpPath);
|
|
125
|
+
return { error: 'Downloaded skill failed validation', issues: validation.errors };
|
|
126
|
+
}
|
|
127
|
+
fs.renameSync(tmpPath, dest);
|
|
119
128
|
|
|
120
129
|
return { success: true, path: dest, name: skill.name };
|
|
121
130
|
} catch (e) {
|
|
@@ -156,7 +165,12 @@ export async function installBundle(bundleId) {
|
|
|
156
165
|
if (!skill?.raw_url) { failed.push(skillId); continue; }
|
|
157
166
|
try {
|
|
158
167
|
const content = await fetchText(skill.raw_url);
|
|
159
|
-
|
|
168
|
+
const dest = path.join(SKILLS_DIR, `${skillId}.md`);
|
|
169
|
+
const tmpPath = dest + '.tmp';
|
|
170
|
+
fs.writeFileSync(tmpPath, content);
|
|
171
|
+
const validation = validateSkill(tmpPath);
|
|
172
|
+
if (!validation.ok) { fs.unlinkSync(tmpPath); failed.push(skillId); continue; }
|
|
173
|
+
fs.renameSync(tmpPath, dest);
|
|
160
174
|
installed.push(skillId);
|
|
161
175
|
} catch {
|
|
162
176
|
failed.push(skillId);
|