promptgraph-mcp 2.9.56 → 2.9.57

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/api.js CHANGED
@@ -44,7 +44,7 @@ export async function index(sourceDir, sourceName) {
44
44
  const { skillId, vecToBlob } = await import('./db.js');
45
45
  const { chunkText } = await import('./chunker.js');
46
46
 
47
- const files = globSync(`${sourceDir}/**/*.md`);
47
+ const files = globSync(`${sourceDir}/**/*.md`, { dot: true });
48
48
  let indexed = 0, skipped = 0, errors = 0;
49
49
  const batch = [];
50
50
 
@@ -118,7 +118,7 @@ export async function update() {
118
118
  const seenFiles = new Set();
119
119
  const allFiles = [];
120
120
  for (const { dir, source } of normalizedSources) {
121
- const files = globSync(`${dir}/**/*.md`);
121
+ const files = globSync(`${dir}/**/*.md`, { dot: true });
122
122
  for (const f of files) {
123
123
  const norm = path.resolve(f);
124
124
  if (!seenFiles.has(norm)) { seenFiles.add(norm); allFiles.push({ file: norm, source }); }
@@ -21,7 +21,7 @@ export default async function handler(args, bin) {
21
21
  }
22
22
 
23
23
  const { globSync } = await import('glob');
24
- const mdCount = globSync(`${abs}/**/*.md`, { absolute: true }).length;
24
+ const mdCount = globSync(`${abs}/**/*.md`, { absolute: true, dot: true }).length;
25
25
  if (mdCount === 0) {
26
26
  error(`No .md files found under ${abs}`);
27
27
  process.exit(1);
@@ -1,157 +1,157 @@
1
- import { colors, banner, success, error, info, section, table } from '../cli.js';
2
- import chalk from 'chalk';
3
- import path from 'path';
4
- import os from 'os';
5
- import fs from 'fs';
6
-
7
- export default async function handler(args, bin) {
8
- // Subcommand: validate / prune all installed marketplace files
9
- if (args[0] === 'validate' || args[0] === 'prune' || args[0] === '--validate' || args[0] === '--prune') {
10
- const { validateAndPruneMarketplace } = await import('../marketplace.js');
11
- const result = validateAndPruneMarketplace();
12
- if (result.removed.length > 0) {
13
- error(`Removed ${result.removed.length} invalid files:`);
14
- result.removed.forEach(r => console.log(` ${chalk.red('✗')} ${r.file}`));
15
- }
16
- if (result.errors.length > 0) {
17
- error(`${result.errors.length} errors:`);
18
- result.errors.forEach(e => console.log(` ${chalk.yellow('⚠')} ${e}`));
19
- }
20
- success(`${result.valid.length} valid files, ${result.removed.length} removed, ${result.errors.length} errors`);
21
- process.exit(result.errors.length > 0 ? 1 : 0);
22
- }
23
-
24
- if (!process.stdout.isTTY) {
25
- error('marketplace TUI requires an interactive terminal');
26
- process.exit(1);
27
- }
28
- const { browseMarketplace, browseBundles, installSkill, installBundle, installBundleBg, validateAndPruneMarketplace } = await import('../marketplace.js');
29
- const { loadConfig: _lcMkt } = await import('../config.js');
30
- const { getDb: _getDbMkt } = await import('../db.js');
31
- const { spinner: spin2 } = await import('../cli.js');
32
- const sp = spin2('Fetching marketplace...');
33
- sp.start();
34
- try {
35
- var [skills, bundles] = await Promise.all([browseMarketplace(1000), browseBundles(1000)]);
36
- } finally {
37
- sp.stop();
38
- }
39
-
40
- if (skills?.error) { error(skills.error); process.exit(1); }
41
-
42
- const { getCachedCount, setCachedCount, refreshCountsInBackground } = await import('../bundle-counts.js');
43
- const { SKILLS_STORE_DIR } = await import('../config.js');
44
- const { globSync } = await import('glob');
45
- const { SCRIPT_GLOBS } = await import('../github-import.js');
46
- const githubDir = path.join(SKILLS_STORE_DIR, 'github');
47
-
48
- // For each bundle: if installed on disk — use real file count + detect scripts; otherwise use cache
49
- const bundlesWithCounts = (Array.isArray(bundles) ? bundles : []).map(b => {
50
- if (!b.repo_url) return b;
51
- const owner = b.repo_url.split('/')[0];
52
- const repo = b.repo_url.split('/')[1];
53
- const clonedDir = path.join(githubDir, `${owner}-${repo}`);
54
- if (fs.existsSync(clonedDir) && fs.readdirSync(clonedDir).length > 0) {
55
- const realCount = globSync(`${clonedDir}/**/*.md`, { absolute: true }).length;
56
- const hasScripts = globSync(SCRIPT_GLOBS.map(p => `${clonedDir}/${p}`), { absolute: true }).length > 0;
57
- setCachedCount(b.repo_url, realCount);
58
- return { ...b, skillCount: realCount, has_tools: b.has_tools || hasScripts };
59
- }
60
- const cached = getCachedCount(b.repo_url);
61
- const knownCount = cached ?? b.skill_count ?? null;
62
- return knownCount !== null ? { ...b, skillCount: knownCount, has_tools: b.has_tools } : b;
63
- });
64
- refreshCountsInBackground(bundlesWithCounts);
65
-
66
- const installedSet = new Set();
67
- try {
68
- const cfg = _lcMkt();
69
- const db = _getDbMkt();
70
-
71
- for (const b of (Array.isArray(bundles) ? bundles : [])) {
72
- if (b.repo_url) {
73
- const owner = b.repo_url.split('/')[0];
74
- const repo = b.repo_url.split('/')[1];
75
- const clonedDir = path.join(githubDir, `${owner}-${repo}`);
76
- if (fs.existsSync(clonedDir) && fs.readdirSync(clonedDir).length > 0) installedSet.add(b.id);
77
- } else if (Array.isArray(b.skills)) {
78
- const allOnDisk = b.skills.every(sid => {
79
- const row = db.prepare('SELECT path FROM skills WHERE id = ?').get(sid);
80
- return row && fs.existsSync(row.path);
81
- });
82
- if (b.skills.length > 0 && allOnDisk) installedSet.add(b.id);
83
- }
84
- }
85
-
86
- for (const row of db.prepare('SELECT id, path FROM skills WHERE source = ?').all('marketplace')) {
87
- if (fs.existsSync(row.path)) installedSet.add(row.id);
88
- }
89
- } catch {}
90
-
91
- const { runTUI } = await import('../tui.js');
92
- const { loadConfig: _lcR, saveConfig: _scR, SKILLS_STORE_DIR: _ssR } = await import('../config.js');
93
- const { getDb: _getDbR } = await import('../db.js');
94
-
95
- await runTUI(
96
- Array.isArray(skills) ? skills : [],
97
- bundlesWithCounts,
98
- async (item, onStatus) => {
99
- if (item.type === 'bundle') {
100
- const r = await installBundleBg(item.id, async (err, result) => {
101
- if (err) { onStatus(false, err.message?.slice(0, 60) || 'Install failed'); return; }
102
- installedSet.add(item.id);
103
- const { getCachedCount } = await import('../bundle-counts.js');
104
- const cached = getCachedCount(item.repo_url);
105
- if (cached !== null) item.skillCount = cached;
106
- validateAndPruneMarketplace();
107
- onStatus(true, `Installed ${item.name}`);
108
- });
109
- if (r?.error) {
110
- if (!r.dedup) onStatus(false, r.error.slice(0, 60));
111
- return;
112
- }
113
- onStatus(null, `Queued ${item.name}…`);
114
- } else {
115
- const r = await installSkill(item.code || item.id);
116
- if (r?.error) { onStatus(false, r.error.slice(0, 60)); return; }
117
- installedSet.add(item.id);
118
- if (item.code) installedSet.add(item.code);
119
- validateAndPruneMarketplace();
120
- onStatus(true, `Installed ${item.name}`);
121
- }
122
- },
123
- installedSet,
124
- async (item) => {
125
- const cfg = _lcR();
126
- const db = _getDbR();
127
- if (item.type === 'bundle' && item.repo_url) {
128
- const owner = item.repo_url.split('/')[0];
129
- const repo = item.repo_url.split('/')[1];
130
- const clonedName = `${owner}-${repo}`;
131
- const clonedDir = path.join(_ssR, 'github', clonedName);
132
- if (fs.existsSync(clonedDir)) fs.rmSync(clonedDir, { recursive: true, force: true });
133
- const src = `github:${clonedName}`;
134
- cfg.sources = cfg.sources.filter(s => s.source !== src && !s.dir.startsWith(clonedDir));
135
- _scR(cfg);
136
- db.prepare('DELETE FROM skills WHERE source = ?').run(src);
137
- db.prepare('DELETE FROM chunks WHERE skill_id NOT IN (SELECT id FROM skills)').run();
138
- } else if (item.type === 'bundle') {
139
- const mktDir = path.join(_ssR, 'marketplace');
140
- for (const sid of (item.skills || [])) {
141
- const row = db.prepare('SELECT path FROM skills WHERE id = ?').get(sid);
142
- if (row?.path && fs.existsSync(row.path)) fs.unlinkSync(row.path);
143
- db.prepare('DELETE FROM skills WHERE id = ?').run(sid);
144
- db.prepare('DELETE FROM chunks WHERE skill_id = ?').run(sid);
145
- }
146
- } else {
147
- const row = db.prepare('SELECT path FROM skills WHERE id = ?').get(item.id);
148
- if (row?.path && fs.existsSync(row.path)) fs.unlinkSync(row.path);
149
- db.prepare('DELETE FROM skills WHERE id = ?').run(item.id);
150
- db.prepare('DELETE FROM chunks WHERE skill_id = ?').run(item.id);
151
- }
152
- installedSet.delete(item.id);
153
- if (item.code) installedSet.delete(item.code);
154
- }
155
- );
156
- process.exit(0);
157
- }
1
+ import { colors, banner, success, error, info, section, table } from '../cli.js';
2
+ import chalk from 'chalk';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import fs from 'fs';
6
+
7
+ export default async function handler(args, bin) {
8
+ // Subcommand: validate / prune all installed marketplace files
9
+ if (args[0] === 'validate' || args[0] === 'prune' || args[0] === '--validate' || args[0] === '--prune') {
10
+ const { validateAndPruneMarketplace } = await import('../marketplace.js');
11
+ const result = validateAndPruneMarketplace();
12
+ if (result.removed.length > 0) {
13
+ error(`Removed ${result.removed.length} invalid files:`);
14
+ result.removed.forEach(r => console.log(` ${chalk.red('✗')} ${r.file}`));
15
+ }
16
+ if (result.errors.length > 0) {
17
+ error(`${result.errors.length} errors:`);
18
+ result.errors.forEach(e => console.log(` ${chalk.yellow('⚠')} ${e}`));
19
+ }
20
+ success(`${result.valid.length} valid files, ${result.removed.length} removed, ${result.errors.length} errors`);
21
+ process.exit(result.errors.length > 0 ? 1 : 0);
22
+ }
23
+
24
+ if (!process.stdout.isTTY) {
25
+ error('marketplace TUI requires an interactive terminal');
26
+ process.exit(1);
27
+ }
28
+ const { browseMarketplace, browseBundles, installSkill, installBundle, installBundleBg, validateAndPruneMarketplace } = await import('../marketplace.js');
29
+ const { loadConfig: _lcMkt } = await import('../config.js');
30
+ const { getDb: _getDbMkt } = await import('../db.js');
31
+ const { spinner: spin2 } = await import('../cli.js');
32
+ const sp = spin2('Fetching marketplace...');
33
+ sp.start();
34
+ try {
35
+ var [skills, bundles] = await Promise.all([browseMarketplace(1000), browseBundles(1000)]);
36
+ } finally {
37
+ sp.stop();
38
+ }
39
+
40
+ if (skills?.error) { error(skills.error); process.exit(1); }
41
+
42
+ const { getCachedCount, setCachedCount, refreshCountsInBackground } = await import('../bundle-counts.js');
43
+ const { SKILLS_STORE_DIR } = await import('../config.js');
44
+ const { globSync } = await import('glob');
45
+ const { SCRIPT_GLOBS } = await import('../github-import.js');
46
+ const githubDir = path.join(SKILLS_STORE_DIR, 'github');
47
+
48
+ // For each bundle: if installed on disk — use real file count + detect scripts; otherwise use cache
49
+ const bundlesWithCounts = (Array.isArray(bundles) ? bundles : []).map(b => {
50
+ if (!b.repo_url) return b;
51
+ const owner = b.repo_url.split('/')[0];
52
+ const repo = b.repo_url.split('/')[1];
53
+ const clonedDir = path.join(githubDir, `${owner}-${repo}`);
54
+ if (fs.existsSync(clonedDir) && fs.readdirSync(clonedDir).length > 0) {
55
+ const realCount = globSync(`${clonedDir}/**/*.md`, { absolute: true, dot: true }).length;
56
+ const hasScripts = globSync(SCRIPT_GLOBS.map(p => `${clonedDir}/${p}`), { absolute: true, dot: true }).length > 0;
57
+ setCachedCount(b.repo_url, realCount);
58
+ return { ...b, skillCount: realCount, has_tools: b.has_tools || hasScripts };
59
+ }
60
+ const cached = getCachedCount(b.repo_url);
61
+ const knownCount = cached ?? b.skill_count ?? null;
62
+ return knownCount !== null ? { ...b, skillCount: knownCount, has_tools: b.has_tools } : b;
63
+ });
64
+ refreshCountsInBackground(bundlesWithCounts);
65
+
66
+ const installedSet = new Set();
67
+ try {
68
+ const cfg = _lcMkt();
69
+ const db = _getDbMkt();
70
+
71
+ for (const b of (Array.isArray(bundles) ? bundles : [])) {
72
+ if (b.repo_url) {
73
+ const owner = b.repo_url.split('/')[0];
74
+ const repo = b.repo_url.split('/')[1];
75
+ const clonedDir = path.join(githubDir, `${owner}-${repo}`);
76
+ if (fs.existsSync(clonedDir) && fs.readdirSync(clonedDir).length > 0) installedSet.add(b.id);
77
+ } else if (Array.isArray(b.skills)) {
78
+ const allOnDisk = b.skills.every(sid => {
79
+ const row = db.prepare('SELECT path FROM skills WHERE id = ?').get(sid);
80
+ return row && fs.existsSync(row.path);
81
+ });
82
+ if (b.skills.length > 0 && allOnDisk) installedSet.add(b.id);
83
+ }
84
+ }
85
+
86
+ for (const row of db.prepare('SELECT id, path FROM skills WHERE source = ?').all('marketplace')) {
87
+ if (fs.existsSync(row.path)) installedSet.add(row.id);
88
+ }
89
+ } catch {}
90
+
91
+ const { runTUI } = await import('../tui.js');
92
+ const { loadConfig: _lcR, saveConfig: _scR, SKILLS_STORE_DIR: _ssR } = await import('../config.js');
93
+ const { getDb: _getDbR } = await import('../db.js');
94
+
95
+ await runTUI(
96
+ Array.isArray(skills) ? skills : [],
97
+ bundlesWithCounts,
98
+ async (item, onStatus) => {
99
+ if (item.type === 'bundle') {
100
+ const r = await installBundleBg(item.id, async (err, result) => {
101
+ if (err) { onStatus(false, err.message?.slice(0, 60) || 'Install failed'); return; }
102
+ installedSet.add(item.id);
103
+ const { getCachedCount } = await import('../bundle-counts.js');
104
+ const cached = getCachedCount(item.repo_url);
105
+ if (cached !== null) item.skillCount = cached;
106
+ validateAndPruneMarketplace();
107
+ onStatus(true, `Installed ${item.name}`);
108
+ });
109
+ if (r?.error) {
110
+ if (!r.dedup) onStatus(false, r.error.slice(0, 60));
111
+ return;
112
+ }
113
+ onStatus(null, `Queued ${item.name}…`);
114
+ } else {
115
+ const r = await installSkill(item.code || item.id);
116
+ if (r?.error) { onStatus(false, r.error.slice(0, 60)); return; }
117
+ installedSet.add(item.id);
118
+ if (item.code) installedSet.add(item.code);
119
+ validateAndPruneMarketplace();
120
+ onStatus(true, `Installed ${item.name}`);
121
+ }
122
+ },
123
+ installedSet,
124
+ async (item) => {
125
+ const cfg = _lcR();
126
+ const db = _getDbR();
127
+ if (item.type === 'bundle' && item.repo_url) {
128
+ const owner = item.repo_url.split('/')[0];
129
+ const repo = item.repo_url.split('/')[1];
130
+ const clonedName = `${owner}-${repo}`;
131
+ const clonedDir = path.join(_ssR, 'github', clonedName);
132
+ if (fs.existsSync(clonedDir)) fs.rmSync(clonedDir, { recursive: true, force: true });
133
+ const src = `github:${clonedName}`;
134
+ cfg.sources = cfg.sources.filter(s => s.source !== src && !s.dir.startsWith(clonedDir));
135
+ _scR(cfg);
136
+ db.prepare('DELETE FROM skills WHERE source = ?').run(src);
137
+ db.prepare('DELETE FROM chunks WHERE skill_id NOT IN (SELECT id FROM skills)').run();
138
+ } else if (item.type === 'bundle') {
139
+ const mktDir = path.join(_ssR, 'marketplace');
140
+ for (const sid of (item.skills || [])) {
141
+ const row = db.prepare('SELECT path FROM skills WHERE id = ?').get(sid);
142
+ if (row?.path && fs.existsSync(row.path)) fs.unlinkSync(row.path);
143
+ db.prepare('DELETE FROM skills WHERE id = ?').run(sid);
144
+ db.prepare('DELETE FROM chunks WHERE skill_id = ?').run(sid);
145
+ }
146
+ } else {
147
+ const row = db.prepare('SELECT path FROM skills WHERE id = ?').get(item.id);
148
+ if (row?.path && fs.existsSync(row.path)) fs.unlinkSync(row.path);
149
+ db.prepare('DELETE FROM skills WHERE id = ?').run(item.id);
150
+ db.prepare('DELETE FROM chunks WHERE skill_id = ?').run(item.id);
151
+ }
152
+ installedSet.delete(item.id);
153
+ if (item.code) installedSet.delete(item.code);
154
+ }
155
+ );
156
+ process.exit(0);
157
+ }