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,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: search_registry
|
|
3
|
+
*
|
|
4
|
+
* Searches the skill registry only (no local search).
|
|
5
|
+
*/
|
|
6
|
+
import { getRegistryClient, successResult, errorResult, validateString, validateLimit } from './utils.js';
|
|
7
|
+
import { RegistryUnavailableError } from '../types.js';
|
|
8
|
+
export function createSearchRegistryHandler() {
|
|
9
|
+
return {
|
|
10
|
+
name: 'search_registry',
|
|
11
|
+
description: 'Search the skill registry for available skills. Returns skills from the remote registry only.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
query: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'Search query to find skills',
|
|
18
|
+
},
|
|
19
|
+
limit: {
|
|
20
|
+
type: 'number',
|
|
21
|
+
default: 20,
|
|
22
|
+
description: 'Maximum number of results (1-100)',
|
|
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 limit = validateLimit(input.limit, 20, 100);
|
|
32
|
+
const client = getRegistryClient();
|
|
33
|
+
// Check if registry is reachable
|
|
34
|
+
const isReachable = await client.ping();
|
|
35
|
+
if (!isReachable) {
|
|
36
|
+
throw new RegistryUnavailableError();
|
|
37
|
+
}
|
|
38
|
+
const searchResult = await client.search(query, { limit });
|
|
39
|
+
const output = {
|
|
40
|
+
results: searchResult.results.map((skill) => ({
|
|
41
|
+
name: skill.name,
|
|
42
|
+
description: skill.description,
|
|
43
|
+
version: skill.version,
|
|
44
|
+
author: skill.author || 'Unknown',
|
|
45
|
+
downloads: skill.downloads || 0,
|
|
46
|
+
})),
|
|
47
|
+
total: searchResult.total,
|
|
48
|
+
};
|
|
49
|
+
// Format output
|
|
50
|
+
if (output.results.length === 0) {
|
|
51
|
+
return successResult(`No skills found in registry for "${query}".`);
|
|
52
|
+
}
|
|
53
|
+
let text = `Registry search for "${query}" (${output.total} results):\n\n`;
|
|
54
|
+
for (const skill of output.results) {
|
|
55
|
+
text += `• ${skill.name} v${skill.version}\n`;
|
|
56
|
+
text += ` ${skill.description}\n`;
|
|
57
|
+
text += ` Author: ${skill.author} | Downloads: ${skill.downloads}\n\n`;
|
|
58
|
+
}
|
|
59
|
+
text += `\nTo install: use install_skill with the skill name.`;
|
|
60
|
+
return successResult(text.trim());
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof RegistryUnavailableError) {
|
|
64
|
+
return errorResult('Registry is currently unavailable.', 'Try again later or use list_skills to see locally installed skills.');
|
|
65
|
+
}
|
|
66
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
67
|
+
return errorResult(`Registry search failed: ${message}`);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=search-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-registry.js","sourceRoot":"","sources":["../../src/tools/search-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-skills.d.ts","sourceRoot":"","sources":["../../src/tools/search-skills.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,WAAW,EAKZ,MAAM,aAAa,CAAC;AAYrB,wBAAgB,yBAAyB,IAAI,WAAW,CAqLvD"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: search_skills
|
|
3
|
+
*
|
|
4
|
+
* Searches for skills in local store and/or registry.
|
|
5
|
+
*/
|
|
6
|
+
import { getStore, getRegistryClient, successResult, errorResult, validateString, validateLimit, calculateRelevanceScore, } from './utils.js';
|
|
7
|
+
export function createSearchSkillsHandler() {
|
|
8
|
+
return {
|
|
9
|
+
name: 'search_skills',
|
|
10
|
+
description: 'Search for skills by keyword. Searches both installed skills and the registry, returning results sorted by relevance.',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
query: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Search query (matches name, description, and tags)',
|
|
17
|
+
},
|
|
18
|
+
source: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
enum: ['all', 'local', 'registry'],
|
|
21
|
+
default: 'all',
|
|
22
|
+
description: 'Where to search: all, local (installed only), or registry (remote only)',
|
|
23
|
+
},
|
|
24
|
+
limit: {
|
|
25
|
+
type: 'number',
|
|
26
|
+
default: 20,
|
|
27
|
+
description: 'Maximum number of results to return (1-100)',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
required: ['query'],
|
|
31
|
+
},
|
|
32
|
+
async execute(args) {
|
|
33
|
+
const input = args;
|
|
34
|
+
try {
|
|
35
|
+
const query = validateString(input.query, 'query');
|
|
36
|
+
const source = input.source || 'all';
|
|
37
|
+
const limit = validateLimit(input.limit, 20, 100);
|
|
38
|
+
const results = [];
|
|
39
|
+
const installedNames = new Set();
|
|
40
|
+
// Search local stores
|
|
41
|
+
if (source === 'all' || source === 'local') {
|
|
42
|
+
const scopes = ['local', 'global'];
|
|
43
|
+
for (const scope of scopes) {
|
|
44
|
+
const store = getStore(scope);
|
|
45
|
+
if (!(await store.isInitialized())) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const skills = await store.listSkills();
|
|
49
|
+
const queryLower = query.toLowerCase();
|
|
50
|
+
for (const skill of skills) {
|
|
51
|
+
// Simple text matching
|
|
52
|
+
const nameMatch = skill.name.toLowerCase().includes(queryLower);
|
|
53
|
+
const descMatch = skill.description.toLowerCase().includes(queryLower);
|
|
54
|
+
if (nameMatch || descMatch) {
|
|
55
|
+
installedNames.add(skill.name);
|
|
56
|
+
results.push({
|
|
57
|
+
id: `${scope}:${skill.name}`,
|
|
58
|
+
name: skill.name,
|
|
59
|
+
description: skill.description,
|
|
60
|
+
version: skill.version,
|
|
61
|
+
source: 'local',
|
|
62
|
+
installed: true,
|
|
63
|
+
rating: 0, // Local skills don't have ratings
|
|
64
|
+
downloads: 0,
|
|
65
|
+
updatedAt: skill.installedAt,
|
|
66
|
+
tags: [],
|
|
67
|
+
relevanceScore: calculateRelevanceScore({
|
|
68
|
+
name: skill.name,
|
|
69
|
+
description: skill.description,
|
|
70
|
+
updatedAt: skill.installedAt,
|
|
71
|
+
}, query),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Search registry
|
|
78
|
+
if (source === 'all' || source === 'registry') {
|
|
79
|
+
try {
|
|
80
|
+
const client = getRegistryClient();
|
|
81
|
+
const searchResult = await client.search(query, { limit });
|
|
82
|
+
for (const skill of searchResult.results) {
|
|
83
|
+
const isInstalled = installedNames.has(skill.name);
|
|
84
|
+
// Skip if already in results from local
|
|
85
|
+
if (isInstalled && source === 'all') {
|
|
86
|
+
// Update existing entry with registry metadata
|
|
87
|
+
const existing = results.find((r) => r.name === skill.name);
|
|
88
|
+
if (existing) {
|
|
89
|
+
existing.downloads = skill.downloads || 0;
|
|
90
|
+
existing.tags = skill.keywords || [];
|
|
91
|
+
}
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
results.push({
|
|
95
|
+
id: `registry:${skill.name}`,
|
|
96
|
+
name: skill.name,
|
|
97
|
+
description: skill.description,
|
|
98
|
+
version: skill.version,
|
|
99
|
+
source: 'registry',
|
|
100
|
+
installed: isInstalled,
|
|
101
|
+
rating: 0, // Registry doesn't have ratings yet
|
|
102
|
+
downloads: skill.downloads || 0,
|
|
103
|
+
updatedAt: skill.updatedAt || new Date().toISOString(),
|
|
104
|
+
tags: skill.keywords || [],
|
|
105
|
+
relevanceScore: calculateRelevanceScore({
|
|
106
|
+
name: skill.name,
|
|
107
|
+
description: skill.description,
|
|
108
|
+
downloads: skill.downloads,
|
|
109
|
+
updatedAt: skill.updatedAt,
|
|
110
|
+
tags: skill.keywords,
|
|
111
|
+
}, query),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// Registry might be unavailable, continue with local results
|
|
117
|
+
if (source === 'registry') {
|
|
118
|
+
return errorResult('Registry is currently unavailable.', 'Try searching with source: "local" to see installed skills.');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Sort by relevance score (descending)
|
|
123
|
+
results.sort((a, b) => b.relevanceScore - a.relevanceScore);
|
|
124
|
+
// Apply limit
|
|
125
|
+
const limitedResults = results.slice(0, limit);
|
|
126
|
+
const output = {
|
|
127
|
+
results: limitedResults,
|
|
128
|
+
total: results.length,
|
|
129
|
+
query,
|
|
130
|
+
};
|
|
131
|
+
// Format output
|
|
132
|
+
if (limitedResults.length === 0) {
|
|
133
|
+
return successResult(`No skills found for "${query}".`);
|
|
134
|
+
}
|
|
135
|
+
let text = `Found ${output.total} skill(s) for "${query}":\n\n`;
|
|
136
|
+
for (const skill of limitedResults) {
|
|
137
|
+
const installed = skill.installed ? ' [installed]' : '';
|
|
138
|
+
const rating = skill.rating > 0 ? ` ⭐${skill.rating.toFixed(1)}` : '';
|
|
139
|
+
const downloads = skill.downloads > 0 ? ` 📥${skill.downloads}` : '';
|
|
140
|
+
text += `• ${skill.name} v${skill.version}${installed}${rating}${downloads}\n`;
|
|
141
|
+
text += ` ${skill.description}\n`;
|
|
142
|
+
if (skill.tags.length > 0) {
|
|
143
|
+
text += ` Tags: ${skill.tags.join(', ')}\n`;
|
|
144
|
+
}
|
|
145
|
+
text += '\n';
|
|
146
|
+
}
|
|
147
|
+
if (output.total > limit) {
|
|
148
|
+
text += `Showing ${limit} of ${output.total} results.`;
|
|
149
|
+
}
|
|
150
|
+
return successResult(text.trim());
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
154
|
+
return errorResult(`Search failed: ${message}`);
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=search-skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-skills.js","sourceRoot":"","sources":["../../src/tools/search-skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-info.d.ts","sourceRoot":"","sources":["../../src/tools/skill-info.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAuD,MAAM,aAAa,CAAC;AAIpG,wBAAgB,sBAAsB,IAAI,WAAW,CAwFpD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: skill_info
|
|
3
|
+
*
|
|
4
|
+
* Gets detailed information about a skill from the registry.
|
|
5
|
+
*/
|
|
6
|
+
import { getRegistryClient, successResult, errorResult, validateString } from './utils.js';
|
|
7
|
+
import { SkillNotFoundError } from '../types.js';
|
|
8
|
+
export function createSkillInfoHandler() {
|
|
9
|
+
return {
|
|
10
|
+
name: 'skill_info',
|
|
11
|
+
description: 'Get detailed information about a skill from the registry, including versions, readme, and metadata.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
name: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'Name of the skill to get information about',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
required: ['name'],
|
|
21
|
+
},
|
|
22
|
+
async execute(args) {
|
|
23
|
+
const input = args;
|
|
24
|
+
try {
|
|
25
|
+
const skillName = validateString(input.name, 'name');
|
|
26
|
+
const client = getRegistryClient();
|
|
27
|
+
let skillInfo;
|
|
28
|
+
try {
|
|
29
|
+
skillInfo = await client.getSkillInfo(skillName);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
const message = error instanceof Error ? error.message : '';
|
|
33
|
+
if (message.includes('404') || message.includes('not found')) {
|
|
34
|
+
throw new SkillNotFoundError(skillName);
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
const author = typeof skillInfo.author === 'string'
|
|
39
|
+
? { name: skillInfo.author }
|
|
40
|
+
: skillInfo.author || { name: 'Unknown' };
|
|
41
|
+
const output = {
|
|
42
|
+
name: skillInfo.name,
|
|
43
|
+
description: skillInfo.description,
|
|
44
|
+
version: skillInfo.version,
|
|
45
|
+
author,
|
|
46
|
+
repository: skillInfo.repository,
|
|
47
|
+
license: skillInfo.license,
|
|
48
|
+
tags: skillInfo.keywords,
|
|
49
|
+
};
|
|
50
|
+
// Format detailed output
|
|
51
|
+
let text = `# ${output.name}\n\n`;
|
|
52
|
+
text += `**Version:** ${output.version}\n`;
|
|
53
|
+
text += `**Author:** ${output.author.name}`;
|
|
54
|
+
if (output.author.email)
|
|
55
|
+
text += ` <${output.author.email}>`;
|
|
56
|
+
if (output.author.url)
|
|
57
|
+
text += ` (${output.author.url})`;
|
|
58
|
+
text += '\n';
|
|
59
|
+
if (output.license) {
|
|
60
|
+
text += `**License:** ${output.license}\n`;
|
|
61
|
+
}
|
|
62
|
+
if (output.repository) {
|
|
63
|
+
text += `**Repository:** ${output.repository}\n`;
|
|
64
|
+
}
|
|
65
|
+
if (output.tags && output.tags.length > 0) {
|
|
66
|
+
text += `**Tags:** ${output.tags.join(', ')}\n`;
|
|
67
|
+
}
|
|
68
|
+
text += '\n---\n\n';
|
|
69
|
+
text += `${output.description}\n`;
|
|
70
|
+
text += `\n\n---\n\nTo install: install_skill source: "${skillName}"`;
|
|
71
|
+
return successResult(text);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (error instanceof SkillNotFoundError) {
|
|
75
|
+
return errorResult(`Skill "${input.name}" not found in registry.`, 'Use search_registry to find available skills.');
|
|
76
|
+
}
|
|
77
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
78
|
+
return errorResult(`Failed to get skill info: ${message}`);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=skill-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-info.js","sourceRoot":"","sources":["../../src/tools/skill-info.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstall-skill.d.ts","sourceRoot":"","sources":["../../src/tools/uninstall-skill.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAyD,MAAM,aAAa,CAAC;AAGtG,wBAAgB,2BAA2B,IAAI,WAAW,CAkEzD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: uninstall_skill
|
|
3
|
+
*
|
|
4
|
+
* Removes an installed skill.
|
|
5
|
+
*/
|
|
6
|
+
import { getStore, successResult, errorResult, validateString, validateScope } from './utils.js';
|
|
7
|
+
export function createUninstallSkillHandler() {
|
|
8
|
+
return {
|
|
9
|
+
name: 'uninstall_skill',
|
|
10
|
+
description: 'Uninstall a skill by name. Removes it from the specified scope.',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
id: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Name of the skill to uninstall',
|
|
17
|
+
},
|
|
18
|
+
scope: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
enum: ['local', 'global'],
|
|
21
|
+
default: 'local',
|
|
22
|
+
description: 'Scope to uninstall from: local (project) or global (~/.skillpkg)',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
required: ['id'],
|
|
26
|
+
},
|
|
27
|
+
async execute(args) {
|
|
28
|
+
const input = args;
|
|
29
|
+
try {
|
|
30
|
+
const skillName = validateString(input.id, 'id');
|
|
31
|
+
const scope = validateScope(input.scope, 'local');
|
|
32
|
+
const store = getStore(scope);
|
|
33
|
+
// Check if store is initialized
|
|
34
|
+
if (!(await store.isInitialized())) {
|
|
35
|
+
return errorResult(`No skills installed in ${scope} scope.`, 'Use list_skills to see installed skills.');
|
|
36
|
+
}
|
|
37
|
+
// Check if skill exists
|
|
38
|
+
const exists = await store.hasSkill(skillName);
|
|
39
|
+
if (!exists) {
|
|
40
|
+
return errorResult(`Skill "${skillName}" is not installed in ${scope} scope.`, 'Use list_skills to see installed skills.');
|
|
41
|
+
}
|
|
42
|
+
// Remove the skill
|
|
43
|
+
const removed = await store.removeSkill(skillName);
|
|
44
|
+
if (!removed) {
|
|
45
|
+
return errorResult(`Failed to uninstall skill "${skillName}".`);
|
|
46
|
+
}
|
|
47
|
+
const output = {
|
|
48
|
+
success: true,
|
|
49
|
+
message: `Successfully uninstalled "${skillName}" from ${scope} scope.`,
|
|
50
|
+
};
|
|
51
|
+
return successResult(output.message);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
55
|
+
return errorResult(`Failed to uninstall skill: ${message}`);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=uninstall-skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstall-skill.js","sourceRoot":"","sources":["../../src/tools/uninstall-skill.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjG,MAAM,UAAU,2BAA2B;IACzC,OAAO;QACL,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,iEAAiE;QAC9E,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,EAAE,EAAE;oBACF,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,gCAAgC;iBAC9C;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;oBACzB,OAAO,EAAE,OAAO;oBAChB,WAAW,EAAE,kEAAkE;iBAChF;aACF;YACD,QAAQ,EAAE,CAAC,IAAI,CAAC;SACjB;QAED,KAAK,CAAC,OAAO,CAAC,IAAa;YACzB,MAAM,KAAK,GAAG,IAA2B,CAAC;YAE1C,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gBACjD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAElD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAE9B,gCAAgC;gBAChC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC;oBACnC,OAAO,WAAW,CAChB,0BAA0B,KAAK,SAAS,EACxC,0CAA0C,CAC3C,CAAC;gBACJ,CAAC;gBAED,wBAAwB;gBACxB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,OAAO,WAAW,CAChB,UAAU,SAAS,yBAAyB,KAAK,SAAS,EAC1D,0CAA0C,CAC3C,CAAC;gBACJ,CAAC;gBAED,mBAAmB;gBACnB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;gBAEnD,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,WAAW,CAAC,8BAA8B,SAAS,IAAI,CAAC,CAAC;gBAClE,CAAC;gBAED,MAAM,MAAM,GAAyB;oBACnC,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,6BAA6B,SAAS,UAAU,KAAK,SAAS;iBACxE,CAAC;gBAEF,OAAO,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,OAAO,WAAW,CAAC,8BAA8B,OAAO,EAAE,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool utilities - shared helpers for tool handlers
|
|
3
|
+
*/
|
|
4
|
+
import { type StoreManager, type RegistryClient } from 'skillpkg-core';
|
|
5
|
+
import type { ToolResult, Scope } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Get the appropriate store based on scope
|
|
8
|
+
*/
|
|
9
|
+
export declare function getStore(scope: Scope, projectPath?: string): StoreManager;
|
|
10
|
+
/**
|
|
11
|
+
* Get registry client
|
|
12
|
+
*/
|
|
13
|
+
export declare function getRegistryClient(): RegistryClient;
|
|
14
|
+
/**
|
|
15
|
+
* Create a success result
|
|
16
|
+
*/
|
|
17
|
+
export declare function successResult(data: unknown): ToolResult;
|
|
18
|
+
/**
|
|
19
|
+
* Create an error result
|
|
20
|
+
*/
|
|
21
|
+
export declare function errorResult(message: string, suggestion?: string): ToolResult;
|
|
22
|
+
/**
|
|
23
|
+
* Validate required string parameter
|
|
24
|
+
*/
|
|
25
|
+
export declare function validateString(value: unknown, name: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Validate optional string parameter
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateOptionalString(value: unknown): string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Validate scope parameter
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateScope(value: unknown, defaultValue?: Scope): Scope;
|
|
34
|
+
/**
|
|
35
|
+
* Validate limit parameter
|
|
36
|
+
*/
|
|
37
|
+
export declare function validateLimit(value: unknown, defaultValue?: number, max?: number): number;
|
|
38
|
+
/**
|
|
39
|
+
* Calculate text match score (0-1)
|
|
40
|
+
*/
|
|
41
|
+
export declare function calculateTextMatch(_text: string, query: string, fields: {
|
|
42
|
+
name?: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
tags?: string[];
|
|
45
|
+
}): number;
|
|
46
|
+
/**
|
|
47
|
+
* Calculate relevance score for a skill
|
|
48
|
+
*/
|
|
49
|
+
export declare function calculateRelevanceScore(skill: {
|
|
50
|
+
name: string;
|
|
51
|
+
description: string;
|
|
52
|
+
tags?: string[];
|
|
53
|
+
rating?: number;
|
|
54
|
+
downloads?: number;
|
|
55
|
+
updatedAt?: string;
|
|
56
|
+
}, query: string): number;
|
|
57
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAGL,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAErD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,CAKzE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAKvD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,CAS5E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKnE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQzE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,GAAE,KAAe,GAAG,KAAK,CAKlF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,SAAK,EAAE,GAAG,SAAM,GAAG,MAAM,CAKlF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAC/D,MAAM,CAyCR;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE;IACL,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,EACD,KAAK,EAAE,MAAM,GACZ,MAAM,CA2BR"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool utilities - shared helpers for tool handlers
|
|
3
|
+
*/
|
|
4
|
+
import { createGlobalStore, createLocalStore, createRegistryClient, } from 'skillpkg-core';
|
|
5
|
+
/**
|
|
6
|
+
* Get the appropriate store based on scope
|
|
7
|
+
*/
|
|
8
|
+
export function getStore(scope, projectPath) {
|
|
9
|
+
if (scope === 'global') {
|
|
10
|
+
return createGlobalStore();
|
|
11
|
+
}
|
|
12
|
+
return createLocalStore(projectPath);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get registry client
|
|
16
|
+
*/
|
|
17
|
+
export function getRegistryClient() {
|
|
18
|
+
// Use GitHub-based registry
|
|
19
|
+
return createRegistryClient({
|
|
20
|
+
registryUrl: 'https://raw.githubusercontent.com/skillpkg/registry/main',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create a success result
|
|
25
|
+
*/
|
|
26
|
+
export function successResult(data) {
|
|
27
|
+
const text = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
|
|
28
|
+
return {
|
|
29
|
+
content: [{ type: 'text', text }],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create an error result
|
|
34
|
+
*/
|
|
35
|
+
export function errorResult(message, suggestion) {
|
|
36
|
+
let text = `Error: ${message}`;
|
|
37
|
+
if (suggestion) {
|
|
38
|
+
text += `\n\nSuggestion: ${suggestion}`;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
content: [{ type: 'text', text }],
|
|
42
|
+
isError: true,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Validate required string parameter
|
|
47
|
+
*/
|
|
48
|
+
export function validateString(value, name) {
|
|
49
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
50
|
+
throw new Error(`${name} is required and must be a non-empty string`);
|
|
51
|
+
}
|
|
52
|
+
return value.trim();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validate optional string parameter
|
|
56
|
+
*/
|
|
57
|
+
export function validateOptionalString(value) {
|
|
58
|
+
if (value === undefined || value === null) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
if (typeof value !== 'string') {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
return value.trim() || undefined;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Validate scope parameter
|
|
68
|
+
*/
|
|
69
|
+
export function validateScope(value, defaultValue = 'local') {
|
|
70
|
+
if (value === 'local' || value === 'global') {
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
return defaultValue;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Validate limit parameter
|
|
77
|
+
*/
|
|
78
|
+
export function validateLimit(value, defaultValue = 20, max = 100) {
|
|
79
|
+
if (typeof value === 'number' && value > 0) {
|
|
80
|
+
return Math.min(value, max);
|
|
81
|
+
}
|
|
82
|
+
return defaultValue;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Calculate text match score (0-1)
|
|
86
|
+
*/
|
|
87
|
+
export function calculateTextMatch(_text, query, fields) {
|
|
88
|
+
const queryLower = query.toLowerCase();
|
|
89
|
+
const words = queryLower.split(/\s+/);
|
|
90
|
+
let score = 0;
|
|
91
|
+
let maxScore = 0;
|
|
92
|
+
// Name match (highest weight)
|
|
93
|
+
if (fields.name) {
|
|
94
|
+
maxScore += 3;
|
|
95
|
+
const nameLower = fields.name.toLowerCase();
|
|
96
|
+
if (nameLower === queryLower) {
|
|
97
|
+
score += 3; // Exact match
|
|
98
|
+
}
|
|
99
|
+
else if (nameLower.includes(queryLower)) {
|
|
100
|
+
score += 2; // Contains query
|
|
101
|
+
}
|
|
102
|
+
else if (words.some((w) => nameLower.includes(w))) {
|
|
103
|
+
score += 1; // Contains word
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Description match
|
|
107
|
+
if (fields.description) {
|
|
108
|
+
maxScore += 2;
|
|
109
|
+
const descLower = fields.description.toLowerCase();
|
|
110
|
+
if (descLower.includes(queryLower)) {
|
|
111
|
+
score += 2;
|
|
112
|
+
}
|
|
113
|
+
else if (words.some((w) => descLower.includes(w))) {
|
|
114
|
+
score += 1;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Tags match
|
|
118
|
+
if (fields.tags && fields.tags.length > 0) {
|
|
119
|
+
maxScore += 1;
|
|
120
|
+
const tagsLower = fields.tags.map((t) => t.toLowerCase());
|
|
121
|
+
if (tagsLower.some((t) => t === queryLower || words.includes(t))) {
|
|
122
|
+
score += 1;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return maxScore > 0 ? score / maxScore : 0;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Calculate relevance score for a skill
|
|
129
|
+
*/
|
|
130
|
+
export function calculateRelevanceScore(skill, query) {
|
|
131
|
+
// Text relevance (0-40)
|
|
132
|
+
const textRelevance = calculateTextMatch(query, query, {
|
|
133
|
+
name: skill.name,
|
|
134
|
+
description: skill.description,
|
|
135
|
+
tags: skill.tags,
|
|
136
|
+
}) * 40;
|
|
137
|
+
// Rating score (0-25)
|
|
138
|
+
const rating = skill.rating ?? 3;
|
|
139
|
+
const ratingScore = (rating / 5) * 25;
|
|
140
|
+
// Popularity score (0-20) - log scale
|
|
141
|
+
const downloads = skill.downloads ?? 0;
|
|
142
|
+
const popularityScore = Math.min(Math.log10(downloads + 1) / 4, 1) * 20;
|
|
143
|
+
// Freshness score (0-15) - decay over 180 days
|
|
144
|
+
let freshnessScore = 15;
|
|
145
|
+
if (skill.updatedAt) {
|
|
146
|
+
const daysSinceUpdate = Math.floor((Date.now() - new Date(skill.updatedAt).getTime()) / (1000 * 60 * 60 * 24));
|
|
147
|
+
freshnessScore = Math.max(0, 1 - daysSinceUpdate / 180) * 15;
|
|
148
|
+
}
|
|
149
|
+
return textRelevance + ratingScore + popularityScore + freshnessScore;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=utils.js.map
|