@npeercy/skills 0.1.8 → 0.1.10

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/lib/skills.js CHANGED
@@ -77,10 +77,9 @@ async function resolveSkillId(input, config) {
77
77
  }
78
78
 
79
79
  function linkNameForSkill(skillId) {
80
- if (skillId.startsWith('__builtin__/local/')) {
81
- return `builtin--${splitSkillId(skillId).name}`;
82
- }
83
- return symlinkName(skillId);
80
+ // Use bare skill name so directory matches name: field in SKILL.md.
81
+ // Pi expects these to match; mismatches show as "[Skill conflicts]".
82
+ return splitSkillId(skillId).name;
84
83
  }
85
84
 
86
85
  async function promptForToken(serverUrl) {
@@ -834,6 +833,16 @@ export async function cmdPublish(args) {
834
833
  const name = skillName || meta.name;
835
834
  if (!org || !user || !name) throw new Error('Cannot infer org/user/name. Provide --path or install the skill first.');
836
835
 
836
+ const id = `${org}/${user}/${name}`;
837
+ console.log(`\nWill publish: ${id}`);
838
+ console.log(` Files: ${Object.keys(collectFiles(dir)).join(', ')}`);
839
+
840
+ const ok = await promptYesNo('Publish to server?', true);
841
+ if (!ok) {
842
+ console.log('Cancelled.');
843
+ return;
844
+ }
845
+
837
846
  const files = collectFiles(dir);
838
847
  const result = await api.publish(org, user, name, args.message || '', files);
839
848
  console.log(`Published ${result.id}@${result.version}`);
@@ -883,6 +892,12 @@ export async function cmdImport(args) {
883
892
  const skillName = meta?.name || name;
884
893
  const id = `${cfg.org}/${me.user}/${skillName}`;
885
894
 
895
+ const ok = await promptYesNo(`Publish "${skillName}" to server as ${id}?`, true);
896
+ if (!ok) {
897
+ console.log(` Skipped ${skillName}.`);
898
+ continue;
899
+ }
900
+
886
901
  try {
887
902
  // Publish to server
888
903
  const files = collectFiles(dir);
package/lib/startup.js CHANGED
@@ -1,4 +1,6 @@
1
- import { loadConfig, saveConfig } from './config.js';
1
+ import { existsSync, readdirSync, lstatSync, readlinkSync, unlinkSync, symlinkSync, mkdirSync } from 'fs';
2
+ import { join, resolve, dirname } from 'path';
3
+ import { loadConfig, saveConfig, loadState, saveState, detectAgents } from './config.js';
2
4
  import { ensureBuiltinsInstalled, getLocalDiagnostics } from './skills.js';
3
5
 
4
6
  function cmpSemver(a, b) {
@@ -52,10 +54,66 @@ async function runUpdateCheck(currentVersion, { silent = false } = {}) {
52
54
  }
53
55
  }
54
56
 
57
+ function migrateOldSymlinks() {
58
+ // Migrate from old naming (org--user--name, builtin--name) to bare skill name.
59
+ // Pi expects directory name == name: field in SKILL.md.
60
+ const st = loadState();
61
+ const agents = detectAgents();
62
+ let migrated = 0;
63
+
64
+ for (const [id, rec] of Object.entries(st.installed)) {
65
+ const parts = id.split('/');
66
+ const bareName = parts[parts.length - 1]; // the skill name
67
+
68
+ // Figure out old link name
69
+ let oldLinkName;
70
+ if (id.startsWith('__builtin__/local/')) {
71
+ oldLinkName = `builtin--${bareName}`;
72
+ } else {
73
+ oldLinkName = id.replace(/\//g, '--');
74
+ }
75
+
76
+ // If old == new, nothing to do
77
+ if (oldLinkName === bareName) continue;
78
+
79
+ for (const agentName of (rec.agents || [])) {
80
+ const agentPath = agents[agentName];
81
+ if (!agentPath || !existsSync(agentPath)) continue;
82
+
83
+ const oldLink = join(agentPath, oldLinkName);
84
+ const newLink = join(agentPath, bareName);
85
+
86
+ // Remove old symlink if it exists
87
+ try {
88
+ if (lstatSync(oldLink).isSymbolicLink()) {
89
+ unlinkSync(oldLink);
90
+ }
91
+ } catch { /* doesn't exist */ }
92
+
93
+ // Create new symlink if not already there
94
+ if (!existsSync(newLink) && rec.path && existsSync(rec.path)) {
95
+ try {
96
+ mkdirSync(agentPath, { recursive: true });
97
+ symlinkSync(rec.path, newLink);
98
+ migrated++;
99
+ } catch { /* best effort */ }
100
+ }
101
+ }
102
+ }
103
+
104
+ return migrated;
105
+ }
106
+
55
107
  async function runAutoHeal(command, { jsonMode = false } = {}) {
56
108
  if (process.env.SKILLS_NO_STARTUP_HEAL === '1') return;
57
109
  if (['init'].includes(command)) return;
58
110
 
111
+ // Migrate old-style symlinks (org--user--name → bare name)
112
+ const migrated = migrateOldSymlinks();
113
+ if (!jsonMode && migrated > 0) {
114
+ console.log(`✓ Startup heal: migrated ${migrated} symlink(s) to match Pi naming.`);
115
+ }
116
+
59
117
  const result = await ensureBuiltinsInstalled({ quiet: true });
60
118
  if (!jsonMode && result.changed) {
61
119
  console.log(`✓ Startup heal: installed ${result.installed.length} missing built-in skill(s).`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@npeercy/skills",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "CLI-first skill marketplace for coding agents",
5
5
  "type": "module",
6
6
  "bin": {