@dayinxisheng/skillctl 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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/dist/commands/activate.d.ts +9 -0
  4. package/dist/commands/activate.d.ts.map +1 -0
  5. package/dist/commands/activate.js +62 -0
  6. package/dist/commands/activate.js.map +1 -0
  7. package/dist/commands/all-list.d.ts +5 -0
  8. package/dist/commands/all-list.d.ts.map +1 -0
  9. package/dist/commands/all-list.js +22 -0
  10. package/dist/commands/all-list.js.map +1 -0
  11. package/dist/commands/config.d.ts +5 -0
  12. package/dist/commands/config.d.ts.map +1 -0
  13. package/dist/commands/config.js +16 -0
  14. package/dist/commands/config.js.map +1 -0
  15. package/dist/commands/deactivate.d.ts +9 -0
  16. package/dist/commands/deactivate.d.ts.map +1 -0
  17. package/dist/commands/deactivate.js +41 -0
  18. package/dist/commands/deactivate.js.map +1 -0
  19. package/dist/commands/import.d.ts +6 -0
  20. package/dist/commands/import.d.ts.map +1 -0
  21. package/dist/commands/import.js +32 -0
  22. package/dist/commands/import.js.map +1 -0
  23. package/dist/commands/list.d.ts +5 -0
  24. package/dist/commands/list.d.ts.map +1 -0
  25. package/dist/commands/list.js +48 -0
  26. package/dist/commands/list.js.map +1 -0
  27. package/dist/commands/locate.d.ts +5 -0
  28. package/dist/commands/locate.d.ts.map +1 -0
  29. package/dist/commands/locate.js +37 -0
  30. package/dist/commands/locate.js.map +1 -0
  31. package/dist/commands/set-repo.d.ts +6 -0
  32. package/dist/commands/set-repo.d.ts.map +1 -0
  33. package/dist/commands/set-repo.js +19 -0
  34. package/dist/commands/set-repo.js.map +1 -0
  35. package/dist/commands/status.d.ts +5 -0
  36. package/dist/commands/status.d.ts.map +1 -0
  37. package/dist/commands/status.js +25 -0
  38. package/dist/commands/status.js.map +1 -0
  39. package/dist/index.d.ts +8 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +184 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/lib/config-manager.d.ts +34 -0
  44. package/dist/lib/config-manager.d.ts.map +1 -0
  45. package/dist/lib/config-manager.js +77 -0
  46. package/dist/lib/config-manager.js.map +1 -0
  47. package/dist/lib/link-handler.d.ts +37 -0
  48. package/dist/lib/link-handler.d.ts.map +1 -0
  49. package/dist/lib/link-handler.js +114 -0
  50. package/dist/lib/link-handler.js.map +1 -0
  51. package/dist/lib/skill-manager.d.ts +49 -0
  52. package/dist/lib/skill-manager.d.ts.map +1 -0
  53. package/dist/lib/skill-manager.js +215 -0
  54. package/dist/lib/skill-manager.js.map +1 -0
  55. package/dist/types/index.d.ts +60 -0
  56. package/dist/types/index.d.ts.map +1 -0
  57. package/dist/types/index.js +5 -0
  58. package/dist/types/index.js.map +1 -0
  59. package/dist/utils/errors.d.ts +25 -0
  60. package/dist/utils/errors.d.ts.map +1 -0
  61. package/dist/utils/errors.js +46 -0
  62. package/dist/utils/errors.js.map +1 -0
  63. package/dist/utils/output.d.ts +14 -0
  64. package/dist/utils/output.d.ts.map +1 -0
  65. package/dist/utils/output.js +61 -0
  66. package/dist/utils/output.js.map +1 -0
  67. package/dist/utils/platform.d.ts +17 -0
  68. package/dist/utils/platform.d.ts.map +1 -0
  69. package/dist/utils/platform.js +39 -0
  70. package/dist/utils/platform.js.map +1 -0
  71. package/package.json +54 -0
package/dist/index.js ADDED
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * skillctl - Claude Skills 管理工具
4
+ *
5
+ * TypeScript/JavaScript 版本
6
+ */
7
+ import { Command } from 'commander';
8
+ import { activate } from './commands/activate.js';
9
+ import { deactivate } from './commands/deactivate.js';
10
+ import { importSkill } from './commands/import.js';
11
+ import { locate } from './commands/locate.js';
12
+ import { status } from './commands/status.js';
13
+ import { list } from './commands/list.js';
14
+ import { allList } from './commands/all-list.js';
15
+ import { setRepo, getRepo } from './commands/set-repo.js';
16
+ import { showConfig } from './commands/config.js';
17
+ import { createRequire } from 'node:module';
18
+ // 从 package.json 读取版本号
19
+ const require = createRequire(import.meta.url);
20
+ const packageJson = require('../package.json');
21
+ const VERSION = packageJson.version;
22
+ const program = new Command();
23
+ program
24
+ .name('skillctl')
25
+ .description('Claude Skills 管理工具 - 管理 Claude Skills 的激活状态和项目归档')
26
+ .version(VERSION);
27
+ // Activate 命令
28
+ program
29
+ .command('activate')
30
+ .description('激活指定的 skill')
31
+ .argument('[skill-name]', 'skill 名称')
32
+ .option('-u, --user', '激活到 user 级别 (~/.claude/skills/)', true)
33
+ .option('-p, --project', '激活到 project 级别 (./.claude/skills/)')
34
+ .option('-a, --all', '批量激活所有 skills')
35
+ .action(async (skillName, options) => {
36
+ try {
37
+ const scope = options.project ? 'project' : 'user';
38
+ if (options.all) {
39
+ await activate({ scope, all: true });
40
+ }
41
+ else if (skillName) {
42
+ await activate(skillName, { scope, all: false });
43
+ }
44
+ else {
45
+ console.error('请指定 skill 名称或使用 --all 选项');
46
+ process.exit(1);
47
+ }
48
+ }
49
+ catch (error) {
50
+ process.exit(1);
51
+ }
52
+ });
53
+ // Deactivate 命令
54
+ program
55
+ .command('deactivate')
56
+ .description('停用已激活的 skill')
57
+ .argument('[skill-name]', 'skill 名称')
58
+ .option('-u, --user', '停用 user 级别的 skill', true)
59
+ .option('-p, --project', '停用 project 级别的 skill')
60
+ .option('-a, --all', '批量停用所有 skills')
61
+ .action(async (skillName, options) => {
62
+ try {
63
+ const scope = options.project ? 'project' : 'user';
64
+ if (options.all) {
65
+ await deactivate({ scope, all: true });
66
+ }
67
+ else if (skillName) {
68
+ await deactivate(skillName, { scope, all: false });
69
+ }
70
+ else {
71
+ console.error('请指定 skill 名称或使用 --all 选项');
72
+ process.exit(1);
73
+ }
74
+ }
75
+ catch (error) {
76
+ process.exit(1);
77
+ }
78
+ });
79
+ // Import 命令
80
+ program
81
+ .command('import')
82
+ .description('将外部 skill 导入到项目 skills 目录')
83
+ .argument('<skill-name>', 'skill 名称')
84
+ .option('-u, --user', '从 user 级别导入 (~/.claude/skills/)', true)
85
+ .option('-p, --project', '从 project 级别导入 (./.claude/skills/)')
86
+ .action(async (skillName, options) => {
87
+ try {
88
+ const scope = options.project ? 'project' : 'user';
89
+ await importSkill(skillName, { scope });
90
+ }
91
+ catch (error) {
92
+ process.exit(1);
93
+ }
94
+ });
95
+ // Locate 命令
96
+ program
97
+ .command('locate')
98
+ .description('显示 skill 的实际存储位置')
99
+ .argument('<skill-name>', 'skill 名称')
100
+ .action(async (skillName) => {
101
+ try {
102
+ await locate(skillName);
103
+ }
104
+ catch (error) {
105
+ process.exit(1);
106
+ }
107
+ });
108
+ // Status 命令
109
+ program
110
+ .command('status')
111
+ .description('显示 skills 的激活状态')
112
+ .action(async () => {
113
+ try {
114
+ await status();
115
+ }
116
+ catch (error) {
117
+ process.exit(1);
118
+ }
119
+ });
120
+ // List 命令
121
+ program
122
+ .command('list')
123
+ .alias('ls')
124
+ .description('列出当前激活的 skills')
125
+ .action(async () => {
126
+ try {
127
+ await list();
128
+ }
129
+ catch (error) {
130
+ process.exit(1);
131
+ }
132
+ });
133
+ // All-list 命令
134
+ program
135
+ .command('all-list')
136
+ .alias('ls-all')
137
+ .description('列出项目中所有可用的 skills')
138
+ .action(async () => {
139
+ try {
140
+ await allList();
141
+ }
142
+ catch (error) {
143
+ process.exit(1);
144
+ }
145
+ });
146
+ // Set-repo 命令
147
+ program
148
+ .command('set-repo')
149
+ .description('设置 skills 仓库路径')
150
+ .argument('<path>', '仓库路径')
151
+ .action(async (path) => {
152
+ try {
153
+ await setRepo(path);
154
+ }
155
+ catch (error) {
156
+ process.exit(1);
157
+ }
158
+ });
159
+ // Get-repo 命令
160
+ program
161
+ .command('get-repo')
162
+ .description('查看当前设置的仓库路径')
163
+ .action(async () => {
164
+ try {
165
+ await getRepo();
166
+ }
167
+ catch (error) {
168
+ process.exit(1);
169
+ }
170
+ });
171
+ // Config 命令
172
+ program
173
+ .command('config')
174
+ .description('查看配置信息')
175
+ .action(async () => {
176
+ try {
177
+ await showConfig();
178
+ }
179
+ catch (error) {
180
+ process.exit(1);
181
+ }
182
+ });
183
+ program.parse();
184
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 配置管理器
3
+ * 管理 ~/.config/skillctl/config.json
4
+ */
5
+ import type { SkillctlConfig } from '../types/index.js';
6
+ /**
7
+ * 读取配置
8
+ */
9
+ export declare function readConfig(): Promise<SkillctlConfig>;
10
+ /**
11
+ * 写入配置
12
+ */
13
+ export declare function writeConfig(config: SkillctlConfig): Promise<void>;
14
+ /**
15
+ * 设置仓库路径
16
+ */
17
+ export declare function setRepository(repoPath: string): Promise<void>;
18
+ /**
19
+ * 获取仓库路径
20
+ */
21
+ export declare function getRepository(): Promise<string | undefined>;
22
+ /**
23
+ * 清除仓库配置
24
+ */
25
+ export declare function clearRepository(): Promise<void>;
26
+ /**
27
+ * 获取配置目录路径
28
+ */
29
+ export declare function getConfigDir(): string;
30
+ /**
31
+ * 获取配置文件路径
32
+ */
33
+ export declare function getConfigFile(): string;
34
+ //# sourceMappingURL=config-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-manager.d.ts","sourceRoot":"","sources":["../../src/lib/config-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAcxD;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC,CAY1D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAInE;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAGjE;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAIrD;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * 配置管理器
3
+ * 管理 ~/.config/skillctl/config.json
4
+ */
5
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
6
+ import { existsSync } from 'node:fs';
7
+ import { join } from 'node:path';
8
+ import { getHomeDir } from '../utils/platform.js';
9
+ const CONFIG_DIR = join(getHomeDir(), '.config', 'skillctl');
10
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
11
+ /**
12
+ * 确保配置目录存在
13
+ */
14
+ async function ensureConfigDir() {
15
+ if (!existsSync(CONFIG_DIR)) {
16
+ await mkdir(CONFIG_DIR, { recursive: true });
17
+ }
18
+ }
19
+ /**
20
+ * 读取配置
21
+ */
22
+ export async function readConfig() {
23
+ try {
24
+ if (!existsSync(CONFIG_FILE)) {
25
+ return {};
26
+ }
27
+ const content = await readFile(CONFIG_FILE, 'utf-8');
28
+ return JSON.parse(content);
29
+ }
30
+ catch (error) {
31
+ // 配置文件损坏时返回空配置
32
+ return {};
33
+ }
34
+ }
35
+ /**
36
+ * 写入配置
37
+ */
38
+ export async function writeConfig(config) {
39
+ await ensureConfigDir();
40
+ await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
41
+ }
42
+ /**
43
+ * 设置仓库路径
44
+ */
45
+ export async function setRepository(repoPath) {
46
+ const config = await readConfig();
47
+ config.repository = repoPath;
48
+ await writeConfig(config);
49
+ }
50
+ /**
51
+ * 获取仓库路径
52
+ */
53
+ export async function getRepository() {
54
+ const config = await readConfig();
55
+ return config.repository;
56
+ }
57
+ /**
58
+ * 清除仓库配置
59
+ */
60
+ export async function clearRepository() {
61
+ const config = await readConfig();
62
+ delete config.repository;
63
+ await writeConfig(config);
64
+ }
65
+ /**
66
+ * 获取配置目录路径
67
+ */
68
+ export function getConfigDir() {
69
+ return CONFIG_DIR;
70
+ }
71
+ /**
72
+ * 获取配置文件路径
73
+ */
74
+ export function getConfigFile() {
75
+ return CONFIG_FILE;
76
+ }
77
+ //# sourceMappingURL=config-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/lib/config-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAW,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAC7D,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEpD;;GAEG;AACH,KAAK,UAAU,eAAe;IAC5B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAmB,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAe;QACf,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAsB;IACtD,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,MAAM,CAAC,UAAU,GAAG,QAAQ,CAAC;IAC7B,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,OAAO,MAAM,CAAC,UAAU,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,OAAO,MAAM,CAAC,UAAU,CAAC;IACzB,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * 链接处理器 - 跨平台软链接处理
3
+ * Windows 使用 junction,其他系统使用 symlink
4
+ */
5
+ /**
6
+ * 创建软链接
7
+ */
8
+ export declare function createLink(target: string, linkPath: string): Promise<void>;
9
+ /**
10
+ * 删除软链接
11
+ */
12
+ export declare function removeLink(linkPath: string): Promise<void>;
13
+ /**
14
+ * 检查路径是否为软链接
15
+ */
16
+ export declare function isSymlink(path: string): boolean;
17
+ /**
18
+ * 读取软链接目标
19
+ */
20
+ export declare function readLinkTarget(linkPath: string): string | undefined;
21
+ /**
22
+ * 解析软链接获取实际路径
23
+ */
24
+ export declare function resolveLink(linkPath: string): string | undefined;
25
+ /**
26
+ * 验证链接是否指向正确的目标
27
+ */
28
+ export declare function validateLink(linkPath: string, expectedTarget: string): boolean;
29
+ /**
30
+ * 检查路径是否存在
31
+ */
32
+ export declare function pathExists(path: string): boolean;
33
+ /**
34
+ * 检查路径是否为目录
35
+ */
36
+ export declare function isDirectory(path: string): boolean;
37
+ //# sourceMappingURL=link-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-handler.d.ts","sourceRoot":"","sources":["../../src/lib/link-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQhE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAO/C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMnE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAahE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAW9E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjD"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * 链接处理器 - 跨平台软链接处理
3
+ * Windows 使用 junction,其他系统使用 symlink
4
+ */
5
+ import { mkdir, symlink, unlink } from 'node:fs/promises';
6
+ import { existsSync, readlinkSync, lstatSync } from 'node:fs';
7
+ import { join, relative, resolve, isAbsolute } from 'node:path';
8
+ import { isWindows } from '../utils/platform.js';
9
+ import { LinkError } from '../utils/errors.js';
10
+ /**
11
+ * 获取平台对应的链接类型
12
+ */
13
+ function getLinkType() {
14
+ return isWindows() ? 'junction' : 'dir';
15
+ }
16
+ /**
17
+ * 创建软链接
18
+ */
19
+ export async function createLink(target, linkPath) {
20
+ try {
21
+ // 确保目标目录存在
22
+ const linkDir = join(linkPath, '..');
23
+ if (!existsSync(linkDir)) {
24
+ await mkdir(linkDir, { recursive: true });
25
+ }
26
+ // Windows 上使用绝对路径,其他系统可以使用相对路径
27
+ const linkTarget = isWindows() ? resolve(target) : relative(linkDir, target);
28
+ await symlink(linkTarget, linkPath, getLinkType());
29
+ }
30
+ catch (error) {
31
+ throw new LinkError(`创建链接失败: ${linkPath} -> ${target}: ${error instanceof Error ? error.message : String(error)}`);
32
+ }
33
+ }
34
+ /**
35
+ * 删除软链接
36
+ */
37
+ export async function removeLink(linkPath) {
38
+ try {
39
+ await unlink(linkPath);
40
+ }
41
+ catch (error) {
42
+ throw new LinkError(`删除链接失败: ${linkPath}: ${error instanceof Error ? error.message : String(error)}`);
43
+ }
44
+ }
45
+ /**
46
+ * 检查路径是否为软链接
47
+ */
48
+ export function isSymlink(path) {
49
+ try {
50
+ const stats = lstatSync(path);
51
+ return stats.isSymbolicLink();
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ }
57
+ /**
58
+ * 读取软链接目标
59
+ */
60
+ export function readLinkTarget(linkPath) {
61
+ try {
62
+ return readlinkSync(linkPath);
63
+ }
64
+ catch {
65
+ return undefined;
66
+ }
67
+ }
68
+ /**
69
+ * 解析软链接获取实际路径
70
+ */
71
+ export function resolveLink(linkPath) {
72
+ const target = readLinkTarget(linkPath);
73
+ if (!target) {
74
+ return undefined;
75
+ }
76
+ // 如果是相对路径,转换为绝对路径
77
+ if (!isAbsolute(target)) {
78
+ const linkDir = join(linkPath, '..');
79
+ return resolve(linkDir, target);
80
+ }
81
+ return target;
82
+ }
83
+ /**
84
+ * 验证链接是否指向正确的目标
85
+ */
86
+ export function validateLink(linkPath, expectedTarget) {
87
+ const resolved = resolveLink(linkPath);
88
+ if (!resolved) {
89
+ return false;
90
+ }
91
+ // 规范化路径后比较
92
+ const normalizedResolved = resolve(resolved);
93
+ const normalizedExpected = resolve(expectedTarget);
94
+ return normalizedResolved === normalizedExpected;
95
+ }
96
+ /**
97
+ * 检查路径是否存在
98
+ */
99
+ export function pathExists(path) {
100
+ return existsSync(path);
101
+ }
102
+ /**
103
+ * 检查路径是否为目录
104
+ */
105
+ export function isDirectory(path) {
106
+ try {
107
+ const stats = lstatSync(path);
108
+ return stats.isDirectory();
109
+ }
110
+ catch {
111
+ return false;
112
+ }
113
+ }
114
+ //# sourceMappingURL=link-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-handler.js","sourceRoot":"","sources":["../../src/lib/link-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Skill 管理器 - 核心业务逻辑
3
+ */
4
+ import type { Scope, SkillStatus, LinkInfo, SkillValidationResult } from '../types/index.js';
5
+ /**
6
+ * 获取激活目录路径
7
+ */
8
+ export declare function getActiveDir(scope: Scope): string;
9
+ /**
10
+ * 获取项目 skills 目录
11
+ */
12
+ export declare function getProjectSkillsDir(): Promise<string>;
13
+ /**
14
+ * 获取 skill 源路径(项目中的实际位置)
15
+ */
16
+ export declare function getSkillSourcePath(skillName: string): Promise<string>;
17
+ /**
18
+ * 验证 skill 是否有效
19
+ */
20
+ export declare function validateSkill(skillName: string): Promise<SkillValidationResult>;
21
+ /**
22
+ * 检查 skill 是否已激活
23
+ */
24
+ export declare function isSkillActive(skillName: string, scope: Scope): Promise<boolean>;
25
+ /**
26
+ * 激活单个 skill
27
+ */
28
+ export declare function activateSkill(skillName: string, scope: Scope): Promise<void>;
29
+ /**
30
+ * 停用单个 skill
31
+ */
32
+ export declare function deactivateSkill(skillName: string, scope: Scope): Promise<void>;
33
+ /**
34
+ * 获取所有可用的 skills
35
+ */
36
+ export declare function getAllSkills(): Promise<string[]>;
37
+ /**
38
+ * 获取 skills 状态
39
+ */
40
+ export declare function getSkillsStatus(): Promise<SkillStatus[]>;
41
+ /**
42
+ * 获取已激活的 skills
43
+ */
44
+ export declare function getActiveSkills(scope: Scope): Promise<LinkInfo[]>;
45
+ /**
46
+ * 定位 skill(在多个位置搜索)
47
+ */
48
+ export declare function locateSkill(skillName: string): Promise<LinkInfo[]>;
49
+ //# sourceMappingURL=skill-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-manager.d.ts","sourceRoot":"","sources":["../../src/lib/skill-manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AA0B7F;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAKjD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAG3D;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG3E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAsBrF;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAUrF;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBlF;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpF;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBtD;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAa9D;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA+BvE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA0CxE"}