reskill 0.11.0 → 0.12.1
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/README.md +106 -20
- package/README.zh-CN.md +106 -20
- package/dist/cli/commands/index.d.ts +3 -3
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/info.d.ts +1 -1
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/install.d.ts +11 -11
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/list.d.ts +1 -1
- package/dist/cli/commands/list.d.ts.map +1 -1
- package/dist/cli/commands/outdated.d.ts +1 -1
- package/dist/cli/commands/outdated.d.ts.map +1 -1
- package/dist/cli/commands/uninstall.d.ts +1 -1
- package/dist/cli/commands/update.d.ts +1 -1
- package/dist/cli/index.js +700 -642
- package/dist/core/agent-registry.d.ts +16 -16
- package/dist/core/agent-registry.d.ts.map +1 -1
- package/dist/core/cache-manager.d.ts +17 -17
- package/dist/core/cache-manager.d.ts.map +1 -1
- package/dist/core/config-loader.d.ts +24 -18
- package/dist/core/config-loader.d.ts.map +1 -1
- package/dist/core/git-resolver.d.ts +23 -23
- package/dist/core/git-resolver.d.ts.map +1 -1
- package/dist/core/index.d.ts +8 -8
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/installer.d.ts +30 -30
- package/dist/core/installer.d.ts.map +1 -1
- package/dist/core/lock-manager.d.ts +17 -17
- package/dist/core/lock-manager.d.ts.map +1 -1
- package/dist/core/skill-manager.d.ts +57 -39
- package/dist/core/skill-manager.d.ts.map +1 -1
- package/dist/core/skill-parser.d.ts +43 -43
- package/dist/core/skill-parser.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +641 -583
- package/dist/types/index.d.ts +84 -84
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/fs.d.ts +7 -7
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/git.d.ts +5 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/package.json +18 -12
package/dist/cli/index.js
CHANGED
|
@@ -3,13 +3,11 @@ import * as __WEBPACK_EXTERNAL_MODULE_node_fs__ from "node:fs";
|
|
|
3
3
|
import * as __WEBPACK_EXTERNAL_MODULE_commander__ from "commander";
|
|
4
4
|
import * as __WEBPACK_EXTERNAL_MODULE_node_path__ from "node:path";
|
|
5
5
|
import * as __WEBPACK_EXTERNAL_MODULE_chalk__ from "chalk";
|
|
6
|
-
import * as
|
|
7
|
-
import * as __WEBPACK_EXTERNAL_MODULE_semver__ from "semver";
|
|
6
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_os__ from "node:os";
|
|
8
7
|
import * as __WEBPACK_EXTERNAL_MODULE_node_child_process__ from "node:child_process";
|
|
9
8
|
import * as __WEBPACK_EXTERNAL_MODULE_node_util__ from "node:util";
|
|
10
|
-
import * as
|
|
11
|
-
import * as
|
|
12
|
-
import * as __WEBPACK_EXTERNAL_MODULE_fs__ from "fs";
|
|
9
|
+
import * as __WEBPACK_EXTERNAL_MODULE_semver__ from "semver";
|
|
10
|
+
import * as __WEBPACK_EXTERNAL_MODULE__clack_prompts__ from "@clack/prompts";
|
|
13
11
|
import * as __WEBPACK_EXTERNAL_MODULE_ora__ from "ora";
|
|
14
12
|
var __webpack_modules__ = {
|
|
15
13
|
"node:fs": function(module) {
|
|
@@ -39,7 +37,7 @@ function writeJson(filePath, data, indent = 2) {
|
|
|
39
37
|
if (!exists(dir)) external_node_fs_.mkdirSync(dir, {
|
|
40
38
|
recursive: true
|
|
41
39
|
});
|
|
42
|
-
external_node_fs_.writeFileSync(filePath, JSON.stringify(data, null, indent)
|
|
40
|
+
external_node_fs_.writeFileSync(filePath, `${JSON.stringify(data, null, indent)}\n`, 'utf-8');
|
|
43
41
|
}
|
|
44
42
|
function ensureDir(dirPath) {
|
|
45
43
|
if (!exists(dirPath)) external_node_fs_.mkdirSync(dirPath, {
|
|
@@ -110,121 +108,9 @@ function shortenPath(fullPath, cwd) {
|
|
|
110
108
|
const home = getHomeDir();
|
|
111
109
|
const currentDir = cwd || process.cwd();
|
|
112
110
|
if (fullPath.startsWith(home)) return fullPath.replace(home, '~');
|
|
113
|
-
if (fullPath.startsWith(currentDir)) return
|
|
111
|
+
if (fullPath.startsWith(currentDir)) return `.${fullPath.slice(currentDir.length)}`;
|
|
114
112
|
return fullPath;
|
|
115
113
|
}
|
|
116
|
-
const DEFAULT_SKILLS_JSON = {
|
|
117
|
-
skills: {},
|
|
118
|
-
defaults: {
|
|
119
|
-
registry: 'github',
|
|
120
|
-
installDir: '.skills'
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
const DEFAULT_REGISTRIES = {
|
|
124
|
-
github: 'https://github.com',
|
|
125
|
-
gitlab: 'https://gitlab.com'
|
|
126
|
-
};
|
|
127
|
-
class ConfigLoader {
|
|
128
|
-
projectRoot;
|
|
129
|
-
configPath;
|
|
130
|
-
config = null;
|
|
131
|
-
constructor(projectRoot){
|
|
132
|
-
this.projectRoot = projectRoot || process.cwd();
|
|
133
|
-
this.configPath = getSkillsJsonPath(this.projectRoot);
|
|
134
|
-
}
|
|
135
|
-
getProjectRoot() {
|
|
136
|
-
return this.projectRoot;
|
|
137
|
-
}
|
|
138
|
-
getConfigPath() {
|
|
139
|
-
return this.configPath;
|
|
140
|
-
}
|
|
141
|
-
exists() {
|
|
142
|
-
return exists(this.configPath);
|
|
143
|
-
}
|
|
144
|
-
load() {
|
|
145
|
-
if (this.config) return this.config;
|
|
146
|
-
if (!this.exists()) throw new Error(`skills.json not found in ${this.projectRoot}. Run 'reskill init' first.`);
|
|
147
|
-
try {
|
|
148
|
-
this.config = readJson(this.configPath);
|
|
149
|
-
return this.config;
|
|
150
|
-
} catch (error) {
|
|
151
|
-
throw new Error(`Failed to parse skills.json: ${error.message}`);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
reload() {
|
|
155
|
-
this.config = null;
|
|
156
|
-
return this.load();
|
|
157
|
-
}
|
|
158
|
-
save(config) {
|
|
159
|
-
const toSave = config || this.config;
|
|
160
|
-
if (!toSave) throw new Error('No config to save');
|
|
161
|
-
writeJson(this.configPath, toSave);
|
|
162
|
-
this.config = toSave;
|
|
163
|
-
}
|
|
164
|
-
create(options) {
|
|
165
|
-
const config = {
|
|
166
|
-
...DEFAULT_SKILLS_JSON,
|
|
167
|
-
...options,
|
|
168
|
-
skills: options?.skills || {},
|
|
169
|
-
defaults: {
|
|
170
|
-
...DEFAULT_SKILLS_JSON.defaults,
|
|
171
|
-
...options?.defaults
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
this.save(config);
|
|
175
|
-
return config;
|
|
176
|
-
}
|
|
177
|
-
getDefaults() {
|
|
178
|
-
const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
|
|
179
|
-
return {
|
|
180
|
-
registry: config.defaults?.registry || DEFAULT_SKILLS_JSON.defaults.registry,
|
|
181
|
-
installDir: config.defaults?.installDir || DEFAULT_SKILLS_JSON.defaults.installDir,
|
|
182
|
-
targetAgents: config.defaults?.targetAgents || [],
|
|
183
|
-
installMode: config.defaults?.installMode || 'symlink'
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
getRegistryUrl(registryName) {
|
|
187
|
-
const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
|
|
188
|
-
if (config.registries?.[registryName]) return config.registries[registryName];
|
|
189
|
-
if (DEFAULT_REGISTRIES[registryName]) return DEFAULT_REGISTRIES[registryName];
|
|
190
|
-
return `https://${registryName}`;
|
|
191
|
-
}
|
|
192
|
-
getInstallDir() {
|
|
193
|
-
const defaults = this.getDefaults();
|
|
194
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.projectRoot, defaults.installDir);
|
|
195
|
-
}
|
|
196
|
-
addSkill(name, ref) {
|
|
197
|
-
if (!this.config) this.load();
|
|
198
|
-
this.config.skills[name] = ref;
|
|
199
|
-
this.save();
|
|
200
|
-
}
|
|
201
|
-
removeSkill(name) {
|
|
202
|
-
if (!this.config) this.load();
|
|
203
|
-
if (this.config.skills[name]) {
|
|
204
|
-
delete this.config.skills[name];
|
|
205
|
-
this.save();
|
|
206
|
-
return true;
|
|
207
|
-
}
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
getSkills() {
|
|
211
|
-
if (!this.config) {
|
|
212
|
-
if (!this.exists()) return {};
|
|
213
|
-
this.load();
|
|
214
|
-
}
|
|
215
|
-
return {
|
|
216
|
-
...this.config.skills
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
hasSkill(name) {
|
|
220
|
-
const skills = this.getSkills();
|
|
221
|
-
return name in skills;
|
|
222
|
-
}
|
|
223
|
-
getSkillRef(name) {
|
|
224
|
-
const skills = this.getSkills();
|
|
225
|
-
return skills[name];
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
114
|
const logger = {
|
|
229
115
|
info (message) {
|
|
230
116
|
console.log(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].blue('ℹ'), message);
|
|
@@ -266,49 +152,170 @@ const logger = {
|
|
|
266
152
|
}
|
|
267
153
|
}
|
|
268
154
|
};
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
155
|
+
const agent_registry_home = (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)();
|
|
156
|
+
const agents = {
|
|
157
|
+
amp: {
|
|
158
|
+
name: 'amp',
|
|
159
|
+
displayName: 'Amp',
|
|
160
|
+
skillsDir: '.agents/skills',
|
|
161
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/agents/skills'),
|
|
162
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/amp'))
|
|
163
|
+
},
|
|
164
|
+
antigravity: {
|
|
165
|
+
name: 'antigravity',
|
|
166
|
+
displayName: 'Antigravity',
|
|
167
|
+
skillsDir: '.agent/skills',
|
|
168
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini/antigravity/skills'),
|
|
169
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(process.cwd(), '.agent')) || (0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini/antigravity'))
|
|
170
|
+
},
|
|
171
|
+
'claude-code': {
|
|
172
|
+
name: 'claude-code',
|
|
173
|
+
displayName: 'Claude Code',
|
|
174
|
+
skillsDir: '.claude/skills',
|
|
175
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.claude/skills'),
|
|
176
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.claude'))
|
|
177
|
+
},
|
|
178
|
+
clawdbot: {
|
|
179
|
+
name: 'clawdbot',
|
|
180
|
+
displayName: 'Clawdbot',
|
|
181
|
+
skillsDir: 'skills',
|
|
182
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.clawdbot/skills'),
|
|
183
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.clawdbot'))
|
|
184
|
+
},
|
|
185
|
+
codex: {
|
|
186
|
+
name: 'codex',
|
|
187
|
+
displayName: 'Codex',
|
|
188
|
+
skillsDir: '.codex/skills',
|
|
189
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codex/skills'),
|
|
190
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codex'))
|
|
191
|
+
},
|
|
192
|
+
cursor: {
|
|
193
|
+
name: 'cursor',
|
|
194
|
+
displayName: 'Cursor',
|
|
195
|
+
skillsDir: '.cursor/skills',
|
|
196
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.cursor/skills'),
|
|
197
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.cursor'))
|
|
198
|
+
},
|
|
199
|
+
droid: {
|
|
200
|
+
name: 'droid',
|
|
201
|
+
displayName: 'Droid',
|
|
202
|
+
skillsDir: '.factory/skills',
|
|
203
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.factory/skills'),
|
|
204
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.factory/skills'))
|
|
205
|
+
},
|
|
206
|
+
'gemini-cli': {
|
|
207
|
+
name: 'gemini-cli',
|
|
208
|
+
displayName: 'Gemini CLI',
|
|
209
|
+
skillsDir: '.gemini/skills',
|
|
210
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini/skills'),
|
|
211
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini'))
|
|
212
|
+
},
|
|
213
|
+
'github-copilot': {
|
|
214
|
+
name: 'github-copilot',
|
|
215
|
+
displayName: 'GitHub Copilot',
|
|
216
|
+
skillsDir: '.github/skills',
|
|
217
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.copilot/skills'),
|
|
218
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(process.cwd(), '.github')) || (0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.copilot'))
|
|
219
|
+
},
|
|
220
|
+
goose: {
|
|
221
|
+
name: 'goose',
|
|
222
|
+
displayName: 'Goose',
|
|
223
|
+
skillsDir: '.goose/skills',
|
|
224
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/goose/skills'),
|
|
225
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/goose'))
|
|
226
|
+
},
|
|
227
|
+
kilo: {
|
|
228
|
+
name: 'kilo',
|
|
229
|
+
displayName: 'Kilo Code',
|
|
230
|
+
skillsDir: '.kilocode/skills',
|
|
231
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kilocode/skills'),
|
|
232
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kilocode'))
|
|
233
|
+
},
|
|
234
|
+
'kiro-cli': {
|
|
235
|
+
name: 'kiro-cli',
|
|
236
|
+
displayName: 'Kiro CLI',
|
|
237
|
+
skillsDir: '.kiro/skills',
|
|
238
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kiro/skills'),
|
|
239
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kiro'))
|
|
240
|
+
},
|
|
241
|
+
opencode: {
|
|
242
|
+
name: 'opencode',
|
|
243
|
+
displayName: 'OpenCode',
|
|
244
|
+
skillsDir: '.opencode/skills',
|
|
245
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/opencode/skills'),
|
|
246
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/opencode')) || (0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.claude/skills'))
|
|
247
|
+
},
|
|
248
|
+
roo: {
|
|
249
|
+
name: 'roo',
|
|
250
|
+
displayName: 'Roo Code',
|
|
251
|
+
skillsDir: '.roo/skills',
|
|
252
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.roo/skills'),
|
|
253
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.roo'))
|
|
254
|
+
},
|
|
255
|
+
trae: {
|
|
256
|
+
name: 'trae',
|
|
257
|
+
displayName: 'Trae',
|
|
258
|
+
skillsDir: '.trae/skills',
|
|
259
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.trae/skills'),
|
|
260
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.trae'))
|
|
261
|
+
},
|
|
262
|
+
windsurf: {
|
|
263
|
+
name: 'windsurf',
|
|
264
|
+
displayName: 'Windsurf',
|
|
265
|
+
skillsDir: '.windsurf/skills',
|
|
266
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codeium/windsurf/skills'),
|
|
267
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codeium/windsurf'))
|
|
268
|
+
},
|
|
269
|
+
neovate: {
|
|
270
|
+
name: 'neovate',
|
|
271
|
+
displayName: 'Neovate',
|
|
272
|
+
skillsDir: '.neovate/skills',
|
|
273
|
+
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.neovate/skills'),
|
|
274
|
+
detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.neovate'))
|
|
274
275
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
logger.log(` Install directory: ${config.defaults?.installDir}`);
|
|
288
|
-
logger.newline();
|
|
289
|
-
logger.log('Next steps:');
|
|
290
|
-
logger.log(' reskill install <skill> Install a skill');
|
|
291
|
-
logger.log(' reskill list List installed skills');
|
|
292
|
-
});
|
|
276
|
+
};
|
|
277
|
+
async function detectInstalledAgents() {
|
|
278
|
+
const installed = [];
|
|
279
|
+
for (const [type, config] of Object.entries(agents))if (await config.detectInstalled()) installed.push(type);
|
|
280
|
+
return installed;
|
|
281
|
+
}
|
|
282
|
+
function getAgentConfig(type) {
|
|
283
|
+
return agents[type];
|
|
284
|
+
}
|
|
285
|
+
function isValidAgentType(type) {
|
|
286
|
+
return type in agents;
|
|
287
|
+
}
|
|
293
288
|
const execAsync = (0, __WEBPACK_EXTERNAL_MODULE_node_util__.promisify)(__WEBPACK_EXTERNAL_MODULE_node_child_process__.exec);
|
|
294
289
|
class GitCloneError extends Error {
|
|
295
290
|
repoUrl;
|
|
296
291
|
originalError;
|
|
297
292
|
isAuthError;
|
|
293
|
+
urlType;
|
|
298
294
|
constructor(repoUrl, originalError){
|
|
299
295
|
const isAuthError = GitCloneError.isAuthenticationError(originalError.message);
|
|
296
|
+
const urlType = GitCloneError.detectUrlType(repoUrl);
|
|
300
297
|
let message = `Failed to clone repository: ${repoUrl}`;
|
|
301
298
|
if (isAuthError) {
|
|
302
|
-
message += '\n\nTip: For private repos, ensure git
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
299
|
+
message += '\n\nTip: For private repos, ensure git credentials are configured:';
|
|
300
|
+
if ('ssh' === urlType) {
|
|
301
|
+
message += '\n - Check ~/.ssh/id_rsa or ~/.ssh/id_ed25519';
|
|
302
|
+
message += '\n - Ensure SSH key is added to your Git hosting service';
|
|
303
|
+
} else {
|
|
304
|
+
message += "\n - Run 'git config --global credential.helper store'";
|
|
305
|
+
message += '\n - Or use a personal access token in the URL';
|
|
306
|
+
}
|
|
306
307
|
}
|
|
307
308
|
super(message);
|
|
308
309
|
this.name = 'GitCloneError';
|
|
309
310
|
this.repoUrl = repoUrl;
|
|
310
311
|
this.originalError = originalError;
|
|
311
312
|
this.isAuthError = isAuthError;
|
|
313
|
+
this.urlType = urlType;
|
|
314
|
+
}
|
|
315
|
+
static detectUrlType(url) {
|
|
316
|
+
if (url.startsWith('git@') || url.startsWith('ssh://')) return 'ssh';
|
|
317
|
+
if (url.startsWith('http://') || url.startsWith('https://')) return 'https';
|
|
318
|
+
return 'unknown';
|
|
312
319
|
}
|
|
313
320
|
static isAuthenticationError(message) {
|
|
314
321
|
const authPatterns = [
|
|
@@ -460,182 +467,10 @@ function parseGitUrl(url) {
|
|
|
460
467
|
}
|
|
461
468
|
return null;
|
|
462
469
|
}
|
|
463
|
-
class
|
|
464
|
-
|
|
465
|
-
constructor(
|
|
466
|
-
this.
|
|
467
|
-
}
|
|
468
|
-
parseRef(ref) {
|
|
469
|
-
const raw = ref;
|
|
470
|
-
if (isGitUrl(ref)) return this.parseGitUrlRef(ref);
|
|
471
|
-
let remaining = ref;
|
|
472
|
-
let registry = this.defaultRegistry;
|
|
473
|
-
let version;
|
|
474
|
-
const registryMatch = remaining.match(/^([a-zA-Z0-9.-]+):(.+)$/);
|
|
475
|
-
if (registryMatch) {
|
|
476
|
-
registry = registryMatch[1];
|
|
477
|
-
remaining = registryMatch[2];
|
|
478
|
-
}
|
|
479
|
-
const atIndex = remaining.lastIndexOf('@');
|
|
480
|
-
if (atIndex > 0) {
|
|
481
|
-
version = remaining.slice(atIndex + 1);
|
|
482
|
-
remaining = remaining.slice(0, atIndex);
|
|
483
|
-
}
|
|
484
|
-
const parts = remaining.split('/');
|
|
485
|
-
if (parts.length < 2) throw new Error(`Invalid skill reference: ${ref}. Expected format: owner/repo[@version]`);
|
|
486
|
-
const owner = parts[0];
|
|
487
|
-
const repo = parts[1];
|
|
488
|
-
const subPath = parts.length > 2 ? parts.slice(2).join('/') : void 0;
|
|
489
|
-
return {
|
|
490
|
-
registry,
|
|
491
|
-
owner,
|
|
492
|
-
repo,
|
|
493
|
-
subPath,
|
|
494
|
-
version,
|
|
495
|
-
raw
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
parseGitUrlRef(ref) {
|
|
499
|
-
const raw = ref;
|
|
500
|
-
let gitUrl = ref;
|
|
501
|
-
let version;
|
|
502
|
-
let subPath;
|
|
503
|
-
const gitSuffixIndex = ref.indexOf('.git');
|
|
504
|
-
if (-1 !== gitSuffixIndex) {
|
|
505
|
-
const afterGit = ref.slice(gitSuffixIndex + 4);
|
|
506
|
-
if (afterGit) {
|
|
507
|
-
const atIndex = afterGit.lastIndexOf('@');
|
|
508
|
-
if (-1 !== atIndex) {
|
|
509
|
-
version = afterGit.slice(atIndex + 1);
|
|
510
|
-
const pathPart = afterGit.slice(0, atIndex);
|
|
511
|
-
if (pathPart.startsWith('/')) subPath = pathPart.slice(1);
|
|
512
|
-
} else if (afterGit.startsWith('/')) subPath = afterGit.slice(1);
|
|
513
|
-
gitUrl = ref.slice(0, gitSuffixIndex + 4);
|
|
514
|
-
}
|
|
515
|
-
} else {
|
|
516
|
-
const atIndex = ref.lastIndexOf('@');
|
|
517
|
-
if (atIndex > 4) {
|
|
518
|
-
version = ref.slice(atIndex + 1);
|
|
519
|
-
gitUrl = ref.slice(0, atIndex);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
const parsed = parseGitUrl(gitUrl);
|
|
523
|
-
if (!parsed) throw new Error(`Invalid Git URL: ${ref}. Expected format: git@host:owner/repo.git or https://host/owner/repo.git`);
|
|
524
|
-
return {
|
|
525
|
-
registry: parsed.host,
|
|
526
|
-
owner: parsed.owner,
|
|
527
|
-
repo: parsed.repo,
|
|
528
|
-
subPath,
|
|
529
|
-
version,
|
|
530
|
-
raw,
|
|
531
|
-
gitUrl
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
parseVersion(versionSpec) {
|
|
535
|
-
if (!versionSpec) return {
|
|
536
|
-
type: 'branch',
|
|
537
|
-
value: 'main',
|
|
538
|
-
raw: ''
|
|
539
|
-
};
|
|
540
|
-
const raw = versionSpec;
|
|
541
|
-
if ('latest' === versionSpec) return {
|
|
542
|
-
type: 'latest',
|
|
543
|
-
value: 'latest',
|
|
544
|
-
raw
|
|
545
|
-
};
|
|
546
|
-
if (versionSpec.startsWith('branch:')) return {
|
|
547
|
-
type: 'branch',
|
|
548
|
-
value: versionSpec.slice(7),
|
|
549
|
-
raw
|
|
550
|
-
};
|
|
551
|
-
if (versionSpec.startsWith('commit:')) return {
|
|
552
|
-
type: 'commit',
|
|
553
|
-
value: versionSpec.slice(7),
|
|
554
|
-
raw
|
|
555
|
-
};
|
|
556
|
-
if (/^[\^~><]/.test(versionSpec)) return {
|
|
557
|
-
type: 'range',
|
|
558
|
-
value: versionSpec,
|
|
559
|
-
raw
|
|
560
|
-
};
|
|
561
|
-
return {
|
|
562
|
-
type: 'exact',
|
|
563
|
-
value: versionSpec,
|
|
564
|
-
raw
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
buildRepoUrl(parsed) {
|
|
568
|
-
if (parsed.gitUrl) return parsed.gitUrl;
|
|
569
|
-
return buildRepoUrl(parsed.registry, `${parsed.owner}/${parsed.repo}`);
|
|
570
|
-
}
|
|
571
|
-
async resolveVersion(repoUrl, versionSpec) {
|
|
572
|
-
switch(versionSpec.type){
|
|
573
|
-
case 'exact':
|
|
574
|
-
return {
|
|
575
|
-
ref: versionSpec.value
|
|
576
|
-
};
|
|
577
|
-
case 'latest':
|
|
578
|
-
{
|
|
579
|
-
const latestTag = await getLatestTag(repoUrl);
|
|
580
|
-
if (!latestTag) {
|
|
581
|
-
const defaultBranch = await getDefaultBranch(repoUrl);
|
|
582
|
-
return {
|
|
583
|
-
ref: defaultBranch
|
|
584
|
-
};
|
|
585
|
-
}
|
|
586
|
-
return {
|
|
587
|
-
ref: latestTag.name,
|
|
588
|
-
commit: latestTag.commit
|
|
589
|
-
};
|
|
590
|
-
}
|
|
591
|
-
case 'range':
|
|
592
|
-
{
|
|
593
|
-
const tags = await getRemoteTags(repoUrl);
|
|
594
|
-
const matchingTags = tags.filter((tag)=>{
|
|
595
|
-
const version = tag.name.replace(/^v/, '');
|
|
596
|
-
return __WEBPACK_EXTERNAL_MODULE_semver__.satisfies(version, versionSpec.value);
|
|
597
|
-
});
|
|
598
|
-
if (0 === matchingTags.length) throw new Error(`No version found matching ${versionSpec.raw} for ${repoUrl}`);
|
|
599
|
-
matchingTags.sort((a, b)=>{
|
|
600
|
-
const aVer = a.name.replace(/^v/, '');
|
|
601
|
-
const bVer = b.name.replace(/^v/, '');
|
|
602
|
-
return __WEBPACK_EXTERNAL_MODULE_semver__.compare(bVer, aVer);
|
|
603
|
-
});
|
|
604
|
-
return {
|
|
605
|
-
ref: matchingTags[0].name,
|
|
606
|
-
commit: matchingTags[0].commit
|
|
607
|
-
};
|
|
608
|
-
}
|
|
609
|
-
case 'branch':
|
|
610
|
-
return {
|
|
611
|
-
ref: versionSpec.value
|
|
612
|
-
};
|
|
613
|
-
case 'commit':
|
|
614
|
-
return {
|
|
615
|
-
ref: versionSpec.value,
|
|
616
|
-
commit: versionSpec.value
|
|
617
|
-
};
|
|
618
|
-
default:
|
|
619
|
-
throw new Error(`Unknown version type: ${versionSpec.type}`);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
async resolve(ref) {
|
|
623
|
-
const parsed = this.parseRef(ref);
|
|
624
|
-
const repoUrl = this.buildRepoUrl(parsed);
|
|
625
|
-
const versionSpec = this.parseVersion(parsed.version);
|
|
626
|
-
const resolved = await this.resolveVersion(repoUrl, versionSpec);
|
|
627
|
-
return {
|
|
628
|
-
parsed,
|
|
629
|
-
repoUrl,
|
|
630
|
-
ref: resolved.ref,
|
|
631
|
-
commit: resolved.commit
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
class CacheManager {
|
|
636
|
-
cacheDir;
|
|
637
|
-
constructor(cacheDir){
|
|
638
|
-
this.cacheDir = cacheDir || getCacheDir();
|
|
470
|
+
class CacheManager {
|
|
471
|
+
cacheDir;
|
|
472
|
+
constructor(cacheDir){
|
|
473
|
+
this.cacheDir = cacheDir || getCacheDir();
|
|
639
474
|
}
|
|
640
475
|
getCacheDir() {
|
|
641
476
|
return this.cacheDir;
|
|
@@ -743,238 +578,294 @@ class CacheManager {
|
|
|
743
578
|
};
|
|
744
579
|
}
|
|
745
580
|
}
|
|
746
|
-
const
|
|
747
|
-
|
|
581
|
+
const DEFAULT_SKILLS_JSON = {
|
|
582
|
+
skills: {},
|
|
583
|
+
defaults: {
|
|
584
|
+
registry: 'github',
|
|
585
|
+
installDir: '.skills'
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
const DEFAULT_REGISTRIES = {
|
|
589
|
+
github: 'https://github.com',
|
|
590
|
+
gitlab: 'https://gitlab.com'
|
|
591
|
+
};
|
|
592
|
+
class ConfigLoader {
|
|
748
593
|
projectRoot;
|
|
749
|
-
|
|
750
|
-
|
|
594
|
+
configPath;
|
|
595
|
+
config = null;
|
|
751
596
|
constructor(projectRoot){
|
|
752
597
|
this.projectRoot = projectRoot || process.cwd();
|
|
753
|
-
this.
|
|
598
|
+
this.configPath = getSkillsJsonPath(this.projectRoot);
|
|
754
599
|
}
|
|
755
|
-
|
|
756
|
-
return this.
|
|
600
|
+
getProjectRoot() {
|
|
601
|
+
return this.projectRoot;
|
|
602
|
+
}
|
|
603
|
+
getConfigPath() {
|
|
604
|
+
return this.configPath;
|
|
757
605
|
}
|
|
758
606
|
exists() {
|
|
759
|
-
return exists(this.
|
|
607
|
+
return exists(this.configPath);
|
|
760
608
|
}
|
|
761
609
|
load() {
|
|
762
|
-
if (this.
|
|
763
|
-
if (!this.exists()) {
|
|
764
|
-
this.lockData = {
|
|
765
|
-
lockfileVersion: LOCKFILE_VERSION,
|
|
766
|
-
skills: {}
|
|
767
|
-
};
|
|
768
|
-
return this.lockData;
|
|
769
|
-
}
|
|
610
|
+
if (this.config) return this.config;
|
|
611
|
+
if (!this.exists()) throw new Error(`skills.json not found in ${this.projectRoot}. Run 'reskill init' first.`);
|
|
770
612
|
try {
|
|
771
|
-
this.
|
|
772
|
-
return this.
|
|
613
|
+
this.config = readJson(this.configPath);
|
|
614
|
+
return this.config;
|
|
773
615
|
} catch (error) {
|
|
774
|
-
throw new Error(`Failed to parse skills.
|
|
616
|
+
throw new Error(`Failed to parse skills.json: ${error.message}`);
|
|
775
617
|
}
|
|
776
618
|
}
|
|
777
619
|
reload() {
|
|
778
|
-
this.
|
|
620
|
+
this.config = null;
|
|
779
621
|
return this.load();
|
|
780
622
|
}
|
|
781
|
-
save(
|
|
782
|
-
const toSave =
|
|
783
|
-
if (!toSave) throw new Error('No
|
|
784
|
-
writeJson(this.
|
|
785
|
-
this.
|
|
623
|
+
save(config) {
|
|
624
|
+
const toSave = config || this.config;
|
|
625
|
+
if (!toSave) throw new Error('No config to save');
|
|
626
|
+
writeJson(this.configPath, toSave);
|
|
627
|
+
this.config = toSave;
|
|
786
628
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
629
|
+
ensureExists() {
|
|
630
|
+
if (this.exists()) return false;
|
|
631
|
+
this.create();
|
|
632
|
+
return true;
|
|
790
633
|
}
|
|
791
|
-
|
|
792
|
-
const
|
|
793
|
-
|
|
634
|
+
create(options) {
|
|
635
|
+
const config = {
|
|
636
|
+
...DEFAULT_SKILLS_JSON,
|
|
637
|
+
...options,
|
|
638
|
+
skills: options?.skills || {},
|
|
639
|
+
defaults: {
|
|
640
|
+
...DEFAULT_SKILLS_JSON.defaults,
|
|
641
|
+
...options?.defaults
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
this.save(config);
|
|
645
|
+
return config;
|
|
646
|
+
}
|
|
647
|
+
getDefaults() {
|
|
648
|
+
const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
|
|
649
|
+
return {
|
|
650
|
+
registry: config.defaults?.registry || 'github',
|
|
651
|
+
installDir: config.defaults?.installDir || '.skills',
|
|
652
|
+
targetAgents: config.defaults?.targetAgents || [],
|
|
653
|
+
installMode: config.defaults?.installMode || 'symlink'
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
getRegistryUrl(registryName) {
|
|
657
|
+
const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
|
|
658
|
+
if (config.registries?.[registryName]) return config.registries[registryName];
|
|
659
|
+
if (DEFAULT_REGISTRIES[registryName]) return DEFAULT_REGISTRIES[registryName];
|
|
660
|
+
return `https://${registryName}`;
|
|
661
|
+
}
|
|
662
|
+
getInstallDir() {
|
|
663
|
+
const defaults = this.getDefaults();
|
|
664
|
+
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.projectRoot, defaults.installDir);
|
|
665
|
+
}
|
|
666
|
+
addSkill(name, ref) {
|
|
667
|
+
if (!this.config) this.load();
|
|
668
|
+
if (this.config) this.config.skills[name] = ref;
|
|
794
669
|
this.save();
|
|
795
670
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
if (
|
|
799
|
-
delete
|
|
671
|
+
removeSkill(name) {
|
|
672
|
+
if (!this.config) this.load();
|
|
673
|
+
if (this.config?.skills[name]) {
|
|
674
|
+
delete this.config.skills[name];
|
|
800
675
|
this.save();
|
|
801
676
|
return true;
|
|
802
677
|
}
|
|
803
678
|
return false;
|
|
804
679
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
680
|
+
getSkills() {
|
|
681
|
+
if (!this.config) {
|
|
682
|
+
if (!this.exists()) return {};
|
|
683
|
+
this.load();
|
|
684
|
+
}
|
|
685
|
+
return {
|
|
686
|
+
...this.config?.skills
|
|
812
687
|
};
|
|
813
|
-
this.set(name, lockedSkill);
|
|
814
|
-
return lockedSkill;
|
|
815
688
|
}
|
|
816
|
-
|
|
817
|
-
const
|
|
689
|
+
hasSkill(name) {
|
|
690
|
+
const skills = this.getSkills();
|
|
691
|
+
return name in skills;
|
|
692
|
+
}
|
|
693
|
+
getSkillRef(name) {
|
|
694
|
+
const skills = this.getSkills();
|
|
695
|
+
return skills[name];
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
class GitResolver {
|
|
699
|
+
defaultRegistry;
|
|
700
|
+
constructor(defaultRegistry = 'github'){
|
|
701
|
+
this.defaultRegistry = defaultRegistry;
|
|
702
|
+
}
|
|
703
|
+
parseRef(ref) {
|
|
704
|
+
const raw = ref;
|
|
705
|
+
if (isGitUrl(ref)) return this.parseGitUrlRef(ref);
|
|
706
|
+
let remaining = ref;
|
|
707
|
+
let registry = this.defaultRegistry;
|
|
708
|
+
let version;
|
|
709
|
+
const registryMatch = remaining.match(/^([a-zA-Z0-9.-]+):(.+)$/);
|
|
710
|
+
if (registryMatch) {
|
|
711
|
+
registry = registryMatch[1];
|
|
712
|
+
remaining = registryMatch[2];
|
|
713
|
+
}
|
|
714
|
+
const atIndex = remaining.lastIndexOf('@');
|
|
715
|
+
if (atIndex > 0) {
|
|
716
|
+
version = remaining.slice(atIndex + 1);
|
|
717
|
+
remaining = remaining.slice(0, atIndex);
|
|
718
|
+
}
|
|
719
|
+
const parts = remaining.split('/');
|
|
720
|
+
if (parts.length < 2) throw new Error(`Invalid skill reference: ${ref}. Expected format: owner/repo[@version]`);
|
|
721
|
+
const owner = parts[0];
|
|
722
|
+
const repo = parts[1];
|
|
723
|
+
const subPath = parts.length > 2 ? parts.slice(2).join('/') : void 0;
|
|
818
724
|
return {
|
|
819
|
-
|
|
725
|
+
registry,
|
|
726
|
+
owner,
|
|
727
|
+
repo,
|
|
728
|
+
subPath,
|
|
729
|
+
version,
|
|
730
|
+
raw
|
|
820
731
|
};
|
|
821
732
|
}
|
|
822
|
-
|
|
823
|
-
const
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
const
|
|
828
|
-
if (
|
|
829
|
-
|
|
733
|
+
parseGitUrlRef(ref) {
|
|
734
|
+
const raw = ref;
|
|
735
|
+
let gitUrl = ref;
|
|
736
|
+
let version;
|
|
737
|
+
let subPath;
|
|
738
|
+
const gitSuffixIndex = ref.indexOf('.git');
|
|
739
|
+
if (-1 !== gitSuffixIndex) {
|
|
740
|
+
const afterGit = ref.slice(gitSuffixIndex + 4);
|
|
741
|
+
if (afterGit) {
|
|
742
|
+
const atIndex = afterGit.lastIndexOf('@');
|
|
743
|
+
if (-1 !== atIndex) {
|
|
744
|
+
version = afterGit.slice(atIndex + 1);
|
|
745
|
+
const pathPart = afterGit.slice(0, atIndex);
|
|
746
|
+
if (pathPart.startsWith('/')) subPath = pathPart.slice(1);
|
|
747
|
+
} else if (afterGit.startsWith('/')) subPath = afterGit.slice(1);
|
|
748
|
+
gitUrl = ref.slice(0, gitSuffixIndex + 4);
|
|
749
|
+
}
|
|
750
|
+
} else {
|
|
751
|
+
const atIndex = ref.lastIndexOf('@');
|
|
752
|
+
if (atIndex > 4) {
|
|
753
|
+
version = ref.slice(atIndex + 1);
|
|
754
|
+
gitUrl = ref.slice(0, atIndex);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
const parsed = parseGitUrl(gitUrl);
|
|
758
|
+
if (!parsed) throw new Error(`Invalid Git URL: ${ref}. Expected format: git@host:owner/repo.git or https://host/owner/repo.git`);
|
|
759
|
+
return {
|
|
760
|
+
registry: parsed.host,
|
|
761
|
+
owner: parsed.owner,
|
|
762
|
+
repo: parsed.repo,
|
|
763
|
+
subPath,
|
|
764
|
+
version,
|
|
765
|
+
raw,
|
|
766
|
+
gitUrl
|
|
767
|
+
};
|
|
830
768
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
769
|
+
parseVersion(versionSpec) {
|
|
770
|
+
if (!versionSpec) return {
|
|
771
|
+
type: 'branch',
|
|
772
|
+
value: 'main',
|
|
773
|
+
raw: ''
|
|
774
|
+
};
|
|
775
|
+
const raw = versionSpec;
|
|
776
|
+
if ('latest' === versionSpec) return {
|
|
777
|
+
type: 'latest',
|
|
778
|
+
value: 'latest',
|
|
779
|
+
raw
|
|
780
|
+
};
|
|
781
|
+
if (versionSpec.startsWith('branch:')) return {
|
|
782
|
+
type: 'branch',
|
|
783
|
+
value: versionSpec.slice(7),
|
|
784
|
+
raw
|
|
785
|
+
};
|
|
786
|
+
if (versionSpec.startsWith('commit:')) return {
|
|
787
|
+
type: 'commit',
|
|
788
|
+
value: versionSpec.slice(7),
|
|
789
|
+
raw
|
|
790
|
+
};
|
|
791
|
+
if (/^[\^~><]/.test(versionSpec)) return {
|
|
792
|
+
type: 'range',
|
|
793
|
+
value: versionSpec,
|
|
794
|
+
raw
|
|
795
|
+
};
|
|
796
|
+
return {
|
|
797
|
+
type: 'exact',
|
|
798
|
+
value: versionSpec,
|
|
799
|
+
raw
|
|
835
800
|
};
|
|
836
|
-
this.save();
|
|
837
801
|
}
|
|
838
|
-
|
|
839
|
-
if (
|
|
840
|
-
|
|
841
|
-
|
|
802
|
+
buildRepoUrl(parsed) {
|
|
803
|
+
if (parsed.gitUrl) return parsed.gitUrl;
|
|
804
|
+
return buildRepoUrl(parsed.registry, `${parsed.owner}/${parsed.repo}`);
|
|
805
|
+
}
|
|
806
|
+
async resolveVersion(repoUrl, versionSpec) {
|
|
807
|
+
switch(versionSpec.type){
|
|
808
|
+
case 'exact':
|
|
809
|
+
return {
|
|
810
|
+
ref: versionSpec.value
|
|
811
|
+
};
|
|
812
|
+
case 'latest':
|
|
813
|
+
{
|
|
814
|
+
const latestTag = await getLatestTag(repoUrl);
|
|
815
|
+
if (!latestTag) {
|
|
816
|
+
const defaultBranch = await getDefaultBranch(repoUrl);
|
|
817
|
+
return {
|
|
818
|
+
ref: defaultBranch
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
return {
|
|
822
|
+
ref: latestTag.name,
|
|
823
|
+
commit: latestTag.commit
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
case 'range':
|
|
827
|
+
{
|
|
828
|
+
const tags = await getRemoteTags(repoUrl);
|
|
829
|
+
const matchingTags = tags.filter((tag)=>{
|
|
830
|
+
const version = tag.name.replace(/^v/, '');
|
|
831
|
+
return __WEBPACK_EXTERNAL_MODULE_semver__.satisfies(version, versionSpec.value);
|
|
832
|
+
});
|
|
833
|
+
if (0 === matchingTags.length) throw new Error(`No version found matching ${versionSpec.raw} for ${repoUrl}`);
|
|
834
|
+
matchingTags.sort((a, b)=>{
|
|
835
|
+
const aVer = a.name.replace(/^v/, '');
|
|
836
|
+
const bVer = b.name.replace(/^v/, '');
|
|
837
|
+
return __WEBPACK_EXTERNAL_MODULE_semver__.compare(bVer, aVer);
|
|
838
|
+
});
|
|
839
|
+
return {
|
|
840
|
+
ref: matchingTags[0].name,
|
|
841
|
+
commit: matchingTags[0].commit
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
case 'branch':
|
|
845
|
+
return {
|
|
846
|
+
ref: versionSpec.value
|
|
847
|
+
};
|
|
848
|
+
case 'commit':
|
|
849
|
+
return {
|
|
850
|
+
ref: versionSpec.value,
|
|
851
|
+
commit: versionSpec.value
|
|
852
|
+
};
|
|
853
|
+
default:
|
|
854
|
+
throw new Error(`Unknown version type: ${versionSpec.type}`);
|
|
842
855
|
}
|
|
843
|
-
this.lockData = null;
|
|
844
856
|
}
|
|
845
|
-
|
|
846
|
-
const
|
|
847
|
-
const
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
name: 'antigravity',
|
|
857
|
-
displayName: 'Antigravity',
|
|
858
|
-
skillsDir: '.agent/skills',
|
|
859
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/antigravity/skills'),
|
|
860
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(process.cwd(), '.agent')) || (0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/antigravity'))
|
|
861
|
-
},
|
|
862
|
-
'claude-code': {
|
|
863
|
-
name: 'claude-code',
|
|
864
|
-
displayName: 'Claude Code',
|
|
865
|
-
skillsDir: '.claude/skills',
|
|
866
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude/skills'),
|
|
867
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude'))
|
|
868
|
-
},
|
|
869
|
-
clawdbot: {
|
|
870
|
-
name: 'clawdbot',
|
|
871
|
-
displayName: 'Clawdbot',
|
|
872
|
-
skillsDir: 'skills',
|
|
873
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.clawdbot/skills'),
|
|
874
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.clawdbot'))
|
|
875
|
-
},
|
|
876
|
-
codex: {
|
|
877
|
-
name: 'codex',
|
|
878
|
-
displayName: 'Codex',
|
|
879
|
-
skillsDir: '.codex/skills',
|
|
880
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codex/skills'),
|
|
881
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codex'))
|
|
882
|
-
},
|
|
883
|
-
cursor: {
|
|
884
|
-
name: 'cursor',
|
|
885
|
-
displayName: 'Cursor',
|
|
886
|
-
skillsDir: '.cursor/skills',
|
|
887
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.cursor/skills'),
|
|
888
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.cursor'))
|
|
889
|
-
},
|
|
890
|
-
droid: {
|
|
891
|
-
name: 'droid',
|
|
892
|
-
displayName: 'Droid',
|
|
893
|
-
skillsDir: '.factory/skills',
|
|
894
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.factory/skills'),
|
|
895
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.factory/skills'))
|
|
896
|
-
},
|
|
897
|
-
'gemini-cli': {
|
|
898
|
-
name: 'gemini-cli',
|
|
899
|
-
displayName: 'Gemini CLI',
|
|
900
|
-
skillsDir: '.gemini/skills',
|
|
901
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/skills'),
|
|
902
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini'))
|
|
903
|
-
},
|
|
904
|
-
'github-copilot': {
|
|
905
|
-
name: 'github-copilot',
|
|
906
|
-
displayName: 'GitHub Copilot',
|
|
907
|
-
skillsDir: '.github/skills',
|
|
908
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.copilot/skills'),
|
|
909
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(process.cwd(), '.github')) || (0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.copilot'))
|
|
910
|
-
},
|
|
911
|
-
goose: {
|
|
912
|
-
name: 'goose',
|
|
913
|
-
displayName: 'Goose',
|
|
914
|
-
skillsDir: '.goose/skills',
|
|
915
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/goose/skills'),
|
|
916
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/goose'))
|
|
917
|
-
},
|
|
918
|
-
kilo: {
|
|
919
|
-
name: 'kilo',
|
|
920
|
-
displayName: 'Kilo Code',
|
|
921
|
-
skillsDir: '.kilocode/skills',
|
|
922
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kilocode/skills'),
|
|
923
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kilocode'))
|
|
924
|
-
},
|
|
925
|
-
'kiro-cli': {
|
|
926
|
-
name: 'kiro-cli',
|
|
927
|
-
displayName: 'Kiro CLI',
|
|
928
|
-
skillsDir: '.kiro/skills',
|
|
929
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kiro/skills'),
|
|
930
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kiro'))
|
|
931
|
-
},
|
|
932
|
-
opencode: {
|
|
933
|
-
name: 'opencode',
|
|
934
|
-
displayName: 'OpenCode',
|
|
935
|
-
skillsDir: '.opencode/skills',
|
|
936
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/opencode/skills'),
|
|
937
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/opencode')) || (0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude/skills'))
|
|
938
|
-
},
|
|
939
|
-
roo: {
|
|
940
|
-
name: 'roo',
|
|
941
|
-
displayName: 'Roo Code',
|
|
942
|
-
skillsDir: '.roo/skills',
|
|
943
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.roo/skills'),
|
|
944
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.roo'))
|
|
945
|
-
},
|
|
946
|
-
trae: {
|
|
947
|
-
name: 'trae',
|
|
948
|
-
displayName: 'Trae',
|
|
949
|
-
skillsDir: '.trae/skills',
|
|
950
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.trae/skills'),
|
|
951
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.trae'))
|
|
952
|
-
},
|
|
953
|
-
windsurf: {
|
|
954
|
-
name: 'windsurf',
|
|
955
|
-
displayName: 'Windsurf',
|
|
956
|
-
skillsDir: '.windsurf/skills',
|
|
957
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codeium/windsurf/skills'),
|
|
958
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codeium/windsurf'))
|
|
959
|
-
},
|
|
960
|
-
neovate: {
|
|
961
|
-
name: 'neovate',
|
|
962
|
-
displayName: 'Neovate',
|
|
963
|
-
skillsDir: '.neovate/skills',
|
|
964
|
-
globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.neovate/skills'),
|
|
965
|
-
detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.neovate'))
|
|
857
|
+
async resolve(ref) {
|
|
858
|
+
const parsed = this.parseRef(ref);
|
|
859
|
+
const repoUrl = this.buildRepoUrl(parsed);
|
|
860
|
+
const versionSpec = this.parseVersion(parsed.version);
|
|
861
|
+
const resolved = await this.resolveVersion(repoUrl, versionSpec);
|
|
862
|
+
return {
|
|
863
|
+
parsed,
|
|
864
|
+
repoUrl,
|
|
865
|
+
ref: resolved.ref,
|
|
866
|
+
commit: resolved.commit
|
|
867
|
+
};
|
|
966
868
|
}
|
|
967
|
-
};
|
|
968
|
-
async function detectInstalledAgents() {
|
|
969
|
-
const installed = [];
|
|
970
|
-
for (const [type, config] of Object.entries(agents))if (await config.detectInstalled()) installed.push(type);
|
|
971
|
-
return installed;
|
|
972
|
-
}
|
|
973
|
-
function getAgentConfig(type) {
|
|
974
|
-
return agents[type];
|
|
975
|
-
}
|
|
976
|
-
function isValidAgentType(type) {
|
|
977
|
-
return type in agents;
|
|
978
869
|
}
|
|
979
870
|
const installer_AGENTS_DIR = '.agents';
|
|
980
871
|
const installer_SKILLS_SUBDIR = 'skills';
|
|
@@ -992,7 +883,7 @@ function installer_isPathSafe(basePath, targetPath) {
|
|
|
992
883
|
return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
|
|
993
884
|
}
|
|
994
885
|
function installer_getCanonicalSkillsDir(isGlobal, cwd) {
|
|
995
|
-
const baseDir = isGlobal ? (0,
|
|
886
|
+
const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)() : cwd || process.cwd();
|
|
996
887
|
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, installer_AGENTS_DIR, installer_SKILLS_SUBDIR);
|
|
997
888
|
}
|
|
998
889
|
function installer_ensureDir(dirPath) {
|
|
@@ -1009,7 +900,8 @@ function installer_remove(targetPath) {
|
|
|
1009
900
|
function copyDirectory(src, dest, options) {
|
|
1010
901
|
const exclude = new Set(options?.exclude || [
|
|
1011
902
|
'README.md',
|
|
1012
|
-
'metadata.json'
|
|
903
|
+
'metadata.json',
|
|
904
|
+
'.reskill-commit'
|
|
1013
905
|
]);
|
|
1014
906
|
installer_ensureDir(dest);
|
|
1015
907
|
const entries = external_node_fs_.readdirSync(src, {
|
|
@@ -1046,7 +938,7 @@ async function installer_createSymlink(target, linkPath) {
|
|
|
1046
938
|
const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
|
|
1047
939
|
installer_ensureDir(linkDir);
|
|
1048
940
|
const relativePath = __WEBPACK_EXTERNAL_MODULE_node_path__.relative(linkDir, target);
|
|
1049
|
-
const symlinkType = 'win32' === (0,
|
|
941
|
+
const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_node_os__.platform)() ? 'junction' : void 0;
|
|
1050
942
|
external_node_fs_.symlinkSync(relativePath, linkPath, symlinkType);
|
|
1051
943
|
return true;
|
|
1052
944
|
} catch {
|
|
@@ -1135,38 +1027,138 @@ class Installer {
|
|
|
1135
1027
|
};
|
|
1136
1028
|
}
|
|
1137
1029
|
}
|
|
1138
|
-
async installToAgents(sourcePath, skillName, targetAgents, options = {}) {
|
|
1139
|
-
const results = new Map();
|
|
1140
|
-
for (const agent of targetAgents){
|
|
1141
|
-
const result = await this.installForAgent(sourcePath, skillName, agent, options);
|
|
1142
|
-
results.set(agent, result);
|
|
1030
|
+
async installToAgents(sourcePath, skillName, targetAgents, options = {}) {
|
|
1031
|
+
const results = new Map();
|
|
1032
|
+
for (const agent of targetAgents){
|
|
1033
|
+
const result = await this.installForAgent(sourcePath, skillName, agent, options);
|
|
1034
|
+
results.set(agent, result);
|
|
1035
|
+
}
|
|
1036
|
+
return results;
|
|
1037
|
+
}
|
|
1038
|
+
isInstalled(skillName, agentType) {
|
|
1039
|
+
const skillPath = this.getAgentSkillPath(skillName, agentType);
|
|
1040
|
+
return external_node_fs_.existsSync(skillPath);
|
|
1041
|
+
}
|
|
1042
|
+
uninstallFromAgent(skillName, agentType) {
|
|
1043
|
+
const skillPath = this.getAgentSkillPath(skillName, agentType);
|
|
1044
|
+
if (!external_node_fs_.existsSync(skillPath)) return false;
|
|
1045
|
+
installer_remove(skillPath);
|
|
1046
|
+
return true;
|
|
1047
|
+
}
|
|
1048
|
+
uninstallFromAgents(skillName, targetAgents) {
|
|
1049
|
+
const results = new Map();
|
|
1050
|
+
for (const agent of targetAgents)results.set(agent, this.uninstallFromAgent(skillName, agent));
|
|
1051
|
+
const canonicalPath = this.getCanonicalPath(skillName);
|
|
1052
|
+
if (external_node_fs_.existsSync(canonicalPath)) installer_remove(canonicalPath);
|
|
1053
|
+
return results;
|
|
1054
|
+
}
|
|
1055
|
+
listInstalledSkills(agentType) {
|
|
1056
|
+
const agent = getAgentConfig(agentType);
|
|
1057
|
+
const skillsDir = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
|
|
1058
|
+
if (!external_node_fs_.existsSync(skillsDir)) return [];
|
|
1059
|
+
return external_node_fs_.readdirSync(skillsDir, {
|
|
1060
|
+
withFileTypes: true
|
|
1061
|
+
}).filter((entry)=>entry.isDirectory() || entry.isSymbolicLink()).map((entry)=>entry.name);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
const LOCKFILE_VERSION = 1;
|
|
1065
|
+
class LockManager {
|
|
1066
|
+
projectRoot;
|
|
1067
|
+
lockPath;
|
|
1068
|
+
lockData = null;
|
|
1069
|
+
constructor(projectRoot){
|
|
1070
|
+
this.projectRoot = projectRoot || process.cwd();
|
|
1071
|
+
this.lockPath = getSkillsLockPath(this.projectRoot);
|
|
1072
|
+
}
|
|
1073
|
+
getLockPath() {
|
|
1074
|
+
return this.lockPath;
|
|
1075
|
+
}
|
|
1076
|
+
exists() {
|
|
1077
|
+
return exists(this.lockPath);
|
|
1078
|
+
}
|
|
1079
|
+
load() {
|
|
1080
|
+
if (this.lockData) return this.lockData;
|
|
1081
|
+
if (!this.exists()) {
|
|
1082
|
+
this.lockData = {
|
|
1083
|
+
lockfileVersion: LOCKFILE_VERSION,
|
|
1084
|
+
skills: {}
|
|
1085
|
+
};
|
|
1086
|
+
return this.lockData;
|
|
1087
|
+
}
|
|
1088
|
+
try {
|
|
1089
|
+
this.lockData = readJson(this.lockPath);
|
|
1090
|
+
return this.lockData;
|
|
1091
|
+
} catch (error) {
|
|
1092
|
+
throw new Error(`Failed to parse skills.lock: ${error.message}`);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
reload() {
|
|
1096
|
+
this.lockData = null;
|
|
1097
|
+
return this.load();
|
|
1098
|
+
}
|
|
1099
|
+
save(lockToSave) {
|
|
1100
|
+
const toSave = lockToSave || this.lockData;
|
|
1101
|
+
if (!toSave) throw new Error('No lock to save');
|
|
1102
|
+
writeJson(this.lockPath, toSave);
|
|
1103
|
+
this.lockData = toSave;
|
|
1104
|
+
}
|
|
1105
|
+
get(name) {
|
|
1106
|
+
const lock = this.load();
|
|
1107
|
+
return lock.skills[name];
|
|
1108
|
+
}
|
|
1109
|
+
set(name, skill) {
|
|
1110
|
+
const lock = this.load();
|
|
1111
|
+
lock.skills[name] = skill;
|
|
1112
|
+
this.save();
|
|
1113
|
+
}
|
|
1114
|
+
remove(name) {
|
|
1115
|
+
const lock = this.load();
|
|
1116
|
+
if (lock.skills[name]) {
|
|
1117
|
+
delete lock.skills[name];
|
|
1118
|
+
this.save();
|
|
1119
|
+
return true;
|
|
1143
1120
|
}
|
|
1144
|
-
return
|
|
1121
|
+
return false;
|
|
1145
1122
|
}
|
|
1146
|
-
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1123
|
+
lockSkill(name, options) {
|
|
1124
|
+
const lockedSkill = {
|
|
1125
|
+
source: options.source,
|
|
1126
|
+
version: options.version,
|
|
1127
|
+
resolved: options.resolved,
|
|
1128
|
+
commit: options.commit,
|
|
1129
|
+
installedAt: new Date().toISOString()
|
|
1130
|
+
};
|
|
1131
|
+
this.set(name, lockedSkill);
|
|
1132
|
+
return lockedSkill;
|
|
1149
1133
|
}
|
|
1150
|
-
|
|
1151
|
-
const
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1134
|
+
getAll() {
|
|
1135
|
+
const lock = this.load();
|
|
1136
|
+
return {
|
|
1137
|
+
...lock.skills
|
|
1138
|
+
};
|
|
1155
1139
|
}
|
|
1156
|
-
|
|
1157
|
-
const
|
|
1158
|
-
|
|
1159
|
-
const canonicalPath = this.getCanonicalPath(skillName);
|
|
1160
|
-
if (external_node_fs_.existsSync(canonicalPath)) installer_remove(canonicalPath);
|
|
1161
|
-
return results;
|
|
1140
|
+
has(name) {
|
|
1141
|
+
const lock = this.load();
|
|
1142
|
+
return name in lock.skills;
|
|
1162
1143
|
}
|
|
1163
|
-
|
|
1164
|
-
const
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1144
|
+
isVersionMatch(name, version) {
|
|
1145
|
+
const locked = this.get(name);
|
|
1146
|
+
if (!locked) return false;
|
|
1147
|
+
return locked.version === version;
|
|
1148
|
+
}
|
|
1149
|
+
clear() {
|
|
1150
|
+
this.lockData = {
|
|
1151
|
+
lockfileVersion: LOCKFILE_VERSION,
|
|
1152
|
+
skills: {}
|
|
1153
|
+
};
|
|
1154
|
+
this.save();
|
|
1155
|
+
}
|
|
1156
|
+
delete() {
|
|
1157
|
+
if (this.exists()) {
|
|
1158
|
+
const fs = __webpack_require__("node:fs");
|
|
1159
|
+
fs.unlinkSync(this.lockPath);
|
|
1160
|
+
}
|
|
1161
|
+
this.lockData = null;
|
|
1170
1162
|
}
|
|
1171
1163
|
}
|
|
1172
1164
|
class SkillManager {
|
|
@@ -1195,8 +1187,17 @@ class SkillManager {
|
|
|
1195
1187
|
if (this.isGlobal) return getGlobalSkillsDir();
|
|
1196
1188
|
return this.config.getInstallDir();
|
|
1197
1189
|
}
|
|
1190
|
+
getCanonicalSkillsDir() {
|
|
1191
|
+
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
1192
|
+
const baseDir = this.isGlobal ? home : this.projectRoot;
|
|
1193
|
+
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, '.agents', 'skills');
|
|
1194
|
+
}
|
|
1198
1195
|
getSkillPath(name) {
|
|
1199
|
-
|
|
1196
|
+
const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
|
|
1197
|
+
if (exists(canonicalPath)) return canonicalPath;
|
|
1198
|
+
const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
|
|
1199
|
+
if (exists(legacyPath)) return legacyPath;
|
|
1200
|
+
return canonicalPath;
|
|
1200
1201
|
}
|
|
1201
1202
|
async install(ref, options = {}) {
|
|
1202
1203
|
const { force = false, save = true } = options;
|
|
@@ -1209,11 +1210,13 @@ class SkillManager {
|
|
|
1209
1210
|
const locked = this.lockManager.get(skillName);
|
|
1210
1211
|
if (locked && locked.version === version) {
|
|
1211
1212
|
logger.info(`${skillName}@${version} is already installed`);
|
|
1212
|
-
|
|
1213
|
+
const installed = this.getInstalledSkill(skillName);
|
|
1214
|
+
if (installed) return installed;
|
|
1213
1215
|
}
|
|
1214
1216
|
if (!force) {
|
|
1215
1217
|
logger.warn(`${skillName} is already installed. Use --force to reinstall.`);
|
|
1216
|
-
|
|
1218
|
+
const installed = this.getInstalledSkill(skillName);
|
|
1219
|
+
if (installed) return installed;
|
|
1217
1220
|
}
|
|
1218
1221
|
}
|
|
1219
1222
|
logger["package"](`Installing ${skillName}@${version}...`);
|
|
@@ -1227,15 +1230,20 @@ class SkillManager {
|
|
|
1227
1230
|
if (exists(skillPath)) remove(skillPath);
|
|
1228
1231
|
await this.cache.copyTo(parsed, version, skillPath);
|
|
1229
1232
|
if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
|
|
1230
|
-
source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ?
|
|
1233
|
+
source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
|
|
1231
1234
|
version,
|
|
1232
1235
|
resolved: repoUrl,
|
|
1233
1236
|
commit: cacheResult.commit
|
|
1234
1237
|
});
|
|
1235
|
-
if (!this.isGlobal && save
|
|
1238
|
+
if (!this.isGlobal && save) {
|
|
1239
|
+
this.config.ensureExists();
|
|
1240
|
+
this.config.addSkill(skillName, ref);
|
|
1241
|
+
}
|
|
1236
1242
|
const locationHint = this.isGlobal ? '(global)' : '';
|
|
1237
1243
|
logger.success(`Installed ${skillName}@${version} to ${skillPath} ${locationHint}`.trim());
|
|
1238
|
-
|
|
1244
|
+
const installed = this.getInstalledSkill(skillName);
|
|
1245
|
+
if (!installed) throw new Error(`Failed to get installed skill info for ${skillName}`);
|
|
1246
|
+
return installed;
|
|
1239
1247
|
}
|
|
1240
1248
|
async installAll(options = {}) {
|
|
1241
1249
|
const skills = this.config.getSkills();
|
|
@@ -1302,7 +1310,7 @@ class SkillManager {
|
|
|
1302
1310
|
skillName = name || skillJson.name || skillName;
|
|
1303
1311
|
} catch {}
|
|
1304
1312
|
const linkPath = this.getSkillPath(skillName);
|
|
1305
|
-
ensureDir(
|
|
1313
|
+
ensureDir(__WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath));
|
|
1306
1314
|
createSymlink(absolutePath, linkPath);
|
|
1307
1315
|
logger.success(`Linked ${skillName} → ${absolutePath}`);
|
|
1308
1316
|
return {
|
|
@@ -1328,20 +1336,36 @@ class SkillManager {
|
|
|
1328
1336
|
return true;
|
|
1329
1337
|
}
|
|
1330
1338
|
list() {
|
|
1331
|
-
const installDir = this.getInstallDir();
|
|
1332
|
-
if (!exists(installDir)) return [];
|
|
1333
1339
|
const skills = [];
|
|
1334
|
-
const
|
|
1335
|
-
|
|
1336
|
-
|
|
1340
|
+
const seenNames = new Set();
|
|
1341
|
+
const canonicalDir = this.getCanonicalSkillsDir();
|
|
1342
|
+
if (exists(canonicalDir)) for (const name of listDir(canonicalDir)){
|
|
1343
|
+
const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalDir, name);
|
|
1344
|
+
if (!isDirectory(skillPath)) continue;
|
|
1345
|
+
const skill = this.getInstalledSkillFromPath(name, skillPath);
|
|
1346
|
+
if (skill) {
|
|
1347
|
+
skills.push(skill);
|
|
1348
|
+
seenNames.add(name);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
const legacyDir = this.getInstallDir();
|
|
1352
|
+
if (exists(legacyDir) && legacyDir !== canonicalDir) for (const name of listDir(legacyDir)){
|
|
1353
|
+
if (seenNames.has(name)) continue;
|
|
1354
|
+
const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(legacyDir, name);
|
|
1337
1355
|
if (!isDirectory(skillPath)) continue;
|
|
1338
|
-
|
|
1339
|
-
|
|
1356
|
+
if (isSymlink(skillPath)) try {
|
|
1357
|
+
const realPath = getRealPath(skillPath);
|
|
1358
|
+
if (realPath.includes(__WEBPACK_EXTERNAL_MODULE_node_path__.join('.agents', 'skills'))) continue;
|
|
1359
|
+
} catch {}
|
|
1360
|
+
const skill = this.getInstalledSkillFromPath(name, skillPath);
|
|
1361
|
+
if (skill) {
|
|
1362
|
+
skills.push(skill);
|
|
1363
|
+
seenNames.add(name);
|
|
1364
|
+
}
|
|
1340
1365
|
}
|
|
1341
1366
|
return skills;
|
|
1342
1367
|
}
|
|
1343
|
-
|
|
1344
|
-
const skillPath = this.getSkillPath(name);
|
|
1368
|
+
getInstalledSkillFromPath(name, skillPath) {
|
|
1345
1369
|
if (!exists(skillPath)) return null;
|
|
1346
1370
|
const isLinked = isSymlink(skillPath);
|
|
1347
1371
|
const locked = this.lockManager.get(name);
|
|
@@ -1359,6 +1383,13 @@ class SkillManager {
|
|
|
1359
1383
|
isLinked
|
|
1360
1384
|
};
|
|
1361
1385
|
}
|
|
1386
|
+
getInstalledSkill(name) {
|
|
1387
|
+
const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
|
|
1388
|
+
if (exists(canonicalPath)) return this.getInstalledSkillFromPath(name, canonicalPath);
|
|
1389
|
+
const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
|
|
1390
|
+
if (exists(legacyPath)) return this.getInstalledSkillFromPath(name, legacyPath);
|
|
1391
|
+
return null;
|
|
1392
|
+
}
|
|
1362
1393
|
getInfo(name) {
|
|
1363
1394
|
return {
|
|
1364
1395
|
installed: this.getInstalledSkill(name),
|
|
@@ -1420,12 +1451,15 @@ class SkillManager {
|
|
|
1420
1451
|
mode: mode
|
|
1421
1452
|
});
|
|
1422
1453
|
if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
|
|
1423
|
-
source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ?
|
|
1454
|
+
source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
|
|
1424
1455
|
version,
|
|
1425
1456
|
resolved: repoUrl,
|
|
1426
1457
|
commit: cacheResult.commit
|
|
1427
1458
|
});
|
|
1428
|
-
if (!this.isGlobal && save
|
|
1459
|
+
if (!this.isGlobal && save) {
|
|
1460
|
+
this.config.ensureExists();
|
|
1461
|
+
this.config.addSkill(skillName, ref);
|
|
1462
|
+
}
|
|
1429
1463
|
const successCount = Array.from(results.values()).filter((r)=>r.success).length;
|
|
1430
1464
|
const failCount = results.size - successCount;
|
|
1431
1465
|
if (0 === failCount) logger.success(`Installed ${skillName}@${version} to ${successCount} agent(s)`);
|
|
@@ -1434,7 +1468,7 @@ class SkillManager {
|
|
|
1434
1468
|
name: skillName,
|
|
1435
1469
|
path: sourcePath,
|
|
1436
1470
|
version,
|
|
1437
|
-
source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ?
|
|
1471
|
+
source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`
|
|
1438
1472
|
};
|
|
1439
1473
|
return {
|
|
1440
1474
|
skill,
|
|
@@ -1477,6 +1511,69 @@ class SkillManager {
|
|
|
1477
1511
|
return results;
|
|
1478
1512
|
}
|
|
1479
1513
|
}
|
|
1514
|
+
const infoCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('info').description('Show skill details').argument('<skill>', 'Skill name').option('-j, --json', 'Output as JSON').action((skillName, options)=>{
|
|
1515
|
+
const skillManager = new SkillManager();
|
|
1516
|
+
const info = skillManager.getInfo(skillName);
|
|
1517
|
+
if (options.json) {
|
|
1518
|
+
console.log(JSON.stringify(info, null, 2));
|
|
1519
|
+
return;
|
|
1520
|
+
}
|
|
1521
|
+
if (!info.installed && !info.config) {
|
|
1522
|
+
logger.error(`Skill ${skillName} not found`);
|
|
1523
|
+
process.exit(1);
|
|
1524
|
+
}
|
|
1525
|
+
logger.log(`Skill: ${skillName}`);
|
|
1526
|
+
logger.newline();
|
|
1527
|
+
if (info.config) {
|
|
1528
|
+
logger.log("Configuration (skills.json):");
|
|
1529
|
+
logger.log(` Reference: ${info.config}`);
|
|
1530
|
+
}
|
|
1531
|
+
if (info.locked) {
|
|
1532
|
+
logger.log("Locked Version (skills.lock):");
|
|
1533
|
+
logger.log(` Version: ${info.locked.version}`);
|
|
1534
|
+
logger.log(` Source: ${info.locked.source}`);
|
|
1535
|
+
logger.log(` Commit: ${info.locked.commit}`);
|
|
1536
|
+
logger.log(` Installed: ${info.locked.installedAt}`);
|
|
1537
|
+
}
|
|
1538
|
+
if (info.installed) {
|
|
1539
|
+
logger.log("Installed:");
|
|
1540
|
+
logger.log(` Path: ${info.installed.path}`);
|
|
1541
|
+
logger.log(` Version: ${info.installed.version}`);
|
|
1542
|
+
logger.log(` Linked: ${info.installed.isLinked ? 'Yes' : 'No'}`);
|
|
1543
|
+
if (info.installed.metadata) {
|
|
1544
|
+
const meta = info.installed.metadata;
|
|
1545
|
+
logger.log("Metadata (skill.json):");
|
|
1546
|
+
if (meta.description) logger.log(` Description: ${meta.description}`);
|
|
1547
|
+
if (meta.author) logger.log(` Author: ${meta.author}`);
|
|
1548
|
+
if (meta.license) logger.log(` License: ${meta.license}`);
|
|
1549
|
+
if (meta.keywords?.length) logger.log(` Keywords: ${meta.keywords.join(', ')}`);
|
|
1550
|
+
}
|
|
1551
|
+
} else logger.warn(`Skill ${skillName} is not installed`);
|
|
1552
|
+
});
|
|
1553
|
+
const initCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('init').description('Initialize a new skills.json configuration').option('-n, --name <name>', 'Project name').option('-r, --registry <registry>', 'Default registry', 'github').option('-d, --install-dir <dir>', 'Skills installation directory', '.skills').option('-y, --yes', 'Skip prompts and use defaults').action(async (options)=>{
|
|
1554
|
+
const configLoader = new ConfigLoader();
|
|
1555
|
+
if (configLoader.exists()) {
|
|
1556
|
+
logger.warn('skills.json already exists');
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
const config = configLoader.create({
|
|
1560
|
+
name: options.name,
|
|
1561
|
+
defaults: {
|
|
1562
|
+
registry: options.registry,
|
|
1563
|
+
installDir: options.installDir
|
|
1564
|
+
}
|
|
1565
|
+
});
|
|
1566
|
+
logger.success('Created skills.json');
|
|
1567
|
+
logger.newline();
|
|
1568
|
+
logger.log('Configuration:');
|
|
1569
|
+
logger.log(` Name: ${config.name || '(not set)'}`);
|
|
1570
|
+
logger.log(` Default registry: ${config.defaults?.registry}`);
|
|
1571
|
+
logger.log(` Install directory: ${config.defaults?.installDir}`);
|
|
1572
|
+
logger.newline();
|
|
1573
|
+
logger.log('Next steps:');
|
|
1574
|
+
logger.log(' reskill install <skill> Install a skill');
|
|
1575
|
+
logger.log(' reskill list List installed skills');
|
|
1576
|
+
});
|
|
1480
1577
|
function formatAgentNames(agentTypes, maxShow = 5) {
|
|
1481
1578
|
const names = agentTypes.map((a)=>agents[a].displayName);
|
|
1482
1579
|
if (names.length <= maxShow) return names.join(', ');
|
|
@@ -1525,7 +1622,7 @@ const installCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('instal
|
|
|
1525
1622
|
label: config.displayName
|
|
1526
1623
|
}));
|
|
1527
1624
|
const selected = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.multiselect({
|
|
1528
|
-
message:
|
|
1625
|
+
message: `Select agents to install skills to ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('(Space to toggle, Enter to confirm)')}`,
|
|
1529
1626
|
options: allAgentChoices,
|
|
1530
1627
|
required: true,
|
|
1531
1628
|
initialValues: allAgentTypes
|
|
@@ -1547,7 +1644,7 @@ const installCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('instal
|
|
|
1547
1644
|
hint: agents[a].skillsDir
|
|
1548
1645
|
}));
|
|
1549
1646
|
const selected = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.multiselect({
|
|
1550
|
-
message:
|
|
1647
|
+
message: `Select agents to install skills to ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('(Space to toggle, Enter to confirm)')}`,
|
|
1551
1648
|
options: agentChoices,
|
|
1552
1649
|
required: true,
|
|
1553
1650
|
initialValues: installedAgents
|
|
@@ -1721,6 +1818,23 @@ const installCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('instal
|
|
|
1721
1818
|
process.exit(1);
|
|
1722
1819
|
}
|
|
1723
1820
|
});
|
|
1821
|
+
const linkCmd = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('link').description('Link a local skill for development').argument('<path>', 'Path to local skill directory').option('-n, --name <name>', 'Custom skill name').action((localPath, options)=>{
|
|
1822
|
+
const skillManager = new SkillManager();
|
|
1823
|
+
try {
|
|
1824
|
+
const linked = skillManager.link(localPath, options.name);
|
|
1825
|
+
logger.log(`Linked skill available at: ${linked.path}`);
|
|
1826
|
+
} catch (error) {
|
|
1827
|
+
logger.error(error.message);
|
|
1828
|
+
process.exit(1);
|
|
1829
|
+
}
|
|
1830
|
+
});
|
|
1831
|
+
const unlinkCmd = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('unlink').description('Unlink a linked skill').argument('<skill>', 'Skill name to unlink').action((skillName)=>{
|
|
1832
|
+
const skillManager = new SkillManager();
|
|
1833
|
+
const result = skillManager.unlink(skillName);
|
|
1834
|
+
if (!result) process.exit(1);
|
|
1835
|
+
});
|
|
1836
|
+
const linkCommand = linkCmd;
|
|
1837
|
+
const unlinkCommand = unlinkCmd;
|
|
1724
1838
|
const listCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('list').alias('ls').description('List installed skills').option('-j, --json', 'Output as JSON').option('-g, --global', 'List globally installed skills').action((options)=>{
|
|
1725
1839
|
const isGlobal = options.global || false;
|
|
1726
1840
|
const skillManager = new SkillManager(void 0, {
|
|
@@ -1753,68 +1867,6 @@ const listCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('list').al
|
|
|
1753
1867
|
logger.newline();
|
|
1754
1868
|
logger.log(`Total: ${skills.length} skill(s)`);
|
|
1755
1869
|
});
|
|
1756
|
-
const infoCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('info').description('Show skill details').argument('<skill>', 'Skill name').option('-j, --json', 'Output as JSON').action((skillName, options)=>{
|
|
1757
|
-
const skillManager = new SkillManager();
|
|
1758
|
-
const info = skillManager.getInfo(skillName);
|
|
1759
|
-
if (options.json) {
|
|
1760
|
-
console.log(JSON.stringify(info, null, 2));
|
|
1761
|
-
return;
|
|
1762
|
-
}
|
|
1763
|
-
if (!info.installed && !info.config) {
|
|
1764
|
-
logger.error(`Skill ${skillName} not found`);
|
|
1765
|
-
process.exit(1);
|
|
1766
|
-
}
|
|
1767
|
-
logger.log(`Skill: ${skillName}`);
|
|
1768
|
-
logger.newline();
|
|
1769
|
-
if (info.config) {
|
|
1770
|
-
logger.log("Configuration (skills.json):");
|
|
1771
|
-
logger.log(` Reference: ${info.config}`);
|
|
1772
|
-
}
|
|
1773
|
-
if (info.locked) {
|
|
1774
|
-
logger.log("Locked Version (skills.lock):");
|
|
1775
|
-
logger.log(` Version: ${info.locked.version}`);
|
|
1776
|
-
logger.log(` Source: ${info.locked.source}`);
|
|
1777
|
-
logger.log(` Commit: ${info.locked.commit}`);
|
|
1778
|
-
logger.log(` Installed: ${info.locked.installedAt}`);
|
|
1779
|
-
}
|
|
1780
|
-
if (info.installed) {
|
|
1781
|
-
logger.log("Installed:");
|
|
1782
|
-
logger.log(` Path: ${info.installed.path}`);
|
|
1783
|
-
logger.log(` Version: ${info.installed.version}`);
|
|
1784
|
-
logger.log(` Linked: ${info.installed.isLinked ? 'Yes' : 'No'}`);
|
|
1785
|
-
if (info.installed.metadata) {
|
|
1786
|
-
const meta = info.installed.metadata;
|
|
1787
|
-
logger.log("Metadata (skill.json):");
|
|
1788
|
-
if (meta.description) logger.log(` Description: ${meta.description}`);
|
|
1789
|
-
if (meta.author) logger.log(` Author: ${meta.author}`);
|
|
1790
|
-
if (meta.license) logger.log(` License: ${meta.license}`);
|
|
1791
|
-
if (meta.keywords?.length) logger.log(` Keywords: ${meta.keywords.join(', ')}`);
|
|
1792
|
-
}
|
|
1793
|
-
} else logger.warn(`Skill ${skillName} is not installed`);
|
|
1794
|
-
});
|
|
1795
|
-
const updateCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('update').alias('up').description('Update installed skills').argument('[skill]', 'Skill name to update (updates all if not specified)').action(async (skill)=>{
|
|
1796
|
-
const configLoader = new ConfigLoader();
|
|
1797
|
-
if (!configLoader.exists()) {
|
|
1798
|
-
logger.error("skills.json not found. Run 'reskill init' first.");
|
|
1799
|
-
process.exit(1);
|
|
1800
|
-
}
|
|
1801
|
-
const skillManager = new SkillManager();
|
|
1802
|
-
const spinner = (0, __WEBPACK_EXTERNAL_MODULE_ora__["default"])(skill ? `Updating ${skill}...` : 'Updating all skills...').start();
|
|
1803
|
-
try {
|
|
1804
|
-
const updated = await skillManager.update(skill);
|
|
1805
|
-
spinner.stop();
|
|
1806
|
-
if (0 === updated.length) {
|
|
1807
|
-
logger.info('No skills to update');
|
|
1808
|
-
return;
|
|
1809
|
-
}
|
|
1810
|
-
logger.success(`Updated ${updated.length} skill(s):`);
|
|
1811
|
-
for (const s of updated)logger.log(` - ${s.name}@${s.version}`);
|
|
1812
|
-
} catch (error) {
|
|
1813
|
-
spinner.fail('Update failed');
|
|
1814
|
-
logger.error(error.message);
|
|
1815
|
-
process.exit(1);
|
|
1816
|
-
}
|
|
1817
|
-
});
|
|
1818
1870
|
const outdatedCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('outdated').description('Check for outdated skills').option('-j, --json', 'Output as JSON').action(async (options)=>{
|
|
1819
1871
|
const configLoader = new ConfigLoader();
|
|
1820
1872
|
if (!configLoader.exists()) {
|
|
@@ -1874,23 +1926,29 @@ const uninstallCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('unin
|
|
|
1874
1926
|
const result = skillManager.uninstall(skillName);
|
|
1875
1927
|
if (!result) process.exit(1);
|
|
1876
1928
|
});
|
|
1877
|
-
const
|
|
1929
|
+
const updateCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('update').alias('up').description('Update installed skills').argument('[skill]', 'Skill name to update (updates all if not specified)').action(async (skill)=>{
|
|
1930
|
+
const configLoader = new ConfigLoader();
|
|
1931
|
+
if (!configLoader.exists()) {
|
|
1932
|
+
logger.error("skills.json not found. Run 'reskill init' first.");
|
|
1933
|
+
process.exit(1);
|
|
1934
|
+
}
|
|
1878
1935
|
const skillManager = new SkillManager();
|
|
1936
|
+
const spinner = (0, __WEBPACK_EXTERNAL_MODULE_ora__["default"])(skill ? `Updating ${skill}...` : 'Updating all skills...').start();
|
|
1879
1937
|
try {
|
|
1880
|
-
const
|
|
1881
|
-
|
|
1938
|
+
const updated = await skillManager.update(skill);
|
|
1939
|
+
spinner.stop();
|
|
1940
|
+
if (0 === updated.length) {
|
|
1941
|
+
logger.info('No skills to update');
|
|
1942
|
+
return;
|
|
1943
|
+
}
|
|
1944
|
+
logger.success(`Updated ${updated.length} skill(s):`);
|
|
1945
|
+
for (const s of updated)logger.log(` - ${s.name}@${s.version}`);
|
|
1882
1946
|
} catch (error) {
|
|
1947
|
+
spinner.fail('Update failed');
|
|
1883
1948
|
logger.error(error.message);
|
|
1884
1949
|
process.exit(1);
|
|
1885
1950
|
}
|
|
1886
1951
|
});
|
|
1887
|
-
const unlinkCmd = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('unlink').description('Unlink a linked skill').argument('<skill>', 'Skill name to unlink').action((skillName)=>{
|
|
1888
|
-
const skillManager = new SkillManager();
|
|
1889
|
-
const result = skillManager.unlink(skillName);
|
|
1890
|
-
if (!result) process.exit(1);
|
|
1891
|
-
});
|
|
1892
|
-
const linkCommand = linkCmd;
|
|
1893
|
-
const unlinkCommand = unlinkCmd;
|
|
1894
1952
|
const program = new __WEBPACK_EXTERNAL_MODULE_commander__.Command();
|
|
1895
1953
|
program.name('reskill').description('AI Skills Package Manager - Git-based skills management for AI agents').version('0.1.0');
|
|
1896
1954
|
program.addCommand(initCommand);
|