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.
- package/cli.js +8 -4
- package/lib/installer.js +84 -66
- 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.
|
|
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
|
-
|
|
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
|
-
//
|
|
522
|
-
|
|
523
|
-
const parsed = parseGitUrl(meta.gitUrl);
|
|
538
|
+
// 解析 Git URL
|
|
539
|
+
const parsed = parseGitUrl(meta.gitUrl);
|
|
524
540
|
|
|
525
|
-
|
|
526
|
-
|
|
541
|
+
// 先检查远程 commit hash(不下载)
|
|
542
|
+
console.log(` 检查远程版本...`);
|
|
543
|
+
const remoteCommitHash = getRemoteCommitHash(parsed.cloneUrl, parsed.branch);
|
|
527
544
|
|
|
528
|
-
|
|
529
|
-
|
|
545
|
+
if (!remoteCommitHash) {
|
|
546
|
+
throw new Error('无法获取远程版本信息');
|
|
547
|
+
}
|
|
530
548
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
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
|
-
|
|
548
|
-
|
|
549
|
-
if (!existsSync(skillManifestPath)) {
|
|
550
|
-
throw new Error(`无效的技能包:未找到 SKILL.md 文件`);
|
|
551
|
-
}
|
|
554
|
+
// 有更新或强制更新,才下载代码
|
|
555
|
+
console.log(` 发现更新,正在下载...`);
|
|
552
556
|
|
|
553
|
-
|
|
554
|
-
|
|
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
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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
|
-
|
|
567
|
+
// 确定源路径
|
|
568
|
+
const sourcePath = parsed.path ? join(tempDir, parsed.path) : tempDir;
|
|
567
569
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
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
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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
|
|