promptgraph-mcp 2.9.34 → 2.9.36

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.
@@ -2,6 +2,18 @@ import { colors, banner, success, error, info, section, table } from '../cli.js'
2
2
  import chalk from 'chalk';
3
3
 
4
4
  export default async function handler(args, bin) {
5
+ const fs = (await import('fs')).default;
6
+ const { PROMPTGRAPH_DIR } = await import('../config.js');
7
+ const path = (await import('path')).default;
8
+
9
+ // --reset-dead clears the dead repos list so they reappear in marketplace
10
+ if (args.includes('--reset-dead')) {
11
+ const deadFile = path.join(PROMPTGRAPH_DIR, 'dead-repos.json');
12
+ try { fs.writeFileSync(deadFile, '[]'); } catch {}
13
+ success('Dead repos list cleared — all bundles visible in marketplace again');
14
+ process.exit(0);
15
+ }
16
+
5
17
  const { runDoctor } = await import('../doctor.js');
6
18
  const spin = (await import('../cli.js')).spinner('Checking database...');
7
19
  spin.start();
@@ -11,5 +23,6 @@ export default async function handler(args, bin) {
11
23
  info(`Removed: ${r.orphanChunks} chunks, ${r.orphanRatings} ratings, ${r.orphanFromEdges + r.danglingEdges} edges`);
12
24
  if (r.duplicatePaths > 0) info(chalk.yellow(`Warning: ${r.duplicatePaths} duplicate paths`));
13
25
  info(chalk.gray(`Now: ${r.totalSkills} skills, ${r.totalChunks} chunks, ${r.totalEdges} edges`));
26
+ info(chalk.gray(` Run \`${bin} doctor --reset-dead\` to restore hidden marketplace bundles`));
14
27
  process.exit(0);
15
28
  }
package/github-import.js CHANGED
@@ -253,9 +253,13 @@ function sparseClone(url, dest, subdir) {
253
253
  if (git(['init'], dest, 'pipe').status !== 0) return false;
254
254
  if (git(['remote', 'add', 'origin', url], dest, 'pipe').status !== 0) return false;
255
255
 
256
- // 2. sparse-checkout — non-cone mode with *.md glob
256
+ // 2. sparse-checkout — non-cone mode with *.md + script files
257
257
  git(['sparse-checkout', 'init'], dest, 'pipe');
258
- git(['sparse-checkout', 'set', '--no-cone', `${subdir}/*.md`, `${subdir}/**/*.md`], dest, 'pipe');
258
+ git(['sparse-checkout', 'set', '--no-cone',
259
+ `${subdir}/*.md`, `${subdir}/**/*.md`,
260
+ `${subdir}/**/*.py`, `${subdir}/**/*.sh`, `${subdir}/**/*.js`,
261
+ `${subdir}/**/*.ts`, `${subdir}/**/*.rb`, `${subdir}/**/*.bash`,
262
+ ], dest, 'pipe');
259
263
 
260
264
  // 3. fetch + checkout (depth=1, skip large blobs)
261
265
  const fetch = git(['fetch', '--depth=1', '--filter=blob:none', 'origin'], dest);
@@ -363,7 +367,11 @@ function sparseUpdate(dest, subdir) {
363
367
  const fetch = git(['fetch', '--depth=1', 'origin'], dest);
364
368
  if (fetch.status !== 0) return false;
365
369
 
366
- git(['sparse-checkout', 'set', '--no-cone', `${subdir}/*.md`, `${subdir}/**/*.md`], dest, 'pipe');
370
+ git(['sparse-checkout', 'set', '--no-cone',
371
+ `${subdir}/*.md`, `${subdir}/**/*.md`,
372
+ `${subdir}/**/*.py`, `${subdir}/**/*.sh`, `${subdir}/**/*.js`,
373
+ `${subdir}/**/*.ts`, `${subdir}/**/*.rb`, `${subdir}/**/*.bash`,
374
+ ], dest, 'pipe');
367
375
 
368
376
  for (const ref of ['origin/main', 'origin/master']) {
369
377
  const r = git(['checkout', ref], dest, 'pipe');
@@ -376,7 +384,17 @@ function sparseUpdate(dest, subdir) {
376
384
 
377
385
  // After checkout, force materialization of sparse-matched files.
378
386
  function finalizeCheckout(dest, success) {
379
- if (success) forceMaterialize(dest);
387
+ if (success) {
388
+ forceMaterialize(dest);
389
+ // Make scripts executable on unix
390
+ if (process.platform !== 'win32') {
391
+ const scriptExts = ['.py', '.sh', '.bash', '.rb'];
392
+ try {
393
+ const scripts = globSync(`${dest}/**/*{${scriptExts.join(',')}}`, { absolute: true });
394
+ for (const s of scripts) { try { fs.chmodSync(s, 0o755); } catch {} }
395
+ } catch {}
396
+ }
397
+ }
380
398
  return success;
381
399
  }
382
400
 
@@ -396,7 +414,10 @@ function fullClone(url, dest) {
396
414
  if (git(['init'], dest, 'pipe').status !== 0) return false;
397
415
  if (git(['remote', 'add', 'origin', url], dest, 'pipe').status !== 0) return false;
398
416
  git(['sparse-checkout', 'init'], dest, 'pipe');
399
- git(['sparse-checkout', 'set', '--no-cone', '*.md', '**/*.md'], dest, 'pipe');
417
+ git(['sparse-checkout', 'set', '--no-cone',
418
+ '*.md', '**/*.md',
419
+ '**/*.py', '**/*.sh', '**/*.js', '**/*.ts', '**/*.rb', '**/*.bash',
420
+ ], dest, 'pipe');
400
421
  const fetch = git(['fetch', '--depth=1', '--filter=blob:none', 'origin'], dest);
401
422
  if (fetch.status !== 0) return false;
402
423
  for (const branch of ['FETCH_HEAD', 'main', 'master']) {
package/marketplace.js CHANGED
@@ -384,7 +384,10 @@ async function _execRepoInstall(bundle) {
384
384
  try {
385
385
  await importFromGitHubLight(bundle.repo_url);
386
386
  } catch (e) {
387
- if (e.message && e.message.includes('No valid skills')) markDeadRepo(bundle.repo_url);
387
+ // Only mark dead on confirmed 404 — not on validation failures or network errors
388
+ if (e.message && (e.message.includes('HTTP 404') || e.message.includes('not found'))) {
389
+ markDeadRepo(bundle.repo_url);
390
+ }
388
391
  throw e;
389
392
  }
390
393
  const real = localSkillCount(bundle.repo_url);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptgraph-mcp",
3
- "version": "2.9.34",
3
+ "version": "2.9.36",
4
4
  "files": [
5
5
  "*.js",
6
6
  "commands/",