bfi-cli 0.1.99 → 0.1.101
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/README.md +117 -5
- package/dist/THIRD-PARTY-LICENSES.md.gz +0 -0
- package/dist/_chunks/agents.mjs +1 -1
- package/dist/_chunks/agents2.mjs +4 -1
- package/dist/_chunks/client.mjs +107 -0
- package/dist/_chunks/command.mjs +697 -0
- package/dist/_chunks/digest.mjs +132 -0
- package/dist/_chunks/files.mjs +89 -0
- package/dist/_chunks/{registry-client.mjs → intent.mjs} +163 -13
- package/dist/_chunks/libs/@clack/core.mjs +63 -58
- package/dist/_chunks/libs/@clack/prompts.mjs +46 -45
- package/dist/_chunks/libs/@kwsites/file-exists.mjs +10 -9
- package/dist/_chunks/libs/simple-git.mjs +4 -2
- package/dist/_chunks/manager.mjs +436 -0
- package/dist/_chunks/mcp.mjs +559 -0
- package/dist/_chunks/model.mjs +124 -0
- package/dist/_chunks/ownership.mjs +7 -0
- package/dist/_chunks/package-plugin.mjs +473 -36
- package/dist/_chunks/receipt.mjs +166 -0
- package/dist/_chunks/rolldown-runtime.mjs +1 -1
- package/dist/_chunks/skills.mjs +6 -3
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +254 -221
- package/dist/mcp-codesearch/main.d.mts +1 -1
- package/dist/mcp-db/main.d.mts +1 -1
- package/dist/mcp-weknora/main.d.mts +1 -1
- package/package.json +4 -2
- package/dist/THIRD-PARTY-LICENSES.md +0 -293
package/dist/cli.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { isCancel } from "./_chunks/libs/@clack/core.mjs";
|
|
|
4
4
|
import { cancel, confirm, groupMultiselect, intro, log, multiselect as multiselect$1, note, outro, select, spinner } from "./_chunks/libs/@clack/prompts.mjs";
|
|
5
5
|
import { require_picocolors } from "./_chunks/libs/picocolors.mjs";
|
|
6
6
|
import { addSkillToLocalLock, addSkillToLock, computeSkillFolderHash, discoverSkills, dismissPrompt, filterSkills, getAllLockedSkills, getGitHubToken, getLastSelectedAgents, getSkillDisplayName, getSkillFromLock, isPromptDismissed, parseFrontmatter, parseSkillMd, readLocalLock, readSkillLock, removeSkillFromLock, sanitizeMetadata, saveSelectedAgents, stripTerminalEscapes } from "./_chunks/skills.mjs";
|
|
7
|
-
import { PluginRegistryClient } from "./_chunks/
|
|
7
|
+
import { PluginRegistryClient, parsePackageIntent } from "./_chunks/intent.mjs";
|
|
8
8
|
import { loadGlobalConfig, loadLockfile, loadProjectConfig, resolveConfig, saveGlobalConfig, saveLockfile, setConfigValue } from "./_chunks/config.mjs";
|
|
9
9
|
import { esm_default } from "./_chunks/libs/simple-git.mjs";
|
|
10
10
|
import { EVE_SUBAGENTS_DIR, agents, detectInstalledAgents, getEveSubagents, getNonUniversalAgents, getUniversalAgents, getVisibleUniversalAgents, isUniversalAgent } from "./_chunks/agents.mjs";
|
|
@@ -451,8 +451,10 @@ async function searchMultiselect(options) {
|
|
|
451
451
|
}
|
|
452
452
|
if (key.name === "space") {
|
|
453
453
|
const item = filtered[cursor];
|
|
454
|
-
if (item)
|
|
455
|
-
|
|
454
|
+
if (item) {
|
|
455
|
+
if (selected.has(item.value)) selected.delete(item.value);
|
|
456
|
+
else selected.add(item.value);
|
|
457
|
+
}
|
|
456
458
|
render();
|
|
457
459
|
return;
|
|
458
460
|
}
|
|
@@ -473,6 +475,46 @@ async function searchMultiselect(options) {
|
|
|
473
475
|
render();
|
|
474
476
|
});
|
|
475
477
|
}
|
|
478
|
+
function getCapabilities(version) {
|
|
479
|
+
return {
|
|
480
|
+
schemaVersion: 1,
|
|
481
|
+
version,
|
|
482
|
+
capabilities: [
|
|
483
|
+
"skill-install-v1",
|
|
484
|
+
"content-plan-v1",
|
|
485
|
+
"collection-bundle-v1",
|
|
486
|
+
"collection-mcp-v1",
|
|
487
|
+
"scope-selection-v1",
|
|
488
|
+
"plugin-plan-v1",
|
|
489
|
+
"plugin-export-v1",
|
|
490
|
+
"plugin-handoff-v1"
|
|
491
|
+
]
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function installationArgumentError(args) {
|
|
495
|
+
const command = ["skills", "skill"].includes(args[0] ?? "") ? args.slice(1) : args;
|
|
496
|
+
const isPackageInstall = ["package", "pkg"].includes(command[0] ?? "") && ["install", "i"].includes(command[1] ?? "");
|
|
497
|
+
if (!isPackageInstall && ![
|
|
498
|
+
"add",
|
|
499
|
+
"a",
|
|
500
|
+
"i",
|
|
501
|
+
"install"
|
|
502
|
+
].includes(command[0] ?? "")) return;
|
|
503
|
+
if (isPackageInstall) try {
|
|
504
|
+
if (parsePackageIntent(command.slice(1)).mode === "plugin") return;
|
|
505
|
+
} catch {
|
|
506
|
+
return "安装参数或模式无效;插件参数必须使用明确的 --as plugin,尚未支持的技能参数不会执行。";
|
|
507
|
+
}
|
|
508
|
+
const reserved = [
|
|
509
|
+
"--content-plan",
|
|
510
|
+
"--scope",
|
|
511
|
+
"--from-archive",
|
|
512
|
+
"--input-env",
|
|
513
|
+
"--skills-only"
|
|
514
|
+
];
|
|
515
|
+
const found = command.find((argument) => reserved.includes(argument.split("=")[0]));
|
|
516
|
+
if (found) return `当前命令不支持 ${found.split("=")[0]};${found.split("=")[0]} 仅用于技能组合完整安装(bfi skills package install)。现有安装不会静默忽略此参数。`;
|
|
517
|
+
}
|
|
476
518
|
var api_exports = /* @__PURE__ */ __exportAll({ SkillHubAPI: () => SkillHubAPI });
|
|
477
519
|
var SkillHubAPI = class {
|
|
478
520
|
registry;
|
|
@@ -512,12 +554,14 @@ var SkillHubAPI = class {
|
|
|
512
554
|
if (url.protocol === "https:") requestOptions.rejectUnauthorized = this.rejectUnauthorized;
|
|
513
555
|
let bodyStr;
|
|
514
556
|
let bodyBuf;
|
|
515
|
-
if (options.body !== void 0)
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
557
|
+
if (options.body !== void 0) {
|
|
558
|
+
if (options.body instanceof Buffer) bodyBuf = options.body;
|
|
559
|
+
else if (typeof options.body === "string") bodyStr = options.body;
|
|
560
|
+
else if (typeof FormData !== "undefined" && options.body instanceof FormData) return this.fetchRequest(url, requestOptions, options.body);
|
|
561
|
+
else {
|
|
562
|
+
requestOptions.headers["Content-Type"] = "application/json";
|
|
563
|
+
bodyStr = JSON.stringify(options.body);
|
|
564
|
+
}
|
|
521
565
|
}
|
|
522
566
|
return new Promise((resolve, reject) => {
|
|
523
567
|
const req = (url.protocol === "https:" ? https : http).request(url, requestOptions, (res) => {
|
|
@@ -674,7 +718,7 @@ var SkillHubAPI = class {
|
|
|
674
718
|
return body.data || body;
|
|
675
719
|
}
|
|
676
720
|
async getPackage(namespace, slug) {
|
|
677
|
-
const body = (await this.request("GET", `/namespaces/${namespace}/packages/${slug}
|
|
721
|
+
const body = (await this.request("GET", `/namespaces/${namespace}/packages/${slug}`, { headers: { "X-BFI-Capabilities": getCapabilities("").capabilities.join(",") } })).body;
|
|
678
722
|
return body.data || body;
|
|
679
723
|
}
|
|
680
724
|
async listComponentFiles(namespace, slug, componentId) {
|
|
@@ -1301,10 +1345,12 @@ async function isDirEntryOrSymlinkToDir(entry, entryPath) {
|
|
|
1301
1345
|
}
|
|
1302
1346
|
}
|
|
1303
1347
|
function getCanonicalSkillsDir(global, cwd) {
|
|
1304
|
-
|
|
1348
|
+
const baseDir = global ? homedir() : cwd || process.cwd();
|
|
1349
|
+
return join(baseDir, AGENTS_DIR, SKILLS_SUBDIR);
|
|
1305
1350
|
}
|
|
1306
1351
|
function getEveSubagentSkillsDir(subagent, cwd) {
|
|
1307
|
-
|
|
1352
|
+
const baseDir = cwd || process.cwd();
|
|
1353
|
+
return join(baseDir, EVE_SUBAGENTS_DIR, sanitizeName(subagent), "skills");
|
|
1308
1354
|
}
|
|
1309
1355
|
function getAgentBaseDir(agentType, global, cwd, eveSubagent) {
|
|
1310
1356
|
if (isUniversalAgent(agentType)) return getCanonicalSkillsDir(global, cwd);
|
|
@@ -1382,7 +1428,8 @@ async function resolveParentSymlinks(path) {
|
|
|
1382
1428
|
const dir = dirname(resolved);
|
|
1383
1429
|
const base = basename(resolved);
|
|
1384
1430
|
try {
|
|
1385
|
-
|
|
1431
|
+
const realDir = await realpath(dir);
|
|
1432
|
+
return join(realDir, base);
|
|
1386
1433
|
} catch {
|
|
1387
1434
|
return resolved;
|
|
1388
1435
|
}
|
|
@@ -1406,7 +1453,8 @@ async function createSymlink(target, linkPath) {
|
|
|
1406
1453
|
}
|
|
1407
1454
|
const linkDir = dirname(linkPath);
|
|
1408
1455
|
await mkdir(linkDir, { recursive: true });
|
|
1409
|
-
const
|
|
1456
|
+
const realLinkDir = await resolveParentSymlinks(linkDir);
|
|
1457
|
+
const relativePath = relative(realLinkDir, target);
|
|
1410
1458
|
const symlinkType = platform() === "win32" ? "junction" : void 0;
|
|
1411
1459
|
await symlink(symlinkType === "junction" ? resolvedTarget : relativePath, linkPath, symlinkType);
|
|
1412
1460
|
return true;
|
|
@@ -1431,6 +1479,8 @@ async function installSkillForAgent(skill, agentType, options = {}) {
|
|
|
1431
1479
|
const canonicalDir = join(canonicalBase, skillName);
|
|
1432
1480
|
const agentBase = getAgentBaseDir(agentType, isGlobal, cwd, eveSubagent);
|
|
1433
1481
|
const agentDir = join(agentBase, skillName);
|
|
1482
|
+
const { assertLegacyUnmanaged } = await import("./_chunks/ownership.mjs");
|
|
1483
|
+
await assertLegacyUnmanaged([canonicalDir, agentDir]);
|
|
1434
1484
|
if (!isPathSafe$1(canonicalBase, canonicalDir)) return {
|
|
1435
1485
|
success: false,
|
|
1436
1486
|
path: agentDir,
|
|
@@ -1475,7 +1525,8 @@ async function installSkillForAgent(skill, agentType, options = {}) {
|
|
|
1475
1525
|
mode: "symlink"
|
|
1476
1526
|
};
|
|
1477
1527
|
if (!isGlobal && !isUniversalAgent(agentType)) {
|
|
1478
|
-
|
|
1528
|
+
const agentRootDir = join(cwd, agents[agentType].skillsDir.split("/")[0]);
|
|
1529
|
+
if (!existsSync(agentRootDir) && agentType !== "claude-code") return {
|
|
1479
1530
|
success: true,
|
|
1480
1531
|
path: canonicalDir,
|
|
1481
1532
|
canonicalPath: canonicalDir,
|
|
@@ -1549,7 +1600,8 @@ async function copyDirectory(src, dest, agentType) {
|
|
|
1549
1600
|
dereference: true,
|
|
1550
1601
|
recursive: true
|
|
1551
1602
|
});
|
|
1552
|
-
|
|
1603
|
+
const sourceStats = await stat(srcPath);
|
|
1604
|
+
await chmod(destPath, sourceStats.mode & 511);
|
|
1553
1605
|
} catch (err) {
|
|
1554
1606
|
if (err instanceof Error && "code" in err && err.code === "ENOENT" && entry.isSymbolicLink()) console.warn(`Skipping broken symlink: ${srcPath}`);
|
|
1555
1607
|
else throw err;
|
|
@@ -1766,7 +1818,8 @@ async function installBlobSkillForAgent(skill, agentType, options = {}) {
|
|
|
1766
1818
|
mode: "symlink"
|
|
1767
1819
|
};
|
|
1768
1820
|
if (!isGlobal && !isUniversalAgent(agentType)) {
|
|
1769
|
-
|
|
1821
|
+
const agentRootDir = join(cwd, agents[agentType].skillsDir.split("/")[0]);
|
|
1822
|
+
if (!existsSync(agentRootDir)) return {
|
|
1770
1823
|
success: true,
|
|
1771
1824
|
path: canonicalDir,
|
|
1772
1825
|
canonicalPath: canonicalDir,
|
|
@@ -1994,7 +2047,7 @@ var ProviderRegistryImpl = class {
|
|
|
1994
2047
|
};
|
|
1995
2048
|
new ProviderRegistryImpl();
|
|
1996
2049
|
const DISCOVERY_SCHEMA_V2 = "https://schemas.agentskills.io/discovery/0.2.0/schema.json";
|
|
1997
|
-
const MAX_ARCHIVE_UNPACKED_BYTES =
|
|
2050
|
+
const MAX_ARCHIVE_UNPACKED_BYTES = 52428800;
|
|
1998
2051
|
const MAX_ARCHIVE_FILES = 1e3;
|
|
1999
2052
|
var WellKnownProvider = class {
|
|
2000
2053
|
id = "well-known";
|
|
@@ -3147,22 +3200,23 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
3147
3200
|
const installedAgents = await detectInstalledAgents();
|
|
3148
3201
|
const totalAgents = Object.keys(agents).length;
|
|
3149
3202
|
spinner.stop(`${totalAgents} agents`);
|
|
3150
|
-
if (installedAgents.length === 0)
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3203
|
+
if (installedAgents.length === 0) {
|
|
3204
|
+
if (options.yes) {
|
|
3205
|
+
targetAgents = validAgents;
|
|
3206
|
+
log.info("正在安装到全部 Agent");
|
|
3207
|
+
} else {
|
|
3208
|
+
log.info("请选择要安装技能的 Agent");
|
|
3209
|
+
const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).map(([key, config]) => ({
|
|
3210
|
+
value: key,
|
|
3211
|
+
label: config.displayName
|
|
3212
|
+
})));
|
|
3213
|
+
if (isCancel(selected)) {
|
|
3214
|
+
cancel("安装已取消");
|
|
3215
|
+
process.exit(0);
|
|
3216
|
+
}
|
|
3217
|
+
targetAgents = selected;
|
|
3162
3218
|
}
|
|
3163
|
-
|
|
3164
|
-
}
|
|
3165
|
-
else if (installedAgents.length === 1 || options.yes) {
|
|
3219
|
+
} else if (installedAgents.length === 1 || options.yes) {
|
|
3166
3220
|
targetAgents = ensureUniversalAgents(installedAgents);
|
|
3167
3221
|
if (installedAgents.length === 1) {
|
|
3168
3222
|
const firstAgent = installedAgents[0];
|
|
@@ -3397,13 +3451,14 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
3397
3451
|
slug = hit.slug;
|
|
3398
3452
|
log.info(`自动选择:${import_picocolors.default.cyan(`@${namespace}/${slug}`)} — ${hit.description || hit.name}`);
|
|
3399
3453
|
} else {
|
|
3454
|
+
const choices = hits.map((h, idx) => ({
|
|
3455
|
+
value: idx,
|
|
3456
|
+
label: `@${h.namespace}/${h.slug}`,
|
|
3457
|
+
hint: h.description || h.name
|
|
3458
|
+
}));
|
|
3400
3459
|
const idx = await select({
|
|
3401
3460
|
message: "匹配到多个技能 — 请选择一个",
|
|
3402
|
-
options:
|
|
3403
|
-
value: idx,
|
|
3404
|
-
label: `@${h.namespace}/${h.slug}`,
|
|
3405
|
-
hint: h.description || h.name
|
|
3406
|
-
}))
|
|
3461
|
+
options: choices
|
|
3407
3462
|
});
|
|
3408
3463
|
if (isCancel(idx)) {
|
|
3409
3464
|
cancel("安装已取消");
|
|
@@ -3430,7 +3485,8 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
3430
3485
|
}
|
|
3431
3486
|
const meta = metadata;
|
|
3432
3487
|
spinner.stop(`Skill: ${import_picocolors.default.cyan(`@${namespace}/${slug}`)}${meta.description ? ` — ${import_picocolors.default.dim(meta.description)}` : ""}`);
|
|
3433
|
-
|
|
3488
|
+
const tmpRoot = tmpdir();
|
|
3489
|
+
tempDir = join(tmpRoot, `.skillhub-skillshub-${canonicalSlug.replace(/[/:@]/g, "-")}-${Date.now()}`);
|
|
3434
3490
|
mkdirSync(tempDir, { recursive: true });
|
|
3435
3491
|
const zipPath = join(tempDir, "skill.zip");
|
|
3436
3492
|
spinner.start("正在下载技能...");
|
|
@@ -3766,23 +3822,24 @@ async function runAdd(args, options = {}) {
|
|
|
3766
3822
|
}
|
|
3767
3823
|
targetAgents = selected;
|
|
3768
3824
|
}
|
|
3769
|
-
} else if (installedAgents.length === 0)
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3825
|
+
} else if (installedAgents.length === 0) {
|
|
3826
|
+
if (options.yes) {
|
|
3827
|
+
targetAgents = validAgents;
|
|
3828
|
+
log.info("正在安装到全部 Agent");
|
|
3829
|
+
} else {
|
|
3830
|
+
log.info("请选择要安装技能的 Agent");
|
|
3831
|
+
const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).filter(([key]) => key !== "eve").map(([key, config]) => ({
|
|
3832
|
+
value: key,
|
|
3833
|
+
label: config.displayName
|
|
3834
|
+
})));
|
|
3835
|
+
if (isCancel(selected)) {
|
|
3836
|
+
cancel("安装已取消");
|
|
3837
|
+
await cleanup(tempDir);
|
|
3838
|
+
process.exit(0);
|
|
3839
|
+
}
|
|
3840
|
+
targetAgents = selected;
|
|
3782
3841
|
}
|
|
3783
|
-
|
|
3784
|
-
}
|
|
3785
|
-
else if (installedAgents.length === 1 || options.yes) {
|
|
3842
|
+
} else if (installedAgents.length === 1 || options.yes) {
|
|
3786
3843
|
targetAgents = ensureUniversalAgents(installedAgents);
|
|
3787
3844
|
if (installedAgents.length === 1) {
|
|
3788
3845
|
const firstAgent = installedAgents[0];
|
|
@@ -3804,17 +3861,18 @@ async function runAdd(args, options = {}) {
|
|
|
3804
3861
|
const availableSubagents = getEveSubagents(process.cwd());
|
|
3805
3862
|
if (options.subagent && options.subagent.length > 0) eveSubagentTargets = options.subagent.map((s) => s === "root" || s === "." ? void 0 : s);
|
|
3806
3863
|
else if (availableSubagents.length > 0 && !options.yes) {
|
|
3864
|
+
const subagentChoices = [{
|
|
3865
|
+
value: "",
|
|
3866
|
+
label: "根 Agent",
|
|
3867
|
+
hint: "agent/skills"
|
|
3868
|
+
}, ...availableSubagents.map((name) => ({
|
|
3869
|
+
value: name,
|
|
3870
|
+
label: name,
|
|
3871
|
+
hint: `agent/subagents/${name}/skills`
|
|
3872
|
+
}))];
|
|
3807
3873
|
const selectedSubagents = await multiselect$1({
|
|
3808
3874
|
message: "Eve 技能安装位置?",
|
|
3809
|
-
options:
|
|
3810
|
-
value: "",
|
|
3811
|
-
label: "根 Agent",
|
|
3812
|
-
hint: "agent/skills"
|
|
3813
|
-
}, ...availableSubagents.map((name) => ({
|
|
3814
|
-
value: name,
|
|
3815
|
-
label: name,
|
|
3816
|
-
hint: `agent/subagents/${name}/skills`
|
|
3817
|
-
}))],
|
|
3875
|
+
options: subagentChoices,
|
|
3818
3876
|
initialValues: [""],
|
|
3819
3877
|
required: true
|
|
3820
3878
|
});
|
|
@@ -3992,9 +4050,11 @@ async function runAdd(args, options = {}) {
|
|
|
3992
4050
|
const normalizedSource = getOwnerRepo(parsed);
|
|
3993
4051
|
const lockSource = getLockSource(parsed.url, normalizedSource);
|
|
3994
4052
|
const projectLockSourceUrl = getProjectLockSourceUrl(parsed.type, parsed.url);
|
|
3995
|
-
if (normalizedSource)
|
|
3996
|
-
if (
|
|
3997
|
-
|
|
4053
|
+
if (normalizedSource) {
|
|
4054
|
+
if (parseOwnerRepo(normalizedSource)) {
|
|
4055
|
+
if (await repoPrivacyPromise === false) selectedSkills.map((s) => s.name).join(","), targetAgents.join(","), { ...installGlobally && { global: "1" } }, JSON.stringify(skillFiles), options.metadata;
|
|
4056
|
+
} else selectedSkills.map((s) => s.name).join(","), targetAgents.join(","), { ...installGlobally && { global: "1" } }, JSON.stringify(skillFiles), options.metadata;
|
|
4057
|
+
}
|
|
3998
4058
|
if (successful.length > 0 && installGlobally && (normalizedSource || parsed.type === "skillhub")) {
|
|
3999
4059
|
const successfulSkillNames = new Set(successful.map((r) => r.skill));
|
|
4000
4060
|
let cachedTree;
|
|
@@ -4011,7 +4071,8 @@ async function runAdd(args, options = {}) {
|
|
|
4011
4071
|
const hash = getSkillFolderHashFromTree(cachedTree, skillPathValue);
|
|
4012
4072
|
if (hash) skillFolderHash = hash;
|
|
4013
4073
|
} else if (skillPathValue && tempDir) {
|
|
4014
|
-
const
|
|
4074
|
+
const skillDir = join(tempDir, dirname(skillPathValue));
|
|
4075
|
+
const hash = await computeSkillFolderHash(skillDir);
|
|
4015
4076
|
if (hash) skillFolderHash = hash;
|
|
4016
4077
|
}
|
|
4017
4078
|
await addSkillToLock(skill.name, {
|
|
@@ -4055,11 +4116,13 @@ async function runAdd(args, options = {}) {
|
|
|
4055
4116
|
const skillResults = bySkill.get(r.skill) || [];
|
|
4056
4117
|
skillResults.push(r);
|
|
4057
4118
|
bySkill.set(r.skill, skillResults);
|
|
4058
|
-
if (skillResults.length === 1)
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4119
|
+
if (skillResults.length === 1) {
|
|
4120
|
+
if (r.pluginName) {
|
|
4121
|
+
const group = r.pluginName;
|
|
4122
|
+
if (!groupedResults[group]) groupedResults[group] = [];
|
|
4123
|
+
groupedResults[group].push(r);
|
|
4124
|
+
} else ungroupedResults.push(r);
|
|
4125
|
+
}
|
|
4063
4126
|
}
|
|
4064
4127
|
const skillCount = bySkill.size;
|
|
4065
4128
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
@@ -4709,6 +4772,14 @@ async function removeCommand(skillNames, options) {
|
|
|
4709
4772
|
targetAgents = Object.keys(agents);
|
|
4710
4773
|
spinner$2.stop(`Targeting ${targetAgents.length} potential agent(s)`);
|
|
4711
4774
|
}
|
|
4775
|
+
const { assertLegacyUnmanaged } = await import("./_chunks/ownership.mjs");
|
|
4776
|
+
await assertLegacyUnmanaged(selectedSkills.flatMap((skill) => [getCanonicalPath(skill, {
|
|
4777
|
+
global: isGlobal,
|
|
4778
|
+
cwd
|
|
4779
|
+
}), ...targetAgents.map((agent) => getInstallPath(skill, agent, {
|
|
4780
|
+
global: isGlobal,
|
|
4781
|
+
cwd
|
|
4782
|
+
}))]));
|
|
4712
4783
|
if (!options.yes) {
|
|
4713
4784
|
console.log();
|
|
4714
4785
|
log.info("要卸载的技能:");
|
|
@@ -4755,12 +4826,15 @@ async function removeCommand(skillNames, options) {
|
|
|
4755
4826
|
}
|
|
4756
4827
|
const remainingAgents = (await detectInstalledAgents()).filter((a) => !targetAgents.includes(a));
|
|
4757
4828
|
let isStillUsed = false;
|
|
4758
|
-
for (const agentKey of remainingAgents)
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4829
|
+
for (const agentKey of remainingAgents) {
|
|
4830
|
+
const path = getInstallPath(skillName, agentKey, {
|
|
4831
|
+
global: isGlobal,
|
|
4832
|
+
cwd
|
|
4833
|
+
});
|
|
4834
|
+
if (await lstat(path).catch(() => null)) {
|
|
4835
|
+
isStillUsed = true;
|
|
4836
|
+
break;
|
|
4837
|
+
}
|
|
4764
4838
|
}
|
|
4765
4839
|
if (!isStillUsed) await rm(canonicalPath, {
|
|
4766
4840
|
recursive: true,
|
|
@@ -4900,12 +4974,14 @@ function parseUpdateOptions(args) {
|
|
|
4900
4974
|
}
|
|
4901
4975
|
function hasProjectSkills(cwd) {
|
|
4902
4976
|
const dir = cwd || process.cwd();
|
|
4903
|
-
|
|
4977
|
+
const lockPath = join(dir, "skills-lock.json");
|
|
4978
|
+
if (existsSync(lockPath)) return true;
|
|
4904
4979
|
const skillsDir = join(dir, ".agents", "skills");
|
|
4905
4980
|
try {
|
|
4906
4981
|
const entries = readdirSync(skillsDir, { withFileTypes: true });
|
|
4907
4982
|
for (const entry of entries) if (entry.isDirectory()) {
|
|
4908
|
-
|
|
4983
|
+
const skillMd = join(skillsDir, entry.name, "SKILL.md");
|
|
4984
|
+
if (existsSync(skillMd)) return true;
|
|
4909
4985
|
}
|
|
4910
4986
|
} catch {}
|
|
4911
4987
|
return false;
|
|
@@ -5329,7 +5405,8 @@ async function updateProjectSkills(options = {}) {
|
|
|
5329
5405
|
try {
|
|
5330
5406
|
tempDir = await cloneRepo(sourceUrl, ref);
|
|
5331
5407
|
const discoveredPaths = (await discoverSkills(tempDir)).map((s) => {
|
|
5332
|
-
|
|
5408
|
+
const relPath = relative(tempDir, s.path);
|
|
5409
|
+
return join(relPath, "SKILL.md").split(sep).join("/");
|
|
5333
5410
|
});
|
|
5334
5411
|
deletedSkills = await checkAndPromptForDeletions(source, allLockedForSource, localLock.skills, false, options, discoveredPaths);
|
|
5335
5412
|
} catch (error) {
|
|
@@ -6300,8 +6377,8 @@ const DIM$5 = "\x1B[38;5;102m";
|
|
|
6300
6377
|
const TEXT$4 = "\x1B[38;5;145m";
|
|
6301
6378
|
function formatFileSize(bytes) {
|
|
6302
6379
|
if (bytes < 1024) return `${bytes} B`;
|
|
6303
|
-
if (bytes <
|
|
6304
|
-
return `${(bytes /
|
|
6380
|
+
if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
6381
|
+
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
6305
6382
|
}
|
|
6306
6383
|
async function runDocs(args, globalOpts) {
|
|
6307
6384
|
switch (args[0]) {
|
|
@@ -6565,7 +6642,8 @@ async function publishFromDir(positionalArgs, api, namespace, visibility) {
|
|
|
6565
6642
|
console.log("需要包含 frontmatter(name, description)的 SKILL.md 文件。");
|
|
6566
6643
|
process.exit(1);
|
|
6567
6644
|
}
|
|
6568
|
-
const
|
|
6645
|
+
const skillMdContent = fs.readFileSync(skillMdPath, "utf-8");
|
|
6646
|
+
const { data: frontmatter } = parseFrontmatter(skillMdContent);
|
|
6569
6647
|
const skillName = frontmatter.name || path$1.basename(resolvedDir);
|
|
6570
6648
|
console.log(`${DIM$4}正在从目录发布技能...${RESET$4}`);
|
|
6571
6649
|
console.log(` ${BOLD$2}名称:${RESET$4} ${TEXT$3}${skillName}${RESET$4}`);
|
|
@@ -6612,7 +6690,8 @@ async function publishFromZip(positionalArgs, api, namespace, visibility) {
|
|
|
6612
6690
|
}
|
|
6613
6691
|
const skillDir = path$1.dirname(skillMdPath);
|
|
6614
6692
|
console.log(` ${GREEN$3}在 ${path$1.relative(tmpDir, skillDir) || "."} 中找到 SKILL.md${RESET$4}`);
|
|
6615
|
-
const
|
|
6693
|
+
const skillMdContent = fs.readFileSync(skillMdPath, "utf-8");
|
|
6694
|
+
const { data: frontmatter } = parseFrontmatter(skillMdContent);
|
|
6616
6695
|
const skillName = frontmatter.name || path$1.basename(skillDir);
|
|
6617
6696
|
console.log(` ${BOLD$2}名称:${RESET$4} ${TEXT$3}${skillName}${RESET$4}`);
|
|
6618
6697
|
console.log(` ${BOLD$2}命名空间:${RESET$4} ${TEXT$3}${namespace}${RESET$4}`);
|
|
@@ -6793,8 +6872,8 @@ function findSkillMd(dir) {
|
|
|
6793
6872
|
}
|
|
6794
6873
|
function formatSize(bytes) {
|
|
6795
6874
|
if (bytes < 1024) return `${bytes} B`;
|
|
6796
|
-
if (bytes <
|
|
6797
|
-
return `${(bytes /
|
|
6875
|
+
if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
6876
|
+
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
6798
6877
|
}
|
|
6799
6878
|
function truncate(text, maxLen) {
|
|
6800
6879
|
if (text.length <= maxLen) return text;
|
|
@@ -6883,107 +6962,6 @@ function maybePrintAnalyticsNotice(env = process.env) {
|
|
|
6883
6962
|
console.log();
|
|
6884
6963
|
} catch {}
|
|
6885
6964
|
}
|
|
6886
|
-
const pluginTargets = [
|
|
6887
|
-
"claude-code",
|
|
6888
|
-
"codex",
|
|
6889
|
-
"zcode",
|
|
6890
|
-
"codebuddy",
|
|
6891
|
-
"qwen-code"
|
|
6892
|
-
];
|
|
6893
|
-
const isPluginArchive = (value) => /\.(zip|tgz|tar\.gz)$/iu.test(value);
|
|
6894
|
-
const isPluginVersion = (value) => /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u.test(value);
|
|
6895
|
-
function parsePackageIntent(args) {
|
|
6896
|
-
const output = [...args];
|
|
6897
|
-
let mode = "skills";
|
|
6898
|
-
const occurrences = args.filter((value) => value === "--as" || value.startsWith("--as="));
|
|
6899
|
-
if (occurrences.length) {
|
|
6900
|
-
const index = output.indexOf("--as");
|
|
6901
|
-
const requested = output[index + 1];
|
|
6902
|
-
if (occurrences.length !== 1 || index < 0 || !["skills", "plugin"].includes(requested ?? "")) throw new Error("Use --as skills or --as plugin exactly once; upgrade bfi if this option is unavailable");
|
|
6903
|
-
mode = requested;
|
|
6904
|
-
output.splice(index, 2);
|
|
6905
|
-
}
|
|
6906
|
-
if (mode === "skills" && (output.some((value) => [
|
|
6907
|
-
"--plan",
|
|
6908
|
-
"--export",
|
|
6909
|
-
"--scope",
|
|
6910
|
-
"--root",
|
|
6911
|
-
"--operation"
|
|
6912
|
-
].includes(value) || /^(--plan|--export|--scope|--root|--operation)=/u.test(value)) || isPluginArchive(output[1] ?? ""))) throw new Error("Plugin archives and plugin options require explicit --as plugin; no skills were installed");
|
|
6913
|
-
return {
|
|
6914
|
-
mode,
|
|
6915
|
-
args: output
|
|
6916
|
-
};
|
|
6917
|
-
}
|
|
6918
|
-
function parsePluginArguments(args) {
|
|
6919
|
-
const command = {
|
|
6920
|
-
install: "install",
|
|
6921
|
-
i: "install",
|
|
6922
|
-
update: "update",
|
|
6923
|
-
up: "update",
|
|
6924
|
-
uninstall: "uninstall",
|
|
6925
|
-
rm: "uninstall",
|
|
6926
|
-
list: "list",
|
|
6927
|
-
ls: "list"
|
|
6928
|
-
}[args[0] ?? ""];
|
|
6929
|
-
if (!command) throw new Error("Plugin intent supports install, update, uninstall and list");
|
|
6930
|
-
const result = {
|
|
6931
|
-
command,
|
|
6932
|
-
scope: "project",
|
|
6933
|
-
planOnly: false,
|
|
6934
|
-
json: false
|
|
6935
|
-
};
|
|
6936
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6937
|
-
const values = /* @__PURE__ */ new Set([
|
|
6938
|
-
"--agent",
|
|
6939
|
-
"--version",
|
|
6940
|
-
"--scope",
|
|
6941
|
-
"--root",
|
|
6942
|
-
"--export",
|
|
6943
|
-
"--operation",
|
|
6944
|
-
"--registry",
|
|
6945
|
-
"--token",
|
|
6946
|
-
"--namespace"
|
|
6947
|
-
]);
|
|
6948
|
-
for (let index = 1; index < args.length; index++) {
|
|
6949
|
-
const option = args[index];
|
|
6950
|
-
if (!option.startsWith("-")) {
|
|
6951
|
-
if (result.source) throw new Error("Specify exactly one plugin source");
|
|
6952
|
-
result.source = option;
|
|
6953
|
-
continue;
|
|
6954
|
-
}
|
|
6955
|
-
const flag = option === "-g" ? "--global" : option === "-y" ? "--yes" : option;
|
|
6956
|
-
if (seen.has(flag)) throw new Error(`Duplicate plugin option: ${flag}`);
|
|
6957
|
-
seen.add(flag);
|
|
6958
|
-
if (values.has(flag)) {
|
|
6959
|
-
const value = args[++index];
|
|
6960
|
-
if (value === void 0 || value.startsWith("-") || /[\u0000-\u001f\u007f]/u.test(value)) throw new Error(`Missing or invalid value for ${flag}`);
|
|
6961
|
-
if (flag === "--agent") {
|
|
6962
|
-
if (!pluginTargets.includes(value)) throw new Error("Unknown native plugin target");
|
|
6963
|
-
result.agent = value;
|
|
6964
|
-
} else if (flag === "--version") {
|
|
6965
|
-
if (!isPluginVersion(value)) throw new Error("Plugin version must be exact SemVer, not latest or a range");
|
|
6966
|
-
result.version = value;
|
|
6967
|
-
} else if (flag === "--scope") {
|
|
6968
|
-
if (!["project", "user"].includes(value)) throw new Error("Plugin scope must be project or user");
|
|
6969
|
-
result.scope = value;
|
|
6970
|
-
} else if (flag === "--root") result.root = value;
|
|
6971
|
-
else if (flag === "--export") result.exportPath = value;
|
|
6972
|
-
else if (flag === "--operation") result.operationId = value;
|
|
6973
|
-
} else if (flag === "--global") result.scope = "user";
|
|
6974
|
-
else if (flag === "--plan") result.planOnly = true;
|
|
6975
|
-
else if (flag === "--json") result.json = true;
|
|
6976
|
-
else if (flag !== "--yes") throw new Error(`Unknown plugin option: ${flag}; upgrade bfi if needed`);
|
|
6977
|
-
}
|
|
6978
|
-
if (seen.has("--scope") && seen.has("--global")) throw new Error("Use --scope or --global, not both");
|
|
6979
|
-
if (command !== "list" && !result.agent) throw new Error("Full plugin operations require an explicit --agent");
|
|
6980
|
-
if (command !== "list" && !result.source && !(command === "uninstall" && result.operationId)) throw new Error("Specify @namespace/package or a local zip/tgz path");
|
|
6981
|
-
if (result.source && !/^@[^/\s]+\/[^/\s]+$/u.test(result.source) && !isPluginArchive(result.source)) throw new Error("Use a namespace-qualified @namespace/package reference or local archive");
|
|
6982
|
-
if (result.planOnly && result.exportPath) throw new Error("Plan and export are separate operations");
|
|
6983
|
-
if (result.root !== void 0 && !isPluginArchive(result.source ?? "") || result.operationId && command !== "uninstall" || (result.exportPath || result.root !== void 0) && command !== "install") throw new Error("Plugin option is invalid for this operation");
|
|
6984
|
-
if (command === "list" && (result.source || result.version || result.planOnly || result.exportPath || result.operationId)) throw new Error("Invalid plugin list options");
|
|
6985
|
-
return result;
|
|
6986
|
-
}
|
|
6987
6965
|
var package_exports = /* @__PURE__ */ __exportAll({ runPackage: () => runPackage });
|
|
6988
6966
|
const RESET$3 = "\x1B[0m";
|
|
6989
6967
|
const BOLD$1 = "\x1B[1m";
|
|
@@ -7065,7 +7043,7 @@ function printPackageHelp() {
|
|
|
7065
7043
|
console.log(`${BOLD$1}选项:${RESET$3}`);
|
|
7066
7044
|
console.log(` --namespace <ns> 目标命名空间`);
|
|
7067
7045
|
console.log(` --agent <a> 目标 agent(如 claude-code、codex)`);
|
|
7068
|
-
console.log(` --as skills|plugin 默认 skills;完整插件必须显式 --as plugin
|
|
7046
|
+
console.log(` --as skills|plugin 默认 skills;完整插件必须显式 --as plugin,未指定 Agent/范围时交互选择`);
|
|
7069
7047
|
console.log(` --version <v> 插件固定版本;省略只解析显式 stable,不回退 latest`);
|
|
7070
7048
|
console.log(` --plan 插件模式只读计划,不写配置或安装记录`);
|
|
7071
7049
|
console.log(` --export <archive> 插件模式校验后导出原始制品,不安装、不覆盖文件`);
|
|
@@ -7079,15 +7057,28 @@ function printPackageHelp() {
|
|
|
7079
7057
|
console.log();
|
|
7080
7058
|
}
|
|
7081
7059
|
async function handleLocalList(args, globalOpts) {
|
|
7082
|
-
const
|
|
7060
|
+
const cwd = getWorkdir(globalOpts, args);
|
|
7061
|
+
const lock = loadLockfile(cwd);
|
|
7083
7062
|
args.includes("-g") || args.includes("--global");
|
|
7084
7063
|
const pkgs = lock.packages || {};
|
|
7085
7064
|
const entries = Object.entries(pkgs);
|
|
7086
|
-
|
|
7087
|
-
|
|
7065
|
+
const json = args.includes("--json");
|
|
7066
|
+
const { receipts } = await import("./_chunks/receipt.mjs");
|
|
7067
|
+
const installed = (await receipts()).filter((record) => record.plan.kind === "COLLECTION");
|
|
7068
|
+
if (json) {
|
|
7069
|
+
console.log(JSON.stringify([...Object.values(pkgs), ...installed.map((record) => ({
|
|
7070
|
+
ref: record.plan.ref,
|
|
7071
|
+
registry: record.plan.registry,
|
|
7072
|
+
state: record.state,
|
|
7073
|
+
operation: record.id,
|
|
7074
|
+
destination: record.destination,
|
|
7075
|
+
skills: record.plan.skills.length,
|
|
7076
|
+
mcps: record.plan.mcps.length
|
|
7077
|
+
}))], null, 2));
|
|
7088
7078
|
return;
|
|
7089
7079
|
}
|
|
7090
|
-
|
|
7080
|
+
for (const record of installed) console.log(`${record.plan.ref} · ${record.state} · ${record.destination.agents.join(", ")} · ${record.destination.scope} · ${record.plan.skills.length} 技能 + ${record.plan.mcps.length} MCP · ${record.id}`);
|
|
7081
|
+
if (entries.length === 0 && installed.length === 0) {
|
|
7091
7082
|
console.log("没有已安装的包。");
|
|
7092
7083
|
console.log(`使用 ${DIM$3}bfi skills package install <ref>${RESET$3} 安装包。`);
|
|
7093
7084
|
return;
|
|
@@ -7276,17 +7267,18 @@ async function handleInstall(args, api, globalOpts) {
|
|
|
7276
7267
|
if (targetAgents.includes("eve")) {
|
|
7277
7268
|
const availableSubagents = getEveSubagents(process.cwd());
|
|
7278
7269
|
if (availableSubagents.length > 0) {
|
|
7270
|
+
const subagentChoices = [{
|
|
7271
|
+
value: "",
|
|
7272
|
+
label: "根 Agent",
|
|
7273
|
+
hint: "agent/skills"
|
|
7274
|
+
}, ...availableSubagents.map((name) => ({
|
|
7275
|
+
value: name,
|
|
7276
|
+
label: name,
|
|
7277
|
+
hint: `agent/subagents/${name}/skills`
|
|
7278
|
+
}))];
|
|
7279
7279
|
const selectedSubagents = await multiselect$1({
|
|
7280
7280
|
message: "Eve 技能安装位置?",
|
|
7281
|
-
options:
|
|
7282
|
-
value: "",
|
|
7283
|
-
label: "根 Agent",
|
|
7284
|
-
hint: "agent/skills"
|
|
7285
|
-
}, ...availableSubagents.map((name) => ({
|
|
7286
|
-
value: name,
|
|
7287
|
-
label: name,
|
|
7288
|
-
hint: `agent/subagents/${name}/skills`
|
|
7289
|
-
}))],
|
|
7281
|
+
options: subagentChoices,
|
|
7290
7282
|
initialValues: [""],
|
|
7291
7283
|
required: true
|
|
7292
7284
|
});
|
|
@@ -7481,7 +7473,8 @@ async function handleUninstall(args, globalOpts) {
|
|
|
7481
7473
|
}
|
|
7482
7474
|
async function handleUpdate(args, api, globalOpts) {
|
|
7483
7475
|
const pkgRef = args[0];
|
|
7484
|
-
const
|
|
7476
|
+
const cwd = getWorkdir(globalOpts, args);
|
|
7477
|
+
const lock = loadLockfile(cwd);
|
|
7485
7478
|
let packagesToUpdate = [];
|
|
7486
7479
|
const pkgs = lock.packages || {};
|
|
7487
7480
|
if (pkgRef) {
|
|
@@ -8814,7 +8807,6 @@ async function runYmc(args, globalOpts) {
|
|
|
8814
8807
|
break;
|
|
8815
8808
|
}
|
|
8816
8809
|
default: {
|
|
8817
|
-
if (sub === "cases" || sub.startsWith("cases")) console.error("案例库已迁移 WeKnora:检索/归档改用 weknora-bfi MCP 工具(kb_search / kb_archive_case)。");
|
|
8818
8810
|
console.error(`未知子命令:${sub}`);
|
|
8819
8811
|
const hint = SUBCOMMAND_HINTS[sub];
|
|
8820
8812
|
if (hint) console.error(`提示:${hint}`);
|
|
@@ -8850,7 +8842,7 @@ const HELP = {
|
|
|
8850
8842
|
禁止 * | SELECT * WHERE 字段=... (WHERE 全扫描必超时)
|
|
8851
8843
|
-t <time> 时间简写 10m/2h/3d/4w(默认无时间=服务端超大窗兜底,会命中数天前记录,务必显式指定)
|
|
8852
8844
|
--start-time/--end-time 精确窗口 yyyy-MM-dd HH:mm:ss 北京时间(优先于 -t)
|
|
8853
|
-
--days N
|
|
8845
|
+
--days N 按天数回溯(等价 -t Nd)
|
|
8854
8846
|
--line N 返回行数上限
|
|
8855
8847
|
示例:
|
|
8856
8848
|
bfi ymc sls-raw 'traceid: abc | SELECT * LIMIT 200' -e daily -t 1d
|
|
@@ -8884,8 +8876,8 @@ const HELP = {
|
|
|
8884
8876
|
--app 服务维度过滤(裸 appCode)
|
|
8885
8877
|
--method 按调用方法过滤
|
|
8886
8878
|
--min-cost <ms> 最小耗时过滤(body.costTime=[ms, 999999])
|
|
8887
|
-
|
|
8888
|
-
|
|
8879
|
+
--profiler 透传上游 enableProfiler(仅返回有 CPU 采样记录的调用);
|
|
8880
|
+
该过滤器常返回空集,常规取证勿带,CPU 热点走 dump-list。
|
|
8889
8881
|
示例:
|
|
8890
8882
|
bfi ymc slowcall -t 1d --trace-id abc -e core3 # 链路分层分解(跨服务根因链必用)
|
|
8891
8883
|
bfi ymc slowcall -t 4w --app yonbip-scm-pu -e pre # 服务慢调用趋势`,
|
|
@@ -8910,12 +8902,6 @@ const HELP = {
|
|
|
8910
8902
|
--size N 返回条数(默认 100,最大 5000)`,
|
|
8911
8903
|
"dump-list": `bfi ymc dump-list -t <time> -e <env> [--app <appCode>] [--type profiler|heap|...] [--json]
|
|
8912
8904
|
诊断文件列表(火焰图/JVM dump;CPU 热点取数的正确入口)。`,
|
|
8913
|
-
cases: `bfi ymc cases <search|show|upload|index> [参数]
|
|
8914
|
-
KEDB 案例库(内部诊断先验第一源)。
|
|
8915
|
-
search [--type <t>] [--finger "<指纹>"] [--service <svc>] [--kw "<关键词>"] [--limit N]
|
|
8916
|
-
show <case_id>
|
|
8917
|
-
upload --file <报告.html> [--type slow-req] [--finger "词1,词2"] [--env] [--service]
|
|
8918
|
-
index 案例库索引重建`,
|
|
8919
8905
|
wiki: `bfi ymc wiki <search|show> [参数]
|
|
8920
8906
|
知识库统一检索(confluence + jira + 文库 ecfile 三源——诊断先验的外部源,勿只查其一)。
|
|
8921
8907
|
search "<关键词>" [--source confluence|jira|ecfile] [--limit N] [--titles]
|
|
@@ -8982,7 +8968,7 @@ bfi ymc — 观测查询(v2 API:YMC/Kibana/SLS/trace)
|
|
|
8982
8968
|
sls-grep "<关键词>" -e <env> SLS 全文检索聚合(异常历史分布取证)
|
|
8983
8969
|
slowsql -t <time> [-e] [--sql-str] [--md5] [--trace-id] [--app] [--no-profiler]
|
|
8984
8970
|
slowcall -t <time> [-e] [--trace-id] [--app] [--method] [--min-cost ms]
|
|
8985
|
-
[--profiler] # ⚠️
|
|
8971
|
+
[--profiler] # ⚠️ 采样过滤器常为空集,常规取证勿带
|
|
8986
8972
|
exceptions -t <time> [-e] [--app]
|
|
8987
8973
|
alerts -t <time> [-e] [--level error|warn|info]
|
|
8988
8974
|
url-stats </uri> -t <time> -e <env> [--app <service_name>]
|
|
@@ -8994,7 +8980,6 @@ bfi ymc — 观测查询(v2 API:YMC/Kibana/SLS/trace)
|
|
|
8994
8980
|
callstat / sqlstat 慢调用/慢SQL 统计版聚合
|
|
8995
8981
|
rca <...> 官方智能诊断 RCA(长耗时)
|
|
8996
8982
|
bpr-download <pk> BPR 报告下载
|
|
8997
|
-
cases <search|show|upload|index> 案例库(KEDB)
|
|
8998
8983
|
wiki search "<kw>" [--source] [--titles] 知识库统一检索(wiki/jira/文库)
|
|
8999
8984
|
wiki show <id> [--source] 知识条目全文
|
|
9000
8985
|
call <route> -e <env> [--data '<json>'] 通用透传(全部注册表端点)
|
|
@@ -9802,11 +9787,12 @@ ${BOLD}━━━ 技能包管理 ━━━${RESET}
|
|
|
9802
9787
|
skills package list [--namespace <ns>] 列出技能包
|
|
9803
9788
|
skills package info <ref> 查看包详情
|
|
9804
9789
|
skills package create <slug> [--name] [--description] 创建包
|
|
9805
|
-
skills package add <pkg> <skill...>
|
|
9806
|
-
skills package remove <pkg> <skill...>
|
|
9790
|
+
skills package add-skills <pkg> <skill...> 添加技能到包
|
|
9791
|
+
skills package remove-skills <pkg> <skill...> 从包移除技能
|
|
9807
9792
|
skills package install <ref> [--agent <a>] 安装技能组合(默认,不安装插件组件)
|
|
9808
9793
|
--as plugin 显式完整插件模式;支持本地 zip/tgz,不兼容时不会降级安装
|
|
9809
9794
|
--plan 只读校验安装计划;--export <archive> 仅导出,不安装
|
|
9795
|
+
--prepare-native <dir> 准备完整原生目录和市场索引,审阅后交给宿主安装;不注册、不转技能
|
|
9810
9796
|
--agent <a> 目标 agent(如 claude-code、codex、zcode)
|
|
9811
9797
|
--global 安装到主目录(跨项目可用)
|
|
9812
9798
|
|
|
@@ -9815,6 +9801,12 @@ ${BOLD}━━━ 文档 ━━━${RESET}
|
|
|
9815
9801
|
docs list 列出文档
|
|
9816
9802
|
docs info <id> 查看文档详情
|
|
9817
9803
|
|
|
9804
|
+
${BOLD}━━━ MCP ━━━${RESET}
|
|
9805
|
+
mcp search / info 查询独立 MCP 市场
|
|
9806
|
+
mcp install <name...> --agent <agent> 保留已有配置,安装选定 MCP
|
|
9807
|
+
mcp list / remove / test --agent <agent> 管理或验证 MCP
|
|
9808
|
+
mcp --help 参数、支持范围与安全说明
|
|
9809
|
+
|
|
9818
9810
|
${BOLD}━━━ 观测查询(ymc)━━━${RESET}
|
|
9819
9811
|
ymc status 登录会话状态
|
|
9820
9812
|
ymc trace <trace_id> -e <env> traceId 三源合一(SLS+链路+ingress)
|
|
@@ -9831,6 +9823,7 @@ ${BOLD}━━━ DB 取证辅助(db)━━━${RESET}
|
|
|
9831
9823
|
ytenant_id 条件且分库未知时,先定位再连)
|
|
9832
9824
|
|
|
9833
9825
|
${BOLD}━━━ 配置 ━━━${RESET}
|
|
9826
|
+
capabilities --json 只读查询此构建已实现的安装能力(不联网、不修改配置)
|
|
9834
9827
|
config get [key] 查看配置
|
|
9835
9828
|
config set <key> <value> [--global] 设置配置
|
|
9836
9829
|
|
|
@@ -9901,7 +9894,7 @@ function runInit(args) {
|
|
|
9901
9894
|
return;
|
|
9902
9895
|
}
|
|
9903
9896
|
if (hasName) mkdirSync(skillDir, { recursive: true });
|
|
9904
|
-
|
|
9897
|
+
const skillContent = `---
|
|
9905
9898
|
name: ${skillName}
|
|
9906
9899
|
description: A brief description of what this skill does
|
|
9907
9900
|
---
|
|
@@ -9919,7 +9912,8 @@ Describe when this skill should be used.
|
|
|
9919
9912
|
1. First step
|
|
9920
9913
|
2. Second step
|
|
9921
9914
|
3. Additional steps as needed
|
|
9922
|
-
|
|
9915
|
+
`;
|
|
9916
|
+
writeFileSync(skillFile, skillContent);
|
|
9923
9917
|
console.log(`${TEXT}已初始化技能:${DIM}${skillName}${RESET}`);
|
|
9924
9918
|
console.log();
|
|
9925
9919
|
console.log(`${DIM}已创建:${RESET}`);
|
|
@@ -10077,6 +10071,45 @@ async function main() {
|
|
|
10077
10071
|
}
|
|
10078
10072
|
const command = args[0];
|
|
10079
10073
|
const restArgs = args.slice(1);
|
|
10074
|
+
if (command === "capabilities") {
|
|
10075
|
+
if (restArgs.some((argument) => argument !== "--json")) {
|
|
10076
|
+
console.error("用法:bfi capabilities [--json]");
|
|
10077
|
+
process.exitCode = 1;
|
|
10078
|
+
return;
|
|
10079
|
+
}
|
|
10080
|
+
console.log(JSON.stringify(getCapabilities(VERSION), null, 2));
|
|
10081
|
+
return;
|
|
10082
|
+
}
|
|
10083
|
+
const { dispatchInstallation } = await import("./_chunks/command.mjs");
|
|
10084
|
+
if (await dispatchInstallation(args)) return;
|
|
10085
|
+
const installationError = installationArgumentError(args);
|
|
10086
|
+
if (installationError) {
|
|
10087
|
+
console.error(installationError);
|
|
10088
|
+
process.exitCode = 1;
|
|
10089
|
+
return;
|
|
10090
|
+
}
|
|
10091
|
+
if (command === "mcp") {
|
|
10092
|
+
const { runMcp } = await import("./_chunks/mcp.mjs");
|
|
10093
|
+
await runMcp(restArgs);
|
|
10094
|
+
return;
|
|
10095
|
+
}
|
|
10096
|
+
const packageRoute = ["skills", "skill"].includes(command) ? restArgs : args;
|
|
10097
|
+
if (["package", "pkg"].includes(packageRoute[0] ?? "") && packageRoute.some((argument) => argument === "--as" || argument.startsWith("--as="))) {
|
|
10098
|
+
const intent = parsePackageIntent(packageRoute.slice(1));
|
|
10099
|
+
if (intent.mode === "plugin") {
|
|
10100
|
+
const pluginOpts = {
|
|
10101
|
+
workdir: process.cwd(),
|
|
10102
|
+
version: VERSION
|
|
10103
|
+
};
|
|
10104
|
+
for (const name of ["registry", "token"]) {
|
|
10105
|
+
const index = args.indexOf(`--${name}`);
|
|
10106
|
+
if (index >= 0) pluginOpts[name] = args[index + 1];
|
|
10107
|
+
}
|
|
10108
|
+
const { runPluginPackage } = await import("./_chunks/package-plugin.mjs");
|
|
10109
|
+
await runPluginPackage(intent.args, pluginOpts);
|
|
10110
|
+
return;
|
|
10111
|
+
}
|
|
10112
|
+
}
|
|
10080
10113
|
try {
|
|
10081
10114
|
const { maybePrintAnalyticsNotice } = await Promise.resolve().then(() => analytics_exports);
|
|
10082
10115
|
maybePrintAnalyticsNotice();
|
|
@@ -10228,4 +10261,4 @@ main().catch((e) => {
|
|
|
10228
10261
|
console.error(`✗ ${e?.message || e}`);
|
|
10229
10262
|
process.exit(1);
|
|
10230
10263
|
});
|
|
10231
|
-
export {
|
|
10264
|
+
export { SkillHubAPI, getAgentBaseDir };
|