skillgo 1.0.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 +26 -0
- package/bin/skillgo.js +177 -0
- package/package.json +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# SkillGo CLI
|
|
2
|
+
|
|
3
|
+
SkillGo 命令行工具 - 搜索、安装、管理 Agent 技能。https://skillgo.cn
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm dlx skillgo install <slug>
|
|
9
|
+
npx skillgo install <slug>
|
|
10
|
+
yarn dlx skillgo install <slug>
|
|
11
|
+
bunx skillgo install <slug>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## 用法
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
skillgo search <keyword> # 搜索技能
|
|
18
|
+
skillgo install <slug> # 安装最新版本到当前目录 skills/
|
|
19
|
+
skillgo install <slug>@<ver> # 安装指定版本
|
|
20
|
+
skillgo list # 列出已安装技能
|
|
21
|
+
skillgo update --all # 更新所有已安装技能
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 环境变量
|
|
25
|
+
|
|
26
|
+
- `SKILLGO_API`: API 地址,默认 `http://localhost:3100`,线上使用 `https://skillgo.cn`
|
package/bin/skillgo.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
const API_BASE = process.env.SKILLGO_API || 'http://localhost:3100'
|
|
5
|
+
|
|
6
|
+
const fetchJson = async (path) => {
|
|
7
|
+
const res = await fetch(`${API_BASE}${path}`)
|
|
8
|
+
if (!res.ok) throw new Error(`请求失败: ${res.status}`)
|
|
9
|
+
return res.json()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const fetchText = async (path) => {
|
|
13
|
+
const res = await fetch(`${API_BASE}${path}`)
|
|
14
|
+
if (!res.ok) throw new Error(`请求失败: ${res.status}`)
|
|
15
|
+
return res.text()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const search = async (keyword) => {
|
|
19
|
+
const data = await fetchJson(`/api/skills?status=published&q=${encodeURIComponent(keyword)}&pageSize=20`)
|
|
20
|
+
const items = data.items || []
|
|
21
|
+
if (items.length === 0) {
|
|
22
|
+
console.log('未找到匹配的技能')
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
console.log('\n技能列表:')
|
|
26
|
+
items.forEach((s) => {
|
|
27
|
+
console.log(` ${s.slug}@${s.version} - ${s.name}`)
|
|
28
|
+
console.log(` ${s.description}`)
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const install = async (slug, version, cwd) => {
|
|
33
|
+
let data
|
|
34
|
+
if (version) {
|
|
35
|
+
data = await fetchJson(`/api/skills?status=published&slug=${encodeURIComponent(slug)}&version=${encodeURIComponent(version)}`)
|
|
36
|
+
} else {
|
|
37
|
+
const all = await fetchJson('/mcp/skills?latest=true')
|
|
38
|
+
const skills = all.skills || []
|
|
39
|
+
const skill = skills.find((s) => s.slug === slug)
|
|
40
|
+
if (!skill) {
|
|
41
|
+
console.error(`未找到技能: ${slug}`)
|
|
42
|
+
process.exit(1)
|
|
43
|
+
}
|
|
44
|
+
const text = await fetchText(`/api/skills/${skill.id}/skill`)
|
|
45
|
+
const fs = await import('fs/promises')
|
|
46
|
+
const path = await import('path')
|
|
47
|
+
const dir = path.join(cwd, 'skills', skill.slug)
|
|
48
|
+
await fs.mkdir(dir, { recursive: true })
|
|
49
|
+
await fs.writeFile(path.join(dir, 'SKILL.md'), text, 'utf-8')
|
|
50
|
+
console.log(`已安装 ${skill.slug}@${skill.version} 到 ${dir}/SKILL.md`)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
const items = data.items || []
|
|
54
|
+
const skill = items[0]
|
|
55
|
+
if (!skill) {
|
|
56
|
+
console.error(`未找到技能: ${slug}${ver ? '@' + ver : ''}`)
|
|
57
|
+
process.exit(1)
|
|
58
|
+
}
|
|
59
|
+
if (skill.review_tier === 'none' || !skill.review_tier) {
|
|
60
|
+
console.warn('警告:该技能未经审核,使用前请自行评估安全风险。')
|
|
61
|
+
}
|
|
62
|
+
const text = await fetchText(`/api/skills/${skill.id}/skill`)
|
|
63
|
+
const fs = await import('fs/promises')
|
|
64
|
+
const path = await import('path')
|
|
65
|
+
const dir = path.join(cwd, 'skills', skill.slug)
|
|
66
|
+
await fs.mkdir(dir, { recursive: true })
|
|
67
|
+
await fs.writeFile(path.join(dir, 'SKILL.md'), text, 'utf-8')
|
|
68
|
+
console.log(`已安装 ${skill.slug}@${skill.version} 到 ${dir}/SKILL.md`)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const list = async (cwd) => {
|
|
72
|
+
const fs = await import('fs/promises')
|
|
73
|
+
const path = await import('path')
|
|
74
|
+
const skillsDir = path.join(cwd, 'skills')
|
|
75
|
+
try {
|
|
76
|
+
const entries = await fs.readdir(skillsDir, { withFileTypes: true })
|
|
77
|
+
const dirs = entries.filter((e) => e.isDirectory())
|
|
78
|
+
if (dirs.length === 0) {
|
|
79
|
+
console.log('当前目录下未安装任何技能')
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
console.log('\n已安装技能:')
|
|
83
|
+
for (const d of dirs) {
|
|
84
|
+
const skillPath = path.join(skillsDir, d.name, 'SKILL.md')
|
|
85
|
+
try {
|
|
86
|
+
await fs.access(skillPath)
|
|
87
|
+
console.log(` ${d.name}`)
|
|
88
|
+
} catch {}
|
|
89
|
+
}
|
|
90
|
+
} catch (e) {
|
|
91
|
+
if (e.code === 'ENOENT') console.log('当前目录下未安装任何技能')
|
|
92
|
+
else throw e
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const update = async (cwd) => {
|
|
97
|
+
const fs = await import('fs/promises')
|
|
98
|
+
const path = await import('path')
|
|
99
|
+
const skillsDir = path.join(cwd, 'skills')
|
|
100
|
+
let entries
|
|
101
|
+
try {
|
|
102
|
+
entries = await fs.readdir(skillsDir, { withFileTypes: true })
|
|
103
|
+
} catch (e) {
|
|
104
|
+
if (e.code === 'ENOENT') {
|
|
105
|
+
console.log('当前目录下未安装任何技能')
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
throw e
|
|
109
|
+
}
|
|
110
|
+
const dirs = entries.filter((e) => e.isDirectory())
|
|
111
|
+
for (const d of dirs) {
|
|
112
|
+
try {
|
|
113
|
+
const slug = d.name.includes('@') ? d.name.split('@')[0] : d.name
|
|
114
|
+
await install(slug, null, cwd)
|
|
115
|
+
} catch (e) {
|
|
116
|
+
console.error(`更新 ${d.name} 失败:`, e.message)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const main = async () => {
|
|
122
|
+
const args = process.argv.slice(2)
|
|
123
|
+
const cmd = args[0]
|
|
124
|
+
const cwd = process.cwd()
|
|
125
|
+
|
|
126
|
+
if (cmd === 'search') {
|
|
127
|
+
const keyword = args[1] || ''
|
|
128
|
+
await search(keyword)
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (cmd === 'install') {
|
|
133
|
+
const spec = args[1]
|
|
134
|
+
if (!spec) {
|
|
135
|
+
console.error('用法: skillgo install <slug>[@version]')
|
|
136
|
+
process.exit(1)
|
|
137
|
+
}
|
|
138
|
+
const at = spec.indexOf('@')
|
|
139
|
+
const slug = at > 0 ? spec.slice(0, at) : spec
|
|
140
|
+
const version = at > 0 ? spec.slice(at + 1) : null
|
|
141
|
+
await install(slug, version, cwd)
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (cmd === 'list') {
|
|
146
|
+
await list(cwd)
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (cmd === 'update') {
|
|
151
|
+
if (args[1] === '--all') {
|
|
152
|
+
await update(cwd)
|
|
153
|
+
} else {
|
|
154
|
+
console.log('用法: skillgo update --all')
|
|
155
|
+
}
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
console.log(`
|
|
160
|
+
SkillGo CLI - 技能管理工具 (https://skillgo.cn)
|
|
161
|
+
|
|
162
|
+
用法:
|
|
163
|
+
skillgo search <keyword> 搜索技能
|
|
164
|
+
skillgo install <slug> 安装技能到当前目录 skills/
|
|
165
|
+
skillgo install <slug>@<ver> 安装指定版本
|
|
166
|
+
skillgo list 列出已安装技能
|
|
167
|
+
skillgo update --all 更新所有已安装技能
|
|
168
|
+
|
|
169
|
+
环境变量:
|
|
170
|
+
SKILLGO_API API 地址,默认 http://localhost:3100
|
|
171
|
+
`)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
main().catch((e) => {
|
|
175
|
+
console.error(e.message)
|
|
176
|
+
process.exit(1)
|
|
177
|
+
})
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "skillgo",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "SkillGo 命令行工具 - 搜索、安装、管理 Agent 技能 (https://skillgo.cn)",
|
|
5
|
+
"bin": {
|
|
6
|
+
"skillgo": "bin/skillgo.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": ["skillgo", "cli", "skill", "agent", "skillgo.cn"],
|
|
9
|
+
"author": "",
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/hsliuping/skillgo.git"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://skillgo.cn",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/hsliuping/skillgo/issues"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"bin/skillgo.js"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|