bfi-cli 0.1.20 → 0.1.24
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/cli.mjs +65 -20
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -28,6 +28,7 @@ import { determineAgent } from "@vercel/detect-agent";
|
|
|
28
28
|
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
29
29
|
const GIT_HOST = process.env.BFI_GIT_HOST || "git.yyrd.com";
|
|
30
30
|
const GIT_URL = `https://${GIT_HOST}`;
|
|
31
|
+
const GIT_SOURCE_TYPE = GIT_HOST === "github.com" ? "github" : "gitlab";
|
|
31
32
|
function getOwnerRepo(parsed) {
|
|
32
33
|
if (parsed.type === "local") return null;
|
|
33
34
|
const sshMatch = parsed.url.match(/^git@[^:]+:(.+)$/);
|
|
@@ -212,7 +213,7 @@ function parseSource(input) {
|
|
|
212
213
|
if (atSkillMatch && !input.includes(":") && !input.startsWith(".") && !input.startsWith("/")) {
|
|
213
214
|
const [, owner, repo, skillFilter] = atSkillMatch;
|
|
214
215
|
return {
|
|
215
|
-
type:
|
|
216
|
+
type: GIT_SOURCE_TYPE,
|
|
216
217
|
url: `${GIT_URL}/${owner}/${repo}.git`,
|
|
217
218
|
...fragmentRef ? { ref: fragmentRef } : {},
|
|
218
219
|
skillFilter: fragmentSkillFilter || skillFilter
|
|
@@ -222,7 +223,7 @@ function parseSource(input) {
|
|
|
222
223
|
if (shorthandMatch && !input.includes(":") && !input.startsWith(".") && !input.startsWith("/")) {
|
|
223
224
|
const [, owner, repo, subpath] = shorthandMatch;
|
|
224
225
|
return {
|
|
225
|
-
type:
|
|
226
|
+
type: GIT_SOURCE_TYPE,
|
|
226
227
|
url: `${GIT_URL}/${owner}/${repo}.git`,
|
|
227
228
|
...fragmentRef ? { ref: fragmentRef } : {},
|
|
228
229
|
subpath: subpath ? sanitizeSubpath(subpath) : subpath,
|
|
@@ -4003,15 +4004,20 @@ function splitAgentsByType(agentTypes) {
|
|
|
4003
4004
|
symlinked
|
|
4004
4005
|
};
|
|
4005
4006
|
}
|
|
4006
|
-
function buildAgentSummaryLines(targetAgents, installMode) {
|
|
4007
|
+
function buildAgentSummaryLines(targetAgents, installMode, selectedAgents) {
|
|
4007
4008
|
const lines = [];
|
|
4008
4009
|
const { universal, symlinked } = splitAgentsByType(targetAgents);
|
|
4010
|
+
const selectedSet = new Set(selectedAgents || targetAgents);
|
|
4009
4011
|
if (installMode === "symlink") {
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
+
const selectedUniversal = universal.filter((a) => selectedSet.has(a));
|
|
4013
|
+
const selectedSymlink = symlinked.filter((a) => selectedSet.has(a));
|
|
4014
|
+
if (selectedUniversal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList$1(selectedUniversal)}`);
|
|
4015
|
+
if (selectedSymlink.length > 0) lines.push(` ${import_picocolors.default.dim("符号链接 →")} ${formatList$1(selectedSymlink)}`);
|
|
4016
|
+
const otherUniversal = universal.filter((a) => !selectedSet.has(a));
|
|
4017
|
+
if (otherUniversal.length > 0) lines.push(` ${import_picocolors.default.dim(`(另外 ${otherUniversal.length} 个使用共享目录的 Agent 也会自动获得此技能)`)}`);
|
|
4012
4018
|
} else {
|
|
4013
|
-
const allNames = targetAgents.map((a) => agents[a].displayName);
|
|
4014
|
-
lines.push(` ${import_picocolors.default.dim("
|
|
4019
|
+
const allNames = targetAgents.filter((a) => selectedSet.has(a)).map((a) => agents[a].displayName);
|
|
4020
|
+
lines.push(` ${import_picocolors.default.dim("复制 →")} ${formatList$1(allNames)}`);
|
|
4015
4021
|
}
|
|
4016
4022
|
return lines;
|
|
4017
4023
|
}
|
|
@@ -4037,7 +4043,7 @@ function buildTargetSummaryLines(targets, installMode) {
|
|
|
4037
4043
|
const subagentNames = targets.filter((t) => t.subagent).map(targetDisplayName);
|
|
4038
4044
|
const { universal, symlinked } = splitAgentsByType(rootAgents);
|
|
4039
4045
|
if (installMode === "symlink") {
|
|
4040
|
-
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList$1(universal)}`);
|
|
4046
|
+
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("共享目录:")} ${formatList$1(universal, 3)}`);
|
|
4041
4047
|
if (symlinked.length > 0) lines.push(` ${import_picocolors.default.dim("符号链接 →")} ${formatList$1(symlinked)}`);
|
|
4042
4048
|
if (subagentNames.length > 0) lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList$1(subagentNames)}`);
|
|
4043
4049
|
} else {
|
|
@@ -4096,22 +4102,36 @@ async function promptForAgents(message, choices) {
|
|
|
4096
4102
|
}
|
|
4097
4103
|
async function selectAgentsInteractive(options) {
|
|
4098
4104
|
const supportsGlobalFilter = (a) => !options.global || agents[a].globalSkillsDir;
|
|
4105
|
+
let installedAgents = [];
|
|
4106
|
+
try {
|
|
4107
|
+
installedAgents = await detectInstalledAgents();
|
|
4108
|
+
} catch {}
|
|
4109
|
+
const hasDetected = installedAgents.length > 0;
|
|
4110
|
+
const installedSet = new Set(installedAgents);
|
|
4099
4111
|
const universalAgents = getUniversalAgents().filter(supportsGlobalFilter);
|
|
4100
4112
|
const visibleUniversalAgents = getVisibleUniversalAgents().filter(supportsGlobalFilter);
|
|
4101
4113
|
const otherAgents = getNonUniversalAgents().filter((agent) => agent !== "eve" && supportsGlobalFilter(agent));
|
|
4114
|
+
const showAll = hasDetected ? false : true;
|
|
4115
|
+
const filteredUniversal = showAll ? visibleUniversalAgents : visibleUniversalAgents.filter((a) => installedSet.has(a));
|
|
4102
4116
|
const universalSection = {
|
|
4103
|
-
title:
|
|
4104
|
-
items:
|
|
4117
|
+
title: `共享目录 (.agents/skills) — ${showAll ? "全部" : `已检测到 ${filteredUniversal.length} 个`}`,
|
|
4118
|
+
items: filteredUniversal.map((a) => ({
|
|
4105
4119
|
value: a,
|
|
4106
4120
|
label: agents[a].displayName
|
|
4107
4121
|
})),
|
|
4108
|
-
hiddenCount: universalAgents.length - visibleUniversalAgents.length
|
|
4122
|
+
hiddenCount: showAll ? universalAgents.length - visibleUniversalAgents.length : 0
|
|
4109
4123
|
};
|
|
4110
|
-
const
|
|
4124
|
+
const filteredOther = showAll ? otherAgents : otherAgents.filter((a) => installedSet.has(a));
|
|
4125
|
+
const otherChoices = filteredOther.map((a) => ({
|
|
4111
4126
|
value: a,
|
|
4112
4127
|
label: agents[a].displayName,
|
|
4113
4128
|
hint: options.global ? agents[a].globalSkillsDir : agents[a].skillsDir
|
|
4114
4129
|
}));
|
|
4130
|
+
if (!showAll && otherAgents.length > filteredOther.length) otherChoices.push({
|
|
4131
|
+
value: "__show_all__",
|
|
4132
|
+
label: `显示全部 ${otherAgents.length + universalAgents.length} 个 Agent...`,
|
|
4133
|
+
hint: "包括未检测到的"
|
|
4134
|
+
});
|
|
4115
4135
|
let lastSelected;
|
|
4116
4136
|
try {
|
|
4117
4137
|
lastSelected = await getLastSelectedAgents();
|
|
@@ -4122,9 +4142,23 @@ async function selectAgentsInteractive(options) {
|
|
|
4122
4142
|
initialSelected: lastSelected ? lastSelected.filter((a) => otherAgents.includes(a) && !universalAgents.includes(a)) : [],
|
|
4123
4143
|
lockedSection: universalSection
|
|
4124
4144
|
});
|
|
4125
|
-
if (!isCancelled(selected))
|
|
4126
|
-
|
|
4127
|
-
|
|
4145
|
+
if (!isCancelled(selected)) {
|
|
4146
|
+
const selection = selected;
|
|
4147
|
+
if (selection.includes("__show_all__")) {
|
|
4148
|
+
const allSelected = [
|
|
4149
|
+
...selection.filter((s) => s !== "__show_all__"),
|
|
4150
|
+
...otherAgents.filter((a) => !installedSet.has(a)),
|
|
4151
|
+
...universalAgents.filter((a) => !installedSet.has(a))
|
|
4152
|
+
];
|
|
4153
|
+
try {
|
|
4154
|
+
await saveSelectedAgents(allSelected);
|
|
4155
|
+
} catch {}
|
|
4156
|
+
return [...new Set(allSelected)];
|
|
4157
|
+
}
|
|
4158
|
+
try {
|
|
4159
|
+
await saveSelectedAgents(selection);
|
|
4160
|
+
} catch {}
|
|
4161
|
+
}
|
|
4128
4162
|
return selected;
|
|
4129
4163
|
}
|
|
4130
4164
|
async function handleWellKnownSkills(source, url, options, spinner) {
|
|
@@ -4401,6 +4435,18 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4401
4435
|
outro(import_picocolors.default.green("完成!") + import_picocolors.default.dim(" 使用前请审阅技能;技能以 Agent 的全部权限运行。"));
|
|
4402
4436
|
await promptForFindSkills(options, targetAgents);
|
|
4403
4437
|
}
|
|
4438
|
+
async function cloneWithGitHubFallback(url, ref, spinner) {
|
|
4439
|
+
try {
|
|
4440
|
+
spinner.start("正在克隆仓库...");
|
|
4441
|
+
return await cloneRepo(url, ref);
|
|
4442
|
+
} catch (error) {
|
|
4443
|
+
if (error instanceof GitCloneError && !url.includes("github.com")) {
|
|
4444
|
+
spinner.message(`GitLab 未找到,降级到 GitHub: ${url.replace(/https:\/\/[^/]+\//, "https://github.com/")}`);
|
|
4445
|
+
return await cloneRepo(url.replace(/https:\/\/[^/]+\//, "https://github.com/"), ref);
|
|
4446
|
+
}
|
|
4447
|
+
throw error;
|
|
4448
|
+
}
|
|
4449
|
+
}
|
|
4404
4450
|
async function installFromSkillHub(parsed, options, spinner) {
|
|
4405
4451
|
const config = resolveConfig();
|
|
4406
4452
|
const api = new SkillHubAPI(config.registry, config.token);
|
|
@@ -4625,8 +4671,7 @@ async function runAdd(args, options = {}) {
|
|
|
4625
4671
|
skills = blobResult.skills;
|
|
4626
4672
|
spinner$2.stop(`Found ${import_picocolors.default.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
|
|
4627
4673
|
} else {
|
|
4628
|
-
spinner$2
|
|
4629
|
-
tempDir = await cloneRepo(parsed.url, parsed.ref);
|
|
4674
|
+
tempDir = await cloneWithGitHubFallback(parsed.url, parsed.ref, spinner$2);
|
|
4630
4675
|
spinner$2.stop("仓库克隆完成");
|
|
4631
4676
|
spinner$2.start("正在发现技能...");
|
|
4632
4677
|
skills = await discoverSkills(tempDir, parsed.subpath, {
|
|
@@ -4635,8 +4680,7 @@ async function runAdd(args, options = {}) {
|
|
|
4635
4680
|
});
|
|
4636
4681
|
}
|
|
4637
4682
|
} else {
|
|
4638
|
-
spinner$2
|
|
4639
|
-
tempDir = await cloneRepo(parsed.url, parsed.ref);
|
|
4683
|
+
tempDir = await cloneWithGitHubFallback(parsed.url, parsed.ref, spinner$2);
|
|
4640
4684
|
spinner$2.stop("仓库克隆完成");
|
|
4641
4685
|
spinner$2.start("正在发现技能...");
|
|
4642
4686
|
skills = await discoverSkills(tempDir, parsed.subpath, {
|
|
@@ -6923,9 +6967,10 @@ async function searchMarketplace(query) {
|
|
|
6923
6967
|
for (const skill of skills.slice(0, 12)) {
|
|
6924
6968
|
const installs = formatInstalls(skill.installs);
|
|
6925
6969
|
console.log(` ${BOLD$5}${skill.name}${RESET$8}`);
|
|
6926
|
-
if (skill.source) console.log(` ${DIM$8}
|
|
6970
|
+
if (skill.source) console.log(` ${DIM$8}来源:${skill.source}${RESET$8}`);
|
|
6927
6971
|
if (installs) console.log(` ${CYAN}${installs}${RESET$8}`);
|
|
6928
6972
|
console.log(` ${TEXT$7}https://skills.sh/${skill.id}${RESET$8}`);
|
|
6973
|
+
if (skill.source) console.log(` ${DIM$8}安装:${TEXT$7}BFI_GIT_HOST=github.com bfi skills add ${skill.source}${RESET$8}`);
|
|
6929
6974
|
console.log();
|
|
6930
6975
|
}
|
|
6931
6976
|
} catch {
|