skillpkg-mcp-server 0.1.0
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 +148 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +40 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +55 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +162 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/index.d.ts +21 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +35 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/install-skill.d.ts +8 -0
- package/dist/tools/install-skill.d.ts.map +1 -0
- package/dist/tools/install-skill.js +233 -0
- package/dist/tools/install-skill.js.map +1 -0
- package/dist/tools/list-skills.d.ts +8 -0
- package/dist/tools/list-skills.d.ts.map +1 -0
- package/dist/tools/list-skills.js +68 -0
- package/dist/tools/list-skills.js.map +1 -0
- package/dist/tools/load-skill.d.ts +8 -0
- package/dist/tools/load-skill.d.ts.map +1 -0
- package/dist/tools/load-skill.js +93 -0
- package/dist/tools/load-skill.js.map +1 -0
- package/dist/tools/recommend-skill.d.ts +8 -0
- package/dist/tools/recommend-skill.d.ts.map +1 -0
- package/dist/tools/recommend-skill.js +133 -0
- package/dist/tools/recommend-skill.js.map +1 -0
- package/dist/tools/search-registry.d.ts +8 -0
- package/dist/tools/search-registry.d.ts.map +1 -0
- package/dist/tools/search-registry.js +72 -0
- package/dist/tools/search-registry.js.map +1 -0
- package/dist/tools/search-skills.d.ts +8 -0
- package/dist/tools/search-skills.d.ts.map +1 -0
- package/dist/tools/search-skills.js +159 -0
- package/dist/tools/search-skills.js.map +1 -0
- package/dist/tools/skill-info.d.ts +8 -0
- package/dist/tools/skill-info.d.ts.map +1 -0
- package/dist/tools/skill-info.js +83 -0
- package/dist/tools/skill-info.js.map +1 -0
- package/dist/tools/uninstall-skill.d.ts +8 -0
- package/dist/tools/uninstall-skill.d.ts.map +1 -0
- package/dist/tools/uninstall-skill.js +60 -0
- package/dist/tools/uninstall-skill.js.map +1 -0
- package/dist/tools/utils.d.ts +57 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +151 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/types.d.ts +182 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +33 -0
- package/dist/types.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: install_skill
|
|
3
|
+
*
|
|
4
|
+
* Installs a skill from registry, GitHub, Gist, URL, or local path.
|
|
5
|
+
*/
|
|
6
|
+
import { getStore, getRegistryClient, successResult, errorResult, validateString, validateScope } from './utils.js';
|
|
7
|
+
import { InvalidSourceError } from '../types.js';
|
|
8
|
+
import { parse as parseSkillYaml } from 'skillpkg-core';
|
|
9
|
+
/**
|
|
10
|
+
* Parse source string to determine source type
|
|
11
|
+
*/
|
|
12
|
+
function parseSource(source) {
|
|
13
|
+
// GitHub: github:user/repo or user/repo
|
|
14
|
+
if (source.startsWith('github:')) {
|
|
15
|
+
return { type: 'github', value: source.slice(7) };
|
|
16
|
+
}
|
|
17
|
+
if (/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+$/.test(source)) {
|
|
18
|
+
return { type: 'github', value: source };
|
|
19
|
+
}
|
|
20
|
+
// Gist: gist:id
|
|
21
|
+
if (source.startsWith('gist:')) {
|
|
22
|
+
return { type: 'gist', value: source.slice(5) };
|
|
23
|
+
}
|
|
24
|
+
// URL: https:// or http://
|
|
25
|
+
if (source.startsWith('https://') || source.startsWith('http://')) {
|
|
26
|
+
return { type: 'url', value: source };
|
|
27
|
+
}
|
|
28
|
+
// Local path: starts with ./ or / or contains path separators
|
|
29
|
+
if (source.startsWith('./') || source.startsWith('/') || source.startsWith('../')) {
|
|
30
|
+
return { type: 'local', value: source };
|
|
31
|
+
}
|
|
32
|
+
// Registry: skill name (alphanumeric with hyphens)
|
|
33
|
+
if (/^[a-z][a-z0-9-]*$/.test(source)) {
|
|
34
|
+
return { type: 'registry', value: source };
|
|
35
|
+
}
|
|
36
|
+
throw new InvalidSourceError(source);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Fetch skill content from URL
|
|
40
|
+
*/
|
|
41
|
+
async function fetchSkillFromUrl(url) {
|
|
42
|
+
const response = await fetch(url, { redirect: 'follow' });
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error(`Failed to fetch from ${url}: ${response.status} ${response.statusText}`);
|
|
45
|
+
}
|
|
46
|
+
return response.text();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Fetch skill from GitHub repo (raw skill.yaml)
|
|
50
|
+
*/
|
|
51
|
+
async function fetchSkillFromGitHub(repo) {
|
|
52
|
+
// Try common locations for skill.yaml
|
|
53
|
+
const paths = ['skill.yaml', 'skill.yml', '.claude/skill.yaml'];
|
|
54
|
+
const branches = ['main', 'master'];
|
|
55
|
+
for (const branch of branches) {
|
|
56
|
+
for (const path of paths) {
|
|
57
|
+
const url = `https://raw.githubusercontent.com/${repo}/${branch}/${path}`;
|
|
58
|
+
try {
|
|
59
|
+
const content = await fetchSkillFromUrl(url);
|
|
60
|
+
return content;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Try next path/branch
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
throw new Error(`Could not find skill.yaml in repository ${repo}`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Fetch skill from Gist
|
|
71
|
+
*/
|
|
72
|
+
async function fetchSkillFromGist(gistId) {
|
|
73
|
+
const apiUrl = `https://api.github.com/gists/${gistId}`;
|
|
74
|
+
const response = await fetch(apiUrl);
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
throw new Error(`Failed to fetch gist ${gistId}: ${response.status}`);
|
|
77
|
+
}
|
|
78
|
+
const gist = (await response.json());
|
|
79
|
+
// Look for skill.yaml or skill.yml
|
|
80
|
+
for (const [filename, file] of Object.entries(gist.files)) {
|
|
81
|
+
if (filename === 'skill.yaml' || filename === 'skill.yml') {
|
|
82
|
+
return file.content;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
throw new Error(`No skill.yaml found in gist ${gistId}`);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Fetch skill from local path
|
|
89
|
+
*/
|
|
90
|
+
async function fetchSkillFromLocal(path) {
|
|
91
|
+
const fs = await import('fs/promises');
|
|
92
|
+
const nodePath = await import('path');
|
|
93
|
+
let skillPath = path;
|
|
94
|
+
const stat = await fs.stat(path);
|
|
95
|
+
if (stat.isDirectory()) {
|
|
96
|
+
// Look for skill.yaml in directory
|
|
97
|
+
const candidates = ['skill.yaml', 'skill.yml'];
|
|
98
|
+
for (const candidate of candidates) {
|
|
99
|
+
const fullPath = nodePath.join(path, candidate);
|
|
100
|
+
try {
|
|
101
|
+
await fs.access(fullPath);
|
|
102
|
+
skillPath = fullPath;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Try next
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return fs.readFile(skillPath, 'utf-8');
|
|
111
|
+
}
|
|
112
|
+
export function createInstallSkillHandler() {
|
|
113
|
+
return {
|
|
114
|
+
name: 'install_skill',
|
|
115
|
+
description: `Install a skill from various sources.
|
|
116
|
+
|
|
117
|
+
Supported source formats:
|
|
118
|
+
• Registry: skill-name (e.g., "commit-helper")
|
|
119
|
+
• GitHub: github:user/repo or user/repo (e.g., "anthropics/claude-code-skills")
|
|
120
|
+
• Gist: gist:id (e.g., "gist:abc123")
|
|
121
|
+
• URL: https://... (direct link to skill.yaml)
|
|
122
|
+
• Local: ./path or /absolute/path (local file or directory)`,
|
|
123
|
+
inputSchema: {
|
|
124
|
+
type: 'object',
|
|
125
|
+
properties: {
|
|
126
|
+
source: {
|
|
127
|
+
type: 'string',
|
|
128
|
+
description: 'Source to install from: skill-name, github:user/repo, gist:id, URL, or local path',
|
|
129
|
+
},
|
|
130
|
+
scope: {
|
|
131
|
+
type: 'string',
|
|
132
|
+
enum: ['local', 'global'],
|
|
133
|
+
default: 'local',
|
|
134
|
+
description: 'Where to install: local (project) or global (~/.skillpkg)',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
required: ['source'],
|
|
138
|
+
},
|
|
139
|
+
async execute(args) {
|
|
140
|
+
const input = args;
|
|
141
|
+
try {
|
|
142
|
+
const sourceStr = validateString(input.source, 'source');
|
|
143
|
+
const scope = validateScope(input.scope, 'local');
|
|
144
|
+
// Parse the source
|
|
145
|
+
const { type, value } = parseSource(sourceStr);
|
|
146
|
+
// Fetch skill content based on source type
|
|
147
|
+
let skillContent;
|
|
148
|
+
switch (type) {
|
|
149
|
+
case 'registry': {
|
|
150
|
+
// Download from registry
|
|
151
|
+
const client = getRegistryClient();
|
|
152
|
+
const info = await client.getSkillInfo(value);
|
|
153
|
+
// For now, fetch the skill.yaml URL if available
|
|
154
|
+
// In future, download tarball and extract
|
|
155
|
+
if (info.repository) {
|
|
156
|
+
skillContent = await fetchSkillFromGitHub(info.repository.replace('https://github.com/', ''));
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
throw new Error(`Registry skill "${value}" does not have a repository URL`);
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case 'github':
|
|
164
|
+
skillContent = await fetchSkillFromGitHub(value);
|
|
165
|
+
break;
|
|
166
|
+
case 'gist':
|
|
167
|
+
skillContent = await fetchSkillFromGist(value);
|
|
168
|
+
break;
|
|
169
|
+
case 'url':
|
|
170
|
+
skillContent = await fetchSkillFromUrl(value);
|
|
171
|
+
break;
|
|
172
|
+
case 'local':
|
|
173
|
+
skillContent = await fetchSkillFromLocal(value);
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
// Parse the skill content
|
|
177
|
+
const parseResult = parseSkillYaml(skillContent);
|
|
178
|
+
if (!parseResult.success || !parseResult.data) {
|
|
179
|
+
const errors = parseResult.errors?.map((e) => e.message).join(', ') || 'Unknown parse error';
|
|
180
|
+
return errorResult(`Invalid skill.yaml: ${errors}`);
|
|
181
|
+
}
|
|
182
|
+
const skill = parseResult.data;
|
|
183
|
+
// Get the store and initialize if needed
|
|
184
|
+
const store = getStore(scope);
|
|
185
|
+
if (!(await store.isInitialized())) {
|
|
186
|
+
await store.init();
|
|
187
|
+
}
|
|
188
|
+
// Check if already installed
|
|
189
|
+
if (await store.hasSkill(skill.name)) {
|
|
190
|
+
// Update instead of error
|
|
191
|
+
await store.updateSkill(skill.name, skill);
|
|
192
|
+
const output = {
|
|
193
|
+
success: true,
|
|
194
|
+
skill: {
|
|
195
|
+
id: `${scope}:${skill.name}`,
|
|
196
|
+
name: skill.name,
|
|
197
|
+
version: skill.version,
|
|
198
|
+
source: sourceStr,
|
|
199
|
+
installedAt: new Date().toISOString(),
|
|
200
|
+
},
|
|
201
|
+
message: `Updated "${skill.name}" to v${skill.version} in ${scope} scope.`,
|
|
202
|
+
};
|
|
203
|
+
return successResult(output.message);
|
|
204
|
+
}
|
|
205
|
+
// Add the skill
|
|
206
|
+
await store.addSkill(skill, {
|
|
207
|
+
source: type === 'local' ? 'local' : type === 'registry' ? 'registry' : 'import',
|
|
208
|
+
sourceUrl: sourceStr,
|
|
209
|
+
});
|
|
210
|
+
const output = {
|
|
211
|
+
success: true,
|
|
212
|
+
skill: {
|
|
213
|
+
id: `${scope}:${skill.name}`,
|
|
214
|
+
name: skill.name,
|
|
215
|
+
version: skill.version,
|
|
216
|
+
source: sourceStr,
|
|
217
|
+
installedAt: new Date().toISOString(),
|
|
218
|
+
},
|
|
219
|
+
message: `Successfully installed "${skill.name}" v${skill.version} to ${scope} scope.`,
|
|
220
|
+
};
|
|
221
|
+
return successResult(output.message);
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
if (error instanceof InvalidSourceError) {
|
|
225
|
+
return errorResult(error.message);
|
|
226
|
+
}
|
|
227
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
228
|
+
return errorResult(`Failed to install skill: ${message}`);
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=install-skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-skill.js","sourceRoot":"","sources":["../../src/tools/install-skill.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACpH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,eAAe,CAAC;AAExD;;GAEG;AACH,SAAS,WAAW,CAAC,MAAc;IACjC,wCAAwC;IACxC,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,CAAC;IACD,IAAI,mCAAmC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC3C,CAAC;IAED,gBAAgB;IAChB,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,CAAC;IAED,2BAA2B;IAC3B,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAClE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACxC,CAAC;IAED,8DAA8D;IAC9D,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAClF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC1C,CAAC;IAED,mDAAmD;IACnD,IAAI,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,iBAAiB,CAAC,GAAW;IAC1C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC1D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,KAAK,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,oBAAoB,CAAC,IAAY;IAC9C,sCAAsC;IACtC,MAAM,KAAK,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,oBAAoB,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEpC,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,qCAAqC,IAAI,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YAC1E,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBAC7C,OAAO,OAAO,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,uBAAuB;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,EAAE,CAAC,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,kBAAkB,CAAC,MAAc;IAC9C,MAAM,MAAM,GAAG,gCAAgC,MAAM,EAAE,CAAC;IACxD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;IAErC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,wBAAwB,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAElC,CAAC;IAEF,mCAAmC;IACnC,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,IAAI,QAAQ,KAAK,YAAY,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,mBAAmB,CAAC,IAAY;IAC7C,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IAEtC,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEjC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACvB,mCAAmC;QACnC,MAAM,UAAU,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;QAC/C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAChD,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC1B,SAAS,GAAG,QAAQ,CAAC;gBACrB,MAAM;YACR,CAAC;YAAC,MAAM,CAAC;gBACP,WAAW;YACb,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE;;;;;;;4DAO2C;QACxD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,mFAAmF;iBACjG;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;oBACzB,OAAO,EAAE,OAAO;oBAChB,WAAW,EAAE,2DAA2D;iBACzE;aACF;YACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;SACrB;QAED,KAAK,CAAC,OAAO,CAAC,IAAa;YACzB,MAAM,KAAK,GAAG,IAAyB,CAAC;YAExC,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACzD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAElD,mBAAmB;gBACnB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;gBAE/C,2CAA2C;gBAC3C,IAAI,YAAoB,CAAC;gBAEzB,QAAQ,IAAI,EAAE,CAAC;oBACb,KAAK,UAAU,CAAC,CAAC,CAAC;wBAChB,yBAAyB;wBACzB,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;wBACnC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;wBAC9C,iDAAiD;wBACjD,0CAA0C;wBAC1C,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;4BACpB,YAAY,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,CAAC;wBAChG,CAAC;6BAAM,CAAC;4BACN,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,kCAAkC,CAAC,CAAC;wBAC9E,CAAC;wBACD,MAAM;oBACR,CAAC;oBAED,KAAK,QAAQ;wBACX,YAAY,GAAG,MAAM,oBAAoB,CAAC,KAAK,CAAC,CAAC;wBACjD,MAAM;oBAER,KAAK,MAAM;wBACT,YAAY,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC;wBAC/C,MAAM;oBAER,KAAK,KAAK;wBACR,YAAY,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;wBAC9C,MAAM;oBAER,KAAK,OAAO;wBACV,YAAY,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,CAAC;wBAChD,MAAM;gBACV,CAAC;gBAED,0BAA0B;gBAC1B,MAAM,WAAW,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;gBACjD,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;oBAC9C,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,qBAAqB,CAAC;oBAC7F,OAAO,WAAW,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;gBACtD,CAAC;gBAED,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC;gBAE/B,yCAAyC;gBACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC9B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC;oBACnC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;gBACrB,CAAC;gBAED,6BAA6B;gBAC7B,IAAI,MAAM,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrC,0BAA0B;oBAC1B,MAAM,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;oBAE3C,MAAM,MAAM,GAAuB;wBACjC,OAAO,EAAE,IAAI;wBACb,KAAK,EAAE;4BACL,EAAE,EAAE,GAAG,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE;4BAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;4BAChB,OAAO,EAAE,KAAK,CAAC,OAAO;4BACtB,MAAM,EAAE,SAAS;4BACjB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;yBACtC;wBACD,OAAO,EAAE,YAAY,KAAK,CAAC,IAAI,SAAS,KAAK,CAAC,OAAO,OAAO,KAAK,SAAS;qBAC3E,CAAC;oBAEF,OAAO,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACvC,CAAC;gBAED,gBAAgB;gBAChB,MAAM,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE;oBAC1B,MAAM,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ;oBAChF,SAAS,EAAE,SAAS;iBACrB,CAAC,CAAC;gBAEH,MAAM,MAAM,GAAuB;oBACjC,OAAO,EAAE,IAAI;oBACb,KAAK,EAAE;wBACL,EAAE,EAAE,GAAG,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE;wBAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,OAAO,EAAE,KAAK,CAAC,OAAO;wBACtB,MAAM,EAAE,SAAS;wBACjB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;qBACtC;oBACD,OAAO,EAAE,2BAA2B,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,OAAO,OAAO,KAAK,SAAS;iBACvF,CAAC;gBAEF,OAAO,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,kBAAkB,EAAE,CAAC;oBACxC,OAAO,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACpC,CAAC;gBACD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,OAAO,WAAW,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-skills.d.ts","sourceRoot":"","sources":["../../src/tools/list-skills.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAwD,MAAM,aAAa,CAAC;AAGrG,wBAAgB,uBAAuB,IAAI,WAAW,CAwErD"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: list_skills
|
|
3
|
+
*
|
|
4
|
+
* Lists all installed skills in local or global scope.
|
|
5
|
+
*/
|
|
6
|
+
import { getStore, successResult, errorResult } from './utils.js';
|
|
7
|
+
export function createListSkillsHandler() {
|
|
8
|
+
return {
|
|
9
|
+
name: 'list_skills',
|
|
10
|
+
description: 'List all installed skills. Returns skill metadata including name, version, description, and installation date.',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
scope: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
enum: ['local', 'global', 'all'],
|
|
17
|
+
default: 'all',
|
|
18
|
+
description: 'Scope to list skills from: local (project), global (~/.skillpkg), or all',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
async execute(args) {
|
|
23
|
+
const input = args;
|
|
24
|
+
const scopeFilter = input.scope || 'all';
|
|
25
|
+
try {
|
|
26
|
+
const results = [];
|
|
27
|
+
// Get skills from requested scopes
|
|
28
|
+
const scopes = scopeFilter === 'all' ? ['local', 'global'] : [scopeFilter];
|
|
29
|
+
for (const scope of scopes) {
|
|
30
|
+
const store = getStore(scope);
|
|
31
|
+
// Initialize store if needed
|
|
32
|
+
if (!(await store.isInitialized())) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const skills = await store.listSkills();
|
|
36
|
+
for (const skill of skills) {
|
|
37
|
+
results.push({
|
|
38
|
+
id: `${scope}:${skill.name}`,
|
|
39
|
+
name: skill.name,
|
|
40
|
+
description: skill.description,
|
|
41
|
+
version: skill.version,
|
|
42
|
+
scope,
|
|
43
|
+
installedAt: skill.installedAt,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Sort by name
|
|
48
|
+
results.sort((a, b) => a.name.localeCompare(b.name));
|
|
49
|
+
// Format output
|
|
50
|
+
if (results.length === 0) {
|
|
51
|
+
return successResult('No skills installed. Use install_skill to add skills.');
|
|
52
|
+
}
|
|
53
|
+
let text = `Found ${results.length} installed skill(s):\n\n`;
|
|
54
|
+
for (const skill of results) {
|
|
55
|
+
text += `• ${skill.name} v${skill.version} [${skill.scope}]\n`;
|
|
56
|
+
text += ` ${skill.description}\n`;
|
|
57
|
+
text += ` Installed: ${new Date(skill.installedAt).toLocaleDateString()}\n\n`;
|
|
58
|
+
}
|
|
59
|
+
return successResult(text.trim());
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
63
|
+
return errorResult(`Failed to list skills: ${message}`);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=list-skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-skills.js","sourceRoot":"","sources":["../../src/tools/list-skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-skill.d.ts","sourceRoot":"","sources":["../../src/tools/load-skill.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAsD,MAAM,aAAa,CAAC;AAInG,wBAAgB,sBAAsB,IAAI,WAAW,CAgGpD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: load_skill
|
|
3
|
+
*
|
|
4
|
+
* Loads a skill's full content including instructions.
|
|
5
|
+
*/
|
|
6
|
+
import { getStore, successResult, errorResult, validateString } from './utils.js';
|
|
7
|
+
import { SkillNotInstalledError } from '../types.js';
|
|
8
|
+
export function createLoadSkillHandler() {
|
|
9
|
+
return {
|
|
10
|
+
name: 'load_skill',
|
|
11
|
+
description: 'Load a skill by ID and return its full content including instructions. The skill must be installed first.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
id: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'Skill ID in format "scope:name" (e.g., "local:commit-helper") or just "name" to search all scopes',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
required: ['id'],
|
|
21
|
+
},
|
|
22
|
+
async execute(args) {
|
|
23
|
+
const input = args;
|
|
24
|
+
try {
|
|
25
|
+
const id = validateString(input.id, 'id');
|
|
26
|
+
// Parse scope from ID
|
|
27
|
+
let scope;
|
|
28
|
+
let skillName;
|
|
29
|
+
if (id.includes(':')) {
|
|
30
|
+
const [scopePart, namePart] = id.split(':', 2);
|
|
31
|
+
if (scopePart === 'local' || scopePart === 'global') {
|
|
32
|
+
scope = scopePart;
|
|
33
|
+
skillName = namePart;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
skillName = id;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
skillName = id;
|
|
41
|
+
}
|
|
42
|
+
// Search for the skill
|
|
43
|
+
const scopesToCheck = scope ? [scope] : ['local', 'global'];
|
|
44
|
+
let foundSkill = null;
|
|
45
|
+
let foundScope = null;
|
|
46
|
+
for (const s of scopesToCheck) {
|
|
47
|
+
const store = getStore(s);
|
|
48
|
+
if (!(await store.isInitialized())) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const skill = await store.getSkill(skillName);
|
|
52
|
+
if (skill) {
|
|
53
|
+
foundSkill = skill;
|
|
54
|
+
foundScope = s;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!foundSkill || !foundScope) {
|
|
59
|
+
throw new SkillNotInstalledError(skillName);
|
|
60
|
+
}
|
|
61
|
+
const output = {
|
|
62
|
+
id: `${foundScope}:${foundSkill.name}`,
|
|
63
|
+
name: foundSkill.name,
|
|
64
|
+
version: foundSkill.version,
|
|
65
|
+
description: foundSkill.description,
|
|
66
|
+
instructions: foundSkill.instructions,
|
|
67
|
+
author: typeof foundSkill.author === 'string'
|
|
68
|
+
? { name: foundSkill.author }
|
|
69
|
+
: foundSkill.author,
|
|
70
|
+
};
|
|
71
|
+
// Format output with instructions
|
|
72
|
+
let text = `# ${output.name} v${output.version}\n\n`;
|
|
73
|
+
text += `${output.description}\n\n`;
|
|
74
|
+
if (output.author) {
|
|
75
|
+
text += `Author: ${output.author.name}`;
|
|
76
|
+
if (output.author.email)
|
|
77
|
+
text += ` <${output.author.email}>`;
|
|
78
|
+
text += '\n\n';
|
|
79
|
+
}
|
|
80
|
+
text += `---\n\n## Instructions\n\n${output.instructions}`;
|
|
81
|
+
return successResult(text);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error instanceof SkillNotInstalledError) {
|
|
85
|
+
return errorResult(error.message, 'Use search_skills to find and install_skill to install it.');
|
|
86
|
+
}
|
|
87
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
88
|
+
return errorResult(`Failed to load skill: ${message}`);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=load-skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-skill.js","sourceRoot":"","sources":["../../src/tools/load-skill.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,WAAW,EACT,2GAA2G;QAC7G,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,EAAE,EAAE;oBACF,IAAI,EAAE,QAAQ;oBACd,WAAW,EACT,mGAAmG;iBACtG;aACF;YACD,QAAQ,EAAE,CAAC,IAAI,CAAC;SACjB;QAED,KAAK,CAAC,OAAO,CAAC,IAAa;YACzB,MAAM,KAAK,GAAG,IAAsB,CAAC;YAErC,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gBAE1C,sBAAsB;gBACtB,IAAI,KAAwB,CAAC;gBAC7B,IAAI,SAAiB,CAAC;gBAEtB,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBACrB,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;oBAC/C,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;wBACpD,KAAK,GAAG,SAAS,CAAC;wBAClB,SAAS,GAAG,QAAQ,CAAC;oBACvB,CAAC;yBAAM,CAAC;wBACN,SAAS,GAAG,EAAE,CAAC;oBACjB,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,SAAS,GAAG,EAAE,CAAC;gBACjB,CAAC;gBAED,uBAAuB;gBACvB,MAAM,aAAa,GAAY,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBACrE,IAAI,UAAU,GAAG,IAAI,CAAC;gBACtB,IAAI,UAAU,GAAiB,IAAI,CAAC;gBAEpC,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;oBAC9B,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;oBAC1B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC;wBACnC,SAAS;oBACX,CAAC;oBAED,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;oBAC9C,IAAI,KAAK,EAAE,CAAC;wBACV,UAAU,GAAG,KAAK,CAAC;wBACnB,UAAU,GAAG,CAAC,CAAC;wBACf,MAAM;oBACR,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,EAAE,CAAC;oBAC/B,MAAM,IAAI,sBAAsB,CAAC,SAAS,CAAC,CAAC;gBAC9C,CAAC;gBAED,MAAM,MAAM,GAAoB;oBAC9B,EAAE,EAAE,GAAG,UAAU,IAAI,UAAU,CAAC,IAAI,EAAE;oBACtC,IAAI,EAAE,UAAU,CAAC,IAAI;oBACrB,OAAO,EAAE,UAAU,CAAC,OAAO;oBAC3B,WAAW,EAAE,UAAU,CAAC,WAAW;oBACnC,YAAY,EAAE,UAAU,CAAC,YAAY;oBACrC,MAAM,EACJ,OAAO,UAAU,CAAC,MAAM,KAAK,QAAQ;wBACnC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE;wBAC7B,CAAC,CAAC,UAAU,CAAC,MAAM;iBACxB,CAAC;gBAEF,kCAAkC;gBAClC,IAAI,IAAI,GAAG,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,MAAM,CAAC;gBACrD,IAAI,IAAI,GAAG,MAAM,CAAC,WAAW,MAAM,CAAC;gBAEpC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBAClB,IAAI,IAAI,WAAW,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;oBACxC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK;wBAAE,IAAI,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC;oBAC7D,IAAI,IAAI,MAAM,CAAC;gBACjB,CAAC;gBAED,IAAI,IAAI,6BAA6B,MAAM,CAAC,YAAY,EAAE,CAAC;gBAE3D,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;oBAC5C,OAAO,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,4DAA4D,CAAC,CAAC;gBAClG,CAAC;gBACD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,OAAO,WAAW,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommend-skill.d.ts","sourceRoot":"","sources":["../../src/tools/recommend-skill.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,WAAW,EAOZ,MAAM,aAAa,CAAC;AAGrB,wBAAgB,2BAA2B,IAAI,WAAW,CAuJzD"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: recommend_skill
|
|
3
|
+
*
|
|
4
|
+
* Recommends the best skill for a given use case.
|
|
5
|
+
*/
|
|
6
|
+
import { getRegistryClient, successResult, errorResult, validateString, calculateRelevanceScore } from './utils.js';
|
|
7
|
+
export function createRecommendSkillHandler() {
|
|
8
|
+
return {
|
|
9
|
+
name: 'recommend_skill',
|
|
10
|
+
description: 'Get a skill recommendation for a specific use case. Returns the best matching skill with reasoning and alternatives.',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
query: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Describe what you need (e.g., "help with git commits", "code review")',
|
|
17
|
+
},
|
|
18
|
+
criteria: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
enum: ['auto', 'popular', 'highest_rated', 'newest'],
|
|
21
|
+
default: 'auto',
|
|
22
|
+
description: 'Recommendation criteria: auto (balanced), popular, highest_rated, or newest',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
required: ['query'],
|
|
26
|
+
},
|
|
27
|
+
async execute(args) {
|
|
28
|
+
const input = args;
|
|
29
|
+
try {
|
|
30
|
+
const query = validateString(input.query, 'query');
|
|
31
|
+
const criteria = input.criteria || 'auto';
|
|
32
|
+
const client = getRegistryClient();
|
|
33
|
+
// Search for relevant skills
|
|
34
|
+
const searchResult = await client.search(query, { limit: 10 });
|
|
35
|
+
if (searchResult.results.length === 0) {
|
|
36
|
+
return successResult(`No skills found matching "${query}". Try a different search term or browse available skills with search_registry.`);
|
|
37
|
+
}
|
|
38
|
+
const scoredSkills = searchResult.results.map((skill) => {
|
|
39
|
+
let score = calculateRelevanceScore({
|
|
40
|
+
name: skill.name,
|
|
41
|
+
description: skill.description,
|
|
42
|
+
downloads: skill.downloads,
|
|
43
|
+
updatedAt: skill.updatedAt,
|
|
44
|
+
tags: skill.keywords,
|
|
45
|
+
}, query);
|
|
46
|
+
// Adjust score based on criteria
|
|
47
|
+
switch (criteria) {
|
|
48
|
+
case 'popular':
|
|
49
|
+
score = (skill.downloads || 0) / 1000 + score * 0.3;
|
|
50
|
+
break;
|
|
51
|
+
case 'highest_rated':
|
|
52
|
+
// Rating not available yet, use downloads as proxy
|
|
53
|
+
score = Math.log10((skill.downloads || 0) + 1) * 10 + score * 0.3;
|
|
54
|
+
break;
|
|
55
|
+
case 'newest':
|
|
56
|
+
if (skill.updatedAt) {
|
|
57
|
+
const daysSinceUpdate = Math.floor((Date.now() - new Date(skill.updatedAt).getTime()) / (1000 * 60 * 60 * 24));
|
|
58
|
+
score = Math.max(0, 100 - daysSinceUpdate) + score * 0.3;
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
// 'auto' uses the default balanced scoring
|
|
62
|
+
}
|
|
63
|
+
return { skill, score };
|
|
64
|
+
});
|
|
65
|
+
scoredSkills.sort((a, b) => b.score - a.score);
|
|
66
|
+
// Get top recommendation
|
|
67
|
+
const topSkill = scoredSkills[0].skill;
|
|
68
|
+
const recommendation = {
|
|
69
|
+
id: topSkill.name,
|
|
70
|
+
name: topSkill.name,
|
|
71
|
+
description: topSkill.description,
|
|
72
|
+
version: topSkill.version,
|
|
73
|
+
rating: 0, // Not available yet
|
|
74
|
+
downloads: topSkill.downloads || 0,
|
|
75
|
+
updatedAt: topSkill.updatedAt || new Date().toISOString(),
|
|
76
|
+
author: topSkill.author || 'Unknown',
|
|
77
|
+
tags: topSkill.keywords || [],
|
|
78
|
+
};
|
|
79
|
+
// Get alternatives (next 3)
|
|
80
|
+
const alternatives = scoredSkills.slice(1, 4).map((item) => ({
|
|
81
|
+
name: item.skill.name,
|
|
82
|
+
description: item.skill.description,
|
|
83
|
+
rating: 0, // Not available yet
|
|
84
|
+
}));
|
|
85
|
+
// Generate reason based on criteria
|
|
86
|
+
let reason = `"${recommendation.name}" is recommended because `;
|
|
87
|
+
switch (criteria) {
|
|
88
|
+
case 'popular':
|
|
89
|
+
reason += `it's the most popular skill (${recommendation.downloads} downloads) that matches your needs.`;
|
|
90
|
+
break;
|
|
91
|
+
case 'highest_rated':
|
|
92
|
+
reason += `it has the highest rating (${recommendation.rating.toFixed(1)}⭐) among matching skills.`;
|
|
93
|
+
break;
|
|
94
|
+
case 'newest':
|
|
95
|
+
reason += `it was recently updated and matches your requirements.`;
|
|
96
|
+
break;
|
|
97
|
+
default:
|
|
98
|
+
reason += `it best matches "${query}" based on name, description, popularity, and rating.`;
|
|
99
|
+
}
|
|
100
|
+
const output = {
|
|
101
|
+
recommendation,
|
|
102
|
+
reason,
|
|
103
|
+
alternatives,
|
|
104
|
+
installCommand: `install_skill source: "${recommendation.name}"`,
|
|
105
|
+
};
|
|
106
|
+
// Format output
|
|
107
|
+
let text = `## Recommended Skill\n\n`;
|
|
108
|
+
text += `**${recommendation.name}** v${recommendation.version}\n`;
|
|
109
|
+
text += `${recommendation.description}\n\n`;
|
|
110
|
+
text += `⭐ ${recommendation.rating.toFixed(1)} | 📥 ${recommendation.downloads} downloads\n`;
|
|
111
|
+
text += `Author: ${recommendation.author}\n`;
|
|
112
|
+
if (recommendation.tags.length > 0) {
|
|
113
|
+
text += `Tags: ${recommendation.tags.join(', ')}\n`;
|
|
114
|
+
}
|
|
115
|
+
text += `\n**Why this skill?**\n${reason}\n`;
|
|
116
|
+
if (alternatives.length > 0) {
|
|
117
|
+
text += `\n## Alternatives\n\n`;
|
|
118
|
+
for (const alt of alternatives) {
|
|
119
|
+
text += `• **${alt.name}** (⭐${alt.rating.toFixed(1)})\n`;
|
|
120
|
+
text += ` ${alt.description}\n\n`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
text += `\n---\n\nTo install: ${output.installCommand}`;
|
|
124
|
+
return successResult(text);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
128
|
+
return errorResult(`Recommendation failed: ${message}`);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=recommend-skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommend-skill.js","sourceRoot":"","sources":["../../src/tools/recommend-skill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-registry.d.ts","sourceRoot":"","sources":["../../src/tools/search-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAyD,MAAM,aAAa,CAAC;AAItG,wBAAgB,2BAA2B,IAAI,WAAW,CA6EzD"}
|