@bgicli/bgicli 2.8.6 → 2.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bgi.js CHANGED
@@ -17783,24 +17783,6 @@ var SKILL_ROUTES = [
17783
17783
  ]
17784
17784
  }
17785
17785
  ];
17786
- function routeSkill(message) {
17787
- const lower = message.toLowerCase();
17788
- const scores = /* @__PURE__ */ new Map();
17789
- for (const route of SKILL_ROUTES) {
17790
- let score = 0;
17791
- for (const kw of route.keywords) {
17792
- if (lower.includes(kw.toLowerCase())) {
17793
- score += 1 + kw.length * 0.1;
17794
- }
17795
- }
17796
- if (score > 0) scores.set(route.id, { route, score });
17797
- }
17798
- const sorted = Array.from(scores.values()).sort((a2, b2) => b2.score - a2.score).slice(0, 5);
17799
- return {
17800
- routes: sorted.map((v2) => v2.route),
17801
- topScore: sorted[0]?.score ?? 0
17802
- };
17803
- }
17804
17786
 
17805
17787
  // src/sessions.ts
17806
17788
  var import_fs5 = require("fs");
@@ -17928,7 +17910,7 @@ function clearCheckpoints(sessionId) {
17928
17910
 
17929
17911
  // src/index.ts
17930
17912
  var import_fs7 = require("fs");
17931
- var VERSION2 = "2.8.6";
17913
+ var VERSION2 = "2.8.7";
17932
17914
  var BRAND2 = "bgi".toLowerCase();
17933
17915
  var SKILLHUB_HUBS = {
17934
17916
  bgi: { label: "BGI \u672C\u5730", apiBase: "", backend: "local" },
@@ -18400,7 +18382,6 @@ async function llmRecommendSkills(userQuery) {
18400
18382
  const cfg = loadConfig();
18401
18383
  const ep = getActiveEndpoint(cfg);
18402
18384
  if (!ep.url) return [];
18403
- if (!ep.apiKey) return [];
18404
18385
  const baseURL = ep.url;
18405
18386
  const model = getCurrentModel(cfg);
18406
18387
  const apiKey = ep.apiKey;
@@ -18418,7 +18399,8 @@ async function llmRecommendSkills(userQuery) {
18418
18399
  if (catalogLines.length === 0) return [];
18419
18400
  const catalog = catalogLines.join("\n");
18420
18401
  const systemMsg = `\u4F60\u662F\u4E00\u4E2A\u751F\u7269\u4FE1\u606F\u5B66 Skill \u63A8\u8350\u52A9\u624B\u3002
18421
- \u7528\u6237\u4F1A\u63CF\u8FF0\u4ED6\u4EEC\u60F3\u505A\u7684\u5206\u6790\u4EFB\u52A1\uFF0C\u4F60\u9700\u8981\u4ECE\u4E0B\u9762\u7684 Skill \u76EE\u5F55\u4E2D\u63A8\u8350\u6700\u76F8\u5173\u7684 5 \u4E2A\uFF08\u6216\u66F4\u5C11\uFF09\u3002
18402
+ \u7528\u6237\u4F1A\u63CF\u8FF0\u4ED6\u4EEC\u60F3\u505A\u7684\u5206\u6790\u4EFB\u52A1\uFF0C\u4F60\u9700\u8981\u4ECE\u4E0B\u9762\u7684 Skill \u76EE\u5F55\u4E2D\u63A8\u8350\u6700\u76F8\u5173\u7684 1-3 \u4E2A\u3002
18403
+ \u53EA\u63A8\u8350\u771F\u6B63\u9700\u8981\u7684\uFF0C\u4E0D\u8981\u51D1\u6570\u3002\u5982\u679C\u6CA1\u6709\u5408\u9002\u7684\u5C31\u8FD4\u56DE\u7A7A\u6570\u7EC4 []\u3002
18422
18404
 
18423
18405
  Skill \u76EE\u5F55\uFF08\u683C\u5F0F: id|\u540D\u79F0 \u2014 \u7B80\u4ECB\uFF09\uFF1A
18424
18406
  ${catalog}
@@ -18436,15 +18418,16 @@ ${catalog}
18436
18418
  { role: "system", content: systemMsg },
18437
18419
  { role: "user", content: userQuery }
18438
18420
  ],
18439
- temperature: 0.2,
18440
- max_tokens: 800
18421
+ temperature: 0.1,
18422
+ max_tokens: 400
18441
18423
  });
18442
18424
  const text = resp.choices[0]?.message?.content ?? "";
18443
- const jsonMatch = text.match(/\[[\s\S]*\]/);
18425
+ const stripped = text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
18426
+ const jsonMatch = stripped.match(/\[[\s\S]*\]/);
18444
18427
  if (!jsonMatch) return [];
18445
18428
  const parsed = JSON.parse(jsonMatch[0]);
18446
18429
  const validIds = new Set(all.map((e2) => e2.id));
18447
- return parsed.filter((r2) => r2.id && validIds.has(r2.id)).slice(0, 5);
18430
+ return parsed.filter((r2) => r2.id && validIds.has(r2.id)).slice(0, 3);
18448
18431
  } catch {
18449
18432
  return [];
18450
18433
  }
@@ -20189,33 +20172,52 @@ async function main() {
20189
20172
  console.log();
20190
20173
  continue;
20191
20174
  }
20192
- const { routes: suggestedRoutes, topScore } = routeSkill(trimmed);
20193
- const newRoutes = suggestedRoutes.filter((r2) => !injectedSkills.has(r2.id));
20194
- if (newRoutes.length === 1 && topScore >= 8) {
20195
- await injectSkill(newRoutes[0].id, history, injectedSkills, rl, false);
20196
- } else if (newRoutes.length >= 1 && topScore >= 2) {
20197
- const candidates = newRoutes.slice(0, 3);
20198
- console.log();
20199
- console.log(source_default.bold.yellow("\u250C\u2500 \u{1F50D} \u68C0\u6D4B\u5230\u76F8\u5173\u6280\u80FD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20200
- candidates.forEach((r2, i2) => {
20201
- console.log(`\u2502 ${source_default.bold.cyan(`[${i2 + 1}]`)} ${source_default.cyan(r2.id)}${source_default.dim(" \u2014")} ${r2.name}`);
20202
- });
20203
- console.log(source_default.bold.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20204
- const pickPrompt = candidates.length > 1 ? ` \u6FC0\u6D3B\u54EA\u4E2A\u6280\u80FD\uFF1F\u8F93\u5165\u7F16\u53F7 (\u5982 1 \u6216 1,2)\uFF0C\u56DE\u8F66\u8DF3\u8FC7 \u203A ` : ` \u6FC0\u6D3B\u6B64\u6280\u80FD\uFF1F[Y/n] \u203A `;
20205
- const skillChoice = await question(rl, source_default.yellow(pickPrompt));
20206
- const choiceTrimmed = skillChoice.trim().toLowerCase();
20207
- if (choiceTrimmed !== "" && choiceTrimmed !== "n") {
20208
- let indices;
20209
- if (candidates.length === 1) {
20210
- indices = choiceTrimmed === "y" || choiceTrimmed === "" ? [0] : [];
20211
- } else {
20212
- indices = choiceTrimmed.split(",").map((s2) => parseInt(s2.trim(), 10) - 1).filter((i2) => i2 >= 0 && i2 < candidates.length);
20175
+ {
20176
+ const SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
20177
+ let spinIdx2 = 0;
20178
+ process.stdout.write(source_default.dim(" \u6B63\u5728\u68C0\u7D22\u76F8\u5173\u6280\u80FD..."));
20179
+ const spinTimer = setInterval(() => {
20180
+ spinIdx2 = (spinIdx2 + 1) % SPIN.length;
20181
+ process.stdout.write(`\r${source_default.dim(` ${SPIN[spinIdx2]} \u6B63\u5728\u68C0\u7D22\u76F8\u5173\u6280\u80FD...`)}`);
20182
+ }, 80);
20183
+ let recs = [];
20184
+ try {
20185
+ recs = await llmRecommendSkills(trimmed);
20186
+ } catch {
20187
+ }
20188
+ clearInterval(spinTimer);
20189
+ process.stdout.write("\r\x1B[K");
20190
+ const newRecs = recs.filter((r2) => !injectedSkills.has(r2.id));
20191
+ if (newRecs.length === 1) {
20192
+ console.log();
20193
+ console.log(source_default.bold.yellow("\u250C\u2500 \u68C0\u6D4B\u5230\u76F8\u5173\u6280\u80FD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20194
+ console.log(`\u2502 ${source_default.bold.cyan("[1]")} ${source_default.cyan(newRecs[0].id)}${source_default.dim(" \u2014")} ${newRecs[0].name}`);
20195
+ console.log(source_default.dim(`\u2502 ${newRecs[0].reason}`));
20196
+ console.log(source_default.bold.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20197
+ const skillChoice = await question(rl, source_default.yellow(" \u6FC0\u6D3B\u6B64\u6280\u80FD\uFF1F[Y/n] \u203A "));
20198
+ const c2 = skillChoice.trim().toLowerCase();
20199
+ if (c2 === "" || c2 === "y") {
20200
+ await injectSkill(newRecs[0].id, history, injectedSkills, rl, true);
20213
20201
  }
20214
- for (const idx of indices) {
20215
- await injectSkill(candidates[idx].id, history, injectedSkills, rl, true);
20202
+ console.log();
20203
+ } else if (newRecs.length > 1) {
20204
+ console.log();
20205
+ console.log(source_default.bold.yellow("\u250C\u2500 \u68C0\u6D4B\u5230\u76F8\u5173\u6280\u80FD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20206
+ newRecs.forEach((r2, i2) => {
20207
+ console.log(`\u2502 ${source_default.bold.cyan(`[${i2 + 1}]`)} ${source_default.cyan(r2.id)}${source_default.dim(" \u2014")} ${r2.name}`);
20208
+ console.log(source_default.dim(`\u2502 ${r2.reason}`));
20209
+ });
20210
+ console.log(source_default.bold.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20211
+ const skillChoice = await question(rl, source_default.yellow(` \u6FC0\u6D3B\u54EA\u4E2A\u6280\u80FD\uFF1F\u8F93\u5165\u7F16\u53F7 (\u5982 1 \u6216 1,2)\uFF0C\u56DE\u8F66\u8DF3\u8FC7 \u203A `));
20212
+ const c2 = skillChoice.trim().toLowerCase();
20213
+ if (c2 !== "" && c2 !== "n") {
20214
+ const indices = c2.split(",").map((s2) => parseInt(s2.trim(), 10) - 1).filter((i2) => i2 >= 0 && i2 < newRecs.length);
20215
+ for (const idx of indices) {
20216
+ await injectSkill(newRecs[idx].id, history, injectedSkills, rl, true);
20217
+ }
20216
20218
  }
20219
+ console.log();
20217
20220
  }
20218
- console.log();
20219
20221
  }
20220
20222
  const expanded = expandFileRefs(trimmed);
20221
20223
  const userContent = thinkMode ? `/think
package/dist/bio.js CHANGED
@@ -17783,24 +17783,6 @@ var SKILL_ROUTES = [
17783
17783
  ]
17784
17784
  }
17785
17785
  ];
17786
- function routeSkill(message) {
17787
- const lower = message.toLowerCase();
17788
- const scores = /* @__PURE__ */ new Map();
17789
- for (const route of SKILL_ROUTES) {
17790
- let score = 0;
17791
- for (const kw of route.keywords) {
17792
- if (lower.includes(kw.toLowerCase())) {
17793
- score += 1 + kw.length * 0.1;
17794
- }
17795
- }
17796
- if (score > 0) scores.set(route.id, { route, score });
17797
- }
17798
- const sorted = Array.from(scores.values()).sort((a2, b2) => b2.score - a2.score).slice(0, 5);
17799
- return {
17800
- routes: sorted.map((v2) => v2.route),
17801
- topScore: sorted[0]?.score ?? 0
17802
- };
17803
- }
17804
17786
 
17805
17787
  // src/sessions.ts
17806
17788
  var import_fs5 = require("fs");
@@ -17928,7 +17910,7 @@ function clearCheckpoints(sessionId) {
17928
17910
 
17929
17911
  // src/index.ts
17930
17912
  var import_fs7 = require("fs");
17931
- var VERSION2 = "2.8.6";
17913
+ var VERSION2 = "2.8.7";
17932
17914
  var BRAND2 = "bio".toLowerCase();
17933
17915
  var SKILLHUB_HUBS = {
17934
17916
  bgi: { label: "BGI \u672C\u5730", apiBase: "", backend: "local" },
@@ -18400,7 +18382,6 @@ async function llmRecommendSkills(userQuery) {
18400
18382
  const cfg = loadConfig();
18401
18383
  const ep = getActiveEndpoint(cfg);
18402
18384
  if (!ep.url) return [];
18403
- if (!ep.apiKey) return [];
18404
18385
  const baseURL = ep.url;
18405
18386
  const model = getCurrentModel(cfg);
18406
18387
  const apiKey = ep.apiKey;
@@ -18418,7 +18399,8 @@ async function llmRecommendSkills(userQuery) {
18418
18399
  if (catalogLines.length === 0) return [];
18419
18400
  const catalog = catalogLines.join("\n");
18420
18401
  const systemMsg = `\u4F60\u662F\u4E00\u4E2A\u751F\u7269\u4FE1\u606F\u5B66 Skill \u63A8\u8350\u52A9\u624B\u3002
18421
- \u7528\u6237\u4F1A\u63CF\u8FF0\u4ED6\u4EEC\u60F3\u505A\u7684\u5206\u6790\u4EFB\u52A1\uFF0C\u4F60\u9700\u8981\u4ECE\u4E0B\u9762\u7684 Skill \u76EE\u5F55\u4E2D\u63A8\u8350\u6700\u76F8\u5173\u7684 5 \u4E2A\uFF08\u6216\u66F4\u5C11\uFF09\u3002
18402
+ \u7528\u6237\u4F1A\u63CF\u8FF0\u4ED6\u4EEC\u60F3\u505A\u7684\u5206\u6790\u4EFB\u52A1\uFF0C\u4F60\u9700\u8981\u4ECE\u4E0B\u9762\u7684 Skill \u76EE\u5F55\u4E2D\u63A8\u8350\u6700\u76F8\u5173\u7684 1-3 \u4E2A\u3002
18403
+ \u53EA\u63A8\u8350\u771F\u6B63\u9700\u8981\u7684\uFF0C\u4E0D\u8981\u51D1\u6570\u3002\u5982\u679C\u6CA1\u6709\u5408\u9002\u7684\u5C31\u8FD4\u56DE\u7A7A\u6570\u7EC4 []\u3002
18422
18404
 
18423
18405
  Skill \u76EE\u5F55\uFF08\u683C\u5F0F: id|\u540D\u79F0 \u2014 \u7B80\u4ECB\uFF09\uFF1A
18424
18406
  ${catalog}
@@ -18436,15 +18418,16 @@ ${catalog}
18436
18418
  { role: "system", content: systemMsg },
18437
18419
  { role: "user", content: userQuery }
18438
18420
  ],
18439
- temperature: 0.2,
18440
- max_tokens: 800
18421
+ temperature: 0.1,
18422
+ max_tokens: 400
18441
18423
  });
18442
18424
  const text = resp.choices[0]?.message?.content ?? "";
18443
- const jsonMatch = text.match(/\[[\s\S]*\]/);
18425
+ const stripped = text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
18426
+ const jsonMatch = stripped.match(/\[[\s\S]*\]/);
18444
18427
  if (!jsonMatch) return [];
18445
18428
  const parsed = JSON.parse(jsonMatch[0]);
18446
18429
  const validIds = new Set(all.map((e2) => e2.id));
18447
- return parsed.filter((r2) => r2.id && validIds.has(r2.id)).slice(0, 5);
18430
+ return parsed.filter((r2) => r2.id && validIds.has(r2.id)).slice(0, 3);
18448
18431
  } catch {
18449
18432
  return [];
18450
18433
  }
@@ -20189,33 +20172,52 @@ async function main() {
20189
20172
  console.log();
20190
20173
  continue;
20191
20174
  }
20192
- const { routes: suggestedRoutes, topScore } = routeSkill(trimmed);
20193
- const newRoutes = suggestedRoutes.filter((r2) => !injectedSkills.has(r2.id));
20194
- if (newRoutes.length === 1 && topScore >= 8) {
20195
- await injectSkill(newRoutes[0].id, history, injectedSkills, rl, false);
20196
- } else if (newRoutes.length >= 1 && topScore >= 2) {
20197
- const candidates = newRoutes.slice(0, 3);
20198
- console.log();
20199
- console.log(source_default.bold.yellow("\u250C\u2500 \u{1F50D} \u68C0\u6D4B\u5230\u76F8\u5173\u6280\u80FD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20200
- candidates.forEach((r2, i2) => {
20201
- console.log(`\u2502 ${source_default.bold.cyan(`[${i2 + 1}]`)} ${source_default.cyan(r2.id)}${source_default.dim(" \u2014")} ${r2.name}`);
20202
- });
20203
- console.log(source_default.bold.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20204
- const pickPrompt = candidates.length > 1 ? ` \u6FC0\u6D3B\u54EA\u4E2A\u6280\u80FD\uFF1F\u8F93\u5165\u7F16\u53F7 (\u5982 1 \u6216 1,2)\uFF0C\u56DE\u8F66\u8DF3\u8FC7 \u203A ` : ` \u6FC0\u6D3B\u6B64\u6280\u80FD\uFF1F[Y/n] \u203A `;
20205
- const skillChoice = await question(rl, source_default.yellow(pickPrompt));
20206
- const choiceTrimmed = skillChoice.trim().toLowerCase();
20207
- if (choiceTrimmed !== "" && choiceTrimmed !== "n") {
20208
- let indices;
20209
- if (candidates.length === 1) {
20210
- indices = choiceTrimmed === "y" || choiceTrimmed === "" ? [0] : [];
20211
- } else {
20212
- indices = choiceTrimmed.split(",").map((s2) => parseInt(s2.trim(), 10) - 1).filter((i2) => i2 >= 0 && i2 < candidates.length);
20175
+ {
20176
+ const SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
20177
+ let spinIdx2 = 0;
20178
+ process.stdout.write(source_default.dim(" \u6B63\u5728\u68C0\u7D22\u76F8\u5173\u6280\u80FD..."));
20179
+ const spinTimer = setInterval(() => {
20180
+ spinIdx2 = (spinIdx2 + 1) % SPIN.length;
20181
+ process.stdout.write(`\r${source_default.dim(` ${SPIN[spinIdx2]} \u6B63\u5728\u68C0\u7D22\u76F8\u5173\u6280\u80FD...`)}`);
20182
+ }, 80);
20183
+ let recs = [];
20184
+ try {
20185
+ recs = await llmRecommendSkills(trimmed);
20186
+ } catch {
20187
+ }
20188
+ clearInterval(spinTimer);
20189
+ process.stdout.write("\r\x1B[K");
20190
+ const newRecs = recs.filter((r2) => !injectedSkills.has(r2.id));
20191
+ if (newRecs.length === 1) {
20192
+ console.log();
20193
+ console.log(source_default.bold.yellow("\u250C\u2500 \u68C0\u6D4B\u5230\u76F8\u5173\u6280\u80FD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20194
+ console.log(`\u2502 ${source_default.bold.cyan("[1]")} ${source_default.cyan(newRecs[0].id)}${source_default.dim(" \u2014")} ${newRecs[0].name}`);
20195
+ console.log(source_default.dim(`\u2502 ${newRecs[0].reason}`));
20196
+ console.log(source_default.bold.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20197
+ const skillChoice = await question(rl, source_default.yellow(" \u6FC0\u6D3B\u6B64\u6280\u80FD\uFF1F[Y/n] \u203A "));
20198
+ const c2 = skillChoice.trim().toLowerCase();
20199
+ if (c2 === "" || c2 === "y") {
20200
+ await injectSkill(newRecs[0].id, history, injectedSkills, rl, true);
20213
20201
  }
20214
- for (const idx of indices) {
20215
- await injectSkill(candidates[idx].id, history, injectedSkills, rl, true);
20202
+ console.log();
20203
+ } else if (newRecs.length > 1) {
20204
+ console.log();
20205
+ console.log(source_default.bold.yellow("\u250C\u2500 \u68C0\u6D4B\u5230\u76F8\u5173\u6280\u80FD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20206
+ newRecs.forEach((r2, i2) => {
20207
+ console.log(`\u2502 ${source_default.bold.cyan(`[${i2 + 1}]`)} ${source_default.cyan(r2.id)}${source_default.dim(" \u2014")} ${r2.name}`);
20208
+ console.log(source_default.dim(`\u2502 ${r2.reason}`));
20209
+ });
20210
+ console.log(source_default.bold.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20211
+ const skillChoice = await question(rl, source_default.yellow(` \u6FC0\u6D3B\u54EA\u4E2A\u6280\u80FD\uFF1F\u8F93\u5165\u7F16\u53F7 (\u5982 1 \u6216 1,2)\uFF0C\u56DE\u8F66\u8DF3\u8FC7 \u203A `));
20212
+ const c2 = skillChoice.trim().toLowerCase();
20213
+ if (c2 !== "" && c2 !== "n") {
20214
+ const indices = c2.split(",").map((s2) => parseInt(s2.trim(), 10) - 1).filter((i2) => i2 >= 0 && i2 < newRecs.length);
20215
+ for (const idx of indices) {
20216
+ await injectSkill(newRecs[idx].id, history, injectedSkills, rl, true);
20217
+ }
20216
20218
  }
20219
+ console.log();
20217
20220
  }
20218
- console.log();
20219
20221
  }
20220
20222
  const expanded = expandFileRefs(trimmed);
20221
20223
  const userContent = thinkMode ? `/think
package/dist/mbp.js CHANGED
@@ -17783,24 +17783,6 @@ var SKILL_ROUTES = [
17783
17783
  ]
17784
17784
  }
17785
17785
  ];
17786
- function routeSkill(message) {
17787
- const lower = message.toLowerCase();
17788
- const scores = /* @__PURE__ */ new Map();
17789
- for (const route of SKILL_ROUTES) {
17790
- let score = 0;
17791
- for (const kw of route.keywords) {
17792
- if (lower.includes(kw.toLowerCase())) {
17793
- score += 1 + kw.length * 0.1;
17794
- }
17795
- }
17796
- if (score > 0) scores.set(route.id, { route, score });
17797
- }
17798
- const sorted = Array.from(scores.values()).sort((a2, b2) => b2.score - a2.score).slice(0, 5);
17799
- return {
17800
- routes: sorted.map((v2) => v2.route),
17801
- topScore: sorted[0]?.score ?? 0
17802
- };
17803
- }
17804
17786
 
17805
17787
  // src/sessions.ts
17806
17788
  var import_fs5 = require("fs");
@@ -17928,7 +17910,7 @@ function clearCheckpoints(sessionId) {
17928
17910
 
17929
17911
  // src/index.ts
17930
17912
  var import_fs7 = require("fs");
17931
- var VERSION2 = "2.8.6";
17913
+ var VERSION2 = "2.8.7";
17932
17914
  var BRAND2 = "mbp".toLowerCase();
17933
17915
  var SKILLHUB_HUBS = {
17934
17916
  bgi: { label: "BGI \u672C\u5730", apiBase: "", backend: "local" },
@@ -18400,7 +18382,6 @@ async function llmRecommendSkills(userQuery) {
18400
18382
  const cfg = loadConfig();
18401
18383
  const ep = getActiveEndpoint(cfg);
18402
18384
  if (!ep.url) return [];
18403
- if (!ep.apiKey) return [];
18404
18385
  const baseURL = ep.url;
18405
18386
  const model = getCurrentModel(cfg);
18406
18387
  const apiKey = ep.apiKey;
@@ -18418,7 +18399,8 @@ async function llmRecommendSkills(userQuery) {
18418
18399
  if (catalogLines.length === 0) return [];
18419
18400
  const catalog = catalogLines.join("\n");
18420
18401
  const systemMsg = `\u4F60\u662F\u4E00\u4E2A\u751F\u7269\u4FE1\u606F\u5B66 Skill \u63A8\u8350\u52A9\u624B\u3002
18421
- \u7528\u6237\u4F1A\u63CF\u8FF0\u4ED6\u4EEC\u60F3\u505A\u7684\u5206\u6790\u4EFB\u52A1\uFF0C\u4F60\u9700\u8981\u4ECE\u4E0B\u9762\u7684 Skill \u76EE\u5F55\u4E2D\u63A8\u8350\u6700\u76F8\u5173\u7684 5 \u4E2A\uFF08\u6216\u66F4\u5C11\uFF09\u3002
18402
+ \u7528\u6237\u4F1A\u63CF\u8FF0\u4ED6\u4EEC\u60F3\u505A\u7684\u5206\u6790\u4EFB\u52A1\uFF0C\u4F60\u9700\u8981\u4ECE\u4E0B\u9762\u7684 Skill \u76EE\u5F55\u4E2D\u63A8\u8350\u6700\u76F8\u5173\u7684 1-3 \u4E2A\u3002
18403
+ \u53EA\u63A8\u8350\u771F\u6B63\u9700\u8981\u7684\uFF0C\u4E0D\u8981\u51D1\u6570\u3002\u5982\u679C\u6CA1\u6709\u5408\u9002\u7684\u5C31\u8FD4\u56DE\u7A7A\u6570\u7EC4 []\u3002
18422
18404
 
18423
18405
  Skill \u76EE\u5F55\uFF08\u683C\u5F0F: id|\u540D\u79F0 \u2014 \u7B80\u4ECB\uFF09\uFF1A
18424
18406
  ${catalog}
@@ -18436,15 +18418,16 @@ ${catalog}
18436
18418
  { role: "system", content: systemMsg },
18437
18419
  { role: "user", content: userQuery }
18438
18420
  ],
18439
- temperature: 0.2,
18440
- max_tokens: 800
18421
+ temperature: 0.1,
18422
+ max_tokens: 400
18441
18423
  });
18442
18424
  const text = resp.choices[0]?.message?.content ?? "";
18443
- const jsonMatch = text.match(/\[[\s\S]*\]/);
18425
+ const stripped = text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
18426
+ const jsonMatch = stripped.match(/\[[\s\S]*\]/);
18444
18427
  if (!jsonMatch) return [];
18445
18428
  const parsed = JSON.parse(jsonMatch[0]);
18446
18429
  const validIds = new Set(all.map((e2) => e2.id));
18447
- return parsed.filter((r2) => r2.id && validIds.has(r2.id)).slice(0, 5);
18430
+ return parsed.filter((r2) => r2.id && validIds.has(r2.id)).slice(0, 3);
18448
18431
  } catch {
18449
18432
  return [];
18450
18433
  }
@@ -20189,33 +20172,52 @@ async function main() {
20189
20172
  console.log();
20190
20173
  continue;
20191
20174
  }
20192
- const { routes: suggestedRoutes, topScore } = routeSkill(trimmed);
20193
- const newRoutes = suggestedRoutes.filter((r2) => !injectedSkills.has(r2.id));
20194
- if (newRoutes.length === 1 && topScore >= 8) {
20195
- await injectSkill(newRoutes[0].id, history, injectedSkills, rl, false);
20196
- } else if (newRoutes.length >= 1 && topScore >= 2) {
20197
- const candidates = newRoutes.slice(0, 3);
20198
- console.log();
20199
- console.log(source_default.bold.yellow("\u250C\u2500 \u{1F50D} \u68C0\u6D4B\u5230\u76F8\u5173\u6280\u80FD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20200
- candidates.forEach((r2, i2) => {
20201
- console.log(`\u2502 ${source_default.bold.cyan(`[${i2 + 1}]`)} ${source_default.cyan(r2.id)}${source_default.dim(" \u2014")} ${r2.name}`);
20202
- });
20203
- console.log(source_default.bold.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20204
- const pickPrompt = candidates.length > 1 ? ` \u6FC0\u6D3B\u54EA\u4E2A\u6280\u80FD\uFF1F\u8F93\u5165\u7F16\u53F7 (\u5982 1 \u6216 1,2)\uFF0C\u56DE\u8F66\u8DF3\u8FC7 \u203A ` : ` \u6FC0\u6D3B\u6B64\u6280\u80FD\uFF1F[Y/n] \u203A `;
20205
- const skillChoice = await question(rl, source_default.yellow(pickPrompt));
20206
- const choiceTrimmed = skillChoice.trim().toLowerCase();
20207
- if (choiceTrimmed !== "" && choiceTrimmed !== "n") {
20208
- let indices;
20209
- if (candidates.length === 1) {
20210
- indices = choiceTrimmed === "y" || choiceTrimmed === "" ? [0] : [];
20211
- } else {
20212
- indices = choiceTrimmed.split(",").map((s2) => parseInt(s2.trim(), 10) - 1).filter((i2) => i2 >= 0 && i2 < candidates.length);
20175
+ {
20176
+ const SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
20177
+ let spinIdx2 = 0;
20178
+ process.stdout.write(source_default.dim(" \u6B63\u5728\u68C0\u7D22\u76F8\u5173\u6280\u80FD..."));
20179
+ const spinTimer = setInterval(() => {
20180
+ spinIdx2 = (spinIdx2 + 1) % SPIN.length;
20181
+ process.stdout.write(`\r${source_default.dim(` ${SPIN[spinIdx2]} \u6B63\u5728\u68C0\u7D22\u76F8\u5173\u6280\u80FD...`)}`);
20182
+ }, 80);
20183
+ let recs = [];
20184
+ try {
20185
+ recs = await llmRecommendSkills(trimmed);
20186
+ } catch {
20187
+ }
20188
+ clearInterval(spinTimer);
20189
+ process.stdout.write("\r\x1B[K");
20190
+ const newRecs = recs.filter((r2) => !injectedSkills.has(r2.id));
20191
+ if (newRecs.length === 1) {
20192
+ console.log();
20193
+ console.log(source_default.bold.yellow("\u250C\u2500 \u68C0\u6D4B\u5230\u76F8\u5173\u6280\u80FD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20194
+ console.log(`\u2502 ${source_default.bold.cyan("[1]")} ${source_default.cyan(newRecs[0].id)}${source_default.dim(" \u2014")} ${newRecs[0].name}`);
20195
+ console.log(source_default.dim(`\u2502 ${newRecs[0].reason}`));
20196
+ console.log(source_default.bold.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20197
+ const skillChoice = await question(rl, source_default.yellow(" \u6FC0\u6D3B\u6B64\u6280\u80FD\uFF1F[Y/n] \u203A "));
20198
+ const c2 = skillChoice.trim().toLowerCase();
20199
+ if (c2 === "" || c2 === "y") {
20200
+ await injectSkill(newRecs[0].id, history, injectedSkills, rl, true);
20213
20201
  }
20214
- for (const idx of indices) {
20215
- await injectSkill(candidates[idx].id, history, injectedSkills, rl, true);
20202
+ console.log();
20203
+ } else if (newRecs.length > 1) {
20204
+ console.log();
20205
+ console.log(source_default.bold.yellow("\u250C\u2500 \u68C0\u6D4B\u5230\u76F8\u5173\u6280\u80FD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20206
+ newRecs.forEach((r2, i2) => {
20207
+ console.log(`\u2502 ${source_default.bold.cyan(`[${i2 + 1}]`)} ${source_default.cyan(r2.id)}${source_default.dim(" \u2014")} ${r2.name}`);
20208
+ console.log(source_default.dim(`\u2502 ${r2.reason}`));
20209
+ });
20210
+ console.log(source_default.bold.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
20211
+ const skillChoice = await question(rl, source_default.yellow(` \u6FC0\u6D3B\u54EA\u4E2A\u6280\u80FD\uFF1F\u8F93\u5165\u7F16\u53F7 (\u5982 1 \u6216 1,2)\uFF0C\u56DE\u8F66\u8DF3\u8FC7 \u203A `));
20212
+ const c2 = skillChoice.trim().toLowerCase();
20213
+ if (c2 !== "" && c2 !== "n") {
20214
+ const indices = c2.split(",").map((s2) => parseInt(s2.trim(), 10) - 1).filter((i2) => i2 >= 0 && i2 < newRecs.length);
20215
+ for (const idx of indices) {
20216
+ await injectSkill(newRecs[idx].id, history, injectedSkills, rl, true);
20217
+ }
20216
20218
  }
20219
+ console.log();
20217
20220
  }
20218
- console.log();
20219
20221
  }
20220
20222
  const expanded = expandFileRefs(trimmed);
20221
20223
  const userContent = thinkMode ? `/think
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgicli/bgicli",
3
- "version": "2.8.6",
3
+ "version": "2.8.7",
4
4
  "description": "BGI CLI — Bioinformatics AI terminal for Chinese researchers (百炼/DeepSeek/Kimi/Qwen)",
5
5
  "bin": {
6
6
  "bgi": "dist/bgi.js",