jinzd-ai-cli 0.4.294 → 0.4.297

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 (34) hide show
  1. package/dist/{batch-6YCLYEII.js → batch-YFQ34DHW.js} +2 -2
  2. package/dist/{chunk-FARHJ42Q.js → chunk-3GIKUDYZ.js} +4 -4
  3. package/dist/{chunk-MMP6SIB7.js → chunk-56AX43FT.js} +1 -1
  4. package/dist/{chunk-CUMSLQKQ.js → chunk-6PBWL3XI.js} +1 -1
  5. package/dist/{chunk-HBFES3RR.js → chunk-CF6RC7OB.js} +4 -4
  6. package/dist/{chunk-UPJMIP5S.js → chunk-D7GLDXPQ.js} +1 -1
  7. package/dist/{chunk-AIQMQCVF.js → chunk-DPNKOXJF.js} +48 -11
  8. package/dist/{chunk-SM7VOJ3B.js → chunk-EFHAMIQF.js} +204 -167
  9. package/dist/{chunk-QKZUWT3S.js → chunk-FBOVBL7P.js} +12 -1
  10. package/dist/{chunk-BOG6LVIC.js → chunk-FZUMKY6C.js} +1 -1
  11. package/dist/{chunk-3H7TVTAE.js → chunk-GNJ3XLS3.js} +1 -1
  12. package/dist/{chunk-7KYONZUN.js → chunk-J6CYL6RN.js} +1 -1
  13. package/dist/{chunk-P3BJAJ34.js → chunk-LXORMKZ6.js} +1 -1
  14. package/dist/{chunk-OMA6DEAR.js → chunk-NB2V7H5C.js} +1 -1
  15. package/dist/{chunk-ZBHRTOWC.js → chunk-O33BYKAD.js} +1 -1
  16. package/dist/{chunk-4J6R2VFW.js → chunk-YKJO3SI4.js} +33 -4
  17. package/dist/{ci-SIS77LEG.js → ci-AR2RLLJD.js} +5 -5
  18. package/dist/{ci-format-LRMGY4ND.js → ci-format-S7RRDV4A.js} +2 -2
  19. package/dist/{constants-QRUMNMCK.js → constants-VZBWOKZZ.js} +1 -1
  20. package/dist/{constants-C7LOS6F4.js → constants-W52VYKDV.js} +1 -1
  21. package/dist/{doctor-cli-UB5KUBVI.js → doctor-cli-VX36CZND.js} +5 -5
  22. package/dist/electron-server.js +138 -24
  23. package/dist/{hub-UWBNCMD4.js → hub-LJL3X7KR.js} +1 -1
  24. package/dist/index.js +24 -23
  25. package/dist/{persistent-memory-TUCWY6O3.js → persistent-memory-CMXW4WSP.js} +2 -2
  26. package/dist/{persistent-memory-GQPXSWDK.js → persistent-memory-WEZMJBIV.js} +2 -2
  27. package/dist/{pr-MVUT6IOA.js → pr-GTDFMNKY.js} +5 -5
  28. package/dist/{run-tests-RSIXZR3O.js → run-tests-ILHN2PYU.js} +2 -2
  29. package/dist/{run-tests-BNKQT42K.js → run-tests-MTWA2NNV.js} +2 -2
  30. package/dist/{server-ILSFJUK5.js → server-QXP5NHE7.js} +15 -15
  31. package/dist/{server-YNVHKFGZ.js → server-WFXEEX2E.js} +5 -5
  32. package/dist/{task-orchestrator-7YEWEKS6.js → task-orchestrator-HZPIN4PT.js} +5 -5
  33. package/dist/{usage-DXX4VHOQ.js → usage-UEN6LLOG.js} +3 -3
  34. package/package.json +3 -1
@@ -50,7 +50,7 @@ import {
50
50
  touchMemoryReferences,
51
51
  updateMemoryApproval,
52
52
  updateMemoryEntry
53
- } from "./chunk-P3BJAJ34.js";
53
+ } from "./chunk-LXORMKZ6.js";
54
54
  import {
55
55
  DEFAULT_PATTERNS,
56
56
  redactJson,
@@ -66,7 +66,7 @@ import {
66
66
  } from "./chunk-CGLYJRFA.js";
67
67
  import {
68
68
  runTestsTool
69
- } from "./chunk-OMA6DEAR.js";
69
+ } from "./chunk-NB2V7H5C.js";
70
70
  import {
71
71
  AGENTIC_BEHAVIOR_GUIDELINE,
72
72
  APP_NAME,
@@ -100,7 +100,7 @@ import {
100
100
  SUBAGENT_MAX_ROUNDS_LIMIT,
101
101
  VERSION,
102
102
  buildUserIdentityPrompt
103
- } from "./chunk-UPJMIP5S.js";
103
+ } from "./chunk-D7GLDXPQ.js";
104
104
 
105
105
  // src/web/server.ts
106
106
  import express from "express";
@@ -882,14 +882,42 @@ var PRICING_TABLE = {
882
882
  "glm-5.1-air": { input: 0.4, output: 1.2 },
883
883
  "glm-z1": { input: 0.5, output: 1.5 },
884
884
  "glm-z1-air": { input: 0.2, output: 0.6 },
885
- "glm-z1-flash": { input: 0, output: 0 }
885
+ "glm-z1-flash": { input: 0, output: 0 },
886
886
  // ── MiniMax (海螺) ────────────────────────────────────────────
887
887
  // GAP (v0.4.184): MiniMax-M3 / M2.x are unpriced — no verified rate anchor yet.
888
888
  // Unpriced → `aicli usage` shows "—" (unknown), not a false $0.00. Add when confirmed.
889
889
  // ── OpenRouter (pass-through — actual cost depends on underlying model) ──
890
- // Left empty by design: model IDs are "vendor/model" (e.g. anthropic/claude-sonnet-4)
891
- // and the real price is set by the underlying model + OpenRouter markup, not statically
892
- // resolvable here. Shows "—" (unknown) in `aicli usage`.
890
+ // 绝大多数 id 仍**刻意留空**:真实价由底层模型 + OpenRouter 加价决定,静态表覆盖不了
891
+ // 396 个模型,未收录的照旧显示 "—"(未知)而不是假的 $0.00。
892
+ //
893
+ // 下面这批是 curated 列表里的国产旗舰,**2026-08-29 对 `/api/v1/models` 实测取回的一手
894
+ // 价格**(该端点直接返回每 token 单价,这里换算成每百万 token 的美元数)。收录它们是因为
895
+ // 东叔真的会用,而 `aicli usage` 记不到价就等于这条路的花费不进预算告警。
896
+ //
897
+ // ⚠ 这是**快照**,不是实时价:OpenRouter 的价格随底层供应商变动,且它自己就有多家供应商
898
+ // 轮转。偏差方向未知(不像智谱那次能靠"记恢复价"保证高估),故注明取数日期,发现明显不符
899
+ // 时以 `/api/v1/models` 为准重取。
900
+ //
901
+ // 与直连国内的对照(同一模型、同一天):
902
+ // deepseek-v4-flash-0731 直连闲时 $0.217/$0.652、峰时 $0.435/$1.304
903
+ // OpenRouter $0.045/$0.090 → **便宜约 5–14 倍**
904
+ // deepseek-v4-pro-0813 直连闲时 $0.652/$1.957 ≈ OpenRouter $0.660/$1.980(基本持平)
905
+ // 直连峰时 $1.304/$3.913 → OpenRouter 便宜约一半
906
+ // glm-5.3-flash 直连恢复价 $0.116/$0.406、5 折促销价 $0.058/$0.203
907
+ // OpenRouter $0.075/$0.250 → 比恢复价便宜、比促销价略贵
908
+ // kimi-k3 两边同价($3.00/$15.00)
909
+ "deepseek/deepseek-v4-flash-0731": { input: 0.045, output: 0.09 },
910
+ "deepseek/deepseek-v4-flash-0731:batch": { input: 0.14, output: 0.28 },
911
+ "deepseek/deepseek-v4-flash": { input: 0.086, output: 0.171 },
912
+ "deepseek/deepseek-v4-pro-0813": { input: 0.66, output: 1.98 },
913
+ "deepseek/deepseek-v4-pro-0813:batch": { input: 1.32, output: 3.96 },
914
+ "deepseek/deepseek-v4-pro": { input: 0.701, output: 1.402 },
915
+ "z-ai/glm-5.3-flash": { input: 0.075, output: 0.25 },
916
+ "z-ai/glm-5.3-flash:batch": { input: 0.15, output: 0.5 },
917
+ "z-ai/glm-5.3": { input: 1.4, output: 4.4 },
918
+ "z-ai/glm-4.6": { input: 0.43, output: 1.75 },
919
+ "moonshotai/kimi-k3": { input: 3, output: 15 },
920
+ "minimax/minimax-m3": { input: 0.3, output: 1.2 }
893
921
  // ── Ollama (local, zero cost) ─────────────────────────────────
894
922
  // Handled via provider check below (FREE_PROVIDERS → genuine $0.00, not "unknown").
895
923
  };
@@ -899,6 +927,7 @@ function getPricing(provider, model, at = /* @__PURE__ */ new Date()) {
899
927
  return { input: 0, output: 0 };
900
928
  }
901
929
  const key = model.toLowerCase();
930
+ if (key.endsWith(":free")) return { input: 0, output: 0 };
902
931
  if (provider.toLowerCase() === "deepseek") {
903
932
  const dynamicPricing = getDeepSeekV4Pricing(key, at);
904
933
  if (dynamicPricing) return dynamicPricing;
@@ -4425,7 +4454,18 @@ var OPENROUTER_CONFIG = {
4425
4454
  { id: "meta-llama/llama-4-maverick", displayName: "Llama 4 Maverick", contextWindow: 1048576, supportsStreaming: true },
4426
4455
  { id: "meta-llama/llama-4-scout", displayName: "Llama 4 Scout", contextWindow: 512e3, supportsStreaming: true },
4427
4456
  { id: "qwen/qwen3-coder", displayName: "Qwen3 Coder", contextWindow: 262144, supportsStreaming: true },
4428
- { id: "mistralai/mistral-large", displayName: "Mistral Large", contextWindow: 131072, supportsStreaming: true }
4457
+ { id: "mistralai/mistral-large", displayName: "Mistral Large", contextWindow: 131072, supportsStreaming: true },
4458
+ // ── 国产旗舰(2026-08-29 对 /api/v1/models 实测取回的真实 id、上下文与价格)──
4459
+ // 走 OpenRouter 的理由不只是"多一个入口":DeepSeek V4 Flash 在这里比直连国内**便宜一个
4460
+ // 数量级**(详见 pricing.ts 的对照注释)。id 一律 `vendor/model` 形式,与直连 provider
4461
+ // 的裸 id 不冲突。
4462
+ { id: "deepseek/deepseek-v4-flash-0731", displayName: "DeepSeek V4 Flash (0731) \u2014 \u6781\u5EC9\u4EF7, 1.31M", contextWindow: 1310720, supportsStreaming: true, supportsThinking: true },
4463
+ { id: "deepseek/deepseek-v4-pro-0813", displayName: "DeepSeek V4 Pro (0813), 1M", contextWindow: 1048576, supportsStreaming: true, supportsThinking: true },
4464
+ { id: "z-ai/glm-5.3-flash", displayName: "GLM-5.3 Flash (\u591A\u6A21\u6001, 1.31M)", contextWindow: 1310720, supportsStreaming: true, supportsThinking: true },
4465
+ { id: "z-ai/glm-5.3", displayName: "GLM-5.3 (\u65D7\u8230, 1.31M)", contextWindow: 1310720, supportsStreaming: true, supportsThinking: true },
4466
+ { id: "z-ai/glm-4.6", displayName: "GLM-4.6 (\u4E2D\u6587\u5199\u4F5C, 200K)", contextWindow: 204800, supportsStreaming: true },
4467
+ { id: "moonshotai/kimi-k3", displayName: "Kimi K3 (1M)", contextWindow: 1048576, supportsStreaming: true, supportsThinking: true },
4468
+ { id: "minimax/minimax-m3", displayName: "MiniMax M3 (1M)", contextWindow: 1048576, supportsStreaming: true }
4429
4469
  ]
4430
4470
  };
4431
4471
  var OpenRouterProvider = createStaticProviderClass(OPENROUTER_CONFIG);
@@ -6007,7 +6047,8 @@ Important rules:
6007
6047
  3. Multiple commands can be combined with semicolons in a single call to reduce rounds.
6008
6048
  4. To delete directories, use Remove-Item -Recurse (the system will automatically optimize to a more reliable method).
6009
6049
  5. IMPORTANT: On Windows, "curl" is an alias for Invoke-WebRequest and does NOT support curl flags like -s, -X, -H. Use Invoke-RestMethod instead for HTTP requests. Example: Invoke-RestMethod -Uri "http://localhost:3000/api/health" -Method Get
6010
- 6. NEVER run long-running / never-exiting commands through bash \u2014 they block until timeout. This includes starting an Android emulator (emulator -avd X), streaming logs (adb logcat), and dev servers (node server.js, npm run dev, metro / react-native start). Use the 'task_create' tool to run these in the background, then poll status with short bash calls (e.g. adb shell getprop sys.boot_completed).` : `Execute commands in ${SHELL2}.
6050
+ 6. NEVER run long-running / never-exiting commands through bash \u2014 they block until timeout. This includes starting an Android emulator (emulator -avd X), streaming logs (adb logcat), and dev servers (node server.js, npm run dev, metro / react-native start). Use the 'task_create' tool to run these in the background, then poll status with short bash calls (e.g. adb shell getprop sys.boot_completed).
6051
+ 7. CRITICAL \u2014 this is PowerShell, NOT bash: \\ is NOT an escape character. Writing \\" inside a double-quoted string CLOSES the string and silently splits your command into fragments \u2014 it often still exits 0 with no output, so it looks like it worked when it did not. To escape a quote use \`" or "". For anything with nested quoting (especially ssh + psql -c "SELECT ..."), do NOT try to escape your way out: write the payload to a file with the 'write_file' tool, 'scp' it to the host, and run it with a single level of quoting (e.g. ssh host "psql -d db -f /tmp/x.sql").` : `Execute commands in ${SHELL2}.
6011
6052
  Important rules:
6012
6053
  1. Each bash call runs in an independent subprocess; cd commands do not persist. To run in a specific directory, use the cwd parameter, or combine commands: e.g. "cd mydir && ls" or "mkdir -p mydir && touch mydir/file.txt".
6013
6054
  2. If a command fails (returns an error or non-zero exit code), stop immediately, report the error to the user, and do not retry the same or similar commands.
@@ -6125,7 +6166,7 @@ ${combined || formatFailureFallback(status)}
6125
6166
  }
6126
6167
  pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
6127
6168
  updateCwdFromCommand(command, effectiveCwd);
6128
- return stdout || "(command completed with no output)";
6169
+ return stdout || emptyOutputResult(command);
6129
6170
  }
6130
6171
  try {
6131
6172
  const { stdout, stderr, status, signal, timedOut, aborted } = await runShell(
@@ -6162,7 +6203,7 @@ ${combined || formatFailureFallback(status)}
6162
6203
  updateCwdFromCommand(command, effectiveCwd);
6163
6204
  pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
6164
6205
  const result = Buffer.isBuffer(stdout) ? IS_WINDOWS3 ? decodeWindowsBuffer(stdout) : stdout.toString("utf-8") : String(stdout ?? "");
6165
- return result || "(command completed with no output)";
6206
+ return result || emptyOutputResult(command);
6166
6207
  } catch (err) {
6167
6208
  pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
6168
6209
  if (err && typeof err === "object") {
@@ -6243,6 +6284,30 @@ function fixWindowsDeleteCommand(command) {
6243
6284
  }
6244
6285
  );
6245
6286
  }
6287
+ function detectPowerShellBackslashQuote(command) {
6288
+ if (!IS_WINDOWS3) return false;
6289
+ let inSingle = false;
6290
+ let inDouble = false;
6291
+ for (let i = 0; i < command.length; i++) {
6292
+ const ch = command[i];
6293
+ if (ch === "\\" && command[i + 1] === '"') {
6294
+ if (inDouble && !inSingle) return true;
6295
+ i++;
6296
+ continue;
6297
+ }
6298
+ if (ch === "'" && !inDouble) inSingle = !inSingle;
6299
+ else if (ch === '"' && !inSingle) inDouble = !inDouble;
6300
+ }
6301
+ return false;
6302
+ }
6303
+ var BACKSLASH_QUOTE_SILENT_WARNING = `
6304
+
6305
+ \u26A0 WARNING: this command contains \\" inside a double-quoted string, but PowerShell does NOT treat \\ as an escape \u2014 that quote CLOSED the string and the command was split into fragments. It exited 0 with no output because the outer program (e.g. ssh) still ran, but it very likely did NOT run what you intended. Do NOT assume this succeeded.
6306
+ Fix: write the payload to a local file with the 'write_file' tool, then 'scp' it over and run 'ssh host "psql -d <db> -f /tmp/x.sql"' (single level of quoting). Inside PowerShell strings, escape a quote with \`" or "" \u2014 never \\".`;
6307
+ function emptyOutputResult(command) {
6308
+ const base = "(command completed with no output)";
6309
+ return detectPowerShellBackslashQuote(command) ? base + BACKSLASH_QUOTE_SILENT_WARNING : base;
6310
+ }
6246
6311
  function buildErrorHint(command, stderr) {
6247
6312
  const hints = [];
6248
6313
  if (IS_WINDOWS3 && /\|\|/.test(command) && /(\|\||is not a valid argument|不是此版本中的有效|ParserError|Unexpected token)/i.test(stderr)) {
@@ -6289,6 +6354,11 @@ function buildErrorHint(command, stderr) {
6289
6354
  `Hint: PostgreSQL says column "${colMissing[1]}" does not exist. Do NOT retry with a guess \u2014 query the actual schema first: \`psql -c "\\d <table>"\` or \`SELECT column_name FROM information_schema.columns WHERE table_name='<table>';\`. Common pitfall: not every table has a 'deleted' soft-delete column.`
6290
6355
  );
6291
6356
  }
6357
+ if (detectPowerShellBackslashQuote(command) && !/^\s*ssh\b/.test(command) && /(syntax error|unexpected|ParserError|parser|意外的|语法|所在位置\s+行|EOF)/i.test(stderr)) {
6358
+ hints.push(
6359
+ `Hint: PowerShell does NOT treat \\ as an escape character \u2014 the \\" in this command closed the double-quoted string and split the command into fragments. Escape quotes with \`" or "" instead. Better: avoid nested quoting entirely \u2014 write the payload to a file with 'write_file', 'scp' it over, and run it with one level of quoting (e.g. ssh host "psql -d <db> -f /tmp/x.sql").`
6360
+ );
6361
+ }
6292
6362
  return hints.length > 0 ? hints.map((h) => `\u{1F4A1} ${h}`).join("\n\n") : null;
6293
6363
  }
6294
6364
  function detectBlockingCommand(command) {
@@ -8259,7 +8329,8 @@ var ToolExecutor = class {
8259
8329
  return Promise.all(calls.map((call) => this.execute(call)));
8260
8330
  }
8261
8331
  console.log();
8262
- console.log(theme.heading(`\u270E Batch file writes (${calls.length} files):`));
8332
+ const roundBadge = this.totalRounds > 0 ? theme.dim(` [${this.round}/${this.totalRounds}]`) : "";
8333
+ console.log(theme.heading(`\u270E Batch file writes (${calls.length} files):`) + roundBadge);
8263
8334
  console.log(theme.dim("\u2500".repeat(50)));
8264
8335
  for (let i = 0; i < calls.length; i++) {
8265
8336
  const call = calls[i];
@@ -8645,9 +8716,15 @@ var subAgentGuard = {
8645
8716
  active: false
8646
8717
  };
8647
8718
 
8719
+ // src/tools/text-metrics.ts
8720
+ function countTextLines(text) {
8721
+ if (text === "") return 0;
8722
+ return text.replace(/\n$/, "").split("\n").length;
8723
+ }
8724
+
8648
8725
  // src/tools/builtin/write-file.ts
8649
8726
  function countFileLines(filePath) {
8650
- return readFileSync10(filePath, "utf-8").split("\n").length;
8727
+ return countTextLines(readFileSync10(filePath, "utf-8"));
8651
8728
  }
8652
8729
  var writeFileTool = {
8653
8730
  definition: {
@@ -8706,7 +8783,7 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
8706
8783
  } else {
8707
8784
  atomicWriteFileSync(filePath, encoding === "utf-8" || encoding === "utf8" ? content : Buffer.from(content, encoding));
8708
8785
  }
8709
- const lines = content.split("\n").length;
8786
+ const lines = countTextLines(content);
8710
8787
  const bytes = Buffer.byteLength(content, encoding);
8711
8788
  const mode = appendMode ? "appended" : "written";
8712
8789
  void (async () => {
@@ -10562,7 +10639,7 @@ Any of these triggers means use save_last_response, NOT write_file:
10562
10639
  undoStack.push(filePath, `save_last_response: ${filePath}`);
10563
10640
  mkdirSync7(dirname6(filePath), { recursive: true });
10564
10641
  atomicWriteFileSync(filePath, content);
10565
- const lines = content.split("\n").length;
10642
+ const lines = countTextLines(content);
10566
10643
  return `File saved: ${filePath} (${lines} lines, ${Buffer.byteLength(content, "utf-8")} bytes)`;
10567
10644
  }
10568
10645
  };
@@ -13799,6 +13876,39 @@ var SkillManager = class {
13799
13876
  return this.skillsDir;
13800
13877
  }
13801
13878
  };
13879
+ function levenshtein(a, b) {
13880
+ const m = a.length, n = b.length;
13881
+ if (m === 0) return n;
13882
+ if (n === 0) return m;
13883
+ let prev = Array.from({ length: n + 1 }, (_, j) => j);
13884
+ for (let i = 1; i <= m; i++) {
13885
+ const cur = [i];
13886
+ for (let j = 1; j <= n; j++) {
13887
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
13888
+ cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost);
13889
+ }
13890
+ prev = cur;
13891
+ }
13892
+ return prev[n];
13893
+ }
13894
+ function suggestSkillName(names, input) {
13895
+ const norm2 = (s) => s.toLowerCase().replace(/[-_\s]/g, "");
13896
+ const target = norm2(input);
13897
+ if (!target) return null;
13898
+ const exact = names.find((n) => norm2(n) === target);
13899
+ if (exact) return exact;
13900
+ const limit = Math.min(3, Math.max(1, Math.floor(target.length / 4)));
13901
+ let best = null;
13902
+ let bestScore = Infinity;
13903
+ for (const n of names) {
13904
+ const d = levenshtein(norm2(n), target);
13905
+ if (d <= limit && d < bestScore) {
13906
+ best = n;
13907
+ bestScore = d;
13908
+ }
13909
+ }
13910
+ return best;
13911
+ }
13802
13912
 
13803
13913
  // src/web/tool-executor-web.ts
13804
13914
  import { randomUUID as randomUUID2 } from "crypto";
@@ -16921,7 +17031,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
16921
17031
  Cost: ${formatCost(cost)}` : "";
16922
17032
  let memoryLine = "";
16923
17033
  try {
16924
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-TUCWY6O3.js");
17034
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-CMXW4WSP.js");
16925
17035
  const pending = countPendingMemories2(ctx.config.getConfigDir());
16926
17036
  if (pending > 0) memoryLine = `
16927
17037
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -17904,7 +18014,7 @@ async function handleTest(args, ctx) {
17904
18014
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
17905
18015
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
17906
18016
  }
17907
- const runTests = ctx.runTests ?? (await import("./run-tests-RSIXZR3O.js")).executeTests;
18017
+ const runTests = ctx.runTests ?? (await import("./run-tests-ILHN2PYU.js")).executeTests;
17908
18018
  const report = await runTests(testArgs);
17909
18019
  ctx.send({ type: "info", message: report });
17910
18020
  } catch (err) {
@@ -18294,7 +18404,7 @@ async function handleMemory(args, ctx) {
18294
18404
  }
18295
18405
  if (intent.kind === "status") {
18296
18406
  const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-DGUOUUQW.js");
18297
- const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-TUCWY6O3.js");
18407
+ const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-CMXW4WSP.js");
18298
18408
  const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
18299
18409
  const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
18300
18410
  const view = buildMemoryStatusView({
@@ -18317,7 +18427,7 @@ async function handleMemory(args, ctx) {
18317
18427
  return;
18318
18428
  }
18319
18429
  if (intent.kind === "recall") {
18320
- const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-TUCWY6O3.js");
18430
+ const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-CMXW4WSP.js");
18321
18431
  const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-DGUOUUQW.js");
18322
18432
  const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
18323
18433
  if (persistentHits.length > 0) {
@@ -18438,7 +18548,7 @@ async function handleMemory(args, ctx) {
18438
18548
  ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
18439
18549
  } else if (intent.kind === "export") {
18440
18550
  if (args[1] === "md") {
18441
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-TUCWY6O3.js");
18551
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-CMXW4WSP.js");
18442
18552
  ctx.send({
18443
18553
  type: "export_data",
18444
18554
  format: "md",
@@ -19443,7 +19553,7 @@ No tools match "${filter}".
19443
19553
  const { join: join29 } = await import("path");
19444
19554
  const { existsSync: existsSync33 } = await import("fs");
19445
19555
  const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
19446
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-QRUMNMCK.js");
19556
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-VZBWOKZZ.js");
19447
19557
  const { approveProject, hashMcpFile } = await import("./project-trust-MUG325AW.js");
19448
19558
  const cwd = process.cwd();
19449
19559
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -19592,9 +19702,13 @@ No tools match "${filter}".
19592
19702
  ctx.renderer.printSuccess(`Reloaded: ${count} skill(s) found.`);
19593
19703
  return;
19594
19704
  }
19595
- const target = manager.listSkills().find((s) => s.meta.name === sub);
19705
+ const allSkills = manager.listSkills();
19706
+ const target = allSkills.find((s) => s.meta.name === sub);
19596
19707
  if (!target) {
19597
- ctx.renderer.renderError(`Skill '${sub}' not found. Use /skill list to see available skills.`);
19708
+ const guess = suggestSkillName(allSkills.map((s) => s.meta.name), sub);
19709
+ ctx.renderer.renderError(
19710
+ guess ? `Skill '${sub}' not found. Did you mean '${guess}'? (/skill ${guess})` : `Skill '${sub}' not found. Use /skill list to see available skills.`
19711
+ );
19598
19712
  return;
19599
19713
  }
19600
19714
  const prev = manager.getActive();
@@ -20358,7 +20472,7 @@ function createReviewCommands() {
20358
20472
  usage: "/test [command|filter]",
20359
20473
  async execute(args, ctx) {
20360
20474
  try {
20361
- const { executeTests } = await import("./run-tests-RSIXZR3O.js");
20475
+ const { executeTests } = await import("./run-tests-ILHN2PYU.js");
20362
20476
  const argStr = args.join(" ").trim();
20363
20477
  let testArgs = {};
20364
20478
  if (argStr) {
@@ -158,7 +158,7 @@ ${content}`);
158
158
  }
159
159
  }
160
160
  async function runTaskMode(config, providers, configManager, topic) {
161
- const { TaskOrchestrator } = await import("./task-orchestrator-7YEWEKS6.js");
161
+ const { TaskOrchestrator } = await import("./task-orchestrator-HZPIN4PT.js");
162
162
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
163
163
  let interrupted = false;
164
164
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -24,12 +24,12 @@ import {
24
24
  setupProxy,
25
25
  snapshotFile,
26
26
  stripRoutingTags
27
- } from "./chunk-SM7VOJ3B.js";
27
+ } from "./chunk-EFHAMIQF.js";
28
28
  import {
29
29
  CostTracker,
30
30
  getPricing,
31
31
  setCostCurrency
32
- } from "./chunk-4J6R2VFW.js";
32
+ } from "./chunk-YKJO3SI4.js";
33
33
  import {
34
34
  ToolExecutor,
35
35
  ToolRegistry,
@@ -49,7 +49,7 @@ import {
49
49
  setMaxOutputCap,
50
50
  spawnAgentContext,
51
51
  undoStack
52
- } from "./chunk-AIQMQCVF.js";
52
+ } from "./chunk-DPNKOXJF.js";
53
53
  import "./chunk-HLWUDRBO.js";
54
54
  import {
55
55
  NO_THINKING,
@@ -62,7 +62,7 @@ import {
62
62
  countPendingMemories,
63
63
  detectStaleLegacyMarkdownEdit,
64
64
  formatMemoryForPrompt
65
- } from "./chunk-7KYONZUN.js";
65
+ } from "./chunk-J6CYL6RN.js";
66
66
  import "./chunk-4DEMGCK4.js";
67
67
  import "./chunk-UUSRWSSX.js";
68
68
  import "./chunk-CKH4KQ4E.js";
@@ -83,22 +83,22 @@ import {
83
83
  import {
84
84
  loadContextFiles,
85
85
  writeCrashLog
86
- } from "./chunk-FARHJ42Q.js";
86
+ } from "./chunk-3GIKUDYZ.js";
87
87
  import {
88
88
  getActivePluginAssets,
89
89
  getPendingHookTrust,
90
90
  installFlushOnExit,
91
91
  mergePluginHooks,
92
92
  runLifecycleHooks
93
- } from "./chunk-BOG6LVIC.js";
93
+ } from "./chunk-FZUMKY6C.js";
94
94
  import "./chunk-RS7SKYTS.js";
95
95
  import {
96
96
  ProviderRegistry,
97
97
  listBuiltInProviderMetadata
98
- } from "./chunk-QKZUWT3S.js";
98
+ } from "./chunk-FBOVBL7P.js";
99
99
  import {
100
100
  ConfigManager
101
- } from "./chunk-ZBHRTOWC.js";
101
+ } from "./chunk-O33BYKAD.js";
102
102
  import {
103
103
  CONTENT_ONLY_STREAM_REMINDER,
104
104
  TEE_FINAL_USER_NUDGE,
@@ -132,7 +132,7 @@ import {
132
132
  } from "./chunk-IW3Q7AE5.js";
133
133
  import "./chunk-XNFIYS7G.js";
134
134
  import "./chunk-4BKXL7SM.js";
135
- import "./chunk-MMP6SIB7.js";
135
+ import "./chunk-56AX43FT.js";
136
136
  import {
137
137
  AGENTIC_BEHAVIOR_GUIDELINE,
138
138
  AUTHOR,
@@ -149,7 +149,7 @@ import {
149
149
  SKILLS_DIR_NAME,
150
150
  VERSION,
151
151
  buildUserIdentityPrompt
152
- } from "./chunk-CUMSLQKQ.js";
152
+ } from "./chunk-6PBWL3XI.js";
153
153
 
154
154
  // src/index.ts
155
155
  import { program } from "commander";
@@ -1067,12 +1067,13 @@ ${content}
1067
1067
 
1068
1068
  // src/repl/vision-hint.ts
1069
1069
  function getVisionModelHint(model, provider) {
1070
+ const bare = model.includes("/") ? model.slice(model.lastIndexOf("/") + 1) : model;
1070
1071
  if (provider === "claude") return null;
1071
1072
  if (provider === "gemini") return null;
1072
- if (model.includes("vision") || model.includes("vl") || model.includes("5v") || // glm-5v-turbo
1073
- model.endsWith(".6v") || // glm-4.6v
1074
- model === "glm-5.3-flash" || // GLM-5 系列首个原生多模态(名字里没有 v,得单独认)
1075
- model.endsWith("-v")) return null;
1073
+ if (bare.includes("vision") || bare.includes("vl") || bare.includes("5v") || // glm-5v-turbo
1074
+ bare.endsWith(".6v") || // glm-4.6v
1075
+ bare === "glm-5.3-flash" || // GLM-5 系列首个原生多模态(名字里没有 v,得单独认)
1076
+ bare.endsWith("-v")) return null;
1076
1077
  if (provider === "kimi") {
1077
1078
  if (model.startsWith("moonshot-v1-")) {
1078
1079
  const visionModel = model + "-vision-preview";
@@ -4004,7 +4005,7 @@ program.command("web").description("Start Web UI server with browser-based chat
4004
4005
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
4005
4006
  process.exit(1);
4006
4007
  }
4007
- const { startWebServer } = await import("./server-ILSFJUK5.js");
4008
+ const { startWebServer } = await import("./server-QXP5NHE7.js");
4008
4009
  await startWebServer({ port, host: options.host });
4009
4010
  });
4010
4011
  program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
@@ -4171,11 +4172,11 @@ program.command("sessions").description("List recent conversation sessions").opt
4171
4172
  console.log(footer + "\n");
4172
4173
  });
4173
4174
  program.command("usage").description("Show token + cost usage grouped by provider/model (cross-session)").option("--days <n>", "Only the last N days (inclusive of today)").option("--month <ym>", "Only a specific month, format YYYY-MM (e.g. 2026-06)").option("--json", "Output as JSON (for scripting)").action(async (options) => {
4174
- const { runUsageCli } = await import("./usage-DXX4VHOQ.js");
4175
+ const { runUsageCli } = await import("./usage-UEN6LLOG.js");
4175
4176
  await runUsageCli(options);
4176
4177
  });
4177
4178
  program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
4178
- const { runDoctorCli } = await import("./doctor-cli-UB5KUBVI.js");
4179
+ const { runDoctorCli } = await import("./doctor-cli-VX36CZND.js");
4179
4180
  const argv = process.argv.slice(2);
4180
4181
  await runDoctorCli({
4181
4182
  json: !!options.json || argv.includes("--json"),
@@ -4184,7 +4185,7 @@ program.command("doctor").description("Health check: API keys, config, MCP, rece
4184
4185
  });
4185
4186
  program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
4186
4187
  try {
4187
- const batch = await import("./batch-6YCLYEII.js");
4188
+ const batch = await import("./batch-YFQ34DHW.js");
4188
4189
  switch (action) {
4189
4190
  case "submit":
4190
4191
  if (!arg) {
@@ -4227,7 +4228,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
4227
4228
  }
4228
4229
  });
4229
4230
  program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
4230
- const { startMcpServer } = await import("./server-YNVHKFGZ.js");
4231
+ const { startMcpServer } = await import("./server-WFXEEX2E.js");
4231
4232
  await startMcpServer({
4232
4233
  allowDestructive: !!options.allowDestructive,
4233
4234
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -4240,7 +4241,7 @@ program.command("pr <action> [target]").description("PR review helpers: review |
4240
4241
  console.error(`Unknown pr action: ${action}. Use review | security-review | summarize.`);
4241
4242
  process.exit(1);
4242
4243
  }
4243
- const { runPrCli } = await import("./pr-MVUT6IOA.js");
4244
+ const { runPrCli } = await import("./pr-GTDFMNKY.js");
4244
4245
  const result = await runPrCli({
4245
4246
  action,
4246
4247
  target,
@@ -4260,8 +4261,8 @@ program.command("pr <action> [target]").description("PR review helpers: review |
4260
4261
  process.exit(result.exitCode);
4261
4262
  });
4262
4263
  program.command("ci").description("Headless PR review (code + security) \u2014 reads git/gh diff, optionally posts to PR. Designed for GitHub Actions.").option("--pr <num>", "PR number or URL; diff fetched via gh pr diff <value>", (v) => /^#?\d+$/.test(v) ? parseInt(v.replace(/^#/, ""), 10) : v).option("--base <ref>", "Base ref for git diff <ref>...HEAD (ignored when --pr set)").option("--post", "Post review as a PR comment (requires gh CLI + GH_TOKEN, needs --pr)").option("--no-update", "Always create a new comment instead of updating the previous aicli review").option("--skip-code", "Skip the code review section").option("--skip-security", "Skip the security review section").option("--detailed", "Use the detailed code-review prompt").option("--max-diff <n>", "Max diff chars sent to the model (default 30000)", (v) => parseInt(v, 10)).option("--provider <id>", "Override provider (default: config.defaultProvider)").option("--model <id>", "Override model").option("--dry-run", "Print result to stdout instead of posting (overrides --post)").option("--json", "Output a structured JSON report").option("--markdown", "Output Markdown report (default)").option("--sarif", "Output SARIF 2.1.0 for code scanning artifacts").option("--fail-on-security-high", "Fail when the security review contains HIGH/CRITICAL findings (default)").option("--no-fail-on-security-high", "Do not fail on security HIGH/CRITICAL findings").option("--fail-on-test-failure", "Fail when the report mentions test failures (default)").option("--no-fail-on-test-failure", "Do not fail on test failure findings").option("--fail-on-lint-failure", "Fail when the report mentions lint/typecheck failures (default)").option("--no-fail-on-lint-failure", "Do not fail on lint/typecheck failure findings").action(async (options) => {
4263
- const { runCi } = await import("./ci-SIS77LEG.js");
4264
- const { formatCiResult } = await import("./ci-format-LRMGY4ND.js");
4264
+ const { runCi } = await import("./ci-AR2RLLJD.js");
4265
+ const { formatCiResult } = await import("./ci-format-S7RRDV4A.js");
4265
4266
  const formats = [options.json, options.markdown, options.sarif].filter(Boolean).length;
4266
4267
  if (formats > 1) {
4267
4268
  console.error("Choose only one output format: --json, --markdown, or --sarif.");
@@ -4420,7 +4421,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
4420
4421
  config.get("customProviders"),
4421
4422
  config.getConfigDir()
4422
4423
  );
4423
- const { startHub } = await import("./hub-UWBNCMD4.js");
4424
+ const { startHub } = await import("./hub-LJL3X7KR.js");
4424
4425
  await startHub(
4425
4426
  {
4426
4427
  topic: topic ?? "",
@@ -27,11 +27,11 @@ import {
27
27
  touchMemoryReferences,
28
28
  updateMemoryApproval,
29
29
  updateMemoryEntry
30
- } from "./chunk-P3BJAJ34.js";
30
+ } from "./chunk-LXORMKZ6.js";
31
31
  import "./chunk-FSC6KEWU.js";
32
32
  import "./chunk-6BUTA5VW.js";
33
33
  import "./chunk-CGLYJRFA.js";
34
- import "./chunk-UPJMIP5S.js";
34
+ import "./chunk-D7GLDXPQ.js";
35
35
  export {
36
36
  addMemoryEntry,
37
37
  backupMemoryStore,
@@ -28,11 +28,11 @@ import {
28
28
  touchMemoryReferences,
29
29
  updateMemoryApproval,
30
30
  updateMemoryEntry
31
- } from "./chunk-7KYONZUN.js";
31
+ } from "./chunk-J6CYL6RN.js";
32
32
  import "./chunk-3FEZSLGI.js";
33
33
  import "./chunk-HOSJZMQS.js";
34
34
  import "./chunk-IW3Q7AE5.js";
35
- import "./chunk-CUMSLQKQ.js";
35
+ import "./chunk-6PBWL3XI.js";
36
36
  export {
37
37
  addMemoryEntry,
38
38
  backupMemoryStore,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  countSeverity,
4
4
  runCi
5
- } from "./chunk-HBFES3RR.js";
6
- import "./chunk-3H7TVTAE.js";
5
+ } from "./chunk-CF6RC7OB.js";
6
+ import "./chunk-GNJ3XLS3.js";
7
7
  import {
8
8
  buildReviewPrompt,
9
9
  buildSecurityReviewPrompt,
@@ -14,16 +14,16 @@ import {
14
14
  } from "./chunk-6YZEZFX5.js";
15
15
  import {
16
16
  ProviderRegistry
17
- } from "./chunk-QKZUWT3S.js";
17
+ } from "./chunk-FBOVBL7P.js";
18
18
  import {
19
19
  ConfigManager
20
- } from "./chunk-ZBHRTOWC.js";
20
+ } from "./chunk-O33BYKAD.js";
21
21
  import "./chunk-Y56UGZPX.js";
22
22
  import "./chunk-TU3L3PW7.js";
23
23
  import "./chunk-IW3Q7AE5.js";
24
24
  import {
25
25
  VERSION
26
- } from "./chunk-CUMSLQKQ.js";
26
+ } from "./chunk-6PBWL3XI.js";
27
27
 
28
28
  // src/cli/pr.ts
29
29
  import { execFileSync } from "child_process";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-OMA6DEAR.js";
5
- import "./chunk-UPJMIP5S.js";
4
+ } from "./chunk-NB2V7H5C.js";
5
+ import "./chunk-D7GLDXPQ.js";
6
6
  export {
7
7
  executeTests,
8
8
  runTestsTool
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-MMP6SIB7.js";
6
- import "./chunk-CUMSLQKQ.js";
5
+ } from "./chunk-56AX43FT.js";
6
+ import "./chunk-6PBWL3XI.js";
7
7
  export {
8
8
  executeTests,
9
9
  runTestsTool