promptgraph-mcp 2.3.6 → 2.3.8

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/github-import.js CHANGED
@@ -33,7 +33,8 @@ function repoExists(ownerRepo) {
33
33
  });
34
34
  }
35
35
 
36
- // Ask GitHub API which subdir to use (without cloning anything).
36
+ // Ask GitHub API which subdir to use (without cloning anything). Exported for validation.
37
+ export
37
38
  // Returns { subdir, label } or null (use root).
38
39
  async function detectSkillsDirFromAPI(ownerRepo) {
39
40
  try {
@@ -211,19 +212,21 @@ export async function importFromGitHub(repoUrl) {
211
212
  const detected = await detectSkillsDirFromAPI(ownerRepo);
212
213
  skillsSubdir = detected?.subdir || null;
213
214
 
214
- if (skillsSubdir) {
215
- console.log(`found: ${detected.label}/`);
216
- console.log(`Sparse-cloning ${url} (${skillsSubdir}/ only)...`);
217
- cloneOk = sparseClone(url, dest, skillsSubdir);
218
- if (!cloneOk) {
219
- console.log('Sparse-checkout failed, falling back to full clone...');
220
- fs.rmSync(dest, { recursive: true, force: true });
221
- cloneOk = fullClone(url, dest);
222
- skillsSubdir = null;
223
- }
224
- } else {
225
- console.log(`no subdir found, cloning root...`);
226
- cloneOk = fullClone(url, dest);
215
+ if (!skillsSubdir) {
216
+ throw new Error(
217
+ `No skill subdirectory found in ${ownerRepo}.\n` +
218
+ `Expected one of: ${SKILL_DIRS.join(', ')}\n` +
219
+ `Or any subfolder with .md files.\n` +
220
+ `Visit https://github.com/${ownerRepo} to check the repo structure.`
221
+ );
222
+ }
223
+
224
+ console.log(`found: ${detected.label}/`);
225
+ console.log(`Sparse-cloning ${url} (${skillsSubdir}/ only)...`);
226
+ cloneOk = sparseClone(url, dest, skillsSubdir);
227
+ if (!cloneOk) {
228
+ fs.rmSync(dest, { recursive: true, force: true });
229
+ throw new Error(`Sparse-checkout failed for ${url}`);
227
230
  }
228
231
 
229
232
  if (!cloneOk) throw new Error(`Clone failed for ${url}`);
package/index.js CHANGED
@@ -449,6 +449,21 @@ if (args[0] === 'bundle') {
449
449
  const repoArg = doPush ? args[2] : args[2];
450
450
  if (!repoArg || !repoArg.includes('/')) { error('Usage: pg bundle add-repo <owner/repo> [--push]'); process.exit(1); }
451
451
  const repo = repoArg.replace('https://github.com/', '').replace('.git', '');
452
+
453
+ // Validate repo has a skill subdirectory before publishing
454
+ const { detectSkillsDirFromAPI: _detectDir } = await import('./github-import.js');
455
+ process.stdout.write(chalk.gray(` Checking ${repo} for skill subdirectory... `));
456
+ const detected = await _detectDir(repo);
457
+ if (!detected) {
458
+ console.log(chalk.red('none found'));
459
+ error(
460
+ `Cannot publish: no skill subdirectory found in ${repo}\n` +
461
+ ` Expected: skills/, prompts/, commands/, agents/, or any folder with .md files\n` +
462
+ ` Visit: https://github.com/${repo}`
463
+ );
464
+ process.exit(1);
465
+ }
466
+ console.log(chalk.green(`found: ${detected.label}/`));
452
467
  const name = repo.split('/')[1].replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
453
468
  const id = repo.replace('/', '-').toLowerCase();
454
469
  const bundle = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptgraph-mcp",
3
- "version": "2.3.6",
3
+ "version": "2.3.8",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "bin": {
package/tui.js CHANGED
@@ -178,7 +178,8 @@ function render(state, installedSet = new Set()) {
178
178
  ? green(' ✓ installed') + dim(' ') + dim('d') + chalk.red(' remove') + dim(' ')
179
179
  : dim(' Enter') + chalk.white(' install') + dim(' ');
180
180
  write(instLabel + dim('Tab') + ' switch ' + dim('/') + ' search ' + dim('q') + ' quit' + CLEAR_EOL + '\n');
181
- write(dim(` → pg ${installCmd}`) + CLEAR_EOL + '\n');
181
+ const ghUrl = sel.repo_url ? chalk.hex('#3B82F6')(` github.com/${sel.repo_url}`) : '';
182
+ write(dim(` → pg ${installCmd}`) + ghUrl + CLEAR_EOL + '\n');
182
183
  } else if (state.confirming) {
183
184
  write(chalk.red.bold(' Remove ') + chalk.white(state.confirming.name) + chalk.red('? ') +
184
185
  chalk.white.bold('[y]') + chalk.gray('es ') + chalk.white.bold('[n]') + chalk.gray('o') + CLEAR_EOL + '\n');