promptgraph-mcp 1.5.17 → 1.5.19

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/cli.js CHANGED
@@ -34,6 +34,11 @@ export function spinner(text) {
34
34
  return ora({ text: colors.muted(text), spinner: 'dots', color: 'magenta' });
35
35
  }
36
36
 
37
+ // Full clear including scrollback (console.clear leaves scrollback on Windows)
38
+ export function clearScreen() {
39
+ process.stdout.write('\x1b[2J\x1b[3J\x1b[H');
40
+ }
41
+
37
42
  export function success(msg) {
38
43
  console.log('\n' + colors.success('✓') + ' ' + msg);
39
44
  }
package/index.js CHANGED
@@ -90,7 +90,7 @@ if (args[0] === 'marketplace' && (args[1] === 'bundles' || args[1] === 'bundle')
90
90
  spin.start();
91
91
  const bundles = await browseBundles(1000);
92
92
  spin.stop();
93
- console.clear();
93
+ (await import('./cli.js')).clearScreen();
94
94
 
95
95
  if (bundles?.error) { error(bundles.error); process.exit(1); }
96
96
 
@@ -134,11 +134,12 @@ if (args[0] === 'marketplace') {
134
134
  const PER_PAGE = 10;
135
135
  const page = Math.max(1, parseInt(args[1]) || 1);
136
136
 
137
+ const { clearScreen } = await import('./cli.js');
137
138
  const spin = (await import('./cli.js')).spinner('Fetching registry...');
138
139
  spin.start();
139
140
  const all = await browseMarketplace(1000);
140
141
  spin.stop();
141
- console.clear();
142
+ clearScreen();
142
143
 
143
144
  if (all?.error) {
144
145
  error(all.error);
@@ -154,6 +155,7 @@ if (args[0] === 'marketplace') {
154
155
  const startIdx = (page - 1) * PER_PAGE;
155
156
  const slice = all.slice(startIdx, startIdx + PER_PAGE);
156
157
  const purple = chalk.hex('#7C3AED');
158
+ const W = 60;
157
159
 
158
160
  const wrap = (text, width, indent) => {
159
161
  const words = (text || '').split(/\s+/);
@@ -164,40 +166,41 @@ if (args[0] === 'marketplace') {
164
166
  else line += ' ' + w;
165
167
  }
166
168
  if (line.trim()) lines.push(line.trim());
167
- return lines.map(l => indent + chalk.gray(l)).join('\n');
169
+ return lines.map(l => indent + chalk.dim(l)).join('\n');
168
170
  };
169
171
 
172
+ // header
170
173
  console.log();
171
- console.log(' ' + purple.bold('PromptGraph Marketplace'));
172
- console.log(' ' + chalk.gray(`${all.length} skill${all.length === 1 ? '' : 's'} · page ${page}/${totalPages}`));
173
- console.log(' ' + chalk.gray(''.repeat(54)));
174
- console.log();
174
+ console.log(' ' + purple.bold('PromptGraph') + chalk.dim(' · marketplace'));
175
+ console.log(' ' + chalk.dim(`${all.length} skills`) + chalk.dim(totalPages > 1 ? ` · page ${page}/${totalPages}` : ''));
176
+ console.log(chalk.dim(' ' + ''.repeat(W)));
175
177
 
176
178
  slice.forEach((s, i) => {
177
- const num = chalk.gray(String(startIdx + i + 1).padStart(2) + '.');
178
- const stars = (s.stars > 0 ? chalk.yellow('' + s.stars) : chalk.gray('★ 0'));
179
- console.log(' ' + num + ' ' + chalk.white.bold(s.id) + ' ' + stars);
180
- console.log(wrap(s.description, 64, ' '));
181
- if (s.tags?.length) console.log(' ' + purple(s.tags.map(t => '#' + t).join(' ')));
182
- console.log(' ' + chalk.gray('install: ') + chalk.cyan(`pg_marketplace_install("${s.id}")`));
183
- console.log(' ' + chalk.gray('use: ') + chalk.cyan(`pg_search("${s.id}")`) + chalk.gray(' → read the file'));
179
+ const n = chalk.dim(String(startIdx + i + 1).padStart(2));
180
+ const code = s.code ? chalk.hex('#A78BFA')(s.code) : '';
181
+ const stars = chalk.yellow('') + chalk.dim(' ' + (s.stars || 0));
184
182
  console.log();
183
+ // line 1: number, name ........ code, stars
184
+ const left = `${n} ${chalk.bold.white(s.id)}`;
185
+ console.log(' ' + left + ' ' + code + ' ' + stars);
186
+ // description
187
+ console.log(wrap(s.description, W - 6, ' '));
188
+ // tags
189
+ if (s.tags?.length) console.log(' ' + chalk.dim(s.tags.map(t => '#' + t).join(' ')));
185
190
  });
186
191
 
187
- console.log(' ' + chalk.gray('─'.repeat(54)));
192
+ console.log();
193
+ console.log(chalk.dim(' ' + '━'.repeat(W)));
194
+
188
195
  if (totalPages > 1) {
189
196
  const nav = [];
190
- if (page > 1) nav.push(chalk.cyan(`${bin} marketplace ${page - 1}`) + chalk.gray(' ‹ prev'));
191
- if (page < totalPages) nav.push(chalk.gray('next › ') + chalk.cyan(`${bin} marketplace ${page + 1}`));
192
- console.log(' ' + nav.join(' '));
193
- console.log();
197
+ if (page > 1) nav.push(chalk.dim('‹ ') + chalk.cyan(`${bin} marketplace ${page - 1}`));
198
+ if (page < totalPages) nav.push(chalk.cyan(`${bin} marketplace ${page + 1}`) + chalk.dim(' ›'));
199
+ console.log(' ' + nav.join(' '));
194
200
  }
195
- console.log(' ' + chalk.gray('These run through your AI assistant via the PromptGraph MCP server:'));
196
- console.log(' ' + chalk.cyan('pg_marketplace_install') + chalk.gray(' install a skill ') + chalk.gray('(or /pg-fetch <id>)'));
197
- console.log(' ' + chalk.cyan('pg_marketplace_publish') + chalk.gray(' share your own ') + chalk.gray('(or /pg-publish <file>)'));
198
- console.log(' ' + chalk.cyan('pg_search') + chalk.gray(' find & apply any installed skill'));
199
- console.log();
200
- console.log(' ' + chalk.gray('Browse curated sets: ') + chalk.cyan(`${bin} marketplace bundles`));
201
+ console.log(' ' + chalk.dim('install ') + chalk.cyan('tell your AI:') + ' ' + chalk.white('install ') + chalk.hex('#A78BFA')(slice[0].code || slice[0].id));
202
+ console.log(' ' + chalk.dim('bundles ') + chalk.cyan(`${bin} marketplace bundles`));
203
+ console.log(' ' + chalk.dim('publish ') + chalk.cyan('tell your AI:') + ' ' + chalk.white('/pg-publish <file>'));
201
204
  console.log();
202
205
  process.exit(0);
203
206
  }
package/marketplace.js CHANGED
@@ -51,13 +51,25 @@ export async function browseMarketplace(topK = 20) {
51
51
  }
52
52
  }
53
53
 
54
- export async function installSkill(skillId) {
54
+ export async function installSkill(query) {
55
55
  try {
56
56
  const text = await fetchText(REGISTRY_URL);
57
57
  const registry = JSON.parse(text);
58
- const skill = registry.skills?.find(s => s.id === skillId);
59
- if (!skill) return { error: `Skill "${skillId}" not found in registry` };
60
- if (!skill.raw_url) return { error: `Skill "${skillId}" has no download URL` };
58
+ const q = String(query).trim().toLowerCase();
59
+ // match by code, id, or name (case-insensitive)
60
+ const skill = registry.skills?.find(s =>
61
+ s.code?.toLowerCase() === q ||
62
+ s.id?.toLowerCase() === q ||
63
+ s.name?.toLowerCase() === q
64
+ );
65
+ if (!skill) {
66
+ // maybe it's a bundle code/id — hint the user
67
+ const bundle = (registry.bundles || []).find(b => b.code?.toLowerCase() === q || b.id?.toLowerCase() === q);
68
+ if (bundle) return { error: `"${query}" is a bundle. Use pg_bundle_install("${bundle.id}") instead.` };
69
+ return { error: `No skill matching "${query}" (try a code like pg-xxxxxx, an id, or a name)` };
70
+ }
71
+ if (!skill.raw_url) return { error: `Skill "${skill.id}" has no download URL` };
72
+ const skillId = skill.id;
61
73
 
62
74
  fs.mkdirSync(SKILLS_DIR, { recursive: true });
63
75
  const dest = path.join(SKILLS_DIR, `${skillId}.md`);
@@ -88,8 +100,11 @@ export async function installBundle(bundleId) {
88
100
  try {
89
101
  const text = await fetchText(REGISTRY_URL);
90
102
  const registry = JSON.parse(text);
91
- const bundle = (registry.bundles || []).find(b => b.id === bundleId);
92
- if (!bundle) return { error: `Bundle "${bundleId}" not found in registry` };
103
+ const q = String(bundleId).trim().toLowerCase();
104
+ const bundle = (registry.bundles || []).find(b =>
105
+ b.code?.toLowerCase() === q || b.id?.toLowerCase() === q || b.name?.toLowerCase() === q
106
+ );
107
+ if (!bundle) return { error: `No bundle matching "${bundleId}"` };
93
108
 
94
109
  fs.mkdirSync(SKILLS_DIR, { recursive: true });
95
110
  const installed = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptgraph-mcp",
3
- "version": "1.5.17",
3
+ "version": "1.5.19",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "bin": {