bfi-cli 0.1.97 → 0.1.98

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 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
- if (selected.has(item.value)) selected.delete(item.value);
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
- if (options.body instanceof Buffer) bodyBuf = options.body;
519
- else if (typeof options.body === "string") bodyStr = options.body;
520
- else if (typeof FormData !== "undefined" && options.body instanceof FormData) return this.fetchRequest(url, requestOptions, options.body);
521
- else {
522
- requestOptions.headers["Content-Type"] = "application/json";
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) => {
@@ -1300,12 +1296,10 @@ async function isDirEntryOrSymlinkToDir(entry, entryPath) {
1300
1296
  }
1301
1297
  }
1302
1298
  function getCanonicalSkillsDir(global, cwd) {
1303
- const baseDir = global ? homedir() : cwd || process.cwd();
1304
- return join(baseDir, AGENTS_DIR, SKILLS_SUBDIR);
1299
+ return join(global ? homedir() : cwd || process.cwd(), AGENTS_DIR, SKILLS_SUBDIR);
1305
1300
  }
1306
1301
  function getEveSubagentSkillsDir(subagent, cwd) {
1307
- const baseDir = cwd || process.cwd();
1308
- return join(baseDir, EVE_SUBAGENTS_DIR, sanitizeName(subagent), "skills");
1302
+ return join(cwd || process.cwd(), EVE_SUBAGENTS_DIR, sanitizeName(subagent), "skills");
1309
1303
  }
1310
1304
  function getAgentBaseDir(agentType, global, cwd, eveSubagent) {
1311
1305
  if (isUniversalAgent(agentType)) return getCanonicalSkillsDir(global, cwd);
@@ -1383,8 +1377,7 @@ async function resolveParentSymlinks(path) {
1383
1377
  const dir = dirname(resolved);
1384
1378
  const base = basename(resolved);
1385
1379
  try {
1386
- const realDir = await realpath(dir);
1387
- return join(realDir, base);
1380
+ return join(await realpath(dir), base);
1388
1381
  } catch {
1389
1382
  return resolved;
1390
1383
  }
@@ -1408,8 +1401,7 @@ async function createSymlink(target, linkPath) {
1408
1401
  }
1409
1402
  const linkDir = dirname(linkPath);
1410
1403
  await mkdir(linkDir, { recursive: true });
1411
- const realLinkDir = await resolveParentSymlinks(linkDir);
1412
- const relativePath = relative(realLinkDir, target);
1404
+ const relativePath = relative(await resolveParentSymlinks(linkDir), target);
1413
1405
  const symlinkType = platform() === "win32" ? "junction" : void 0;
1414
1406
  await symlink(symlinkType === "junction" ? resolvedTarget : relativePath, linkPath, symlinkType);
1415
1407
  return true;
@@ -1478,8 +1470,7 @@ async function installSkillForAgent(skill, agentType, options = {}) {
1478
1470
  mode: "symlink"
1479
1471
  };
1480
1472
  if (!isGlobal && !isUniversalAgent(agentType)) {
1481
- const agentRootDir = join(cwd, agents[agentType].skillsDir.split("/")[0]);
1482
- if (!existsSync(agentRootDir) && agentType !== "claude-code") return {
1473
+ if (!existsSync(join(cwd, agents[agentType].skillsDir.split("/")[0])) && agentType !== "claude-code") return {
1483
1474
  success: true,
1484
1475
  path: canonicalDir,
1485
1476
  canonicalPath: canonicalDir,
@@ -1553,8 +1544,7 @@ async function copyDirectory(src, dest, agentType) {
1553
1544
  dereference: true,
1554
1545
  recursive: true
1555
1546
  });
1556
- const sourceStats = await stat(srcPath);
1557
- await chmod(destPath, sourceStats.mode & 511);
1547
+ await chmod(destPath, (await stat(srcPath)).mode & 511);
1558
1548
  } catch (err) {
1559
1549
  if (err instanceof Error && "code" in err && err.code === "ENOENT" && entry.isSymbolicLink()) console.warn(`Skipping broken symlink: ${srcPath}`);
1560
1550
  else throw err;
@@ -1771,8 +1761,7 @@ async function installBlobSkillForAgent(skill, agentType, options = {}) {
1771
1761
  mode: "symlink"
1772
1762
  };
1773
1763
  if (!isGlobal && !isUniversalAgent(agentType)) {
1774
- const agentRootDir = join(cwd, agents[agentType].skillsDir.split("/")[0]);
1775
- if (!existsSync(agentRootDir)) return {
1764
+ if (!existsSync(join(cwd, agents[agentType].skillsDir.split("/")[0]))) return {
1776
1765
  success: true,
1777
1766
  path: canonicalDir,
1778
1767
  canonicalPath: canonicalDir,
@@ -2000,7 +1989,7 @@ var ProviderRegistryImpl = class {
2000
1989
  };
2001
1990
  new ProviderRegistryImpl();
2002
1991
  const DISCOVERY_SCHEMA_V2 = "https://schemas.agentskills.io/discovery/0.2.0/schema.json";
2003
- const MAX_ARCHIVE_UNPACKED_BYTES = 52428800;
1992
+ const MAX_ARCHIVE_UNPACKED_BYTES = 50 * 1024 * 1024;
2004
1993
  const MAX_ARCHIVE_FILES = 1e3;
2005
1994
  var WellKnownProvider = class {
2006
1995
  id = "well-known";
@@ -3153,23 +3142,22 @@ async function handleWellKnownSkills(source, url, options, spinner) {
3153
3142
  const installedAgents = await detectInstalledAgents();
3154
3143
  const totalAgents = Object.keys(agents).length;
3155
3144
  spinner.stop(`${totalAgents} agents`);
3156
- if (installedAgents.length === 0) {
3157
- if (options.yes) {
3158
- targetAgents = validAgents;
3159
- log.info("正在安装到全部 Agent");
3160
- } else {
3161
- log.info("请选择要安装技能的 Agent");
3162
- const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).map(([key, config]) => ({
3163
- value: key,
3164
- label: config.displayName
3165
- })));
3166
- if (isCancel(selected)) {
3167
- cancel("安装已取消");
3168
- process.exit(0);
3169
- }
3170
- targetAgents = selected;
3145
+ if (installedAgents.length === 0) if (options.yes) {
3146
+ targetAgents = validAgents;
3147
+ log.info("正在安装到全部 Agent");
3148
+ } else {
3149
+ log.info("请选择要安装技能的 Agent");
3150
+ const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).map(([key, config]) => ({
3151
+ value: key,
3152
+ label: config.displayName
3153
+ })));
3154
+ if (isCancel(selected)) {
3155
+ cancel("安装已取消");
3156
+ process.exit(0);
3171
3157
  }
3172
- } else if (installedAgents.length === 1 || options.yes) {
3158
+ targetAgents = selected;
3159
+ }
3160
+ else if (installedAgents.length === 1 || options.yes) {
3173
3161
  targetAgents = ensureUniversalAgents(installedAgents);
3174
3162
  if (installedAgents.length === 1) {
3175
3163
  const firstAgent = installedAgents[0];
@@ -3404,14 +3392,13 @@ async function installFromSkillHub(parsed, options, spinner) {
3404
3392
  slug = hit.slug;
3405
3393
  log.info(`自动选择:${import_picocolors.default.cyan(`@${namespace}/${slug}`)} — ${hit.description || hit.name}`);
3406
3394
  } 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
3395
  const idx = await select({
3413
3396
  message: "匹配到多个技能 — 请选择一个",
3414
- options: choices
3397
+ options: hits.map((h, idx) => ({
3398
+ value: idx,
3399
+ label: `@${h.namespace}/${h.slug}`,
3400
+ hint: h.description || h.name
3401
+ }))
3415
3402
  });
3416
3403
  if (isCancel(idx)) {
3417
3404
  cancel("安装已取消");
@@ -3438,8 +3425,7 @@ async function installFromSkillHub(parsed, options, spinner) {
3438
3425
  }
3439
3426
  const meta = metadata;
3440
3427
  spinner.stop(`Skill: ${import_picocolors.default.cyan(`@${namespace}/${slug}`)}${meta.description ? ` — ${import_picocolors.default.dim(meta.description)}` : ""}`);
3441
- const tmpRoot = tmpdir();
3442
- tempDir = join(tmpRoot, `.skillhub-skillshub-${canonicalSlug.replace(/[/:@]/g, "-")}-${Date.now()}`);
3428
+ tempDir = join(tmpdir(), `.skillhub-skillshub-${canonicalSlug.replace(/[/:@]/g, "-")}-${Date.now()}`);
3443
3429
  mkdirSync(tempDir, { recursive: true });
3444
3430
  const zipPath = join(tempDir, "skill.zip");
3445
3431
  spinner.start("正在下载技能...");
@@ -3775,24 +3761,23 @@ async function runAdd(args, options = {}) {
3775
3761
  }
3776
3762
  targetAgents = selected;
3777
3763
  }
3778
- } else if (installedAgents.length === 0) {
3779
- if (options.yes) {
3780
- targetAgents = validAgents;
3781
- log.info("正在安装到全部 Agent");
3782
- } else {
3783
- log.info("请选择要安装技能的 Agent");
3784
- const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).filter(([key]) => key !== "eve").map(([key, config]) => ({
3785
- value: key,
3786
- label: config.displayName
3787
- })));
3788
- if (isCancel(selected)) {
3789
- cancel("安装已取消");
3790
- await cleanup(tempDir);
3791
- process.exit(0);
3792
- }
3793
- targetAgents = selected;
3764
+ } else if (installedAgents.length === 0) if (options.yes) {
3765
+ targetAgents = validAgents;
3766
+ log.info("正在安装到全部 Agent");
3767
+ } else {
3768
+ log.info("请选择要安装技能的 Agent");
3769
+ const selected = await promptForAgents("请选择要安装到的 Agent:", Object.entries(agents).filter(([key]) => key !== "eve").map(([key, config]) => ({
3770
+ value: key,
3771
+ label: config.displayName
3772
+ })));
3773
+ if (isCancel(selected)) {
3774
+ cancel("安装已取消");
3775
+ await cleanup(tempDir);
3776
+ process.exit(0);
3794
3777
  }
3795
- } else if (installedAgents.length === 1 || options.yes) {
3778
+ targetAgents = selected;
3779
+ }
3780
+ else if (installedAgents.length === 1 || options.yes) {
3796
3781
  targetAgents = ensureUniversalAgents(installedAgents);
3797
3782
  if (installedAgents.length === 1) {
3798
3783
  const firstAgent = installedAgents[0];
@@ -3814,18 +3799,17 @@ async function runAdd(args, options = {}) {
3814
3799
  const availableSubagents = getEveSubagents(process.cwd());
3815
3800
  if (options.subagent && options.subagent.length > 0) eveSubagentTargets = options.subagent.map((s) => s === "root" || s === "." ? void 0 : s);
3816
3801
  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
3802
  const selectedSubagents = await multiselect$1({
3827
3803
  message: "Eve 技能安装位置?",
3828
- options: subagentChoices,
3804
+ options: [{
3805
+ value: "",
3806
+ label: "根 Agent",
3807
+ hint: "agent/skills"
3808
+ }, ...availableSubagents.map((name) => ({
3809
+ value: name,
3810
+ label: name,
3811
+ hint: `agent/subagents/${name}/skills`
3812
+ }))],
3829
3813
  initialValues: [""],
3830
3814
  required: true
3831
3815
  });
@@ -4003,11 +3987,9 @@ async function runAdd(args, options = {}) {
4003
3987
  const normalizedSource = getOwnerRepo(parsed);
4004
3988
  const lockSource = getLockSource(parsed.url, normalizedSource);
4005
3989
  const projectLockSourceUrl = getProjectLockSourceUrl(parsed.type, parsed.url);
4006
- if (normalizedSource) {
4007
- if (parseOwnerRepo(normalizedSource)) {
4008
- if (await repoPrivacyPromise === false) selectedSkills.map((s) => s.name).join(","), targetAgents.join(","), { ...installGlobally && { global: "1" } }, JSON.stringify(skillFiles), options.metadata;
4009
- } else selectedSkills.map((s) => s.name).join(","), targetAgents.join(","), { ...installGlobally && { global: "1" } }, JSON.stringify(skillFiles), options.metadata;
4010
- }
3990
+ if (normalizedSource) if (parseOwnerRepo(normalizedSource)) {
3991
+ if (await repoPrivacyPromise === false) selectedSkills.map((s) => s.name).join(","), targetAgents.join(","), { ...installGlobally && { global: "1" } }, JSON.stringify(skillFiles), options.metadata;
3992
+ } else selectedSkills.map((s) => s.name).join(","), targetAgents.join(","), { ...installGlobally && { global: "1" } }, JSON.stringify(skillFiles), options.metadata;
4011
3993
  if (successful.length > 0 && installGlobally && (normalizedSource || parsed.type === "skillhub")) {
4012
3994
  const successfulSkillNames = new Set(successful.map((r) => r.skill));
4013
3995
  let cachedTree;
@@ -4024,8 +4006,7 @@ async function runAdd(args, options = {}) {
4024
4006
  const hash = getSkillFolderHashFromTree(cachedTree, skillPathValue);
4025
4007
  if (hash) skillFolderHash = hash;
4026
4008
  } else if (skillPathValue && tempDir) {
4027
- const skillDir = join(tempDir, dirname(skillPathValue));
4028
- const hash = await computeSkillFolderHash(skillDir);
4009
+ const hash = await computeSkillFolderHash(join(tempDir, dirname(skillPathValue)));
4029
4010
  if (hash) skillFolderHash = hash;
4030
4011
  }
4031
4012
  await addSkillToLock(skill.name, {
@@ -4069,13 +4050,11 @@ async function runAdd(args, options = {}) {
4069
4050
  const skillResults = bySkill.get(r.skill) || [];
4070
4051
  skillResults.push(r);
4071
4052
  bySkill.set(r.skill, skillResults);
4072
- if (skillResults.length === 1) {
4073
- if (r.pluginName) {
4074
- const group = r.pluginName;
4075
- if (!groupedResults[group]) groupedResults[group] = [];
4076
- groupedResults[group].push(r);
4077
- } else ungroupedResults.push(r);
4078
- }
4053
+ if (skillResults.length === 1) if (r.pluginName) {
4054
+ const group = r.pluginName;
4055
+ if (!groupedResults[group]) groupedResults[group] = [];
4056
+ groupedResults[group].push(r);
4057
+ } else ungroupedResults.push(r);
4079
4058
  }
4080
4059
  const skillCount = bySkill.size;
4081
4060
  const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
@@ -4771,15 +4750,12 @@ async function removeCommand(skillNames, options) {
4771
4750
  }
4772
4751
  const remainingAgents = (await detectInstalledAgents()).filter((a) => !targetAgents.includes(a));
4773
4752
  let isStillUsed = false;
4774
- for (const agentKey of remainingAgents) {
4775
- const path = getInstallPath(skillName, agentKey, {
4776
- global: isGlobal,
4777
- cwd
4778
- });
4779
- if (await lstat(path).catch(() => null)) {
4780
- isStillUsed = true;
4781
- break;
4782
- }
4753
+ for (const agentKey of remainingAgents) if (await lstat(getInstallPath(skillName, agentKey, {
4754
+ global: isGlobal,
4755
+ cwd
4756
+ })).catch(() => null)) {
4757
+ isStillUsed = true;
4758
+ break;
4783
4759
  }
4784
4760
  if (!isStillUsed) await rm(canonicalPath, {
4785
4761
  recursive: true,
@@ -4919,14 +4895,12 @@ function parseUpdateOptions(args) {
4919
4895
  }
4920
4896
  function hasProjectSkills(cwd) {
4921
4897
  const dir = cwd || process.cwd();
4922
- const lockPath = join(dir, "skills-lock.json");
4923
- if (existsSync(lockPath)) return true;
4898
+ if (existsSync(join(dir, "skills-lock.json"))) return true;
4924
4899
  const skillsDir = join(dir, ".agents", "skills");
4925
4900
  try {
4926
4901
  const entries = readdirSync(skillsDir, { withFileTypes: true });
4927
4902
  for (const entry of entries) if (entry.isDirectory()) {
4928
- const skillMd = join(skillsDir, entry.name, "SKILL.md");
4929
- if (existsSync(skillMd)) return true;
4903
+ if (existsSync(join(skillsDir, entry.name, "SKILL.md"))) return true;
4930
4904
  }
4931
4905
  } catch {}
4932
4906
  return false;
@@ -5350,8 +5324,7 @@ async function updateProjectSkills(options = {}) {
5350
5324
  try {
5351
5325
  tempDir = await cloneRepo(sourceUrl, ref);
5352
5326
  const discoveredPaths = (await discoverSkills(tempDir)).map((s) => {
5353
- const relPath = relative(tempDir, s.path);
5354
- return join(relPath, "SKILL.md").split(sep).join("/");
5327
+ return join(relative(tempDir, s.path), "SKILL.md").split(sep).join("/");
5355
5328
  });
5356
5329
  deletedSkills = await checkAndPromptForDeletions(source, allLockedForSource, localLock.skills, false, options, discoveredPaths);
5357
5330
  } catch (error) {
@@ -6285,8 +6258,8 @@ const DIM$5 = "\x1B[38;5;102m";
6285
6258
  const TEXT$4 = "\x1B[38;5;145m";
6286
6259
  function formatFileSize(bytes) {
6287
6260
  if (bytes < 1024) return `${bytes} B`;
6288
- if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
6289
- return `${(bytes / 1048576).toFixed(1)} MB`;
6261
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
6262
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
6290
6263
  }
6291
6264
  async function runDocs(args, globalOpts) {
6292
6265
  switch (args[0]) {
@@ -6550,8 +6523,7 @@ async function publishFromDir(positionalArgs, api, namespace, visibility) {
6550
6523
  console.log("需要包含 frontmatter(name, description)的 SKILL.md 文件。");
6551
6524
  process.exit(1);
6552
6525
  }
6553
- const skillMdContent = fs.readFileSync(skillMdPath, "utf-8");
6554
- const { data: frontmatter } = parseFrontmatter(skillMdContent);
6526
+ const { data: frontmatter } = parseFrontmatter(fs.readFileSync(skillMdPath, "utf-8"));
6555
6527
  const skillName = frontmatter.name || path$1.basename(resolvedDir);
6556
6528
  console.log(`${DIM$4}正在从目录发布技能...${RESET$4}`);
6557
6529
  console.log(` ${BOLD$2}名称:${RESET$4} ${TEXT$3}${skillName}${RESET$4}`);
@@ -6598,8 +6570,7 @@ async function publishFromZip(positionalArgs, api, namespace, visibility) {
6598
6570
  }
6599
6571
  const skillDir = path$1.dirname(skillMdPath);
6600
6572
  console.log(` ${GREEN$3}在 ${path$1.relative(tmpDir, skillDir) || "."} 中找到 SKILL.md${RESET$4}`);
6601
- const skillMdContent = fs.readFileSync(skillMdPath, "utf-8");
6602
- const { data: frontmatter } = parseFrontmatter(skillMdContent);
6573
+ const { data: frontmatter } = parseFrontmatter(fs.readFileSync(skillMdPath, "utf-8"));
6603
6574
  const skillName = frontmatter.name || path$1.basename(skillDir);
6604
6575
  console.log(` ${BOLD$2}名称:${RESET$4} ${TEXT$3}${skillName}${RESET$4}`);
6605
6576
  console.log(` ${BOLD$2}命名空间:${RESET$4} ${TEXT$3}${namespace}${RESET$4}`);
@@ -6769,8 +6740,8 @@ function findSkillMd(dir) {
6769
6740
  }
6770
6741
  function formatSize(bytes) {
6771
6742
  if (bytes < 1024) return `${bytes} B`;
6772
- if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
6773
- return `${(bytes / 1048576).toFixed(1)} MB`;
6743
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
6744
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
6774
6745
  }
6775
6746
  function truncate(text, maxLen) {
6776
6747
  if (text.length <= maxLen) return text;
@@ -7055,8 +7026,7 @@ function printPackageHelp() {
7055
7026
  console.log();
7056
7027
  }
7057
7028
  async function handleLocalList(args, globalOpts) {
7058
- const cwd = getWorkdir(globalOpts, args);
7059
- const lock = loadLockfile(cwd);
7029
+ const lock = loadLockfile(getWorkdir(globalOpts, args));
7060
7030
  args.includes("-g") || args.includes("--global");
7061
7031
  const pkgs = lock.packages || {};
7062
7032
  const entries = Object.entries(pkgs);
@@ -7253,18 +7223,17 @@ async function handleInstall(args, api, globalOpts) {
7253
7223
  if (targetAgents.includes("eve")) {
7254
7224
  const availableSubagents = getEveSubagents(process.cwd());
7255
7225
  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
7226
  const selectedSubagents = await multiselect$1({
7266
7227
  message: "Eve 技能安装位置?",
7267
- options: subagentChoices,
7228
+ options: [{
7229
+ value: "",
7230
+ label: "根 Agent",
7231
+ hint: "agent/skills"
7232
+ }, ...availableSubagents.map((name) => ({
7233
+ value: name,
7234
+ label: name,
7235
+ hint: `agent/subagents/${name}/skills`
7236
+ }))],
7268
7237
  initialValues: [""],
7269
7238
  required: true
7270
7239
  });
@@ -7459,8 +7428,7 @@ async function handleUninstall(args, globalOpts) {
7459
7428
  }
7460
7429
  async function handleUpdate(args, api, globalOpts) {
7461
7430
  const pkgRef = args[0];
7462
- const cwd = getWorkdir(globalOpts, args);
7463
- const lock = loadLockfile(cwd);
7431
+ const lock = loadLockfile(getWorkdir(globalOpts, args));
7464
7432
  let packagesToUpdate = [];
7465
7433
  const pkgs = lock.packages || {};
7466
7434
  if (pkgRef) {
@@ -9880,7 +9848,7 @@ function runInit(args) {
9880
9848
  return;
9881
9849
  }
9882
9850
  if (hasName) mkdirSync(skillDir, { recursive: true });
9883
- const skillContent = `---
9851
+ writeFileSync(skillFile, `---
9884
9852
  name: ${skillName}
9885
9853
  description: A brief description of what this skill does
9886
9854
  ---
@@ -9898,8 +9866,7 @@ Describe when this skill should be used.
9898
9866
  1. First step
9899
9867
  2. Second step
9900
9868
  3. Additional steps as needed
9901
- `;
9902
- writeFileSync(skillFile, skillContent);
9869
+ `);
9903
9870
  console.log(`${TEXT}已初始化技能:${DIM}${skillName}${RESET}`);
9904
9871
  console.log();
9905
9872
  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
  }
@@ -1 +1 @@
1
- export {}
1
+ export { };
@@ -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 body = await resp.json().catch(() => ({}));
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bfi-cli",
3
- "version": "0.1.97",
3
+ "version": "0.1.98",
4
4
  "description": "用友大业财BFI统一命令行工具,支持技能,技能包,元数据,UI元数据等",
5
5
  "type": "module",
6
6
  "bin": {
@@ -36,6 +36,7 @@
36
36
  "devDependencies": {
37
37
  "@clack/prompts": "^1.2.0",
38
38
  "@types/bun": "latest",
39
+ "@types/json-bigint": "^1.0.4",
39
40
  "@types/node": "^22.10.0",
40
41
  "@types/tar-stream": "3.1.5",
41
42
  "@types/yauzl": "3.4.0",
@@ -53,11 +54,12 @@
53
54
  "dependencies": {
54
55
  "@modelcontextprotocol/sdk": "^1.12.0",
55
56
  "@vercel/detect-agent": "^1.2.3",
57
+ "json-bigint": "^1.0.0",
56
58
  "mysql2": "^3.14.0",
57
59
  "source-map": "^0.7.4",
58
60
  "tar-stream": "3.2.2",
59
- "yauzl": "3.4.0",
60
61
  "yaml": "^2.8.3",
62
+ "yauzl": "3.4.0",
61
63
  "zod": "^3.25.0"
62
64
  }
63
65
  }
Binary file