eskill 1.0.18 → 1.0.21

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/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
3
  import ora from 'ora';
4
- import { installFromGitUrl, listSkills, removeSkill } from './lib/installer.js';
4
+ import { installFromGitUrl, listSkills, removeSkill, cleanupAllSkills, cleanupAll } from './lib/installer.js';
5
5
  import { AGENTS, getDefaultAgent } from './lib/agent-config.js';
6
6
  import { bashCompletionScript, zshCompletionScript, listSkillsForCompletion } from './lib/completion.js';
7
7
  import { searchSkills, formatSkillList } from './lib/search.js';
@@ -203,6 +203,39 @@ program
203
203
  }
204
204
  });
205
205
 
206
+ // 清理命令
207
+ program
208
+ .command('cleanup')
209
+ .description('清理 eskill 数据')
210
+ .option('-a, --all', '清理所有数据(包括配置和技能)', false)
211
+ .action(async (options) => {
212
+ try {
213
+ if (options.all) {
214
+ console.log('\n⚠️ 警告:这将删除所有 eskill 数据(包括 API Key 配置和已安装的技能)');
215
+
216
+ const rl = readline.createInterface({
217
+ input: process.stdin,
218
+ output: process.stdout
219
+ });
220
+
221
+ rl.question('确认完全清理?: ', (answer) => {
222
+ rl.close();
223
+ if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
224
+ cleanupAll();
225
+ } else {
226
+ console.log('\n已取消清理\n');
227
+ }
228
+ });
229
+ } else {
230
+ console.log('\n清理所有已安装的技能(保留配置)...\n');
231
+ cleanupAllSkills();
232
+ }
233
+ } catch (error) {
234
+ console.error(`\n❌ 清理失败: ${error.message}\n`);
235
+ process.exit(1);
236
+ }
237
+ });
238
+
206
239
  // 列出支持的 agents
207
240
  program
208
241
  .command('agents')
package/lib/installer.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { execSync } from 'child_process';
2
- import { existsSync, mkdirSync, symlinkSync, rmSync, readdirSync, writeFileSync, readFileSync } from 'fs';
2
+ import { existsSync, mkdirSync, symlinkSync, rmSync, readdirSync, writeFileSync, readFileSync, copyFileSync } from 'fs';
3
3
  import { join, basename, dirname } from 'path';
4
- import { tmpdir } from 'os';
4
+ import { tmpdir, homedir } from 'os';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { parseGitUrl } from './git-url-parser.js';
7
7
  import { AGENTS, expandHomePath } from './agent-config.js';
@@ -19,11 +19,63 @@ function getEskillPackageDir() {
19
19
  }
20
20
 
21
21
  /**
22
- * 获取技能存储目录
22
+ * 获取技能存储目录(用户主目录下,不受 npm 更新影响)
23
23
  */
24
24
  function getSkillsStorageDir() {
25
- const pkgDir = getEskillPackageDir();
26
- return join(pkgDir, 'skills-storage');
25
+ return join(homedir(), '.eskill', 'skills');
26
+ }
27
+
28
+ /**
29
+ * 迁移旧位置的技能到新位置
30
+ */
31
+ function migrateOldSkills() {
32
+ const __filename = fileURLToPath(import.meta.url);
33
+ const __dirname = dirname(__filename);
34
+ const pkgDir = dirname(__dirname);
35
+ const oldDir = join(pkgDir, 'skills-storage');
36
+ const newDir = getSkillsStorageDir();
37
+
38
+ // 如果旧位置不存在,无需迁移
39
+ if (!existsSync(oldDir)) {
40
+ return;
41
+ }
42
+
43
+ // 如果新位置已存在,不重复迁移
44
+ if (existsSync(newDir)) {
45
+ return;
46
+ }
47
+
48
+ try {
49
+ // 创建新目录
50
+ mkdirSync(newDir, { recursive: true });
51
+
52
+ // 读取旧目录中的技能
53
+ const skills = readdirSync(oldDir, { withFileTypes: true })
54
+ .filter(dirent => dirent.isDirectory());
55
+
56
+ if (skills.length === 0) {
57
+ return;
58
+ }
59
+
60
+ console.log(`\n检测到旧位置的技能,正在迁移...`);
61
+
62
+ // 迁移每个技能
63
+ for (const skill of skills) {
64
+ const oldPath = join(oldDir, skill.name);
65
+ const newPath = join(newDir, skill.name);
66
+
67
+ // 递归复制目录
68
+ execSync(`cp -r "${oldPath}" "${newPath}"`, { stdio: 'inherit' });
69
+ console.log(` ✓ 迁移: ${skill.name}`);
70
+ }
71
+
72
+ console.log(`\n技能迁移完成!\n`);
73
+ console.log(`旧位置: ${oldDir}`);
74
+ console.log(`新位置: ${newDir}`);
75
+ console.log(`\n提示: 可以删除旧位置以节省空间\n`);
76
+ } catch (error) {
77
+ console.log(`\n迁移失败: ${error.message}`);
78
+ }
27
79
  }
28
80
 
29
81
  /**
@@ -220,8 +272,8 @@ export async function installFromGitUrl(gitUrl, options = {}) {
220
272
  }
221
273
 
222
274
  console.log(`\n✓ 技能已安装到: ${targetPath}`);
223
- console.log(` 存储位置: eskill 包目录`);
224
- console.log(` 说明: 卸载 eskill 时会自动删除所有技能`);
275
+ console.log(` 存储位置: ~/.eskill/skills/`);
276
+ console.log(` 说明: 技能永久保存,更新 eskill 不会丢失`);
225
277
 
226
278
  // 保存技能元数据(作者、Git URL 等)
227
279
  saveSkillMeta(targetPath, {
@@ -248,6 +300,9 @@ export async function installFromGitUrl(gitUrl, options = {}) {
248
300
  * 列出已安装的技能
249
301
  */
250
302
  export function listSkills(agent = 'claude') {
303
+ // 自动迁移旧位置的技能
304
+ migrateOldSkills();
305
+
251
306
  const skillDir = getSkillsStorageDir();
252
307
 
253
308
  if (!existsSync(skillDir)) {
@@ -284,6 +339,46 @@ export function removeSkill(skillName, agent = 'claude') {
284
339
  console.log(`✓ 已删除技能: ${skillName}`);
285
340
  }
286
341
 
342
+ /**
343
+ * 清理所有技能(用于卸载)
344
+ */
345
+ export function cleanupAllSkills() {
346
+ const skillDir = getSkillsStorageDir();
347
+
348
+ if (!existsSync(skillDir)) {
349
+ console.log('没有需要清理的技能');
350
+ return;
351
+ }
352
+
353
+ try {
354
+ rmSync(skillDir, { recursive: true, force: true });
355
+ console.log(`✓ 已清理所有技能: ${skillDir}`);
356
+ } catch (error) {
357
+ console.error(`清理失败: ${error.message}`);
358
+ throw error;
359
+ }
360
+ }
361
+
362
+ /**
363
+ * 完全清理 eskill(包括配置和技能)
364
+ */
365
+ export function cleanupAll() {
366
+ const eskillDir = join(homedir(), '.eskill');
367
+
368
+ if (!existsSync(eskillDir)) {
369
+ console.log('没有需要清理的数据');
370
+ return;
371
+ }
372
+
373
+ try {
374
+ rmSync(eskillDir, { recursive: true, force: true });
375
+ console.log(`✓ 已完全清理 eskill 数据: ${eskillDir}`);
376
+ } catch (error) {
377
+ console.error(`清理失败: ${error.message}`);
378
+ throw error;
379
+ }
380
+ }
381
+
287
382
  /**
288
383
  * 获取技能存储目录路径
289
384
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eskill",
3
- "version": "1.0.18",
3
+ "version": "1.0.21",
4
4
  "description": "Unified AI Agent Skills Management - Install skills from Git URLs",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "scripts": {
11
11
  "prepublishOnly": "node scripts/pre-publish-check.js",
12
+ "preuninstall": "node scripts/uninstall.js",
12
13
  "test": "node scripts/pre-publish-check.js",
13
14
  "security-check": "node scripts/pre-publish-check.js"
14
15
  },
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * eskill 卸载脚本
4
+ * 在 npm uninstall 时自动清理技能和配置
5
+ */
6
+ import { existsSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+ import { rmSync } from 'fs';
10
+
11
+ const ESKILL_DIR = join(homedir(), '.eskill');
12
+
13
+ if (existsSync(ESKILL_DIR)) {
14
+ try {
15
+ // 删除整个 .eskill 目录
16
+ rmSync(ESKILL_DIR, { recursive: true, force: true });
17
+ console.log('✓ eskill 数据已清理');
18
+ } catch (error) {
19
+ console.error(`清理失败: ${error.message}`);
20
+ }
21
+ }