bfi-cli 0.1.5 → 0.1.7
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 +462 -462
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1199,12 +1199,12 @@ async function tryGhClone(repo, tempDir, ref) {
|
|
|
1199
1199
|
return true;
|
|
1200
1200
|
}
|
|
1201
1201
|
function buildGitHubAuthError(url, repo, message) {
|
|
1202
|
-
if (repo && isGitHubSsoAuthError(message)) return `GitHub
|
|
1203
|
-
if (repo) return
|
|
1204
|
-
return
|
|
1202
|
+
if (repo && isGitHubSsoAuthError(message)) return `GitHub 阻止了 ${url} 的 HTTPS 访问,因为组织强制使用 SAML SSO。\n skills 已尝试您现有的 git 凭据和可用回退方案,但均未成功。\n - 重新授权您的 GitHub 凭据/应用以符合该组织的 SSO 策略\n - 或使用 SSH 重新运行:npx skills add ${repo.sshUrl}\n - 验证访问权限:gh auth status -h github.com 或 ssh -T git@github.com`;
|
|
1203
|
+
if (repo) return `身份验证失败:${url}。\n - 私有仓库请确保您有访问权限\n - 使用 SSH 重试:npx skills add ${repo.sshUrl}\n - 检查访问权限:gh auth status -h github.com 或 ssh -T git@github.com`;
|
|
1204
|
+
return `身份验证失败:${url}。\n - 私有仓库请确保您有访问权限\n - SSH:使用 'ssh -T git@github.com' 检查您的密钥\n - HTTPS:运行 'gh auth login' 或配置 git 凭据`;
|
|
1205
1205
|
}
|
|
1206
1206
|
async function cloneRepo(url, ref) {
|
|
1207
|
-
if (/^ext::/i.test(url)) throw new GitCloneError("
|
|
1207
|
+
if (/^ext::/i.test(url)) throw new GitCloneError("不支持的 Git 传输协议:ext", url);
|
|
1208
1208
|
const tempDir = await mkdtemp(join(tmpdir(), "skills-"));
|
|
1209
1209
|
const cloneOptions = ref ? [
|
|
1210
1210
|
"--depth",
|
|
@@ -1225,7 +1225,7 @@ async function cloneRepo(url, ref) {
|
|
|
1225
1225
|
recursive: true,
|
|
1226
1226
|
force: true
|
|
1227
1227
|
}).catch(() => {});
|
|
1228
|
-
throw new GitCloneError(
|
|
1228
|
+
throw new GitCloneError(`克隆超时(${Math.round(CLONE_TIMEOUT_MS / 1e3)} 秒)。常见原因:\n - 仓库过大:使用 SKILLS_CLONE_TIMEOUT_MS=600000 (10 分钟) 提高超时时间\n - 网络较慢:重试,或手动克隆后将本地路径传给 'skills add'\n - 私有仓库未配置凭据:请确保身份验证已配置\n - SSH:ssh-add -l(检查已加载的密钥)\n - HTTPS:gh auth status(如果使用 GitHub CLI)`, url, true, false);
|
|
1229
1229
|
}
|
|
1230
1230
|
if (isAuthError && repo && isGitHubHttpsCloneUrl(url)) {
|
|
1231
1231
|
try {
|
|
@@ -1243,7 +1243,7 @@ async function cloneRepo(url, ref) {
|
|
|
1243
1243
|
force: true
|
|
1244
1244
|
}).catch(() => {});
|
|
1245
1245
|
if (isAuthError) throw new GitCloneError(buildGitHubAuthError(url, repo, errorMessage), url, false, true);
|
|
1246
|
-
throw new GitCloneError(
|
|
1246
|
+
throw new GitCloneError(`克隆失败 ${url}:${errorMessage}`, url, false, false);
|
|
1247
1247
|
}
|
|
1248
1248
|
}
|
|
1249
1249
|
async function cleanupTempDir(dir) {
|
|
@@ -2366,7 +2366,7 @@ const agents = {
|
|
|
2366
2366
|
},
|
|
2367
2367
|
universal: {
|
|
2368
2368
|
name: "universal",
|
|
2369
|
-
displayName: "
|
|
2369
|
+
displayName: "共享目录",
|
|
2370
2370
|
skillsDir: ".agents/skills",
|
|
2371
2371
|
globalSkillsDir: join(configHome, "agents/skills"),
|
|
2372
2372
|
showInUniversalList: false,
|
|
@@ -2502,7 +2502,7 @@ async function installSkillForAgent(skill, agentType, options = {}) {
|
|
|
2502
2502
|
success: false,
|
|
2503
2503
|
path: "",
|
|
2504
2504
|
mode: options.mode ?? "symlink",
|
|
2505
|
-
error: `${agent.displayName}
|
|
2505
|
+
error: `${agent.displayName} 不支持全局技能安装`
|
|
2506
2506
|
};
|
|
2507
2507
|
const skillName = sanitizeName(skill.name || basename(skill.path));
|
|
2508
2508
|
const installMode = options.mode ?? "symlink";
|
|
@@ -2514,13 +2514,13 @@ async function installSkillForAgent(skill, agentType, options = {}) {
|
|
|
2514
2514
|
success: false,
|
|
2515
2515
|
path: agentDir,
|
|
2516
2516
|
mode: installMode,
|
|
2517
|
-
error: "
|
|
2517
|
+
error: "无效的技能名称:检测到潜在的路径遍历攻击"
|
|
2518
2518
|
};
|
|
2519
2519
|
if (!isPathSafe$1(agentBase, agentDir)) return {
|
|
2520
2520
|
success: false,
|
|
2521
2521
|
path: agentDir,
|
|
2522
2522
|
mode: installMode,
|
|
2523
|
-
error: "
|
|
2523
|
+
error: "无效的技能名称:检测到潜在的路径遍历攻击"
|
|
2524
2524
|
};
|
|
2525
2525
|
try {
|
|
2526
2526
|
if (pathsOverlap(skill.path, agentDir)) return {
|
|
@@ -2584,7 +2584,7 @@ async function installSkillForAgent(skill, agentType, options = {}) {
|
|
|
2584
2584
|
success: false,
|
|
2585
2585
|
path: agentDir,
|
|
2586
2586
|
mode: installMode,
|
|
2587
|
-
error: error instanceof Error ? error.message : "
|
|
2587
|
+
error: error instanceof Error ? error.message : "未知错误"
|
|
2588
2588
|
};
|
|
2589
2589
|
}
|
|
2590
2590
|
}
|
|
@@ -2687,7 +2687,7 @@ async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
|
|
|
2687
2687
|
success: false,
|
|
2688
2688
|
path: "",
|
|
2689
2689
|
mode: installMode,
|
|
2690
|
-
error: `${agent.displayName}
|
|
2690
|
+
error: `${agent.displayName} 不支持全局技能安装`
|
|
2691
2691
|
};
|
|
2692
2692
|
const skillName = sanitizeName(skill.installName);
|
|
2693
2693
|
const canonicalBase = agentType === "eve" && installMode === "symlink" ? getAgentBaseDir(agentType, isGlobal, cwd, eveSubagent) : getCanonicalSkillsDir(isGlobal, cwd);
|
|
@@ -2698,13 +2698,13 @@ async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
|
|
|
2698
2698
|
success: false,
|
|
2699
2699
|
path: agentDir,
|
|
2700
2700
|
mode: installMode,
|
|
2701
|
-
error: "
|
|
2701
|
+
error: "无效的技能名称:检测到潜在的路径遍历攻击"
|
|
2702
2702
|
};
|
|
2703
2703
|
if (!isPathSafe$1(agentBase, agentDir)) return {
|
|
2704
2704
|
success: false,
|
|
2705
2705
|
path: agentDir,
|
|
2706
2706
|
mode: installMode,
|
|
2707
|
-
error: "
|
|
2707
|
+
error: "无效的技能名称:检测到潜在的路径遍历攻击"
|
|
2708
2708
|
};
|
|
2709
2709
|
async function writeSkillFiles(targetDir) {
|
|
2710
2710
|
for (const [filePath, content] of skill.files) {
|
|
@@ -2755,7 +2755,7 @@ async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
|
|
|
2755
2755
|
success: false,
|
|
2756
2756
|
path: agentDir,
|
|
2757
2757
|
mode: installMode,
|
|
2758
|
-
error: error instanceof Error ? error.message : "
|
|
2758
|
+
error: error instanceof Error ? error.message : "未知错误"
|
|
2759
2759
|
};
|
|
2760
2760
|
}
|
|
2761
2761
|
}
|
|
@@ -2769,7 +2769,7 @@ async function installBlobSkillForAgent(skill, agentType, options = {}) {
|
|
|
2769
2769
|
success: false,
|
|
2770
2770
|
path: "",
|
|
2771
2771
|
mode: installMode,
|
|
2772
|
-
error: `${agent.displayName}
|
|
2772
|
+
error: `${agent.displayName} 不支持全局技能安装`
|
|
2773
2773
|
};
|
|
2774
2774
|
const skillName = sanitizeName(skill.installName);
|
|
2775
2775
|
const agentBase = getAgentBaseDir(agentType, isGlobal, cwd, eveSubagent);
|
|
@@ -2779,7 +2779,7 @@ async function installBlobSkillForAgent(skill, agentType, options = {}) {
|
|
|
2779
2779
|
success: false,
|
|
2780
2780
|
path: flatSkillPath,
|
|
2781
2781
|
mode: installMode,
|
|
2782
|
-
error: "
|
|
2782
|
+
error: "无效的技能名称:检测到潜在的路径遍历攻击"
|
|
2783
2783
|
};
|
|
2784
2784
|
try {
|
|
2785
2785
|
await mkdir(agentBase, { recursive: true });
|
|
@@ -2798,7 +2798,7 @@ async function installBlobSkillForAgent(skill, agentType, options = {}) {
|
|
|
2798
2798
|
success: false,
|
|
2799
2799
|
path: flatSkillPath,
|
|
2800
2800
|
mode: installMode,
|
|
2801
|
-
error: error instanceof Error ? error.message : "
|
|
2801
|
+
error: error instanceof Error ? error.message : "未知错误"
|
|
2802
2802
|
};
|
|
2803
2803
|
}
|
|
2804
2804
|
}
|
|
@@ -2809,13 +2809,13 @@ async function installBlobSkillForAgent(skill, agentType, options = {}) {
|
|
|
2809
2809
|
success: false,
|
|
2810
2810
|
path: agentDir,
|
|
2811
2811
|
mode: installMode,
|
|
2812
|
-
error: "
|
|
2812
|
+
error: "无效的技能名称:检测到潜在的路径遍历攻击"
|
|
2813
2813
|
};
|
|
2814
2814
|
if (!isPathSafe$1(agentBase, agentDir)) return {
|
|
2815
2815
|
success: false,
|
|
2816
2816
|
path: agentDir,
|
|
2817
2817
|
mode: installMode,
|
|
2818
|
-
error: "
|
|
2818
|
+
error: "无效的技能名称:检测到潜在的路径遍历攻击"
|
|
2819
2819
|
};
|
|
2820
2820
|
async function writeSkillFiles(targetDir) {
|
|
2821
2821
|
for (const file of skill.files) {
|
|
@@ -2875,7 +2875,7 @@ async function installBlobSkillForAgent(skill, agentType, options = {}) {
|
|
|
2875
2875
|
success: false,
|
|
2876
2876
|
path: agentDir,
|
|
2877
2877
|
mode: installMode,
|
|
2878
|
-
error: error instanceof Error ? error.message : "
|
|
2878
|
+
error: error instanceof Error ? error.message : "未知错误"
|
|
2879
2879
|
};
|
|
2880
2880
|
}
|
|
2881
2881
|
}
|
|
@@ -4056,7 +4056,7 @@ function multiselect(opts) {
|
|
|
4056
4056
|
return multiselect$1({
|
|
4057
4057
|
...opts,
|
|
4058
4058
|
options: opts.options,
|
|
4059
|
-
message: `${opts.message} ${import_picocolors.default.dim("(
|
|
4059
|
+
message: `${opts.message} ${import_picocolors.default.dim("(空格切换)")}`
|
|
4060
4060
|
});
|
|
4061
4061
|
}
|
|
4062
4062
|
async function promptForAgents(message, choices) {
|
|
@@ -4090,7 +4090,7 @@ async function selectAgentsInteractive(options) {
|
|
|
4090
4090
|
const visibleUniversalAgents = getVisibleUniversalAgents().filter(supportsGlobalFilter);
|
|
4091
4091
|
const otherAgents = getNonUniversalAgents().filter((agent) => agent !== "eve" && supportsGlobalFilter(agent));
|
|
4092
4092
|
const universalSection = {
|
|
4093
|
-
title: "
|
|
4093
|
+
title: "共享目录 (.agents/skills)",
|
|
4094
4094
|
items: visibleUniversalAgents.map((a) => ({
|
|
4095
4095
|
value: a,
|
|
4096
4096
|
label: agents[a].displayName
|
|
@@ -4107,7 +4107,7 @@ async function selectAgentsInteractive(options) {
|
|
|
4107
4107
|
lastSelected = await getLastSelectedAgents();
|
|
4108
4108
|
} catch {}
|
|
4109
4109
|
const selected = await searchMultiselect({
|
|
4110
|
-
message: "
|
|
4110
|
+
message: "请选择要安装到的 Agent:",
|
|
4111
4111
|
items: otherChoices,
|
|
4112
4112
|
initialSelected: lastSelected ? lastSelected.filter((a) => otherAgents.includes(a) && !universalAgents.includes(a)) : [],
|
|
4113
4113
|
lockedSection: universalSection
|
|
@@ -4118,29 +4118,29 @@ async function selectAgentsInteractive(options) {
|
|
|
4118
4118
|
return selected;
|
|
4119
4119
|
}
|
|
4120
4120
|
async function handleWellKnownSkills(source, url, options, spinner) {
|
|
4121
|
-
spinner.start("
|
|
4121
|
+
spinner.start("正在从 well-known 端点发现技能...");
|
|
4122
4122
|
const skills = await wellKnownProvider.fetchAllSkills(url);
|
|
4123
4123
|
if (skills.length === 0) {
|
|
4124
|
-
spinner.stop(import_picocolors.default.red("
|
|
4125
|
-
outro(import_picocolors.default.red("
|
|
4124
|
+
spinner.stop(import_picocolors.default.red("未找到技能"));
|
|
4125
|
+
outro(import_picocolors.default.red("该 URL 未找到技能。请确保服务器提供 /.well-known/agent-skills/index.json 或 /.well-known/skills/index.json 文件。"));
|
|
4126
4126
|
process.exit(1);
|
|
4127
4127
|
}
|
|
4128
4128
|
spinner.stop(`Found ${import_picocolors.default.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
|
|
4129
4129
|
for (const skill of skills) {
|
|
4130
4130
|
log.info(`Skill: ${import_picocolors.default.cyan(skill.installName)}`);
|
|
4131
4131
|
log.message(import_picocolors.default.dim(skill.description));
|
|
4132
|
-
if (skill.files.size > 1) log.message(import_picocolors.default.dim(`
|
|
4132
|
+
if (skill.files.size > 1) log.message(import_picocolors.default.dim(` 文件: ${Array.from(skill.files.keys()).join(", ")}`));
|
|
4133
4133
|
}
|
|
4134
4134
|
if (options.list) {
|
|
4135
4135
|
console.log();
|
|
4136
|
-
log.step(import_picocolors.default.bold("
|
|
4136
|
+
log.step(import_picocolors.default.bold("可用技能"));
|
|
4137
4137
|
for (const skill of skills) {
|
|
4138
4138
|
log.message(` ${import_picocolors.default.cyan(skill.installName)}`);
|
|
4139
4139
|
log.message(` ${import_picocolors.default.dim(skill.description)}`);
|
|
4140
|
-
if (skill.files.size > 1) log.message(` ${import_picocolors.default.dim(
|
|
4140
|
+
if (skill.files.size > 1) log.message(` ${import_picocolors.default.dim(`文件: ${skill.files.size}`)}`);
|
|
4141
4141
|
}
|
|
4142
4142
|
console.log();
|
|
4143
|
-
outro("
|
|
4143
|
+
outro("不带 --list 参数运行即可安装");
|
|
4144
4144
|
process.exit(0);
|
|
4145
4145
|
}
|
|
4146
4146
|
let selectedSkills;
|
|
@@ -4150,8 +4150,8 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4150
4150
|
} else if (options.skill && options.skill.length > 0) {
|
|
4151
4151
|
selectedSkills = skills.filter((s) => options.skill.some((name) => s.installName.toLowerCase() === name.toLowerCase() || s.name.toLowerCase() === name.toLowerCase()));
|
|
4152
4152
|
if (selectedSkills.length === 0) {
|
|
4153
|
-
log.error(
|
|
4154
|
-
log.info("
|
|
4153
|
+
log.error(`未找到匹配技能:${options.skill.join(", ")}`);
|
|
4154
|
+
log.info("可用技能:");
|
|
4155
4155
|
for (const s of skills) log.message(` - ${s.installName}`);
|
|
4156
4156
|
process.exit(1);
|
|
4157
4157
|
}
|
|
@@ -4164,7 +4164,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4164
4164
|
log.info(`Installing all ${skills.length} skills`);
|
|
4165
4165
|
} else {
|
|
4166
4166
|
const selected = await multiselect({
|
|
4167
|
-
message: "
|
|
4167
|
+
message: "选择要安装的技能",
|
|
4168
4168
|
options: skills.map((s) => ({
|
|
4169
4169
|
value: s,
|
|
4170
4170
|
label: s.installName,
|
|
@@ -4173,7 +4173,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4173
4173
|
required: true
|
|
4174
4174
|
});
|
|
4175
4175
|
if (isCancel(selected)) {
|
|
4176
|
-
cancel("
|
|
4176
|
+
cancel("安装已取消");
|
|
4177
4177
|
process.exit(0);
|
|
4178
4178
|
}
|
|
4179
4179
|
selectedSkills = selected;
|
|
@@ -4186,27 +4186,27 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4186
4186
|
} else if (options.agent && options.agent.length > 0) {
|
|
4187
4187
|
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
4188
4188
|
if (invalidAgents.length > 0) {
|
|
4189
|
-
log.error(
|
|
4190
|
-
log.info(
|
|
4189
|
+
log.error(`无效 Agent:${invalidAgents.join(", ")}`);
|
|
4190
|
+
log.info(`可用 Agent:${validAgents.join(", ")}`);
|
|
4191
4191
|
process.exit(1);
|
|
4192
4192
|
}
|
|
4193
4193
|
targetAgents = options.agent;
|
|
4194
4194
|
} else {
|
|
4195
|
-
spinner.start("
|
|
4195
|
+
spinner.start("正在加载 Agent...");
|
|
4196
4196
|
const installedAgents = await detectInstalledAgents();
|
|
4197
4197
|
const totalAgents = Object.keys(agents).length;
|
|
4198
4198
|
spinner.stop(`${totalAgents} agents`);
|
|
4199
4199
|
if (installedAgents.length === 0) if (options.yes) {
|
|
4200
4200
|
targetAgents = validAgents;
|
|
4201
|
-
log.info("
|
|
4201
|
+
log.info("正在安装到全部 Agent");
|
|
4202
4202
|
} else {
|
|
4203
|
-
log.info("
|
|
4204
|
-
const selected = await promptForAgents("
|
|
4203
|
+
log.info("请选择要安装技能的 Agent");
|
|
4204
|
+
const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).map(([key, config]) => ({
|
|
4205
4205
|
value: key,
|
|
4206
4206
|
label: config.displayName
|
|
4207
4207
|
})));
|
|
4208
4208
|
if (isCancel(selected)) {
|
|
4209
|
-
cancel("
|
|
4209
|
+
cancel("安装已取消");
|
|
4210
4210
|
process.exit(0);
|
|
4211
4211
|
}
|
|
4212
4212
|
targetAgents = selected;
|
|
@@ -4220,7 +4220,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4220
4220
|
} else {
|
|
4221
4221
|
const selected = await selectAgentsInteractive({ global: options.global });
|
|
4222
4222
|
if (isCancel(selected)) {
|
|
4223
|
-
cancel("
|
|
4223
|
+
cancel("安装已取消");
|
|
4224
4224
|
process.exit(0);
|
|
4225
4225
|
}
|
|
4226
4226
|
targetAgents = selected;
|
|
@@ -4230,19 +4230,19 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4230
4230
|
const supportsGlobal = targetAgents.some((a) => agents[a].globalSkillsDir !== void 0);
|
|
4231
4231
|
if (options.global === void 0 && !options.yes && supportsGlobal) {
|
|
4232
4232
|
const scope = await select({
|
|
4233
|
-
message: "
|
|
4233
|
+
message: "安装范围",
|
|
4234
4234
|
options: [{
|
|
4235
4235
|
value: false,
|
|
4236
|
-
label: "
|
|
4237
|
-
hint: "
|
|
4236
|
+
label: "项目",
|
|
4237
|
+
hint: "安装到当前目录(随项目一起提交)"
|
|
4238
4238
|
}, {
|
|
4239
4239
|
value: true,
|
|
4240
|
-
label: "
|
|
4241
|
-
hint: "
|
|
4240
|
+
label: "全局",
|
|
4241
|
+
hint: "安装到主目录(跨所有项目可用)"
|
|
4242
4242
|
}]
|
|
4243
4243
|
});
|
|
4244
4244
|
if (isCancel(scope)) {
|
|
4245
|
-
cancel("
|
|
4245
|
+
cancel("安装已取消");
|
|
4246
4246
|
process.exit(0);
|
|
4247
4247
|
}
|
|
4248
4248
|
installGlobally = scope;
|
|
@@ -4251,19 +4251,19 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4251
4251
|
const uniqueDirs = new Set(targetAgents.map((a) => agents[a].skillsDir));
|
|
4252
4252
|
if (!options.copy && !options.yes && uniqueDirs.size > 1) {
|
|
4253
4253
|
const modeChoice = await select({
|
|
4254
|
-
message: "
|
|
4254
|
+
message: "安装方式",
|
|
4255
4255
|
options: [{
|
|
4256
4256
|
value: "symlink",
|
|
4257
|
-
label: "
|
|
4258
|
-
hint: "
|
|
4257
|
+
label: "符号链接(推荐)",
|
|
4258
|
+
hint: "单一来源,易于更新"
|
|
4259
4259
|
}, {
|
|
4260
4260
|
value: "copy",
|
|
4261
|
-
label: "
|
|
4262
|
-
hint: "
|
|
4261
|
+
label: "复制到所有 Agent",
|
|
4262
|
+
hint: "每个 Agent 独立副本"
|
|
4263
4263
|
}]
|
|
4264
4264
|
});
|
|
4265
4265
|
if (isCancel(modeChoice)) {
|
|
4266
|
-
cancel("
|
|
4266
|
+
cancel("安装已取消");
|
|
4267
4267
|
process.exit(0);
|
|
4268
4268
|
}
|
|
4269
4269
|
installMode = modeChoice;
|
|
@@ -4292,17 +4292,17 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4292
4292
|
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$1(overwriteAgents)}`);
|
|
4293
4293
|
}
|
|
4294
4294
|
console.log();
|
|
4295
|
-
note(summaryLines.join("\n"), "
|
|
4295
|
+
note(summaryLines.join("\n"), "安装摘要");
|
|
4296
4296
|
if (!options.yes) {
|
|
4297
|
-
const confirmed = await confirm({ message: "
|
|
4297
|
+
const confirmed = await confirm({ message: "确认安装?" });
|
|
4298
4298
|
if (isCancel(confirmed) || !confirmed) {
|
|
4299
|
-
cancel("
|
|
4299
|
+
cancel("安装已取消");
|
|
4300
4300
|
process.exit(0);
|
|
4301
4301
|
}
|
|
4302
4302
|
}
|
|
4303
4303
|
const sourceIdentifier = wellKnownProvider.getSourceIdentifier(url);
|
|
4304
4304
|
const wellKnownPrivacyPromise = isSourcePrivate(sourceIdentifier).catch(() => null);
|
|
4305
|
-
spinner.start("
|
|
4305
|
+
spinner.start("正在安装技能...");
|
|
4306
4306
|
const results = [];
|
|
4307
4307
|
for (const skill of selectedSkills) for (const agent of targetAgents) {
|
|
4308
4308
|
const result = await installWellKnownSkillForAgent(skill, agent, {
|
|
@@ -4315,7 +4315,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4315
4315
|
...result
|
|
4316
4316
|
});
|
|
4317
4317
|
}
|
|
4318
|
-
spinner.stop("
|
|
4318
|
+
spinner.stop("安装完成");
|
|
4319
4319
|
console.log();
|
|
4320
4320
|
const successful = results.filter((r) => r.success);
|
|
4321
4321
|
const failed = results.filter((r) => !r.success);
|
|
@@ -4378,17 +4378,17 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
4378
4378
|
const title = import_picocolors.default.green(`Installed ${skillCount} skill${skillCount !== 1 ? "s" : ""}`);
|
|
4379
4379
|
note(resultLines.join("\n"), title);
|
|
4380
4380
|
if (symlinkFailures.length > 0) {
|
|
4381
|
-
log.warn(import_picocolors.default.yellow(
|
|
4382
|
-
log.message(import_picocolors.default.dim("
|
|
4381
|
+
log.warn(import_picocolors.default.yellow(`符号链接失败: ${formatList$1(copiedAgents)}`));
|
|
4382
|
+
log.message(import_picocolors.default.dim(" 已改为复制文件。在 Windows 上,请启用开发者模式以支持符号链接。"));
|
|
4383
4383
|
}
|
|
4384
4384
|
}
|
|
4385
4385
|
if (failed.length > 0) {
|
|
4386
4386
|
console.log();
|
|
4387
|
-
log.error(import_picocolors.default.red(
|
|
4387
|
+
log.error(import_picocolors.default.red(`安装失败 ${failed.length} 个`));
|
|
4388
4388
|
for (const r of failed) log.message(` ${import_picocolors.default.red("✗")} ${r.skill} → ${r.agent}: ${import_picocolors.default.dim(r.error)}`);
|
|
4389
4389
|
}
|
|
4390
4390
|
console.log();
|
|
4391
|
-
outro(import_picocolors.default.green("
|
|
4391
|
+
outro(import_picocolors.default.green("完成!") + import_picocolors.default.dim(" 使用前请审阅技能;技能以 Agent 的全部权限运行。"));
|
|
4392
4392
|
await promptForFindSkills(options, targetAgents);
|
|
4393
4393
|
}
|
|
4394
4394
|
async function installFromSkillHub(parsed, options, spinner) {
|
|
@@ -4399,10 +4399,10 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
4399
4399
|
let namespace;
|
|
4400
4400
|
let slug;
|
|
4401
4401
|
if (restParts.length === 0) {
|
|
4402
|
-
spinner.start(
|
|
4402
|
+
spinner.start(`正在 SkillHub 搜索 "${rawRef}"...`);
|
|
4403
4403
|
const hits = ((await api.searchSkills(rawRef)).data || []).slice(0, 20);
|
|
4404
4404
|
if (hits.length === 0) {
|
|
4405
|
-
spinner.stop(import_picocolors.default.red("
|
|
4405
|
+
spinner.stop(import_picocolors.default.red("无结果"));
|
|
4406
4406
|
outro(import_picocolors.default.red(`No skills found on SkillHub for "${rawRef}".`));
|
|
4407
4407
|
process.exit(1);
|
|
4408
4408
|
}
|
|
@@ -4411,10 +4411,10 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
4411
4411
|
const hit = hits[0];
|
|
4412
4412
|
namespace = hit.namespace;
|
|
4413
4413
|
slug = hit.slug;
|
|
4414
|
-
log.info(
|
|
4414
|
+
log.info(`自动选择:${import_picocolors.default.cyan(`@${namespace}/${slug}`)} — ${hit.description || hit.name}`);
|
|
4415
4415
|
} else {
|
|
4416
4416
|
const idx = await select({
|
|
4417
|
-
message: "
|
|
4417
|
+
message: "匹配到多个技能 — 请选择一个",
|
|
4418
4418
|
options: hits.map((h, idx) => ({
|
|
4419
4419
|
value: idx,
|
|
4420
4420
|
label: `@${h.namespace}/${h.slug}`,
|
|
@@ -4422,7 +4422,7 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
4422
4422
|
}))
|
|
4423
4423
|
});
|
|
4424
4424
|
if (isCancel(idx)) {
|
|
4425
|
-
cancel("
|
|
4425
|
+
cancel("安装已取消");
|
|
4426
4426
|
process.exit(0);
|
|
4427
4427
|
}
|
|
4428
4428
|
const chosen = hits[idx];
|
|
@@ -4435,13 +4435,13 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
4435
4435
|
}
|
|
4436
4436
|
const canonicalSlug = toCanonicalSlug(namespace, slug);
|
|
4437
4437
|
const version = parsed.ref || "latest";
|
|
4438
|
-
spinner.start(
|
|
4438
|
+
spinner.start(`正在获取 @${namespace}/${slug} 的技能元数据...`);
|
|
4439
4439
|
let metadata;
|
|
4440
4440
|
try {
|
|
4441
4441
|
metadata = await api.getSkill(canonicalSlug);
|
|
4442
4442
|
} catch (err) {
|
|
4443
|
-
spinner.stop(import_picocolors.default.red("
|
|
4444
|
-
outro(import_picocolors.default.red(
|
|
4443
|
+
spinner.stop(import_picocolors.default.red("获取元数据失败"));
|
|
4444
|
+
outro(import_picocolors.default.red(`未在 SkillHub 上找到技能 @${namespace}/${slug}: ${err.message}`));
|
|
4445
4445
|
process.exit(1);
|
|
4446
4446
|
}
|
|
4447
4447
|
const meta = metadata;
|
|
@@ -4449,39 +4449,39 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
4449
4449
|
const tempDir = join(tmpdir(), `.bfi-skillhub-${canonicalSlug.replace(/[/:@]/g, "-")}-${Date.now()}`);
|
|
4450
4450
|
mkdirSync(tempDir, { recursive: true });
|
|
4451
4451
|
const zipPath = join(tempDir, "skill.zip");
|
|
4452
|
-
spinner.start("
|
|
4452
|
+
spinner.start("正在下载技能...");
|
|
4453
4453
|
try {
|
|
4454
4454
|
await api.downloadSkill(namespace, slug, version, zipPath);
|
|
4455
4455
|
} catch (err) {
|
|
4456
|
-
spinner.stop(import_picocolors.default.red("
|
|
4456
|
+
spinner.stop(import_picocolors.default.red("下载失败"));
|
|
4457
4457
|
try {
|
|
4458
4458
|
rmSync(tempDir, {
|
|
4459
4459
|
recursive: true,
|
|
4460
4460
|
force: true
|
|
4461
4461
|
});
|
|
4462
4462
|
} catch {}
|
|
4463
|
-
outro(import_picocolors.default.red(
|
|
4463
|
+
outro(import_picocolors.default.red(`下载失败 @${namespace}/${slug}:${err.message}`));
|
|
4464
4464
|
process.exit(1);
|
|
4465
4465
|
}
|
|
4466
|
-
spinner.stop("
|
|
4467
|
-
spinner.start("
|
|
4466
|
+
spinner.stop("下载完成");
|
|
4467
|
+
spinner.start("正在解压...");
|
|
4468
4468
|
const extractDir = join(tempDir, "extracted");
|
|
4469
4469
|
mkdirSync(extractDir, { recursive: true });
|
|
4470
4470
|
try {
|
|
4471
4471
|
await extractZip(zipPath, extractDir);
|
|
4472
4472
|
} catch (err) {
|
|
4473
|
-
spinner.stop(import_picocolors.default.red("
|
|
4473
|
+
spinner.stop(import_picocolors.default.red("解压失败"));
|
|
4474
4474
|
try {
|
|
4475
4475
|
rmSync(tempDir, {
|
|
4476
4476
|
recursive: true,
|
|
4477
4477
|
force: true
|
|
4478
4478
|
});
|
|
4479
4479
|
} catch {}
|
|
4480
|
-
outro(import_picocolors.default.red(
|
|
4480
|
+
outro(import_picocolors.default.red(`解压技能压缩包失败:${err.message}`));
|
|
4481
4481
|
process.exit(1);
|
|
4482
4482
|
}
|
|
4483
|
-
spinner.stop("
|
|
4484
|
-
spinner.start("
|
|
4483
|
+
spinner.stop("解压完成");
|
|
4484
|
+
spinner.start("正在发现技能...");
|
|
4485
4485
|
const skills = await discoverSkills(extractDir, parsed.subpath, {
|
|
4486
4486
|
includeInternal: !!(options.skill && options.skill.length > 0),
|
|
4487
4487
|
fullDepth: options.fullDepth
|
|
@@ -4507,7 +4507,7 @@ async function runAdd(args, options = {}) {
|
|
|
4507
4507
|
let installTipShown = false;
|
|
4508
4508
|
const showInstallTip = () => {
|
|
4509
4509
|
if (installTipShown) return;
|
|
4510
|
-
log.message(import_picocolors.default.dim("
|
|
4510
|
+
log.message(import_picocolors.default.dim("提示:使用 --yes (-y) 和 --global (-g) 参数可跳过交互提示直接安装。"));
|
|
4511
4511
|
installTipShown = true;
|
|
4512
4512
|
};
|
|
4513
4513
|
if (!source) {
|
|
@@ -4537,14 +4537,14 @@ async function runAdd(args, options = {}) {
|
|
|
4537
4537
|
}
|
|
4538
4538
|
console.log();
|
|
4539
4539
|
if (!agentResult.isAgent) intro(import_picocolors.default.bgCyan(import_picocolors.default.black(" skills ")));
|
|
4540
|
-
if (agentResult.isAgent) log.info(import_picocolors.default.bgCyan(import_picocolors.default.black(import_picocolors.default.bold(` ${agentResult.agent.name} `))) + " Agent
|
|
4540
|
+
if (agentResult.isAgent) log.info(import_picocolors.default.bgCyan(import_picocolors.default.black(import_picocolors.default.bold(` ${agentResult.agent.name} `))) + " 已检测到 Agent — 以非交互模式安装");
|
|
4541
4541
|
else if (!process.stdin.isTTY) showInstallTip();
|
|
4542
4542
|
let tempDir = null;
|
|
4543
4543
|
try {
|
|
4544
4544
|
const spinner$2 = spinner();
|
|
4545
|
-
spinner$2.start("
|
|
4545
|
+
spinner$2.start("正在解析源...");
|
|
4546
4546
|
const parsed = parseSource(source);
|
|
4547
|
-
spinner$2.stop(
|
|
4547
|
+
spinner$2.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)}` : ""}`);
|
|
4548
4548
|
const ownerRepoRaw = getOwnerRepo(parsed);
|
|
4549
4549
|
const repoPrivacyPromise = (() => {
|
|
4550
4550
|
if (!ownerRepoRaw) return Promise.resolve(null);
|
|
@@ -4568,14 +4568,14 @@ async function runAdd(args, options = {}) {
|
|
|
4568
4568
|
skills = result.skills;
|
|
4569
4569
|
tempDir = result.tempDir;
|
|
4570
4570
|
} else if (parsed.type === "local") {
|
|
4571
|
-
spinner$2.start("
|
|
4571
|
+
spinner$2.start("正在验证本地路径...");
|
|
4572
4572
|
if (!existsSync(parsed.localPath)) {
|
|
4573
|
-
spinner$2.stop(import_picocolors.default.red("
|
|
4574
|
-
outro(import_picocolors.default.red(
|
|
4573
|
+
spinner$2.stop(import_picocolors.default.red("路径未找到"));
|
|
4574
|
+
outro(import_picocolors.default.red(`本地路径不存在:${parsed.localPath}`));
|
|
4575
4575
|
process.exit(1);
|
|
4576
4576
|
}
|
|
4577
|
-
spinner$2.stop("
|
|
4578
|
-
spinner$2.start("
|
|
4577
|
+
spinner$2.stop("本地路径验证通过");
|
|
4578
|
+
spinner$2.start("正在发现技能...");
|
|
4579
4579
|
skills = await discoverSkills(parsed.localPath, parsed.subpath, {
|
|
4580
4580
|
includeInternal,
|
|
4581
4581
|
fullDepth: options.fullDepth
|
|
@@ -4590,7 +4590,7 @@ async function runAdd(args, options = {}) {
|
|
|
4590
4590
|
const owner = ownerRepo?.split("/")[0]?.toLowerCase();
|
|
4591
4591
|
const isSelfHostedRepo = !!ownerRepo && Object.hasOwn(BLOB_ALLOWED_REPOS, ownerRepo.toLowerCase());
|
|
4592
4592
|
if (ownerRepo && owner && (isSelfHostedRepo || BLOB_ALLOWED_OWNERS.includes(owner))) {
|
|
4593
|
-
spinner$2.start("
|
|
4593
|
+
spinner$2.start("正在获取技能...");
|
|
4594
4594
|
blobResult = await tryBlobInstall(ownerRepo, {
|
|
4595
4595
|
subpath: parsed.subpath,
|
|
4596
4596
|
skillFilter: parsed.skillFilter,
|
|
@@ -4604,35 +4604,35 @@ async function runAdd(args, options = {}) {
|
|
|
4604
4604
|
skills = blobResult.skills;
|
|
4605
4605
|
spinner$2.stop(`Found ${import_picocolors.default.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
|
|
4606
4606
|
} else {
|
|
4607
|
-
spinner$2.start("
|
|
4607
|
+
spinner$2.start("正在克隆仓库...");
|
|
4608
4608
|
tempDir = await cloneRepo(parsed.url, parsed.ref);
|
|
4609
|
-
spinner$2.stop("
|
|
4610
|
-
spinner$2.start("
|
|
4609
|
+
spinner$2.stop("仓库克隆完成");
|
|
4610
|
+
spinner$2.start("正在发现技能...");
|
|
4611
4611
|
skills = await discoverSkills(tempDir, parsed.subpath, {
|
|
4612
4612
|
includeInternal,
|
|
4613
4613
|
fullDepth: options.fullDepth
|
|
4614
4614
|
});
|
|
4615
4615
|
}
|
|
4616
4616
|
} else {
|
|
4617
|
-
spinner$2.start("
|
|
4617
|
+
spinner$2.start("正在克隆仓库...");
|
|
4618
4618
|
tempDir = await cloneRepo(parsed.url, parsed.ref);
|
|
4619
|
-
spinner$2.stop("
|
|
4620
|
-
spinner$2.start("
|
|
4619
|
+
spinner$2.stop("仓库克隆完成");
|
|
4620
|
+
spinner$2.start("正在发现技能...");
|
|
4621
4621
|
skills = await discoverSkills(tempDir, parsed.subpath, {
|
|
4622
4622
|
includeInternal,
|
|
4623
4623
|
fullDepth: options.fullDepth
|
|
4624
4624
|
});
|
|
4625
4625
|
}
|
|
4626
4626
|
if (skills.length === 0) {
|
|
4627
|
-
spinner$2.stop(import_picocolors.default.red("
|
|
4628
|
-
outro(import_picocolors.default.red("
|
|
4627
|
+
spinner$2.stop(import_picocolors.default.red("未找到技能"));
|
|
4628
|
+
outro(import_picocolors.default.red("未找到有效技能。技能需要包含 name 和 description 的 SKILL.md 文件。"));
|
|
4629
4629
|
await cleanup(tempDir);
|
|
4630
4630
|
process.exit(1);
|
|
4631
4631
|
}
|
|
4632
4632
|
if (!blobResult) spinner$2.stop(`Found ${import_picocolors.default.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
|
|
4633
4633
|
if (options.list) {
|
|
4634
4634
|
console.log();
|
|
4635
|
-
log.step(import_picocolors.default.bold("
|
|
4635
|
+
log.step(import_picocolors.default.bold("可用技能"));
|
|
4636
4636
|
const groupedSkills = {};
|
|
4637
4637
|
const ungroupedSkills = [];
|
|
4638
4638
|
for (const skill of skills) if (skill.pluginName) {
|
|
@@ -4658,7 +4658,7 @@ async function runAdd(args, options = {}) {
|
|
|
4658
4658
|
}
|
|
4659
4659
|
}
|
|
4660
4660
|
console.log();
|
|
4661
|
-
outro("
|
|
4661
|
+
outro("使用 --skill <name> 安装指定技能");
|
|
4662
4662
|
await cleanup(tempDir);
|
|
4663
4663
|
process.exit(0);
|
|
4664
4664
|
}
|
|
@@ -4669,8 +4669,8 @@ async function runAdd(args, options = {}) {
|
|
|
4669
4669
|
} else if (options.skill && options.skill.length > 0) {
|
|
4670
4670
|
selectedSkills = filterSkills(skills, options.skill);
|
|
4671
4671
|
if (selectedSkills.length === 0) {
|
|
4672
|
-
log.error(
|
|
4673
|
-
log.info("
|
|
4672
|
+
log.error(`未找到匹配技能:${options.skill.join(", ")}`);
|
|
4673
|
+
log.info("可用技能:");
|
|
4674
4674
|
for (const s of skills) log.message(` - ${getSkillDisplayName(s)}`);
|
|
4675
4675
|
await cleanup(tempDir);
|
|
4676
4676
|
process.exit(1);
|
|
@@ -4706,12 +4706,12 @@ async function runAdd(args, options = {}) {
|
|
|
4706
4706
|
});
|
|
4707
4707
|
}
|
|
4708
4708
|
selected = await groupMultiselect({
|
|
4709
|
-
message: `Select skills to install ${import_picocolors.default.dim("(
|
|
4709
|
+
message: `Select skills to install ${import_picocolors.default.dim("(空格切换)")}`,
|
|
4710
4710
|
options: grouped,
|
|
4711
4711
|
required: true
|
|
4712
4712
|
});
|
|
4713
4713
|
} else selected = await multiselect({
|
|
4714
|
-
message: "
|
|
4714
|
+
message: "选择要安装的技能",
|
|
4715
4715
|
options: sortedSkills.map((s) => ({
|
|
4716
4716
|
value: s,
|
|
4717
4717
|
label: getSkillDisplayName(s),
|
|
@@ -4720,7 +4720,7 @@ async function runAdd(args, options = {}) {
|
|
|
4720
4720
|
required: true
|
|
4721
4721
|
});
|
|
4722
4722
|
if (isCancel(selected)) {
|
|
4723
|
-
cancel("
|
|
4723
|
+
cancel("安装已取消");
|
|
4724
4724
|
await cleanup(tempDir);
|
|
4725
4725
|
process.exit(0);
|
|
4726
4726
|
}
|
|
@@ -4736,14 +4736,14 @@ async function runAdd(args, options = {}) {
|
|
|
4736
4736
|
} else if (options.agent && options.agent.length > 0) {
|
|
4737
4737
|
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
4738
4738
|
if (invalidAgents.length > 0) {
|
|
4739
|
-
log.error(
|
|
4740
|
-
log.info(
|
|
4739
|
+
log.error(`无效 Agent:${invalidAgents.join(", ")}`);
|
|
4740
|
+
log.info(`可用 Agent:${validAgents.join(", ")}`);
|
|
4741
4741
|
await cleanup(tempDir);
|
|
4742
4742
|
process.exit(1);
|
|
4743
4743
|
}
|
|
4744
4744
|
targetAgents = options.agent;
|
|
4745
4745
|
} else {
|
|
4746
|
-
spinner$2.start("
|
|
4746
|
+
spinner$2.start("正在加载 Agent...");
|
|
4747
4747
|
const installedAgents = await detectInstalledAgents();
|
|
4748
4748
|
const totalAgents = Object.keys(agents).length;
|
|
4749
4749
|
spinner$2.stop(`${totalAgents} agents`);
|
|
@@ -4753,17 +4753,17 @@ async function runAdd(args, options = {}) {
|
|
|
4753
4753
|
initialValue: true
|
|
4754
4754
|
});
|
|
4755
4755
|
if (isCancel(useEve)) {
|
|
4756
|
-
cancel("
|
|
4756
|
+
cancel("安装已取消");
|
|
4757
4757
|
await cleanup(tempDir);
|
|
4758
4758
|
process.exit(0);
|
|
4759
4759
|
}
|
|
4760
4760
|
if (useEve) {
|
|
4761
4761
|
targetAgents = ["eve"];
|
|
4762
|
-
log.info(
|
|
4762
|
+
log.info(`安装到:${import_picocolors.default.cyan(EVE_AGENT_LABEL)}`);
|
|
4763
4763
|
} else {
|
|
4764
4764
|
const selected = await selectAgentsInteractive({ global: options.global });
|
|
4765
4765
|
if (isCancel(selected)) {
|
|
4766
|
-
cancel("
|
|
4766
|
+
cancel("安装已取消");
|
|
4767
4767
|
await cleanup(tempDir);
|
|
4768
4768
|
process.exit(0);
|
|
4769
4769
|
}
|
|
@@ -4771,15 +4771,15 @@ async function runAdd(args, options = {}) {
|
|
|
4771
4771
|
}
|
|
4772
4772
|
} else if (installedAgents.length === 0) if (options.yes) {
|
|
4773
4773
|
targetAgents = validAgents;
|
|
4774
|
-
log.info("
|
|
4774
|
+
log.info("正在安装到全部 Agent");
|
|
4775
4775
|
} else {
|
|
4776
|
-
log.info("
|
|
4777
|
-
const selected = await promptForAgents("
|
|
4776
|
+
log.info("请选择要安装技能的 Agent");
|
|
4777
|
+
const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).filter(([key]) => key !== "eve").map(([key, config]) => ({
|
|
4778
4778
|
value: key,
|
|
4779
4779
|
label: config.displayName
|
|
4780
4780
|
})));
|
|
4781
4781
|
if (isCancel(selected)) {
|
|
4782
|
-
cancel("
|
|
4782
|
+
cancel("安装已取消");
|
|
4783
4783
|
await cleanup(tempDir);
|
|
4784
4784
|
process.exit(0);
|
|
4785
4785
|
}
|
|
@@ -4794,7 +4794,7 @@ async function runAdd(args, options = {}) {
|
|
|
4794
4794
|
} else {
|
|
4795
4795
|
const selected = await selectAgentsInteractive({ global: options.global });
|
|
4796
4796
|
if (isCancel(selected)) {
|
|
4797
|
-
cancel("
|
|
4797
|
+
cancel("安装已取消");
|
|
4798
4798
|
await cleanup(tempDir);
|
|
4799
4799
|
process.exit(0);
|
|
4800
4800
|
}
|
|
@@ -4808,10 +4808,10 @@ async function runAdd(args, options = {}) {
|
|
|
4808
4808
|
if (options.subagent && options.subagent.length > 0) eveSubagentTargets = options.subagent.map((s) => s === "root" || s === "." ? void 0 : s);
|
|
4809
4809
|
else if (availableSubagents.length > 0 && !options.yes) {
|
|
4810
4810
|
const selectedSubagents = await multiselect$1({
|
|
4811
|
-
message: "
|
|
4811
|
+
message: "Eve 技能安装位置?",
|
|
4812
4812
|
options: [{
|
|
4813
4813
|
value: "",
|
|
4814
|
-
label: "
|
|
4814
|
+
label: "根 Agent",
|
|
4815
4815
|
hint: "agent/skills"
|
|
4816
4816
|
}, ...availableSubagents.map((name) => ({
|
|
4817
4817
|
value: name,
|
|
@@ -4822,7 +4822,7 @@ async function runAdd(args, options = {}) {
|
|
|
4822
4822
|
required: true
|
|
4823
4823
|
});
|
|
4824
4824
|
if (isCancel(selectedSubagents)) {
|
|
4825
|
-
cancel("
|
|
4825
|
+
cancel("安装已取消");
|
|
4826
4826
|
await cleanup(tempDir);
|
|
4827
4827
|
process.exit(0);
|
|
4828
4828
|
}
|
|
@@ -4834,19 +4834,19 @@ async function runAdd(args, options = {}) {
|
|
|
4834
4834
|
const supportsGlobal = targetAgents.some((a) => agents[a].globalSkillsDir !== void 0);
|
|
4835
4835
|
if (options.global === void 0 && !options.yes && supportsGlobal) {
|
|
4836
4836
|
const scope = await select({
|
|
4837
|
-
message: "
|
|
4837
|
+
message: "安装范围",
|
|
4838
4838
|
options: [{
|
|
4839
4839
|
value: false,
|
|
4840
4840
|
label: "Project",
|
|
4841
|
-
hint: "
|
|
4841
|
+
hint: "安装到当前目录(随项目一起提交)"
|
|
4842
4842
|
}, {
|
|
4843
4843
|
value: true,
|
|
4844
4844
|
label: "Global",
|
|
4845
|
-
hint: "
|
|
4845
|
+
hint: "安装到主目录(跨所有项目可用)"
|
|
4846
4846
|
}]
|
|
4847
4847
|
});
|
|
4848
4848
|
if (isCancel(scope)) {
|
|
4849
|
-
cancel("
|
|
4849
|
+
cancel("安装已取消");
|
|
4850
4850
|
await cleanup(tempDir);
|
|
4851
4851
|
process.exit(0);
|
|
4852
4852
|
}
|
|
@@ -4857,19 +4857,19 @@ async function runAdd(args, options = {}) {
|
|
|
4857
4857
|
const uniqueDirs = new Set(installTargets.map((t) => t.subagent ? `eve:subagent:${t.subagent}` : agents[t.agent].skillsDir));
|
|
4858
4858
|
if (!options.copy && !options.yes && uniqueDirs.size > 1 && !allEve) {
|
|
4859
4859
|
const modeChoice = await select({
|
|
4860
|
-
message: "
|
|
4860
|
+
message: "安装方式",
|
|
4861
4861
|
options: [{
|
|
4862
4862
|
value: "symlink",
|
|
4863
|
-
label: "
|
|
4864
|
-
hint: "
|
|
4863
|
+
label: "符号链接(推荐)",
|
|
4864
|
+
hint: "单一来源,易于更新"
|
|
4865
4865
|
}, {
|
|
4866
4866
|
value: "copy",
|
|
4867
|
-
label: "
|
|
4868
|
-
hint: "
|
|
4867
|
+
label: "复制到所有 Agent",
|
|
4868
|
+
hint: "每个 Agent 独立副本"
|
|
4869
4869
|
}]
|
|
4870
4870
|
});
|
|
4871
4871
|
if (isCancel(modeChoice)) {
|
|
4872
|
-
cancel("
|
|
4872
|
+
cancel("安装已取消");
|
|
4873
4873
|
await cleanup(tempDir);
|
|
4874
4874
|
process.exit(0);
|
|
4875
4875
|
}
|
|
@@ -4927,7 +4927,7 @@ async function runAdd(args, options = {}) {
|
|
|
4927
4927
|
printSkillSummary(ungroupedSummary);
|
|
4928
4928
|
}
|
|
4929
4929
|
console.log();
|
|
4930
|
-
note(summaryLines.join("\n"), "
|
|
4930
|
+
note(summaryLines.join("\n"), "安装摘要");
|
|
4931
4931
|
try {
|
|
4932
4932
|
const auditData = await auditPromise;
|
|
4933
4933
|
if (auditData && ownerRepoForAudit) {
|
|
@@ -4935,18 +4935,18 @@ async function runAdd(args, options = {}) {
|
|
|
4935
4935
|
slug: getSkillDisplayName(s),
|
|
4936
4936
|
displayName: getSkillDisplayName(s)
|
|
4937
4937
|
})), ownerRepoForAudit);
|
|
4938
|
-
if (securityLines.length > 0) note(securityLines.join("\n"), "
|
|
4938
|
+
if (securityLines.length > 0) note(securityLines.join("\n"), "安全风险评估");
|
|
4939
4939
|
}
|
|
4940
4940
|
} catch {}
|
|
4941
4941
|
if (!options.yes) {
|
|
4942
|
-
const confirmed = await confirm({ message: "
|
|
4942
|
+
const confirmed = await confirm({ message: "确认安装?" });
|
|
4943
4943
|
if (isCancel(confirmed) || !confirmed) {
|
|
4944
|
-
cancel("
|
|
4944
|
+
cancel("安装已取消");
|
|
4945
4945
|
await cleanup(tempDir);
|
|
4946
4946
|
process.exit(0);
|
|
4947
4947
|
}
|
|
4948
4948
|
}
|
|
4949
|
-
spinner$2.start("
|
|
4949
|
+
spinner$2.start("正在安装技能...");
|
|
4950
4950
|
const results = [];
|
|
4951
4951
|
for (const skill of selectedSkills) for (const target of installTargets) {
|
|
4952
4952
|
const { agent, subagent } = target;
|
|
@@ -4983,7 +4983,7 @@ async function runAdd(args, options = {}) {
|
|
|
4983
4983
|
...result
|
|
4984
4984
|
});
|
|
4985
4985
|
}
|
|
4986
|
-
spinner$2.stop("
|
|
4986
|
+
spinner$2.stop("安装完成");
|
|
4987
4987
|
console.log();
|
|
4988
4988
|
const successful = results.filter((r) => r.success);
|
|
4989
4989
|
const failed = results.filter((r) => !r.success);
|
|
@@ -5073,7 +5073,7 @@ async function runAdd(args, options = {}) {
|
|
|
5073
5073
|
const skillResults = bySkill.get(entry.skill) || [];
|
|
5074
5074
|
const firstResult = skillResults[0];
|
|
5075
5075
|
if (firstResult.mode === "copy") {
|
|
5076
|
-
resultLines.push(`${import_picocolors.default.green("✓")} ${entry.skill} ${import_picocolors.default.dim("(
|
|
5076
|
+
resultLines.push(`${import_picocolors.default.green("✓")} ${entry.skill} ${import_picocolors.default.dim("(已复制)")}`);
|
|
5077
5077
|
for (const r of skillResults) {
|
|
5078
5078
|
const shortPath = shortenPath$1(r.path, cwd);
|
|
5079
5079
|
resultLines.push(` ${import_picocolors.default.dim("→")} ${shortPath}`);
|
|
@@ -5104,13 +5104,13 @@ async function runAdd(args, options = {}) {
|
|
|
5104
5104
|
const title = import_picocolors.default.green(`Installed ${skillCount} skill${skillCount !== 1 ? "s" : ""}`);
|
|
5105
5105
|
note(resultLines.join("\n"), title);
|
|
5106
5106
|
if (symlinkFailures.length > 0) {
|
|
5107
|
-
log.warn(import_picocolors.default.yellow(
|
|
5108
|
-
log.message(import_picocolors.default.dim("
|
|
5107
|
+
log.warn(import_picocolors.default.yellow(`符号链接失败: ${formatList$1(copiedAgents)}`));
|
|
5108
|
+
log.message(import_picocolors.default.dim(" 已改为复制文件。在 Windows 上,请启用开发者模式以支持符号链接。"));
|
|
5109
5109
|
}
|
|
5110
5110
|
}
|
|
5111
5111
|
if (failed.length > 0) {
|
|
5112
5112
|
console.log();
|
|
5113
|
-
log.error(import_picocolors.default.red(
|
|
5113
|
+
log.error(import_picocolors.default.red(`安装失败 ${failed.length} 个`));
|
|
5114
5114
|
for (const r of failed) log.message(` ${import_picocolors.default.red("✗")} ${r.skill} → ${r.agent}: ${import_picocolors.default.dim(r.error)}`);
|
|
5115
5115
|
}
|
|
5116
5116
|
console.log();
|
|
@@ -5118,11 +5118,11 @@ async function runAdd(args, options = {}) {
|
|
|
5118
5118
|
await promptForFindSkills(options, targetAgents);
|
|
5119
5119
|
} catch (error) {
|
|
5120
5120
|
if (error instanceof GitCloneError) {
|
|
5121
|
-
log.error(import_picocolors.default.red("
|
|
5121
|
+
log.error(import_picocolors.default.red("克隆仓库失败"));
|
|
5122
5122
|
for (const line of error.message.split("\n")) log.message(import_picocolors.default.dim(line));
|
|
5123
5123
|
} else log.error(error instanceof Error ? error.message : "Unknown error occurred");
|
|
5124
5124
|
showInstallTip();
|
|
5125
|
-
outro(import_picocolors.default.red("
|
|
5125
|
+
outro(import_picocolors.default.red("安装失败"));
|
|
5126
5126
|
process.exit(1);
|
|
5127
5127
|
} finally {
|
|
5128
5128
|
await cleanup(tempDir);
|
|
@@ -5143,7 +5143,7 @@ async function promptForFindSkills(options, targetAgents) {
|
|
|
5143
5143
|
return;
|
|
5144
5144
|
}
|
|
5145
5145
|
console.log();
|
|
5146
|
-
log.message(import_picocolors.default.dim("
|
|
5146
|
+
log.message(import_picocolors.default.dim("一次性提示 - 关闭后将不再询问。"));
|
|
5147
5147
|
const install = await confirm({ message: `Install the ${import_picocolors.default.cyan("find-skills")} skill? It helps your agent discover and suggest skills.` });
|
|
5148
5148
|
if (isCancel(install)) {
|
|
5149
5149
|
await dismissPrompt("findSkillsPrompt");
|
|
@@ -5154,7 +5154,7 @@ async function promptForFindSkills(options, targetAgents) {
|
|
|
5154
5154
|
const findSkillsAgents = targetAgents?.filter((a) => a !== "replit");
|
|
5155
5155
|
if (!findSkillsAgents || findSkillsAgents.length === 0) return;
|
|
5156
5156
|
console.log();
|
|
5157
|
-
log.step("
|
|
5157
|
+
log.step("正在安装 find-skills 技能...");
|
|
5158
5158
|
try {
|
|
5159
5159
|
await runAdd(["vercel-labs/skills"], {
|
|
5160
5160
|
skill: ["find-skills"],
|
|
@@ -5163,12 +5163,12 @@ async function promptForFindSkills(options, targetAgents) {
|
|
|
5163
5163
|
agent: findSkillsAgents
|
|
5164
5164
|
});
|
|
5165
5165
|
} catch {
|
|
5166
|
-
log.warn("
|
|
5166
|
+
log.warn("安装 find-skills 失败。你可以稍后重试:");
|
|
5167
5167
|
log.message(import_picocolors.default.dim(" npx skills add vercel-labs/skills@find-skills -g -y --all"));
|
|
5168
5168
|
}
|
|
5169
5169
|
} else {
|
|
5170
5170
|
await dismissPrompt("findSkillsPrompt");
|
|
5171
|
-
log.message(import_picocolors.default.dim("
|
|
5171
|
+
log.message(import_picocolors.default.dim("你可以稍后通过以下命令安装:npx skills add vercel-labs/skills@find-skills"));
|
|
5172
5172
|
}
|
|
5173
5173
|
} catch {}
|
|
5174
5174
|
}
|
|
@@ -5204,12 +5204,12 @@ function parseAddOptions(args) {
|
|
|
5204
5204
|
i--;
|
|
5205
5205
|
} else if (arg === "--metadata") {
|
|
5206
5206
|
const metadata = args[++i];
|
|
5207
|
-
if (metadata === void 0) errors.push("--metadata
|
|
5207
|
+
if (metadata === void 0) errors.push("--metadata 需要 JSON 值");
|
|
5208
5208
|
else try {
|
|
5209
5209
|
JSON.parse(metadata);
|
|
5210
5210
|
options.metadata = metadata;
|
|
5211
5211
|
} catch {
|
|
5212
|
-
errors.push("--metadata
|
|
5212
|
+
errors.push("--metadata 必须是有效的 JSON");
|
|
5213
5213
|
}
|
|
5214
5214
|
} else if (arg === "--full-depth") options.fullDepth = true;
|
|
5215
5215
|
else if (arg === "--copy") options.copy = true;
|
|
@@ -5241,7 +5241,7 @@ function formatInstalls$1(count) {
|
|
|
5241
5241
|
if (!count || count <= 0) return "";
|
|
5242
5242
|
if (count >= 1e6) return `${(count / 1e6).toFixed(1).replace(/\.0$/, "")}M installs`;
|
|
5243
5243
|
if (count >= 1e3) return `${(count / 1e3).toFixed(1).replace(/\.0$/, "")}K installs`;
|
|
5244
|
-
return `${count}
|
|
5244
|
+
return `${count} 次安装`;
|
|
5245
5245
|
}
|
|
5246
5246
|
const GITHUB_OWNER_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,38})$/i;
|
|
5247
5247
|
function parseFindOptions(args) {
|
|
@@ -5324,11 +5324,11 @@ async function runSearchPrompt(initialQuery = "", owner) {
|
|
|
5324
5324
|
process.stdout.write(CLEAR_DOWN);
|
|
5325
5325
|
const lines = [];
|
|
5326
5326
|
const cursor = `${BOLD$8}_${RESET$11}`;
|
|
5327
|
-
lines.push(`${TEXT$9}
|
|
5327
|
+
lines.push(`${TEXT$9}搜索技能:${RESET$11} ${query}${cursor}`);
|
|
5328
5328
|
lines.push("");
|
|
5329
|
-
if (!query || query.length < 2) lines.push(`${DIM$11}
|
|
5330
|
-
else if (results.length === 0 && loading) lines.push(`${DIM$11}
|
|
5331
|
-
else if (results.length === 0) lines.push(`${DIM$11}
|
|
5329
|
+
if (!query || query.length < 2) lines.push(`${DIM$11}输入关键词搜索(最少 2 个字符)${RESET$11}`);
|
|
5330
|
+
else if (results.length === 0 && loading) lines.push(`${DIM$11}搜索中...${RESET$11}`);
|
|
5331
|
+
else if (results.length === 0) lines.push(`${DIM$11}未找到技能${RESET$11}`);
|
|
5332
5332
|
else {
|
|
5333
5333
|
const visible = results.slice(0, 8);
|
|
5334
5334
|
for (let i = 0; i < visible.length; i++) {
|
|
@@ -5344,7 +5344,7 @@ async function runSearchPrompt(initialQuery = "", owner) {
|
|
|
5344
5344
|
}
|
|
5345
5345
|
}
|
|
5346
5346
|
lines.push("");
|
|
5347
|
-
lines.push(`${DIM$11}
|
|
5347
|
+
lines.push(`${DIM$11}上下键导航 | 回车选择 | ESC 取消${RESET$11}`);
|
|
5348
5348
|
for (const line of lines) process.stdout.write(line + "\n");
|
|
5349
5349
|
lastRenderedLines = lines.length;
|
|
5350
5350
|
}
|
|
@@ -5454,10 +5454,10 @@ ${DIM$11} 2) npx skills add <owner/repo@skill>${RESET$11}`;
|
|
|
5454
5454
|
String(results.length);
|
|
5455
5455
|
if (results.length === 0) {
|
|
5456
5456
|
const ownerSuffix = owner ? ` from owner "${owner}"` : "";
|
|
5457
|
-
console.log(`${DIM$11}
|
|
5457
|
+
console.log(`${DIM$11}未找到 "${query}" 的技能${ownerSuffix}${RESET$11}`);
|
|
5458
5458
|
return;
|
|
5459
5459
|
}
|
|
5460
|
-
console.log(`${DIM$11}
|
|
5460
|
+
console.log(`${DIM$11}安装:${RESET$11} npx skills add <owner/repo@skill>`);
|
|
5461
5461
|
console.log();
|
|
5462
5462
|
for (const skill of results.slice(0, 6)) {
|
|
5463
5463
|
const pkg = skill.source || skill.slug;
|
|
@@ -5476,14 +5476,14 @@ ${DIM$11} 2) npx skills add <owner/repo@skill>${RESET$11}`;
|
|
|
5476
5476
|
}
|
|
5477
5477
|
const selected = await runSearchPrompt("", owner);
|
|
5478
5478
|
if (!selected) {
|
|
5479
|
-
console.log(`${DIM$11}
|
|
5479
|
+
console.log(`${DIM$11}搜索已取消${RESET$11}`);
|
|
5480
5480
|
console.log();
|
|
5481
5481
|
return;
|
|
5482
5482
|
}
|
|
5483
5483
|
const pkg = selected.source || selected.slug;
|
|
5484
5484
|
const skillName = selected.name;
|
|
5485
5485
|
console.log();
|
|
5486
|
-
console.log(`${TEXT$9}
|
|
5486
|
+
console.log(`${TEXT$9}正在从 ${DIM$11}${pkg}${RESET$11} 安装 ${BOLD$8}${skillName}${RESET$11}...`);
|
|
5487
5487
|
console.log();
|
|
5488
5488
|
const { source, options: addOptions } = parseAddOptions([
|
|
5489
5489
|
pkg,
|
|
@@ -5493,8 +5493,8 @@ ${DIM$11} 2) npx skills add <owner/repo@skill>${RESET$11}`;
|
|
|
5493
5493
|
await runAdd(source, addOptions);
|
|
5494
5494
|
console.log();
|
|
5495
5495
|
const info = getOwnerRepoFromString(pkg);
|
|
5496
|
-
if (info && await isRepoPublic(info.owner, info.repo)) console.log(`${DIM$11}
|
|
5497
|
-
else console.log(`${DIM$11}
|
|
5496
|
+
if (info && await isRepoPublic(info.owner, info.repo)) console.log(`${DIM$11}查看技能:${RESET$11} ${TEXT$9}https://skills.sh/${selected.slug}${RESET$11}`);
|
|
5497
|
+
else console.log(`${DIM$11}发现更多技能:${RESET$11} ${TEXT$9}https://skills.sh${RESET$11}`);
|
|
5498
5498
|
console.log();
|
|
5499
5499
|
}
|
|
5500
5500
|
const RESET$10 = "\x1B[0m";
|
|
@@ -5557,15 +5557,15 @@ async function runList(args) {
|
|
|
5557
5557
|
}
|
|
5558
5558
|
const lockedSkills = await getAllLockedSkills();
|
|
5559
5559
|
const cwd = process.cwd();
|
|
5560
|
-
const scopeLabel = scope ? "
|
|
5560
|
+
const scopeLabel = scope ? "全局" : "项目";
|
|
5561
5561
|
if (installedSkills.length === 0) {
|
|
5562
5562
|
if (options.json) {
|
|
5563
5563
|
console.log("[]");
|
|
5564
5564
|
return;
|
|
5565
5565
|
}
|
|
5566
|
-
console.log(`${DIM$10}
|
|
5567
|
-
if (scope) console.log(`${DIM$10}
|
|
5568
|
-
else console.log(`${DIM$10}
|
|
5566
|
+
console.log(`${DIM$10}未找到${scopeLabel}技能。${RESET$10}`);
|
|
5567
|
+
if (scope) console.log(`${DIM$10}尝试不带 -g 参数列出项目技能${RESET$10}`);
|
|
5568
|
+
else console.log(`${DIM$10}尝试带 -g 参数列出全局技能${RESET$10}`);
|
|
5569
5569
|
return;
|
|
5570
5570
|
}
|
|
5571
5571
|
function printSkill(skill, indent = false, maxNameLength = 0, maxPathLength = 0) {
|
|
@@ -5577,7 +5577,7 @@ async function runList(args) {
|
|
|
5577
5577
|
const paddedPath = shortPath.padEnd(maxPathLength);
|
|
5578
5578
|
console.log(`${prefix}${CYAN$1}${paddedName}${RESET$10} ${DIM$10}${paddedPath}${RESET$10} ${DIM$10}Agents:${RESET$10} ${agentInfo}`);
|
|
5579
5579
|
}
|
|
5580
|
-
console.log(`${BOLD$7}${scopeLabel}
|
|
5580
|
+
console.log(`${BOLD$7}${scopeLabel}技能${RESET$10}`);
|
|
5581
5581
|
console.log();
|
|
5582
5582
|
const groupedSkills = {};
|
|
5583
5583
|
const ungroupedSkills = [];
|
|
@@ -5609,7 +5609,7 @@ async function runList(args) {
|
|
|
5609
5609
|
console.log();
|
|
5610
5610
|
}
|
|
5611
5611
|
if (ungroupedSkills.length > 0) {
|
|
5612
|
-
console.log(`${BOLD$7}
|
|
5612
|
+
console.log(`${BOLD$7}通用${RESET$10}`);
|
|
5613
5613
|
let maxNameLength = 0;
|
|
5614
5614
|
let maxPathLength = 0;
|
|
5615
5615
|
for (const skill of ungroupedSkills) {
|
|
@@ -5638,12 +5638,12 @@ async function removeCommand(skillNames, options) {
|
|
|
5638
5638
|
const agentResult = await detectAgent();
|
|
5639
5639
|
if (agentResult.isAgent) {
|
|
5640
5640
|
options.yes = true;
|
|
5641
|
-
log.info(import_picocolors.default.bgCyan(import_picocolors.default.black(import_picocolors.default.bold(` ${agentResult.agent.name} `))) + " Agent
|
|
5641
|
+
log.info(import_picocolors.default.bgCyan(import_picocolors.default.black(import_picocolors.default.bold(` ${agentResult.agent.name} `))) + " 已检测到 Agent — 以非交互模式卸载");
|
|
5642
5642
|
}
|
|
5643
5643
|
const isGlobal = options.global ?? false;
|
|
5644
5644
|
const cwd = process.cwd();
|
|
5645
5645
|
const spinner$1 = spinner();
|
|
5646
|
-
spinner$1.start("
|
|
5646
|
+
spinner$1.start("正在扫描已安装的技能...");
|
|
5647
5647
|
const skillNamesSet = /* @__PURE__ */ new Set();
|
|
5648
5648
|
const scanDir = async (dir) => {
|
|
5649
5649
|
try {
|
|
@@ -5662,17 +5662,17 @@ async function removeCommand(skillNames, options) {
|
|
|
5662
5662
|
for (const subagent of getEveSubagents(cwd)) await scanDir(getEveSubagentSkillsDir(subagent, cwd));
|
|
5663
5663
|
}
|
|
5664
5664
|
const installedSkills = Array.from(skillNamesSet).sort();
|
|
5665
|
-
spinner$1.stop(
|
|
5665
|
+
spinner$1.stop(`发现 ${installedSkills.length} 个已安装技能`);
|
|
5666
5666
|
if (installedSkills.length === 0) {
|
|
5667
|
-
outro(import_picocolors.default.yellow("
|
|
5667
|
+
outro(import_picocolors.default.yellow("没有可卸载的技能。"));
|
|
5668
5668
|
return;
|
|
5669
5669
|
}
|
|
5670
5670
|
if (options.agent && options.agent.length > 0) {
|
|
5671
5671
|
const validAgents = Object.keys(agents);
|
|
5672
5672
|
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
5673
5673
|
if (invalidAgents.length > 0) {
|
|
5674
|
-
log.error(
|
|
5675
|
-
log.info(
|
|
5674
|
+
log.error(`无效 Agent:${invalidAgents.join(", ")}`);
|
|
5675
|
+
log.info(`可用 Agent:${validAgents.join(", ")}`);
|
|
5676
5676
|
process.exit(1);
|
|
5677
5677
|
}
|
|
5678
5678
|
}
|
|
@@ -5681,7 +5681,7 @@ async function removeCommand(skillNames, options) {
|
|
|
5681
5681
|
else if (skillNames.length > 0) {
|
|
5682
5682
|
selectedSkills = installedSkills.filter((s) => skillNames.some((name) => name.toLowerCase() === s.toLowerCase()));
|
|
5683
5683
|
if (selectedSkills.length === 0) {
|
|
5684
|
-
log.error(
|
|
5684
|
+
log.error(`未找到匹配技能:${skillNames.join(", ")}`);
|
|
5685
5685
|
return;
|
|
5686
5686
|
}
|
|
5687
5687
|
} else {
|
|
@@ -5695,7 +5695,7 @@ async function removeCommand(skillNames, options) {
|
|
|
5695
5695
|
required: true
|
|
5696
5696
|
});
|
|
5697
5697
|
if (isCancel(selected)) {
|
|
5698
|
-
cancel("
|
|
5698
|
+
cancel("卸载已取消");
|
|
5699
5699
|
process.exit(0);
|
|
5700
5700
|
}
|
|
5701
5701
|
selectedSkills = selected;
|
|
@@ -5708,16 +5708,16 @@ async function removeCommand(skillNames, options) {
|
|
|
5708
5708
|
}
|
|
5709
5709
|
if (!options.yes) {
|
|
5710
5710
|
console.log();
|
|
5711
|
-
log.info("
|
|
5711
|
+
log.info("要卸载的技能:");
|
|
5712
5712
|
for (const skill of selectedSkills) log.message(` ${import_picocolors.default.red("•")} ${skill}`);
|
|
5713
5713
|
console.log();
|
|
5714
|
-
const confirmed = await confirm({ message:
|
|
5714
|
+
const confirmed = await confirm({ message: `确认要卸载 ${selectedSkills.length} 个技能?` });
|
|
5715
5715
|
if (isCancel(confirmed) || !confirmed) {
|
|
5716
|
-
cancel("
|
|
5716
|
+
cancel("卸载已取消");
|
|
5717
5717
|
process.exit(0);
|
|
5718
5718
|
}
|
|
5719
5719
|
}
|
|
5720
|
-
spinner$1.start("
|
|
5720
|
+
spinner$1.start("正在卸载技能...");
|
|
5721
5721
|
const results = [];
|
|
5722
5722
|
for (const skillName of selectedSkills) try {
|
|
5723
5723
|
const canonicalPath = getCanonicalPath(skillName, {
|
|
@@ -5779,7 +5779,7 @@ async function removeCommand(skillNames, options) {
|
|
|
5779
5779
|
error: err instanceof Error ? err.message : String(err)
|
|
5780
5780
|
});
|
|
5781
5781
|
}
|
|
5782
|
-
spinner$1.stop("
|
|
5782
|
+
spinner$1.stop("卸载完成");
|
|
5783
5783
|
const successful = results.filter((r) => r.success);
|
|
5784
5784
|
const failed = results.filter((r) => !r.success);
|
|
5785
5785
|
if (successful.length > 0) {
|
|
@@ -5793,13 +5793,13 @@ async function removeCommand(skillNames, options) {
|
|
|
5793
5793
|
}
|
|
5794
5794
|
for (const [source, data] of bySource) data.skills.join(","), targetAgents.join(","), { ...isGlobal && { global: "1" } }, data.sourceType;
|
|
5795
5795
|
}
|
|
5796
|
-
if (successful.length > 0) log.success(import_picocolors.default.green(
|
|
5796
|
+
if (successful.length > 0) log.success(import_picocolors.default.green(`已成功卸载 ${successful.length} 个技能`));
|
|
5797
5797
|
if (failed.length > 0) {
|
|
5798
|
-
log.error(import_picocolors.default.red(
|
|
5798
|
+
log.error(import_picocolors.default.red(`卸载失败 ${failed.length} 个`));
|
|
5799
5799
|
for (const r of failed) log.message(` ${import_picocolors.default.red("✗")} ${r.skill}: ${r.error}`);
|
|
5800
5800
|
}
|
|
5801
5801
|
console.log();
|
|
5802
|
-
outro(import_picocolors.default.green("
|
|
5802
|
+
outro(import_picocolors.default.green("完成!"));
|
|
5803
5803
|
}
|
|
5804
5804
|
function parseRemoveOptions(args) {
|
|
5805
5805
|
const options = {};
|
|
@@ -5916,27 +5916,27 @@ async function resolveUpdateScope(options) {
|
|
|
5916
5916
|
if (options.project) return "project";
|
|
5917
5917
|
if (options.yes || !process.stdin.isTTY) return hasProjectSkills() ? "project" : "global";
|
|
5918
5918
|
const scope = await select({
|
|
5919
|
-
message: "
|
|
5919
|
+
message: "更新范围",
|
|
5920
5920
|
options: [
|
|
5921
5921
|
{
|
|
5922
5922
|
value: "project",
|
|
5923
|
-
label: "
|
|
5924
|
-
hint: "
|
|
5923
|
+
label: "项目",
|
|
5924
|
+
hint: "更新当前目录中的技能"
|
|
5925
5925
|
},
|
|
5926
5926
|
{
|
|
5927
5927
|
value: "global",
|
|
5928
|
-
label: "
|
|
5929
|
-
hint: "
|
|
5928
|
+
label: "全局",
|
|
5929
|
+
hint: "更新主目录中的技能"
|
|
5930
5930
|
},
|
|
5931
5931
|
{
|
|
5932
5932
|
value: "both",
|
|
5933
|
-
label: "
|
|
5934
|
-
hint: "
|
|
5933
|
+
label: "全部",
|
|
5934
|
+
hint: "更新所有技能"
|
|
5935
5935
|
}
|
|
5936
5936
|
]
|
|
5937
5937
|
});
|
|
5938
5938
|
if (isCancel(scope)) {
|
|
5939
|
-
cancel("
|
|
5939
|
+
cancel("已取消");
|
|
5940
5940
|
process.exit(0);
|
|
5941
5941
|
}
|
|
5942
5942
|
return scope;
|
|
@@ -5947,12 +5947,12 @@ function matchesSkillFilter(name, filter) {
|
|
|
5947
5947
|
return filter.some((f) => f.toLowerCase() === lower);
|
|
5948
5948
|
}
|
|
5949
5949
|
function getSkipReason(entry) {
|
|
5950
|
-
if (entry.sourceType === "local") return "
|
|
5951
|
-
if (entry.sourceType === "git") return "Git
|
|
5952
|
-
if (entry.sourceType === "well-known") return "Well-known
|
|
5953
|
-
if (!entry.skillFolderHash) return "
|
|
5954
|
-
if (!entry.skillPath) return "
|
|
5955
|
-
return "
|
|
5950
|
+
if (entry.sourceType === "local") return "本地路径";
|
|
5951
|
+
if (entry.sourceType === "git") return "Git 地址";
|
|
5952
|
+
if (entry.sourceType === "well-known") return "Well-known 技能";
|
|
5953
|
+
if (!entry.skillFolderHash) return "私有或已删除的仓库";
|
|
5954
|
+
if (!entry.skillPath) return "无路径记录";
|
|
5955
|
+
return "无版本跟踪";
|
|
5956
5956
|
}
|
|
5957
5957
|
function getInstallSource(skill) {
|
|
5958
5958
|
let url = skill.sourceUrl;
|
|
@@ -5965,7 +5965,7 @@ function getInstallSource(skill) {
|
|
|
5965
5965
|
function printSkippedSkills(skipped) {
|
|
5966
5966
|
if (skipped.length === 0) return;
|
|
5967
5967
|
console.log();
|
|
5968
|
-
console.log(`${DIM$9}${skipped.length}
|
|
5968
|
+
console.log(`${DIM$9}${skipped.length} 个技能无法自动检查:${RESET$9}`);
|
|
5969
5969
|
const grouped = /* @__PURE__ */ new Map();
|
|
5970
5970
|
for (const skill of skipped) {
|
|
5971
5971
|
const source = getInstallSource(skill);
|
|
@@ -5982,7 +5982,7 @@ function printSkippedSkills(skipped) {
|
|
|
5982
5982
|
const names = skills.map((s) => sanitizeMetadata(s.name)).join(", ");
|
|
5983
5983
|
console.log(` ${TEXT$8}•${RESET$9} ${names} ${DIM$9}(${reason})${RESET$9}`);
|
|
5984
5984
|
}
|
|
5985
|
-
console.log(` ${DIM$9}
|
|
5985
|
+
console.log(` ${DIM$9}更新方法:${TEXT$8}npx skills add ${source} -g -y${RESET$9}`);
|
|
5986
5986
|
}
|
|
5987
5987
|
}
|
|
5988
5988
|
async function getProjectSkillsForUpdate(skillFilter) {
|
|
@@ -6007,13 +6007,13 @@ async function checkAndPromptForDeletions(source, allLockedForSource, lockSkills
|
|
|
6007
6007
|
});
|
|
6008
6008
|
if (deletedSkills.length > 0) {
|
|
6009
6009
|
console.log();
|
|
6010
|
-
console.log(`${DIM$9}
|
|
6010
|
+
console.log(`${DIM$9}警告:${RESET$9} 以下来自 ${DIM$9}${source}${RESET$9} 的技能似乎已在源仓库中删除:`);
|
|
6011
6011
|
for (const s of deletedSkills) console.log(` ${DIM$9}•${RESET$9} ${s}`);
|
|
6012
|
-
if (options.yes || !process.stdin.isTTY) console.log(`${DIM$9}
|
|
6012
|
+
if (options.yes || !process.stdin.isTTY) console.log(`${DIM$9}非交互模式,跳过删除。${RESET$9}`);
|
|
6013
6013
|
else {
|
|
6014
|
-
const confirmed = await confirm({ message:
|
|
6014
|
+
const confirmed = await confirm({ message: `是否删除这些已删除技能的本地副本?` });
|
|
6015
6015
|
if (confirmed && !isCancel(confirmed)) for (const s of deletedSkills) {
|
|
6016
|
-
console.log(`${DIM$9}
|
|
6016
|
+
console.log(`${DIM$9}正在卸载${RESET$9} ${s}...`);
|
|
6017
6017
|
await removeCommand([s], {
|
|
6018
6018
|
yes: true,
|
|
6019
6019
|
global: isGlobal
|
|
@@ -6030,8 +6030,8 @@ async function updateGlobalSkills(options = {}) {
|
|
|
6030
6030
|
let failCount = 0;
|
|
6031
6031
|
if (skillNames.length === 0) {
|
|
6032
6032
|
if (!options.skills) {
|
|
6033
|
-
console.log(`${DIM$9}
|
|
6034
|
-
console.log(`${DIM$9}
|
|
6033
|
+
console.log(`${DIM$9}锁文件中没有跟踪的全局技能。${RESET$9}`);
|
|
6034
|
+
console.log(`${DIM$9}安装技能:${RESET$9} ${TEXT$8}npx skills add <package> -g${RESET$9}`);
|
|
6035
6035
|
}
|
|
6036
6036
|
return {
|
|
6037
6037
|
successCount,
|
|
@@ -6120,7 +6120,7 @@ async function updateGlobalSkills(options = {}) {
|
|
|
6120
6120
|
if (checkable.length > 0) process.stdout.write("\r\x1B[K");
|
|
6121
6121
|
const checkedCount = checkable.length + skipped.length;
|
|
6122
6122
|
if (checkable.length === 0 && skipped.length === 0) {
|
|
6123
|
-
if (!options.skills) console.log(`${DIM$9}
|
|
6123
|
+
if (!options.skills) console.log(`${DIM$9}没有可检查的全局技能。${RESET$9}`);
|
|
6124
6124
|
return {
|
|
6125
6125
|
successCount,
|
|
6126
6126
|
failCount,
|
|
@@ -6136,18 +6136,18 @@ async function updateGlobalSkills(options = {}) {
|
|
|
6136
6136
|
};
|
|
6137
6137
|
}
|
|
6138
6138
|
if (updates.length === 0) {
|
|
6139
|
-
console.log(`${TEXT$8}✓
|
|
6139
|
+
console.log(`${TEXT$8}✓ 所有全局技能已是最新${RESET$9}`);
|
|
6140
6140
|
return {
|
|
6141
6141
|
successCount,
|
|
6142
6142
|
failCount,
|
|
6143
6143
|
checkedCount
|
|
6144
6144
|
};
|
|
6145
6145
|
}
|
|
6146
|
-
console.log(`${TEXT$8}
|
|
6146
|
+
console.log(`${TEXT$8}发现 ${updates.length} 个可更新全局技能${RESET$9}`);
|
|
6147
6147
|
console.log();
|
|
6148
6148
|
for (const update of updates) {
|
|
6149
6149
|
const safeName = sanitizeMetadata(update.name);
|
|
6150
|
-
console.log(`${TEXT$8}
|
|
6150
|
+
console.log(`${TEXT$8}正在更新 ${safeName}...${RESET$9}`);
|
|
6151
6151
|
const installUrl = buildUpdateInstallSource(update.entry);
|
|
6152
6152
|
if (!installUrl) {
|
|
6153
6153
|
failCount++;
|
|
@@ -6176,10 +6176,10 @@ async function updateGlobalSkills(options = {}) {
|
|
|
6176
6176
|
shell: false
|
|
6177
6177
|
}).status === 0) {
|
|
6178
6178
|
successCount++;
|
|
6179
|
-
console.log(` ${TEXT$8}✓${RESET$9}
|
|
6179
|
+
console.log(` ${TEXT$8}✓${RESET$9} 已更新 ${safeName}`);
|
|
6180
6180
|
} else {
|
|
6181
6181
|
failCount++;
|
|
6182
|
-
console.log(` ${DIM$9}✗
|
|
6182
|
+
console.log(` ${DIM$9}✗ 更新 ${safeName} 失败${RESET$9}`);
|
|
6183
6183
|
}
|
|
6184
6184
|
}
|
|
6185
6185
|
printSkippedSkills(skipped);
|
|
@@ -6195,7 +6195,7 @@ async function updateProjectSkills(options = {}) {
|
|
|
6195
6195
|
let failCount = 0;
|
|
6196
6196
|
if (projectSkills.length === 0) {
|
|
6197
6197
|
if (!options.skills) {
|
|
6198
|
-
console.log(`${DIM$9}
|
|
6198
|
+
console.log(`${DIM$9}没有可更新的项目技能。${RESET$9}`);
|
|
6199
6199
|
console.log(`${DIM$9}Install project skills with${RESET$9} ${TEXT$8}npx skills add <package>${RESET$9}`);
|
|
6200
6200
|
}
|
|
6201
6201
|
return {
|
|
@@ -6227,8 +6227,8 @@ async function updateProjectSkills(options = {}) {
|
|
|
6227
6227
|
const targetParts = [];
|
|
6228
6228
|
if (hasUniversal) targetParts.push("Universal");
|
|
6229
6229
|
targetParts.push(...targetAgentNames);
|
|
6230
|
-
if (targetParts.length > 0) console.log(`${TEXT$8}
|
|
6231
|
-
console.log(`${TEXT$8}
|
|
6230
|
+
if (targetParts.length > 0) console.log(`${TEXT$8}更新目标:${targetParts.join(", ")}${RESET$9}`);
|
|
6231
|
+
console.log(`${TEXT$8}正在刷新 ${updatable.length} 个技能...${RESET$9}`);
|
|
6232
6232
|
console.log();
|
|
6233
6233
|
const bySource = /* @__PURE__ */ new Map();
|
|
6234
6234
|
for (const skill of updatable) {
|
|
@@ -6240,7 +6240,7 @@ async function updateProjectSkills(options = {}) {
|
|
|
6240
6240
|
const localLock = await readLocalLock();
|
|
6241
6241
|
const cliEntry = join(__dirname$1, "..", "bin", "cli.mjs");
|
|
6242
6242
|
if (!existsSync(cliEntry)) {
|
|
6243
|
-
console.log(`${DIM$9}✗ CLI
|
|
6243
|
+
console.log(`${DIM$9}✗ CLI 入口未找到 ${cliEntry}${RESET$9}`);
|
|
6244
6244
|
return {
|
|
6245
6245
|
successCount,
|
|
6246
6246
|
failCount: updatable.length,
|
|
@@ -6266,14 +6266,14 @@ async function updateProjectSkills(options = {}) {
|
|
|
6266
6266
|
});
|
|
6267
6267
|
deletedSkills = await checkAndPromptForDeletions(source, allLockedForSource, localLock.skills, false, options, discoveredPaths);
|
|
6268
6268
|
} catch (error) {
|
|
6269
|
-
console.log(`${DIM$9}✗
|
|
6269
|
+
console.log(`${DIM$9}✗ 检查 ${source} 已删除技能失败${RESET$9}`);
|
|
6270
6270
|
} finally {
|
|
6271
6271
|
if (tempDir) await cleanupTempDir(tempDir);
|
|
6272
6272
|
}
|
|
6273
6273
|
const remainingSkills = skillsForSource.filter((s) => !deletedSkills.includes(s.name));
|
|
6274
6274
|
for (const skill of remainingSkills) {
|
|
6275
6275
|
const safeName = sanitizeMetadata(skill.name);
|
|
6276
|
-
console.log(`${TEXT$8}
|
|
6276
|
+
console.log(`${TEXT$8}正在更新 ${safeName}...${RESET$9}`);
|
|
6277
6277
|
const installUrl = buildLocalUpdateSource(skill.entry);
|
|
6278
6278
|
if (!installUrl) {
|
|
6279
6279
|
failCount++;
|
|
@@ -6299,10 +6299,10 @@ async function updateProjectSkills(options = {}) {
|
|
|
6299
6299
|
shell: false
|
|
6300
6300
|
}).status === 0) {
|
|
6301
6301
|
successCount++;
|
|
6302
|
-
console.log(` ${TEXT$8}✓${RESET$9}
|
|
6302
|
+
console.log(` ${TEXT$8}✓${RESET$9} 已更新 ${safeName}`);
|
|
6303
6303
|
} else {
|
|
6304
6304
|
failCount++;
|
|
6305
|
-
console.log(` ${DIM$9}✗
|
|
6305
|
+
console.log(` ${DIM$9}✗ 更新 ${safeName} 失败${RESET$9}`);
|
|
6306
6306
|
}
|
|
6307
6307
|
}
|
|
6308
6308
|
}
|
|
@@ -6320,21 +6320,21 @@ function printLegacyProjectSkills(legacy) {
|
|
|
6320
6320
|
for (const skill of legacy) {
|
|
6321
6321
|
const reinstall = buildLocalUpdateSource(skill.entry);
|
|
6322
6322
|
console.log(` ${TEXT$8}•${RESET$9} ${sanitizeMetadata(skill.name)}`);
|
|
6323
|
-
if (reinstall) console.log(` ${DIM$9}
|
|
6323
|
+
if (reinstall) console.log(` ${DIM$9}刷新方法:${TEXT$8}npx skills add ${reinstall} -y${RESET$9}`);
|
|
6324
6324
|
else console.log(` ${DIM$9}To refresh: reinstall using the original full Git URL; this lock entry only has an ambiguous shorthand.${RESET$9}`);
|
|
6325
6325
|
}
|
|
6326
6326
|
}
|
|
6327
6327
|
async function runUpdate(args = []) {
|
|
6328
6328
|
const options = parseUpdateOptions(args);
|
|
6329
6329
|
const scope = await resolveUpdateScope(options);
|
|
6330
|
-
if (options.skills) console.log(`${TEXT$8}
|
|
6331
|
-
else console.log(`${TEXT$8}
|
|
6330
|
+
if (options.skills) console.log(`${TEXT$8}正在更新 ${options.skills.join(", ")}...${RESET$9}`);
|
|
6331
|
+
else console.log(`${TEXT$8}正在检查技能更新...${RESET$9}`);
|
|
6332
6332
|
console.log();
|
|
6333
6333
|
let totalSuccess = 0;
|
|
6334
6334
|
let totalFail = 0;
|
|
6335
6335
|
let totalFound = 0;
|
|
6336
6336
|
if (scope === "global" || scope === "both") {
|
|
6337
|
-
if (scope === "both" && !options.skills) console.log(`${BOLD$6}
|
|
6337
|
+
if (scope === "both" && !options.skills) console.log(`${BOLD$6}全局技能${RESET$9}`);
|
|
6338
6338
|
const { successCount, failCount, checkedCount } = await updateGlobalSkills(options);
|
|
6339
6339
|
totalSuccess += successCount;
|
|
6340
6340
|
totalFail += failCount;
|
|
@@ -6342,17 +6342,17 @@ async function runUpdate(args = []) {
|
|
|
6342
6342
|
if (scope === "both" && !options.skills) console.log();
|
|
6343
6343
|
}
|
|
6344
6344
|
if (scope === "project" || scope === "both") {
|
|
6345
|
-
if (scope === "both" && !options.skills) console.log(`${BOLD$6}
|
|
6345
|
+
if (scope === "both" && !options.skills) console.log(`${BOLD$6}项目技能${RESET$9}`);
|
|
6346
6346
|
const { successCount, failCount, foundCount } = await updateProjectSkills(options);
|
|
6347
6347
|
totalSuccess += successCount;
|
|
6348
6348
|
totalFail += failCount;
|
|
6349
6349
|
totalFound += foundCount;
|
|
6350
6350
|
}
|
|
6351
|
-
if (options.skills && totalFound === 0) console.log(`${DIM$9}
|
|
6351
|
+
if (options.skills && totalFound === 0) console.log(`${DIM$9}未找到匹配的已安装技能:${options.skills.join(", ")}${RESET$9}`);
|
|
6352
6352
|
console.log();
|
|
6353
|
-
if (totalSuccess > 0) console.log(`${TEXT$8}✓
|
|
6353
|
+
if (totalSuccess > 0) console.log(`${TEXT$8}✓ 已更新 ${totalSuccess} 个技能${RESET$9}`);
|
|
6354
6354
|
if (totalFail > 0) {
|
|
6355
|
-
console.log(`${DIM$9}
|
|
6355
|
+
console.log(`${DIM$9}更新失败 ${totalFail} 个技能${RESET$9}`);
|
|
6356
6356
|
process.exitCode = 1;
|
|
6357
6357
|
}
|
|
6358
6358
|
String(totalSuccess + totalFail);
|
|
@@ -6394,7 +6394,7 @@ function parseUseOptions(args) {
|
|
|
6394
6394
|
const value = args[i + 1];
|
|
6395
6395
|
if (!value || value.startsWith("-")) errors.push(`${arg} requires a skill name`);
|
|
6396
6396
|
else if (options.skill) {
|
|
6397
|
-
errors.push("
|
|
6397
|
+
errors.push("只能提供一个 --skill 值");
|
|
6398
6398
|
i++;
|
|
6399
6399
|
} else {
|
|
6400
6400
|
options.skill = value;
|
|
@@ -6412,7 +6412,7 @@ function parseUseOptions(args) {
|
|
|
6412
6412
|
}
|
|
6413
6413
|
if (options.agent.length === startCount) errors.push(`${arg} requires an agent name`);
|
|
6414
6414
|
i--;
|
|
6415
|
-
} else if (arg.startsWith("-")) errors.push(
|
|
6415
|
+
} else if (arg.startsWith("-")) errors.push(`未知选项:${arg}`);
|
|
6416
6416
|
else source.push(arg);
|
|
6417
6417
|
}
|
|
6418
6418
|
errors.push(...validateUseAgentOption(options.agent));
|
|
@@ -6454,15 +6454,15 @@ async function runUse(sourceArgs, options = {}, parseErrors = []) {
|
|
|
6454
6454
|
return;
|
|
6455
6455
|
}
|
|
6456
6456
|
if (parseErrors.length > 0) fail(parseErrors.join("\n"));
|
|
6457
|
-
if (sourceArgs.length === 0) fail(
|
|
6458
|
-
if (sourceArgs.length > 1) fail(
|
|
6457
|
+
if (sourceArgs.length === 0) fail(`缺少必要参数:source\n\n${getUseHelp()}`);
|
|
6458
|
+
if (sourceArgs.length > 1) fail(`期望一个源,收到 ${sourceArgs.length} 个:${sourceArgs.join(", ")}`);
|
|
6459
6459
|
const useAgent = options.agent?.[0];
|
|
6460
6460
|
if (useAgent && !USE_AGENT_CONFIGS[useAgent]) fail(formatUnsupportedAgentError(useAgent));
|
|
6461
6461
|
const source = sourceArgs[0];
|
|
6462
6462
|
const parsed = parseSource(source);
|
|
6463
6463
|
if (getOwnerRepo(parsed)?.split("/")[0]?.toLowerCase() === "openclaw" && !options.dangerouslyAcceptOpenclawRisks) fail([
|
|
6464
6464
|
"OpenClaw skills are unverified community submissions.",
|
|
6465
|
-
"
|
|
6465
|
+
"技能以 Agent 的全部权限运行,可能存在恶意行为。",
|
|
6466
6466
|
`If you understand the risks, re-run with: skills use ${source} --dangerously-accept-openclaw-risks`
|
|
6467
6467
|
].join("\n"));
|
|
6468
6468
|
const selector = resolveSelector(parsed.skillFilter, options.skill);
|
|
@@ -6550,7 +6550,7 @@ async function launchAgentInteractively(agent, prompt, spawnImpl = spawnAgent) {
|
|
|
6550
6550
|
if (settled) return;
|
|
6551
6551
|
settled = true;
|
|
6552
6552
|
if (error.code === "ENOENT") {
|
|
6553
|
-
reject(new UseCommandError(
|
|
6553
|
+
reject(new UseCommandError(`无法启动 ${agents[agent].displayName}:未找到命令:${config.command}`));
|
|
6554
6554
|
return;
|
|
6555
6555
|
}
|
|
6556
6556
|
reject(error);
|
|
@@ -6591,7 +6591,7 @@ function resolveSelector(sourceSelector, optionSelector) {
|
|
|
6591
6591
|
return optionSelector ?? sourceSelector;
|
|
6592
6592
|
}
|
|
6593
6593
|
function selectSkill(skills, selector, source) {
|
|
6594
|
-
if (skills.length === 0) throw new UseCommandError("
|
|
6594
|
+
if (skills.length === 0) throw new UseCommandError("未找到有效技能。技能需要包含 name 和 description 的 SKILL.md 文件。");
|
|
6595
6595
|
if (!selector) {
|
|
6596
6596
|
if (skills.length === 1) return skills[0];
|
|
6597
6597
|
throw new UseCommandError(formatMultipleSkillsError(source, skills.map(getSkillDisplayName)));
|
|
@@ -6602,7 +6602,7 @@ function selectSkill(skills, selector, source) {
|
|
|
6602
6602
|
return selected[0];
|
|
6603
6603
|
}
|
|
6604
6604
|
function selectWellKnownSkill(skills, selector, source) {
|
|
6605
|
-
if (skills.length === 0) throw new UseCommandError("
|
|
6605
|
+
if (skills.length === 0) throw new UseCommandError("该 URL 未找到技能。请确保服务器提供 /.well-known/agent-skills/index.json 或 /.well-known/skills/index.json 文件。");
|
|
6606
6606
|
let selected;
|
|
6607
6607
|
if (!selector) {
|
|
6608
6608
|
if (skills.length !== 1) throw new UseCommandError(formatMultipleSkillsError(source, skills.map((s) => s.installName)));
|
|
@@ -6623,7 +6623,7 @@ function selectWellKnownSkill(skills, selector, source) {
|
|
|
6623
6623
|
}
|
|
6624
6624
|
function formatMultipleSkillsError(source, names) {
|
|
6625
6625
|
return [
|
|
6626
|
-
"
|
|
6626
|
+
"该源包含多个技能。请指定一个技能:",
|
|
6627
6627
|
...names.map((name) => ` - ${name}`),
|
|
6628
6628
|
"",
|
|
6629
6629
|
`Examples:\n skills use ${source}@${names[0] ?? "<skill>"}\n skills use ${source} --skill ${names[0] ?? "<skill>"}`
|
|
@@ -6632,7 +6632,7 @@ function formatMultipleSkillsError(source, names) {
|
|
|
6632
6632
|
function formatNoMatchError(selector, names) {
|
|
6633
6633
|
return [
|
|
6634
6634
|
`No matching skill found for: ${selector}`,
|
|
6635
|
-
"
|
|
6635
|
+
"可用技能:",
|
|
6636
6636
|
...names.map((name) => ` - ${name}`)
|
|
6637
6637
|
].join("\n");
|
|
6638
6638
|
}
|
|
@@ -6647,7 +6647,7 @@ function validateUseAgentOption(agentValues) {
|
|
|
6647
6647
|
return errors;
|
|
6648
6648
|
}
|
|
6649
6649
|
function formatUnsupportedAgentError(agent) {
|
|
6650
|
-
return [
|
|
6650
|
+
return [`暂不支持运行 ${agents[agent].displayName}。`, `skills use --agent 支持的 Agent:${SUPPORTED_USE_AGENTS.join(", ")}`].join("\n");
|
|
6651
6651
|
}
|
|
6652
6652
|
async function writeSnapshotFiles(targetDir, files) {
|
|
6653
6653
|
for (const file of files) await writeSafeFile(targetDir, file.path, file.contents);
|
|
@@ -6724,7 +6724,7 @@ async function runLogin(args, globalOpts) {
|
|
|
6724
6724
|
const token = getOptionValue$3(args, "--token");
|
|
6725
6725
|
const { registry } = resolveConfig(globalOpts);
|
|
6726
6726
|
if (!token) {
|
|
6727
|
-
console.error("
|
|
6727
|
+
console.error("用法:bfi auth login --token <token>");
|
|
6728
6728
|
process.exit(1);
|
|
6729
6729
|
}
|
|
6730
6730
|
const api = new SkillHubAPI(registry, token);
|
|
@@ -6740,10 +6740,10 @@ async function runLogin(args, globalOpts) {
|
|
|
6740
6740
|
handle: String(userInfo.handle || "")
|
|
6741
6741
|
};
|
|
6742
6742
|
saveGlobalConfig(config);
|
|
6743
|
-
console.log(`✓
|
|
6744
|
-
console.log(`
|
|
6743
|
+
console.log(`✓ 已登录为 ${userInfo.displayName || userInfo.name || "Unknown"}`);
|
|
6744
|
+
console.log(` 注册中心:${registry}`);
|
|
6745
6745
|
} catch (error) {
|
|
6746
|
-
console.error(
|
|
6746
|
+
console.error(`登录失败:${error.message}`);
|
|
6747
6747
|
process.exit(1);
|
|
6748
6748
|
}
|
|
6749
6749
|
}
|
|
@@ -6753,21 +6753,21 @@ async function runLogout() {
|
|
|
6753
6753
|
delete config.token;
|
|
6754
6754
|
delete config.user;
|
|
6755
6755
|
saveGlobalConfig(config);
|
|
6756
|
-
console.log("✓
|
|
6757
|
-
} else console.log("
|
|
6756
|
+
console.log("✓ 已登出");
|
|
6757
|
+
} else console.log("未登录。");
|
|
6758
6758
|
}
|
|
6759
6759
|
async function runWhoami(globalOpts) {
|
|
6760
6760
|
const { registry, token } = resolveConfig(globalOpts);
|
|
6761
6761
|
if (!token) {
|
|
6762
|
-
console.error("
|
|
6762
|
+
console.error("未认证。运行:bfi auth login --token <token>");
|
|
6763
6763
|
process.exit(1);
|
|
6764
6764
|
}
|
|
6765
6765
|
const response = await new SkillHubAPI(registry, token).whoami();
|
|
6766
6766
|
const user = response.user || response;
|
|
6767
|
-
console.log(`\
|
|
6768
|
-
console.log(`
|
|
6769
|
-
console.log(`
|
|
6770
|
-
console.log(` ID
|
|
6767
|
+
console.log(`\n当前用户:`);
|
|
6768
|
+
console.log(` 名称: ${user.displayName || user.name || "N/A"}`);
|
|
6769
|
+
console.log(` 句柄: ${user.handle || "N/A"}`);
|
|
6770
|
+
console.log(` ID: ${user.id || "N/A"}`);
|
|
6771
6771
|
console.log();
|
|
6772
6772
|
}
|
|
6773
6773
|
function getOptionValue$3(args, flag) {
|
|
@@ -6784,12 +6784,12 @@ async function runSearch(args, globalOpts) {
|
|
|
6784
6784
|
const query = parseSearchQuery(args);
|
|
6785
6785
|
const namespace = args.includes("--namespace") ? getOptionValue$2(args, "--namespace") : void 0;
|
|
6786
6786
|
if (!query) {
|
|
6787
|
-
console.log("
|
|
6787
|
+
console.log("用法:bfi search <query> [--namespace <ns>] [--marketplace]");
|
|
6788
6788
|
console.log();
|
|
6789
|
-
console.log("
|
|
6790
|
-
console.log(" --namespace <ns>
|
|
6791
|
-
console.log(" --marketplace
|
|
6792
|
-
console.log(" --all
|
|
6789
|
+
console.log("选项:");
|
|
6790
|
+
console.log(" --namespace <ns> 按 SkillHub 命名空间筛选");
|
|
6791
|
+
console.log(" --marketplace 仅搜索 skills.sh 市场");
|
|
6792
|
+
console.log(" --all 同时搜索 SkillHub 和市场");
|
|
6793
6793
|
return;
|
|
6794
6794
|
}
|
|
6795
6795
|
const useMarketplace = args.includes("--marketplace");
|
|
@@ -6799,9 +6799,9 @@ async function runSearch(args, globalOpts) {
|
|
|
6799
6799
|
return;
|
|
6800
6800
|
}
|
|
6801
6801
|
if (searchAll) {
|
|
6802
|
-
console.log(`${BOLD$5}=== SkillHub
|
|
6802
|
+
console.log(`${BOLD$5}=== SkillHub 注册表 ===${RESET$8}\n`);
|
|
6803
6803
|
await searchSkillHub(query, namespace, globalOpts);
|
|
6804
|
-
console.log(`\n${BOLD$5}=== skills.sh
|
|
6804
|
+
console.log(`\n${BOLD$5}=== skills.sh 市场 ===${RESET$8}\n`);
|
|
6805
6805
|
await searchMarketplace(query);
|
|
6806
6806
|
return;
|
|
6807
6807
|
}
|
|
@@ -6831,10 +6831,10 @@ async function searchSkillHub(query, namespace, globalOpts) {
|
|
|
6831
6831
|
});
|
|
6832
6832
|
const skills = result.results || result.data || [];
|
|
6833
6833
|
if (skills.length === 0) {
|
|
6834
|
-
console.log(`${DIM$8}
|
|
6834
|
+
console.log(`${DIM$8}SkillHub 上未找到 "${query}" 的技能${RESET$8}`);
|
|
6835
6835
|
return;
|
|
6836
6836
|
}
|
|
6837
|
-
console.log(`
|
|
6837
|
+
console.log(`SkillHub 上找到 ${skills.length} 个技能:\n`);
|
|
6838
6838
|
for (const skill of skills) {
|
|
6839
6839
|
const name = skill.displayName || skill.name || skill.slug;
|
|
6840
6840
|
const desc = skill.summary || skill.description || "";
|
|
@@ -6846,7 +6846,7 @@ async function searchSkillHub(query, namespace, globalOpts) {
|
|
|
6846
6846
|
console.log();
|
|
6847
6847
|
}
|
|
6848
6848
|
} catch (error) {
|
|
6849
|
-
console.error(`${DIM$8}SkillHub
|
|
6849
|
+
console.error(`${DIM$8}SkillHub 搜索失败:${error.message}${RESET$8}`);
|
|
6850
6850
|
}
|
|
6851
6851
|
}
|
|
6852
6852
|
async function searchMarketplace(query) {
|
|
@@ -6858,15 +6858,15 @@ async function searchMarketplace(query) {
|
|
|
6858
6858
|
const url = `${MARKETPLACE_API}/api/search?${params.toString()}`;
|
|
6859
6859
|
const res = await fetch(url);
|
|
6860
6860
|
if (!res.ok) {
|
|
6861
|
-
console.log(`${DIM$8}
|
|
6861
|
+
console.log(`${DIM$8}skills.sh 市场无结果${RESET$8}`);
|
|
6862
6862
|
return;
|
|
6863
6863
|
}
|
|
6864
6864
|
const skills = (await res.json()).skills || [];
|
|
6865
6865
|
if (skills.length === 0) {
|
|
6866
|
-
console.log(`${DIM$8}
|
|
6866
|
+
console.log(`${DIM$8}skills.sh 上未找到 "${query}" 的技能${RESET$8}`);
|
|
6867
6867
|
return;
|
|
6868
6868
|
}
|
|
6869
|
-
console.log(`
|
|
6869
|
+
console.log(`skills.sh 上找到 ${skills.length} 个技能:\n`);
|
|
6870
6870
|
for (const skill of skills.slice(0, 12)) {
|
|
6871
6871
|
const installs = formatInstalls(skill.installs);
|
|
6872
6872
|
console.log(` ${BOLD$5}${skill.name}${RESET$8}`);
|
|
@@ -6876,14 +6876,14 @@ async function searchMarketplace(query) {
|
|
|
6876
6876
|
console.log();
|
|
6877
6877
|
}
|
|
6878
6878
|
} catch {
|
|
6879
|
-
console.log(`${DIM$8}skills.sh
|
|
6879
|
+
console.log(`${DIM$8}skills.sh 市场不可用${RESET$8}`);
|
|
6880
6880
|
}
|
|
6881
6881
|
}
|
|
6882
6882
|
function formatInstalls(count) {
|
|
6883
6883
|
if (!count || count <= 0) return "";
|
|
6884
6884
|
if (count >= 1e6) return `${(count / 1e6).toFixed(1).replace(/\.0$/, "")}M installs`;
|
|
6885
6885
|
if (count >= 1e3) return `${(count / 1e3).toFixed(1).replace(/\.0$/, "")}K installs`;
|
|
6886
|
-
return `${count}
|
|
6886
|
+
return `${count} 次安装`;
|
|
6887
6887
|
}
|
|
6888
6888
|
function truncate$2(text, maxLen) {
|
|
6889
6889
|
if (text.length <= maxLen) return text;
|
|
@@ -6903,8 +6903,8 @@ const GREEN$4 = "\x1B[32m";
|
|
|
6903
6903
|
async function runInfo(args, globalOpts) {
|
|
6904
6904
|
const slug = args[0];
|
|
6905
6905
|
if (!slug) {
|
|
6906
|
-
console.log("
|
|
6907
|
-
console.log("
|
|
6906
|
+
console.log("用法:bfi info <skill-slug>");
|
|
6907
|
+
console.log("示例:bfi info global/my-skill");
|
|
6908
6908
|
process.exit(1);
|
|
6909
6909
|
}
|
|
6910
6910
|
const { registry, token } = resolveConfig(globalOpts);
|
|
@@ -6913,35 +6913,35 @@ async function runInfo(args, globalOpts) {
|
|
|
6913
6913
|
const result = await api.getSkill(slug);
|
|
6914
6914
|
const skill = result.data || result.skill || result;
|
|
6915
6915
|
if (!skill || !skill.slug) {
|
|
6916
|
-
console.log(`${DIM$7}
|
|
6916
|
+
console.log(`${DIM$7}未找到技能:${slug}${RESET$7}`);
|
|
6917
6917
|
process.exit(1);
|
|
6918
6918
|
}
|
|
6919
6919
|
console.log();
|
|
6920
6920
|
console.log(`${BOLD$4}${skill.displayName || skill.name || skill.slug}${RESET$7}`);
|
|
6921
6921
|
console.log(`${DIM$7}${"─".repeat(48)}${RESET$7}`);
|
|
6922
|
-
console.log(` ${BOLD$4}Slug
|
|
6923
|
-
if (skill.summary || skill.description) console.log(` ${BOLD$4}
|
|
6922
|
+
console.log(` ${BOLD$4}Slug:${RESET$7} ${TEXT$6}${skill.slug}${RESET$7}`);
|
|
6923
|
+
if (skill.summary || skill.description) console.log(` ${BOLD$4}描述:${RESET$7} ${TEXT$6}${skill.summary || skill.description}${RESET$7}`);
|
|
6924
6924
|
const owner = skill.owner;
|
|
6925
6925
|
if (owner) {
|
|
6926
|
-
console.log(` ${BOLD$4}
|
|
6927
|
-
if (owner.handle) console.log(` ${BOLD$4}
|
|
6926
|
+
console.log(` ${BOLD$4}所有者:${RESET$7} ${TEXT$6}${owner.displayName || owner.handle}${RESET$7}`);
|
|
6927
|
+
if (owner.handle) console.log(` ${BOLD$4}句柄:${RESET$7} ${TEXT$6}${owner.handle}${RESET$7}`);
|
|
6928
6928
|
}
|
|
6929
6929
|
const latestVersion = skill.latestVersion;
|
|
6930
6930
|
if (latestVersion) {
|
|
6931
|
-
console.log(` ${BOLD$4}
|
|
6932
|
-
if (latestVersion.license) console.log(` ${BOLD$4}
|
|
6933
|
-
if (latestVersion.changelog) console.log(` ${BOLD$4}
|
|
6931
|
+
console.log(` ${BOLD$4}版本:${RESET$7} ${TEXT$6}${latestVersion.version || "N/A"}${RESET$7}`);
|
|
6932
|
+
if (latestVersion.license) console.log(` ${BOLD$4}许可证:${RESET$7} ${TEXT$6}${latestVersion.license}${RESET$7}`);
|
|
6933
|
+
if (latestVersion.changelog) console.log(` ${BOLD$4}变更日志:${RESET$7} ${DIM$7}${truncate$1(latestVersion.changelog, 80)}${RESET$7}`);
|
|
6934
6934
|
if (latestVersion.createdAt) {
|
|
6935
6935
|
const date = new Date(latestVersion.createdAt).toISOString().split("T")[0];
|
|
6936
|
-
console.log(` ${BOLD$4}
|
|
6936
|
+
console.log(` ${BOLD$4}发布时间:${RESET$7} ${TEXT$6}${date}${RESET$7}`);
|
|
6937
6937
|
}
|
|
6938
6938
|
}
|
|
6939
6939
|
const stats = skill.stats;
|
|
6940
6940
|
if (stats) {
|
|
6941
6941
|
console.log();
|
|
6942
|
-
console.log(` ${BOLD$4}
|
|
6943
|
-
if (stats.downloads !== void 0) console.log(`
|
|
6944
|
-
if (stats.views !== void 0) console.log(`
|
|
6942
|
+
console.log(` ${BOLD$4}统计:${RESET$7}`);
|
|
6943
|
+
if (stats.downloads !== void 0) console.log(` 下载量:${TEXT$6}${stats.downloads}${RESET$7}`);
|
|
6944
|
+
if (stats.views !== void 0) console.log(` 浏览量:${TEXT$6}${stats.views}${RESET$7}`);
|
|
6945
6945
|
}
|
|
6946
6946
|
const tags = skill.tags;
|
|
6947
6947
|
if (Array.isArray(tags) && tags.length > 0) {
|
|
@@ -6949,33 +6949,33 @@ async function runInfo(args, globalOpts) {
|
|
|
6949
6949
|
const tag = t;
|
|
6950
6950
|
return tag.name || tag;
|
|
6951
6951
|
}).join(", ");
|
|
6952
|
-
console.log(` ${BOLD$4}
|
|
6952
|
+
console.log(` ${BOLD$4}标签:${RESET$7} ${TEXT$6}${tagList}${RESET$7}`);
|
|
6953
6953
|
}
|
|
6954
6954
|
const moderation = skill.moderation;
|
|
6955
6955
|
if (moderation) {
|
|
6956
6956
|
const verdict = moderation.verdict;
|
|
6957
6957
|
if (verdict === "MALWARE_BLOCKED" || moderation.isMalwareBlocked) {
|
|
6958
6958
|
console.log();
|
|
6959
|
-
console.log(` ${RED$2}${BOLD$4}⚠
|
|
6959
|
+
console.log(` ${RED$2}${BOLD$4}⚠ 已封禁:检测到恶意软件${RESET$7}`);
|
|
6960
6960
|
if (moderation.summary) console.log(` ${RED$2}${moderation.summary}${RESET$7}`);
|
|
6961
6961
|
} else if (verdict === "SUSPICIOUS" || moderation.isSuspicious) {
|
|
6962
6962
|
console.log();
|
|
6963
|
-
console.log(` ${YELLOW$2}⚠
|
|
6963
|
+
console.log(` ${YELLOW$2}⚠ 可疑技能${RESET$7}`);
|
|
6964
6964
|
if (moderation.summary) console.log(` ${YELLOW$2}${moderation.summary}${RESET$7}`);
|
|
6965
|
-
} else if (verdict === "SAFE") console.log(` ${BOLD$4}
|
|
6965
|
+
} else if (verdict === "SAFE") console.log(` ${BOLD$4}安全:${RESET$7} ${GREEN$4}已验证安全${RESET$7}`);
|
|
6966
6966
|
}
|
|
6967
6967
|
if (skill.createdAt) {
|
|
6968
6968
|
const created = new Date(skill.createdAt).toISOString().split("T")[0];
|
|
6969
|
-
console.log(` ${BOLD$4}
|
|
6969
|
+
console.log(` ${BOLD$4}创建时间:${RESET$7} ${TEXT$6}${created}${RESET$7}`);
|
|
6970
6970
|
}
|
|
6971
6971
|
if (skill.updatedAt) {
|
|
6972
6972
|
const updated = new Date(skill.updatedAt).toISOString().split("T")[0];
|
|
6973
|
-
console.log(` ${BOLD$4}
|
|
6973
|
+
console.log(` ${BOLD$4}更新时间:${RESET$7} ${TEXT$6}${updated}${RESET$7}`);
|
|
6974
6974
|
}
|
|
6975
6975
|
console.log();
|
|
6976
6976
|
} catch (error) {
|
|
6977
|
-
if (error.status === 404) console.error(
|
|
6978
|
-
else console.error(
|
|
6977
|
+
if (error.status === 404) console.error(`未找到技能:${slug}`);
|
|
6978
|
+
else console.error(`获取技能信息失败:${error.message}`);
|
|
6979
6979
|
process.exit(1);
|
|
6980
6980
|
}
|
|
6981
6981
|
}
|
|
@@ -6997,22 +6997,22 @@ async function runConfig(args, globalOpts) {
|
|
|
6997
6997
|
}
|
|
6998
6998
|
}
|
|
6999
6999
|
function printConfigHelp() {
|
|
7000
|
-
console.log("
|
|
7001
|
-
console.log(" bfi config get [key]
|
|
7002
|
-
console.log(" bfi config set <key> <value>
|
|
7000
|
+
console.log("配置命令:");
|
|
7001
|
+
console.log(" bfi config get [key] 获取配置值");
|
|
7002
|
+
console.log(" bfi config set <key> <value> 设置配置值");
|
|
7003
7003
|
console.log();
|
|
7004
|
-
console.log("
|
|
7004
|
+
console.log("可用键(全局):");
|
|
7005
7005
|
console.log(" registry API registry URL");
|
|
7006
7006
|
console.log(" default-namespace Default namespace");
|
|
7007
7007
|
console.log(" default-ide Default IDE");
|
|
7008
7008
|
console.log();
|
|
7009
|
-
console.log("
|
|
7009
|
+
console.log("可用键(项目):");
|
|
7010
7010
|
console.log(" registry API registry URL");
|
|
7011
7011
|
console.log(" namespace Project namespace");
|
|
7012
7012
|
console.log(" ide Project IDE");
|
|
7013
7013
|
console.log();
|
|
7014
|
-
console.log("
|
|
7015
|
-
console.log(" --global
|
|
7014
|
+
console.log("标志:");
|
|
7015
|
+
console.log(" --global 全局应用设置(默认:项目)");
|
|
7016
7016
|
}
|
|
7017
7017
|
async function handleGet(args, globalOpts) {
|
|
7018
7018
|
const key = args[1];
|
|
@@ -7035,21 +7035,21 @@ async function handleGet(args, globalOpts) {
|
|
|
7035
7035
|
const projectConfigKey = projectKeyMap[key] || key;
|
|
7036
7036
|
const globalValue = globalConfig[globalConfigKey];
|
|
7037
7037
|
const projectValue = projectConfig[projectConfigKey];
|
|
7038
|
-
console.log(`\
|
|
7038
|
+
console.log(`\n配置:${key}`);
|
|
7039
7039
|
console.log("-".repeat(40));
|
|
7040
|
-
if (projectValue !== void 0) console.log(
|
|
7041
|
-
else console.log(
|
|
7042
|
-
if (globalValue !== void 0) console.log(
|
|
7043
|
-
else console.log(
|
|
7040
|
+
if (projectValue !== void 0) console.log(`项目 (.bfirc):${projectValue}`);
|
|
7041
|
+
else console.log(`项目 (.bfirc):(未设置)`);
|
|
7042
|
+
if (globalValue !== void 0) console.log(`全局 (~/.bfi/config.json):${key === "token" ? "********" : globalValue}`);
|
|
7043
|
+
else console.log(`全局 (~/.bfi/config.json):(未设置)`);
|
|
7044
7044
|
console.log();
|
|
7045
7045
|
} else {
|
|
7046
|
-
console.log("\
|
|
7046
|
+
console.log("\n项目配置 (.bfirc):");
|
|
7047
7047
|
console.log("-".repeat(40));
|
|
7048
|
-
if (Object.keys(projectConfig).length === 0) console.log("
|
|
7048
|
+
if (Object.keys(projectConfig).length === 0) console.log(" (无项目配置)");
|
|
7049
7049
|
else for (const [k, v] of Object.entries(projectConfig)) console.log(` ${k}: ${v}`);
|
|
7050
|
-
console.log("\
|
|
7050
|
+
console.log("\n全局配置 (~/.bfi/config.json):");
|
|
7051
7051
|
console.log("-".repeat(40));
|
|
7052
|
-
if (Object.keys(globalConfig).length === 0) console.log("
|
|
7052
|
+
if (Object.keys(globalConfig).length === 0) console.log(" (无全局配置)");
|
|
7053
7053
|
else for (const [k, v] of Object.entries(globalConfig)) console.log(` ${k}: ${k === "token" ? "********" : v}`);
|
|
7054
7054
|
console.log();
|
|
7055
7055
|
}
|
|
@@ -7058,9 +7058,9 @@ async function handleSet(args, _globalOpts) {
|
|
|
7058
7058
|
const key = args[1];
|
|
7059
7059
|
const value = args[2];
|
|
7060
7060
|
if (!key || value === void 0) {
|
|
7061
|
-
console.error("
|
|
7061
|
+
console.error("用法:bfi config set <key> <value>");
|
|
7062
7062
|
console.log();
|
|
7063
|
-
console.log("
|
|
7063
|
+
console.log("使用 --global 标志进行全局设置:");
|
|
7064
7064
|
console.log(" bfi config set registry https://skillhub.example.com --global");
|
|
7065
7065
|
console.log(" bfi config set namespace myteam --global");
|
|
7066
7066
|
process.exit(1);
|
|
@@ -7073,13 +7073,13 @@ async function handleSet(args, _globalOpts) {
|
|
|
7073
7073
|
"default-ide"
|
|
7074
7074
|
];
|
|
7075
7075
|
if (!validKeys.includes(key)) {
|
|
7076
|
-
console.error(
|
|
7077
|
-
console.log(
|
|
7076
|
+
console.error(`无效的键:${key}`);
|
|
7077
|
+
console.log(`有效键:${validKeys.join(", ")}`);
|
|
7078
7078
|
process.exit(1);
|
|
7079
7079
|
}
|
|
7080
7080
|
const isGlobal = args.includes("--global");
|
|
7081
7081
|
setConfigValue(key, value, isGlobal);
|
|
7082
|
-
console.log(`${DIM$6}✓${RESET$6}
|
|
7082
|
+
console.log(`${DIM$6}✓${RESET$6} 已设置 ${key} = ${value}(${(isGlobal ? "global" : "project") === "global" ? "全局" : "项目"})`);
|
|
7083
7083
|
}
|
|
7084
7084
|
const RESET$5 = "\x1B[0m";
|
|
7085
7085
|
const BOLD$3 = "\x1B[1m";
|
|
@@ -7100,12 +7100,12 @@ async function runDocs(args, globalOpts) {
|
|
|
7100
7100
|
}
|
|
7101
7101
|
}
|
|
7102
7102
|
function printDocsHelp() {
|
|
7103
|
-
console.log("
|
|
7104
|
-
console.log(" bfi docs upload <file>
|
|
7105
|
-
console.log(" bfi docs list
|
|
7106
|
-
console.log(" bfi docs info <id>
|
|
7103
|
+
console.log("文档命令:");
|
|
7104
|
+
console.log(" bfi docs upload <file> 上传文档进行解析");
|
|
7105
|
+
console.log(" bfi docs list 列出已上传文档");
|
|
7106
|
+
console.log(" bfi docs info <id> 查看文档处理状态");
|
|
7107
7107
|
console.log();
|
|
7108
|
-
console.log("
|
|
7108
|
+
console.log("示例:");
|
|
7109
7109
|
console.log(` ${DIM$5}$ ${RESET$5}bfi docs upload resume.pdf`);
|
|
7110
7110
|
console.log(` ${DIM$5}$ ${RESET$5}bfi docs list`);
|
|
7111
7111
|
console.log(` ${DIM$5}$ ${RESET$5}bfi docs info 42`);
|
|
@@ -7113,18 +7113,18 @@ function printDocsHelp() {
|
|
|
7113
7113
|
async function handleUpload(args, globalOpts) {
|
|
7114
7114
|
const filePath = args[0];
|
|
7115
7115
|
if (!filePath) {
|
|
7116
|
-
console.error("
|
|
7117
|
-
console.log("
|
|
7116
|
+
console.error("用法:bfi docs upload <file>");
|
|
7117
|
+
console.log("上传文档文件进行解析。");
|
|
7118
7118
|
process.exit(1);
|
|
7119
7119
|
}
|
|
7120
7120
|
const resolvedPath = path$1.resolve(filePath);
|
|
7121
7121
|
if (!fs.existsSync(resolvedPath)) {
|
|
7122
|
-
console.error(
|
|
7122
|
+
console.error(`文件未找到:${resolvedPath}`);
|
|
7123
7123
|
process.exit(1);
|
|
7124
7124
|
}
|
|
7125
7125
|
const stats = fs.statSync(resolvedPath);
|
|
7126
7126
|
if (!stats.isFile()) {
|
|
7127
|
-
console.error(
|
|
7127
|
+
console.error(`不是文件:${resolvedPath}`);
|
|
7128
7128
|
process.exit(1);
|
|
7129
7129
|
}
|
|
7130
7130
|
const { registry, token } = resolveConfig(globalOpts);
|
|
@@ -7132,19 +7132,19 @@ async function handleUpload(args, globalOpts) {
|
|
|
7132
7132
|
const fileName = path$1.basename(resolvedPath);
|
|
7133
7133
|
const fileSize = stats.size;
|
|
7134
7134
|
const fileSizeStr = fileSize < 1024 ? `${fileSize} B` : fileSize < 1024 * 1024 ? `${(fileSize / 1024).toFixed(1)} KB` : `${(fileSize / (1024 * 1024)).toFixed(1)} MB`;
|
|
7135
|
-
console.log(`${DIM$5}
|
|
7135
|
+
console.log(`${DIM$5}正在上传 ${fileName} (${fileSizeStr})...${RESET$5}`);
|
|
7136
7136
|
try {
|
|
7137
7137
|
const fileBuffer = fs.readFileSync(resolvedPath);
|
|
7138
7138
|
const result = await api.uploadDoc(fileBuffer, fileName);
|
|
7139
|
-
console.log(`${TEXT$5}✓
|
|
7139
|
+
console.log(`${TEXT$5}✓ 上传成功${RESET$5}`);
|
|
7140
7140
|
console.log();
|
|
7141
|
-
if (result.id) console.log(` ${BOLD$3}ID
|
|
7142
|
-
if (result.status) console.log(` ${BOLD$3}
|
|
7143
|
-
if (result.fileName) console.log(` ${BOLD$3}
|
|
7141
|
+
if (result.id) console.log(` ${BOLD$3}ID:${RESET$5} ${TEXT$5}${result.id}${RESET$5}`);
|
|
7142
|
+
if (result.status) console.log(` ${BOLD$3}状态:${RESET$5} ${TEXT$5}${result.status}${RESET$5}`);
|
|
7143
|
+
if (result.fileName) console.log(` ${BOLD$3}文件:${RESET$5} ${TEXT$5}${result.fileName}${RESET$5}`);
|
|
7144
7144
|
console.log();
|
|
7145
|
-
if (result.id) console.log(`${DIM$5}
|
|
7145
|
+
if (result.id) console.log(`${DIM$5}查看状态:bfi docs info ${result.id}${RESET$5}`);
|
|
7146
7146
|
} catch (error) {
|
|
7147
|
-
console.error(
|
|
7147
|
+
console.error(`上传失败:${error.message}`);
|
|
7148
7148
|
process.exit(1);
|
|
7149
7149
|
}
|
|
7150
7150
|
}
|
|
@@ -7157,11 +7157,11 @@ async function handleList$1(args, globalOpts) {
|
|
|
7157
7157
|
const result = await api.listDocs(page, size);
|
|
7158
7158
|
const docs = result.data || result.docs || result.content || [];
|
|
7159
7159
|
if (!Array.isArray(docs) || docs.length === 0) {
|
|
7160
|
-
console.log(`${DIM$5}
|
|
7160
|
+
console.log(`${DIM$5}未找到文档。${RESET$5}`);
|
|
7161
7161
|
return;
|
|
7162
7162
|
}
|
|
7163
7163
|
console.log();
|
|
7164
|
-
console.log(`${BOLD$3}
|
|
7164
|
+
console.log(`${BOLD$3}文档${RESET$5}(第 ${page} 页,共 ${docs.length} 条结果):`);
|
|
7165
7165
|
console.log(`${DIM$5}${"─".repeat(64)}${RESET$5}`);
|
|
7166
7166
|
for (const doc of docs) {
|
|
7167
7167
|
const id = doc.id || "?";
|
|
@@ -7170,26 +7170,26 @@ async function handleList$1(args, globalOpts) {
|
|
|
7170
7170
|
const createdAt = doc.createdAt || doc.created_at;
|
|
7171
7171
|
const dateStr = createdAt ? new Date(createdAt).toISOString().split("T")[0] : "N/A";
|
|
7172
7172
|
console.log(` ${BOLD$3}#${id}${RESET$5} ${TEXT$5}${fileName}${RESET$5}`);
|
|
7173
|
-
console.log(` ${DIM$5}
|
|
7173
|
+
console.log(` ${DIM$5}状态:${status} | 日期:${dateStr}${RESET$5}`);
|
|
7174
7174
|
console.log();
|
|
7175
7175
|
}
|
|
7176
7176
|
const total = result.total || result.totalElements;
|
|
7177
|
-
if (total && Number(total) > (page + 1) * size) console.log(`${DIM$5}
|
|
7177
|
+
if (total && Number(total) > (page + 1) * size) console.log(`${DIM$5}下一页:bfi docs list ${page + 1}${RESET$5}`);
|
|
7178
7178
|
console.log();
|
|
7179
7179
|
} catch (error) {
|
|
7180
|
-
console.error(
|
|
7180
|
+
console.error(`列出文档失败:${error.message}`);
|
|
7181
7181
|
process.exit(1);
|
|
7182
7182
|
}
|
|
7183
7183
|
}
|
|
7184
7184
|
async function handleInfo$1(args, globalOpts) {
|
|
7185
7185
|
const docId = args[0];
|
|
7186
7186
|
if (!docId) {
|
|
7187
|
-
console.error("
|
|
7187
|
+
console.error("用法:bfi docs info <id>");
|
|
7188
7188
|
process.exit(1);
|
|
7189
7189
|
}
|
|
7190
7190
|
const id = parseInt(docId, 10);
|
|
7191
7191
|
if (isNaN(id)) {
|
|
7192
|
-
console.error(
|
|
7192
|
+
console.error(`无效的文档 ID:${docId}`);
|
|
7193
7193
|
process.exit(1);
|
|
7194
7194
|
}
|
|
7195
7195
|
const { registry, token } = resolveConfig(globalOpts);
|
|
@@ -7198,40 +7198,40 @@ async function handleInfo$1(args, globalOpts) {
|
|
|
7198
7198
|
const result = await api.getDoc(id);
|
|
7199
7199
|
const doc = result.data || result;
|
|
7200
7200
|
if (!doc || !doc.id) {
|
|
7201
|
-
console.log(`${DIM$5}
|
|
7201
|
+
console.log(`${DIM$5}未找到文档:${id}${RESET$5}`);
|
|
7202
7202
|
process.exit(1);
|
|
7203
7203
|
}
|
|
7204
7204
|
console.log();
|
|
7205
|
-
console.log(`${BOLD$3}
|
|
7205
|
+
console.log(`${BOLD$3}文档 #${doc.id}${RESET$5}`);
|
|
7206
7206
|
console.log(`${DIM$5}${"─".repeat(48)}${RESET$5}`);
|
|
7207
|
-
if (doc.fileName || doc.file_name) console.log(` ${BOLD$3}
|
|
7207
|
+
if (doc.fileName || doc.file_name) console.log(` ${BOLD$3}文件:${RESET$5} ${TEXT$5}${doc.fileName || doc.file_name}${RESET$5}`);
|
|
7208
7208
|
if (doc.status) {
|
|
7209
7209
|
const statusColor = doc.status === "completed" || doc.status === "COMPLETED" ? "\x1B[32m" : doc.status === "failed" || doc.status === "FAILED" ? "\x1B[31m" : TEXT$5;
|
|
7210
|
-
console.log(` ${BOLD$3}
|
|
7210
|
+
console.log(` ${BOLD$3}状态:${RESET$5} ${statusColor}${doc.status}${RESET$5}`);
|
|
7211
7211
|
}
|
|
7212
7212
|
if (doc.createdAt || doc.created_at) {
|
|
7213
7213
|
const date = new Date(doc.createdAt || doc.created_at).toISOString().replace("T", " ").slice(0, 19);
|
|
7214
|
-
console.log(` ${BOLD$3}
|
|
7214
|
+
console.log(` ${BOLD$3}创建时间:${RESET$5} ${TEXT$5}${date}${RESET$5}`);
|
|
7215
7215
|
}
|
|
7216
7216
|
if (doc.updatedAt || doc.updated_at) {
|
|
7217
7217
|
const date = new Date(doc.updatedAt || doc.updated_at).toISOString().replace("T", " ").slice(0, 19);
|
|
7218
|
-
console.log(` ${BOLD$3}
|
|
7218
|
+
console.log(` ${BOLD$3}更新时间:${RESET$5} ${TEXT$5}${date}${RESET$5}`);
|
|
7219
7219
|
}
|
|
7220
7220
|
if (doc.result) {
|
|
7221
7221
|
console.log();
|
|
7222
|
-
console.log(` ${BOLD$3}
|
|
7222
|
+
console.log(` ${BOLD$3}结果:${RESET$5}`);
|
|
7223
7223
|
const resultStr = typeof doc.result === "string" ? doc.result : JSON.stringify(doc.result, null, 4);
|
|
7224
7224
|
for (const line of resultStr.split("\n")) console.log(` ${DIM$5}${line}${RESET$5}`);
|
|
7225
7225
|
}
|
|
7226
7226
|
if (doc.error || doc.errorMessage) {
|
|
7227
7227
|
console.log();
|
|
7228
|
-
console.log(` \x1b[31m${BOLD$3}
|
|
7228
|
+
console.log(` \x1b[31m${BOLD$3}错误:${RESET$5}`);
|
|
7229
7229
|
console.log(` \x1b[31m${doc.error || doc.errorMessage}${RESET$5}`);
|
|
7230
7230
|
}
|
|
7231
7231
|
console.log();
|
|
7232
7232
|
} catch (error) {
|
|
7233
|
-
if (error.status === 404) console.error(
|
|
7234
|
-
else console.error(
|
|
7233
|
+
if (error.status === 404) console.error(`未找到文档:${id}`);
|
|
7234
|
+
else console.error(`获取文档信息失败:${error.message}`);
|
|
7235
7235
|
process.exit(1);
|
|
7236
7236
|
}
|
|
7237
7237
|
}
|
|
@@ -7272,53 +7272,53 @@ async function runPublish(args, globalOpts) {
|
|
|
7272
7272
|
await publishFromGit(positionalArgs, api, namespace, visibility, yes, branch, directory, skillFilter);
|
|
7273
7273
|
break;
|
|
7274
7274
|
default:
|
|
7275
|
-
console.error(
|
|
7276
|
-
console.log("
|
|
7277
|
-
console.log("
|
|
7275
|
+
console.error(`未知发布模式:${mode}`);
|
|
7276
|
+
console.log("可用模式:dir, zip, git");
|
|
7277
|
+
console.log("用法:bfi publish [source] --from dir|zip|git [options]");
|
|
7278
7278
|
process.exit(1);
|
|
7279
7279
|
}
|
|
7280
7280
|
}
|
|
7281
7281
|
async function publishFromDir(positionalArgs, api, namespace, visibility) {
|
|
7282
7282
|
const dirPath = positionalArgs[0];
|
|
7283
7283
|
if (!dirPath) {
|
|
7284
|
-
console.error("
|
|
7285
|
-
console.log("
|
|
7284
|
+
console.error("用法:bfi publish <directory> --from dir");
|
|
7285
|
+
console.log("从包含 SKILL.md 的本地目录发布技能。");
|
|
7286
7286
|
process.exit(1);
|
|
7287
7287
|
}
|
|
7288
7288
|
const resolvedDir = path$1.resolve(dirPath);
|
|
7289
7289
|
if (!fs.existsSync(resolvedDir)) {
|
|
7290
|
-
console.error(
|
|
7290
|
+
console.error(`目录未找到:${resolvedDir}`);
|
|
7291
7291
|
process.exit(1);
|
|
7292
7292
|
}
|
|
7293
7293
|
if (!fs.statSync(resolvedDir).isDirectory()) {
|
|
7294
|
-
console.error(
|
|
7294
|
+
console.error(`不是目录:${resolvedDir}`);
|
|
7295
7295
|
process.exit(1);
|
|
7296
7296
|
}
|
|
7297
7297
|
const skillMdPath = path$1.join(resolvedDir, "SKILL.md");
|
|
7298
7298
|
if (!fs.existsSync(skillMdPath)) {
|
|
7299
|
-
console.error(
|
|
7300
|
-
console.log("
|
|
7299
|
+
console.error(`在 ${resolvedDir} 中未找到 SKILL.md`);
|
|
7300
|
+
console.log("需要包含 frontmatter(name, description)的 SKILL.md 文件。");
|
|
7301
7301
|
process.exit(1);
|
|
7302
7302
|
}
|
|
7303
7303
|
const { data: frontmatter } = parseFrontmatter(fs.readFileSync(skillMdPath, "utf-8"));
|
|
7304
7304
|
const skillName = frontmatter.name || path$1.basename(resolvedDir);
|
|
7305
|
-
console.log(`${DIM$4}
|
|
7306
|
-
console.log(` ${BOLD$2}
|
|
7307
|
-
console.log(` ${BOLD$2}
|
|
7308
|
-
console.log(` ${BOLD$2}
|
|
7309
|
-
console.log(` ${BOLD$2}
|
|
7305
|
+
console.log(`${DIM$4}正在从目录发布技能...${RESET$4}`);
|
|
7306
|
+
console.log(` ${BOLD$2}名称:${RESET$4} ${TEXT$4}${skillName}${RESET$4}`);
|
|
7307
|
+
console.log(` ${BOLD$2}命名空间:${RESET$4} ${TEXT$4}${namespace}${RESET$4}`);
|
|
7308
|
+
console.log(` ${BOLD$2}可见性:${RESET$4} ${TEXT$4}${visibility}${RESET$4}`);
|
|
7309
|
+
console.log(` ${BOLD$2}目录:${RESET$4} ${TEXT$4}${resolvedDir}${RESET$4}`);
|
|
7310
7310
|
console.log();
|
|
7311
|
-
console.log(`${DIM$4}
|
|
7311
|
+
console.log(`${DIM$4}正在创建 zip...${RESET$4}`);
|
|
7312
7312
|
const zipBuffer = createZipFromDir(resolvedDir);
|
|
7313
|
-
console.log(` ${GREEN$3}Zip
|
|
7314
|
-
console.log(`${DIM$4}
|
|
7313
|
+
console.log(` ${GREEN$3}Zip 已创建 (${formatSize(zipBuffer.length)})${RESET$4}`);
|
|
7314
|
+
console.log(`${DIM$4}正在上传到 SkillHub...${RESET$4}`);
|
|
7315
7315
|
try {
|
|
7316
7316
|
const res = await api.publishSkill(namespace, zipBuffer, visibility);
|
|
7317
|
-
console.log(` ${GREEN$3}
|
|
7318
|
-
if (res.slug) console.log(` ${BOLD$2}Slug
|
|
7319
|
-
if (res.url) console.log(` ${BOLD$2}URL
|
|
7317
|
+
console.log(` ${GREEN$3}发布成功!${RESET$4}`);
|
|
7318
|
+
if (res.slug) console.log(` ${BOLD$2}Slug:${RESET$4} ${TEXT$4}${res.slug}${RESET$4}`);
|
|
7319
|
+
if (res.url) console.log(` ${BOLD$2}URL:${RESET$4} ${TEXT$4}${res.url}${RESET$4}`);
|
|
7320
7320
|
} catch (error) {
|
|
7321
|
-
console.error(` ${RED$1}
|
|
7321
|
+
console.error(` ${RED$1}发布失败:${error.message}${RESET$4}`);
|
|
7322
7322
|
process.exit(1);
|
|
7323
7323
|
}
|
|
7324
7324
|
console.log();
|
|
@@ -7326,43 +7326,43 @@ async function publishFromDir(positionalArgs, api, namespace, visibility) {
|
|
|
7326
7326
|
async function publishFromZip(positionalArgs, api, namespace, visibility) {
|
|
7327
7327
|
const zipPath = positionalArgs[0];
|
|
7328
7328
|
if (!zipPath) {
|
|
7329
|
-
console.error("
|
|
7330
|
-
console.log("
|
|
7329
|
+
console.error("用法:bfi publish <file.zip> --from zip");
|
|
7330
|
+
console.log("从包含 SKILL.md 的 zip 文件发布技能。");
|
|
7331
7331
|
process.exit(1);
|
|
7332
7332
|
}
|
|
7333
7333
|
const resolvedZip = path$1.resolve(zipPath);
|
|
7334
7334
|
if (!fs.existsSync(resolvedZip)) {
|
|
7335
|
-
console.error(
|
|
7335
|
+
console.error(`文件未找到:${resolvedZip}`);
|
|
7336
7336
|
process.exit(1);
|
|
7337
7337
|
}
|
|
7338
|
-
console.log(`${DIM$4}
|
|
7338
|
+
console.log(`${DIM$4}正在解压 zip...${RESET$4}`);
|
|
7339
7339
|
const tmpDir = path$1.join(os$1.tmpdir(), `.bfi-publish-${Date.now()}`);
|
|
7340
7340
|
fs.mkdirSync(tmpDir, { recursive: true });
|
|
7341
7341
|
try {
|
|
7342
7342
|
await extractZip(resolvedZip, tmpDir);
|
|
7343
7343
|
const skillMdPath = findSkillMd(tmpDir);
|
|
7344
7344
|
if (!skillMdPath) {
|
|
7345
|
-
console.error(` ${RED$1}SKILL.md
|
|
7345
|
+
console.error(` ${RED$1}zip 文件中未找到 SKILL.md${RESET$4}`);
|
|
7346
7346
|
process.exit(1);
|
|
7347
7347
|
}
|
|
7348
7348
|
const skillDir = path$1.dirname(skillMdPath);
|
|
7349
|
-
console.log(` ${GREEN$3}
|
|
7349
|
+
console.log(` ${GREEN$3}在 ${path$1.relative(tmpDir, skillDir) || "."} 中找到 SKILL.md${RESET$4}`);
|
|
7350
7350
|
const { data: frontmatter } = parseFrontmatter(fs.readFileSync(skillMdPath, "utf-8"));
|
|
7351
7351
|
const skillName = frontmatter.name || path$1.basename(skillDir);
|
|
7352
|
-
console.log(` ${BOLD$2}
|
|
7353
|
-
console.log(` ${BOLD$2}
|
|
7354
|
-
console.log(` ${BOLD$2}
|
|
7352
|
+
console.log(` ${BOLD$2}名称:${RESET$4} ${TEXT$4}${skillName}${RESET$4}`);
|
|
7353
|
+
console.log(` ${BOLD$2}命名空间:${RESET$4} ${TEXT$4}${namespace}${RESET$4}`);
|
|
7354
|
+
console.log(` ${BOLD$2}可见性:${RESET$4} ${TEXT$4}${visibility}${RESET$4}`);
|
|
7355
7355
|
console.log();
|
|
7356
|
-
console.log(`${DIM$4}
|
|
7356
|
+
console.log(`${DIM$4}正在重新打包...${RESET$4}`);
|
|
7357
7357
|
const zipBuffer = createZipFromDir(skillDir);
|
|
7358
|
-
console.log(` ${GREEN$3}Zip
|
|
7359
|
-
console.log(`${DIM$4}
|
|
7358
|
+
console.log(` ${GREEN$3}Zip 已创建 (${formatSize(zipBuffer.length)})${RESET$4}`);
|
|
7359
|
+
console.log(`${DIM$4}正在上传到 SkillHub...${RESET$4}`);
|
|
7360
7360
|
const res = await api.publishSkill(namespace, zipBuffer, visibility);
|
|
7361
|
-
console.log(` ${GREEN$3}
|
|
7362
|
-
if (res.slug) console.log(` ${BOLD$2}Slug
|
|
7363
|
-
if (res.url) console.log(` ${BOLD$2}URL
|
|
7361
|
+
console.log(` ${GREEN$3}发布成功!${RESET$4}`);
|
|
7362
|
+
if (res.slug) console.log(` ${BOLD$2}Slug:${RESET$4} ${TEXT$4}${res.slug}${RESET$4}`);
|
|
7363
|
+
if (res.url) console.log(` ${BOLD$2}URL:${RESET$4} ${TEXT$4}${res.url}${RESET$4}`);
|
|
7364
7364
|
} catch (error) {
|
|
7365
|
-
if (error.message && !error.message.includes("Publish failed")) console.error(` ${RED$1}
|
|
7365
|
+
if (error.message && !error.message.includes("Publish failed")) console.error(` ${RED$1}错误:${error.message}${RESET$4}`);
|
|
7366
7366
|
process.exit(1);
|
|
7367
7367
|
} finally {
|
|
7368
7368
|
try {
|
|
@@ -7377,10 +7377,10 @@ async function publishFromZip(positionalArgs, api, namespace, visibility) {
|
|
|
7377
7377
|
async function publishFromGit(positionalArgs, api, namespace, visibility, yes, branch, directory, skillFilter) {
|
|
7378
7378
|
const repoArg = positionalArgs[0];
|
|
7379
7379
|
if (!repoArg) {
|
|
7380
|
-
console.error("
|
|
7381
|
-
console.log("
|
|
7380
|
+
console.error("用法:bfi publish <repo-url> --from git [options]");
|
|
7381
|
+
console.log("使用服务端发现从 Git 仓库发布技能。");
|
|
7382
7382
|
console.log();
|
|
7383
|
-
console.log("
|
|
7383
|
+
console.log("示例:");
|
|
7384
7384
|
console.log(` ${DIM$4}$ ${RESET$4}bfi publish https://github.com/user/repo --from git`);
|
|
7385
7385
|
console.log(` ${DIM$4}$ ${RESET$4}bfi publish user/repo --from git --branch main`);
|
|
7386
7386
|
process.exit(1);
|
|
@@ -7393,40 +7393,40 @@ async function publishFromGit(positionalArgs, api, namespace, visibility, yes, b
|
|
|
7393
7393
|
}
|
|
7394
7394
|
const effectiveBranch = branch || "main";
|
|
7395
7395
|
const effectiveDir = directory || null;
|
|
7396
|
-
console.log(`${DIM$4}
|
|
7397
|
-
console.log(` ${BOLD$2}
|
|
7398
|
-
console.log(` ${BOLD$2}
|
|
7399
|
-
if (effectiveDir) console.log(` ${BOLD$2}
|
|
7396
|
+
console.log(`${DIM$4}正在从 Git 仓库发现技能...${RESET$4}`);
|
|
7397
|
+
console.log(` ${BOLD$2}仓库:${RESET$4} ${TEXT$4}${repoUrl}${RESET$4}`);
|
|
7398
|
+
console.log(` ${BOLD$2}分支:${RESET$4} ${TEXT$4}${effectiveBranch}${RESET$4}`);
|
|
7399
|
+
if (effectiveDir) console.log(` ${BOLD$2}目录:${RESET$4} ${TEXT$4}${effectiveDir}${RESET$4}`);
|
|
7400
7400
|
console.log();
|
|
7401
7401
|
let parseResult;
|
|
7402
7402
|
try {
|
|
7403
7403
|
parseResult = await api.gitParse(repoUrl, effectiveBranch, effectiveDir);
|
|
7404
7404
|
} catch (error) {
|
|
7405
|
-
console.error(` ${RED$1}Git
|
|
7405
|
+
console.error(` ${RED$1}Git 解析失败:${error.message}${RESET$4}`);
|
|
7406
7406
|
process.exit(1);
|
|
7407
7407
|
}
|
|
7408
7408
|
const sessionId = parseResult.sessionId;
|
|
7409
7409
|
const discoveredSkills = parseResult.skills || [];
|
|
7410
7410
|
const precheck = parseResult.precheck;
|
|
7411
7411
|
if (!sessionId || discoveredSkills.length === 0) {
|
|
7412
|
-
console.log(`${YELLOW$1}
|
|
7412
|
+
console.log(`${YELLOW$1}仓库中未发现技能。${RESET$4}`);
|
|
7413
7413
|
if (precheck && (precheck.errors || precheck.warnings)) {
|
|
7414
7414
|
console.log();
|
|
7415
|
-
console.log(`${BOLD$2}
|
|
7415
|
+
console.log(`${BOLD$2}预检结果:${RESET$4}`);
|
|
7416
7416
|
const errors = precheck.errors;
|
|
7417
7417
|
const warnings = precheck.warnings;
|
|
7418
7418
|
if (errors && errors.length > 0) {
|
|
7419
|
-
console.log(` ${RED$1}
|
|
7419
|
+
console.log(` ${RED$1}错误:${RESET$4}`);
|
|
7420
7420
|
for (const e of errors) console.log(` ${RED$1}- ${e}${RESET$4}`);
|
|
7421
7421
|
}
|
|
7422
7422
|
if (warnings && warnings.length > 0) {
|
|
7423
|
-
console.log(` ${YELLOW$1}
|
|
7423
|
+
console.log(` ${YELLOW$1}警告:${RESET$4}`);
|
|
7424
7424
|
for (const w of warnings) console.log(` ${YELLOW$1}- ${w}${RESET$4}`);
|
|
7425
7425
|
}
|
|
7426
7426
|
}
|
|
7427
7427
|
process.exit(1);
|
|
7428
7428
|
}
|
|
7429
|
-
console.log(`${BOLD$2}
|
|
7429
|
+
console.log(`${BOLD$2}发现 ${discoveredSkills.length} 个技能:${RESET$4}`);
|
|
7430
7430
|
console.log();
|
|
7431
7431
|
let selectedSkills = discoveredSkills;
|
|
7432
7432
|
if (skillFilter) {
|
|
@@ -7437,7 +7437,7 @@ async function publishFromGit(positionalArgs, api, namespace, visibility, yes, b
|
|
|
7437
7437
|
return filters.some((f) => slug.includes(f) || name.includes(f));
|
|
7438
7438
|
});
|
|
7439
7439
|
if (selectedSkills.length === 0) {
|
|
7440
|
-
console.log(`${YELLOW$1}
|
|
7440
|
+
console.log(`${YELLOW$1}没有技能匹配筛选条件:${skillFilter}${RESET$4}`);
|
|
7441
7441
|
console.log("Available skills:");
|
|
7442
7442
|
for (const s of discoveredSkills) console.log(` - ${s.slug || s.name}`);
|
|
7443
7443
|
process.exit(1);
|
|
@@ -7460,8 +7460,8 @@ async function publishFromGit(positionalArgs, api, namespace, visibility, yes, b
|
|
|
7460
7460
|
if (skillPrecheck) {
|
|
7461
7461
|
const errors = skillPrecheck.errors;
|
|
7462
7462
|
const warnings = skillPrecheck.warnings;
|
|
7463
|
-
if (errors && errors.length > 0) for (const e of errors) console.log(` ${RED$1}
|
|
7464
|
-
if (warnings && warnings.length > 0) for (const w of warnings) console.log(` ${YELLOW$1}
|
|
7463
|
+
if (errors && errors.length > 0) for (const e of errors) console.log(` ${RED$1}错误:${e}${RESET$4}`);
|
|
7464
|
+
if (warnings && warnings.length > 0) for (const w of warnings) console.log(` ${YELLOW$1}警告:${w}${RESET$4}`);
|
|
7465
7465
|
}
|
|
7466
7466
|
console.log();
|
|
7467
7467
|
}
|
|
@@ -7474,21 +7474,21 @@ async function publishFromGit(positionalArgs, api, namespace, visibility, yes, b
|
|
|
7474
7474
|
const selectedSlugs = skillFilter ? selectedSkills.map((s) => String(s.slug)) : null;
|
|
7475
7475
|
if (!yes) {
|
|
7476
7476
|
const count = selectedSlugs ? selectedSlugs.length : discoveredSkills.length;
|
|
7477
|
-
console.log(`${DIM$4}
|
|
7478
|
-
console.log(`${DIM$4}
|
|
7479
|
-
await confirmPrompt("
|
|
7477
|
+
console.log(`${DIM$4}正在将 ${count} 个技能发布到 @${namespace} (${visibility})${RESET$4}`);
|
|
7478
|
+
console.log(`${DIM$4}按 Ctrl+C 取消,或按 Enter 继续...${RESET$4}`);
|
|
7479
|
+
await confirmPrompt("确认发布?");
|
|
7480
7480
|
}
|
|
7481
|
-
console.log(`${DIM$4}
|
|
7481
|
+
console.log(`${DIM$4}正在发布到 SkillHub...${RESET$4}`);
|
|
7482
7482
|
try {
|
|
7483
7483
|
const res = await api.gitPublish(sessionId, namespace, visibility, selectedSlugs, confirmWarnings);
|
|
7484
|
-
console.log(` ${GREEN$3}
|
|
7484
|
+
console.log(` ${GREEN$3}发布成功!${RESET$4}`);
|
|
7485
7485
|
const publishedSkills = res.skills || res.published;
|
|
7486
7486
|
if (Array.isArray(publishedSkills)) for (const s of publishedSkills) {
|
|
7487
7487
|
const ps = s;
|
|
7488
7488
|
console.log(` ${GREEN$3}✓ ${ps.slug || ps.name}${RESET$4}`);
|
|
7489
7489
|
}
|
|
7490
7490
|
} catch (error) {
|
|
7491
|
-
console.error(` ${RED$1}
|
|
7491
|
+
console.error(` ${RED$1}发布失败:${error.message}${RESET$4}`);
|
|
7492
7492
|
process.exit(1);
|
|
7493
7493
|
}
|
|
7494
7494
|
console.log();
|
|
@@ -7584,21 +7584,21 @@ async function runPackage(args, globalOpts) {
|
|
|
7584
7584
|
}
|
|
7585
7585
|
function printPackageHelp() {
|
|
7586
7586
|
console.log();
|
|
7587
|
-
console.log(`${BOLD$1}
|
|
7588
|
-
console.log(` ${DIM$3}bfi package list${RESET$3}
|
|
7589
|
-
console.log(` ${DIM$3}bfi package info <ref>${RESET$3}
|
|
7590
|
-
console.log(` ${DIM$3}bfi package create <slug>${RESET$3}
|
|
7591
|
-
console.log(` ${DIM$3}bfi package add <pkg> <skills>${RESET$3}
|
|
7592
|
-
console.log(` ${DIM$3}bfi package remove <pkg> <skills>${RESET$3}
|
|
7587
|
+
console.log(`${BOLD$1}包命令:${RESET$3}`);
|
|
7588
|
+
console.log(` ${DIM$3}bfi package list${RESET$3} 列出包`);
|
|
7589
|
+
console.log(` ${DIM$3}bfi package info <ref>${RESET$3} 查看包详情`);
|
|
7590
|
+
console.log(` ${DIM$3}bfi package create <slug>${RESET$3} 创建新包`);
|
|
7591
|
+
console.log(` ${DIM$3}bfi package add <pkg> <skills>${RESET$3} 添加技能到包`);
|
|
7592
|
+
console.log(` ${DIM$3}bfi package remove <pkg> <skills>${RESET$3} 从包移除技能`);
|
|
7593
7593
|
console.log();
|
|
7594
|
-
console.log(`${BOLD$1}
|
|
7595
|
-
console.log(` --namespace <ns>
|
|
7596
|
-
console.log(` --name <name>
|
|
7597
|
-
console.log(` --description <text>
|
|
7598
|
-
console.log(` --visibility <v>
|
|
7599
|
-
console.log(` --json
|
|
7594
|
+
console.log(`${BOLD$1}选项:${RESET$3}`);
|
|
7595
|
+
console.log(` --namespace <ns> 目标命名空间`);
|
|
7596
|
+
console.log(` --name <name> 显示名称(create 时)`);
|
|
7597
|
+
console.log(` --description <text> 描述(create 时)`);
|
|
7598
|
+
console.log(` --visibility <v> 私有或公开(create 时)`);
|
|
7599
|
+
console.log(` --json 以 JSON 输出`);
|
|
7600
7600
|
console.log();
|
|
7601
|
-
console.log(`${BOLD$1}
|
|
7601
|
+
console.log(`${BOLD$1}示例:${RESET$3}`);
|
|
7602
7602
|
console.log(` ${DIM$3}$ ${RESET$3}bfi package list --namespace myteam`);
|
|
7603
7603
|
console.log(` ${DIM$3}$ ${RESET$3}bfi package info @myteam/my-package`);
|
|
7604
7604
|
console.log(` ${DIM$3}$ ${RESET$3}bfi package create my-utils --namespace myteam`);
|
|
@@ -7621,7 +7621,7 @@ async function handleList(args, api, globalOpts) {
|
|
|
7621
7621
|
return;
|
|
7622
7622
|
}
|
|
7623
7623
|
console.log();
|
|
7624
|
-
console.log(`${BOLD$1}
|
|
7624
|
+
console.log(`${BOLD$1}@${namespace} 中的包${RESET$3}(${packages.length} 个):`);
|
|
7625
7625
|
console.log();
|
|
7626
7626
|
packages.forEach((pkg, index) => {
|
|
7627
7627
|
const visibility = pkg.visibility || "private";
|
|
@@ -7634,7 +7634,7 @@ async function handleList(args, api, globalOpts) {
|
|
|
7634
7634
|
console.log();
|
|
7635
7635
|
});
|
|
7636
7636
|
} catch (error) {
|
|
7637
|
-
console.error(
|
|
7637
|
+
console.error(`列出包失败:${error.message}`);
|
|
7638
7638
|
process.exit(1);
|
|
7639
7639
|
}
|
|
7640
7640
|
}
|
|
@@ -7660,26 +7660,26 @@ async function handleInfo(args, api, globalOpts) {
|
|
|
7660
7660
|
console.log();
|
|
7661
7661
|
console.log(`${BOLD$1}${pkg.name || slug}${RESET$3}`);
|
|
7662
7662
|
console.log(`${DIM$3}${"=".repeat(48)}${RESET$3}`);
|
|
7663
|
-
console.log(` ${BOLD$1}Slug
|
|
7664
|
-
console.log(` ${BOLD$1}
|
|
7665
|
-
console.log(` ${BOLD$1}
|
|
7666
|
-
console.log(` ${BOLD$1}
|
|
7663
|
+
console.log(` ${BOLD$1}Slug:${RESET$3} ${TEXT$3}${toCanonicalSlug(namespace, slug)}${RESET$3}`);
|
|
7664
|
+
console.log(` ${BOLD$1}命名空间:${RESET$3} ${TEXT$3}@${namespace}${RESET$3}`);
|
|
7665
|
+
console.log(` ${BOLD$1}可见性:${RESET$3} ${TEXT$3}${pkg.visibility || "private"}${RESET$3}`);
|
|
7666
|
+
console.log(` ${BOLD$1}描述:${RESET$3} ${TEXT$3}${pkg.description || "N/A"}${RESET$3}`);
|
|
7667
7667
|
const skills = pkg.skills;
|
|
7668
7668
|
if (skills && skills.length > 0) {
|
|
7669
7669
|
console.log();
|
|
7670
|
-
console.log(` ${BOLD$1}
|
|
7670
|
+
console.log(` ${BOLD$1}技能(${skills.length} 个):${RESET$3}`);
|
|
7671
7671
|
for (const skill of skills) console.log(` ${DIM$3}- ${skill.slug}${skill.name ? ` (${skill.name})` : ""}${RESET$3}`);
|
|
7672
7672
|
}
|
|
7673
7673
|
console.log();
|
|
7674
7674
|
} catch (error) {
|
|
7675
|
-
console.error(
|
|
7675
|
+
console.error(`获取包信息失败:${error.message}`);
|
|
7676
7676
|
process.exit(1);
|
|
7677
7677
|
}
|
|
7678
7678
|
}
|
|
7679
7679
|
async function handleCreate(args, api, globalOpts) {
|
|
7680
7680
|
const slug = args[0];
|
|
7681
7681
|
if (!slug) {
|
|
7682
|
-
console.error("
|
|
7682
|
+
console.error("用法:bfi package create <slug> [options]");
|
|
7683
7683
|
process.exit(1);
|
|
7684
7684
|
}
|
|
7685
7685
|
const namespace = getOptionValue(args, "--namespace") || globalOpts.namespace || "global";
|
|
@@ -7693,14 +7693,14 @@ async function handleCreate(args, api, globalOpts) {
|
|
|
7693
7693
|
description: description || "",
|
|
7694
7694
|
visibility
|
|
7695
7695
|
});
|
|
7696
|
-
console.log(`${GREEN$2}✓
|
|
7696
|
+
console.log(`${GREEN$2}✓ 已创建包 ${toSkillRefString(namespace, slug)}${RESET$3}`);
|
|
7697
7697
|
const createdPkg = result.package;
|
|
7698
7698
|
if (createdPkg) {
|
|
7699
|
-
console.log(` ${BOLD$1}
|
|
7699
|
+
console.log(` ${BOLD$1}名称:${RESET$3} ${TEXT$3}${createdPkg.name || slug}${RESET$3}`);
|
|
7700
7700
|
console.log(` ${BOLD$1}Visibility:${RESET$3} ${TEXT$3}${createdPkg.visibility || visibility}${RESET$3}`);
|
|
7701
7701
|
}
|
|
7702
7702
|
} catch (error) {
|
|
7703
|
-
console.error(
|
|
7703
|
+
console.error(`创建包失败:${error.message}`);
|
|
7704
7704
|
process.exit(1);
|
|
7705
7705
|
}
|
|
7706
7706
|
}
|
|
@@ -7708,7 +7708,7 @@ async function handleAdd(args, api, globalOpts) {
|
|
|
7708
7708
|
const pkgRef = args[0];
|
|
7709
7709
|
const skillRefs = args.slice(1);
|
|
7710
7710
|
if (!pkgRef || skillRefs.length === 0) {
|
|
7711
|
-
console.error("
|
|
7711
|
+
console.error("用法:bfi package add <package-ref> <skill-ref...>");
|
|
7712
7712
|
process.exit(1);
|
|
7713
7713
|
}
|
|
7714
7714
|
const { namespace, slug } = parseSkillRef(pkgRef, globalOpts.namespace);
|
|
@@ -7721,10 +7721,10 @@ async function handleAdd(args, api, globalOpts) {
|
|
|
7721
7721
|
});
|
|
7722
7722
|
try {
|
|
7723
7723
|
await api.addSkillsToPackage(namespace, slug, skills);
|
|
7724
|
-
console.log(`${GREEN$2}✓
|
|
7724
|
+
console.log(`${GREEN$2}✓ 已添加 ${skills.length} 个技能到 ${toSkillRefString(namespace, slug)}${RESET$3}`);
|
|
7725
7725
|
for (const s of skills) console.log(` ${DIM$3}- ${toSkillRefString(s.namespace, s.slug)}${RESET$3}`);
|
|
7726
7726
|
} catch (error) {
|
|
7727
|
-
console.error(
|
|
7727
|
+
console.error(`添加技能失败:${error.message}`);
|
|
7728
7728
|
process.exit(1);
|
|
7729
7729
|
}
|
|
7730
7730
|
}
|
|
@@ -7732,7 +7732,7 @@ async function handleRemove(args, api, globalOpts) {
|
|
|
7732
7732
|
const pkgRef = args[0];
|
|
7733
7733
|
const skillRefs = args.slice(1);
|
|
7734
7734
|
if (!pkgRef || skillRefs.length === 0) {
|
|
7735
|
-
console.error("
|
|
7735
|
+
console.error("用法:bfi package remove <package-ref> <skill-ref...>");
|
|
7736
7736
|
process.exit(1);
|
|
7737
7737
|
}
|
|
7738
7738
|
const { namespace, slug } = parseSkillRef(pkgRef, globalOpts.namespace);
|
|
@@ -7745,10 +7745,10 @@ async function handleRemove(args, api, globalOpts) {
|
|
|
7745
7745
|
});
|
|
7746
7746
|
try {
|
|
7747
7747
|
await api.removeSkillsFromPackage(namespace, slug, skills);
|
|
7748
|
-
console.log(`${GREEN$2}✓
|
|
7748
|
+
console.log(`${GREEN$2}✓ 已从 ${toSkillRefString(namespace, slug)} 移除 ${skills.length} 个技能${RESET$3}`);
|
|
7749
7749
|
for (const s of skills) console.log(` ${DIM$3}- ${toSkillRefString(s.namespace, s.slug)}${RESET$3}`);
|
|
7750
7750
|
} catch (error) {
|
|
7751
|
-
console.error(
|
|
7751
|
+
console.error(`移除技能失败:${error.message}`);
|
|
7752
7752
|
process.exit(1);
|
|
7753
7753
|
}
|
|
7754
7754
|
}
|
|
@@ -7764,11 +7764,11 @@ const RED = "\x1B[31m";
|
|
|
7764
7764
|
async function runLog(args, globalOpts) {
|
|
7765
7765
|
const skillRef = args[0];
|
|
7766
7766
|
if (!skillRef) {
|
|
7767
|
-
console.log("
|
|
7767
|
+
console.log("用法:bfi log <skill-ref> [summary]");
|
|
7768
7768
|
console.log();
|
|
7769
|
-
console.log("
|
|
7769
|
+
console.log("记录技能使用到 SkillHub 用于追踪和分析。");
|
|
7770
7770
|
console.log();
|
|
7771
|
-
console.log("
|
|
7771
|
+
console.log("示例:");
|
|
7772
7772
|
console.log(` ${DIM$2}$ ${RESET$2}bfi log @myteam/my-skill`);
|
|
7773
7773
|
console.log(` ${DIM$2}$ ${RESET$2}bfi log my-skill "Used for code review"`);
|
|
7774
7774
|
process.exit(1);
|
|
@@ -7778,10 +7778,10 @@ async function runLog(args, globalOpts) {
|
|
|
7778
7778
|
const api = new SkillHubAPI(registry, token);
|
|
7779
7779
|
try {
|
|
7780
7780
|
const result = await api.logSkillUsage(skillRef, summary);
|
|
7781
|
-
console.log(`${GREEN$1}✓
|
|
7781
|
+
console.log(`${GREEN$1}✓ 已记录使用 ${TEXT$2}${skillRef}${RESET$2}`);
|
|
7782
7782
|
if (result.message) console.log(` ${DIM$2}${result.message}${RESET$2}`);
|
|
7783
7783
|
} catch (error) {
|
|
7784
|
-
console.error(`${RED}
|
|
7784
|
+
console.error(`${RED}记录技能使用失败:${error.message}${RESET$2}`);
|
|
7785
7785
|
process.exit(1);
|
|
7786
7786
|
}
|
|
7787
7787
|
}
|
|
@@ -7796,14 +7796,14 @@ async function runInstall(args, globalOpts) {
|
|
|
7796
7796
|
const skillEntries = Object.entries(lock.skills);
|
|
7797
7797
|
const packageEntries = Object.entries(lock.packages);
|
|
7798
7798
|
if (skillEntries.length === 0 && packageEntries.length === 0) {
|
|
7799
|
-
console.log(`${DIM$1}
|
|
7800
|
-
console.log(`${DIM$1}
|
|
7799
|
+
console.log(`${DIM$1}锁文件 (.bfi/lock.json) 中未找到技能或包。${RESET$1}`);
|
|
7800
|
+
console.log(`${DIM$1}请先运行 'bfi skills add <source>' 安装技能。${RESET$1}`);
|
|
7801
7801
|
return;
|
|
7802
7802
|
}
|
|
7803
7803
|
console.log();
|
|
7804
|
-
console.log(`${DIM$1}
|
|
7805
|
-
console.log(`
|
|
7806
|
-
console.log(`
|
|
7804
|
+
console.log(`${DIM$1}正在从锁文件恢复...${RESET$1}`);
|
|
7805
|
+
console.log(` 技能:${skillEntries.length}`);
|
|
7806
|
+
console.log(` 包:${packageEntries.length}`);
|
|
7807
7807
|
console.log();
|
|
7808
7808
|
let installedCount = 0;
|
|
7809
7809
|
let failedCount = 0;
|
|
@@ -7818,35 +7818,35 @@ async function runInstall(args, globalOpts) {
|
|
|
7818
7818
|
if (sourceType === "skillhub" || namespace !== "global") installSource = `@${namespace}/${slug}`;
|
|
7819
7819
|
else if (source) installSource = source;
|
|
7820
7820
|
else {
|
|
7821
|
-
console.log(` ${YELLOW}
|
|
7821
|
+
console.log(` ${YELLOW}跳过 ${skillName}:未知源类型${RESET$1}`);
|
|
7822
7822
|
continue;
|
|
7823
7823
|
}
|
|
7824
|
-
console.log(` ${TEXT$1}
|
|
7824
|
+
console.log(` ${TEXT$1}正在从 ${installSource} 安装 ${skillName}...${RESET$1}`);
|
|
7825
7825
|
try {
|
|
7826
7826
|
await runAdd([installSource], { yes });
|
|
7827
7827
|
installedCount++;
|
|
7828
7828
|
console.log(` ${GREEN}✓ ${skillName}${RESET$1}`);
|
|
7829
7829
|
} catch (error) {
|
|
7830
7830
|
failedCount++;
|
|
7831
|
-
console.error(` ${YELLOW}
|
|
7831
|
+
console.error(` ${YELLOW}失败:${error.message}${RESET$1}`);
|
|
7832
7832
|
}
|
|
7833
7833
|
}
|
|
7834
7834
|
for (const [pkgRef, entry] of packageEntries) {
|
|
7835
7835
|
const pkgEntry = entry;
|
|
7836
7836
|
const installSource = `@${String(pkgEntry.namespace || "global")}/${String(pkgEntry.slug || pkgRef)}`;
|
|
7837
|
-
console.log(` ${TEXT$1}
|
|
7837
|
+
console.log(` ${TEXT$1}正在从 ${installSource} 安装包 ${pkgRef}...${RESET$1}`);
|
|
7838
7838
|
try {
|
|
7839
7839
|
await runAdd([installSource], { yes });
|
|
7840
7840
|
installedCount++;
|
|
7841
7841
|
console.log(` ${GREEN}✓ ${pkgRef}${RESET$1}`);
|
|
7842
7842
|
} catch (error) {
|
|
7843
7843
|
failedCount++;
|
|
7844
|
-
console.error(` ${YELLOW}
|
|
7844
|
+
console.error(` ${YELLOW}失败:${error.message}${RESET$1}`);
|
|
7845
7845
|
}
|
|
7846
7846
|
}
|
|
7847
7847
|
console.log();
|
|
7848
|
-
if (installedCount > 0) console.log(`${GREEN}✓
|
|
7849
|
-
if (failedCount > 0) console.log(`${YELLOW}⚠ ${failedCount}
|
|
7848
|
+
if (installedCount > 0) console.log(`${GREEN}✓ 已恢复 ${installedCount} 项${RESET$1}`);
|
|
7849
|
+
if (failedCount > 0) console.log(`${YELLOW}⚠ ${failedCount} 项恢复失败${RESET$1}`);
|
|
7850
7850
|
console.log();
|
|
7851
7851
|
}
|
|
7852
7852
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -7897,8 +7897,8 @@ function showBanner() {
|
|
|
7897
7897
|
console.log(` ${DIM}$${RESET} ${TEXT}npx bfi skills search ${DIM}[query]${RESET}`);
|
|
7898
7898
|
console.log(` ${DIM}$${RESET} ${TEXT}npx bfi skills update${RESET}`);
|
|
7899
7899
|
console.log();
|
|
7900
|
-
console.log(
|
|
7901
|
-
console.log(
|
|
7900
|
+
console.log(`发现更多技能:${TEXT}https://skills.sh/${RESET}`);
|
|
7901
|
+
console.log(`以及 ${TEXT}https://skillhub.skillhub.woa.com/${RESET}`);
|
|
7902
7902
|
console.log();
|
|
7903
7903
|
}
|
|
7904
7904
|
function showHelp() {
|
|
@@ -7978,21 +7978,21 @@ function showRemoveHelp() {
|
|
|
7978
7978
|
console.log(`
|
|
7979
7979
|
${BOLD}Usage:${RESET} bfi skills remove [skills...] [options]
|
|
7980
7980
|
|
|
7981
|
-
${BOLD}
|
|
7981
|
+
${BOLD}说明:${RESET}
|
|
7982
7982
|
Remove installed skills from agents. If no skill names are provided,
|
|
7983
7983
|
an interactive selection menu will be shown.
|
|
7984
7984
|
|
|
7985
|
-
${BOLD}
|
|
7985
|
+
${BOLD}参数:${RESET}
|
|
7986
7986
|
skills Optional skill names to remove (space-separated)
|
|
7987
7987
|
|
|
7988
|
-
${BOLD}
|
|
7988
|
+
${BOLD}选项:${RESET}
|
|
7989
7989
|
-g, --global Remove from global scope (~/) instead of project scope
|
|
7990
7990
|
-a, --agent Remove from specific agents (use '*' for all agents)
|
|
7991
7991
|
-s, --skill Specify skills to remove (use '*' for all skills)
|
|
7992
7992
|
-y, --yes Skip confirmation prompts
|
|
7993
7993
|
--all Shorthand for --skill '*' --agent '*' -y
|
|
7994
7994
|
|
|
7995
|
-
${BOLD}
|
|
7995
|
+
${BOLD}示例:${RESET}
|
|
7996
7996
|
${DIM}$${RESET} bfi skills remove ${DIM}# interactive selection${RESET}
|
|
7997
7997
|
${DIM}$${RESET} bfi skills remove my-skill ${DIM}# remove specific skill${RESET}
|
|
7998
7998
|
${DIM}$${RESET} bfi skills remove skill1 skill2 -y ${DIM}# remove multiple skills${RESET}
|
|
@@ -8013,7 +8013,7 @@ function runInit(args) {
|
|
|
8013
8013
|
const skillFile = join(skillDir, "SKILL.md");
|
|
8014
8014
|
const displayPath = hasName ? `${skillName}/SKILL.md` : "SKILL.md";
|
|
8015
8015
|
if (existsSync(skillFile)) {
|
|
8016
|
-
console.log(`${TEXT}
|
|
8016
|
+
console.log(`${TEXT}技能已存在:${DIM}${displayPath}${RESET}`);
|
|
8017
8017
|
return;
|
|
8018
8018
|
}
|
|
8019
8019
|
if (hasName) mkdirSync(skillDir, { recursive: true });
|
|
@@ -8036,16 +8036,16 @@ Describe when this skill should be used.
|
|
|
8036
8036
|
2. Second step
|
|
8037
8037
|
3. Additional steps as needed
|
|
8038
8038
|
`);
|
|
8039
|
-
console.log(`${TEXT}
|
|
8039
|
+
console.log(`${TEXT}已初始化技能:${DIM}${skillName}${RESET}`);
|
|
8040
8040
|
console.log();
|
|
8041
|
-
console.log(`${DIM}
|
|
8041
|
+
console.log(`${DIM}已创建:${RESET}`);
|
|
8042
8042
|
console.log(` ${displayPath}`);
|
|
8043
8043
|
console.log();
|
|
8044
|
-
console.log(`${DIM}
|
|
8044
|
+
console.log(`${DIM}下一步:${RESET}`);
|
|
8045
8045
|
console.log(` 1. Edit ${TEXT}${displayPath}${RESET} to define your skill instructions`);
|
|
8046
8046
|
console.log(` 2. Update the ${TEXT}name${RESET} and ${TEXT}description${RESET} in the frontmatter`);
|
|
8047
8047
|
console.log();
|
|
8048
|
-
console.log(`${DIM}
|
|
8048
|
+
console.log(`${DIM}发布方式:${RESET}`);
|
|
8049
8049
|
console.log(` ${DIM}GitHub:${RESET} Push to a repo, then ${TEXT}npx bfi skills add <owner>/<repo>${RESET}`);
|
|
8050
8050
|
console.log(` ${DIM}URL:${RESET} Host the file, then ${TEXT}npx bfi skills add https://example.com/${displayPath}${RESET}`);
|
|
8051
8051
|
console.log();
|
|
@@ -8174,10 +8174,10 @@ async function dispatchSkillSubcommand(args, globalOpts) {
|
|
|
8174
8174
|
console.log(`${BOLD}Docs:${RESET}`);
|
|
8175
8175
|
console.log(` docs <cmd> Document management`);
|
|
8176
8176
|
console.log();
|
|
8177
|
-
console.log(
|
|
8177
|
+
console.log(`运行 ${BOLD}bfi --help${RESET} 查看更多详情。`);
|
|
8178
8178
|
} else {
|
|
8179
|
-
console.log(
|
|
8180
|
-
console.log(
|
|
8179
|
+
console.log(`未知技能命令:${sub}`);
|
|
8180
|
+
console.log(`运行 ${BOLD}bfi skills --help${RESET} 查看用法。`);
|
|
8181
8181
|
}
|
|
8182
8182
|
}
|
|
8183
8183
|
}
|
|
@@ -8308,8 +8308,8 @@ async function main() {
|
|
|
8308
8308
|
console.log(VERSION);
|
|
8309
8309
|
break;
|
|
8310
8310
|
default:
|
|
8311
|
-
console.log(
|
|
8312
|
-
console.log(
|
|
8311
|
+
console.log(`未知命令:${command}`);
|
|
8312
|
+
console.log(`运行 ${BOLD}bfi --help${RESET} 查看用法。`);
|
|
8313
8313
|
}
|
|
8314
8314
|
}
|
|
8315
8315
|
main().finally(() => process.exit(process.exitCode ?? 0));
|