bfi-cli 0.1.97 → 0.1.99
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/THIRD-PARTY-LICENSES.md +293 -0
- package/dist/_chunks/libs/@clack/core.mjs +58 -63
- package/dist/_chunks/libs/@clack/prompts.mjs +45 -46
- package/dist/_chunks/libs/@kwsites/file-exists.mjs +9 -10
- package/dist/_chunks/libs/simple-git.mjs +2 -4
- package/dist/_chunks/rolldown-runtime.mjs +1 -1
- package/dist/_chunks/skills.mjs +3 -6
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +164 -144
- package/dist/mcp-codesearch/main.d.mts +1 -1
- package/dist/mcp-codesearch/main.mjs +2 -0
- package/dist/mcp-db/main.d.mts +1 -1
- package/dist/mcp-db/main.mjs +12 -2
- package/dist/mcp-weknora/main.d.mts +1 -1
- package/dist/mcp-weknora/main.mjs +2 -0
- package/package.json +4 -2
- package/dist/THIRD-PARTY-LICENSES.md.gz +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -451,10 +451,8 @@ async function searchMultiselect(options) {
|
|
|
451
451
|
}
|
|
452
452
|
if (key.name === "space") {
|
|
453
453
|
const item = filtered[cursor];
|
|
454
|
-
if (item)
|
|
455
|
-
|
|
456
|
-
else selected.add(item.value);
|
|
457
|
-
}
|
|
454
|
+
if (item) if (selected.has(item.value)) selected.delete(item.value);
|
|
455
|
+
else selected.add(item.value);
|
|
458
456
|
render();
|
|
459
457
|
return;
|
|
460
458
|
}
|
|
@@ -514,14 +512,12 @@ var SkillHubAPI = class {
|
|
|
514
512
|
if (url.protocol === "https:") requestOptions.rejectUnauthorized = this.rejectUnauthorized;
|
|
515
513
|
let bodyStr;
|
|
516
514
|
let bodyBuf;
|
|
517
|
-
if (options.body !== void 0)
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
bodyStr = JSON.stringify(options.body);
|
|
524
|
-
}
|
|
515
|
+
if (options.body !== void 0) if (options.body instanceof Buffer) bodyBuf = options.body;
|
|
516
|
+
else if (typeof options.body === "string") bodyStr = options.body;
|
|
517
|
+
else if (typeof FormData !== "undefined" && options.body instanceof FormData) return this.fetchRequest(url, requestOptions, options.body);
|
|
518
|
+
else {
|
|
519
|
+
requestOptions.headers["Content-Type"] = "application/json";
|
|
520
|
+
bodyStr = JSON.stringify(options.body);
|
|
525
521
|
}
|
|
526
522
|
return new Promise((resolve, reject) => {
|
|
527
523
|
const req = (url.protocol === "https:" ? https : http).request(url, requestOptions, (res) => {
|
|
@@ -870,7 +866,12 @@ var SkillHubAPI = class {
|
|
|
870
866
|
try {
|
|
871
867
|
const parsed = JSON.parse(data);
|
|
872
868
|
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) resolve(parsed);
|
|
873
|
-
else
|
|
869
|
+
else {
|
|
870
|
+
const error = new Error(parsed.msg || parsed.message || `HTTP ${res.statusCode}`);
|
|
871
|
+
error.status = res.statusCode;
|
|
872
|
+
error.body = parsed;
|
|
873
|
+
reject(error);
|
|
874
|
+
}
|
|
874
875
|
} catch {
|
|
875
876
|
reject(new Error(data || `HTTP ${res.statusCode}`));
|
|
876
877
|
}
|
|
@@ -1300,12 +1301,10 @@ async function isDirEntryOrSymlinkToDir(entry, entryPath) {
|
|
|
1300
1301
|
}
|
|
1301
1302
|
}
|
|
1302
1303
|
function getCanonicalSkillsDir(global, cwd) {
|
|
1303
|
-
|
|
1304
|
-
return join(baseDir, AGENTS_DIR, SKILLS_SUBDIR);
|
|
1304
|
+
return join(global ? homedir() : cwd || process.cwd(), AGENTS_DIR, SKILLS_SUBDIR);
|
|
1305
1305
|
}
|
|
1306
1306
|
function getEveSubagentSkillsDir(subagent, cwd) {
|
|
1307
|
-
|
|
1308
|
-
return join(baseDir, EVE_SUBAGENTS_DIR, sanitizeName(subagent), "skills");
|
|
1307
|
+
return join(cwd || process.cwd(), EVE_SUBAGENTS_DIR, sanitizeName(subagent), "skills");
|
|
1309
1308
|
}
|
|
1310
1309
|
function getAgentBaseDir(agentType, global, cwd, eveSubagent) {
|
|
1311
1310
|
if (isUniversalAgent(agentType)) return getCanonicalSkillsDir(global, cwd);
|
|
@@ -1383,8 +1382,7 @@ async function resolveParentSymlinks(path) {
|
|
|
1383
1382
|
const dir = dirname(resolved);
|
|
1384
1383
|
const base = basename(resolved);
|
|
1385
1384
|
try {
|
|
1386
|
-
|
|
1387
|
-
return join(realDir, base);
|
|
1385
|
+
return join(await realpath(dir), base);
|
|
1388
1386
|
} catch {
|
|
1389
1387
|
return resolved;
|
|
1390
1388
|
}
|
|
@@ -1408,8 +1406,7 @@ async function createSymlink(target, linkPath) {
|
|
|
1408
1406
|
}
|
|
1409
1407
|
const linkDir = dirname(linkPath);
|
|
1410
1408
|
await mkdir(linkDir, { recursive: true });
|
|
1411
|
-
const
|
|
1412
|
-
const relativePath = relative(realLinkDir, target);
|
|
1409
|
+
const relativePath = relative(await resolveParentSymlinks(linkDir), target);
|
|
1413
1410
|
const symlinkType = platform() === "win32" ? "junction" : void 0;
|
|
1414
1411
|
await symlink(symlinkType === "junction" ? resolvedTarget : relativePath, linkPath, symlinkType);
|
|
1415
1412
|
return true;
|
|
@@ -1478,8 +1475,7 @@ async function installSkillForAgent(skill, agentType, options = {}) {
|
|
|
1478
1475
|
mode: "symlink"
|
|
1479
1476
|
};
|
|
1480
1477
|
if (!isGlobal && !isUniversalAgent(agentType)) {
|
|
1481
|
-
|
|
1482
|
-
if (!existsSync(agentRootDir) && agentType !== "claude-code") return {
|
|
1478
|
+
if (!existsSync(join(cwd, agents[agentType].skillsDir.split("/")[0])) && agentType !== "claude-code") return {
|
|
1483
1479
|
success: true,
|
|
1484
1480
|
path: canonicalDir,
|
|
1485
1481
|
canonicalPath: canonicalDir,
|
|
@@ -1553,8 +1549,7 @@ async function copyDirectory(src, dest, agentType) {
|
|
|
1553
1549
|
dereference: true,
|
|
1554
1550
|
recursive: true
|
|
1555
1551
|
});
|
|
1556
|
-
|
|
1557
|
-
await chmod(destPath, sourceStats.mode & 511);
|
|
1552
|
+
await chmod(destPath, (await stat(srcPath)).mode & 511);
|
|
1558
1553
|
} catch (err) {
|
|
1559
1554
|
if (err instanceof Error && "code" in err && err.code === "ENOENT" && entry.isSymbolicLink()) console.warn(`Skipping broken symlink: ${srcPath}`);
|
|
1560
1555
|
else throw err;
|
|
@@ -1771,8 +1766,7 @@ async function installBlobSkillForAgent(skill, agentType, options = {}) {
|
|
|
1771
1766
|
mode: "symlink"
|
|
1772
1767
|
};
|
|
1773
1768
|
if (!isGlobal && !isUniversalAgent(agentType)) {
|
|
1774
|
-
|
|
1775
|
-
if (!existsSync(agentRootDir)) return {
|
|
1769
|
+
if (!existsSync(join(cwd, agents[agentType].skillsDir.split("/")[0]))) return {
|
|
1776
1770
|
success: true,
|
|
1777
1771
|
path: canonicalDir,
|
|
1778
1772
|
canonicalPath: canonicalDir,
|
|
@@ -2000,7 +1994,7 @@ var ProviderRegistryImpl = class {
|
|
|
2000
1994
|
};
|
|
2001
1995
|
new ProviderRegistryImpl();
|
|
2002
1996
|
const DISCOVERY_SCHEMA_V2 = "https://schemas.agentskills.io/discovery/0.2.0/schema.json";
|
|
2003
|
-
const MAX_ARCHIVE_UNPACKED_BYTES =
|
|
1997
|
+
const MAX_ARCHIVE_UNPACKED_BYTES = 50 * 1024 * 1024;
|
|
2004
1998
|
const MAX_ARCHIVE_FILES = 1e3;
|
|
2005
1999
|
var WellKnownProvider = class {
|
|
2006
2000
|
id = "well-known";
|
|
@@ -3153,23 +3147,22 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
3153
3147
|
const installedAgents = await detectInstalledAgents();
|
|
3154
3148
|
const totalAgents = Object.keys(agents).length;
|
|
3155
3149
|
spinner.stop(`${totalAgents} agents`);
|
|
3156
|
-
if (installedAgents.length === 0) {
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
process.exit(0);
|
|
3169
|
-
}
|
|
3170
|
-
targetAgents = selected;
|
|
3150
|
+
if (installedAgents.length === 0) if (options.yes) {
|
|
3151
|
+
targetAgents = validAgents;
|
|
3152
|
+
log.info("正在安装到全部 Agent");
|
|
3153
|
+
} else {
|
|
3154
|
+
log.info("请选择要安装技能的 Agent");
|
|
3155
|
+
const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).map(([key, config]) => ({
|
|
3156
|
+
value: key,
|
|
3157
|
+
label: config.displayName
|
|
3158
|
+
})));
|
|
3159
|
+
if (isCancel(selected)) {
|
|
3160
|
+
cancel("安装已取消");
|
|
3161
|
+
process.exit(0);
|
|
3171
3162
|
}
|
|
3172
|
-
|
|
3163
|
+
targetAgents = selected;
|
|
3164
|
+
}
|
|
3165
|
+
else if (installedAgents.length === 1 || options.yes) {
|
|
3173
3166
|
targetAgents = ensureUniversalAgents(installedAgents);
|
|
3174
3167
|
if (installedAgents.length === 1) {
|
|
3175
3168
|
const firstAgent = installedAgents[0];
|
|
@@ -3404,14 +3397,13 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
3404
3397
|
slug = hit.slug;
|
|
3405
3398
|
log.info(`自动选择:${import_picocolors.default.cyan(`@${namespace}/${slug}`)} — ${hit.description || hit.name}`);
|
|
3406
3399
|
} else {
|
|
3407
|
-
const choices = hits.map((h, idx) => ({
|
|
3408
|
-
value: idx,
|
|
3409
|
-
label: `@${h.namespace}/${h.slug}`,
|
|
3410
|
-
hint: h.description || h.name
|
|
3411
|
-
}));
|
|
3412
3400
|
const idx = await select({
|
|
3413
3401
|
message: "匹配到多个技能 — 请选择一个",
|
|
3414
|
-
options:
|
|
3402
|
+
options: hits.map((h, idx) => ({
|
|
3403
|
+
value: idx,
|
|
3404
|
+
label: `@${h.namespace}/${h.slug}`,
|
|
3405
|
+
hint: h.description || h.name
|
|
3406
|
+
}))
|
|
3415
3407
|
});
|
|
3416
3408
|
if (isCancel(idx)) {
|
|
3417
3409
|
cancel("安装已取消");
|
|
@@ -3438,8 +3430,7 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
3438
3430
|
}
|
|
3439
3431
|
const meta = metadata;
|
|
3440
3432
|
spinner.stop(`Skill: ${import_picocolors.default.cyan(`@${namespace}/${slug}`)}${meta.description ? ` — ${import_picocolors.default.dim(meta.description)}` : ""}`);
|
|
3441
|
-
|
|
3442
|
-
tempDir = join(tmpRoot, `.skillhub-skillshub-${canonicalSlug.replace(/[/:@]/g, "-")}-${Date.now()}`);
|
|
3433
|
+
tempDir = join(tmpdir(), `.skillhub-skillshub-${canonicalSlug.replace(/[/:@]/g, "-")}-${Date.now()}`);
|
|
3443
3434
|
mkdirSync(tempDir, { recursive: true });
|
|
3444
3435
|
const zipPath = join(tempDir, "skill.zip");
|
|
3445
3436
|
spinner.start("正在下载技能...");
|
|
@@ -3775,24 +3766,23 @@ async function runAdd(args, options = {}) {
|
|
|
3775
3766
|
}
|
|
3776
3767
|
targetAgents = selected;
|
|
3777
3768
|
}
|
|
3778
|
-
} else if (installedAgents.length === 0) {
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
process.exit(0);
|
|
3792
|
-
}
|
|
3793
|
-
targetAgents = selected;
|
|
3769
|
+
} else if (installedAgents.length === 0) if (options.yes) {
|
|
3770
|
+
targetAgents = validAgents;
|
|
3771
|
+
log.info("正在安装到全部 Agent");
|
|
3772
|
+
} else {
|
|
3773
|
+
log.info("请选择要安装技能的 Agent");
|
|
3774
|
+
const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).filter(([key]) => key !== "eve").map(([key, config]) => ({
|
|
3775
|
+
value: key,
|
|
3776
|
+
label: config.displayName
|
|
3777
|
+
})));
|
|
3778
|
+
if (isCancel(selected)) {
|
|
3779
|
+
cancel("安装已取消");
|
|
3780
|
+
await cleanup(tempDir);
|
|
3781
|
+
process.exit(0);
|
|
3794
3782
|
}
|
|
3795
|
-
|
|
3783
|
+
targetAgents = selected;
|
|
3784
|
+
}
|
|
3785
|
+
else if (installedAgents.length === 1 || options.yes) {
|
|
3796
3786
|
targetAgents = ensureUniversalAgents(installedAgents);
|
|
3797
3787
|
if (installedAgents.length === 1) {
|
|
3798
3788
|
const firstAgent = installedAgents[0];
|
|
@@ -3814,18 +3804,17 @@ async function runAdd(args, options = {}) {
|
|
|
3814
3804
|
const availableSubagents = getEveSubagents(process.cwd());
|
|
3815
3805
|
if (options.subagent && options.subagent.length > 0) eveSubagentTargets = options.subagent.map((s) => s === "root" || s === "." ? void 0 : s);
|
|
3816
3806
|
else if (availableSubagents.length > 0 && !options.yes) {
|
|
3817
|
-
const subagentChoices = [{
|
|
3818
|
-
value: "",
|
|
3819
|
-
label: "根 Agent",
|
|
3820
|
-
hint: "agent/skills"
|
|
3821
|
-
}, ...availableSubagents.map((name) => ({
|
|
3822
|
-
value: name,
|
|
3823
|
-
label: name,
|
|
3824
|
-
hint: `agent/subagents/${name}/skills`
|
|
3825
|
-
}))];
|
|
3826
3807
|
const selectedSubagents = await multiselect$1({
|
|
3827
3808
|
message: "Eve 技能安装位置?",
|
|
3828
|
-
options:
|
|
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
|
+
}))],
|
|
3829
3818
|
initialValues: [""],
|
|
3830
3819
|
required: true
|
|
3831
3820
|
});
|
|
@@ -4003,11 +3992,9 @@ async function runAdd(args, options = {}) {
|
|
|
4003
3992
|
const normalizedSource = getOwnerRepo(parsed);
|
|
4004
3993
|
const lockSource = getLockSource(parsed.url, normalizedSource);
|
|
4005
3994
|
const projectLockSourceUrl = getProjectLockSourceUrl(parsed.type, parsed.url);
|
|
4006
|
-
if (normalizedSource) {
|
|
4007
|
-
if (
|
|
4008
|
-
|
|
4009
|
-
} else selectedSkills.map((s) => s.name).join(","), targetAgents.join(","), { ...installGlobally && { global: "1" } }, JSON.stringify(skillFiles), options.metadata;
|
|
4010
|
-
}
|
|
3995
|
+
if (normalizedSource) if (parseOwnerRepo(normalizedSource)) {
|
|
3996
|
+
if (await repoPrivacyPromise === false) selectedSkills.map((s) => s.name).join(","), targetAgents.join(","), { ...installGlobally && { global: "1" } }, JSON.stringify(skillFiles), options.metadata;
|
|
3997
|
+
} else selectedSkills.map((s) => s.name).join(","), targetAgents.join(","), { ...installGlobally && { global: "1" } }, JSON.stringify(skillFiles), options.metadata;
|
|
4011
3998
|
if (successful.length > 0 && installGlobally && (normalizedSource || parsed.type === "skillhub")) {
|
|
4012
3999
|
const successfulSkillNames = new Set(successful.map((r) => r.skill));
|
|
4013
4000
|
let cachedTree;
|
|
@@ -4024,8 +4011,7 @@ async function runAdd(args, options = {}) {
|
|
|
4024
4011
|
const hash = getSkillFolderHashFromTree(cachedTree, skillPathValue);
|
|
4025
4012
|
if (hash) skillFolderHash = hash;
|
|
4026
4013
|
} else if (skillPathValue && tempDir) {
|
|
4027
|
-
const
|
|
4028
|
-
const hash = await computeSkillFolderHash(skillDir);
|
|
4014
|
+
const hash = await computeSkillFolderHash(join(tempDir, dirname(skillPathValue)));
|
|
4029
4015
|
if (hash) skillFolderHash = hash;
|
|
4030
4016
|
}
|
|
4031
4017
|
await addSkillToLock(skill.name, {
|
|
@@ -4069,13 +4055,11 @@ async function runAdd(args, options = {}) {
|
|
|
4069
4055
|
const skillResults = bySkill.get(r.skill) || [];
|
|
4070
4056
|
skillResults.push(r);
|
|
4071
4057
|
bySkill.set(r.skill, skillResults);
|
|
4072
|
-
if (skillResults.length === 1) {
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
} else ungroupedResults.push(r);
|
|
4078
|
-
}
|
|
4058
|
+
if (skillResults.length === 1) if (r.pluginName) {
|
|
4059
|
+
const group = r.pluginName;
|
|
4060
|
+
if (!groupedResults[group]) groupedResults[group] = [];
|
|
4061
|
+
groupedResults[group].push(r);
|
|
4062
|
+
} else ungroupedResults.push(r);
|
|
4079
4063
|
}
|
|
4080
4064
|
const skillCount = bySkill.size;
|
|
4081
4065
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
@@ -4771,15 +4755,12 @@ async function removeCommand(skillNames, options) {
|
|
|
4771
4755
|
}
|
|
4772
4756
|
const remainingAgents = (await detectInstalledAgents()).filter((a) => !targetAgents.includes(a));
|
|
4773
4757
|
let isStillUsed = false;
|
|
4774
|
-
for (const agentKey of remainingAgents) {
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
isStillUsed = true;
|
|
4781
|
-
break;
|
|
4782
|
-
}
|
|
4758
|
+
for (const agentKey of remainingAgents) if (await lstat(getInstallPath(skillName, agentKey, {
|
|
4759
|
+
global: isGlobal,
|
|
4760
|
+
cwd
|
|
4761
|
+
})).catch(() => null)) {
|
|
4762
|
+
isStillUsed = true;
|
|
4763
|
+
break;
|
|
4783
4764
|
}
|
|
4784
4765
|
if (!isStillUsed) await rm(canonicalPath, {
|
|
4785
4766
|
recursive: true,
|
|
@@ -4919,14 +4900,12 @@ function parseUpdateOptions(args) {
|
|
|
4919
4900
|
}
|
|
4920
4901
|
function hasProjectSkills(cwd) {
|
|
4921
4902
|
const dir = cwd || process.cwd();
|
|
4922
|
-
|
|
4923
|
-
if (existsSync(lockPath)) return true;
|
|
4903
|
+
if (existsSync(join(dir, "skills-lock.json"))) return true;
|
|
4924
4904
|
const skillsDir = join(dir, ".agents", "skills");
|
|
4925
4905
|
try {
|
|
4926
4906
|
const entries = readdirSync(skillsDir, { withFileTypes: true });
|
|
4927
4907
|
for (const entry of entries) if (entry.isDirectory()) {
|
|
4928
|
-
|
|
4929
|
-
if (existsSync(skillMd)) return true;
|
|
4908
|
+
if (existsSync(join(skillsDir, entry.name, "SKILL.md"))) return true;
|
|
4930
4909
|
}
|
|
4931
4910
|
} catch {}
|
|
4932
4911
|
return false;
|
|
@@ -5350,8 +5329,7 @@ async function updateProjectSkills(options = {}) {
|
|
|
5350
5329
|
try {
|
|
5351
5330
|
tempDir = await cloneRepo(sourceUrl, ref);
|
|
5352
5331
|
const discoveredPaths = (await discoverSkills(tempDir)).map((s) => {
|
|
5353
|
-
|
|
5354
|
-
return join(relPath, "SKILL.md").split(sep).join("/");
|
|
5332
|
+
return join(relative(tempDir, s.path), "SKILL.md").split(sep).join("/");
|
|
5355
5333
|
});
|
|
5356
5334
|
deletedSkills = await checkAndPromptForDeletions(source, allLockedForSource, localLock.skills, false, options, discoveredPaths);
|
|
5357
5335
|
} catch (error) {
|
|
@@ -5810,12 +5788,8 @@ function fail(message) {
|
|
|
5810
5788
|
}
|
|
5811
5789
|
var UseCommandError = class extends Error {};
|
|
5812
5790
|
async function runLogin(args, globalOpts) {
|
|
5813
|
-
const token = getOptionValue$3(args, "--token");
|
|
5791
|
+
const token = getOptionValue$3(args, "--token") || await promptForToken();
|
|
5814
5792
|
const { registry } = resolveConfig(globalOpts);
|
|
5815
|
-
if (!token) {
|
|
5816
|
-
console.error("用法:bfi auth login --token <token>");
|
|
5817
|
-
process.exit(1);
|
|
5818
|
-
}
|
|
5819
5793
|
const api = new SkillHubAPI(registry, token);
|
|
5820
5794
|
try {
|
|
5821
5795
|
const response = await api.whoami();
|
|
@@ -5848,7 +5822,7 @@ async function runLogout() {
|
|
|
5848
5822
|
async function runWhoami(globalOpts) {
|
|
5849
5823
|
const { registry, token } = resolveConfig(globalOpts);
|
|
5850
5824
|
if (!token) {
|
|
5851
|
-
console.error("未认证。运行:bfi auth login
|
|
5825
|
+
console.error("未认证。运行:bfi auth login(在隐藏提示中输入 Token)");
|
|
5852
5826
|
process.exit(1);
|
|
5853
5827
|
}
|
|
5854
5828
|
const response = await new SkillHubAPI(registry, token).whoami();
|
|
@@ -5889,6 +5863,47 @@ async function runWhoami(globalOpts) {
|
|
|
5889
5863
|
}
|
|
5890
5864
|
console.log();
|
|
5891
5865
|
}
|
|
5866
|
+
function promptForToken() {
|
|
5867
|
+
const input = process.stdin;
|
|
5868
|
+
if (!input.isTTY || typeof input.setRawMode !== "function") throw new Error("请在交互式终端运行 `bfi auth login`,Token 将以隐藏方式输入。");
|
|
5869
|
+
process.stderr.write("请输入 SkillHub Token(输入内容隐藏): ");
|
|
5870
|
+
return new Promise((resolve, reject) => {
|
|
5871
|
+
let token = "";
|
|
5872
|
+
let finished = false;
|
|
5873
|
+
const wasRaw = input.isRaw;
|
|
5874
|
+
const cleanup = () => {
|
|
5875
|
+
if (finished) return;
|
|
5876
|
+
finished = true;
|
|
5877
|
+
input.off("data", onData);
|
|
5878
|
+
input.setRawMode(Boolean(wasRaw));
|
|
5879
|
+
input.pause();
|
|
5880
|
+
process.stderr.write("\n");
|
|
5881
|
+
};
|
|
5882
|
+
const onData = (chunk) => {
|
|
5883
|
+
for (const character of chunk.toString("utf8")) {
|
|
5884
|
+
const code = character.charCodeAt(0);
|
|
5885
|
+
if (code === 3 || code === 4) {
|
|
5886
|
+
cleanup();
|
|
5887
|
+
reject(/* @__PURE__ */ new Error("登录已取消。"));
|
|
5888
|
+
return;
|
|
5889
|
+
}
|
|
5890
|
+
if (character === "\r" || character === "\n") {
|
|
5891
|
+
cleanup();
|
|
5892
|
+
const value = token.trim();
|
|
5893
|
+
if (value) resolve(value);
|
|
5894
|
+
else reject(/* @__PURE__ */ new Error("Token 不能为空。"));
|
|
5895
|
+
return;
|
|
5896
|
+
}
|
|
5897
|
+
if (code === 8 || code === 127) token = token.slice(0, -1);
|
|
5898
|
+
else if (code >= 32 && code <= 126) token += character;
|
|
5899
|
+
}
|
|
5900
|
+
};
|
|
5901
|
+
input.setRawMode(true);
|
|
5902
|
+
input.setEncoding("utf8");
|
|
5903
|
+
input.resume();
|
|
5904
|
+
input.on("data", onData);
|
|
5905
|
+
});
|
|
5906
|
+
}
|
|
5892
5907
|
function getOptionValue$3(args, flag) {
|
|
5893
5908
|
const idx = args.indexOf(flag);
|
|
5894
5909
|
return idx !== -1 && args[idx + 1] ? args[idx + 1] : void 0;
|
|
@@ -6285,8 +6300,8 @@ const DIM$5 = "\x1B[38;5;102m";
|
|
|
6285
6300
|
const TEXT$4 = "\x1B[38;5;145m";
|
|
6286
6301
|
function formatFileSize(bytes) {
|
|
6287
6302
|
if (bytes < 1024) return `${bytes} B`;
|
|
6288
|
-
if (bytes <
|
|
6289
|
-
return `${(bytes /
|
|
6303
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
6304
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
6290
6305
|
}
|
|
6291
6306
|
async function runDocs(args, globalOpts) {
|
|
6292
6307
|
switch (args[0]) {
|
|
@@ -6550,8 +6565,7 @@ async function publishFromDir(positionalArgs, api, namespace, visibility) {
|
|
|
6550
6565
|
console.log("需要包含 frontmatter(name, description)的 SKILL.md 文件。");
|
|
6551
6566
|
process.exit(1);
|
|
6552
6567
|
}
|
|
6553
|
-
const
|
|
6554
|
-
const { data: frontmatter } = parseFrontmatter(skillMdContent);
|
|
6568
|
+
const { data: frontmatter } = parseFrontmatter(fs.readFileSync(skillMdPath, "utf-8"));
|
|
6555
6569
|
const skillName = frontmatter.name || path$1.basename(resolvedDir);
|
|
6556
6570
|
console.log(`${DIM$4}正在从目录发布技能...${RESET$4}`);
|
|
6557
6571
|
console.log(` ${BOLD$2}名称:${RESET$4} ${TEXT$3}${skillName}${RESET$4}`);
|
|
@@ -6569,7 +6583,7 @@ async function publishFromDir(positionalArgs, api, namespace, visibility) {
|
|
|
6569
6583
|
if (res.slug) console.log(` ${BOLD$2}Slug:${RESET$4} ${TEXT$3}${res.slug}${RESET$4}`);
|
|
6570
6584
|
if (res.url) console.log(` ${BOLD$2}URL:${RESET$4} ${TEXT$3}${res.url}${RESET$4}`);
|
|
6571
6585
|
} catch (error) {
|
|
6572
|
-
|
|
6586
|
+
printPublishFailure(error, api.registry);
|
|
6573
6587
|
process.exit(1);
|
|
6574
6588
|
}
|
|
6575
6589
|
console.log();
|
|
@@ -6598,8 +6612,7 @@ async function publishFromZip(positionalArgs, api, namespace, visibility) {
|
|
|
6598
6612
|
}
|
|
6599
6613
|
const skillDir = path$1.dirname(skillMdPath);
|
|
6600
6614
|
console.log(` ${GREEN$3}在 ${path$1.relative(tmpDir, skillDir) || "."} 中找到 SKILL.md${RESET$4}`);
|
|
6601
|
-
const
|
|
6602
|
-
const { data: frontmatter } = parseFrontmatter(skillMdContent);
|
|
6615
|
+
const { data: frontmatter } = parseFrontmatter(fs.readFileSync(skillMdPath, "utf-8"));
|
|
6603
6616
|
const skillName = frontmatter.name || path$1.basename(skillDir);
|
|
6604
6617
|
console.log(` ${BOLD$2}名称:${RESET$4} ${TEXT$3}${skillName}${RESET$4}`);
|
|
6605
6618
|
console.log(` ${BOLD$2}命名空间:${RESET$4} ${TEXT$3}${namespace}${RESET$4}`);
|
|
@@ -6614,7 +6627,7 @@ async function publishFromZip(positionalArgs, api, namespace, visibility) {
|
|
|
6614
6627
|
if (res.slug) console.log(` ${BOLD$2}Slug:${RESET$4} ${TEXT$3}${res.slug}${RESET$4}`);
|
|
6615
6628
|
if (res.url) console.log(` ${BOLD$2}URL:${RESET$4} ${TEXT$3}${res.url}${RESET$4}`);
|
|
6616
6629
|
} catch (error) {
|
|
6617
|
-
if (error.message && !error.message.includes("Publish failed"))
|
|
6630
|
+
if (error.message && !error.message.includes("Publish failed")) printPublishFailure(error, api.registry);
|
|
6618
6631
|
process.exit(1);
|
|
6619
6632
|
} finally {
|
|
6620
6633
|
try {
|
|
@@ -6724,7 +6737,7 @@ async function publishFromGit(positionalArgs, api, namespace, visibility, yes, b
|
|
|
6724
6737
|
console.log(` ${GREEN$3}✓ 已发布:${namespace}--${res.slug || skill.name}${RESET$4}`);
|
|
6725
6738
|
successCount++;
|
|
6726
6739
|
} catch (error) {
|
|
6727
|
-
|
|
6740
|
+
printPublishFailure(error, api.registry, `✗ ${skill.name}:`);
|
|
6728
6741
|
}
|
|
6729
6742
|
}
|
|
6730
6743
|
console.log(`\n${GREEN$3}发布完成:${successCount}/${selectedSkills.length} 个技能${RESET$4}`);
|
|
@@ -6733,6 +6746,17 @@ async function publishFromGit(positionalArgs, api, namespace, visibility, yes, b
|
|
|
6733
6746
|
await cleanupTempDir(tmpDir);
|
|
6734
6747
|
} catch {}
|
|
6735
6748
|
}
|
|
6749
|
+
function printPublishFailure(error, registry, label = "发布失败:") {
|
|
6750
|
+
const requiredScope = error?.body?.data?.requiredScope;
|
|
6751
|
+
if (error?.status === 403 && typeof requiredScope === "string" && requiredScope) {
|
|
6752
|
+
const settingsUrl = `${registry}/dashboard/tokens`;
|
|
6753
|
+
console.error(` ${RED$2}${label}当前 API Token 缺少「${requiredScope}」权限。${RESET$4}`);
|
|
6754
|
+
console.error(` ${DIM$4}修复:打开 ${settingsUrl} 新建 Token 并勾选「技能发布」,${RESET$4}`);
|
|
6755
|
+
console.error(` ${DIM$4}然后执行 bfi auth login --token <新 Token> 后重试。${RESET$4}`);
|
|
6756
|
+
return;
|
|
6757
|
+
}
|
|
6758
|
+
console.error(` ${RED$2}${label}${error.message}${RESET$4}`);
|
|
6759
|
+
}
|
|
6736
6760
|
function getOptionValue$1(args, flag) {
|
|
6737
6761
|
const idx = args.indexOf(flag);
|
|
6738
6762
|
return idx !== -1 && idx < args.length - 1 ? args[idx + 1] : void 0;
|
|
@@ -6769,8 +6793,8 @@ function findSkillMd(dir) {
|
|
|
6769
6793
|
}
|
|
6770
6794
|
function formatSize(bytes) {
|
|
6771
6795
|
if (bytes < 1024) return `${bytes} B`;
|
|
6772
|
-
if (bytes <
|
|
6773
|
-
return `${(bytes /
|
|
6796
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
6797
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
6774
6798
|
}
|
|
6775
6799
|
function truncate(text, maxLen) {
|
|
6776
6800
|
if (text.length <= maxLen) return text;
|
|
@@ -7055,8 +7079,7 @@ function printPackageHelp() {
|
|
|
7055
7079
|
console.log();
|
|
7056
7080
|
}
|
|
7057
7081
|
async function handleLocalList(args, globalOpts) {
|
|
7058
|
-
const
|
|
7059
|
-
const lock = loadLockfile(cwd);
|
|
7082
|
+
const lock = loadLockfile(getWorkdir(globalOpts, args));
|
|
7060
7083
|
args.includes("-g") || args.includes("--global");
|
|
7061
7084
|
const pkgs = lock.packages || {};
|
|
7062
7085
|
const entries = Object.entries(pkgs);
|
|
@@ -7253,18 +7276,17 @@ async function handleInstall(args, api, globalOpts) {
|
|
|
7253
7276
|
if (targetAgents.includes("eve")) {
|
|
7254
7277
|
const availableSubagents = getEveSubagents(process.cwd());
|
|
7255
7278
|
if (availableSubagents.length > 0) {
|
|
7256
|
-
const subagentChoices = [{
|
|
7257
|
-
value: "",
|
|
7258
|
-
label: "根 Agent",
|
|
7259
|
-
hint: "agent/skills"
|
|
7260
|
-
}, ...availableSubagents.map((name) => ({
|
|
7261
|
-
value: name,
|
|
7262
|
-
label: name,
|
|
7263
|
-
hint: `agent/subagents/${name}/skills`
|
|
7264
|
-
}))];
|
|
7265
7279
|
const selectedSubagents = await multiselect$1({
|
|
7266
7280
|
message: "Eve 技能安装位置?",
|
|
7267
|
-
options:
|
|
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
|
+
}))],
|
|
7268
7290
|
initialValues: [""],
|
|
7269
7291
|
required: true
|
|
7270
7292
|
});
|
|
@@ -7459,8 +7481,7 @@ async function handleUninstall(args, globalOpts) {
|
|
|
7459
7481
|
}
|
|
7460
7482
|
async function handleUpdate(args, api, globalOpts) {
|
|
7461
7483
|
const pkgRef = args[0];
|
|
7462
|
-
const
|
|
7463
|
-
const lock = loadLockfile(cwd);
|
|
7484
|
+
const lock = loadLockfile(getWorkdir(globalOpts, args));
|
|
7464
7485
|
let packagesToUpdate = [];
|
|
7465
7486
|
const pkgs = lock.packages || {};
|
|
7466
7487
|
if (pkgRef) {
|
|
@@ -9751,7 +9772,7 @@ ${BOLD}bfi — 用友大业财BFI统一命令行工具${RESET}
|
|
|
9751
9772
|
${BOLD}Usage:${RESET} bfi <command> [options]
|
|
9752
9773
|
|
|
9753
9774
|
${BOLD}━━━ 认证 ━━━${RESET}
|
|
9754
|
-
auth login --token <token>
|
|
9775
|
+
auth login [--token <token>] 登录 SkillHub(不带参数时隐藏输入 Token)
|
|
9755
9776
|
auth logout 登出
|
|
9756
9777
|
auth whoami 查看当前用户
|
|
9757
9778
|
|
|
@@ -9826,7 +9847,7 @@ ${BOLD}━━━ 技能引用格式 ━━━${RESET}
|
|
|
9826
9847
|
owner/repo 从 GitHub 安装
|
|
9827
9848
|
|
|
9828
9849
|
${BOLD}━━━ 示例 ━━━${RESET}
|
|
9829
|
-
${DIM}$ bfi auth login
|
|
9850
|
+
${DIM}$ bfi auth login${RESET}
|
|
9830
9851
|
${DIM}$ bfi skills search react${RESET}
|
|
9831
9852
|
${DIM}$ bfi skills add @myteam/db-explore${RESET}
|
|
9832
9853
|
${DIM}$ bfi skills add vercel-labs/agent-skills --skill pr-review${RESET}
|
|
@@ -9880,7 +9901,7 @@ function runInit(args) {
|
|
|
9880
9901
|
return;
|
|
9881
9902
|
}
|
|
9882
9903
|
if (hasName) mkdirSync(skillDir, { recursive: true });
|
|
9883
|
-
|
|
9904
|
+
writeFileSync(skillFile, `---
|
|
9884
9905
|
name: ${skillName}
|
|
9885
9906
|
description: A brief description of what this skill does
|
|
9886
9907
|
---
|
|
@@ -9898,8 +9919,7 @@ Describe when this skill should be used.
|
|
|
9898
9919
|
1. First step
|
|
9899
9920
|
2. Second step
|
|
9900
9921
|
3. Additional steps as needed
|
|
9901
|
-
|
|
9902
|
-
writeFileSync(skillFile, skillContent);
|
|
9922
|
+
`);
|
|
9903
9923
|
console.log(`${TEXT}已初始化技能:${DIM}${skillName}${RESET}`);
|
|
9904
9924
|
console.log();
|
|
9905
9925
|
console.log(`${DIM}已创建:${RESET}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {}
|
|
1
|
+
export { };
|
|
@@ -3,6 +3,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
3
3
|
import { CallToolRequestSchema, CallToolResultSchema, ListToolsRequestSchema, ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5
5
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
6
|
+
import JSONbig from "json-bigint";
|
|
6
7
|
import fs from "node:fs";
|
|
7
8
|
import path from "node:path";
|
|
8
9
|
import os from "node:os";
|
|
@@ -90,6 +91,7 @@ function loadGlobalConfig() {
|
|
|
90
91
|
}
|
|
91
92
|
return null;
|
|
92
93
|
}
|
|
94
|
+
JSONbig({ storeAsString: true });
|
|
93
95
|
function resolveApiBase() {
|
|
94
96
|
return process.env.BFI_API_BASE || "https://bfi.yyuap.com/bfi-api";
|
|
95
97
|
}
|
package/dist/mcp-db/main.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {}
|
|
1
|
+
export { };
|
package/dist/mcp-db/main.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import mysql from "mysql2/promise";
|
|
5
|
+
import JSONbig from "json-bigint";
|
|
5
6
|
import fs from "node:fs";
|
|
6
7
|
import path from "node:path";
|
|
7
8
|
import os from "node:os";
|
|
@@ -98,7 +99,9 @@ async function directExecute(dsn, sql, maxRows = DEFAULT_MAX_ROWS) {
|
|
|
98
99
|
try {
|
|
99
100
|
conn = await mysql.createConnection({
|
|
100
101
|
uri: dsn,
|
|
101
|
-
connectTimeout: 8e3
|
|
102
|
+
connectTimeout: 8e3,
|
|
103
|
+
supportBigNumbers: true,
|
|
104
|
+
bigNumberStrings: true
|
|
102
105
|
});
|
|
103
106
|
} catch (e) {
|
|
104
107
|
return {
|
|
@@ -150,6 +153,7 @@ function loadGlobalConfig() {
|
|
|
150
153
|
}
|
|
151
154
|
return null;
|
|
152
155
|
}
|
|
156
|
+
const JSONBigString = JSONbig({ storeAsString: true });
|
|
153
157
|
function resolveApiBase() {
|
|
154
158
|
return process.env.BFI_API_BASE || "https://bfi.yyuap.com/bfi-api";
|
|
155
159
|
}
|
|
@@ -185,7 +189,13 @@ async function post(path, payload, fetchImpl = fetch) {
|
|
|
185
189
|
throw new RestError("upstream_unreachable", `bfi-api(${resolveApiBase()})不可达:${e instanceof Error ? e.message : String(e)}`);
|
|
186
190
|
}
|
|
187
191
|
if (resp.status === 401) throw new RestError("unauthorized", "v2 token 无效或过期:请重新 `bfi auth login --token <token>`");
|
|
188
|
-
const
|
|
192
|
+
const rawText = await resp.text().catch(() => "");
|
|
193
|
+
let body = {};
|
|
194
|
+
try {
|
|
195
|
+
body = JSONBigString.parse(rawText);
|
|
196
|
+
} catch {
|
|
197
|
+
body = {};
|
|
198
|
+
}
|
|
189
199
|
if (body.code === 0) return body.data;
|
|
190
200
|
throw new RestError(body.data?.error_kind || "upstream_error", body.msg || "bfi-api 返回错误");
|
|
191
201
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {}
|
|
1
|
+
export { };
|
|
@@ -3,6 +3,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
3
3
|
import { CallToolRequestSchema, CallToolResultSchema, ListToolsRequestSchema, ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5
5
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
6
|
+
import JSONbig from "json-bigint";
|
|
6
7
|
import fs from "node:fs";
|
|
7
8
|
import path from "node:path";
|
|
8
9
|
import os from "node:os";
|
|
@@ -87,6 +88,7 @@ function loadGlobalConfig() {
|
|
|
87
88
|
}
|
|
88
89
|
return null;
|
|
89
90
|
}
|
|
91
|
+
JSONbig({ storeAsString: true });
|
|
90
92
|
function resolveToken() {
|
|
91
93
|
if (process.env.BFI_TOKEN) return process.env.BFI_TOKEN;
|
|
92
94
|
return loadGlobalConfig()?.token ?? null;
|