eskill 1.0.25 → 1.0.27

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 (3) hide show
  1. package/cli.js +8 -4
  2. package/lib/installer.js +84 -66
  3. package/package.json +1 -1
package/cli.js CHANGED
@@ -13,7 +13,7 @@ const program = new Command();
13
13
  program
14
14
  .name('eskill')
15
15
  .description('Unified AI Agent Skills Management - Install skills from Git URLs')
16
- .version('1.0.25');
16
+ .version('1.0.27');
17
17
 
18
18
  // 安装命令
19
19
  program
@@ -95,11 +95,15 @@ program
95
95
  program
96
96
  .command('update')
97
97
  .description('更新技能')
98
- .argument('[name]', '技能名称(不指定则更新所有)')
98
+ .argument('[name]', '技能名称(不指定或 "all" 则更新所有)')
99
99
  .option('-f, --force', '强制更新(即使版本相同)', false)
100
100
  .action(async (name, options) => {
101
101
  try {
102
- if (name) {
102
+ // 支持显式使用 "all" 参数
103
+ if (name === 'all' || name === 'All' || name === 'ALL') {
104
+ // 更新所有技能
105
+ await updateAllSkills(options);
106
+ } else if (name) {
103
107
  // 更新单个技能
104
108
  console.log(`\n检查技能: ${name}`);
105
109
  const result = await updateSkill(name, options);
@@ -114,7 +118,7 @@ program
114
118
  console.log(` 新版本: ${result.newVersion}\n`);
115
119
  }
116
120
  } else {
117
- // 更新所有技能
121
+ // 更新所有技能(不指定参数时)
118
122
  await updateAllSkills(options);
119
123
  }
120
124
  } catch (error) {
package/lib/installer.js CHANGED
@@ -495,6 +495,23 @@ export function getSkillsDir() {
495
495
  return getSkillsStorageDir();
496
496
  }
497
497
 
498
+ /**
499
+ * 获取远程仓库的 commit hash(不克隆)
500
+ */
501
+ function getRemoteCommitHash(gitUrl, branch) {
502
+ try {
503
+ const result = execSync(
504
+ `git ls-remote "${gitUrl}" refs/heads/${branch}`,
505
+ { encoding: 'utf-8' }
506
+ );
507
+ // 输出格式: "commitHash\trefs/heads/branch"
508
+ const match = result.trim().split('\t');
509
+ return match[0] || null;
510
+ } catch (error) {
511
+ return null;
512
+ }
513
+ }
514
+
498
515
  /**
499
516
  * 更新单个技能
500
517
  */
@@ -518,83 +535,84 @@ export async function updateSkill(skillName, options = {}) {
518
535
 
519
536
  const currentVersion = meta.version || meta.commitHash?.substring(0, 7) || 'unknown';
520
537
 
521
- // 重新安装技能(使用内部的 installFromGitUrl,但不打印)
522
- try {
523
- const parsed = parseGitUrl(meta.gitUrl);
538
+ // 解析 Git URL
539
+ const parsed = parseGitUrl(meta.gitUrl);
524
540
 
525
- // 确定技能名称
526
- const skillNameFromUrl = parsed.path ? basename(parsed.path) : parsed.repo;
541
+ // 先检查远程 commit hash(不下载)
542
+ console.log(` 检查远程版本...`);
543
+ const remoteCommitHash = getRemoteCommitHash(parsed.cloneUrl, parsed.branch);
527
544
 
528
- // 创建临时目录
529
- const tempDir = join(tmpdir(), `eskill-update-${Date.now()}`);
545
+ if (!remoteCommitHash) {
546
+ throw new Error('无法获取远程版本信息');
547
+ }
530
548
 
531
- try {
532
- // 克隆仓库(静默模式)
533
- const cloneUrl = parsed.cloneUrl;
534
- execSync(
535
- `git clone --depth 1 --branch ${parsed.branch} --single-branch "${cloneUrl}" "${tempDir}"`,
536
- { stdio: 'inherit' }
537
- );
538
-
539
- // 确定源路径
540
- const sourcePath = parsed.path ? join(tempDir, parsed.path) : tempDir;
541
-
542
- // 验证源路径存在
543
- if (!existsSync(sourcePath)) {
544
- throw new Error(`路径不存在: ${sourcePath}`);
545
- }
549
+ // 检查是否有更新
550
+ if (!force && remoteCommitHash === meta.commitHash) {
551
+ return { success: true, skill: skillName, updated: false, currentVersion };
552
+ }
546
553
 
547
- // 检查 SKILL.md 是否存在
548
- const skillManifestPath = join(sourcePath, 'SKILL.md');
549
- if (!existsSync(skillManifestPath)) {
550
- throw new Error(`无效的技能包:未找到 SKILL.md 文件`);
551
- }
554
+ // 有更新或强制更新,才下载代码
555
+ console.log(` 发现更新,正在下载...`);
552
556
 
553
- // 获取新版本信息
554
- const newCommitHash = getGitCommitHash(sourcePath);
555
- const newVersion = getGitVersion(sourcePath);
556
- const newVersionDisplay = newVersion || newCommitHash?.substring(0, 7) || 'unknown';
557
+ // 创建临时目录
558
+ const tempDir = join(tmpdir(), `eskill-update-${Date.now()}`);
557
559
 
558
- // 检查是否有更新
559
- if (!force && newCommitHash === meta.commitHash) {
560
- // 删除临时目录
561
- rmSync(tempDir, { recursive: true, force: true });
562
- return { success: true, skill: skillName, updated: false, currentVersion };
563
- }
560
+ try {
561
+ // 克隆仓库(静默模式)
562
+ execSync(
563
+ `git clone --depth 1 --branch ${parsed.branch} --single-branch "${parsed.cloneUrl}" "${tempDir}"`,
564
+ { stdio: 'inherit' }
565
+ );
564
566
 
565
- // 删除旧技能
566
- rmSync(targetPath, { recursive: true, force: true });
567
+ // 确定源路径
568
+ const sourcePath = parsed.path ? join(tempDir, parsed.path) : tempDir;
567
569
 
568
- // 复制新技能
569
- if (process.platform === 'win32') {
570
- execSync(`xcopy "${sourcePath}" "${targetPath}" /E /I /H /Y`, { stdio: 'inherit' });
571
- } else {
572
- execSync(`cp -r "${sourcePath}" "${targetPath}"`, { stdio: 'inherit' });
573
- }
570
+ // 验证源路径存在
571
+ if (!existsSync(sourcePath)) {
572
+ throw new Error(`路径不存在: ${sourcePath}`);
573
+ }
574
+
575
+ // 检查 SKILL.md 是否存在
576
+ const skillManifestPath = join(sourcePath, 'SKILL.md');
577
+ if (!existsSync(skillManifestPath)) {
578
+ throw new Error(`无效的技能包:未找到 SKILL.md 文件`);
579
+ }
574
580
 
575
- // 更新元数据
576
- saveSkillMeta(skillName, {
577
- ...meta,
578
- commitHash: newCommitHash,
579
- version: newVersion,
580
- updatedAt: new Date().toISOString()
581
- });
581
+ // 获取新版本信息
582
+ const newCommitHash = getGitCommitHash(sourcePath);
583
+ const newVersion = getGitVersion(sourcePath);
584
+ const newVersionDisplay = newVersion || newCommitHash?.substring(0, 7) || 'unknown';
582
585
 
583
- return {
584
- success: true,
585
- skill: skillName,
586
- updated: true,
587
- currentVersion,
588
- newVersion: newVersionDisplay
589
- };
590
- } finally {
591
- // 清理临时目录
592
- if (existsSync(tempDir)) {
593
- rmSync(tempDir, { recursive: true, force: true });
594
- }
586
+ // 删除旧技能
587
+ rmSync(targetPath, { recursive: true, force: true });
588
+
589
+ // 复制新技能
590
+ if (process.platform === 'win32') {
591
+ execSync(`xcopy "${sourcePath}" "${targetPath}" /E /I /H /Y`, { stdio: 'inherit' });
592
+ } else {
593
+ execSync(`cp -r "${sourcePath}" "${targetPath}"`, { stdio: 'inherit' });
594
+ }
595
+
596
+ // 更新元数据
597
+ saveSkillMeta(skillName, {
598
+ ...meta,
599
+ commitHash: newCommitHash,
600
+ version: newVersion,
601
+ updatedAt: new Date().toISOString()
602
+ });
603
+
604
+ return {
605
+ success: true,
606
+ skill: skillName,
607
+ updated: true,
608
+ currentVersion,
609
+ newVersion: newVersionDisplay
610
+ };
611
+ } finally {
612
+ // 清理临时目录
613
+ if (existsSync(tempDir)) {
614
+ rmSync(tempDir, { recursive: true, force: true });
595
615
  }
596
- } catch (error) {
597
- throw new Error(`更新失败: ${error.message}`);
598
616
  }
599
617
  }
600
618
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eskill",
3
- "version": "1.0.25",
3
+ "version": "1.0.27",
4
4
  "description": "Unified AI Agent Skills Management - Install skills from Git URLs",
5
5
  "main": "index.js",
6
6
  "type": "module",