@bgicli/bgicli 2.3.9 → 2.4.1

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 (3) hide show
  1. package/README.md +57 -11
  2. package/dist/bgi.js +29 -11
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  - ✅ **开箱即用** — `npm install -g @bgicli/bgicli` 即可
6
6
  - ✅ **内置 889 个技能** — 21 个生信工作流 + 868 个 OpenClaw 医学技能,自动安装
7
7
  - ✅ **智能技能路由** — 描述任务自动激活对应技能,无需手动搜索
8
- - ✅ **中国 AI 服务商** — 百炼(DashScope)聚合:Qwen3.5、DeepSeek、Kimi、MiniMax 等 20+ 模型
8
+ - ✅ **中国 AI 服务商** — 百炼(DashScope)聚合:Qwen、DeepSeek、Kimi、MiniMax 等 20+ 模型
9
9
  - ✅ **真实工具调用** — 执行 bash、读写文件、运行 R/Python 脚本
10
10
  - ✅ **内网支持** — 可接入公司私有化部署的大模型
11
11
 
@@ -91,7 +91,7 @@ bgi # 启动
91
91
  ### 服务商 / 模型
92
92
  | 命令 | 说明 |
93
93
  |------|------|
94
- | `/provider <name>` | 切换服务商 (`bailian` / `intranet` / `custom`) |
94
+ | `/provider <name>` | 切换服务商(`bailian` / `intranet` / `custom`) |
95
95
  | `/model <name>` | 切换模型 |
96
96
  | `/models` | 列出当前服务商所有可用模型 |
97
97
  | `/providers` | 列出所有服务商 |
@@ -116,6 +116,34 @@ bgi # 启动
116
116
  | `/save [文件名]` | 保存对话为 Markdown 文件 |
117
117
  | `/think [on\|off]` | 切换思考模式(Qwen3 `/think` 前缀) |
118
118
 
119
+ ### 断点与恢复
120
+ | 命令 | 说明 |
121
+ |------|------|
122
+ | `/checkpoint` | 保存当前对话断点(含激活的技能) |
123
+ | `/checkpoint save [标签]` | 保存断点并指定标签 |
124
+ | `/checkpoint list` | 列出本次会话所有断点 |
125
+ | `/checkpoint restore <id>` | 恢复到指定断点 |
126
+
127
+ > 适合长时间分析任务中途保存进度,防止意外中断丢失上下文。
128
+
129
+ ### 数据库管理
130
+ | 命令 | 说明 |
131
+ |------|------|
132
+ | `/db list` | 列出已注册的参考数据库 |
133
+ | `/db add <路径> [基因组] [类型] [说明]` | 手动注册数据库路径 |
134
+ | `/db scan [目录]` | 自动扫描文件系统查找已知数据库 |
135
+ | `/db rm <id>` | 删除数据库记录 |
136
+ | `/db download [名称]` | 显示标准数据库下载命令 |
137
+
138
+ > 注册后 AI 可自动引用正确路径,无需每次手动指定。支持 hg38/hg19/mm10 基因组、STAR/HISAT2 索引、GTF 注释等。
139
+
140
+ ### 安全扫描
141
+ | 命令 | 说明 |
142
+ |------|------|
143
+ | `/scan <命令>` | 扫描命令安全风险,输出 CRITICAL / HIGH / MEDIUM / LOW 等级 |
144
+
145
+ > AI 执行每条 bash 命令前均自动扫描;CRITICAL 级别命令将被拦截。
146
+
119
147
  ### 文件与目录
120
148
  | 命令 | 说明 |
121
149
  |------|------|
@@ -124,11 +152,27 @@ bgi # 启动
124
152
  | `/tools` | 列出 AI 可调用的工具 |
125
153
  | `@路径` | 消息中内嵌文件内容(如 `@data.csv 里有什么?`) |
126
154
 
155
+ ### 会话报告与记忆
156
+ 退出时(双击 Ctrl+C 或输入 `exit`)自动显示会话报告:
157
+ - 运行时长
158
+ - 消耗 Token(输入 / 输出)
159
+ - 执行命令成功 / 失败次数
160
+ - 可选保存会话记忆到 `~/.bgicli/memory/`
161
+
127
162
  ### 其他
128
163
  | 命令 | 说明 |
129
164
  |------|------|
130
165
  | `/help` | 显示帮助 |
131
- | `exit` / `quit` / `q` | 退出 |
166
+ | `exit` / `quit` / `q` | 退出(显示会话报告) |
167
+
168
+ ---
169
+
170
+ ## 快捷键
171
+
172
+ | 快捷键 | 说明 |
173
+ |--------|------|
174
+ | `Ctrl+C`(单次) | 中断当前 AI 任务(保留对话历史) |
175
+ | `Ctrl+C`(连按两次) | 退出程序(显示会话报告) |
132
176
 
133
177
  ---
134
178
 
@@ -195,14 +239,16 @@ npm link
195
239
 
196
240
  ```
197
241
  bgi
198
- ├── src/index.ts — CLI 主入口、命令处理、智能路由
199
- ├── src/chat.ts 流式对话引擎(工具调用循环)
200
- ├── src/tools.ts — 工具实现(bash / read_file / write_file 等)
201
- ├── src/skillRouter.ts 关键词路由表(35个核心技能自动匹配)
202
- ├── src/prompt.ts 生物信息学系统提示
203
- ├── src/providers.ts 中国 AI 服务商配置
204
- ├── src/config.ts 配置管理(~/.bgicli/config.json)
205
- └── data/ 内置数据(工作流 + Skills + Python 工具)
242
+ ├── src/index.ts — CLI 主入口、命令处理、智能路由、会话管理
243
+ ├── src/chat.ts 流式对话引擎(工具调用循环、进度渲染)
244
+ ├── src/tools.ts — 工具实现(bash / read_file / write_file 等)
245
+ ├── src/security.ts 命令安全扫描(CRITICAL / HIGH / MEDIUM / LOW)
246
+ ├── src/databases.ts 参考数据库注册与管理
247
+ ├── src/skillRouter.ts 关键词路由表(35个核心技能自动匹配)
248
+ ├── src/prompt.ts 生物信息学系统提示
249
+ ├── src/providers.ts 中国 AI 服务商配置
250
+ ├── src/config.ts — 配置管理(~/.bgicli/config.json)
251
+ └── data/ — 内置数据(工作流 + Skills + Python 工具)
206
252
  ```
207
253
 
208
254
  ---
package/dist/bgi.js CHANGED
@@ -13956,7 +13956,7 @@ var TOOL_DEFINITIONS = [
13956
13956
  }
13957
13957
  }
13958
13958
  ];
13959
- async function executeTool(name, args, onStream) {
13959
+ async function executeTool(name, args, onStream, signal) {
13960
13960
  try {
13961
13961
  switch (name) {
13962
13962
  case "bash": {
@@ -13964,9 +13964,9 @@ async function executeTool(name, args, onStream) {
13964
13964
  const requestedTimeout = args["timeout_ms"] ?? 3e5;
13965
13965
  const isDownload = /\b(wget|curl|aria2c|axel|rsync)\b/.test(cmd);
13966
13966
  if (isDownload) {
13967
- return await toolBash(cmd, args["workdir"], 0, onStream, 6e5);
13967
+ return await toolBash(cmd, args["workdir"], 0, onStream, 6e5, signal);
13968
13968
  }
13969
- return await toolBash(cmd, args["workdir"], requestedTimeout, onStream);
13969
+ return await toolBash(cmd, args["workdir"], requestedTimeout, onStream, void 0, signal);
13970
13970
  }
13971
13971
  case "read_file":
13972
13972
  return toolReadFile(
@@ -14017,7 +14017,7 @@ function injectProgressFlags(cmd) {
14017
14017
  }
14018
14018
  return cmd;
14019
14019
  }
14020
- async function toolBash(command, workdir, timeoutMs = 3e5, onStream, inactivityMs) {
14020
+ async function toolBash(command, workdir, timeoutMs = 3e5, onStream, inactivityMs, signal) {
14021
14021
  const scan = scanCommand(command);
14022
14022
  const criticals = scan.matches.filter((m2) => m2.pattern.level === "CRITICAL");
14023
14023
  if (criticals.length > 0) {
@@ -14067,6 +14067,17 @@ async function toolBash(command, workdir, timeoutMs = 3e5, onStream, inactivityM
14067
14067
  });
14068
14068
  let timedOut = false;
14069
14069
  let timedOutSecs = 0;
14070
+ let aborted = false;
14071
+ if (signal) {
14072
+ if (signal.aborted) {
14073
+ child.kill();
14074
+ return resolve4({ output: "", error: "\u4EFB\u52A1\u5DF2\u4E2D\u65AD" });
14075
+ }
14076
+ signal.addEventListener("abort", () => {
14077
+ aborted = true;
14078
+ child.kill();
14079
+ }, { once: true });
14080
+ }
14070
14081
  const effectiveMs = inactivityMs ?? timeoutMs;
14071
14082
  let timer = setTimeout(() => {
14072
14083
  timedOut = true;
@@ -14088,7 +14099,9 @@ async function toolBash(command, workdir, timeoutMs = 3e5, onStream, inactivityM
14088
14099
  child.on("close", (code) => {
14089
14100
  clearTimeout(timer);
14090
14101
  const out = (decodeBuffer(Buffer.concat(outChunks)) + "\n" + decodeBuffer(Buffer.concat(errChunks))).trim();
14091
- if (timedOut) {
14102
+ if (aborted) {
14103
+ resolve4({ output: out, error: "\u4EFB\u52A1\u5DF2\u4E2D\u65AD" });
14104
+ } else if (timedOut) {
14092
14105
  const msg = inactivityMs ? `\u4E0B\u8F7D\u505C\u6EDE \u2014 \u8D85\u8FC7 ${timedOutSecs}s \u65E0\u4EFB\u4F55\u8F93\u51FA\uFF08\u8FDE\u63A5\u53EF\u80FD\u5DF2\u65AD\u5F00\uFF09` : `Command timed out after ${timedOutSecs}s`;
14093
14106
  resolve4({ output: out, error: msg });
14094
14107
  } else if (code !== 0) {
@@ -14334,6 +14347,13 @@ ${label} `);
14334
14347
  };
14335
14348
  let lastChunkTime = t0;
14336
14349
  let heartbeat = null;
14350
+ const clearHeartbeat = () => {
14351
+ if (heartbeat) {
14352
+ clearInterval(heartbeat);
14353
+ heartbeat = null;
14354
+ }
14355
+ };
14356
+ signal?.addEventListener("abort", clearHeartbeat, { once: true });
14337
14357
  const onStream = isBash ? (chunk) => {
14338
14358
  lastChunkTime = Date.now();
14339
14359
  if (!outputStarted) {
@@ -14382,11 +14402,9 @@ ${label} `);
14382
14402
  }
14383
14403
  }
14384
14404
  } : void 0;
14385
- const result = await executeTool(tc.name, args, onStream);
14386
- if (heartbeat) {
14387
- clearInterval(heartbeat);
14388
- heartbeat = null;
14389
- }
14405
+ const result = await executeTool(tc.name, args, onStream, signal);
14406
+ signal?.removeEventListener("abort", clearHeartbeat);
14407
+ clearHeartbeat();
14390
14408
  if (partialLine) {
14391
14409
  if (streamedLines < MAX_STREAM_LINES) {
14392
14410
  process.stdout.write("\r" + source_default.dim(" \u2502 ") + partialLine + "\x1B[K\n");
@@ -15981,7 +15999,7 @@ function clearCheckpoints(sessionId) {
15981
15999
 
15982
16000
  // src/index.ts
15983
16001
  var import_fs7 = require("fs");
15984
- var VERSION2 = "2.3.9";
16002
+ var VERSION2 = "2.4.1";
15985
16003
  var SKILLHUB_HUBS = {
15986
16004
  bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
15987
16005
  clawhub: { label: "clawhub.ai", apiBase: "https://clawhub.ai", backend: "clawhub" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgicli/bgicli",
3
- "version": "2.3.9",
3
+ "version": "2.4.1",
4
4
  "description": "BGI CLI — Bioinformatics AI terminal for Chinese researchers (百炼/DeepSeek/Kimi/Qwen)",
5
5
  "bin": {
6
6
  "bgi": "dist/bgi.js"