@bgicli/bgicli 2.8.0 → 2.8.2

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.
Files changed (4) hide show
  1. package/dist/bgi.js +132 -109
  2. package/dist/bio.js +132 -109
  3. package/dist/mbp.js +132 -109
  4. package/package.json +1 -1
package/dist/bgi.js CHANGED
@@ -14366,52 +14366,6 @@ function ensureDirs() {
14366
14366
  if (!(0, import_fs2.existsSync)(dir)) (0, import_fs2.mkdirSync)(dir, { recursive: true });
14367
14367
  }
14368
14368
  }
14369
- var PRESET_ENDPOINTS = [
14370
- {
14371
- name: "\u767E\u70BC \xB7 \u963F\u91CC\u4E91 (DashScope)",
14372
- url: "https://dashscope.aliyuncs.com/compatible-mode/v1",
14373
- models: [
14374
- "qwen3.5-plus",
14375
- "qwen3.5-flash",
14376
- "qwen3-235b-a22b",
14377
- "qwen3-max",
14378
- "qwen3-32b",
14379
- "qwen-max",
14380
- "qwen-plus",
14381
- "qwen-turbo",
14382
- "qwen-long",
14383
- "deepseek-v3",
14384
- "deepseek-r1",
14385
- "qwq-plus",
14386
- "MiniMax-M2.5"
14387
- ],
14388
- activeModel: "qwen3.5-plus"
14389
- },
14390
- {
14391
- name: "DeepSeek",
14392
- url: "https://api.deepseek.com/v1",
14393
- models: ["deepseek-chat", "deepseek-reasoner"],
14394
- activeModel: "deepseek-chat"
14395
- },
14396
- {
14397
- name: "Moonshot (Kimi)",
14398
- url: "https://api.moonshot.cn/v1",
14399
- models: ["moonshot-v1-8k", "moonshot-v1-32k", "moonshot-v1-128k", "kimi-k2.5"],
14400
- activeModel: "moonshot-v1-8k"
14401
- },
14402
- {
14403
- name: "MiniMax",
14404
- url: "https://api.minimax.chat/v1",
14405
- models: ["MiniMax-M2.5", "MiniMax-Text-01"],
14406
- activeModel: "MiniMax-M2.5"
14407
- },
14408
- {
14409
- name: "\u5185\u7F51 Qwen3-235B",
14410
- url: "http://172.16.224.137:1024/v1",
14411
- models: ["Qwen3-235B-A22B"],
14412
- activeModel: "Qwen3-235B-A22B"
14413
- }
14414
- ];
14415
14369
  function getActiveEndpoint(cfg) {
14416
14370
  return cfg.endpoints[cfg.activeIndex] ?? cfg.endpoints[0] ?? {
14417
14371
  name: "\u672A\u914D\u7F6E",
@@ -14438,30 +14392,27 @@ function isOldFormat(raw) {
14438
14392
  return typeof raw["provider"] === "string" && !Array.isArray(raw["endpoints"]);
14439
14393
  }
14440
14394
  function migrateOldConfig(old) {
14441
- const provider = old["provider"] ?? "bailian";
14395
+ const provider = old["provider"] ?? "custom";
14442
14396
  const apiKeys = old["apiKeys"] ?? {};
14443
14397
  const model = old["model"] ?? "";
14444
- let ep;
14445
- if (provider === "custom") {
14446
- ep = {
14447
- name: "\u81EA\u5B9A\u4E49",
14448
- url: old["customUrl"] ?? "",
14449
- apiKey: apiKeys["custom"],
14450
- models: old["customModel"] ? [old["customModel"]] : [],
14451
- activeModel: old["customModel"] ?? model
14452
- };
14453
- } else if (provider === "intranet") {
14454
- ep = { ...PRESET_ENDPOINTS[4], apiKey: void 0 };
14455
- } else {
14456
- const presetMap = {
14457
- bailian: 0,
14458
- deepseek: 1,
14459
- kimi: 2,
14460
- minimax: 3
14461
- };
14462
- const preset = PRESET_ENDPOINTS[presetMap[provider] ?? 0];
14463
- ep = { ...preset, apiKey: apiKeys[provider], activeModel: model || preset.activeModel };
14464
- }
14398
+ const legacyUrls = {
14399
+ bailian: "https://dashscope.aliyuncs.com/compatible-mode/v1",
14400
+ deepseek: "https://api.deepseek.com/v1",
14401
+ kimi: "https://api.moonshot.cn/v1",
14402
+ minimax: "https://api.minimax.chat/v1",
14403
+ intranet: "http://172.16.0.1:8080/v1"
14404
+ };
14405
+ const url = provider === "custom" ? old["customUrl"] ?? "" : legacyUrls[provider] ?? "";
14406
+ const name = provider === "custom" ? old["customUrl"] ?? "\u81EA\u5B9A\u4E49" : provider;
14407
+ const mdl = provider === "custom" ? old["customModel"] ?? model : model;
14408
+ const apiKey = provider === "intranet" ? void 0 : apiKeys[provider] ?? apiKeys["custom"];
14409
+ const ep = {
14410
+ name,
14411
+ url,
14412
+ apiKey,
14413
+ models: mdl ? [mdl] : [],
14414
+ activeModel: mdl || void 0
14415
+ };
14465
14416
  return {
14466
14417
  endpoints: [ep],
14467
14418
  activeIndex: 0,
@@ -15320,6 +15271,96 @@ async function streamOnce(client, messages, model, signal) {
15320
15271
  let finishReason = null;
15321
15272
  let inputTokens = 0;
15322
15273
  let outputTokens = 0;
15274
+ const THINK_OPEN = "<think>";
15275
+ const THINK_CLOSE = "</think>";
15276
+ const SPIN_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
15277
+ let pendingBuf = "";
15278
+ let inThink = false;
15279
+ let thinkBuf = "";
15280
+ let thinkStartMs = 0;
15281
+ let spinInterval = null;
15282
+ let spinIdx = 0;
15283
+ let normalWritten = false;
15284
+ const writeNormal = (s2) => {
15285
+ if (!s2) return;
15286
+ process.stdout.write(s2);
15287
+ text += s2;
15288
+ normalWritten = true;
15289
+ };
15290
+ const startThinkBlock = () => {
15291
+ inThink = true;
15292
+ thinkBuf = "";
15293
+ thinkStartMs = Date.now();
15294
+ if (!normalWritten) process.stdout.write("\n");
15295
+ process.stdout.write(source_default.dim(" \u280B \u601D\u8003\u4E2D..."));
15296
+ spinIdx = 0;
15297
+ spinInterval = setInterval(() => {
15298
+ spinIdx = (spinIdx + 1) % SPIN_FRAMES.length;
15299
+ process.stdout.write(`\r${source_default.dim(` ${SPIN_FRAMES[spinIdx]} \u601D\u8003\u4E2D...`)}`);
15300
+ }, 80);
15301
+ };
15302
+ const endThinkBlock = () => {
15303
+ if (spinInterval) {
15304
+ clearInterval(spinInterval);
15305
+ spinInterval = null;
15306
+ }
15307
+ process.stdout.write("\r\x1B[K");
15308
+ const elapsed = ((Date.now() - thinkStartMs) / 1e3).toFixed(1);
15309
+ const trimmed = thinkBuf.trim();
15310
+ if (trimmed) {
15311
+ const W2 = 44;
15312
+ const suffix = ` \u2713 ${elapsed}s`;
15313
+ process.stdout.write(source_default.dim(` \u256D${"\u2500".repeat(W2)}
15314
+ `));
15315
+ for (const line of trimmed.split("\n")) {
15316
+ const chunks = line.match(/.{1,78}/g) ?? [""];
15317
+ for (const c2 of chunks) process.stdout.write(source_default.dim(` \u2502 ${c2}
15318
+ `));
15319
+ }
15320
+ process.stdout.write(source_default.dim(` \u2570${"\u2500".repeat(Math.max(0, W2 - suffix.length))}${suffix}
15321
+
15322
+ `));
15323
+ }
15324
+ inThink = false;
15325
+ thinkBuf = "";
15326
+ };
15327
+ const partialTagLen = (s2, tag) => {
15328
+ const max = Math.min(s2.length, tag.length - 1);
15329
+ for (let i2 = max; i2 > 0; i2--) {
15330
+ if (tag.startsWith(s2.slice(-i2))) return i2;
15331
+ }
15332
+ return 0;
15333
+ };
15334
+ const processChunk = (chunk) => {
15335
+ pendingBuf += chunk;
15336
+ let guard = 0;
15337
+ while (pendingBuf.length > 0 && guard++ < 2e4) {
15338
+ if (!inThink) {
15339
+ const openIdx = pendingBuf.indexOf(THINK_OPEN);
15340
+ if (openIdx === -1) {
15341
+ const hold = partialTagLen(pendingBuf, THINK_OPEN);
15342
+ writeNormal(pendingBuf.slice(0, pendingBuf.length - hold));
15343
+ pendingBuf = hold > 0 ? pendingBuf.slice(-hold) : "";
15344
+ break;
15345
+ }
15346
+ writeNormal(pendingBuf.slice(0, openIdx));
15347
+ pendingBuf = pendingBuf.slice(openIdx + THINK_OPEN.length);
15348
+ startThinkBlock();
15349
+ } else {
15350
+ const closeIdx = pendingBuf.indexOf(THINK_CLOSE);
15351
+ if (closeIdx === -1) {
15352
+ const hold = partialTagLen(pendingBuf, THINK_CLOSE);
15353
+ thinkBuf += pendingBuf.slice(0, pendingBuf.length - hold);
15354
+ pendingBuf = hold > 0 ? pendingBuf.slice(-hold) : "";
15355
+ break;
15356
+ }
15357
+ thinkBuf += pendingBuf.slice(0, closeIdx);
15358
+ pendingBuf = pendingBuf.slice(closeIdx + THINK_CLOSE.length);
15359
+ endThinkBlock();
15360
+ if (!normalWritten) process.stdout.write(source_default.green(`${BRAND} \u203A `));
15361
+ }
15362
+ }
15363
+ };
15323
15364
  process.stdout.write(source_default.green(`${BRAND} \u203A `));
15324
15365
  for await (const chunk of stream) {
15325
15366
  if (chunk.usage) {
@@ -15331,8 +15372,7 @@ async function streamOnce(client, messages, model, signal) {
15331
15372
  const delta = choice.delta;
15332
15373
  finishReason = choice.finish_reason ?? finishReason;
15333
15374
  if (delta.content) {
15334
- process.stdout.write(delta.content);
15335
- text += delta.content;
15375
+ processChunk(delta.content);
15336
15376
  }
15337
15377
  if (delta.tool_calls) {
15338
15378
  for (const tc of delta.tool_calls) {
@@ -15352,6 +15392,12 @@ async function streamOnce(client, messages, model, signal) {
15352
15392
  }
15353
15393
  }
15354
15394
  }
15395
+ if (pendingBuf) writeNormal(pendingBuf);
15396
+ if (inThink) endThinkBlock();
15397
+ if (spinInterval) {
15398
+ clearInterval(spinInterval);
15399
+ spinInterval = null;
15400
+ }
15355
15401
  if (text) process.stdout.write("\n");
15356
15402
  return {
15357
15403
  text,
@@ -17866,7 +17912,7 @@ function clearCheckpoints(sessionId) {
17866
17912
 
17867
17913
  // src/index.ts
17868
17914
  var import_fs7 = require("fs");
17869
- var VERSION2 = "2.8.0";
17915
+ var VERSION2 = "2.8.2";
17870
17916
  var BRAND2 = "bgi".toLowerCase();
17871
17917
  var SKILLHUB_HUBS = {
17872
17918
  bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
@@ -18214,50 +18260,27 @@ function printHelp() {
18214
18260
  async function addEndpointWizard(rl) {
18215
18261
  console.log(source_default.yellow("\n\u6DFB\u52A0\u7AEF\u70B9"));
18216
18262
  console.log(source_default.dim("\u652F\u6301\u4EFB\u4F55\u517C\u5BB9 OpenAI Chat Completions API \u7684\u670D\u52A1\uFF08\u767E\u70BC/DeepSeek/Kimi/vLLM/Ollama \u7B49\uFF09\n"));
18217
- PRESET_ENDPOINTS.forEach((p2, i2) => {
18218
- const noKey = p2.url.includes("172.16") ? source_default.dim(" (\u5185\u7F51\uFF0C\u65E0\u9700 Key)") : "";
18219
- console.log(` ${source_default.cyan(i2 + 1)}) ${p2.name}${noKey}`);
18220
- });
18221
- console.log(` ${source_default.cyan(PRESET_ENDPOINTS.length + 1)}) \u81EA\u5B9A\u4E49 URL`);
18222
- console.log();
18223
- const choice = await question(rl, source_default.cyan(`\u9009\u62E9\u9884\u8BBE\u6216\u81EA\u5B9A\u4E49 (1-${PRESET_ENDPOINTS.length + 1}, \u9ED8\u8BA4 1) \u203A `));
18224
- const idx = parseInt(choice.trim()) - 1;
18225
- const safeIdx = isNaN(idx) || idx < 0 ? 0 : idx;
18226
- let url = "";
18227
- let name = "";
18228
- let defaultModels = [];
18229
- let defaultModel = "";
18230
- if (safeIdx < PRESET_ENDPOINTS.length) {
18231
- const preset = PRESET_ENDPOINTS[safeIdx];
18232
- url = preset.url;
18233
- name = preset.name;
18234
- defaultModels = preset.models ?? [];
18235
- defaultModel = preset.activeModel ?? "";
18236
- } else {
18237
- const inputUrl = await question(rl, source_default.cyan(" API Base URL (\u5982 http://192.168.1.100:8080/v1) \u203A "));
18238
- url = inputUrl.trim();
18239
- if (!url) {
18240
- console.log(source_default.red(" URL \u4E0D\u80FD\u4E3A\u7A7A"));
18241
- return null;
18242
- }
18243
- const inputName = await question(rl, source_default.cyan(" \u7AEF\u70B9\u540D\u79F0 (\u53EF\u9009) \u203A "));
18244
- name = inputName.trim() || url;
18263
+ const inputUrl = await question(rl, source_default.cyan(" API Base URL (\u5982 https://api.deepseek.com/v1) \u203A "));
18264
+ const url = inputUrl.trim();
18265
+ if (!url) {
18266
+ console.log(source_default.red(" URL \u4E0D\u80FD\u4E3A\u7A7A"));
18267
+ return null;
18245
18268
  }
18269
+ const inputName = await question(rl, source_default.cyan(" \u7AEF\u70B9\u540D\u79F0 (\u53EF\u9009) \u203A "));
18270
+ const name = inputName.trim() || url;
18246
18271
  const apiKey = (await question(rl, source_default.cyan(" API Key (\u65E0\u9700\u9274\u6743\u53EF\u76F4\u63A5\u56DE\u8F66) \u203A "))).trim();
18247
- const ep = { name, url, apiKey: apiKey || void 0, models: defaultModels, activeModel: defaultModel };
18272
+ const ep = { name, url, apiKey: apiKey || void 0, models: [], activeModel: void 0 };
18248
18273
  process.stdout.write(source_default.dim(" \u626B\u63CF\u53EF\u7528\u6A21\u578B..."));
18249
18274
  const scanned = await scanModels(ep);
18250
18275
  if (scanned.length > 0) {
18251
18276
  ep.models = scanned;
18252
- if (!ep.activeModel || !scanned.includes(ep.activeModel)) ep.activeModel = scanned[0];
18277
+ ep.activeModel = scanned[0];
18253
18278
  console.log(source_default.green(` \u53D1\u73B0 ${scanned.length} \u4E2A\u6A21\u578B`));
18254
18279
  } else {
18255
- console.log(source_default.dim(" \u65E0\u6CD5\u81EA\u52A8\u626B\u63CF\uFF0C\u4F7F\u7528\u9884\u8BBE\u5217\u8868"));
18256
- if (!ep.activeModel) {
18257
- const m2 = await question(rl, source_default.cyan(" \u9ED8\u8BA4\u6A21\u578B\u540D \u203A "));
18258
- ep.activeModel = m2.trim();
18259
- if (ep.activeModel) ep.models = [ep.activeModel];
18260
- }
18280
+ console.log(source_default.dim(" \u65E0\u6CD5\u81EA\u52A8\u626B\u63CF"));
18281
+ const m2 = await question(rl, source_default.cyan(" \u9ED8\u8BA4\u6A21\u578B\u540D \u203A "));
18282
+ ep.activeModel = m2.trim() || void 0;
18283
+ if (ep.activeModel) ep.models = [ep.activeModel];
18261
18284
  }
18262
18285
  return ep;
18263
18286
  }
@@ -19792,7 +19815,7 @@ async function main() {
19792
19815
  const ep = getActiveEndpoint(cfg);
19793
19816
  const allSkillsList = collectAllSkills();
19794
19817
  const totalSkills = allSkillsList.length;
19795
- const userSkillCount = allSkillsList.filter((e2) => e2.tag === "user").length;
19818
+ const userSkillCount = allSkillsList.filter((e2) => e2.tag === "downloaded").length;
19796
19819
  const skillsLabel = totalSkills > 0 ? source_default.green(`${totalSkills} \u4E2A`) + (userSkillCount > 0 ? source_default.dim(` (\u542B ${userSkillCount} \u4E2A\u7528\u6237\u5B89\u88C5)`) : "") : source_default.yellow("\u672A\u5B89\u88C5");
19797
19820
  console.log(source_default.bold.cyan("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
19798
19821
  console.log(` ${source_default.bold("\u7AEF\u70B9:")} ${source_default.cyan(ep.name)} ${source_default.dim(ep.url)}`);
@@ -19909,7 +19932,7 @@ async function main() {
19909
19932
  const lines = [
19910
19933
  `# \u4F1A\u8BDD\u8BB0\u5FC6 ${new Date(sessionStartTime).toLocaleString("zh-CN")}`,
19911
19934
  ``,
19912
- `- \u6A21\u578B: ${loadConfig().model}`,
19935
+ `- \u6A21\u578B: ${getCurrentModel(loadConfig())}`,
19913
19936
  `- Token: \u8F93\u5165 ${sessionStats.inputTokens} / \u8F93\u51FA ${sessionStats.outputTokens}`,
19914
19937
  `- \u547D\u4EE4: ${sessionStats.successCmds} \u6210\u529F / ${sessionStats.failCmds} \u5931\u8D25`,
19915
19938
  ``
package/dist/bio.js CHANGED
@@ -14366,52 +14366,6 @@ function ensureDirs() {
14366
14366
  if (!(0, import_fs2.existsSync)(dir)) (0, import_fs2.mkdirSync)(dir, { recursive: true });
14367
14367
  }
14368
14368
  }
14369
- var PRESET_ENDPOINTS = [
14370
- {
14371
- name: "\u767E\u70BC \xB7 \u963F\u91CC\u4E91 (DashScope)",
14372
- url: "https://dashscope.aliyuncs.com/compatible-mode/v1",
14373
- models: [
14374
- "qwen3.5-plus",
14375
- "qwen3.5-flash",
14376
- "qwen3-235b-a22b",
14377
- "qwen3-max",
14378
- "qwen3-32b",
14379
- "qwen-max",
14380
- "qwen-plus",
14381
- "qwen-turbo",
14382
- "qwen-long",
14383
- "deepseek-v3",
14384
- "deepseek-r1",
14385
- "qwq-plus",
14386
- "MiniMax-M2.5"
14387
- ],
14388
- activeModel: "qwen3.5-plus"
14389
- },
14390
- {
14391
- name: "DeepSeek",
14392
- url: "https://api.deepseek.com/v1",
14393
- models: ["deepseek-chat", "deepseek-reasoner"],
14394
- activeModel: "deepseek-chat"
14395
- },
14396
- {
14397
- name: "Moonshot (Kimi)",
14398
- url: "https://api.moonshot.cn/v1",
14399
- models: ["moonshot-v1-8k", "moonshot-v1-32k", "moonshot-v1-128k", "kimi-k2.5"],
14400
- activeModel: "moonshot-v1-8k"
14401
- },
14402
- {
14403
- name: "MiniMax",
14404
- url: "https://api.minimax.chat/v1",
14405
- models: ["MiniMax-M2.5", "MiniMax-Text-01"],
14406
- activeModel: "MiniMax-M2.5"
14407
- },
14408
- {
14409
- name: "\u5185\u7F51 Qwen3-235B",
14410
- url: "http://172.16.224.137:1024/v1",
14411
- models: ["Qwen3-235B-A22B"],
14412
- activeModel: "Qwen3-235B-A22B"
14413
- }
14414
- ];
14415
14369
  function getActiveEndpoint(cfg) {
14416
14370
  return cfg.endpoints[cfg.activeIndex] ?? cfg.endpoints[0] ?? {
14417
14371
  name: "\u672A\u914D\u7F6E",
@@ -14438,30 +14392,27 @@ function isOldFormat(raw) {
14438
14392
  return typeof raw["provider"] === "string" && !Array.isArray(raw["endpoints"]);
14439
14393
  }
14440
14394
  function migrateOldConfig(old) {
14441
- const provider = old["provider"] ?? "bailian";
14395
+ const provider = old["provider"] ?? "custom";
14442
14396
  const apiKeys = old["apiKeys"] ?? {};
14443
14397
  const model = old["model"] ?? "";
14444
- let ep;
14445
- if (provider === "custom") {
14446
- ep = {
14447
- name: "\u81EA\u5B9A\u4E49",
14448
- url: old["customUrl"] ?? "",
14449
- apiKey: apiKeys["custom"],
14450
- models: old["customModel"] ? [old["customModel"]] : [],
14451
- activeModel: old["customModel"] ?? model
14452
- };
14453
- } else if (provider === "intranet") {
14454
- ep = { ...PRESET_ENDPOINTS[4], apiKey: void 0 };
14455
- } else {
14456
- const presetMap = {
14457
- bailian: 0,
14458
- deepseek: 1,
14459
- kimi: 2,
14460
- minimax: 3
14461
- };
14462
- const preset = PRESET_ENDPOINTS[presetMap[provider] ?? 0];
14463
- ep = { ...preset, apiKey: apiKeys[provider], activeModel: model || preset.activeModel };
14464
- }
14398
+ const legacyUrls = {
14399
+ bailian: "https://dashscope.aliyuncs.com/compatible-mode/v1",
14400
+ deepseek: "https://api.deepseek.com/v1",
14401
+ kimi: "https://api.moonshot.cn/v1",
14402
+ minimax: "https://api.minimax.chat/v1",
14403
+ intranet: "http://172.16.0.1:8080/v1"
14404
+ };
14405
+ const url = provider === "custom" ? old["customUrl"] ?? "" : legacyUrls[provider] ?? "";
14406
+ const name = provider === "custom" ? old["customUrl"] ?? "\u81EA\u5B9A\u4E49" : provider;
14407
+ const mdl = provider === "custom" ? old["customModel"] ?? model : model;
14408
+ const apiKey = provider === "intranet" ? void 0 : apiKeys[provider] ?? apiKeys["custom"];
14409
+ const ep = {
14410
+ name,
14411
+ url,
14412
+ apiKey,
14413
+ models: mdl ? [mdl] : [],
14414
+ activeModel: mdl || void 0
14415
+ };
14465
14416
  return {
14466
14417
  endpoints: [ep],
14467
14418
  activeIndex: 0,
@@ -15320,6 +15271,96 @@ async function streamOnce(client, messages, model, signal) {
15320
15271
  let finishReason = null;
15321
15272
  let inputTokens = 0;
15322
15273
  let outputTokens = 0;
15274
+ const THINK_OPEN = "<think>";
15275
+ const THINK_CLOSE = "</think>";
15276
+ const SPIN_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
15277
+ let pendingBuf = "";
15278
+ let inThink = false;
15279
+ let thinkBuf = "";
15280
+ let thinkStartMs = 0;
15281
+ let spinInterval = null;
15282
+ let spinIdx = 0;
15283
+ let normalWritten = false;
15284
+ const writeNormal = (s2) => {
15285
+ if (!s2) return;
15286
+ process.stdout.write(s2);
15287
+ text += s2;
15288
+ normalWritten = true;
15289
+ };
15290
+ const startThinkBlock = () => {
15291
+ inThink = true;
15292
+ thinkBuf = "";
15293
+ thinkStartMs = Date.now();
15294
+ if (!normalWritten) process.stdout.write("\n");
15295
+ process.stdout.write(source_default.dim(" \u280B \u601D\u8003\u4E2D..."));
15296
+ spinIdx = 0;
15297
+ spinInterval = setInterval(() => {
15298
+ spinIdx = (spinIdx + 1) % SPIN_FRAMES.length;
15299
+ process.stdout.write(`\r${source_default.dim(` ${SPIN_FRAMES[spinIdx]} \u601D\u8003\u4E2D...`)}`);
15300
+ }, 80);
15301
+ };
15302
+ const endThinkBlock = () => {
15303
+ if (spinInterval) {
15304
+ clearInterval(spinInterval);
15305
+ spinInterval = null;
15306
+ }
15307
+ process.stdout.write("\r\x1B[K");
15308
+ const elapsed = ((Date.now() - thinkStartMs) / 1e3).toFixed(1);
15309
+ const trimmed = thinkBuf.trim();
15310
+ if (trimmed) {
15311
+ const W2 = 44;
15312
+ const suffix = ` \u2713 ${elapsed}s`;
15313
+ process.stdout.write(source_default.dim(` \u256D${"\u2500".repeat(W2)}
15314
+ `));
15315
+ for (const line of trimmed.split("\n")) {
15316
+ const chunks = line.match(/.{1,78}/g) ?? [""];
15317
+ for (const c2 of chunks) process.stdout.write(source_default.dim(` \u2502 ${c2}
15318
+ `));
15319
+ }
15320
+ process.stdout.write(source_default.dim(` \u2570${"\u2500".repeat(Math.max(0, W2 - suffix.length))}${suffix}
15321
+
15322
+ `));
15323
+ }
15324
+ inThink = false;
15325
+ thinkBuf = "";
15326
+ };
15327
+ const partialTagLen = (s2, tag) => {
15328
+ const max = Math.min(s2.length, tag.length - 1);
15329
+ for (let i2 = max; i2 > 0; i2--) {
15330
+ if (tag.startsWith(s2.slice(-i2))) return i2;
15331
+ }
15332
+ return 0;
15333
+ };
15334
+ const processChunk = (chunk) => {
15335
+ pendingBuf += chunk;
15336
+ let guard = 0;
15337
+ while (pendingBuf.length > 0 && guard++ < 2e4) {
15338
+ if (!inThink) {
15339
+ const openIdx = pendingBuf.indexOf(THINK_OPEN);
15340
+ if (openIdx === -1) {
15341
+ const hold = partialTagLen(pendingBuf, THINK_OPEN);
15342
+ writeNormal(pendingBuf.slice(0, pendingBuf.length - hold));
15343
+ pendingBuf = hold > 0 ? pendingBuf.slice(-hold) : "";
15344
+ break;
15345
+ }
15346
+ writeNormal(pendingBuf.slice(0, openIdx));
15347
+ pendingBuf = pendingBuf.slice(openIdx + THINK_OPEN.length);
15348
+ startThinkBlock();
15349
+ } else {
15350
+ const closeIdx = pendingBuf.indexOf(THINK_CLOSE);
15351
+ if (closeIdx === -1) {
15352
+ const hold = partialTagLen(pendingBuf, THINK_CLOSE);
15353
+ thinkBuf += pendingBuf.slice(0, pendingBuf.length - hold);
15354
+ pendingBuf = hold > 0 ? pendingBuf.slice(-hold) : "";
15355
+ break;
15356
+ }
15357
+ thinkBuf += pendingBuf.slice(0, closeIdx);
15358
+ pendingBuf = pendingBuf.slice(closeIdx + THINK_CLOSE.length);
15359
+ endThinkBlock();
15360
+ if (!normalWritten) process.stdout.write(source_default.green(`${BRAND} \u203A `));
15361
+ }
15362
+ }
15363
+ };
15323
15364
  process.stdout.write(source_default.green(`${BRAND} \u203A `));
15324
15365
  for await (const chunk of stream) {
15325
15366
  if (chunk.usage) {
@@ -15331,8 +15372,7 @@ async function streamOnce(client, messages, model, signal) {
15331
15372
  const delta = choice.delta;
15332
15373
  finishReason = choice.finish_reason ?? finishReason;
15333
15374
  if (delta.content) {
15334
- process.stdout.write(delta.content);
15335
- text += delta.content;
15375
+ processChunk(delta.content);
15336
15376
  }
15337
15377
  if (delta.tool_calls) {
15338
15378
  for (const tc of delta.tool_calls) {
@@ -15352,6 +15392,12 @@ async function streamOnce(client, messages, model, signal) {
15352
15392
  }
15353
15393
  }
15354
15394
  }
15395
+ if (pendingBuf) writeNormal(pendingBuf);
15396
+ if (inThink) endThinkBlock();
15397
+ if (spinInterval) {
15398
+ clearInterval(spinInterval);
15399
+ spinInterval = null;
15400
+ }
15355
15401
  if (text) process.stdout.write("\n");
15356
15402
  return {
15357
15403
  text,
@@ -17866,7 +17912,7 @@ function clearCheckpoints(sessionId) {
17866
17912
 
17867
17913
  // src/index.ts
17868
17914
  var import_fs7 = require("fs");
17869
- var VERSION2 = "2.8.0";
17915
+ var VERSION2 = "2.8.2";
17870
17916
  var BRAND2 = "bio".toLowerCase();
17871
17917
  var SKILLHUB_HUBS = {
17872
17918
  bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
@@ -18214,50 +18260,27 @@ function printHelp() {
18214
18260
  async function addEndpointWizard(rl) {
18215
18261
  console.log(source_default.yellow("\n\u6DFB\u52A0\u7AEF\u70B9"));
18216
18262
  console.log(source_default.dim("\u652F\u6301\u4EFB\u4F55\u517C\u5BB9 OpenAI Chat Completions API \u7684\u670D\u52A1\uFF08\u767E\u70BC/DeepSeek/Kimi/vLLM/Ollama \u7B49\uFF09\n"));
18217
- PRESET_ENDPOINTS.forEach((p2, i2) => {
18218
- const noKey = p2.url.includes("172.16") ? source_default.dim(" (\u5185\u7F51\uFF0C\u65E0\u9700 Key)") : "";
18219
- console.log(` ${source_default.cyan(i2 + 1)}) ${p2.name}${noKey}`);
18220
- });
18221
- console.log(` ${source_default.cyan(PRESET_ENDPOINTS.length + 1)}) \u81EA\u5B9A\u4E49 URL`);
18222
- console.log();
18223
- const choice = await question(rl, source_default.cyan(`\u9009\u62E9\u9884\u8BBE\u6216\u81EA\u5B9A\u4E49 (1-${PRESET_ENDPOINTS.length + 1}, \u9ED8\u8BA4 1) \u203A `));
18224
- const idx = parseInt(choice.trim()) - 1;
18225
- const safeIdx = isNaN(idx) || idx < 0 ? 0 : idx;
18226
- let url = "";
18227
- let name = "";
18228
- let defaultModels = [];
18229
- let defaultModel = "";
18230
- if (safeIdx < PRESET_ENDPOINTS.length) {
18231
- const preset = PRESET_ENDPOINTS[safeIdx];
18232
- url = preset.url;
18233
- name = preset.name;
18234
- defaultModels = preset.models ?? [];
18235
- defaultModel = preset.activeModel ?? "";
18236
- } else {
18237
- const inputUrl = await question(rl, source_default.cyan(" API Base URL (\u5982 http://192.168.1.100:8080/v1) \u203A "));
18238
- url = inputUrl.trim();
18239
- if (!url) {
18240
- console.log(source_default.red(" URL \u4E0D\u80FD\u4E3A\u7A7A"));
18241
- return null;
18242
- }
18243
- const inputName = await question(rl, source_default.cyan(" \u7AEF\u70B9\u540D\u79F0 (\u53EF\u9009) \u203A "));
18244
- name = inputName.trim() || url;
18263
+ const inputUrl = await question(rl, source_default.cyan(" API Base URL (\u5982 https://api.deepseek.com/v1) \u203A "));
18264
+ const url = inputUrl.trim();
18265
+ if (!url) {
18266
+ console.log(source_default.red(" URL \u4E0D\u80FD\u4E3A\u7A7A"));
18267
+ return null;
18245
18268
  }
18269
+ const inputName = await question(rl, source_default.cyan(" \u7AEF\u70B9\u540D\u79F0 (\u53EF\u9009) \u203A "));
18270
+ const name = inputName.trim() || url;
18246
18271
  const apiKey = (await question(rl, source_default.cyan(" API Key (\u65E0\u9700\u9274\u6743\u53EF\u76F4\u63A5\u56DE\u8F66) \u203A "))).trim();
18247
- const ep = { name, url, apiKey: apiKey || void 0, models: defaultModels, activeModel: defaultModel };
18272
+ const ep = { name, url, apiKey: apiKey || void 0, models: [], activeModel: void 0 };
18248
18273
  process.stdout.write(source_default.dim(" \u626B\u63CF\u53EF\u7528\u6A21\u578B..."));
18249
18274
  const scanned = await scanModels(ep);
18250
18275
  if (scanned.length > 0) {
18251
18276
  ep.models = scanned;
18252
- if (!ep.activeModel || !scanned.includes(ep.activeModel)) ep.activeModel = scanned[0];
18277
+ ep.activeModel = scanned[0];
18253
18278
  console.log(source_default.green(` \u53D1\u73B0 ${scanned.length} \u4E2A\u6A21\u578B`));
18254
18279
  } else {
18255
- console.log(source_default.dim(" \u65E0\u6CD5\u81EA\u52A8\u626B\u63CF\uFF0C\u4F7F\u7528\u9884\u8BBE\u5217\u8868"));
18256
- if (!ep.activeModel) {
18257
- const m2 = await question(rl, source_default.cyan(" \u9ED8\u8BA4\u6A21\u578B\u540D \u203A "));
18258
- ep.activeModel = m2.trim();
18259
- if (ep.activeModel) ep.models = [ep.activeModel];
18260
- }
18280
+ console.log(source_default.dim(" \u65E0\u6CD5\u81EA\u52A8\u626B\u63CF"));
18281
+ const m2 = await question(rl, source_default.cyan(" \u9ED8\u8BA4\u6A21\u578B\u540D \u203A "));
18282
+ ep.activeModel = m2.trim() || void 0;
18283
+ if (ep.activeModel) ep.models = [ep.activeModel];
18261
18284
  }
18262
18285
  return ep;
18263
18286
  }
@@ -19792,7 +19815,7 @@ async function main() {
19792
19815
  const ep = getActiveEndpoint(cfg);
19793
19816
  const allSkillsList = collectAllSkills();
19794
19817
  const totalSkills = allSkillsList.length;
19795
- const userSkillCount = allSkillsList.filter((e2) => e2.tag === "user").length;
19818
+ const userSkillCount = allSkillsList.filter((e2) => e2.tag === "downloaded").length;
19796
19819
  const skillsLabel = totalSkills > 0 ? source_default.green(`${totalSkills} \u4E2A`) + (userSkillCount > 0 ? source_default.dim(` (\u542B ${userSkillCount} \u4E2A\u7528\u6237\u5B89\u88C5)`) : "") : source_default.yellow("\u672A\u5B89\u88C5");
19797
19820
  console.log(source_default.bold.cyan("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
19798
19821
  console.log(` ${source_default.bold("\u7AEF\u70B9:")} ${source_default.cyan(ep.name)} ${source_default.dim(ep.url)}`);
@@ -19909,7 +19932,7 @@ async function main() {
19909
19932
  const lines = [
19910
19933
  `# \u4F1A\u8BDD\u8BB0\u5FC6 ${new Date(sessionStartTime).toLocaleString("zh-CN")}`,
19911
19934
  ``,
19912
- `- \u6A21\u578B: ${loadConfig().model}`,
19935
+ `- \u6A21\u578B: ${getCurrentModel(loadConfig())}`,
19913
19936
  `- Token: \u8F93\u5165 ${sessionStats.inputTokens} / \u8F93\u51FA ${sessionStats.outputTokens}`,
19914
19937
  `- \u547D\u4EE4: ${sessionStats.successCmds} \u6210\u529F / ${sessionStats.failCmds} \u5931\u8D25`,
19915
19938
  ``
package/dist/mbp.js CHANGED
@@ -14366,52 +14366,6 @@ function ensureDirs() {
14366
14366
  if (!(0, import_fs2.existsSync)(dir)) (0, import_fs2.mkdirSync)(dir, { recursive: true });
14367
14367
  }
14368
14368
  }
14369
- var PRESET_ENDPOINTS = [
14370
- {
14371
- name: "\u767E\u70BC \xB7 \u963F\u91CC\u4E91 (DashScope)",
14372
- url: "https://dashscope.aliyuncs.com/compatible-mode/v1",
14373
- models: [
14374
- "qwen3.5-plus",
14375
- "qwen3.5-flash",
14376
- "qwen3-235b-a22b",
14377
- "qwen3-max",
14378
- "qwen3-32b",
14379
- "qwen-max",
14380
- "qwen-plus",
14381
- "qwen-turbo",
14382
- "qwen-long",
14383
- "deepseek-v3",
14384
- "deepseek-r1",
14385
- "qwq-plus",
14386
- "MiniMax-M2.5"
14387
- ],
14388
- activeModel: "qwen3.5-plus"
14389
- },
14390
- {
14391
- name: "DeepSeek",
14392
- url: "https://api.deepseek.com/v1",
14393
- models: ["deepseek-chat", "deepseek-reasoner"],
14394
- activeModel: "deepseek-chat"
14395
- },
14396
- {
14397
- name: "Moonshot (Kimi)",
14398
- url: "https://api.moonshot.cn/v1",
14399
- models: ["moonshot-v1-8k", "moonshot-v1-32k", "moonshot-v1-128k", "kimi-k2.5"],
14400
- activeModel: "moonshot-v1-8k"
14401
- },
14402
- {
14403
- name: "MiniMax",
14404
- url: "https://api.minimax.chat/v1",
14405
- models: ["MiniMax-M2.5", "MiniMax-Text-01"],
14406
- activeModel: "MiniMax-M2.5"
14407
- },
14408
- {
14409
- name: "\u5185\u7F51 Qwen3-235B",
14410
- url: "http://172.16.224.137:1024/v1",
14411
- models: ["Qwen3-235B-A22B"],
14412
- activeModel: "Qwen3-235B-A22B"
14413
- }
14414
- ];
14415
14369
  function getActiveEndpoint(cfg) {
14416
14370
  return cfg.endpoints[cfg.activeIndex] ?? cfg.endpoints[0] ?? {
14417
14371
  name: "\u672A\u914D\u7F6E",
@@ -14438,30 +14392,27 @@ function isOldFormat(raw) {
14438
14392
  return typeof raw["provider"] === "string" && !Array.isArray(raw["endpoints"]);
14439
14393
  }
14440
14394
  function migrateOldConfig(old) {
14441
- const provider = old["provider"] ?? "bailian";
14395
+ const provider = old["provider"] ?? "custom";
14442
14396
  const apiKeys = old["apiKeys"] ?? {};
14443
14397
  const model = old["model"] ?? "";
14444
- let ep;
14445
- if (provider === "custom") {
14446
- ep = {
14447
- name: "\u81EA\u5B9A\u4E49",
14448
- url: old["customUrl"] ?? "",
14449
- apiKey: apiKeys["custom"],
14450
- models: old["customModel"] ? [old["customModel"]] : [],
14451
- activeModel: old["customModel"] ?? model
14452
- };
14453
- } else if (provider === "intranet") {
14454
- ep = { ...PRESET_ENDPOINTS[4], apiKey: void 0 };
14455
- } else {
14456
- const presetMap = {
14457
- bailian: 0,
14458
- deepseek: 1,
14459
- kimi: 2,
14460
- minimax: 3
14461
- };
14462
- const preset = PRESET_ENDPOINTS[presetMap[provider] ?? 0];
14463
- ep = { ...preset, apiKey: apiKeys[provider], activeModel: model || preset.activeModel };
14464
- }
14398
+ const legacyUrls = {
14399
+ bailian: "https://dashscope.aliyuncs.com/compatible-mode/v1",
14400
+ deepseek: "https://api.deepseek.com/v1",
14401
+ kimi: "https://api.moonshot.cn/v1",
14402
+ minimax: "https://api.minimax.chat/v1",
14403
+ intranet: "http://172.16.0.1:8080/v1"
14404
+ };
14405
+ const url = provider === "custom" ? old["customUrl"] ?? "" : legacyUrls[provider] ?? "";
14406
+ const name = provider === "custom" ? old["customUrl"] ?? "\u81EA\u5B9A\u4E49" : provider;
14407
+ const mdl = provider === "custom" ? old["customModel"] ?? model : model;
14408
+ const apiKey = provider === "intranet" ? void 0 : apiKeys[provider] ?? apiKeys["custom"];
14409
+ const ep = {
14410
+ name,
14411
+ url,
14412
+ apiKey,
14413
+ models: mdl ? [mdl] : [],
14414
+ activeModel: mdl || void 0
14415
+ };
14465
14416
  return {
14466
14417
  endpoints: [ep],
14467
14418
  activeIndex: 0,
@@ -15320,6 +15271,96 @@ async function streamOnce(client, messages, model, signal) {
15320
15271
  let finishReason = null;
15321
15272
  let inputTokens = 0;
15322
15273
  let outputTokens = 0;
15274
+ const THINK_OPEN = "<think>";
15275
+ const THINK_CLOSE = "</think>";
15276
+ const SPIN_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
15277
+ let pendingBuf = "";
15278
+ let inThink = false;
15279
+ let thinkBuf = "";
15280
+ let thinkStartMs = 0;
15281
+ let spinInterval = null;
15282
+ let spinIdx = 0;
15283
+ let normalWritten = false;
15284
+ const writeNormal = (s2) => {
15285
+ if (!s2) return;
15286
+ process.stdout.write(s2);
15287
+ text += s2;
15288
+ normalWritten = true;
15289
+ };
15290
+ const startThinkBlock = () => {
15291
+ inThink = true;
15292
+ thinkBuf = "";
15293
+ thinkStartMs = Date.now();
15294
+ if (!normalWritten) process.stdout.write("\n");
15295
+ process.stdout.write(source_default.dim(" \u280B \u601D\u8003\u4E2D..."));
15296
+ spinIdx = 0;
15297
+ spinInterval = setInterval(() => {
15298
+ spinIdx = (spinIdx + 1) % SPIN_FRAMES.length;
15299
+ process.stdout.write(`\r${source_default.dim(` ${SPIN_FRAMES[spinIdx]} \u601D\u8003\u4E2D...`)}`);
15300
+ }, 80);
15301
+ };
15302
+ const endThinkBlock = () => {
15303
+ if (spinInterval) {
15304
+ clearInterval(spinInterval);
15305
+ spinInterval = null;
15306
+ }
15307
+ process.stdout.write("\r\x1B[K");
15308
+ const elapsed = ((Date.now() - thinkStartMs) / 1e3).toFixed(1);
15309
+ const trimmed = thinkBuf.trim();
15310
+ if (trimmed) {
15311
+ const W2 = 44;
15312
+ const suffix = ` \u2713 ${elapsed}s`;
15313
+ process.stdout.write(source_default.dim(` \u256D${"\u2500".repeat(W2)}
15314
+ `));
15315
+ for (const line of trimmed.split("\n")) {
15316
+ const chunks = line.match(/.{1,78}/g) ?? [""];
15317
+ for (const c2 of chunks) process.stdout.write(source_default.dim(` \u2502 ${c2}
15318
+ `));
15319
+ }
15320
+ process.stdout.write(source_default.dim(` \u2570${"\u2500".repeat(Math.max(0, W2 - suffix.length))}${suffix}
15321
+
15322
+ `));
15323
+ }
15324
+ inThink = false;
15325
+ thinkBuf = "";
15326
+ };
15327
+ const partialTagLen = (s2, tag) => {
15328
+ const max = Math.min(s2.length, tag.length - 1);
15329
+ for (let i2 = max; i2 > 0; i2--) {
15330
+ if (tag.startsWith(s2.slice(-i2))) return i2;
15331
+ }
15332
+ return 0;
15333
+ };
15334
+ const processChunk = (chunk) => {
15335
+ pendingBuf += chunk;
15336
+ let guard = 0;
15337
+ while (pendingBuf.length > 0 && guard++ < 2e4) {
15338
+ if (!inThink) {
15339
+ const openIdx = pendingBuf.indexOf(THINK_OPEN);
15340
+ if (openIdx === -1) {
15341
+ const hold = partialTagLen(pendingBuf, THINK_OPEN);
15342
+ writeNormal(pendingBuf.slice(0, pendingBuf.length - hold));
15343
+ pendingBuf = hold > 0 ? pendingBuf.slice(-hold) : "";
15344
+ break;
15345
+ }
15346
+ writeNormal(pendingBuf.slice(0, openIdx));
15347
+ pendingBuf = pendingBuf.slice(openIdx + THINK_OPEN.length);
15348
+ startThinkBlock();
15349
+ } else {
15350
+ const closeIdx = pendingBuf.indexOf(THINK_CLOSE);
15351
+ if (closeIdx === -1) {
15352
+ const hold = partialTagLen(pendingBuf, THINK_CLOSE);
15353
+ thinkBuf += pendingBuf.slice(0, pendingBuf.length - hold);
15354
+ pendingBuf = hold > 0 ? pendingBuf.slice(-hold) : "";
15355
+ break;
15356
+ }
15357
+ thinkBuf += pendingBuf.slice(0, closeIdx);
15358
+ pendingBuf = pendingBuf.slice(closeIdx + THINK_CLOSE.length);
15359
+ endThinkBlock();
15360
+ if (!normalWritten) process.stdout.write(source_default.green(`${BRAND} \u203A `));
15361
+ }
15362
+ }
15363
+ };
15323
15364
  process.stdout.write(source_default.green(`${BRAND} \u203A `));
15324
15365
  for await (const chunk of stream) {
15325
15366
  if (chunk.usage) {
@@ -15331,8 +15372,7 @@ async function streamOnce(client, messages, model, signal) {
15331
15372
  const delta = choice.delta;
15332
15373
  finishReason = choice.finish_reason ?? finishReason;
15333
15374
  if (delta.content) {
15334
- process.stdout.write(delta.content);
15335
- text += delta.content;
15375
+ processChunk(delta.content);
15336
15376
  }
15337
15377
  if (delta.tool_calls) {
15338
15378
  for (const tc of delta.tool_calls) {
@@ -15352,6 +15392,12 @@ async function streamOnce(client, messages, model, signal) {
15352
15392
  }
15353
15393
  }
15354
15394
  }
15395
+ if (pendingBuf) writeNormal(pendingBuf);
15396
+ if (inThink) endThinkBlock();
15397
+ if (spinInterval) {
15398
+ clearInterval(spinInterval);
15399
+ spinInterval = null;
15400
+ }
15355
15401
  if (text) process.stdout.write("\n");
15356
15402
  return {
15357
15403
  text,
@@ -17866,7 +17912,7 @@ function clearCheckpoints(sessionId) {
17866
17912
 
17867
17913
  // src/index.ts
17868
17914
  var import_fs7 = require("fs");
17869
- var VERSION2 = "2.8.0";
17915
+ var VERSION2 = "2.8.2";
17870
17916
  var BRAND2 = "mbp".toLowerCase();
17871
17917
  var SKILLHUB_HUBS = {
17872
17918
  bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
@@ -18214,50 +18260,27 @@ function printHelp() {
18214
18260
  async function addEndpointWizard(rl) {
18215
18261
  console.log(source_default.yellow("\n\u6DFB\u52A0\u7AEF\u70B9"));
18216
18262
  console.log(source_default.dim("\u652F\u6301\u4EFB\u4F55\u517C\u5BB9 OpenAI Chat Completions API \u7684\u670D\u52A1\uFF08\u767E\u70BC/DeepSeek/Kimi/vLLM/Ollama \u7B49\uFF09\n"));
18217
- PRESET_ENDPOINTS.forEach((p2, i2) => {
18218
- const noKey = p2.url.includes("172.16") ? source_default.dim(" (\u5185\u7F51\uFF0C\u65E0\u9700 Key)") : "";
18219
- console.log(` ${source_default.cyan(i2 + 1)}) ${p2.name}${noKey}`);
18220
- });
18221
- console.log(` ${source_default.cyan(PRESET_ENDPOINTS.length + 1)}) \u81EA\u5B9A\u4E49 URL`);
18222
- console.log();
18223
- const choice = await question(rl, source_default.cyan(`\u9009\u62E9\u9884\u8BBE\u6216\u81EA\u5B9A\u4E49 (1-${PRESET_ENDPOINTS.length + 1}, \u9ED8\u8BA4 1) \u203A `));
18224
- const idx = parseInt(choice.trim()) - 1;
18225
- const safeIdx = isNaN(idx) || idx < 0 ? 0 : idx;
18226
- let url = "";
18227
- let name = "";
18228
- let defaultModels = [];
18229
- let defaultModel = "";
18230
- if (safeIdx < PRESET_ENDPOINTS.length) {
18231
- const preset = PRESET_ENDPOINTS[safeIdx];
18232
- url = preset.url;
18233
- name = preset.name;
18234
- defaultModels = preset.models ?? [];
18235
- defaultModel = preset.activeModel ?? "";
18236
- } else {
18237
- const inputUrl = await question(rl, source_default.cyan(" API Base URL (\u5982 http://192.168.1.100:8080/v1) \u203A "));
18238
- url = inputUrl.trim();
18239
- if (!url) {
18240
- console.log(source_default.red(" URL \u4E0D\u80FD\u4E3A\u7A7A"));
18241
- return null;
18242
- }
18243
- const inputName = await question(rl, source_default.cyan(" \u7AEF\u70B9\u540D\u79F0 (\u53EF\u9009) \u203A "));
18244
- name = inputName.trim() || url;
18263
+ const inputUrl = await question(rl, source_default.cyan(" API Base URL (\u5982 https://api.deepseek.com/v1) \u203A "));
18264
+ const url = inputUrl.trim();
18265
+ if (!url) {
18266
+ console.log(source_default.red(" URL \u4E0D\u80FD\u4E3A\u7A7A"));
18267
+ return null;
18245
18268
  }
18269
+ const inputName = await question(rl, source_default.cyan(" \u7AEF\u70B9\u540D\u79F0 (\u53EF\u9009) \u203A "));
18270
+ const name = inputName.trim() || url;
18246
18271
  const apiKey = (await question(rl, source_default.cyan(" API Key (\u65E0\u9700\u9274\u6743\u53EF\u76F4\u63A5\u56DE\u8F66) \u203A "))).trim();
18247
- const ep = { name, url, apiKey: apiKey || void 0, models: defaultModels, activeModel: defaultModel };
18272
+ const ep = { name, url, apiKey: apiKey || void 0, models: [], activeModel: void 0 };
18248
18273
  process.stdout.write(source_default.dim(" \u626B\u63CF\u53EF\u7528\u6A21\u578B..."));
18249
18274
  const scanned = await scanModels(ep);
18250
18275
  if (scanned.length > 0) {
18251
18276
  ep.models = scanned;
18252
- if (!ep.activeModel || !scanned.includes(ep.activeModel)) ep.activeModel = scanned[0];
18277
+ ep.activeModel = scanned[0];
18253
18278
  console.log(source_default.green(` \u53D1\u73B0 ${scanned.length} \u4E2A\u6A21\u578B`));
18254
18279
  } else {
18255
- console.log(source_default.dim(" \u65E0\u6CD5\u81EA\u52A8\u626B\u63CF\uFF0C\u4F7F\u7528\u9884\u8BBE\u5217\u8868"));
18256
- if (!ep.activeModel) {
18257
- const m2 = await question(rl, source_default.cyan(" \u9ED8\u8BA4\u6A21\u578B\u540D \u203A "));
18258
- ep.activeModel = m2.trim();
18259
- if (ep.activeModel) ep.models = [ep.activeModel];
18260
- }
18280
+ console.log(source_default.dim(" \u65E0\u6CD5\u81EA\u52A8\u626B\u63CF"));
18281
+ const m2 = await question(rl, source_default.cyan(" \u9ED8\u8BA4\u6A21\u578B\u540D \u203A "));
18282
+ ep.activeModel = m2.trim() || void 0;
18283
+ if (ep.activeModel) ep.models = [ep.activeModel];
18261
18284
  }
18262
18285
  return ep;
18263
18286
  }
@@ -19792,7 +19815,7 @@ async function main() {
19792
19815
  const ep = getActiveEndpoint(cfg);
19793
19816
  const allSkillsList = collectAllSkills();
19794
19817
  const totalSkills = allSkillsList.length;
19795
- const userSkillCount = allSkillsList.filter((e2) => e2.tag === "user").length;
19818
+ const userSkillCount = allSkillsList.filter((e2) => e2.tag === "downloaded").length;
19796
19819
  const skillsLabel = totalSkills > 0 ? source_default.green(`${totalSkills} \u4E2A`) + (userSkillCount > 0 ? source_default.dim(` (\u542B ${userSkillCount} \u4E2A\u7528\u6237\u5B89\u88C5)`) : "") : source_default.yellow("\u672A\u5B89\u88C5");
19797
19820
  console.log(source_default.bold.cyan("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
19798
19821
  console.log(` ${source_default.bold("\u7AEF\u70B9:")} ${source_default.cyan(ep.name)} ${source_default.dim(ep.url)}`);
@@ -19909,7 +19932,7 @@ async function main() {
19909
19932
  const lines = [
19910
19933
  `# \u4F1A\u8BDD\u8BB0\u5FC6 ${new Date(sessionStartTime).toLocaleString("zh-CN")}`,
19911
19934
  ``,
19912
- `- \u6A21\u578B: ${loadConfig().model}`,
19935
+ `- \u6A21\u578B: ${getCurrentModel(loadConfig())}`,
19913
19936
  `- Token: \u8F93\u5165 ${sessionStats.inputTokens} / \u8F93\u51FA ${sessionStats.outputTokens}`,
19914
19937
  `- \u547D\u4EE4: ${sessionStats.successCmds} \u6210\u529F / ${sessionStats.failCmds} \u5931\u8D25`,
19915
19938
  ``
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgicli/bgicli",
3
- "version": "2.8.0",
3
+ "version": "2.8.2",
4
4
  "description": "BGI CLI — Bioinformatics AI terminal for Chinese researchers (百炼/DeepSeek/Kimi/Qwen)",
5
5
  "bin": {
6
6
  "bgi": "dist/bgi.js",