bfi-cli 0.1.57 → 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 +287 -69
- 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) {
|
|
@@ -6749,6 +6751,51 @@ async function handleLocalList(args, globalOpts) {
|
|
|
6749
6751
|
console.log();
|
|
6750
6752
|
}
|
|
6751
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
|
+
}
|
|
6752
6799
|
async function handleInstall(args, api, globalOpts) {
|
|
6753
6800
|
const pkgRef = args[0];
|
|
6754
6801
|
if (!pkgRef) {
|
|
@@ -6757,6 +6804,8 @@ async function handleInstall(args, api, globalOpts) {
|
|
|
6757
6804
|
process.exit(1);
|
|
6758
6805
|
}
|
|
6759
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");
|
|
6760
6809
|
console.log(`${DIM$3}正在获取包信息...${RESET$3}`);
|
|
6761
6810
|
let pkgInfo;
|
|
6762
6811
|
try {
|
|
@@ -6773,16 +6822,185 @@ async function handleInstall(args, api, globalOpts) {
|
|
|
6773
6822
|
}
|
|
6774
6823
|
console.log(`${BOLD$1}${pkgInfo.name || slug}${RESET$3}(${skills.length} 个技能):`);
|
|
6775
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
|
+
}
|
|
6776
6989
|
const { runAdd } = await Promise.resolve().then(() => add_exports);
|
|
6777
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");
|
|
6778
6999
|
for (const skill of skills) {
|
|
6779
|
-
const skillRef = skill.namespace
|
|
7000
|
+
const skillRef = `@${skill.namespace || namespace}/${skill.slug}`;
|
|
6780
7001
|
console.log(` ${DIM$3}正在安装 ${skillRef}...${RESET$3}`);
|
|
6781
7002
|
try {
|
|
6782
|
-
await runAdd([skillRef],
|
|
6783
|
-
...globalOpts,
|
|
6784
|
-
yes: true
|
|
6785
|
-
});
|
|
7003
|
+
await runAdd([skillRef], runAddBaseOpts);
|
|
6786
7004
|
console.log(` ${GREEN$2}✓ ${skill.slug}${RESET$3}`);
|
|
6787
7005
|
installedSkills.push(skill.slug);
|
|
6788
7006
|
} catch (error) {
|