jinzd-ai-cli 0.4.329 → 0.4.331

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 (44) hide show
  1. package/README.md +4 -4
  2. package/README.zh-CN.md +4 -4
  3. package/dist/{batch-NNYRIS4U.js → batch-OOHC5POO.js} +2 -2
  4. package/dist/{chunk-BRZZ3QAI.js → chunk-2BAFLDDL.js} +44 -7
  5. package/dist/{chunk-XF2S7LNM.js → chunk-56ME7PB2.js} +1 -1
  6. package/dist/{chunk-DRNRQ6SD.js → chunk-6BGW25LG.js} +1 -1
  7. package/dist/{chunk-E2W2MI6H.js → chunk-C6GA7H5D.js} +1 -72
  8. package/dist/{chunk-2CNJ25U7.js → chunk-CM5C7ZSM.js} +9 -3
  9. package/dist/{chunk-IUC3DRGB.js → chunk-DTVN2LDU.js} +1 -1
  10. package/dist/{chunk-ABIR2TGW.js → chunk-EWARNWJ4.js} +4 -4
  11. package/dist/{chunk-YDH5ZWOQ.js → chunk-IJNDIOOQ.js} +1 -1
  12. package/dist/{chunk-LSSOPLKJ.js → chunk-L3FDFFD2.js} +9 -9
  13. package/dist/{chunk-TYQODNI7.js → chunk-MJSK6ZYR.js} +4 -4
  14. package/dist/{chunk-C2Z77RTU.js → chunk-MN25ELTF.js} +15 -4
  15. package/dist/{chunk-72AR23R2.js → chunk-NOLK5C4U.js} +54 -2
  16. package/dist/{chunk-SS3PG7LP.js → chunk-Q26V2PNA.js} +1 -1
  17. package/dist/{chunk-I5KLH7TL.js → chunk-QFF2PTI3.js} +53 -43
  18. package/dist/{chunk-LKSMXCFL.js → chunk-R3XIU7NS.js} +1 -1
  19. package/dist/{chunk-MPCQG7LV.js → chunk-RZDRBFAB.js} +9 -7
  20. package/dist/{chunk-LRRBYGHE.js → chunk-TF2FNRDZ.js} +1 -1
  21. package/dist/chunk-W4P2KJZN.js +75 -0
  22. package/dist/{chunk-6UDKGZ3D.js → chunk-YCDF6FNR.js} +1 -1
  23. package/dist/{ci-ODKA57IG.js → ci-HNYUXJUE.js} +7 -6
  24. package/dist/{ci-format-QDC4XKYZ.js → ci-format-ZLBEAU7Z.js} +2 -2
  25. package/dist/{constants-MG7EGG5J.js → constants-4EH6Y6VI.js} +1 -1
  26. package/dist/{constants-BYWEJLAI.js → constants-JM6MK5SS.js} +1 -1
  27. package/dist/{doctor-cli-LYZSHYR6.js → doctor-cli-VCNERMX5.js} +7 -6
  28. package/dist/electron-server.js +292 -178
  29. package/dist/{hub-GRHYVLGV.js → hub-3OXLWTEP.js} +8 -18
  30. package/dist/{hub-server-JLC7CNP7.js → hub-server-LJWXNEWK.js} +2 -1
  31. package/dist/index.js +23 -21
  32. package/dist/{persistent-memory-OCDFR4BH.js → persistent-memory-LMVWIHMX.js} +2 -2
  33. package/dist/{persistent-memory-O6GWHGJH.js → persistent-memory-PAS7NAPQ.js} +2 -2
  34. package/dist/{pr-LDUIDU27.js → pr-IMR62OHN.js} +7 -6
  35. package/dist/{run-tests-YTRU22LY.js → run-tests-2TVEWCQI.js} +2 -2
  36. package/dist/{run-tests-LTYJACRX.js → run-tests-MQVGE6FK.js} +2 -2
  37. package/dist/{server-ZTFB3KMS.js → server-55X6MCGX.js} +7 -6
  38. package/dist/{server-2NZN22XP.js → server-6MS2NGEJ.js} +30 -20
  39. package/dist/{task-orchestrator-URFLWSPI.js → task-orchestrator-KIDJB7NP.js} +9 -7
  40. package/dist/{usage-IP6G4Q2K.js → usage-X2CQYAUA.js} +3 -3
  41. package/dist/web/client/app.js +19 -0
  42. package/dist/web/client/app.js.br +0 -0
  43. package/dist/web/client/app.js.gz +0 -0
  44. package/package.json +1 -1
package/README.md CHANGED
@@ -134,10 +134,10 @@ aicli user delete x # Delete user
134
134
  | **DeepSeek** | deepseek-flash (default, multimodal), deepseek-v4-pro | [platform.deepseek.com](https://platform.deepseek.com) |
135
135
  | **OpenAI** | GPT-5.4, GPT-5, GPT-4.1, o3, o4-mini | [platform.openai.com](https://platform.openai.com) |
136
136
  | **OpenRouter** | 300+ models (Claude, GPT, Gemini, Llama, Qwen, Mistral...) | [openrouter.ai](https://openrouter.ai) |
137
- | **Zhipu** | GLM-4, GLM-5 | [open.bigmodel.cn](https://open.bigmodel.cn) |
138
- | **Kimi** | Kimi K2.6, K2.5, K2 Thinking | [platform.moonshot.cn](https://platform.moonshot.cn) |
139
- | **Qwen** | qwen-plus, qwen-max, qwen-turbo, qwen-coder-plus | [bailian.console.aliyun.com](https://bailian.console.aliyun.com) |
140
- | **MiniMax** | MiniMax-M3 (default), M2.7, M2.5, M2.1, M2 | [platform.minimaxi.com](https://platform.minimaxi.com) |
137
+ | **Zhipu** | glm-5.3-flash (default), glm-5.3-flashx, glm-5.3, glm-4.7-flash (free) | [open.bigmodel.cn](https://open.bigmodel.cn) |
138
+ | **Kimi** | kimi-k2.7-code (default), kimi-k2.7-code-highspeed, kimi-k3 | [platform.moonshot.cn](https://platform.moonshot.cn) |
139
+ | **Qwen** | qwen3.8-flash (default), qwen3.7-plus, qwen3.8-max, qwen-flash | [bailian.console.aliyun.com](https://bailian.console.aliyun.com) |
140
+ | **MiniMax** | MiniMax-M3 (default) | [platform.minimaxi.com](https://platform.minimaxi.com) |
141
141
  | **Ollama** | Any locally installed model (Llama, Qwen, Gemma, Mistral...) | No API key — [ollama.com](https://ollama.com) |
142
142
 
143
143
  Any OpenAI-compatible API can also be used via `customBaseUrls` in config.
package/README.zh-CN.md CHANGED
@@ -122,10 +122,10 @@ aicli user delete x # 删除用户
122
122
  | **DeepSeek** | deepseek-flash(默认,多模态), deepseek-v4-pro | [platform.deepseek.com](https://platform.deepseek.com) |
123
123
  | **OpenAI** | GPT-5.4, GPT-5, GPT-4.1, o3, o4-mini | [platform.openai.com](https://platform.openai.com) |
124
124
  | **OpenRouter** | 300+ 模型(Claude/GPT/Gemini/Llama/Qwen/Mistral...) | [openrouter.ai](https://openrouter.ai) |
125
- | **Zhipu(智谱)** | GLM-4, GLM-5 | [open.bigmodel.cn](https://open.bigmodel.cn) |
126
- | **Kimi** | Kimi K2.6, K2.5, K2 Thinking | [platform.moonshot.cn](https://platform.moonshot.cn) |
127
- | **Qwen** | qwen-plus, qwen-max, qwen-turbo, qwen-coder-plus | [bailian.console.aliyun.com](https://bailian.console.aliyun.com) |
128
- | **MiniMax** | MiniMax-M3(默认)、M2.7、M2.5、M2.1、M2 | [platform.minimaxi.com](https://platform.minimaxi.com) |
125
+ | **Zhipu(智谱)** | glm-5.3-flash(默认)、glm-5.3-flashx、glm-5.3、glm-4.7-flash(免费) | [open.bigmodel.cn](https://open.bigmodel.cn) |
126
+ | **Kimi** | kimi-k2.7-code(默认)、kimi-k2.7-code-highspeed、kimi-k3 | [platform.moonshot.cn](https://platform.moonshot.cn) |
127
+ | **Qwen** | qwen3.8-flash(默认)、qwen3.7-plus、qwen3.8-max、qwen-flash | [bailian.console.aliyun.com](https://bailian.console.aliyun.com) |
128
+ | **MiniMax** | MiniMax-M3(默认) | [platform.minimaxi.com](https://platform.minimaxi.com) |
129
129
  | **Ollama** | 任意本地模型(Llama、Qwen、Gemma、Mistral...) | 无需 API Key — [ollama.com](https://ollama.com) |
130
130
 
131
131
  也可通过 `customBaseUrls` 配置接入任意 OpenAI 兼容 API。
@@ -4,12 +4,12 @@ import {
4
4
  } from "./chunk-RS7SKYTS.js";
5
5
  import {
6
6
  ConfigManager
7
- } from "./chunk-2CNJ25U7.js";
7
+ } from "./chunk-CM5C7ZSM.js";
8
8
  import "./chunk-TU3L3PW7.js";
9
9
  import {
10
10
  atomicWriteFileSync
11
11
  } from "./chunk-BMLQPSHP.js";
12
- import "./chunk-6UDKGZ3D.js";
12
+ import "./chunk-YCDF6FNR.js";
13
13
 
14
14
  // src/cli/batch.ts
15
15
  import Anthropic from "@anthropic-ai/sdk";
@@ -16,7 +16,6 @@ function deepSeekCnyPricing(cacheRead, input, output) {
16
16
  output: output / CNY_PER_USD
17
17
  };
18
18
  }
19
- var DEEPSEEK_V4_PRO_ROUTED_TO_FLASH_AT = /* @__PURE__ */ new Date("2026-09-14T04:00:00.000Z");
20
19
  var DEEPSEEK_V41_FLASH_ROUTING_CONFIRMED_AT = /* @__PURE__ */ new Date("2026-09-11T00:00:00.000Z");
21
20
  function isDeepSeekPeakHour(at) {
22
21
  const weekday = at.getUTCDay();
@@ -32,7 +31,6 @@ function getDeepSeekV4Pricing(model, at) {
32
31
  const isPro = model.startsWith("deepseek-v4-pro");
33
32
  const isFlash = model.startsWith("deepseek-v4-flash");
34
33
  if (!isPro && !isFlash) return null;
35
- if (isPro && at >= DEEPSEEK_V4_PRO_ROUTED_TO_FLASH_AT) return deepSeekFlash41Pricing(at);
36
34
  if (isFlash && at >= DEEPSEEK_V41_FLASH_ROUTING_CONFIRMED_AT) return deepSeekFlash41Pricing(at);
37
35
  if (at < DEEPSEEK_TIME_PRICING_EFFECTIVE_AT) {
38
36
  return isPro ? deepSeekCnyPricing(0.025, 3, 6) : deepSeekCnyPricing(0.02, 1, 2);
@@ -111,6 +109,12 @@ var PRICING_TABLE = {
111
109
  // Kimi K3(2026-07 旗舰,1M 上下文)官方定价 platform.kimi.ai/pricing/chat-k3:
112
110
  // 输入 cache-miss $3.00 / cache-hit $0.30,输出 $15.00(/MTok)。
113
111
  "kimi-k3": { input: 3, output: 15, cacheRead: 0.3 },
112
+ // K2.6 / K2.7 Code:官方 platform.kimi.ai/docs/pricing/chat(2026-10-18 核对,USD/MTok)。
113
+ // 国内站人民币价 ¥6.5/¥27(缓存 ¥1.1 / ¥1.3)按 ¥6.9 折算与之相差 <3%,沿用 K3 那行的美元口径。
114
+ // 此前 K2.6 没有单列,前缀落到 'kimi-k2'($0.6/$2.5),输出低报约 37%。
115
+ "kimi-k2.6": { input: 0.95, output: 4, cacheRead: 0.16 },
116
+ "kimi-k2.7-code": { input: 0.95, output: 4, cacheRead: 0.19 },
117
+ "kimi-k2.7-code-highspeed": { input: 1.9, output: 8, cacheRead: 0.38 },
114
118
  // ── Zhipu GLM ─────────────────────────────────────────────────
115
119
  "glm-4-plus": { input: 0.7, output: 0.7 },
116
120
  "glm-4": { input: 0.14, output: 0.14 },
@@ -132,6 +136,11 @@ var PRICING_TABLE = {
132
136
  // 没公布截止日期,静态表表达不了这个时间维度;高估比低估安全——预算告警早触发
133
137
  // 好过晚触发。折扣期内 `/cost` 会比实际偏高约一倍,这是刻意的取舍。
134
138
  "glm-5.3-flash": { input: 0.116, output: 0.406, cacheRead: 0.033 },
139
+ // GLM-5.3-FlashX:官方定价页(docs.bigmodel.cn/cn/guide/start/pricing,2026-10-18 浏览器读取)
140
+ // 输入 2 元、输出 7 元、缓存命中 0.57 元。必须单列——否则前缀匹配会落到上面的 glm-5.3-flash,低报 2.5 倍。
141
+ "glm-5.3-flashx": { input: 2 / CNY_PER_USD, output: 7 / CNY_PER_USD, cacheRead: 0.57 / CNY_PER_USD },
142
+ // GLM-4.7-Flash:官方免费(输入/输出/缓存全免)。必须单列——否则前缀落到 'glm-4'($0.14)。
143
+ "glm-4.7-flash": { input: 0, output: 0, cacheRead: 0 },
135
144
  // GLM-5.2:与 GLM-5.3 同价(同一定价页:8 / 28 / 缓存命中 2 元),口径修正同上。
136
145
  "glm-5.2": { input: 8 / CNY_PER_USD, output: 28 / CNY_PER_USD, cacheRead: 2 / CNY_PER_USD },
137
146
  // GLM-5V-Turbo(2026-04 视觉编程旗舰)官方直连 API 定价 $1.20 / $4.00。
@@ -141,8 +150,26 @@ var PRICING_TABLE = {
141
150
  "glm-z1-air": { input: 0.2, output: 0.6 },
142
151
  "glm-z1-flash": { input: 0, output: 0 },
143
152
  // ── MiniMax (海螺) ────────────────────────────────────────────
144
- // GAP (v0.4.184): MiniMax-M3 / M2.x are unpriced — no verified rate anchor yet.
145
- // Unpriced → `aicli usage` shows "—" (unknown), not a false $0.00. Add when confirmed.
153
+ // 官方定价页 platform.minimax.cn/docs/guides/pricing(2026-10-18 核对,元/百万 tokens),按 ¥6.9 折算。
154
+ // 本 provider 打的是国内站 api.minimaxi.com,按人民币计费。
155
+ // M3 记的是「永久五折」后的价(官方原文标注永久,不同于智谱的限时折扣),≤512K 输入档;
156
+ // >512K 那档见 computeCost 的 LONG_PROMPT_TIERS。M3 未公布缓存写入价,缺省按输入价(偏高估)。
157
+ "minimax-m3": { input: 2.1 / CNY_PER_USD, output: 8.4 / CNY_PER_USD, cacheRead: 0.42 / CNY_PER_USD },
158
+ "minimax-m2.7": { input: 2.1 / CNY_PER_USD, output: 8.4 / CNY_PER_USD, cacheRead: 0.42 / CNY_PER_USD, cacheWrite: 2.625 / CNY_PER_USD },
159
+ "minimax-m2.7-highspeed": { input: 4.2 / CNY_PER_USD, output: 16.8 / CNY_PER_USD, cacheRead: 0.42 / CNY_PER_USD, cacheWrite: 2.625 / CNY_PER_USD },
160
+ // M2.5 / M2.1 / M2(历史模型)同价;highspeed 变体输入输出翻倍、缓存同价。
161
+ "minimax-m2": { input: 2.1 / CNY_PER_USD, output: 8.4 / CNY_PER_USD, cacheRead: 0.21 / CNY_PER_USD, cacheWrite: 2.625 / CNY_PER_USD },
162
+ "minimax-m2.5-highspeed": { input: 4.2 / CNY_PER_USD, output: 16.8 / CNY_PER_USD, cacheRead: 0.21 / CNY_PER_USD, cacheWrite: 2.625 / CNY_PER_USD },
163
+ "minimax-m2.1-highspeed": { input: 4.2 / CNY_PER_USD, output: 16.8 / CNY_PER_USD, cacheRead: 0.21 / CNY_PER_USD, cacheWrite: 2.625 / CNY_PER_USD },
164
+ // ── Qwen(阿里云百炼,北京地域)───────────────────────────────────
165
+ // 官方 help.aliyun.com/zh/model-studio/model-pricing(2026-10-18 核对,元/百万 tokens,原价),按 ¥6.9 折算。
166
+ // 思考与非思考输出同价。qwen3.7-plus 当前限时 8 折,记原价(高估方向,同智谱 glm-5.3-flash 的取舍)。
167
+ // 官方未给出各模型的缓存单价,不填 cacheRead,命中按输入全价算(高估方向)。
168
+ // 长提示分档(qwen3.7-plus >256K、qwen-flash >128K / >256K)见 LONG_PROMPT_TIERS;此处为最低档。
169
+ "qwen3.8-max": { input: 12 / CNY_PER_USD, output: 36 / CNY_PER_USD },
170
+ "qwen3.7-plus": { input: 2 / CNY_PER_USD, output: 8 / CNY_PER_USD },
171
+ "qwen3.8-flash": { input: 0.8 / CNY_PER_USD, output: 2.7 / CNY_PER_USD },
172
+ "qwen-flash": { input: 0.15 / CNY_PER_USD, output: 1.5 / CNY_PER_USD },
146
173
  // ── OpenRouter (pass-through — actual cost depends on underlying model) ──
147
174
  // 绝大多数 id 仍**刻意留空**:真实价由底层模型 + OpenRouter 加价决定,静态表覆盖不了
148
175
  // 396 个模型,未收录的照旧显示 "—"(未知)而不是假的 $0.00。
@@ -197,11 +224,21 @@ function getPricing(provider, model, at = /* @__PURE__ */ new Date()) {
197
224
  return null;
198
225
  }
199
226
  var CLAUDE_HAIKU_55_LONG = { input: 0.5, output: 2.5, cacheWrite: 0.625, cacheRead: 0.05 };
200
- var CLAUDE_HAIKU_55_TIER_TOKENS = 1e5;
227
+ var LONG_PROMPT_TIERS = [
228
+ { prefix: "claude-haiku-5-5", overTokens: 1e5, pricing: CLAUDE_HAIKU_55_LONG },
229
+ {
230
+ prefix: "minimax-m3",
231
+ overTokens: 512e3,
232
+ pricing: { input: 4.2 / CNY_PER_USD, output: 16.8 / CNY_PER_USD, cacheRead: 0.84 / CNY_PER_USD }
233
+ },
234
+ { prefix: "qwen3.7-plus", overTokens: 256e3, pricing: { input: 6 / CNY_PER_USD, output: 24 / CNY_PER_USD } },
235
+ { prefix: "qwen-flash", overTokens: 256e3, pricing: { input: 1.2 / CNY_PER_USD, output: 12 / CNY_PER_USD } },
236
+ { prefix: "qwen-flash", overTokens: 128e3, pricing: { input: 0.6 / CNY_PER_USD, output: 6 / CNY_PER_USD } }
237
+ ];
201
238
  function longPromptTier(model, usage) {
202
- if (!model.toLowerCase().startsWith("claude-haiku-5-5")) return null;
239
+ const key = model.toLowerCase();
203
240
  const prompt = usage.inputTokens + (usage.cacheCreationTokens ?? 0) + (usage.cacheReadTokens ?? 0);
204
- return prompt > CLAUDE_HAIKU_55_TIER_TOKENS ? CLAUDE_HAIKU_55_LONG : null;
241
+ return LONG_PROMPT_TIERS.find((t) => key.startsWith(t.prefix) && prompt > t.overTokens)?.pricing ?? null;
205
242
  }
206
243
  function computeCost(provider, model, usage, at = /* @__PURE__ */ new Date()) {
207
244
  const p = longPromptTier(model, usage) ?? getPricing(provider, model, at);
@@ -13,7 +13,7 @@ import {
13
13
  MEMORY_FILE_NAME,
14
14
  MEMORY_MAX_CHARS,
15
15
  MEMORY_STORE_FILE_NAME
16
- } from "./chunk-6UDKGZ3D.js";
16
+ } from "./chunk-YCDF6FNR.js";
17
17
 
18
18
  // src/memory/persistent-memory.ts
19
19
  import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-6UDKGZ3D.js";
4
+ } from "./chunk-YCDF6FNR.js";
5
5
  import {
6
6
  getExecutionConfigDir,
7
7
  getExecutionSignal
@@ -1270,74 +1270,6 @@ async function runLeanAgentLoop(opts) {
1270
1270
  return { content, usage, roundsUsed, toolCallCount };
1271
1271
  }
1272
1272
 
1273
- // src/tools/types.ts
1274
- function isFileWriteTool(name) {
1275
- return name === "write_file" || name === "edit_file" || name === "notebook_edit";
1276
- }
1277
- function getDangerLevel(toolName, args) {
1278
- if (toolName.startsWith("mcp__")) {
1279
- const rawName = toolName.split("__").pop() ?? "";
1280
- const normalized = rawName.toLowerCase().replace(/[^a-z0-9]+/g, "_");
1281
- if (/^(read|get|list|search|find|query|fetch|status|describe|inspect|show|lookup)(?:_|$)/.test(normalized)) {
1282
- return "safe";
1283
- }
1284
- return "write";
1285
- }
1286
- if (toolName === "bash") {
1287
- const cmd = String(args["command"] ?? "");
1288
- if (/\bgit\s+(?:clean\b|reset\s+--hard\b|push\b[^\n]*(?:--force\b|\s-f\b))/i.test(cmd)) return "destructive";
1289
- if (/\brm\s+[^\n]*(?:-\w*[rRfF]\w*|--recursive|--force)\b/.test(cmd)) return "destructive";
1290
- if (/\brm\s+\S/.test(cmd)) return "destructive";
1291
- if (/\brmdir\b|\bmkfs\b|\bdd\s+if=|\bshred\b|\bfdisk\b|\bparted\b/.test(cmd)) return "destructive";
1292
- if (/(?:^|[;&|(\n]\s*)format(?:\.com)?\s+[A-Za-z]:/im.test(cmd)) return "destructive";
1293
- if (/\bshutdown\b|\breboot\b|\bhalt\b|\bpoweroff\b/.test(cmd)) return "destructive";
1294
- if (/\bkill\s+-9\b|\bkillall\b/.test(cmd)) return "destructive";
1295
- if (/\bRemove-Item\b|\bri\s+\S/i.test(cmd)) return "destructive";
1296
- if (/\brd\s+\/s\b|\brmdir\s+\/s\b/i.test(cmd)) return "destructive";
1297
- if (/\bdel\s+\S/.test(cmd)) return "destructive";
1298
- if (/\bShutdown(-Computer)?\b|\bRestart-Computer\b/i.test(cmd)) return "destructive";
1299
- if (/(?:^|[\s|;&])>>?\s*\S/.test(cmd)) return "write";
1300
- if (/\btee\b|\bcp\b|\bmv\b|\bln\s+-s/.test(cmd)) return "write";
1301
- if (/\bchmod\b|\bchown\b/.test(cmd)) return "write";
1302
- if (/\bSet-Content\b|\bOut-File\b|\bAdd-Content\b|\bCopy-Item\b|\bMove-Item\b|\bSet-ItemProperty\b|\bNew-ItemProperty\b/i.test(cmd)) return "write";
1303
- if (/\b(python3?|node|deno|bun|perl|ruby|php|bash|sh|zsh|pwsh|powershell)(\.exe)?\b[^\n]*?\s-(?:Command|EncodedCommand|c|e|p|r)\b/i.test(cmd)) return "write";
1304
- if (/\bcmd(\.exe)?\s+\/[ck]\b/i.test(cmd)) return "write";
1305
- if (!/[;&|`$<>\n\r(){}]/.test(cmd) && (/^(?:pwd|ls|cat|head|tail|wc|Get-ChildItem|Get-Location|Get-Content)(?:\s+[\w ./\\:*?=,@'"-]+)?\s*$/i.test(cmd.trim()) || /^echo(?:\s+[\w .,'"-]+)?\s*$/.test(cmd.trim()) || /^(?:node|python3?)\s+(?:-v|--version)\s*$/.test(cmd.trim()) || /^git\s+(?:status|log)(?:\s+(?:--short|--porcelain|--oneline|-\d+))*\s*$/.test(cmd.trim()))) return "safe";
1306
- return "write";
1307
- }
1308
- if (toolName === "run_tests") return "write";
1309
- if (toolName === "write_file") return "write";
1310
- if (toolName === "edit_file") return "write";
1311
- if (toolName === "save_last_response") return "write";
1312
- if (toolName === "run_interactive") {
1313
- const exe = String(args["executable"] ?? "").toLowerCase();
1314
- if (/\b(rm|rmdir|del|format|mkfs|Remove-Item)\b/i.test(exe)) return "destructive";
1315
- if (/\b(bash|sh|zsh|cmd|powershell|pwsh|python|node|ruby|perl)\b/i.test(exe)) return "write";
1316
- return "write";
1317
- }
1318
- if (toolName === "task_create" || toolName === "task_stop") return "write";
1319
- if (toolName === "task_list") return "safe";
1320
- if (toolName === "git_commit") return "write";
1321
- if (toolName === "git_status" || toolName === "git_diff" || toolName === "git_log") return "safe";
1322
- if (toolName === "notebook_edit") return "write";
1323
- if (toolName === "read_file" || toolName === "list_dir" || toolName === "grep_files" || toolName === "glob_files" || toolName === "web_fetch" || toolName === "save_memory" || toolName === "ask_user" || toolName === "write_todos" || toolName === "google_search" || toolName === "spawn_agent") return "safe";
1324
- return "write";
1325
- }
1326
- function schemaToJsonSchema(schema) {
1327
- const result = {
1328
- type: schema.type,
1329
- description: schema.description
1330
- };
1331
- if (schema.enum) result["enum"] = schema.enum;
1332
- if (schema.items) result["items"] = schemaToJsonSchema(schema.items);
1333
- if (schema.properties) {
1334
- result["properties"] = Object.fromEntries(
1335
- Object.entries(schema.properties).map(([k, v]) => [k, schemaToJsonSchema(v)])
1336
- );
1337
- }
1338
- return result;
1339
- }
1340
-
1341
1273
  export {
1342
1274
  detectsHallucinatedFileOp,
1343
1275
  TOOL_CALL_REMINDER,
@@ -1360,8 +1292,5 @@ export {
1360
1292
  accumulateUsage,
1361
1293
  buildRoundBudgetHint,
1362
1294
  runAgentLoop,
1363
- runLeanAgentLoop,
1364
- isFileWriteTool,
1365
- getDangerLevel,
1366
- schemaToJsonSchema
1295
+ runLeanAgentLoop
1367
1296
  };
@@ -11,7 +11,7 @@ import {
11
11
  CONFIG_FILE_NAME,
12
12
  HISTORY_DIR_NAME,
13
13
  PLUGINS_DIR_NAME
14
- } from "./chunk-6UDKGZ3D.js";
14
+ } from "./chunk-YCDF6FNR.js";
15
15
 
16
16
  // src/config/config-manager.ts
17
17
  import { readFileSync, existsSync, mkdirSync } from "fs";
@@ -388,8 +388,14 @@ ${err}`
388
388
  "deepseek-v4-flash-vision-exp"
389
389
  ]);
390
390
  const DEEPSEEK_TARGET = "deepseek-flash";
391
- const LEGACY_KIMI = /* @__PURE__ */ new Set(["kimi-k2-0711-preview", "kimi-k2-turbo-preview"]);
392
- const KIMI_TARGET = "kimi-k2.6";
391
+ const LEGACY_KIMI = /* @__PURE__ */ new Set([
392
+ "kimi-k2-0711-preview",
393
+ "kimi-k2-turbo-preview",
394
+ "kimi-k2.5",
395
+ "kimi-k2-thinking",
396
+ "kimi-k2-thinking-turbo"
397
+ ]);
398
+ const KIMI_TARGET = "kimi-k2.7-code";
393
399
  const LEGACY_CLAUDE = {
394
400
  "claude-sonnet-4-5-20250929": "claude-sonnet-5-5",
395
401
  "claude-sonnet-4-5": "claude-sonnet-5-5",
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.329";
2
+ var VERSION = "0.4.331";
3
3
  var APP_NAME = "ai-cli";
4
4
  var CONFIG_DIR_NAME = ".aicli";
5
5
  var CONFIG_FILE_NAME = "config.json";
@@ -8,13 +8,13 @@ import {
8
8
  listHooks,
9
9
  listInstalledPlugins,
10
10
  resetStats
11
- } from "./chunk-SS3PG7LP.js";
11
+ } from "./chunk-Q26V2PNA.js";
12
12
  import {
13
13
  ProviderRegistry
14
- } from "./chunk-I5KLH7TL.js";
14
+ } from "./chunk-QFF2PTI3.js";
15
15
  import {
16
16
  ConfigManager
17
- } from "./chunk-2CNJ25U7.js";
17
+ } from "./chunk-CM5C7ZSM.js";
18
18
  import {
19
19
  getGitRoot
20
20
  } from "./chunk-HOSJZMQS.js";
@@ -26,7 +26,7 @@ import {
26
26
  MCP_PROJECT_CONFIG_NAME,
27
27
  MEMORY_FILE_NAME,
28
28
  VERSION
29
- } from "./chunk-6UDKGZ3D.js";
29
+ } from "./chunk-YCDF6FNR.js";
30
30
 
31
31
  // src/diagnostics/doctor-report.ts
32
32
  import { existsSync as existsSync3, statSync as statSync2 } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-6UDKGZ3D.js";
4
+ } from "./chunk-YCDF6FNR.js";
5
5
 
6
6
  // src/cli/ci-format.ts
7
7
  var DEFAULT_CI_THRESHOLDS = {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  computeCost,
4
4
  formatCost
5
- } from "./chunk-BRZZ3QAI.js";
5
+ } from "./chunk-2BAFLDDL.js";
6
6
  import {
7
7
  clearRecentlyDeniedAutoActions,
8
8
  estimateTokens,
@@ -16,7 +16,7 @@ import {
16
16
  setPreferredAgentName,
17
17
  truncateForPersist,
18
18
  undoStack
19
- } from "./chunk-MPCQG7LV.js";
19
+ } from "./chunk-RZDRBFAB.js";
20
20
  import {
21
21
  buildReviewPrompt,
22
22
  buildSecurityReviewPrompt
@@ -51,7 +51,7 @@ import {
51
51
  touchMemoryReferences,
52
52
  updateMemoryApproval,
53
53
  updateMemoryEntry
54
- } from "./chunk-XF2S7LNM.js";
54
+ } from "./chunk-56ME7PB2.js";
55
55
  import {
56
56
  theme
57
57
  } from "./chunk-5C76XDDF.js";
@@ -65,7 +65,7 @@ import {
65
65
  import {
66
66
  buildDoctorReport,
67
67
  formatDoctorReport
68
- } from "./chunk-ABIR2TGW.js";
68
+ } from "./chunk-EWARNWJ4.js";
69
69
  import {
70
70
  describePlugin,
71
71
  getActivePluginAssets,
@@ -80,11 +80,11 @@ import {
80
80
  trustHook,
81
81
  trustPlugin,
82
82
  untrustHook
83
- } from "./chunk-SS3PG7LP.js";
83
+ } from "./chunk-Q26V2PNA.js";
84
84
  import {
85
85
  isCleanDocumentBody,
86
86
  stripOuterCodeFence
87
- } from "./chunk-E2W2MI6H.js";
87
+ } from "./chunk-C6GA7H5D.js";
88
88
  import {
89
89
  formatGitContextForPrompt,
90
90
  getGitContext
@@ -109,7 +109,7 @@ import {
109
109
  MCP_TOOL_PREFIX,
110
110
  REPO_URL,
111
111
  VERSION
112
- } from "./chunk-6UDKGZ3D.js";
112
+ } from "./chunk-YCDF6FNR.js";
113
113
 
114
114
  // src/skills/manager.ts
115
115
  import { existsSync, readdirSync, mkdirSync, statSync } from "fs";
@@ -2445,7 +2445,7 @@ No tools match "${filter}".
2445
2445
  const { join: join6 } = await import("path");
2446
2446
  const { existsSync: existsSync6 } = await import("fs");
2447
2447
  const { getGitRoot } = await import("./git-context-EXOEHQSF.js");
2448
- const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-MG7EGG5J.js");
2448
+ const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-4EH6Y6VI.js");
2449
2449
  const { approveProject, hashMcpFile } = await import("./project-trust-KGG2BWKC.js");
2450
2450
  const cwd = process.cwd();
2451
2451
  const projectRoot = getGitRoot(cwd) ?? cwd;
@@ -3553,7 +3553,7 @@ function createReviewCommands() {
3553
3553
  usage: "/test [command|filter]",
3554
3554
  async execute(args, ctx) {
3555
3555
  try {
3556
- const { executeTests } = await import("./run-tests-YTRU22LY.js");
3556
+ const { executeTests } = await import("./run-tests-2TVEWCQI.js");
3557
3557
  const argStr = args.join(" ").trim();
3558
3558
  let testArgs = {};
3559
3559
  if (argStr) {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  evaluateCiGate,
4
4
  normalizeCiThresholds
5
- } from "./chunk-YDH5ZWOQ.js";
5
+ } from "./chunk-IJNDIOOQ.js";
6
6
  import {
7
7
  buildReviewPrompt,
8
8
  buildSecurityReviewPrompt,
@@ -13,13 +13,13 @@ import {
13
13
  } from "./chunk-6YZEZFX5.js";
14
14
  import {
15
15
  ProviderRegistry
16
- } from "./chunk-I5KLH7TL.js";
16
+ } from "./chunk-QFF2PTI3.js";
17
17
  import {
18
18
  ConfigManager
19
- } from "./chunk-2CNJ25U7.js";
19
+ } from "./chunk-CM5C7ZSM.js";
20
20
  import {
21
21
  VERSION
22
- } from "./chunk-6UDKGZ3D.js";
22
+ } from "./chunk-YCDF6FNR.js";
23
23
 
24
24
  // src/cli/ci.ts
25
25
  import { execFileSync } from "child_process";
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ ThinkTagFilter
4
+ } from "./chunk-C6GA7H5D.js";
2
5
 
3
6
  // src/hub/convergence.ts
4
7
  function convergenceThreshold(total) {
@@ -19,8 +22,12 @@ function stripConvergedMarker(content) {
19
22
 
20
23
  // src/hub/agent.ts
21
24
  var PASS_MARKER = "[PASS]";
25
+ function stripThinkBlocks(raw) {
26
+ const filter = new ThinkTagFilter();
27
+ return filter.push(raw) + filter.flush();
28
+ }
22
29
  function parseTurn(raw) {
23
- const trimmed = raw.trim();
30
+ const trimmed = stripThinkBlocks(raw).trim();
24
31
  const upper = trimmed.toUpperCase();
25
32
  if (upper.startsWith(PASS_MARKER) || upper === PASS_MARKER) {
26
33
  return { content: "", passed: true, converged: false };
@@ -100,6 +107,7 @@ var HubAgent = class {
100
107
  const systemPrompt = this.buildSystemPrompt(topic, round, maxRounds, opts?.voteConverge);
101
108
  const messages = this.buildMessages(history);
102
109
  let raw = "";
110
+ const thinkFilter = new ThinkTagFilter();
103
111
  const stream = provider.chatStream({
104
112
  messages,
105
113
  model: this.modelId,
@@ -114,13 +122,16 @@ var HubAgent = class {
114
122
  for await (const chunk of stream) {
115
123
  if (chunk.delta) {
116
124
  raw += chunk.delta;
117
- onToken?.(chunk.delta);
125
+ const visible = thinkFilter.push(chunk.delta);
126
+ if (visible) onToken?.(visible);
118
127
  }
119
128
  if (opts?.signal?.aborted) break;
120
129
  }
121
130
  } catch (error) {
122
131
  if (!opts?.signal?.aborted) throw error;
123
132
  }
133
+ const tail = thinkFilter.flush();
134
+ if (tail) onToken?.(tail);
124
135
  const { content, passed, converged } = parseTurn(raw);
125
136
  return {
126
137
  speaker: this.role.id,
@@ -155,7 +166,7 @@ var HubAgent = class {
155
166
  maxTokens: 4096,
156
167
  ...this.thinking ?? {}
157
168
  });
158
- return response.content.trim();
169
+ return stripThinkBlocks(response.content).trim();
159
170
  }
160
171
  // ── Private ──────────────────────────────────────────────────────
161
172
  buildSystemPrompt(topic, round, maxRounds, voteConverge) {
@@ -236,7 +247,7 @@ Produce a structured, decision-oriented synthesis with these exact sections:
236
247
  4. **Action Items** \u2014 concrete next steps as a checklist. For each, suggest which role/expertise should own it, e.g. "- [ ] (\u67B6\u6784\u5E08) \u8BC4\u4F30\u670D\u52A1\u62C6\u5206\u8FB9\u754C".
237
248
  5. **Risks & Open Questions** \u2014 unresolved issues and what to watch.
238
249
 
239
- Keep it tight (within ~600 words). Use the same language as the discussion.`;
250
+ Keep it tight (within ~600 words). Use the same language as the discussion \u2014 including the section headings (translate them, e.g. \u51B3\u7B56 / \u5EFA\u8BAE\u3001\u5173\u952E\u5171\u8BC6\u3001\u5206\u6B67\u70B9\u3001\u884C\u52A8\u9879\u3001\u98CE\u9669\u4E0E\u5F00\u653E\u95EE\u9898 for a Chinese discussion).`;
240
251
  }
241
252
  };
242
253
 
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  HubAgent,
4
4
  isConverged
5
- } from "./chunk-C2Z77RTU.js";
5
+ } from "./chunk-MN25ELTF.js";
6
6
 
7
7
  // src/hub/discuss.ts
8
8
  var DiscussionOrchestrator = class {
@@ -379,9 +379,61 @@ function resolveRoleProviders(roles, lookup, defaultProvider, defaultModel, avai
379
379
  return { roles: outRoles, assignments, warnings };
380
380
  }
381
381
 
382
+ // src/hub/custom-presets.ts
383
+ import { existsSync, readdirSync, readFileSync } from "fs";
384
+ import { join, basename } from "path";
385
+ var CUSTOM_PRESET_PREFIX = "custom:";
386
+ var HUB_ROLES_DIRNAME = "hub-roles";
387
+ function parseRolesJson(parsed) {
388
+ const rawRoles = Array.isArray(parsed) ? parsed : parsed?.roles;
389
+ if (!Array.isArray(rawRoles) || rawRoles.length === 0) {
390
+ throw new Error("roles must be a non-empty array");
391
+ }
392
+ return rawRoles.map((r) => ({
393
+ id: r.id ?? r.name?.toLowerCase().replace(/\s+/g, "-") ?? "agent",
394
+ name: r.name ?? r.id ?? "Agent",
395
+ persona: r.persona ?? r.description ?? `You are ${r.name ?? "an AI assistant"}.`,
396
+ ...r.provider && { provider: r.provider },
397
+ ...r.model && { model: r.model },
398
+ ...r.color && { color: r.color }
399
+ }));
400
+ }
401
+ function loadCustomPresets(configDir) {
402
+ const dir = join(configDir, HUB_ROLES_DIRNAME);
403
+ const presets = [];
404
+ const warnings = [];
405
+ if (!existsSync(dir)) return { presets, warnings };
406
+ let files;
407
+ try {
408
+ files = readdirSync(dir).filter((f) => f.toLowerCase().endsWith(".json")).sort();
409
+ } catch (err) {
410
+ return { presets, warnings: [`${dir}: ${err.message}`] };
411
+ }
412
+ for (const file of files) {
413
+ const stem = basename(file, file.slice(file.lastIndexOf(".")));
414
+ try {
415
+ const parsed = JSON.parse(readFileSync(join(dir, file), "utf-8").replace(/^/, ""));
416
+ const roles = parseRolesJson(parsed);
417
+ const meta = Array.isArray(parsed) ? {} : parsed;
418
+ presets.push({
419
+ id: `${CUSTOM_PRESET_PREFIX}${stem}`,
420
+ name: typeof meta.name === "string" && meta.name.trim() ? meta.name.trim() : stem,
421
+ description: typeof meta.description === "string" && meta.description.trim() ? meta.description.trim() : roles.map((r) => r.name).join("\xB7"),
422
+ roles
423
+ });
424
+ } catch (err) {
425
+ warnings.push(`${HUB_ROLES_DIRNAME}/${file}: ${err.message}`);
426
+ }
427
+ }
428
+ return { presets, warnings };
429
+ }
430
+
382
431
  export {
383
432
  DiscussionOrchestrator,
384
433
  getPreset,
385
434
  listPresets,
386
- resolveRoleProviders
435
+ resolveRoleProviders,
436
+ CUSTOM_PRESET_PREFIX,
437
+ parseRolesJson,
438
+ loadCustomPresets
387
439
  };
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  CONFIG_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-6UDKGZ3D.js";
11
+ } from "./chunk-YCDF6FNR.js";
12
12
 
13
13
  // src/diagnostics/tool-stats.ts
14
14
  import { mkdirSync } from "fs";