@bgicli/bgicli 2.3.2 → 2.3.4

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 (2) hide show
  1. package/dist/bgi.js +61 -5
  2. package/package.json +1 -1
package/dist/bgi.js CHANGED
@@ -14006,6 +14006,15 @@ function decodeBuffer(buf) {
14006
14006
  }
14007
14007
  }
14008
14008
  }
14009
+ function injectProgressFlags(cmd) {
14010
+ if (/\bwget\b/.test(cmd) && !/-q\b|--quiet|--show-progress|--progress/.test(cmd)) {
14011
+ cmd = cmd.replace(/\bwget\b/, "wget --show-progress");
14012
+ }
14013
+ if (/\bcurl\b/.test(cmd) && !/-s\b|--silent|-S\b|-#|--progress-bar|--no-progress-meter/.test(cmd)) {
14014
+ cmd = cmd.replace(/\bcurl\b/, "curl --progress-bar");
14015
+ }
14016
+ return cmd;
14017
+ }
14009
14018
  async function toolBash(command, workdir, timeoutMs = 3e5, onStream) {
14010
14019
  const scan = scanCommand(command);
14011
14020
  const criticals = scan.matches.filter((m2) => m2.pattern.level === "CRITICAL");
@@ -14023,11 +14032,19 @@ async function toolBash(command, workdir, timeoutMs = 3e5, onStream) {
14023
14032
  if (onStream) onStream(`\u26A0 \u5B89\u5168\u8B66\u544A [HIGH]: ${reasons}
14024
14033
  `);
14025
14034
  }
14035
+ const processedCommand = injectProgressFlags(command);
14026
14036
  return new Promise((resolve4) => {
14027
14037
  const isWin = process.platform === "win32";
14028
- const child = (0, import_child_process.spawn)(isWin ? "cmd" : "/bin/sh", isWin ? ["/c", command] : ["-c", command], {
14038
+ const child = (0, import_child_process.spawn)(isWin ? "cmd" : "/bin/sh", isWin ? ["/c", processedCommand] : ["-c", processedCommand], {
14029
14039
  cwd: workdir ?? process.cwd(),
14030
- env: { ...process.env, PYTHONIOENCODING: "utf-8" },
14040
+ env: {
14041
+ ...process.env,
14042
+ PYTHONIOENCODING: "utf-8",
14043
+ PYTHONUNBUFFERED: "1",
14044
+ // prevent Python stdout buffering
14045
+ FORCE_COLOR: "1"
14046
+ // hint color support to tools that check
14047
+ },
14031
14048
  stdio: ["pipe", "pipe", "pipe"]
14032
14049
  });
14033
14050
  const outChunks = [];
@@ -14295,12 +14312,22 @@ ${label} `);
14295
14312
  clearInterval(spin);
14296
14313
  process.stdout.write("\r\x1B[2K");
14297
14314
  };
14315
+ let lastChunkTime = t0;
14316
+ let heartbeat = null;
14298
14317
  const onStream = isBash ? (chunk) => {
14318
+ lastChunkTime = Date.now();
14299
14319
  if (streamedLines >= MAX_STREAM_LINES) return;
14300
14320
  if (streamedLines === 0) {
14301
14321
  clearSpinner();
14302
14322
  process.stdout.write(`${label}
14303
14323
  `);
14324
+ heartbeat = setInterval(() => {
14325
+ if (Date.now() - lastChunkTime >= 5e3) {
14326
+ const totalSecs = ((Date.now() - t0) / 1e3).toFixed(0);
14327
+ process.stdout.write(source_default.dim(`
14328
+ \u2502 \u23F1 \u8FD0\u884C\u4E2D... ${totalSecs}s`));
14329
+ }
14330
+ }, 5e3);
14304
14331
  }
14305
14332
  const lines = chunk.split("\n");
14306
14333
  for (let i2 = 0; i2 < lines.length; i2++) {
@@ -14322,6 +14349,10 @@ ${label} `);
14322
14349
  }
14323
14350
  } : void 0;
14324
14351
  const result = await executeTool(tc.name, args, onStream);
14352
+ if (heartbeat) {
14353
+ clearInterval(heartbeat);
14354
+ heartbeat = null;
14355
+ }
14325
14356
  if (stats) {
14326
14357
  if (result.error) stats.failCmds++;
14327
14358
  else stats.successCmds++;
@@ -15910,7 +15941,7 @@ function clearCheckpoints(sessionId) {
15910
15941
 
15911
15942
  // src/index.ts
15912
15943
  var import_fs7 = require("fs");
15913
- var VERSION2 = "2.3.2";
15944
+ var VERSION2 = "2.3.4";
15914
15945
  var SKILLHUB_HUBS = {
15915
15946
  bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
15916
15947
  clawhub: { label: "clawhub.ai", apiBase: "https://clawhub.ai", backend: "clawhub" },
@@ -17663,17 +17694,42 @@ async function main() {
17663
17694
  async function exitWithReport() {
17664
17695
  if (exiting) return;
17665
17696
  exiting = true;
17697
+ rl.removeAllListeners("SIGINT");
17698
+ process.removeAllListeners("SIGINT");
17666
17699
  const runtime = formatDuration(Date.now() - sessionStartTime);
17667
17700
  console.log("\n" + source_default.bold.cyan("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 \u4F1A\u8BDD\u62A5\u544A \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
17668
17701
  console.log(` \u8FD0\u884C\u65F6\u95F4: ${source_default.white(runtime)}`);
17669
17702
  console.log(` \u6D88\u8017 Token: ${source_default.yellow("\u8F93\u5165")} ${source_default.bold(String(sessionStats.inputTokens))} | ${source_default.green("\u8F93\u51FA")} ${source_default.bold(String(sessionStats.outputTokens))}`);
17670
17703
  console.log(` \u6267\u884C\u547D\u4EE4: ${source_default.green("\u2713 " + sessionStats.successCmds + " \u6210\u529F")} ${sessionStats.failCmds > 0 ? source_default.yellow("\u2717 " + sessionStats.failCmds + " \u5931\u8D25") : source_default.dim("\u2717 0 \u5931\u8D25")}`);
17671
17704
  console.log(source_default.bold.cyan("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
17705
+ rl.removeAllListeners("close");
17706
+ rl.close();
17707
+ let ans = "n";
17672
17708
  try {
17673
- const ans = await question(rl, source_default.cyan("\n \u662F\u5426\u4FDD\u5B58\u672C\u6B21\u4F1A\u8BDD\u8BB0\u5FC6\uFF1F[y/N] "));
17674
- if (ans.trim().toLowerCase() === "y") saveSessionMemory();
17709
+ const exitRl = (0, import_readline.createInterface)({ input: process.stdin, output: process.stdout });
17710
+ exitRl.on("SIGINT", () => {
17711
+ exitRl.close();
17712
+ process.exit(0);
17713
+ });
17714
+ process.once("SIGINT", () => {
17715
+ exitRl.close();
17716
+ process.exit(0);
17717
+ });
17718
+ ans = await Promise.race([
17719
+ new Promise((res) => {
17720
+ exitRl.question(source_default.cyan("\n \u662F\u5426\u4FDD\u5B58\u672C\u6B21\u4F1A\u8BDD\u8BB0\u5FC6\uFF1F[y/N] "), (a2) => {
17721
+ exitRl.close();
17722
+ res(a2.trim().toLowerCase());
17723
+ });
17724
+ }),
17725
+ new Promise((res) => setTimeout(() => {
17726
+ exitRl.close();
17727
+ res("n");
17728
+ }, 15e3))
17729
+ ]);
17675
17730
  } catch {
17676
17731
  }
17732
+ if (ans === "y") saveSessionMemory();
17677
17733
  console.log(source_default.dim("\n\u518D\u89C1\uFF01"));
17678
17734
  process.exit(0);
17679
17735
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgicli/bgicli",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "BGI CLI — Bioinformatics AI terminal for Chinese researchers (百炼/DeepSeek/Kimi/Qwen)",
5
5
  "bin": {
6
6
  "bgi": "dist/bgi.js"