bfi-cli 0.1.56 → 0.1.58
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/dist/_chunks/agents2.mjs +6 -2
- package/dist/cli.mjs +313 -80
- package/package.json +1 -1
package/dist/_chunks/agents2.mjs
CHANGED
|
@@ -33,8 +33,12 @@ function saveCache(agents, maxUpdatedAt) {
|
|
|
33
33
|
}));
|
|
34
34
|
} catch {}
|
|
35
35
|
}
|
|
36
|
+
function expandTilde(p) {
|
|
37
|
+
if (p && p.startsWith("~/")) return path.join(os.homedir(), p.slice(2));
|
|
38
|
+
return p;
|
|
39
|
+
}
|
|
36
40
|
function mapToAgentConfig(a) {
|
|
37
|
-
const gsd = a.globalSkillsDir || void 0;
|
|
41
|
+
const gsd = expandTilde(a.globalSkillsDir || void 0);
|
|
38
42
|
return {
|
|
39
43
|
name: a.name,
|
|
40
44
|
displayName: a.displayName || a.name,
|
|
@@ -45,7 +49,7 @@ function mapToAgentConfig(a) {
|
|
|
45
49
|
};
|
|
46
50
|
}
|
|
47
51
|
function mapCustomEntry(name, entry) {
|
|
48
|
-
const gsd = entry.globalSkillsDir || void 0;
|
|
52
|
+
const gsd = expandTilde(entry.globalSkillsDir || void 0);
|
|
49
53
|
return {
|
|
50
54
|
name,
|
|
51
55
|
displayName: entry.displayName || name,
|
package/dist/cli.mjs
CHANGED
|
@@ -2796,12 +2796,14 @@ async function tryBlobInstall(ownerRepo, options = {}) {
|
|
|
2796
2796
|
};
|
|
2797
2797
|
}
|
|
2798
2798
|
var add_exports = /* @__PURE__ */ __exportAll({
|
|
2799
|
+
ensureUniversalAgents: () => ensureUniversalAgents,
|
|
2799
2800
|
formatEveInstallPromptMessage: () => formatEveInstallPromptMessage,
|
|
2800
2801
|
getLockSource: () => getLockSource,
|
|
2801
2802
|
getProjectLockSourceUrl: () => getProjectLockSourceUrl,
|
|
2802
2803
|
parseAddOptions: () => parseAddOptions,
|
|
2803
2804
|
promptForAgents: () => promptForAgents,
|
|
2804
|
-
runAdd: () => runAdd
|
|
2805
|
+
runAdd: () => runAdd,
|
|
2806
|
+
selectAgentsInteractive: () => selectAgentsInteractive
|
|
2805
2807
|
});
|
|
2806
2808
|
const isCancelled = (value) => typeof value === "symbol";
|
|
2807
2809
|
const EVE_AGENT_LABEL = "eve agent";
|
|
@@ -2876,20 +2878,20 @@ function computeSingleFileSkillHash(contents) {
|
|
|
2876
2878
|
hash.update(contents);
|
|
2877
2879
|
return hash.digest("hex");
|
|
2878
2880
|
}
|
|
2879
|
-
function formatList$
|
|
2881
|
+
function formatList$2(items, maxShow = 5) {
|
|
2880
2882
|
if (items.length <= maxShow) return items.join(", ");
|
|
2881
2883
|
const shown = items.slice(0, maxShow);
|
|
2882
2884
|
const remaining = items.length - maxShow;
|
|
2883
2885
|
return `${shown.join(", ")} +${remaining} more`;
|
|
2884
2886
|
}
|
|
2885
2887
|
function formatSkillPromptSubject(skills) {
|
|
2886
|
-
const namedSubject = formatList$
|
|
2888
|
+
const namedSubject = formatList$2(skills.map((skill) => import_picocolors.default.cyan(getSkillDisplayName(skill))), 3);
|
|
2887
2889
|
return stripTerminalEscapes(namedSubject).length <= 80 ? namedSubject : `${skills.length} selected skills`;
|
|
2888
2890
|
}
|
|
2889
2891
|
function formatEveInstallPromptMessage(skills) {
|
|
2890
2892
|
return `Detected an eve project. Install ${formatSkillPromptSubject(skills)} for your ${EVE_AGENT_LABEL} to use?`;
|
|
2891
2893
|
}
|
|
2892
|
-
function splitAgentsByType(agentTypes) {
|
|
2894
|
+
function splitAgentsByType$1(agentTypes) {
|
|
2893
2895
|
const universal = [];
|
|
2894
2896
|
const symlinked = [];
|
|
2895
2897
|
for (const a of agentTypes) if (isUniversalAgent(a)) universal.push(agents[a].displayName);
|
|
@@ -2901,29 +2903,29 @@ function splitAgentsByType(agentTypes) {
|
|
|
2901
2903
|
}
|
|
2902
2904
|
function buildAgentSummaryLines(targetAgents, installMode, selectedAgents) {
|
|
2903
2905
|
const lines = [];
|
|
2904
|
-
const { universal, symlinked } = splitAgentsByType(targetAgents);
|
|
2906
|
+
const { universal, symlinked } = splitAgentsByType$1(targetAgents);
|
|
2905
2907
|
const selectedSet = new Set(selectedAgents || targetAgents);
|
|
2906
2908
|
if (installMode === "symlink") {
|
|
2907
2909
|
const selectedUniversal = universal.filter((a) => selectedSet.has(a));
|
|
2908
2910
|
const selectedSymlink = symlinked.filter((a) => selectedSet.has(a));
|
|
2909
|
-
if (selectedUniversal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList$
|
|
2910
|
-
if (selectedSymlink.length > 0) lines.push(` ${import_picocolors.default.dim("符号链接 →")} ${formatList$
|
|
2911
|
+
if (selectedUniversal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList$2(selectedUniversal)}`);
|
|
2912
|
+
if (selectedSymlink.length > 0) lines.push(` ${import_picocolors.default.dim("符号链接 →")} ${formatList$2(selectedSymlink)}`);
|
|
2911
2913
|
const otherUniversal = universal.filter((a) => !selectedSet.has(a));
|
|
2912
2914
|
if (otherUniversal.length > 0) lines.push(` ${import_picocolors.default.dim(`(另外 ${otherUniversal.length} 个使用共享目录的 Agent 也会自动获得此技能)`)}`);
|
|
2913
2915
|
} else {
|
|
2914
2916
|
const allNames = targetAgents.filter((a) => selectedSet.has(a)).map((a) => agents[a].displayName);
|
|
2915
|
-
lines.push(` ${import_picocolors.default.dim("复制 →")} ${formatList$
|
|
2917
|
+
lines.push(` ${import_picocolors.default.dim("复制 →")} ${formatList$2(allNames)}`);
|
|
2916
2918
|
}
|
|
2917
2919
|
return lines;
|
|
2918
2920
|
}
|
|
2919
|
-
function targetDisplayName(target) {
|
|
2921
|
+
function targetDisplayName$1(target) {
|
|
2920
2922
|
const base = agents[target.agent].displayName;
|
|
2921
2923
|
return target.subagent ? `${base} (${target.subagent})` : base;
|
|
2922
2924
|
}
|
|
2923
|
-
function targetKey(target) {
|
|
2925
|
+
function targetKey$1(target) {
|
|
2924
2926
|
return target.subagent ? `${target.agent}:${target.subagent}` : target.agent;
|
|
2925
2927
|
}
|
|
2926
|
-
function buildInstallTargets(targetAgents, eveSubagentTargets) {
|
|
2928
|
+
function buildInstallTargets$1(targetAgents, eveSubagentTargets) {
|
|
2927
2929
|
const targets = [];
|
|
2928
2930
|
for (const agent of targetAgents) if (agent === "eve") for (const subagent of eveSubagentTargets) targets.push({
|
|
2929
2931
|
agent,
|
|
@@ -2932,18 +2934,18 @@ function buildInstallTargets(targetAgents, eveSubagentTargets) {
|
|
|
2932
2934
|
else targets.push({ agent });
|
|
2933
2935
|
return targets;
|
|
2934
2936
|
}
|
|
2935
|
-
function buildTargetSummaryLines(targets, installMode) {
|
|
2937
|
+
function buildTargetSummaryLines$1(targets, installMode) {
|
|
2936
2938
|
const lines = [];
|
|
2937
2939
|
const rootAgents = targets.filter((t) => !t.subagent).map((t) => t.agent);
|
|
2938
|
-
const subagentNames = targets.filter((t) => t.subagent).map(targetDisplayName);
|
|
2939
|
-
const { universal, symlinked } = splitAgentsByType(rootAgents);
|
|
2940
|
+
const subagentNames = targets.filter((t) => t.subagent).map(targetDisplayName$1);
|
|
2941
|
+
const { universal, symlinked } = splitAgentsByType$1(rootAgents);
|
|
2940
2942
|
if (installMode === "symlink") {
|
|
2941
|
-
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList$
|
|
2942
|
-
if (symlinked.length > 0) lines.push(` ${import_picocolors.default.dim("符号链接 →")} ${formatList$
|
|
2943
|
-
if (subagentNames.length > 0) lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList$
|
|
2943
|
+
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList$2(universal, 3)}`);
|
|
2944
|
+
if (symlinked.length > 0) lines.push(` ${import_picocolors.default.dim("符号链接 →")} ${formatList$2(symlinked)}`);
|
|
2945
|
+
if (subagentNames.length > 0) lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList$2(subagentNames)}`);
|
|
2944
2946
|
} else {
|
|
2945
|
-
const allNames = targets.map(targetDisplayName);
|
|
2946
|
-
lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList$
|
|
2947
|
+
const allNames = targets.map(targetDisplayName$1);
|
|
2948
|
+
lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList$2(allNames)}`);
|
|
2947
2949
|
}
|
|
2948
2950
|
return lines;
|
|
2949
2951
|
}
|
|
@@ -2955,12 +2957,12 @@ function ensureUniversalAgents(targetAgents) {
|
|
|
2955
2957
|
}
|
|
2956
2958
|
function buildResultLines(results, targetAgents) {
|
|
2957
2959
|
const lines = [];
|
|
2958
|
-
const { universal, symlinked: symlinkAgents } = splitAgentsByType(targetAgents);
|
|
2960
|
+
const { universal, symlinked: symlinkAgents } = splitAgentsByType$1(targetAgents);
|
|
2959
2961
|
const successfulSymlinks = results.filter((r) => !r.symlinkFailed && !r.skipped && !universal.includes(r.agent)).map((r) => r.agent);
|
|
2960
2962
|
const failedSymlinks = results.filter((r) => r.symlinkFailed && !r.skipped).map((r) => r.agent);
|
|
2961
|
-
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList$
|
|
2962
|
-
if (successfulSymlinks.length > 0) lines.push(` ${import_picocolors.default.dim("符号链接:")} ${formatList$
|
|
2963
|
-
if (failedSymlinks.length > 0) lines.push(` ${import_picocolors.default.yellow("copied:")} ${formatList$
|
|
2963
|
+
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList$2(universal)}`);
|
|
2964
|
+
if (successfulSymlinks.length > 0) lines.push(` ${import_picocolors.default.dim("符号链接:")} ${formatList$2(successfulSymlinks)}`);
|
|
2965
|
+
if (failedSymlinks.length > 0) lines.push(` ${import_picocolors.default.yellow("copied:")} ${formatList$2(failedSymlinks)}`);
|
|
2964
2966
|
return lines;
|
|
2965
2967
|
}
|
|
2966
2968
|
function multiselect(opts) {
|
|
@@ -3215,7 +3217,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
3215
3217
|
if (skill.files.size > 1) summaryLines.push(` ${import_picocolors.default.dim("files:")} ${skill.files.size}`);
|
|
3216
3218
|
const skillOverwrites = overwriteStatus.get(skill.installName);
|
|
3217
3219
|
const overwriteAgents = targetAgents.filter((a) => skillOverwrites?.get(a)).map((a) => agents[a].displayName);
|
|
3218
|
-
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$
|
|
3220
|
+
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$2(overwriteAgents)}`);
|
|
3219
3221
|
}
|
|
3220
3222
|
console.log();
|
|
3221
3223
|
note(summaryLines.join("\n"), "安装摘要");
|
|
@@ -3304,7 +3306,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
3304
3306
|
const title = import_picocolors.default.green(`已安装 ${skillCount} 个技能`);
|
|
3305
3307
|
note(resultLines.join("\n"), title);
|
|
3306
3308
|
if (symlinkFailures.length > 0) {
|
|
3307
|
-
log.warn(import_picocolors.default.yellow(`符号链接失败: ${formatList$
|
|
3309
|
+
log.warn(import_picocolors.default.yellow(`符号链接失败: ${formatList$2(copiedAgents)}`));
|
|
3308
3310
|
log.message(import_picocolors.default.dim(" 已改为复制文件。在 Windows 上,请启用开发者模式以支持符号链接。"));
|
|
3309
3311
|
}
|
|
3310
3312
|
}
|
|
@@ -3500,10 +3502,10 @@ async function runAdd(args, options = {}) {
|
|
|
3500
3502
|
else if (!process.stdin.isTTY) showInstallTip();
|
|
3501
3503
|
let tempDir = null;
|
|
3502
3504
|
try {
|
|
3503
|
-
const spinner$
|
|
3504
|
-
spinner$
|
|
3505
|
+
const spinner$3 = spinner();
|
|
3506
|
+
spinner$3.start("正在解析源...");
|
|
3505
3507
|
const parsed = parseSource(source);
|
|
3506
|
-
spinner$
|
|
3508
|
+
spinner$3.stop(`源:${parsed.type === "local" ? parsed.localPath : parsed.url}${parsed.ref ? ` @ ${import_picocolors.default.yellow(parsed.ref)}` : ""}${parsed.subpath ? ` (${parsed.subpath})` : ""}${parsed.skillFilter ? ` ${import_picocolors.default.dim("@")}${import_picocolors.default.cyan(parsed.skillFilter)}` : ""}`);
|
|
3507
3509
|
const ownerRepoRaw = getOwnerRepo(parsed);
|
|
3508
3510
|
const repoPrivacyPromise = (() => {
|
|
3509
3511
|
if (!ownerRepoRaw) return Promise.resolve(null);
|
|
@@ -3512,7 +3514,7 @@ async function runAdd(args, options = {}) {
|
|
|
3512
3514
|
return isRepoPrivate(ownerRepo.owner, ownerRepo.repo).catch(() => null);
|
|
3513
3515
|
})();
|
|
3514
3516
|
if (parsed.type === "well-known") {
|
|
3515
|
-
await handleWellKnownSkills(source, parsed.url, options, spinner$
|
|
3517
|
+
await handleWellKnownSkills(source, parsed.url, options, spinner$3);
|
|
3516
3518
|
return;
|
|
3517
3519
|
}
|
|
3518
3520
|
if (parsed.skillFilter) {
|
|
@@ -3523,18 +3525,18 @@ async function runAdd(args, options = {}) {
|
|
|
3523
3525
|
let skills;
|
|
3524
3526
|
let blobResult = null;
|
|
3525
3527
|
if (parsed.type === "skillhub") {
|
|
3526
|
-
const result = await installFromSkillHub(parsed, options, spinner$
|
|
3528
|
+
const result = await installFromSkillHub(parsed, options, spinner$3);
|
|
3527
3529
|
skills = result.skills;
|
|
3528
3530
|
tempDir = result.tempDir;
|
|
3529
3531
|
} else if (parsed.type === "local") {
|
|
3530
|
-
spinner$
|
|
3532
|
+
spinner$3.start("正在验证本地路径...");
|
|
3531
3533
|
if (!existsSync(parsed.localPath)) {
|
|
3532
|
-
spinner$
|
|
3534
|
+
spinner$3.stop(import_picocolors.default.red("路径未找到"));
|
|
3533
3535
|
outro(import_picocolors.default.red(`本地路径不存在:${parsed.localPath}`));
|
|
3534
3536
|
process.exit(1);
|
|
3535
3537
|
}
|
|
3536
|
-
spinner$
|
|
3537
|
-
spinner$
|
|
3538
|
+
spinner$3.stop("本地路径验证通过");
|
|
3539
|
+
spinner$3.start("正在发现技能...");
|
|
3538
3540
|
skills = await discoverSkills(parsed.localPath, parsed.subpath, {
|
|
3539
3541
|
includeInternal,
|
|
3540
3542
|
fullDepth: options.fullDepth
|
|
@@ -3549,7 +3551,7 @@ async function runAdd(args, options = {}) {
|
|
|
3549
3551
|
const owner = ownerRepo?.split("/")[0]?.toLowerCase();
|
|
3550
3552
|
const isSelfHostedRepo = !!ownerRepo && Object.hasOwn(BLOB_ALLOWED_REPOS, ownerRepo.toLowerCase());
|
|
3551
3553
|
if (ownerRepo && owner && (isSelfHostedRepo || BLOB_ALLOWED_OWNERS.includes(owner))) {
|
|
3552
|
-
spinner$
|
|
3554
|
+
spinner$3.start("正在获取技能...");
|
|
3553
3555
|
blobResult = await tryBlobInstall(ownerRepo, {
|
|
3554
3556
|
subpath: parsed.subpath,
|
|
3555
3557
|
skillFilter: parsed.skillFilter,
|
|
@@ -3557,36 +3559,36 @@ async function runAdd(args, options = {}) {
|
|
|
3557
3559
|
getToken: getGitHubToken,
|
|
3558
3560
|
includeInternal
|
|
3559
3561
|
});
|
|
3560
|
-
if (!blobResult) spinner$
|
|
3562
|
+
if (!blobResult) spinner$3.stop(import_picocolors.default.dim("Falling back to clone..."));
|
|
3561
3563
|
}
|
|
3562
3564
|
if (blobResult) {
|
|
3563
3565
|
skills = blobResult.skills;
|
|
3564
|
-
spinner$
|
|
3566
|
+
spinner$3.stop(`Found ${import_picocolors.default.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
|
|
3565
3567
|
} else {
|
|
3566
|
-
tempDir = await cloneWithGitHubFallback(parsed.url, options.branch || parsed.ref, spinner$
|
|
3567
|
-
spinner$
|
|
3568
|
-
spinner$
|
|
3568
|
+
tempDir = await cloneWithGitHubFallback(parsed.url, options.branch || parsed.ref, spinner$3);
|
|
3569
|
+
spinner$3.stop("仓库克隆完成");
|
|
3570
|
+
spinner$3.start("正在发现技能...");
|
|
3569
3571
|
skills = await discoverSkills(tempDir, parsed.subpath, {
|
|
3570
3572
|
includeInternal,
|
|
3571
3573
|
fullDepth: options.fullDepth
|
|
3572
3574
|
});
|
|
3573
3575
|
}
|
|
3574
3576
|
} else {
|
|
3575
|
-
tempDir = await cloneWithGitHubFallback(parsed.url, options.branch || parsed.ref, spinner$
|
|
3576
|
-
spinner$
|
|
3577
|
-
spinner$
|
|
3577
|
+
tempDir = await cloneWithGitHubFallback(parsed.url, options.branch || parsed.ref, spinner$3);
|
|
3578
|
+
spinner$3.stop("仓库克隆完成");
|
|
3579
|
+
spinner$3.start("正在发现技能...");
|
|
3578
3580
|
skills = await discoverSkills(tempDir, parsed.subpath, {
|
|
3579
3581
|
includeInternal,
|
|
3580
3582
|
fullDepth: options.fullDepth
|
|
3581
3583
|
});
|
|
3582
3584
|
}
|
|
3583
3585
|
if (skills.length === 0) {
|
|
3584
|
-
spinner$
|
|
3586
|
+
spinner$3.stop(import_picocolors.default.red("未找到技能"));
|
|
3585
3587
|
outro(import_picocolors.default.red("未找到有效技能。技能需要包含 name 和 description 的 SKILL.md 文件。"));
|
|
3586
3588
|
await cleanup(tempDir);
|
|
3587
3589
|
process.exit(1);
|
|
3588
3590
|
}
|
|
3589
|
-
if (!blobResult) spinner$
|
|
3591
|
+
if (!blobResult) spinner$3.stop(`Found ${import_picocolors.default.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
|
|
3590
3592
|
if (options.list) {
|
|
3591
3593
|
console.log();
|
|
3592
3594
|
log.step(import_picocolors.default.bold("可用技能"));
|
|
@@ -3700,10 +3702,10 @@ async function runAdd(args, options = {}) {
|
|
|
3700
3702
|
}
|
|
3701
3703
|
targetAgents = options.agent;
|
|
3702
3704
|
} else {
|
|
3703
|
-
spinner$
|
|
3705
|
+
spinner$3.start("正在加载 Agent...");
|
|
3704
3706
|
const installedAgents = await detectInstalledAgents();
|
|
3705
3707
|
const totalAgents = Object.keys(agents).length;
|
|
3706
|
-
spinner$
|
|
3708
|
+
spinner$3.stop(`${totalAgents} agents`);
|
|
3707
3709
|
if (installedAgents.includes("eve") && (options.yes || !agentResult.isAgent)) {
|
|
3708
3710
|
const useEve = options.yes ? true : await confirm({
|
|
3709
3711
|
message: formatEveInstallPromptMessage(selectedSkills),
|
|
@@ -3786,7 +3788,7 @@ async function runAdd(args, options = {}) {
|
|
|
3786
3788
|
eveSubagentTargets = selectedSubagents.map((s) => s === "" ? void 0 : s);
|
|
3787
3789
|
}
|
|
3788
3790
|
}
|
|
3789
|
-
const installTargets = buildInstallTargets(targetAgents, eveSubagentTargets);
|
|
3791
|
+
const installTargets = buildInstallTargets$1(targetAgents, eveSubagentTargets);
|
|
3790
3792
|
let installGlobally = options.global ?? false;
|
|
3791
3793
|
const supportsGlobal = targetAgents.some((a) => agents[a].globalSkillsDir !== void 0);
|
|
3792
3794
|
if (options.global === void 0 && !options.yes && supportsGlobal) {
|
|
@@ -3845,7 +3847,7 @@ async function runAdd(args, options = {}) {
|
|
|
3845
3847
|
const overwriteStatus = /* @__PURE__ */ new Map();
|
|
3846
3848
|
for (const { skillName, target, installed } of overwriteChecks) {
|
|
3847
3849
|
if (!overwriteStatus.has(skillName)) overwriteStatus.set(skillName, /* @__PURE__ */ new Map());
|
|
3848
|
-
overwriteStatus.get(skillName).set(targetKey(target), installed);
|
|
3850
|
+
overwriteStatus.get(skillName).set(targetKey$1(target), installed);
|
|
3849
3851
|
}
|
|
3850
3852
|
const groupedSummary = {};
|
|
3851
3853
|
const ungroupedSummary = [];
|
|
@@ -3863,10 +3865,10 @@ async function runAdd(args, options = {}) {
|
|
|
3863
3865
|
eveSubagent: installTargets[0].subagent
|
|
3864
3866
|
}) : getCanonicalPath(skill.name, { global: installGlobally }), cwd);
|
|
3865
3867
|
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
3866
|
-
summaryLines.push(...buildTargetSummaryLines(installTargets, installMode));
|
|
3868
|
+
summaryLines.push(...buildTargetSummaryLines$1(installTargets, installMode));
|
|
3867
3869
|
const skillOverwrites = overwriteStatus.get(skill.name);
|
|
3868
|
-
const overwriteAgents = installTargets.filter((t) => skillOverwrites?.get(targetKey(t))).map(targetDisplayName);
|
|
3869
|
-
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$
|
|
3870
|
+
const overwriteAgents = installTargets.filter((t) => skillOverwrites?.get(targetKey$1(t))).map(targetDisplayName$1);
|
|
3871
|
+
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$2(overwriteAgents)}`);
|
|
3870
3872
|
}
|
|
3871
3873
|
};
|
|
3872
3874
|
const sortedGroups = Object.keys(groupedSummary).sort();
|
|
@@ -3903,7 +3905,7 @@ async function runAdd(args, options = {}) {
|
|
|
3903
3905
|
process.exit(0);
|
|
3904
3906
|
}
|
|
3905
3907
|
}
|
|
3906
|
-
spinner$
|
|
3908
|
+
spinner$3.start("正在安装技能...");
|
|
3907
3909
|
const results = [];
|
|
3908
3910
|
for (const skill of selectedSkills) for (const target of installTargets) {
|
|
3909
3911
|
const { agent, subagent } = target;
|
|
@@ -3935,12 +3937,12 @@ async function runAdd(args, options = {}) {
|
|
|
3935
3937
|
});
|
|
3936
3938
|
results.push({
|
|
3937
3939
|
skill: getSkillDisplayName(skill),
|
|
3938
|
-
agent: targetDisplayName(target),
|
|
3940
|
+
agent: targetDisplayName$1(target),
|
|
3939
3941
|
pluginName: skill.pluginName,
|
|
3940
3942
|
...result
|
|
3941
3943
|
});
|
|
3942
3944
|
}
|
|
3943
|
-
spinner$
|
|
3945
|
+
spinner$3.stop("安装完成");
|
|
3944
3946
|
console.log();
|
|
3945
3947
|
const successful = results.filter((r) => r.success);
|
|
3946
3948
|
const failed = results.filter((r) => !r.success);
|
|
@@ -4061,7 +4063,7 @@ async function runAdd(args, options = {}) {
|
|
|
4061
4063
|
const title = import_picocolors.default.green(`已安装 ${skillCount} 个技能`);
|
|
4062
4064
|
note(resultLines.join("\n"), title);
|
|
4063
4065
|
if (symlinkFailures.length > 0) {
|
|
4064
|
-
log.warn(import_picocolors.default.yellow(`符号链接失败: ${formatList$
|
|
4066
|
+
log.warn(import_picocolors.default.yellow(`符号链接失败: ${formatList$2(copiedAgents)}`));
|
|
4065
4067
|
log.message(import_picocolors.default.dim(" 已改为复制文件。在 Windows 上,请启用开发者模式以支持符号链接。"));
|
|
4066
4068
|
}
|
|
4067
4069
|
}
|
|
@@ -4467,7 +4469,7 @@ function shortenPath(fullPath, cwd) {
|
|
|
4467
4469
|
if (fullPath.startsWith(cwd)) return "." + fullPath.slice(cwd.length);
|
|
4468
4470
|
return fullPath;
|
|
4469
4471
|
}
|
|
4470
|
-
function formatList(items, maxShow = 5) {
|
|
4472
|
+
function formatList$1(items, maxShow = 5) {
|
|
4471
4473
|
if (items.length <= maxShow) return items.join(", ");
|
|
4472
4474
|
const shown = items.slice(0, maxShow);
|
|
4473
4475
|
const remaining = items.length - maxShow;
|
|
@@ -4531,7 +4533,7 @@ async function runList(args) {
|
|
|
4531
4533
|
const prefix = indent ? " " : "";
|
|
4532
4534
|
const shortPath = shortenPath(skill.canonicalPath, cwd);
|
|
4533
4535
|
const agentNames = skill.agents.map((a) => agents[a].displayName);
|
|
4534
|
-
const agentInfo = skill.agents.length > 0 ? formatList(agentNames) : `${YELLOW$4}not linked${RESET$10}`;
|
|
4536
|
+
const agentInfo = skill.agents.length > 0 ? formatList$1(agentNames) : `${YELLOW$4}not linked${RESET$10}`;
|
|
4535
4537
|
const paddedName = sanitizeMetadata(skill.name).padEnd(maxNameLength);
|
|
4536
4538
|
const paddedPath = shortPath.padEnd(maxPathLength);
|
|
4537
4539
|
console.log(`${prefix}${CYAN$1}${paddedName}${RESET$10} ${DIM$10}${paddedPath}${RESET$10} ${DIM$10}Agents:${RESET$10} ${agentInfo}`);
|
|
@@ -4605,8 +4607,8 @@ async function removeCommand(skillNames, options) {
|
|
|
4605
4607
|
}
|
|
4606
4608
|
const isGlobal = options.global ?? false;
|
|
4607
4609
|
const cwd = process.cwd();
|
|
4608
|
-
const spinner$
|
|
4609
|
-
spinner$
|
|
4610
|
+
const spinner$2 = spinner();
|
|
4611
|
+
spinner$2.start("正在扫描已安装的技能...");
|
|
4610
4612
|
const skillNamesSet = /* @__PURE__ */ new Set();
|
|
4611
4613
|
const scanDir = async (dir) => {
|
|
4612
4614
|
try {
|
|
@@ -4625,7 +4627,7 @@ async function removeCommand(skillNames, options) {
|
|
|
4625
4627
|
for (const subagent of getEveSubagents(cwd)) await scanDir(getEveSubagentSkillsDir(subagent, cwd));
|
|
4626
4628
|
}
|
|
4627
4629
|
const installedSkills = Array.from(skillNamesSet).sort();
|
|
4628
|
-
spinner$
|
|
4630
|
+
spinner$2.stop(`发现 ${installedSkills.length} 个已安装技能`);
|
|
4629
4631
|
if (installedSkills.length === 0) {
|
|
4630
4632
|
outro(import_picocolors.default.yellow("没有可卸载的技能。"));
|
|
4631
4633
|
return;
|
|
@@ -4667,7 +4669,7 @@ async function removeCommand(skillNames, options) {
|
|
|
4667
4669
|
if (options.agent && options.agent.length > 0) targetAgents = options.agent;
|
|
4668
4670
|
else {
|
|
4669
4671
|
targetAgents = Object.keys(agents);
|
|
4670
|
-
spinner$
|
|
4672
|
+
spinner$2.stop(`Targeting ${targetAgents.length} potential agent(s)`);
|
|
4671
4673
|
}
|
|
4672
4674
|
if (!options.yes) {
|
|
4673
4675
|
console.log();
|
|
@@ -4680,7 +4682,7 @@ async function removeCommand(skillNames, options) {
|
|
|
4680
4682
|
process.exit(0);
|
|
4681
4683
|
}
|
|
4682
4684
|
}
|
|
4683
|
-
spinner$
|
|
4685
|
+
spinner$2.start("正在卸载技能...");
|
|
4684
4686
|
const results = [];
|
|
4685
4687
|
for (const skillName of selectedSkills) try {
|
|
4686
4688
|
const canonicalPath = getCanonicalPath(skillName, {
|
|
@@ -4742,7 +4744,7 @@ async function removeCommand(skillNames, options) {
|
|
|
4742
4744
|
error: err instanceof Error ? err.message : String(err)
|
|
4743
4745
|
});
|
|
4744
4746
|
}
|
|
4745
|
-
spinner$
|
|
4747
|
+
spinner$2.stop("卸载完成");
|
|
4746
4748
|
const successful = results.filter((r) => r.success);
|
|
4747
4749
|
const failed = results.filter((r) => !r.success);
|
|
4748
4750
|
if (successful.length > 0) {
|
|
@@ -6195,6 +6197,11 @@ const RESET$5 = "\x1B[0m";
|
|
|
6195
6197
|
const BOLD$3 = "\x1B[1m";
|
|
6196
6198
|
const DIM$5 = "\x1B[38;5;102m";
|
|
6197
6199
|
const TEXT$4 = "\x1B[38;5;145m";
|
|
6200
|
+
function formatFileSize(bytes) {
|
|
6201
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
6202
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
6203
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
6204
|
+
}
|
|
6198
6205
|
async function runDocs(args, globalOpts) {
|
|
6199
6206
|
switch (args[0]) {
|
|
6200
6207
|
case "upload":
|
|
@@ -6240,8 +6247,7 @@ async function handleUpload(args, globalOpts) {
|
|
|
6240
6247
|
const { registry, token } = resolveConfig(globalOpts);
|
|
6241
6248
|
const api = new SkillHubAPI(registry, token);
|
|
6242
6249
|
const fileName = path$1.basename(resolvedPath);
|
|
6243
|
-
const
|
|
6244
|
-
const fileSizeStr = fileSize < 1024 ? `${fileSize} B` : fileSize < 1024 * 1024 ? `${(fileSize / 1024).toFixed(1)} KB` : `${(fileSize / (1024 * 1024)).toFixed(1)} MB`;
|
|
6250
|
+
const fileSizeStr = formatFileSize(stats.size);
|
|
6245
6251
|
console.log(`${DIM$5}正在上传 ${fileName} (${fileSizeStr})...${RESET$5}`);
|
|
6246
6252
|
try {
|
|
6247
6253
|
const fileBuffer = fs.readFileSync(resolvedPath);
|
|
@@ -6280,11 +6286,14 @@ async function handleList(args, globalOpts) {
|
|
|
6280
6286
|
for (const doc of docs) {
|
|
6281
6287
|
const id = doc.id || "?";
|
|
6282
6288
|
const fileName = doc.fileName || doc.file_name || "unknown";
|
|
6283
|
-
const
|
|
6289
|
+
const fileSize = doc.fileSize || doc.file_size;
|
|
6290
|
+
const sizeStr = fileSize ? formatFileSize(Number(fileSize)) : "N/A";
|
|
6291
|
+
const user = doc.userDisplayName || doc.userId || "N/A";
|
|
6292
|
+
const ip = doc.clientIp || "N/A";
|
|
6284
6293
|
const createdAt = doc.createdAt || doc.created_at;
|
|
6285
6294
|
const dateStr = createdAt ? new Date(createdAt).toISOString().split("T")[0] : "N/A";
|
|
6286
6295
|
console.log(` ${BOLD$3}#${id}${RESET$5} ${TEXT$4}${fileName}${RESET$5}`);
|
|
6287
|
-
console.log(` ${DIM$5}
|
|
6296
|
+
console.log(` ${DIM$5}${sizeStr} | ${user} | ${ip} | ${dateStr}${RESET$5}`);
|
|
6288
6297
|
console.log();
|
|
6289
6298
|
}
|
|
6290
6299
|
if (total && Number(total) > (page + 1) * size) console.log(`${DIM$5}下一页:bfi docs list ${page + 1}${RESET$5}`);
|
|
@@ -6314,13 +6323,20 @@ async function handleInfo(args, globalOpts) {
|
|
|
6314
6323
|
console.log(`${DIM$5}未找到文档:${id}${RESET$5}`);
|
|
6315
6324
|
process.exit(1);
|
|
6316
6325
|
}
|
|
6326
|
+
const content = doc.content;
|
|
6327
|
+
const hasContent = typeof content === "string" && content.trim().length > 0;
|
|
6317
6328
|
console.log();
|
|
6318
6329
|
console.log(`${BOLD$3}文档 #${doc.id}${RESET$5}`);
|
|
6319
6330
|
console.log(`${DIM$5}${"─".repeat(48)}${RESET$5}`);
|
|
6320
6331
|
if (doc.fileName || doc.file_name) console.log(` ${BOLD$3}文件:${RESET$5} ${TEXT$4}${doc.fileName || doc.file_name}${RESET$5}`);
|
|
6332
|
+
const fileSize = doc.fileSize || doc.file_size;
|
|
6333
|
+
if (fileSize) console.log(` ${BOLD$3}大小:${RESET$5} ${TEXT$4}${formatFileSize(Number(fileSize))}${RESET$5}`);
|
|
6334
|
+
const user = doc.userDisplayName || doc.userId;
|
|
6335
|
+
if (user) console.log(` ${BOLD$3}上传者:${RESET$5} ${TEXT$4}${user}${RESET$5}`);
|
|
6336
|
+
if (doc.clientIp) console.log(` ${BOLD$3}IP:${RESET$5} ${TEXT$4}${doc.clientIp}${RESET$5}`);
|
|
6321
6337
|
if (doc.status) {
|
|
6322
6338
|
const statusColor = doc.status === "completed" || doc.status === "COMPLETED" ? "\x1B[32m" : doc.status === "failed" || doc.status === "FAILED" ? "\x1B[31m" : TEXT$4;
|
|
6323
|
-
console.log(` ${BOLD$3}状态:${RESET$5}
|
|
6339
|
+
console.log(` ${BOLD$3}状态:${RESET$5} ${statusColor}${doc.status}${RESET$5}`);
|
|
6324
6340
|
}
|
|
6325
6341
|
if (doc.createdAt || doc.created_at) {
|
|
6326
6342
|
const date = new Date(doc.createdAt || doc.created_at).toISOString().replace("T", " ").slice(0, 19);
|
|
@@ -6330,17 +6346,18 @@ async function handleInfo(args, globalOpts) {
|
|
|
6330
6346
|
const date = new Date(doc.updatedAt || doc.updated_at).toISOString().replace("T", " ").slice(0, 19);
|
|
6331
6347
|
console.log(` ${BOLD$3}更新时间:${RESET$5} ${TEXT$4}${date}${RESET$5}`);
|
|
6332
6348
|
}
|
|
6333
|
-
if (doc.result) {
|
|
6334
|
-
console.log();
|
|
6335
|
-
console.log(` ${BOLD$3}结果:${RESET$5}`);
|
|
6336
|
-
const resultStr = typeof doc.result === "string" ? doc.result : JSON.stringify(doc.result, null, 4);
|
|
6337
|
-
for (const line of resultStr.split("\n")) console.log(` ${DIM$5}${line}${RESET$5}`);
|
|
6338
|
-
}
|
|
6339
6349
|
if (doc.error || doc.errorMessage) {
|
|
6340
6350
|
console.log();
|
|
6341
6351
|
console.log(` \x1b[31m${BOLD$3}错误:${RESET$5}`);
|
|
6342
6352
|
console.log(` \x1b[31m${doc.error || doc.errorMessage}${RESET$5}`);
|
|
6343
6353
|
}
|
|
6354
|
+
if (hasContent) {
|
|
6355
|
+
console.log();
|
|
6356
|
+
console.log(` ${BOLD$3}内容:${RESET$5}`);
|
|
6357
|
+
console.log(`${DIM$5}${"─".repeat(48)}${RESET$5}`);
|
|
6358
|
+
for (const line of content.split("\n")) console.log(` ${TEXT$4}${line}${RESET$5}`);
|
|
6359
|
+
console.log(`${DIM$5}${"─".repeat(48)}${RESET$5}`);
|
|
6360
|
+
}
|
|
6344
6361
|
console.log();
|
|
6345
6362
|
} catch (error) {
|
|
6346
6363
|
if (error.status === 404) console.error(`未找到文档:${id}`);
|
|
@@ -6734,6 +6751,51 @@ async function handleLocalList(args, globalOpts) {
|
|
|
6734
6751
|
console.log();
|
|
6735
6752
|
}
|
|
6736
6753
|
}
|
|
6754
|
+
function targetDisplayName(target) {
|
|
6755
|
+
const base = agents[target.agent].displayName;
|
|
6756
|
+
return target.subagent ? `${base} (${target.subagent})` : base;
|
|
6757
|
+
}
|
|
6758
|
+
function targetKey(target) {
|
|
6759
|
+
return target.subagent ? `${target.agent}:${target.subagent}` : target.agent;
|
|
6760
|
+
}
|
|
6761
|
+
function buildInstallTargets(targetAgents, eveSubagentTargets) {
|
|
6762
|
+
const targets = [];
|
|
6763
|
+
for (const agent of targetAgents) if (agent === "eve") for (const subagent of eveSubagentTargets) targets.push({
|
|
6764
|
+
agent,
|
|
6765
|
+
subagent
|
|
6766
|
+
});
|
|
6767
|
+
else targets.push({ agent });
|
|
6768
|
+
return targets;
|
|
6769
|
+
}
|
|
6770
|
+
function splitAgentsByType(agentTypes) {
|
|
6771
|
+
const universal = [];
|
|
6772
|
+
const symlinked = [];
|
|
6773
|
+
for (const a of agentTypes) if (isUniversalAgent(a)) universal.push(agents[a].displayName);
|
|
6774
|
+
else symlinked.push(agents[a].displayName);
|
|
6775
|
+
return {
|
|
6776
|
+
universal,
|
|
6777
|
+
symlinked
|
|
6778
|
+
};
|
|
6779
|
+
}
|
|
6780
|
+
function formatList(items, maxShow = 5) {
|
|
6781
|
+
if (items.length <= maxShow) return items.join(", ");
|
|
6782
|
+
return `${items.slice(0, maxShow).join(", ")} +${items.length - maxShow} more`;
|
|
6783
|
+
}
|
|
6784
|
+
function buildTargetSummaryLines(targets, installMode) {
|
|
6785
|
+
const lines = [];
|
|
6786
|
+
const rootAgents = targets.filter((t) => !t.subagent).map((t) => t.agent);
|
|
6787
|
+
const subagentNames = targets.filter((t) => t.subagent).map(targetDisplayName);
|
|
6788
|
+
const { universal, symlinked } = splitAgentsByType(rootAgents);
|
|
6789
|
+
if (installMode === "symlink") {
|
|
6790
|
+
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList(universal, 3)}`);
|
|
6791
|
+
if (symlinked.length > 0) lines.push(` ${import_picocolors.default.dim("符号链接 →")} ${formatList(symlinked)}`);
|
|
6792
|
+
if (subagentNames.length > 0) lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList(subagentNames)}`);
|
|
6793
|
+
} else {
|
|
6794
|
+
const allNames = targets.map(targetDisplayName);
|
|
6795
|
+
lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList(allNames)}`);
|
|
6796
|
+
}
|
|
6797
|
+
return lines;
|
|
6798
|
+
}
|
|
6737
6799
|
async function handleInstall(args, api, globalOpts) {
|
|
6738
6800
|
const pkgRef = args[0];
|
|
6739
6801
|
if (!pkgRef) {
|
|
@@ -6742,6 +6804,8 @@ async function handleInstall(args, api, globalOpts) {
|
|
|
6742
6804
|
process.exit(1);
|
|
6743
6805
|
}
|
|
6744
6806
|
const { namespace, slug } = parseSkillRef(pkgRef, globalOpts.namespace);
|
|
6807
|
+
const isYes = args.includes("-y") || args.includes("--yes") || globalOpts.yes;
|
|
6808
|
+
const isGlobal = args.includes("-g") || args.includes("--global");
|
|
6745
6809
|
console.log(`${DIM$3}正在获取包信息...${RESET$3}`);
|
|
6746
6810
|
let pkgInfo;
|
|
6747
6811
|
try {
|
|
@@ -6758,16 +6822,185 @@ async function handleInstall(args, api, globalOpts) {
|
|
|
6758
6822
|
}
|
|
6759
6823
|
console.log(`${BOLD$1}${pkgInfo.name || slug}${RESET$3}(${skills.length} 个技能):`);
|
|
6760
6824
|
console.log();
|
|
6825
|
+
for (const skill of skills) {
|
|
6826
|
+
const ref = `@${skill.namespace || namespace}/${skill.slug}`;
|
|
6827
|
+
console.log(` ${DIM$3}• ${skill.displayName || skill.slug}${RESET$3} ${DIM$3}${ref}${RESET$3}`);
|
|
6828
|
+
}
|
|
6829
|
+
console.log();
|
|
6830
|
+
let targetAgents;
|
|
6831
|
+
let installGlobally;
|
|
6832
|
+
let installMode;
|
|
6833
|
+
let eveSubagentTargets = [void 0];
|
|
6834
|
+
if (isYes) {
|
|
6835
|
+
const installed = await detectInstalledAgents();
|
|
6836
|
+
const validAgents = Object.keys(agents);
|
|
6837
|
+
targetAgents = ensureUniversalAgents(installed.length > 0 ? installed : validAgents);
|
|
6838
|
+
installGlobally = isGlobal;
|
|
6839
|
+
installMode = "symlink";
|
|
6840
|
+
console.log(`${DIM$3}安装到:${targetAgents.map((a) => agents[a].displayName).join(", ")}${RESET$3}`);
|
|
6841
|
+
console.log(`${DIM$3}范围:${installGlobally ? "全局" : "项目"} | 方式:${installMode === "symlink" ? "符号链接" : "复制"}${RESET$3}`);
|
|
6842
|
+
console.log();
|
|
6843
|
+
} else {
|
|
6844
|
+
const spinner$1 = spinner();
|
|
6845
|
+
spinner$1.start("正在加载 Agent...");
|
|
6846
|
+
const installedAgents = await detectInstalledAgents();
|
|
6847
|
+
const totalAgents = Object.keys(agents).length;
|
|
6848
|
+
spinner$1.stop(`${totalAgents} agents`);
|
|
6849
|
+
const skillNames = skills.map((s) => s.displayName || s.slug);
|
|
6850
|
+
const skillSubject = skillNames.length <= 3 ? skillNames.map((n) => import_picocolors.default.cyan(n)).join(", ") : `${skills.length} 个技能`;
|
|
6851
|
+
if (installedAgents.includes("eve")) {
|
|
6852
|
+
const useEve = await confirm({
|
|
6853
|
+
message: `检测到 Eve 项目。为您的 eve agent 安装 ${skillSubject}?`,
|
|
6854
|
+
initialValue: true
|
|
6855
|
+
});
|
|
6856
|
+
if (isCancel(useEve)) {
|
|
6857
|
+
cancel("安装已取消");
|
|
6858
|
+
process.exit(0);
|
|
6859
|
+
}
|
|
6860
|
+
if (useEve) {
|
|
6861
|
+
targetAgents = ["eve"];
|
|
6862
|
+
console.log(`${DIM$3}安装到:eve agent${RESET$3}`);
|
|
6863
|
+
} else {
|
|
6864
|
+
const selected = await selectAgentsInteractive({ global: false });
|
|
6865
|
+
if (isCancel(selected)) {
|
|
6866
|
+
cancel("安装已取消");
|
|
6867
|
+
process.exit(0);
|
|
6868
|
+
}
|
|
6869
|
+
targetAgents = selected;
|
|
6870
|
+
}
|
|
6871
|
+
} else if (installedAgents.length === 0) {
|
|
6872
|
+
const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).filter(([key]) => key !== "eve").map(([key, config]) => ({
|
|
6873
|
+
value: key,
|
|
6874
|
+
label: config.displayName
|
|
6875
|
+
})));
|
|
6876
|
+
if (isCancel(selected)) {
|
|
6877
|
+
cancel("安装已取消");
|
|
6878
|
+
process.exit(0);
|
|
6879
|
+
}
|
|
6880
|
+
targetAgents = selected;
|
|
6881
|
+
} else if (installedAgents.length === 1) {
|
|
6882
|
+
targetAgents = ensureUniversalAgents(installedAgents);
|
|
6883
|
+
const firstAgent = installedAgents[0];
|
|
6884
|
+
console.log(`${DIM$3}安装到:${agents[firstAgent].displayName}${RESET$3}`);
|
|
6885
|
+
} else {
|
|
6886
|
+
const selected = await selectAgentsInteractive({ global: false });
|
|
6887
|
+
if (isCancel(selected)) {
|
|
6888
|
+
cancel("安装已取消");
|
|
6889
|
+
process.exit(0);
|
|
6890
|
+
}
|
|
6891
|
+
targetAgents = selected;
|
|
6892
|
+
}
|
|
6893
|
+
if (targetAgents.includes("eve")) {
|
|
6894
|
+
const availableSubagents = getEveSubagents(process.cwd());
|
|
6895
|
+
if (availableSubagents.length > 0) {
|
|
6896
|
+
const selectedSubagents = await multiselect$1({
|
|
6897
|
+
message: "Eve 技能安装位置?",
|
|
6898
|
+
options: [{
|
|
6899
|
+
value: "",
|
|
6900
|
+
label: "根 Agent",
|
|
6901
|
+
hint: "agent/skills"
|
|
6902
|
+
}, ...availableSubagents.map((name) => ({
|
|
6903
|
+
value: name,
|
|
6904
|
+
label: name,
|
|
6905
|
+
hint: `agent/subagents/${name}/skills`
|
|
6906
|
+
}))],
|
|
6907
|
+
initialValues: [""],
|
|
6908
|
+
required: true
|
|
6909
|
+
});
|
|
6910
|
+
if (isCancel(selectedSubagents)) {
|
|
6911
|
+
cancel("安装已取消");
|
|
6912
|
+
process.exit(0);
|
|
6913
|
+
}
|
|
6914
|
+
eveSubagentTargets = selectedSubagents.map((s) => s === "" ? void 0 : s);
|
|
6915
|
+
}
|
|
6916
|
+
}
|
|
6917
|
+
const installTargets = buildInstallTargets(targetAgents, eveSubagentTargets);
|
|
6918
|
+
installGlobally = isGlobal;
|
|
6919
|
+
const supportsGlobal = targetAgents.some((a) => agents[a].globalSkillsDir !== void 0);
|
|
6920
|
+
if (!isGlobal && supportsGlobal) {
|
|
6921
|
+
const scope = await select({
|
|
6922
|
+
message: "安装范围",
|
|
6923
|
+
options: [{
|
|
6924
|
+
value: false,
|
|
6925
|
+
label: "项目",
|
|
6926
|
+
hint: "安装到当前目录(随项目一起提交)"
|
|
6927
|
+
}, {
|
|
6928
|
+
value: true,
|
|
6929
|
+
label: "全局",
|
|
6930
|
+
hint: "安装到主目录(跨所有项目可用)"
|
|
6931
|
+
}]
|
|
6932
|
+
});
|
|
6933
|
+
if (isCancel(scope)) {
|
|
6934
|
+
cancel("安装已取消");
|
|
6935
|
+
process.exit(0);
|
|
6936
|
+
}
|
|
6937
|
+
installGlobally = scope;
|
|
6938
|
+
}
|
|
6939
|
+
const allEve = installTargets.every((t) => t.agent === "eve");
|
|
6940
|
+
if (new Set(installTargets.map((t) => t.subagent ? `eve:subagent:${t.subagent}` : agents[t.agent].skillsDir)).size > 1 && !allEve) {
|
|
6941
|
+
const modeChoice = await select({
|
|
6942
|
+
message: "安装方式",
|
|
6943
|
+
options: [{
|
|
6944
|
+
value: "symlink",
|
|
6945
|
+
label: "符号链接(推荐)",
|
|
6946
|
+
hint: "单一来源,易于更新"
|
|
6947
|
+
}, {
|
|
6948
|
+
value: "copy",
|
|
6949
|
+
label: "复制到所有 Agent",
|
|
6950
|
+
hint: "每个 Agent 独立副本"
|
|
6951
|
+
}]
|
|
6952
|
+
});
|
|
6953
|
+
if (isCancel(modeChoice)) {
|
|
6954
|
+
cancel("安装已取消");
|
|
6955
|
+
process.exit(0);
|
|
6956
|
+
}
|
|
6957
|
+
installMode = modeChoice;
|
|
6958
|
+
} else installMode = "copy";
|
|
6959
|
+
const overwriteChecks = await Promise.all(skills.flatMap((skill) => installTargets.map(async (target) => ({
|
|
6960
|
+
skillName: skill.slug,
|
|
6961
|
+
target,
|
|
6962
|
+
installed: await isSkillInstalled(skill.slug, target.agent, {
|
|
6963
|
+
global: installGlobally,
|
|
6964
|
+
eveSubagent: target.subagent
|
|
6965
|
+
})
|
|
6966
|
+
}))));
|
|
6967
|
+
const overwriteStatus = /* @__PURE__ */ new Map();
|
|
6968
|
+
for (const { skillName, target, installed } of overwriteChecks) {
|
|
6969
|
+
if (!overwriteStatus.has(skillName)) overwriteStatus.set(skillName, /* @__PURE__ */ new Map());
|
|
6970
|
+
overwriteStatus.get(skillName).set(targetKey(target), installed);
|
|
6971
|
+
}
|
|
6972
|
+
const summaryLines = [];
|
|
6973
|
+
for (const skill of skills) {
|
|
6974
|
+
if (summaryLines.length > 0) summaryLines.push("");
|
|
6975
|
+
const skillOverwrites = overwriteStatus.get(skill.slug);
|
|
6976
|
+
const overwriteAgents = installTargets.filter((t) => skillOverwrites?.get(targetKey(t))).map(targetDisplayName);
|
|
6977
|
+
summaryLines.push(`${import_picocolors.default.cyan(skill.displayName || skill.slug)}`);
|
|
6978
|
+
summaryLines.push(...buildTargetSummaryLines(installTargets, installMode));
|
|
6979
|
+
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("覆盖:")} ${overwriteAgents.join(", ")}`);
|
|
6980
|
+
}
|
|
6981
|
+
console.log();
|
|
6982
|
+
note(summaryLines.join("\n"), "安装摘要");
|
|
6983
|
+
const confirmed = await confirm({ message: "确认安装?" });
|
|
6984
|
+
if (isCancel(confirmed) || !confirmed) {
|
|
6985
|
+
cancel("安装已取消");
|
|
6986
|
+
process.exit(0);
|
|
6987
|
+
}
|
|
6988
|
+
}
|
|
6761
6989
|
const { runAdd } = await Promise.resolve().then(() => add_exports);
|
|
6762
6990
|
const installedSkills = [];
|
|
6991
|
+
const nonEveAgents = targetAgents.filter((a) => a !== "eve");
|
|
6992
|
+
const runAddBaseOpts = {
|
|
6993
|
+
global: installGlobally,
|
|
6994
|
+
copy: installMode === "copy",
|
|
6995
|
+
yes: true
|
|
6996
|
+
};
|
|
6997
|
+
if (nonEveAgents.length > 0) runAddBaseOpts.agent = nonEveAgents;
|
|
6998
|
+
if (targetAgents.includes("eve")) runAddBaseOpts.subagent = eveSubagentTargets.map((s) => s ?? "root");
|
|
6763
6999
|
for (const skill of skills) {
|
|
6764
|
-
const skillRef = skill.namespace
|
|
7000
|
+
const skillRef = `@${skill.namespace || namespace}/${skill.slug}`;
|
|
6765
7001
|
console.log(` ${DIM$3}正在安装 ${skillRef}...${RESET$3}`);
|
|
6766
7002
|
try {
|
|
6767
|
-
await runAdd([skillRef],
|
|
6768
|
-
...globalOpts,
|
|
6769
|
-
yes: true
|
|
6770
|
-
});
|
|
7003
|
+
await runAdd([skillRef], runAddBaseOpts);
|
|
6771
7004
|
console.log(` ${GREEN$2}✓ ${skill.slug}${RESET$3}`);
|
|
6772
7005
|
installedSkills.push(skill.slug);
|
|
6773
7006
|
} catch (error) {
|