@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 +19 -4
- package/lib/startup.js +59 -1
- package/package.json +1 -1
package/lib/skills.js
CHANGED
|
@@ -77,10 +77,9 @@ async function resolveSkillId(input, config) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
function linkNameForSkill(skillId) {
|
|
80
|
-
|
|
81
|
-
|
|
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 {
|
|
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).`);
|