@cli-skill/cli 0.0.1-beta.20260402075508 → 0.0.1-beta.20260402112811
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 +27 -21
- package/package.json +2 -3
- package/skill/SKILL.md +34 -29
- package/skill/references/core.md +6 -6
- package/src/app.ts +2 -2
- package/src/bun.ts +32 -2
- package/src/commands/config.ts +33 -4
- package/src/commands/create.ts +2 -0
- package/src/commands/install.ts +8 -10
- package/src/commands/list.ts +17 -22
- package/src/commands/skill.ts +59 -146
- package/src/commands/uninstall.ts +13 -5
- package/src/project.ts +4 -8
- package/src/registry.ts +192 -191
- package/test/registry.test.ts +74 -0
package/README.md
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
`@cli-skill/cli` 是 `cli-skill` 的平台命令行入口。
|
|
4
4
|
|
|
5
|
-
它不是某一个具体 skill 的运行时,而是整个 skill
|
|
5
|
+
它不是某一个具体 skill 的运行时,而是整个 skill 生命周期和本地注册表的管理入口。
|
|
6
6
|
|
|
7
7
|
## 主要职责
|
|
8
8
|
|
|
9
9
|
- 创建新的 skill 项目
|
|
10
|
-
-
|
|
11
|
-
-
|
|
10
|
+
- 维护本地 skill 注册表
|
|
11
|
+
- 提供当前目录命令和已注册 skill 执行入口
|
|
12
|
+
- 生成 `skill/` 产物
|
|
12
13
|
- 安装和卸载已发布 skill
|
|
13
14
|
- 挂载和取消挂载本地 skill
|
|
14
15
|
- 发布本地 skill
|
|
@@ -25,30 +26,31 @@ cli-skill install <skillName> [--packageName <packageName>]
|
|
|
25
26
|
cli-skill uninstall <packageName>
|
|
26
27
|
cli-skill config get [keyPath]
|
|
27
28
|
cli-skill config set <keyPath> <value>
|
|
29
|
+
cli-skill exec <skillName> <toolName> [rawInput]
|
|
28
30
|
```
|
|
29
31
|
|
|
30
|
-
###
|
|
32
|
+
### 当前目录命令
|
|
31
33
|
|
|
32
34
|
```bash
|
|
33
|
-
cli-skill
|
|
34
|
-
cli-skill
|
|
35
|
-
cli-skill
|
|
36
|
-
cli-skill
|
|
37
|
-
cli-skill
|
|
38
|
-
cli-skill
|
|
39
|
-
cli-skill
|
|
40
|
-
cli-skill
|
|
41
|
-
cli-skill
|
|
35
|
+
cli-skill tools
|
|
36
|
+
cli-skill run <toolName> [rawInput]
|
|
37
|
+
cli-skill config get [keyPath]
|
|
38
|
+
cli-skill config set <keyPath> <value>
|
|
39
|
+
cli-skill config unset <keyPath>
|
|
40
|
+
cli-skill build
|
|
41
|
+
cli-skill mount [targetPath]
|
|
42
|
+
cli-skill unmount [targetPath]
|
|
43
|
+
cli-skill publish [--dry-run] [--tag <tag>]
|
|
42
44
|
```
|
|
43
45
|
|
|
44
46
|
## 典型工作流
|
|
45
47
|
|
|
46
48
|
```bash
|
|
47
49
|
cli-skill create my-skill --cli-name my-skill
|
|
48
|
-
cd
|
|
50
|
+
cd ./my-skill
|
|
49
51
|
bun install
|
|
50
|
-
cli-skill
|
|
51
|
-
cli-skill
|
|
52
|
+
cli-skill build
|
|
53
|
+
cli-skill mount
|
|
52
54
|
```
|
|
53
55
|
|
|
54
56
|
## skill 项目结构
|
|
@@ -68,7 +70,7 @@ cli-skill my-skill mount
|
|
|
68
70
|
- `src/skill/*`
|
|
69
71
|
- 文档模板源目录
|
|
70
72
|
|
|
71
|
-
执行 `build` 后会生成:
|
|
73
|
+
执行 `cli-skill build` 后会生成:
|
|
72
74
|
|
|
73
75
|
- `skill/SKILL.md`
|
|
74
76
|
- `skill/agents/openai.yaml`
|
|
@@ -80,7 +82,7 @@ cli-skill my-skill mount
|
|
|
80
82
|
|
|
81
83
|
## build 输入
|
|
82
84
|
|
|
83
|
-
`cli-skill
|
|
85
|
+
`cli-skill build` 会读取:
|
|
84
86
|
|
|
85
87
|
- `src/index.ts`
|
|
86
88
|
- `src/skill/`
|
|
@@ -97,13 +99,17 @@ cli-skill my-skill mount
|
|
|
97
99
|
|
|
98
100
|
## 安装模型
|
|
99
101
|
|
|
100
|
-
|
|
102
|
+
本地创建的 skill 默认放在当前目录:
|
|
103
|
+
|
|
104
|
+
- `./<skill-name>`
|
|
105
|
+
|
|
106
|
+
已安装 skill 默认放在:
|
|
101
107
|
|
|
102
108
|
- `~/.cli-skill/skills`
|
|
103
109
|
|
|
104
|
-
|
|
110
|
+
本地注册表默认放在:
|
|
105
111
|
|
|
106
|
-
- `~/.cli-skill/
|
|
112
|
+
- `~/.cli-skill/registry.json`
|
|
107
113
|
|
|
108
114
|
默认 agent 目录是:
|
|
109
115
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cli-skill/cli",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.20260402112811",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -14,11 +14,10 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build": "tsc -p tsconfig.json",
|
|
18
17
|
"test": "tsc -p tsconfig.test.json && bun test ./test"
|
|
19
18
|
},
|
|
20
19
|
"dependencies": {
|
|
21
|
-
"@cli-skill/core": "^0.0.1-beta.
|
|
20
|
+
"@cli-skill/core": "^0.0.1-beta.20260402112811",
|
|
22
21
|
"cac": "^6.7.14",
|
|
23
22
|
"lodash": "^4.17.21",
|
|
24
23
|
"zod": "^3.25.76"
|
package/skill/SKILL.md
CHANGED
|
@@ -23,7 +23,7 @@ description: 当任务涉及 cli skill 的创建、挂载、安装、发布或
|
|
|
23
23
|
|
|
24
24
|
## 工作模型
|
|
25
25
|
|
|
26
|
-
处理 cli skill
|
|
26
|
+
处理 cli skill 时,默认按三类命令来理解:
|
|
27
27
|
|
|
28
28
|
- 平台命令
|
|
29
29
|
- `cli-skill create`
|
|
@@ -31,10 +31,16 @@ description: 当任务涉及 cli skill 的创建、挂载、安装、发布或
|
|
|
31
31
|
- `cli-skill install`
|
|
32
32
|
- `cli-skill uninstall`
|
|
33
33
|
- `cli-skill config ...`
|
|
34
|
-
-
|
|
35
|
-
- `cli-skill
|
|
34
|
+
- 当前目录命令
|
|
35
|
+
- `cli-skill tools`
|
|
36
|
+
- `cli-skill run`
|
|
37
|
+
- `cli-skill build`
|
|
38
|
+
- `cli-skill mount`
|
|
39
|
+
- `cli-skill publish`
|
|
40
|
+
- 已注册 skill 执行命令
|
|
41
|
+
- `cli-skill exec <skill-name> ...`
|
|
36
42
|
|
|
37
|
-
skill 自己的 bin
|
|
43
|
+
skill 自己的 bin 只是一个转发入口,最终会落到 `cli-skill exec <skill-name> ...`。
|
|
38
44
|
|
|
39
45
|
## 默认流程
|
|
40
46
|
|
|
@@ -42,9 +48,10 @@ skill 自己的 bin 只是一个转发入口,仍然会落到 `cli-skill <skill
|
|
|
42
48
|
|
|
43
49
|
```bash
|
|
44
50
|
cli-skill create <skill-name> --cli-name <cli-name>
|
|
51
|
+
cd ./<skill-name>
|
|
45
52
|
bun install
|
|
46
|
-
cli-skill
|
|
47
|
-
cli-skill
|
|
53
|
+
cli-skill build
|
|
54
|
+
cli-skill mount
|
|
48
55
|
```
|
|
49
56
|
|
|
50
57
|
如果没有提供 `cli-name`,默认令它等于 `skill-name`。
|
|
@@ -66,13 +73,7 @@ cli-skill <skill-name> mount
|
|
|
66
73
|
- `src/skill/*`
|
|
67
74
|
- 文档模板源目录
|
|
68
75
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
cli-skill <skill-name> build
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
会生成:
|
|
76
|
+
执行 `cli-skill build` 会生成:
|
|
76
77
|
|
|
77
78
|
- `skill/SKILL.md`
|
|
78
79
|
- `skill/agents/openai.yaml`
|
|
@@ -85,15 +86,16 @@ cli-skill <skill-name> build
|
|
|
85
86
|
| 查看 skill 列表 | `cli-skill list` |
|
|
86
87
|
| 安装已发布 skill | `cli-skill install <skill-name>` |
|
|
87
88
|
| 卸载已发布 skill | `cli-skill uninstall <package-name>` |
|
|
88
|
-
| 查看 tool 列表 | `cli-skill
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
|
89
|
+
| 查看 tool 列表 | `cli-skill tools` |
|
|
90
|
+
| 运行当前目录 tool | `cli-skill run <tool-name> [rawInput]` |
|
|
91
|
+
| 运行已注册 skill 的 tool | `cli-skill exec <skill-name> <tool-name> [rawInput]` |
|
|
92
|
+
| 读取当前 skill 配置 | `cli-skill config get [keyPath]` |
|
|
93
|
+
| 写入当前 skill 配置 | `cli-skill config set <keyPath> <value>` |
|
|
94
|
+
| 删除当前 skill 配置 | `cli-skill config unset <keyPath>` |
|
|
95
|
+
| 挂载当前 skill | `cli-skill mount [targetPath]` |
|
|
96
|
+
| 取消挂载当前 skill | `cli-skill unmount [targetPath]` |
|
|
97
|
+
| 构建 skill 产物 | `cli-skill build` |
|
|
98
|
+
| 发布当前 skill | `cli-skill publish [--dry-run] [--tag <tag>]` |
|
|
97
99
|
| 读取全局配置 | `cli-skill config get [keyPath]` |
|
|
98
100
|
| 写入全局配置 | `cli-skill config set <keyPath> <value>` |
|
|
99
101
|
|
|
@@ -106,14 +108,16 @@ cli-skill <skill-name> build
|
|
|
106
108
|
- 注册根目录 `skill/` 到 agent 目录
|
|
107
109
|
- `mount` 不应隐式执行 `install`。
|
|
108
110
|
- `install` / `uninstall` 面向已发布 skill。
|
|
109
|
-
- `publish`
|
|
111
|
+
- `publish` 只针对当前目录的本地 skill。
|
|
110
112
|
|
|
111
113
|
默认目录:
|
|
112
114
|
|
|
113
|
-
-
|
|
115
|
+
- 当前目录创建的 skill:
|
|
116
|
+
- `./<skill-name>`
|
|
117
|
+
- 已安装 skill:
|
|
114
118
|
- `~/.cli-skill/skills/<skill-name>`
|
|
115
|
-
-
|
|
116
|
-
- `~/.cli-skill/
|
|
119
|
+
- 本地注册表:
|
|
120
|
+
- `~/.cli-skill/registry.json`
|
|
117
121
|
- agent 默认目录:
|
|
118
122
|
- `~/.agents/skills/<skill-name>`
|
|
119
123
|
|
|
@@ -132,8 +136,9 @@ skill 作用域配置路径:
|
|
|
132
136
|
```bash
|
|
133
137
|
cli-skill config get
|
|
134
138
|
cli-skill config set skillsRoot ~/.cli-skill/skills
|
|
135
|
-
|
|
136
|
-
cli-skill
|
|
139
|
+
cd ./<skill-name>
|
|
140
|
+
cli-skill config get
|
|
141
|
+
cli-skill config set baseUrl https://example.com
|
|
137
142
|
```
|
|
138
143
|
|
|
139
144
|
## 文档规则
|
|
@@ -143,7 +148,7 @@ cli-skill <skill-name> config set baseUrl https://example.com
|
|
|
143
148
|
- tool 或配置变更后,应重新执行:
|
|
144
149
|
|
|
145
150
|
```bash
|
|
146
|
-
cli-skill
|
|
151
|
+
cli-skill build
|
|
147
152
|
```
|
|
148
153
|
|
|
149
154
|
## 不要做的事
|
package/skill/references/core.md
CHANGED
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
- 真正执行动作的最小单元
|
|
15
15
|
- `skill`
|
|
16
16
|
- 对 tools 的组织与描述
|
|
17
|
-
- `
|
|
17
|
+
- `skill/` 产物
|
|
18
18
|
- 给 agent 使用的 `skill/` 目录
|
|
19
19
|
|
|
20
20
|
源码不是直接写给 agent 的。
|
|
21
|
-
源码先定义 skill 和 tools,然后再由 `build` 生成 agent 真正消费的产物。
|
|
21
|
+
源码先定义 skill 和 tools,然后再由 `cli-skill build` 生成 agent 真正消费的产物。
|
|
22
22
|
|
|
23
23
|
## skill 项目源码结构
|
|
24
24
|
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
执行:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
cli-skill
|
|
43
|
+
cli-skill build
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
之后,根目录会生成:
|
|
@@ -179,11 +179,11 @@ export default defineSkill({
|
|
|
179
179
|
|
|
180
180
|
- `tool` 负责声明自己要 `browserPlugin`
|
|
181
181
|
- `skill` 只负责把它组织起来
|
|
182
|
-
- `build` 再负责生成 `skill/` 产物
|
|
182
|
+
- `cli-skill build` 再负责生成 `skill/` 产物
|
|
183
183
|
|
|
184
184
|
## 文档模板怎么写
|
|
185
185
|
|
|
186
|
-
`src/skill/*` 下的 `.md/.yaml/.yml` 文件会在 build 时做变量替换。
|
|
186
|
+
`src/skill/*` 下的 `.md/.yaml/.yml` 文件会在 `cli-skill build` 时做变量替换。
|
|
187
187
|
|
|
188
188
|
当前常用变量有:
|
|
189
189
|
|
|
@@ -217,7 +217,7 @@ export default defineSkill({
|
|
|
217
217
|
|
|
218
218
|
- 怎么创建 skill
|
|
219
219
|
- 怎么 mount / install / publish
|
|
220
|
-
-
|
|
220
|
+
- 怎么生成 `skill/` 产物
|
|
221
221
|
|
|
222
222
|
优先回到主 skill 文档:
|
|
223
223
|
|
package/src/app.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { registerConfigCommand } from "./commands/config";
|
|
|
3
3
|
import { registerCreateCommand } from "./commands/create";
|
|
4
4
|
import { registerInstallCommand } from "./commands/install";
|
|
5
5
|
import { registerListCommand } from "./commands/list";
|
|
6
|
-
import {
|
|
6
|
+
import { registerSkillCommands } from "./commands/skill";
|
|
7
7
|
import { registerUninstallCommand } from "./commands/uninstall";
|
|
8
8
|
|
|
9
9
|
export function createApp(version: string) {
|
|
@@ -14,7 +14,7 @@ export function createApp(version: string) {
|
|
|
14
14
|
registerListCommand(cli);
|
|
15
15
|
registerInstallCommand(cli);
|
|
16
16
|
registerUninstallCommand(cli);
|
|
17
|
-
|
|
17
|
+
registerSkillCommands(cli);
|
|
18
18
|
|
|
19
19
|
cli.help();
|
|
20
20
|
cli.version(version);
|
package/src/bun.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { execFile } from "node:child_process";
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
2
|
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { promisify } from "node:util";
|
|
5
6
|
|
|
@@ -19,6 +20,33 @@ export async function runBun(
|
|
|
19
20
|
});
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
export async function runBunStreaming(
|
|
24
|
+
args: string[],
|
|
25
|
+
cwd?: string,
|
|
26
|
+
envOverrides?: Record<string, string | undefined>,
|
|
27
|
+
): Promise<void> {
|
|
28
|
+
await new Promise<void>((resolve, reject) => {
|
|
29
|
+
const child = spawn("bun", args, {
|
|
30
|
+
cwd,
|
|
31
|
+
env: {
|
|
32
|
+
...process.env,
|
|
33
|
+
...envOverrides,
|
|
34
|
+
},
|
|
35
|
+
stdio: "inherit",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
child.on("error", reject);
|
|
39
|
+
child.on("exit", (code, signal) => {
|
|
40
|
+
if (code === 0) {
|
|
41
|
+
resolve();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
reject(new Error(`bun ${args.join(" ")} failed with code ${code ?? "null"}${signal ? ` signal ${signal}` : ""}`));
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
22
50
|
export async function runBunx(args: string[], cwd?: string): Promise<string> {
|
|
23
51
|
const { stdout } = await execFileAsync("bunx", args, {
|
|
24
52
|
cwd,
|
|
@@ -36,7 +64,9 @@ export async function runBunAndCapture(args: string[], cwd?: string): Promise<st
|
|
|
36
64
|
}
|
|
37
65
|
|
|
38
66
|
export async function getBunGlobalBinDir(): Promise<string> {
|
|
39
|
-
|
|
67
|
+
const home = process.env.HOME || os.homedir();
|
|
68
|
+
const bunInstall = process.env.BUN_INSTALL || path.join(home, ".bun");
|
|
69
|
+
return path.join(bunInstall, "bin");
|
|
40
70
|
}
|
|
41
71
|
|
|
42
72
|
export async function installPackageToDirectory(packageSpec: string, installDir: string): Promise<void> {
|
package/src/commands/config.ts
CHANGED
|
@@ -6,7 +6,9 @@ import {
|
|
|
6
6
|
parseConfigCliValue,
|
|
7
7
|
saveBrowserSkillCliConfig,
|
|
8
8
|
setConfigValue,
|
|
9
|
+
unsetConfigValue,
|
|
9
10
|
} from "../config";
|
|
11
|
+
import { getCurrentSkillProject } from "../registry";
|
|
10
12
|
|
|
11
13
|
function printConfigValue(value: unknown): void {
|
|
12
14
|
if (typeof value === "string") {
|
|
@@ -25,13 +27,24 @@ function printConfigValue(value: unknown): void {
|
|
|
25
27
|
export function registerConfigCommand(cli: CAC): void {
|
|
26
28
|
cli
|
|
27
29
|
.command("config [...args]", "Manage cli-skill config")
|
|
28
|
-
.usage("config get [keyPath]\n cli-skill config set <keyPath> <value>")
|
|
30
|
+
.usage("config get [keyPath]\n cli-skill config set <keyPath> <value>\n cli-skill config unset <keyPath>")
|
|
29
31
|
.action(async (args: string[] = []) => {
|
|
30
32
|
const [subcommand, keyPath, rawValue] = args;
|
|
33
|
+
let currentSkillName: string | null = null;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
currentSkillName = (await getCurrentSkillProject()).skillName;
|
|
37
|
+
} catch {}
|
|
38
|
+
|
|
39
|
+
const scopedKeyPath = currentSkillName && keyPath
|
|
40
|
+
? `skillConfig.${currentSkillName}.${keyPath}`
|
|
41
|
+
: currentSkillName
|
|
42
|
+
? `skillConfig.${currentSkillName}`
|
|
43
|
+
: keyPath;
|
|
31
44
|
|
|
32
45
|
if (subcommand === "get") {
|
|
33
46
|
const currentConfig = await loadBrowserSkillCliConfig();
|
|
34
|
-
const value = getConfigValue(currentConfig,
|
|
47
|
+
const value = getConfigValue(currentConfig, scopedKeyPath);
|
|
35
48
|
printConfigValue(value);
|
|
36
49
|
return;
|
|
37
50
|
}
|
|
@@ -42,12 +55,28 @@ export function registerConfigCommand(cli: CAC): void {
|
|
|
42
55
|
}
|
|
43
56
|
|
|
44
57
|
const currentConfig = await loadBrowserSkillCliConfig();
|
|
45
|
-
const nextConfig = setConfigValue(
|
|
58
|
+
const nextConfig = setConfigValue(
|
|
59
|
+
currentConfig,
|
|
60
|
+
scopedKeyPath!,
|
|
61
|
+
parseConfigCliValue(rawValue),
|
|
62
|
+
);
|
|
63
|
+
await saveBrowserSkillCliConfig(nextConfig);
|
|
64
|
+
console.log(getBrowserSkillConfigPath());
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (subcommand === "unset") {
|
|
69
|
+
if (!keyPath) {
|
|
70
|
+
throw new Error("Usage: cli-skill config unset <keyPath>");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const currentConfig = await loadBrowserSkillCliConfig();
|
|
74
|
+
const nextConfig = unsetConfigValue(currentConfig, scopedKeyPath!);
|
|
46
75
|
await saveBrowserSkillCliConfig(nextConfig);
|
|
47
76
|
console.log(getBrowserSkillConfigPath());
|
|
48
77
|
return;
|
|
49
78
|
}
|
|
50
79
|
|
|
51
|
-
throw new Error("Usage: cli-skill config get [keyPath] | cli-skill config set <keyPath> <value>");
|
|
80
|
+
throw new Error("Usage: cli-skill config get [keyPath] | cli-skill config set <keyPath> <value> | cli-skill config unset <keyPath>");
|
|
52
81
|
});
|
|
53
82
|
}
|
package/src/commands/create.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CAC } from "cac";
|
|
2
2
|
import { DEFAULT_TEMPLATE_NAME } from "../constants";
|
|
3
3
|
import { createSkillProject } from "../project";
|
|
4
|
+
import { registerLocalSkillProject } from "../registry";
|
|
4
5
|
|
|
5
6
|
function resolveTemplateName(templateOption?: string): string {
|
|
6
7
|
return templateOption ?? DEFAULT_TEMPLATE_NAME;
|
|
@@ -20,6 +21,7 @@ export function registerCreateCommand(cli: CAC): void {
|
|
|
20
21
|
options.cliName ?? skillName,
|
|
21
22
|
resolveTemplateName(options.template),
|
|
22
23
|
);
|
|
24
|
+
await registerLocalSkillProject(targetDir);
|
|
23
25
|
console.log(targetDir);
|
|
24
26
|
});
|
|
25
27
|
}
|
package/src/commands/install.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type { CAC } from "cac";
|
|
|
2
2
|
import https from "node:https";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { installPackageToDirectory } from "../bun";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { getDefaultSkillsRoot } from "../constants";
|
|
6
|
+
import { registerInstalledSkillProject, setupLocalSkillBins } from "../registry";
|
|
7
7
|
|
|
8
8
|
interface SearchResultPackage {
|
|
9
9
|
name: string;
|
|
@@ -98,23 +98,21 @@ export function registerInstallCommand(cli: CAC): void {
|
|
|
98
98
|
.alias("i")
|
|
99
99
|
.option("--packageName <packageName>", "Install directly by explicit package name")
|
|
100
100
|
.option("--package-name <packageName>", "Install directly by explicit package name")
|
|
101
|
-
.option("--skill-root <skillRoot>", "Override the target skill registration directory")
|
|
102
101
|
.action(
|
|
103
102
|
async (
|
|
104
103
|
skillName: string,
|
|
105
|
-
options: { packageName?: string; "package-name"?: string
|
|
104
|
+
options: { packageName?: string; "package-name"?: string },
|
|
106
105
|
) => {
|
|
107
106
|
const explicitPackageName = options.packageName ?? options["package-name"];
|
|
108
107
|
const { packageSpec, packageName } = await resolveInstallTarget(skillName, explicitPackageName);
|
|
109
108
|
|
|
110
|
-
const
|
|
111
|
-
const installDir = path.join(
|
|
109
|
+
const skillsRoot = await getDefaultSkillsRoot();
|
|
110
|
+
const installDir = path.join(skillsRoot, skillName);
|
|
112
111
|
await installPackageToDirectory(packageSpec, installDir);
|
|
113
112
|
const packageDir = path.join(installDir, "node_modules", packageName);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
console.log(targetPath);
|
|
113
|
+
await registerInstalledSkillProject(packageDir);
|
|
114
|
+
await setupLocalSkillBins(packageDir);
|
|
115
|
+
console.log(packageDir);
|
|
118
116
|
},
|
|
119
117
|
);
|
|
120
118
|
}
|
package/src/commands/list.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CAC } from "cac";
|
|
2
2
|
import os from "node:os";
|
|
3
|
-
import {
|
|
3
|
+
import { listRegisteredSkills } from "../registry";
|
|
4
4
|
|
|
5
5
|
function pad(value: string, width: number): string {
|
|
6
6
|
return value.padEnd(width, " ");
|
|
@@ -21,54 +21,49 @@ function formatPath(value: string): string {
|
|
|
21
21
|
|
|
22
22
|
export function registerListCommand(cli: CAC): void {
|
|
23
23
|
cli.command("list", "List local and installed cli skills").action(async () => {
|
|
24
|
-
const skills = await
|
|
24
|
+
const skills = await listRegisteredSkills();
|
|
25
25
|
if (skills.length === 0) {
|
|
26
26
|
console.log("无");
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const rows = skills.map((skill) => ({
|
|
31
|
-
|
|
32
|
-
source: skill.source === "local" ? "local" : "remote",
|
|
31
|
+
name: skill.skillName,
|
|
33
32
|
packageName: skill.packageName,
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
source: skill.source,
|
|
34
|
+
mounted: `[${skill.agentPaths.map((agentPath) => formatPath(agentPath)).join(", ")}]`,
|
|
36
35
|
}));
|
|
37
36
|
|
|
38
37
|
const headers = {
|
|
39
|
-
|
|
40
|
-
source: "Source",
|
|
38
|
+
name: "Name",
|
|
41
39
|
packageName: "Package",
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
source: "Source",
|
|
41
|
+
mounted: "MountPaths",
|
|
44
42
|
};
|
|
45
43
|
|
|
46
44
|
const widths = {
|
|
47
|
-
|
|
48
|
-
source: Math.max(headers.source.length, ...rows.map((row) => row.source.length)),
|
|
45
|
+
name: Math.max(headers.name.length, ...rows.map((row) => row.name.length)),
|
|
49
46
|
packageName: Math.max(headers.packageName.length, ...rows.map((row) => row.packageName.length)),
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
source: Math.max(headers.source.length, ...rows.map((row) => row.source.length)),
|
|
48
|
+
mounted: Math.max(headers.mounted.length, ...rows.map((row) => row.mounted.length)),
|
|
52
49
|
};
|
|
53
50
|
|
|
54
51
|
console.log(
|
|
55
52
|
[
|
|
56
|
-
pad(headers.
|
|
57
|
-
pad(headers.source, widths.source),
|
|
53
|
+
pad(headers.name, widths.name),
|
|
58
54
|
pad(headers.packageName, widths.packageName),
|
|
59
|
-
pad(headers.
|
|
60
|
-
headers.
|
|
55
|
+
pad(headers.source, widths.source),
|
|
56
|
+
headers.mounted,
|
|
61
57
|
].join(" "),
|
|
62
58
|
);
|
|
63
59
|
|
|
64
60
|
for (const row of rows) {
|
|
65
61
|
console.log(
|
|
66
62
|
[
|
|
67
|
-
pad(row.
|
|
68
|
-
pad(row.source, widths.source),
|
|
63
|
+
pad(row.name, widths.name),
|
|
69
64
|
pad(row.packageName, widths.packageName),
|
|
70
|
-
pad(row.
|
|
71
|
-
row.
|
|
65
|
+
pad(row.source, widths.source),
|
|
66
|
+
row.mounted,
|
|
72
67
|
].join(" "),
|
|
73
68
|
);
|
|
74
69
|
}
|