@dayinxisheng/skillctl 1.0.1 → 1.0.3

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +6 -0
  3. package/dist/commands/list.d.ts.map +1 -1
  4. package/dist/commands/list.js +3 -2
  5. package/dist/commands/list.js.map +1 -1
  6. package/dist/commands/pull.d.ts +13 -0
  7. package/dist/commands/pull.d.ts.map +1 -0
  8. package/dist/commands/pull.js +52 -0
  9. package/dist/commands/pull.js.map +1 -0
  10. package/dist/index.js +16 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/lib/pull-handler.d.ts +12 -0
  13. package/dist/lib/pull-handler.d.ts.map +1 -0
  14. package/dist/lib/pull-handler.js +192 -0
  15. package/dist/lib/pull-handler.js.map +1 -0
  16. package/dist/types/index.d.ts +32 -0
  17. package/dist/types/index.d.ts.map +1 -1
  18. package/dist/utils/archive-extractor.d.ts +17 -0
  19. package/dist/utils/archive-extractor.d.ts.map +1 -0
  20. package/dist/utils/archive-extractor.js +84 -0
  21. package/dist/utils/archive-extractor.js.map +1 -0
  22. package/dist/utils/downloader.d.ts +23 -0
  23. package/dist/utils/downloader.d.ts.map +1 -0
  24. package/dist/utils/downloader.js +70 -0
  25. package/dist/utils/downloader.js.map +1 -0
  26. package/dist/utils/errors.d.ts +12 -0
  27. package/dist/utils/errors.d.ts.map +1 -1
  28. package/dist/utils/errors.js +24 -0
  29. package/dist/utils/errors.js.map +1 -1
  30. package/dist/utils/github-parser.d.ts +38 -0
  31. package/dist/utils/github-parser.d.ts.map +1 -0
  32. package/dist/utils/github-parser.js +103 -0
  33. package/dist/utils/github-parser.js.map +1 -0
  34. package/dist/utils/skill-validator.d.ts +30 -0
  35. package/dist/utils/skill-validator.d.ts.map +1 -0
  36. package/dist/utils/skill-validator.js +118 -0
  37. package/dist/utils/skill-validator.js.map +1 -0
  38. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.3] - 2026-03-05
9
+
10
+ ### Added
11
+ - **`pull` 命令** - 从 Git 仓库拉取 skills 到本地
12
+ - 支持从 GitHub 仓库提取指定目录作为 skill
13
+ - 支持同时拉取多个 skills
14
+ - 严格验证 SKILL.md 文件及 name 字段
15
+ - `--force` 选项强制覆盖已存在的 skill(自动备份旧版本)
16
+ - 跨平台支持(Linux/macOS 使用 tar.gz,Windows 使用 zip)
17
+ - 支持国内 GitHub 镜像服务(ghfast.top、ghproxy.net 等)
18
+ - 下载进度显示
19
+
20
+ ### Changed
21
+ - 重命名 `.claude/plans/` 目录下的计划文档,使用 `YYYY-MM-DD-<topic>-design.md` 格式
22
+
23
+ ## [1.0.2] - 2026-03-05
24
+
25
+ ### Fixed
26
+ - 修复 Windows 平台上 `list` 命令显示错误的 Unix 风格路径(`~/.claude/skills`)
27
+ - 现在 `list` 命令会根据平台自动显示正确的路径格式:
28
+ - Windows: `C:\Users\用户名\.claude\skills`
29
+ - Linux: `/home/用户名/.claude/skills`
30
+ - macOS: `/Users/用户名/.claude/skills`
31
+
8
32
  ## [1.0.1] - 2026-03-05
9
33
 
10
34
  ### Added
package/README.md CHANGED
@@ -10,6 +10,12 @@
10
10
  npm install -g @dayinxisheng/skillctl
11
11
  ```
12
12
 
13
+ ## 更新
14
+
15
+ ```bash
16
+ npm update -g @dayinxisheng/skillctl
17
+ ```
18
+
13
19
  安装完成后,可以在任何目录使用 `skillctl` 命令。
14
20
 
15
21
  ## 🚀 快速开始
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAuC1C"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAwC1C"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * List 命令 - 列出已激活的 skills
3
3
  */
4
- import { getActiveSkills } from '../lib/skill-manager.js';
4
+ import { getActiveSkills, getActiveDir } from '../lib/skill-manager.js';
5
5
  import { printHeader, printInfo, printLink } from '../utils/output.js';
6
6
  import chalk from 'chalk';
7
7
  import { getCwd } from '../utils/platform.js';
@@ -12,7 +12,8 @@ export async function list() {
12
12
  // 获取 project 级别的 skills
13
13
  const projectSkills = await getActiveSkills('project');
14
14
  // 显示全局 skills
15
- console.log(chalk.cyan(`全局 (${chalk.yellow('~/.claude/skills')})`));
15
+ const userDir = getActiveDir('user');
16
+ console.log(chalk.cyan(`全局 (${chalk.yellow(userDir)})`));
16
17
  if (userSkills.length === 0) {
17
18
  console.log(` ${chalk.yellow('(无)')}`);
18
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,WAAW,CAAC,cAAc,CAAC,CAAC;IAE5B,qBAAqB;IACrB,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;IACjD,wBAAwB;IACxB,MAAM,aAAa,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IAEvD,cAAc;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAC/B,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjB,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QACD,SAAS,CAAC,KAAK,UAAU,CAAC,MAAM,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,cAAc;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjB,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QACD,SAAS,CAAC,KAAK,aAAa,CAAC,MAAM,IAAI,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,WAAW,CAAC,cAAc,CAAC,CAAC;IAE5B,qBAAqB;IACrB,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;IACjD,wBAAwB;IACxB,MAAM,aAAa,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IAEvD,cAAc;IACd,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAC/B,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjB,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QACD,SAAS,CAAC,KAAK,UAAU,CAAC,MAAM,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,cAAc;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjB,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QACD,SAAS,CAAC,KAAK,aAAa,CAAC,MAAM,IAAI,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Pull 命令处理器
3
+ * 从 Git 仓库提取特定目录到 skills 仓库
4
+ */
5
+ import type { PullOptions } from '../types/index.js';
6
+ /**
7
+ * 执行 pull 命令
8
+ * @param repoUrl - Git 仓库 URL
9
+ * @param subpaths - 子路径列表
10
+ * @param options - 命令选项
11
+ */
12
+ export declare function pullCommand(repoUrl: string, subpaths: string[], options: Partial<PullOptions>): Promise<void>;
13
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKrD;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC,CA0Cf"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Pull 命令处理器
3
+ * 从 Git 仓库提取特定目录到 skills 仓库
4
+ */
5
+ import { pull } from '../lib/pull-handler.js';
6
+ import { printError, printHeader } from '../utils/output.js';
7
+ import { SkillctlError } from '../utils/errors.js';
8
+ /**
9
+ * 执行 pull 命令
10
+ * @param repoUrl - Git 仓库 URL
11
+ * @param subpaths - 子路径列表
12
+ * @param options - 命令选项
13
+ */
14
+ export async function pullCommand(repoUrl, subpaths, options) {
15
+ try {
16
+ // 验证参数
17
+ if (!repoUrl) {
18
+ throw new SkillctlError('请指定仓库 URL');
19
+ }
20
+ if (!subpaths || subpaths.length === 0) {
21
+ throw new SkillctlError('请指定至少一个子路径');
22
+ }
23
+ const pullOptions = {
24
+ repoUrl,
25
+ subpaths,
26
+ force: options.force || false,
27
+ };
28
+ printHeader('Pull Skills');
29
+ const results = await pull(pullOptions);
30
+ // 显示结果汇总
31
+ console.log();
32
+ const successCount = results.filter((r) => r.status === 'success').length;
33
+ const failedCount = results.filter((r) => r.status === 'failed').length;
34
+ if (successCount > 0) {
35
+ console.log(`✓ 成功: ${successCount} 个 skill`);
36
+ }
37
+ if (failedCount > 0) {
38
+ console.log(`✗ 失败: ${failedCount} 个 skill`);
39
+ process.exit(1);
40
+ }
41
+ }
42
+ catch (error) {
43
+ if (error instanceof SkillctlError) {
44
+ printError(error.message);
45
+ }
46
+ else {
47
+ printError(error instanceof Error ? error.message : '未知错误');
48
+ }
49
+ process.exit(1);
50
+ }
51
+ }
52
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAe,EACf,QAAkB,EAClB,OAA6B;IAE7B,IAAI,CAAC;QACH,OAAO;QACP,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,aAAa,CAAC,WAAW,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,WAAW,GAAgB;YAC/B,OAAO;YACP,QAAQ;YACR,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;SAC9B,CAAC;QAEF,WAAW,CAAC,aAAa,CAAC,CAAC;QAE3B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC;QAExC,SAAS;QACT,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QAC1E,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;QAExE,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,SAAS,YAAY,UAAU,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,SAAS,WAAW,UAAU,CAAC,CAAC;YAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;YACnC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ import { list } from './commands/list.js';
14
14
  import { allList } from './commands/all-list.js';
15
15
  import { setRepo, getRepo } from './commands/set-repo.js';
16
16
  import { showConfig } from './commands/config.js';
17
+ import { pullCommand } from './commands/pull.js';
17
18
  import { createRequire } from 'node:module';
18
19
  // 从 package.json 读取版本号
19
20
  const require = createRequire(import.meta.url);
@@ -180,5 +181,20 @@ program
180
181
  process.exit(1);
181
182
  }
182
183
  });
184
+ // Pull 命令
185
+ program
186
+ .command('pull')
187
+ .description('从 Git 仓库提取 skill 到本地')
188
+ .argument('<repo-url>', 'Git 仓库 URL(如:https://github.com/owner/repo)')
189
+ .argument('<subpath...>', '仓库中的子路径(可指定多个)')
190
+ .option('-f, --force', '强制覆盖已存在的 skill(会自动备份)')
191
+ .action(async (repoUrl, subpaths, options) => {
192
+ try {
193
+ await pullCommand(repoUrl, subpaths, options);
194
+ }
195
+ catch (error) {
196
+ process.exit(1);
197
+ }
198
+ });
183
199
  program.parse();
184
200
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Pull 命令核心处理逻辑
3
+ * 从 Git 仓库提取特定目录到 skills 仓库
4
+ */
5
+ import type { PullOptions, PullResult } from '../types/index.js';
6
+ /**
7
+ * 执行 pull 命令
8
+ * @param options - pull 命令选项
9
+ * @returns 处理结果列表
10
+ */
11
+ export declare function pull(options: PullOptions): Promise<PullResult[]>;
12
+ //# sourceMappingURL=pull-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull-handler.d.ts","sourceRoot":"","sources":["../../src/lib/pull-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAkB,MAAM,mBAAmB,CAAC;AA8KjF;;;;GAIG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAoCtE"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Pull 命令核心处理逻辑
3
+ * 从 Git 仓库提取特定目录到 skills 仓库
4
+ */
5
+ import { join } from 'node:path';
6
+ import { rm, rename, cp } from 'node:fs/promises';
7
+ import { existsSync } from 'node:fs';
8
+ import { mkdtemp } from 'node:fs/promises';
9
+ import { tmpdir } from 'node:os';
10
+ import { getProjectSkillsDir } from './skill-manager.js';
11
+ import { parseGitHubRepoUrl, buildArchiveUrl, buildArchiveUrlZip } from '../utils/github-parser.js';
12
+ import { downloadFile } from '../utils/downloader.js';
13
+ import { extractArchive, getArchiveExtension } from '../utils/archive-extractor.js';
14
+ import { validateSkillStrict, extractDisplayName } from '../utils/skill-validator.js';
15
+ import { SkillAlreadyExistsError, SkillValidationError, } from '../utils/errors.js';
16
+ import { printInfo, printSuccess, printError } from '../utils/output.js';
17
+ import { isWindows } from '../utils/platform.js';
18
+ /**
19
+ * 生成备份文件名
20
+ * @param skillName - skill 名称
21
+ * @returns 备份文件名
22
+ */
23
+ function generateBackupName(skillName) {
24
+ const now = new Date();
25
+ const timestamp = now.toISOString().replace(/[:.]/g, '').slice(0, 15);
26
+ return `${skillName}.bak.${timestamp}`;
27
+ }
28
+ /**
29
+ * 清理临时目录
30
+ * @param tempDir - 临时目录路径
31
+ */
32
+ async function cleanupTempDir(tempDir) {
33
+ try {
34
+ await rm(tempDir, { recursive: true, force: true });
35
+ }
36
+ catch {
37
+ // 忽略清理错误
38
+ }
39
+ }
40
+ /**
41
+ * 备份已存在的 skill
42
+ * @param skillName - skill 名称
43
+ * @param skillsDir - skills 目录
44
+ */
45
+ async function backupExistingSkill(skillName, skillsDir) {
46
+ const skillPath = join(skillsDir, skillName);
47
+ const backupName = generateBackupName(skillName);
48
+ const backupPath = join(skillsDir, backupName);
49
+ await rename(skillPath, backupPath);
50
+ printInfo(`备份: ${skillName} → ${backupName}`);
51
+ }
52
+ /**
53
+ * 复制 skill 目录到目标位置
54
+ * @param sourcePath - 源目录
55
+ * @param destPath - 目标目录
56
+ */
57
+ async function copySkillDirectory(sourcePath, destPath) {
58
+ await cp(sourcePath, destPath, { recursive: true, verbatimSymlinks: true });
59
+ }
60
+ /**
61
+ * 获取仓库解压后的目录名
62
+ * @param repo - 仓库名
63
+ * @returns 解压后的目录名
64
+ */
65
+ function getExtractedDirName(repo) {
66
+ return `${repo}-main`;
67
+ }
68
+ /**
69
+ * 处理单个 subpath
70
+ * @param repoUrl - 仓库 URL
71
+ * @param subpath - 子路径
72
+ * @param skillsDir - skills 目录
73
+ * @param force - 是否强制覆盖
74
+ * @returns 处理结果
75
+ */
76
+ async function pullSingleSkill(repoUrl, subpath, skillsDir, force) {
77
+ // 解析仓库 URL(包含可能的 mirror 信息)
78
+ const repoInfo = parseGitHubRepoUrl(repoUrl);
79
+ const { owner, repo, mirror } = repoInfo;
80
+ const displayName = extractDisplayName(subpath);
81
+ printInfo(`正在处理: ${displayName}`);
82
+ // 创建临时目录
83
+ const tempDir = await mkdtemp(join(tmpdir(), 'skillctl-pull-'));
84
+ const archiveExt = getArchiveExtension();
85
+ try {
86
+ // 构建 archive URL(包含 mirror 信息)
87
+ const ghInfo = {
88
+ owner,
89
+ repo,
90
+ branch: 'main',
91
+ subpath,
92
+ mirror,
93
+ };
94
+ const archiveUrl = isWindows() ? buildArchiveUrlZip(ghInfo) : buildArchiveUrl(ghInfo);
95
+ const archivePath = join(tempDir, `archive${archiveExt}`);
96
+ // 下载
97
+ printInfo(`正在下载: ${displayName} (0%)`);
98
+ await downloadFile(archiveUrl, archivePath, (percent) => {
99
+ // 简单进度显示,覆盖同一行
100
+ process.stdout.write(`\r${` 正在下载: ${displayName} (${percent}%)`.padEnd(60)}`);
101
+ });
102
+ console.log(); // 换行
103
+ // 解压
104
+ printInfo('正在解压...');
105
+ await extractArchive(archivePath, tempDir);
106
+ // 构建源路径
107
+ const extractedDirName = getExtractedDirName(repo);
108
+ const sourcePath = join(tempDir, extractedDirName, subpath);
109
+ // 检查源路径是否存在
110
+ if (!existsSync(sourcePath)) {
111
+ throw new SkillValidationError(displayName, `仓库中未找到路径: ${subpath}`);
112
+ }
113
+ // 验证 skill
114
+ printInfo('正在验证 skill...');
115
+ const validation = await validateSkillStrict(sourcePath);
116
+ if (!validation.valid) {
117
+ throw new SkillValidationError(displayName, validation.error || '未知错误');
118
+ }
119
+ // 获取 skill 名称
120
+ const skillName = validation.metadata?.name || displayName;
121
+ // 检查是否已存在
122
+ const destPath = join(skillsDir, skillName);
123
+ if (existsSync(destPath)) {
124
+ if (!force) {
125
+ throw new SkillAlreadyExistsError(skillName);
126
+ }
127
+ // 备份已存在的 skill
128
+ await backupExistingSkill(skillName, skillsDir);
129
+ }
130
+ // 复制到目标位置
131
+ await copySkillDirectory(sourcePath, destPath);
132
+ return {
133
+ skillName,
134
+ status: 'success',
135
+ };
136
+ }
137
+ catch (error) {
138
+ if (error instanceof SkillValidationError || error instanceof SkillAlreadyExistsError) {
139
+ return {
140
+ skillName: displayName,
141
+ status: 'failed',
142
+ error: error.message,
143
+ };
144
+ }
145
+ return {
146
+ skillName: displayName,
147
+ status: 'failed',
148
+ error: error instanceof Error ? error.message : '未知错误',
149
+ };
150
+ }
151
+ finally {
152
+ // 清理临时文件
153
+ await cleanupTempDir(tempDir);
154
+ }
155
+ }
156
+ /**
157
+ * 执行 pull 命令
158
+ * @param options - pull 命令选项
159
+ * @returns 处理结果列表
160
+ */
161
+ export async function pull(options) {
162
+ const { repoUrl, subpaths, force } = options;
163
+ const results = [];
164
+ // 获取 skills 目录
165
+ const skillsDir = await getProjectSkillsDir();
166
+ printInfo(`正在解析仓库信息...`);
167
+ // 解析仓库信息验证
168
+ try {
169
+ parseGitHubRepoUrl(repoUrl);
170
+ }
171
+ catch (error) {
172
+ printError(error instanceof Error ? error.message : '无法解析仓库 URL');
173
+ return results;
174
+ }
175
+ // 逐个处理 subpath
176
+ for (const subpath of subpaths) {
177
+ const result = await pullSingleSkill(repoUrl, subpath, skillsDir, force);
178
+ results.push(result);
179
+ // 如果失败且不是 force 模式,停止后续处理
180
+ if (result.status === 'failed' && !force) {
181
+ printError(result.error || '未知错误');
182
+ printInfo('操作已中止,临时文件已清理');
183
+ break;
184
+ }
185
+ // 显示成功结果
186
+ if (result.status === 'success') {
187
+ printSuccess(`已安装: ${result.skillName}`);
188
+ }
189
+ }
190
+ return results;
191
+ }
192
+ //# sourceMappingURL=pull-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull-handler.js","sourceRoot":"","sources":["../../src/lib/pull-handler.ts"],"names":[],"mappings":"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"}
@@ -57,4 +57,36 @@ export interface SkillValidationResult {
57
57
  * 平台类型
58
58
  */
59
59
  export type Platform = 'windows' | 'macos' | 'linux' | 'unknown';
60
+ /**
61
+ * Pull 命令选项
62
+ */
63
+ export interface PullOptions {
64
+ force: boolean;
65
+ repoUrl: string;
66
+ subpaths: string[];
67
+ }
68
+ /**
69
+ * Skill 元数据(从 SKILL.md 解析)
70
+ */
71
+ export interface SkillMetadata {
72
+ name: string;
73
+ description?: string;
74
+ }
75
+ /**
76
+ * 下载任务状态
77
+ */
78
+ export interface PullResult {
79
+ skillName: string;
80
+ status: 'success' | 'skipped' | 'failed';
81
+ error?: string;
82
+ }
83
+ /**
84
+ * GitHub 仓库信息
85
+ */
86
+ export interface GitHubRepoInfo {
87
+ owner: string;
88
+ repo: string;
89
+ branch?: string;
90
+ subpath: string;
91
+ }
60
92
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 解压工具
3
+ * 跨平台解压工具(Linux 用 tar,Windows 用 zip)
4
+ */
5
+ /**
6
+ * 解压压缩包到指定目录
7
+ * @param archivePath - 压缩包路径
8
+ * @param destPath - 目标目录
9
+ * @throws {Error} 如果解压失败
10
+ */
11
+ export declare function extractArchive(archivePath: string, destPath: string): Promise<void>;
12
+ /**
13
+ * 根据平台选择合适的压缩包扩展名
14
+ * @returns 扩展名(.tar.gz 或 .zip)
15
+ */
16
+ export declare function getArchiveExtension(): string;
17
+ //# sourceMappingURL=archive-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-extractor.d.ts","sourceRoot":"","sources":["../../src/utils/archive-extractor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgEH;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 解压工具
3
+ * 跨平台解压工具(Linux 用 tar,Windows 用 zip)
4
+ */
5
+ import { spawn } from 'node:child_process';
6
+ import { isWindows } from './platform.js';
7
+ /**
8
+ * 执行命令并等待完成
9
+ * @param command - 命令
10
+ * @param args - 参数列表
11
+ * @returns Promise
12
+ */
13
+ function execCommand(command, args) {
14
+ return new Promise((resolve, reject) => {
15
+ const proc = spawn(command, args, { stdio: 'pipe' });
16
+ let stderr = '';
17
+ proc.stderr?.on('data', (data) => {
18
+ stderr += data.toString();
19
+ });
20
+ proc.on('close', (code) => {
21
+ if (code === 0) {
22
+ resolve();
23
+ }
24
+ else {
25
+ reject(new Error(`命令执行失败: ${command} ${args.join(' ')}\n${stderr}`));
26
+ }
27
+ });
28
+ proc.on('error', (error) => {
29
+ reject(error);
30
+ });
31
+ });
32
+ }
33
+ /**
34
+ * 使用 tar 解压
35
+ * @param archivePath - 压缩包路径
36
+ * @param destPath - 目标目录
37
+ */
38
+ async function extractTar(archivePath, destPath) {
39
+ // tar -xzf archive.tar.gz -C dest
40
+ await execCommand('tar', ['-xzf', archivePath, '-C', destPath]);
41
+ }
42
+ /**
43
+ * 使用 unzip 解压(Windows)
44
+ * @param archivePath - 压缩包路径
45
+ * @param destPath - 目标目录
46
+ */
47
+ async function extractZip(archivePath, destPath) {
48
+ if (isWindows()) {
49
+ // Windows: 使用 PowerShell 的 Expand-Archive
50
+ await execCommand('powershell', [
51
+ '-NoProfile',
52
+ '-Command',
53
+ `Expand-Archive -Path '${archivePath}' -DestinationPath '${destPath}' -Force`
54
+ ]);
55
+ }
56
+ else {
57
+ // Linux/macOS: 使用 unzip
58
+ await execCommand('unzip', ['-q', archivePath, '-d', destPath]);
59
+ }
60
+ }
61
+ /**
62
+ * 解压压缩包到指定目录
63
+ * @param archivePath - 压缩包路径
64
+ * @param destPath - 目标目录
65
+ * @throws {Error} 如果解压失败
66
+ */
67
+ export async function extractArchive(archivePath, destPath) {
68
+ const isZip = archivePath.endsWith('.zip');
69
+ if (isZip) {
70
+ await extractZip(archivePath, destPath);
71
+ }
72
+ else {
73
+ // 默认使用 tar
74
+ await extractTar(archivePath, destPath);
75
+ }
76
+ }
77
+ /**
78
+ * 根据平台选择合适的压缩包扩展名
79
+ * @returns 扩展名(.tar.gz 或 .zip)
80
+ */
81
+ export function getArchiveExtension() {
82
+ return isWindows() ? '.zip' : '.tar.gz';
83
+ }
84
+ //# sourceMappingURL=archive-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-extractor.js","sourceRoot":"","sources":["../../src/utils/archive-extractor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C;;;;;GAKG;AACH,SAAS,WAAW,CAAC,OAAe,EAAE,IAAc;IAClD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAErD,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAC/B,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC;YACvE,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACzB,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,UAAU,CAAC,WAAmB,EAAE,QAAgB;IAC7D,kCAAkC;IAClC,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,UAAU,CAAC,WAAmB,EAAE,QAAgB;IAC7D,IAAI,SAAS,EAAE,EAAE,CAAC;QAChB,0CAA0C;QAC1C,MAAM,WAAW,CAAC,YAAY,EAAE;YAC9B,YAAY;YACZ,UAAU;YACV,yBAAyB,WAAW,uBAAuB,QAAQ,UAAU;SAC9E,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,wBAAwB;QACxB,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAmB,EACnB,QAAgB;IAEhB,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE3C,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,UAAU,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,WAAW;QACX,MAAM,UAAU,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 下载工具
3
+ * 使用原生 https 模块下载文件,支持进度显示
4
+ */
5
+ /**
6
+ * 进度回调类型
7
+ */
8
+ export type ProgressCallback = (percent: number) => void;
9
+ /**
10
+ * 下载文件到指定路径
11
+ * @param url - 下载 URL
12
+ * @param destPath - 目标文件路径
13
+ * @param onProgress - 进度回调函数(可选)
14
+ * @throws {DownloadError} 如果下载失败
15
+ */
16
+ export declare function downloadFile(url: string, destPath: string, onProgress?: ProgressCallback): Promise<void>;
17
+ /**
18
+ * 格式化字节数为人类可读格式
19
+ * @param bytes - 字节数
20
+ * @returns 格式化后的字符串
21
+ */
22
+ export declare function formatBytes(bytes: number): string;
23
+ //# sourceMappingURL=downloader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"downloader.d.ts","sourceRoot":"","sources":["../../src/utils/downloader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * 下载工具
3
+ * 使用原生 https 模块下载文件,支持进度显示
4
+ */
5
+ import * as https from 'node:https';
6
+ import { createWriteStream, mkdir } from 'node:fs';
7
+ import { dirname } from 'node:path';
8
+ import { promisify } from 'node:util';
9
+ import { pipeline } from 'node:stream';
10
+ import { DownloadError } from './errors.js';
11
+ const pipelineAsync = promisify(pipeline);
12
+ /**
13
+ * 下载文件到指定路径
14
+ * @param url - 下载 URL
15
+ * @param destPath - 目标文件路径
16
+ * @param onProgress - 进度回调函数(可选)
17
+ * @throws {DownloadError} 如果下载失败
18
+ */
19
+ export async function downloadFile(url, destPath, onProgress) {
20
+ // 确保目标目录存在
21
+ await promisify(mkdir)(dirname(destPath), { recursive: true });
22
+ return new Promise((resolve, reject) => {
23
+ https.get(url, (response) => {
24
+ // 检查响应状态
25
+ if (response.statusCode !== 200) {
26
+ reject(new DownloadError(url, new Error(`HTTP ${response.statusCode}`)));
27
+ return;
28
+ }
29
+ // 获取文件大小
30
+ const contentLength = response.headers['content-length'];
31
+ const totalBytes = contentLength ? parseInt(contentLength, 10) : 0;
32
+ let downloadedBytes = 0;
33
+ // 创建写入流
34
+ const fileStream = createWriteStream(destPath);
35
+ // 监听数据进度
36
+ response.on('data', (chunk) => {
37
+ downloadedBytes += chunk.length;
38
+ if (onProgress && totalBytes > 0) {
39
+ const percent = Math.floor((downloadedBytes / totalBytes) * 100);
40
+ onProgress(percent);
41
+ }
42
+ });
43
+ // 使用 pipeline 管道传输
44
+ pipelineAsync(response, fileStream)
45
+ .then(() => {
46
+ fileStream.close();
47
+ resolve();
48
+ })
49
+ .catch((error) => {
50
+ reject(new DownloadError(url, error));
51
+ });
52
+ }).on('error', (error) => {
53
+ reject(new DownloadError(url, error));
54
+ });
55
+ });
56
+ }
57
+ /**
58
+ * 格式化字节数为人类可读格式
59
+ * @param bytes - 字节数
60
+ * @returns 格式化后的字符串
61
+ */
62
+ export function formatBytes(bytes) {
63
+ if (bytes === 0)
64
+ return '0 B';
65
+ const k = 1024;
66
+ const sizes = ['B', 'KB', 'MB', 'GB'];
67
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
68
+ return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
69
+ }
70
+ //# sourceMappingURL=downloader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"downloader.js","sourceRoot":"","sources":["../../src/utils/downloader.ts"],"names":[],"mappings":"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"}
@@ -22,4 +22,16 @@ export declare class DirectoryNotFoundError extends SkillctlError {
22
22
  export declare class InvalidSkillError extends SkillctlError {
23
23
  constructor(path: string);
24
24
  }
25
+ export declare class InvalidRepoUrlError extends SkillctlError {
26
+ constructor(url: string);
27
+ }
28
+ export declare class SkillValidationError extends SkillctlError {
29
+ constructor(skillName: string, reason: string);
30
+ }
31
+ export declare class DownloadError extends SkillctlError {
32
+ constructor(url: string, originalError: Error);
33
+ }
34
+ export declare class SkillAlreadyExistsError extends SkillctlError {
35
+ constructor(skillName: string);
36
+ }
25
37
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,aAAa;gBACvC,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,uBAAwB,SAAQ,aAAa;gBAC5C,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAI7C;AAED,qBAAa,WAAY,SAAQ,aAAa;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,SAAU,SAAQ,aAAa;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,sBAAuB,SAAQ,aAAa;gBAC3C,IAAI,EAAE,MAAM;CAIzB;AAED,qBAAa,iBAAkB,SAAQ,aAAa;gBACtC,IAAI,EAAE,MAAM;CAIzB"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,aAAa;gBACvC,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,uBAAwB,SAAQ,aAAa;gBAC5C,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAI7C;AAED,qBAAa,WAAY,SAAQ,aAAa;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,SAAU,SAAQ,aAAa;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,sBAAuB,SAAQ,aAAa;gBAC3C,IAAI,EAAE,MAAM;CAIzB;AAED,qBAAa,iBAAkB,SAAQ,aAAa;gBACtC,IAAI,EAAE,MAAM;CAIzB;AAED,qBAAa,mBAAoB,SAAQ,aAAa;gBACxC,GAAG,EAAE,MAAM;CAIxB;AAED,qBAAa,oBAAqB,SAAQ,aAAa;gBACzC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAI9C;AAED,qBAAa,aAAc,SAAQ,aAAa;gBAClC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK;CAI9C;AAED,qBAAa,uBAAwB,SAAQ,aAAa;gBAC5C,SAAS,EAAE,MAAM;CAI9B"}
@@ -43,4 +43,28 @@ export class InvalidSkillError extends SkillctlError {
43
43
  this.name = 'InvalidSkillError';
44
44
  }
45
45
  }
46
+ export class InvalidRepoUrlError extends SkillctlError {
47
+ constructor(url) {
48
+ super(`无法识别的仓库 URL: ${url}`);
49
+ this.name = 'InvalidRepoUrlError';
50
+ }
51
+ }
52
+ export class SkillValidationError extends SkillctlError {
53
+ constructor(skillName, reason) {
54
+ super(`Skill 验证失败: ${skillName}\n 原因: ${reason}`);
55
+ this.name = 'SkillValidationError';
56
+ }
57
+ }
58
+ export class DownloadError extends SkillctlError {
59
+ constructor(url, originalError) {
60
+ super(`下载失败: ${url}\n ${originalError.message}`);
61
+ this.name = 'DownloadError';
62
+ }
63
+ }
64
+ export class SkillAlreadyExistsError extends SkillctlError {
65
+ constructor(skillName) {
66
+ super(`Skill 已存在: ${skillName}\n 使用 --force 强制覆盖(会自动备份旧版本)`);
67
+ this.name = 'SkillAlreadyExistsError';
68
+ }
69
+ }
46
70
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,aAAa;IACnD,YAAY,SAAiB;QAC3B,KAAK,CAAC,cAAc,SAAS,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,aAAa;IACxD,YAAY,SAAiB,EAAE,KAAa;QAC1C,KAAK,CAAC,cAAc,SAAS,KAAK,KAAK,GAAG,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,aAAa;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,aAAa;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,aAAa;IACvD,YAAY,IAAY;QACtB,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,aAAa;IAClD,YAAY,IAAY;QACtB,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,aAAa;IACnD,YAAY,SAAiB;QAC3B,KAAK,CAAC,cAAc,SAAS,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,aAAa;IACxD,YAAY,SAAiB,EAAE,KAAa;QAC1C,KAAK,CAAC,cAAc,SAAS,KAAK,KAAK,GAAG,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,aAAa;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,aAAa;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,aAAa;IACvD,YAAY,IAAY;QACtB,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,aAAa;IAClD,YAAY,IAAY;QACtB,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,aAAa;IACpD,YAAY,GAAW;QACrB,KAAK,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,aAAa;IACrD,YAAY,SAAiB,EAAE,MAAc;QAC3C,KAAK,CAAC,eAAe,SAAS,WAAW,MAAM,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,aAAa;IAC9C,YAAY,GAAW,EAAE,aAAoB;QAC3C,KAAK,CAAC,SAAS,GAAG,OAAO,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,aAAa;IACxD,YAAY,SAAiB;QAC3B,KAAK,CAAC,cAAc,SAAS,+BAA+B,CAAC,CAAC;QAC9D,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * GitHub URL 解析器
3
+ * 解析 GitHub 仓库 URL 并构建下载链接
4
+ * 支持国内镜像服务(如 ghfast.top)
5
+ */
6
+ import type { GitHubRepoInfo } from '../types/index.js';
7
+ /**
8
+ * 解析 GitHub 仓库 URL(支持镜像服务)
9
+ * @param url - GitHub 仓库 URL(可以是镜像 URL)
10
+ * @returns GitHub 仓库信息
11
+ * @throws {InvalidRepoUrlError} 如果 URL 格式无效
12
+ */
13
+ export declare function parseGitHubRepoUrl(url: string): Omit<GitHubRepoInfo, 'subpath' | 'branch'> & {
14
+ mirror?: string;
15
+ };
16
+ /**
17
+ * 构建 GitHub archive 下载 URL
18
+ * @param info - GitHub 仓库信息(包含 subpath 和可选的 mirror)
19
+ * @returns archive 下载 URL
20
+ */
21
+ export declare function buildArchiveUrl(info: GitHubRepoInfo & {
22
+ mirror?: string;
23
+ }): string;
24
+ /**
25
+ * 构建 GitHub archive 下载 URL(ZIP 格式)
26
+ * @param info - GitHub 仓库信息(包含 subpath 和可选的 mirror)
27
+ * @returns archive 下载 URL(ZIP 格式)
28
+ */
29
+ export declare function buildArchiveUrlZip(info: GitHubRepoInfo & {
30
+ mirror?: string;
31
+ }): string;
32
+ /**
33
+ * 验证是否为有效的 GitHub URL
34
+ * @param url - 待验证的 URL
35
+ * @returns 是否为有效的 GitHub URL
36
+ */
37
+ export declare function isValidGitHubUrl(url: string): boolean;
38
+ //# sourceMappingURL=github-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-parser.d.ts","sourceRoot":"","sources":["../../src/utils/github-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAgCxD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,QAAQ,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAgChH;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAWlF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,cAAc,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAWrF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOrD"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * GitHub URL 解析器
3
+ * 解析 GitHub 仓库 URL 并构建下载链接
4
+ * 支持国内镜像服务(如 ghfast.top)
5
+ */
6
+ import { InvalidRepoUrlError } from './errors.js';
7
+ /**
8
+ * 原始 GitHub URL 正则表达式
9
+ * 支持: https://github.com/owner/repo
10
+ * git@github.com:owner/repo.git
11
+ */
12
+ const GITHUB_URL_PATTERNS = [
13
+ /^https?:\/\/github\.com\/([^\/]+)\/([^\/\?#]+)(?:\/)?$/,
14
+ /^git@github\.com:([^\/]+)\/([^\/\.]+)(?:\.git)?$/,
15
+ ];
16
+ /**
17
+ * 国内镜像服务 URL 正则表达式
18
+ * 支持: https://ghfast.top/https://github.com/owner/repo
19
+ * https://ghfast.top/http://github.com/owner/repo
20
+ * https://mirror.ghproxy.com/https://github.com/owner/repo
21
+ */
22
+ const MIRROR_URL_PATTERNS = [
23
+ /^https?:\/\/(?:ghfast\.top|ghproxy\.net|mirror\.ghproxy\.com|gh\.proxy\.com)\/(https?:\/\/github\.com\/([^\/]+)\/([^\/\?#]+))/i,
24
+ ];
25
+ /**
26
+ * 解析 GitHub 仓库 URL(支持镜像服务)
27
+ * @param url - GitHub 仓库 URL(可以是镜像 URL)
28
+ * @returns GitHub 仓库信息
29
+ * @throws {InvalidRepoUrlError} 如果 URL 格式无效
30
+ */
31
+ export function parseGitHubRepoUrl(url) {
32
+ // 去除末尾的斜杠和 .git
33
+ const cleanUrl = url.replace(/\/$/, '').replace(/\.git$/, '');
34
+ // 首先尝试镜像 URL 格式
35
+ for (const pattern of MIRROR_URL_PATTERNS) {
36
+ const match = cleanUrl.match(pattern);
37
+ if (match) {
38
+ // match[1] = https://github.com/owner/repo
39
+ // match[2] = owner
40
+ // match[3] = repo
41
+ const mirrorHost = cleanUrl.match(/^https?:\/\/([^\/]+)/)?.[1];
42
+ return {
43
+ owner: match[2],
44
+ repo: match[3],
45
+ mirror: mirrorHost,
46
+ };
47
+ }
48
+ }
49
+ // 尝试原始 GitHub URL 格式
50
+ for (const pattern of GITHUB_URL_PATTERNS) {
51
+ const match = cleanUrl.match(pattern);
52
+ if (match) {
53
+ return {
54
+ owner: match[1],
55
+ repo: match[2],
56
+ };
57
+ }
58
+ }
59
+ throw new InvalidRepoUrlError(url);
60
+ }
61
+ /**
62
+ * 构建 GitHub archive 下载 URL
63
+ * @param info - GitHub 仓库信息(包含 subpath 和可选的 mirror)
64
+ * @returns archive 下载 URL
65
+ */
66
+ export function buildArchiveUrl(info) {
67
+ const { owner, repo, branch = 'main', mirror } = info;
68
+ const rawUrl = `https://github.com/${owner}/${repo}/archive/refs/heads/${branch}.tar.gz`;
69
+ // 如果使用镜像,将原始 URL 包装在镜像 URL 中
70
+ if (mirror) {
71
+ return `https://${mirror}/${rawUrl}`;
72
+ }
73
+ return rawUrl;
74
+ }
75
+ /**
76
+ * 构建 GitHub archive 下载 URL(ZIP 格式)
77
+ * @param info - GitHub 仓库信息(包含 subpath 和可选的 mirror)
78
+ * @returns archive 下载 URL(ZIP 格式)
79
+ */
80
+ export function buildArchiveUrlZip(info) {
81
+ const { owner, repo, branch = 'main', mirror } = info;
82
+ const rawUrl = `https://github.com/${owner}/${repo}/archive/refs/heads/${branch}.zip`;
83
+ // 如果使用镜像,将原始 URL 包装在镜像 URL 中
84
+ if (mirror) {
85
+ return `https://${mirror}/${rawUrl}`;
86
+ }
87
+ return rawUrl;
88
+ }
89
+ /**
90
+ * 验证是否为有效的 GitHub URL
91
+ * @param url - 待验证的 URL
92
+ * @returns 是否为有效的 GitHub URL
93
+ */
94
+ export function isValidGitHubUrl(url) {
95
+ try {
96
+ parseGitHubRepoUrl(url);
97
+ return true;
98
+ }
99
+ catch {
100
+ return false;
101
+ }
102
+ }
103
+ //# sourceMappingURL=github-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-parser.js","sourceRoot":"","sources":["../../src/utils/github-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;;;GAIG;AACH,MAAM,mBAAmB,GAAG;IAC1B,wDAAwD;IACxD,kDAAkD;CACnD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG;IAC1B,gIAAgI;CACjI,CAAC;AAWF;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,gBAAgB;IAChB,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAE9D,gBAAgB;IAChB,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,KAAK,EAAE,CAAC;YACV,2CAA2C;YAC3C,mBAAmB;YACnB,kBAAkB;YAClB,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/D,OAAO;gBACL,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;gBACf,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;gBACd,MAAM,EAAE,UAAU;aACnB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO;gBACL,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;gBACf,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;aACf,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAA0C;IACxE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEtD,MAAM,MAAM,GAAG,sBAAsB,KAAK,IAAI,IAAI,uBAAuB,MAAM,SAAS,CAAC;IAEzF,6BAA6B;IAC7B,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,WAAW,MAAM,IAAI,MAAM,EAAE,CAAC;IACvC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAA0C;IAC3E,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEtD,MAAM,MAAM,GAAG,sBAAsB,KAAK,IAAI,IAAI,uBAAuB,MAAM,MAAM,CAAC;IAEtF,6BAA6B;IAC7B,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,WAAW,MAAM,IAAI,MAAM,EAAE,CAAC;IACvC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,CAAC;QACH,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Skill 验证器
3
+ * 严格验证 skill 是否有效
4
+ */
5
+ import type { SkillMetadata } from '../types/index.js';
6
+ /**
7
+ * 从 SKILL.md 解析元数据
8
+ * @param skillPath - skill 目录路径
9
+ * @returns Skill 元数据,如果解析失败则返回 null
10
+ */
11
+ export declare function parseSkillMetadata(skillPath: string): Promise<SkillMetadata | null>;
12
+ /**
13
+ * 严格验证 skill 是否有效
14
+ * 1. SKILL.md 必须存在
15
+ * 2. name 字段必须存在
16
+ * @param skillPath - skill 目录路径
17
+ * @returns 验证结果
18
+ */
19
+ export declare function validateSkillStrict(skillPath: string): Promise<{
20
+ valid: boolean;
21
+ metadata?: SkillMetadata;
22
+ error?: string;
23
+ }>;
24
+ /**
25
+ * 从子路径提取显示名称
26
+ * @param subpath - 子路径(如 agent/skills/headless-web-viewer)
27
+ * @returns 显示名称(如 headless-web-viewer)
28
+ */
29
+ export declare function extractDisplayName(subpath: string): string;
30
+ //# sourceMappingURL=skill-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-validator.d.ts","sourceRoot":"","sources":["../../src/utils/skill-validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA8CvD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAyB/B;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAqCvE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Skill 验证器
3
+ * 严格验证 skill 是否有效
4
+ */
5
+ import { readFile, readdir } from 'node:fs/promises';
6
+ import { join } from 'node:path';
7
+ /**
8
+ * 解析 SKILL.md 中的 YAML frontmatter
9
+ * @param content - SKILL.md 文件内容
10
+ * @returns 解析后的元数据
11
+ */
12
+ function parseFrontmatter(content) {
13
+ // 检查是否有 frontmatter(以 --- 开始和结束)
14
+ const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---/;
15
+ const match = content.match(frontmatterRegex);
16
+ if (!match) {
17
+ return null;
18
+ }
19
+ const yamlContent = match[1];
20
+ // 简单的 YAML 解析器(只处理键值对)
21
+ const result = {};
22
+ const lines = yamlContent.split('\n');
23
+ for (const line of lines) {
24
+ const trimmed = line.trim();
25
+ if (!trimmed || trimmed.startsWith('#')) {
26
+ continue;
27
+ }
28
+ const colonIndex = trimmed.indexOf(':');
29
+ if (colonIndex > 0) {
30
+ const key = trimmed.substring(0, colonIndex).trim();
31
+ let value = trimmed.substring(colonIndex + 1).trim();
32
+ // 去除引号
33
+ if ((value.startsWith('"') && value.endsWith('"')) ||
34
+ (value.startsWith("'") && value.endsWith("'"))) {
35
+ value = value.slice(1, -1);
36
+ }
37
+ result[key] = value;
38
+ }
39
+ }
40
+ return result;
41
+ }
42
+ /**
43
+ * 从 SKILL.md 解析元数据
44
+ * @param skillPath - skill 目录路径
45
+ * @returns Skill 元数据,如果解析失败则返回 null
46
+ */
47
+ export async function parseSkillMetadata(skillPath) {
48
+ const skillMdPath = join(skillPath, 'SKILL.md');
49
+ try {
50
+ const content = await readFile(skillMdPath, 'utf-8');
51
+ const frontmatter = parseFrontmatter(content);
52
+ if (!frontmatter) {
53
+ return null;
54
+ }
55
+ const name = frontmatter['name'];
56
+ const description = frontmatter['description'];
57
+ if (!name || typeof name !== 'string') {
58
+ return null;
59
+ }
60
+ return {
61
+ name,
62
+ description,
63
+ };
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ }
69
+ /**
70
+ * 严格验证 skill 是否有效
71
+ * 1. SKILL.md 必须存在
72
+ * 2. name 字段必须存在
73
+ * @param skillPath - skill 目录路径
74
+ * @returns 验证结果
75
+ */
76
+ export async function validateSkillStrict(skillPath) {
77
+ // 检查 SKILL.md 是否存在
78
+ const skillMdPath = join(skillPath, 'SKILL.md');
79
+ let files = [];
80
+ try {
81
+ files = await readdir(skillPath);
82
+ }
83
+ catch {
84
+ return {
85
+ valid: false,
86
+ error: '无法读取 skill 目录',
87
+ };
88
+ }
89
+ const hasSkillMd = files.some((f) => f === 'SKILL.md');
90
+ if (!hasSkillMd) {
91
+ return {
92
+ valid: false,
93
+ error: '未找到 SKILL.md 文件\n 这可能不是一个有效的 Claude Skill',
94
+ };
95
+ }
96
+ // 解析元数据
97
+ const metadata = await parseSkillMetadata(skillPath);
98
+ if (!metadata || !metadata.name) {
99
+ return {
100
+ valid: false,
101
+ error: 'SKILL.md 中缺少 name 字段定义\n 请确保 SKILL.md 包含正确的元数据',
102
+ };
103
+ }
104
+ return {
105
+ valid: true,
106
+ metadata,
107
+ };
108
+ }
109
+ /**
110
+ * 从子路径提取显示名称
111
+ * @param subpath - 子路径(如 agent/skills/headless-web-viewer)
112
+ * @returns 显示名称(如 headless-web-viewer)
113
+ */
114
+ export function extractDisplayName(subpath) {
115
+ const parts = subpath.split('/');
116
+ return parts[parts.length - 1];
117
+ }
118
+ //# sourceMappingURL=skill-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-validator.js","sourceRoot":"","sources":["../../src/utils/skill-validator.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dayinxisheng/skillctl",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Claude Skills 管理工具 - 管理 Claude Skills 的激活状态和项目归档",
5
5
  "main": "dist/index.js",
6
6
  "bin": {