agentskillsdk 0.1.0 → 0.1.2
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/package.json +1 -1
- package/src/commands/add.js +52 -28
- package/src/index.js +2 -1
- package/src/lib/api.js +1 -2
- package/src/lib/download.js +12 -2
- package/src/lib/parse-source.js +7 -0
package/package.json
CHANGED
package/src/commands/add.js
CHANGED
|
@@ -3,41 +3,61 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { fetchSkill, fetchSkills } from '../lib/api.js';
|
|
4
4
|
import { detectAgents } from '../lib/detect-agent.js';
|
|
5
5
|
import { downloadSkill } from '../lib/download.js';
|
|
6
|
+
import { parseGithubSource } from '../lib/parse-source.js';
|
|
6
7
|
|
|
7
|
-
export async function addCommand(skillName) {
|
|
8
|
+
export async function addCommand(skillName, options) {
|
|
8
9
|
const cwd = process.cwd();
|
|
10
|
+
const githubSource = parseGithubSource(skillName);
|
|
9
11
|
|
|
10
|
-
// 1. Look up skill
|
|
11
12
|
let skill;
|
|
12
|
-
|
|
13
|
-
skill = await fetchSkill(skillName);
|
|
14
|
-
} catch (err) {
|
|
15
|
-
console.error(chalk.red(`\n ${err.message}\n`));
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
13
|
+
let installName;
|
|
18
14
|
|
|
19
|
-
if (
|
|
20
|
-
|
|
15
|
+
if (githubSource) {
|
|
16
|
+
// GitHub owner/repo source
|
|
17
|
+
const skillPath = options.skill || '';
|
|
18
|
+
installName = skillPath ? skillPath.split('/').pop() : githubSource.repo;
|
|
19
|
+
skill = {
|
|
20
|
+
name: installName,
|
|
21
|
+
githubOwner: githubSource.owner,
|
|
22
|
+
githubRepo: githubSource.repo,
|
|
23
|
+
githubPath: skillPath,
|
|
24
|
+
defaultBranch: 'main',
|
|
25
|
+
};
|
|
26
|
+
console.log(chalk.green(' \u2713') + ` GitHub source: ${chalk.bold(`${githubSource.owner}/${githubSource.repo}`)}` +
|
|
27
|
+
(options.skill ? ` (skill: ${chalk.bold(options.skill)})` : ''));
|
|
28
|
+
} else {
|
|
29
|
+
// Registry source
|
|
30
|
+
installName = skillName;
|
|
21
31
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} catch {
|
|
27
|
-
// If we can't fetch suggestions, just show the not-found message
|
|
32
|
+
skill = await fetchSkill(skillName);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
console.error(chalk.red(`\n ${err.message}\n`));
|
|
35
|
+
process.exit(1);
|
|
28
36
|
}
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
if (!skill) {
|
|
39
|
+
let suggestions = [];
|
|
40
|
+
try {
|
|
41
|
+
const allSkills = await fetchSkills();
|
|
42
|
+
suggestions = allSkills
|
|
43
|
+
.filter(s => s.name.includes(skillName) || skillName.includes(s.name))
|
|
44
|
+
.slice(0, 3);
|
|
45
|
+
} catch {
|
|
46
|
+
// If we can't fetch suggestions, just show the not-found message
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.error(chalk.red(`\n Skill "${skillName}" not found.\n`));
|
|
50
|
+
if (suggestions.length > 0) {
|
|
51
|
+
console.error(' Did you mean:');
|
|
52
|
+
suggestions.forEach(s => console.error(` - ${chalk.bold(s.name)}`));
|
|
53
|
+
console.error('');
|
|
54
|
+
}
|
|
55
|
+
console.error(` Browse all skills: ${chalk.underline('https://agentskills.dk/skills')}\n`);
|
|
56
|
+
process.exit(1);
|
|
35
57
|
}
|
|
36
|
-
console.error(` Browse all skills: ${chalk.underline('https://agentskills.dk/skills')}\n`);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
58
|
|
|
40
|
-
|
|
59
|
+
console.log(chalk.green(' \u2713') + ` Found skill: ${chalk.bold(skill.name)}`);
|
|
60
|
+
}
|
|
41
61
|
|
|
42
62
|
// 2. Detect agent
|
|
43
63
|
const agents = await detectAgents(cwd);
|
|
@@ -45,7 +65,7 @@ export async function addCommand(skillName) {
|
|
|
45
65
|
|
|
46
66
|
// 3. Download + install for each selected agent
|
|
47
67
|
for (const agent of agents) {
|
|
48
|
-
const destDir = join(cwd, agent.path(
|
|
68
|
+
const destDir = join(cwd, agent.path(installName));
|
|
49
69
|
try {
|
|
50
70
|
await downloadSkill(skill, destDir);
|
|
51
71
|
} catch (err) {
|
|
@@ -53,10 +73,14 @@ export async function addCommand(skillName) {
|
|
|
53
73
|
console.error(chalk.red(` ${err.message}\n`));
|
|
54
74
|
process.exit(1);
|
|
55
75
|
}
|
|
56
|
-
console.log(chalk.green(' \u2713') + ` Installed to ${agent.path(
|
|
76
|
+
console.log(chalk.green(' \u2713') + ` Installed to ${agent.path(installName)}`);
|
|
57
77
|
}
|
|
58
78
|
|
|
59
79
|
// 4. Done
|
|
60
80
|
console.log(`\n Skill ready. Start a new ${agents[0].name} session to use it.`);
|
|
61
|
-
|
|
81
|
+
if (!githubSource) {
|
|
82
|
+
console.log(` Learn more: ${chalk.underline(`https://agentskills.dk/skills/${skill.namespace}`)}\n`);
|
|
83
|
+
} else {
|
|
84
|
+
console.log('');
|
|
85
|
+
}
|
|
62
86
|
}
|
package/src/index.js
CHANGED
|
@@ -12,7 +12,8 @@ program
|
|
|
12
12
|
program
|
|
13
13
|
.command('add')
|
|
14
14
|
.description('Install a skill into your project')
|
|
15
|
-
.argument('<skill-name>', 'name of the skill to install')
|
|
15
|
+
.argument('<skill-name>', 'name of the skill to install (or owner/repo for GitHub)')
|
|
16
|
+
.option('--skill <path>', 'path within repo, e.g. skills/twitter')
|
|
16
17
|
.action(addCommand);
|
|
17
18
|
|
|
18
19
|
program
|
package/src/lib/api.js
CHANGED
|
@@ -8,8 +8,7 @@ export async function fetchSkills() {
|
|
|
8
8
|
throw new Error('Could not reach agentskills.dk. Check your internet connection.');
|
|
9
9
|
}
|
|
10
10
|
if (!res.ok) throw new Error(`Failed to fetch skills: ${res.status}`);
|
|
11
|
-
|
|
12
|
-
return data.skills;
|
|
11
|
+
return res.json();
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
export async function fetchSkill(name) {
|
package/src/lib/download.js
CHANGED
|
@@ -33,8 +33,18 @@ export async function downloadSkill(skill, destDir) {
|
|
|
33
33
|
parts.shift();
|
|
34
34
|
const relativePath = parts.join('/');
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
let fileRelative;
|
|
37
|
+
if (skillPath === '') {
|
|
38
|
+
if (header.type === 'file' && relativePath) {
|
|
39
|
+
fileRelative = relativePath;
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
if (header.type === 'file' && relativePath.startsWith(skillPath + '/')) {
|
|
43
|
+
fileRelative = relativePath.slice(skillPath.length + 1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (fileRelative) {
|
|
38
48
|
const destPath = join(destDir, fileRelative);
|
|
39
49
|
|
|
40
50
|
mkdirSync(dirname(destPath), { recursive: true });
|