jinzd-ai-cli 0.4.316 → 0.4.317

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 (36) hide show
  1. package/dist/{batch-5E7RXEV6.js → batch-OWVPYMTH.js} +2 -2
  2. package/dist/{chunk-WHDKVCCD.js → chunk-27RIJK3U.js} +1 -1
  3. package/dist/{chunk-RXQNA7IG.js → chunk-2Z7SOAPR.js} +40 -5
  4. package/dist/{chunk-O3XKUPD6.js → chunk-6EM2TRG5.js} +1 -1
  5. package/dist/{chunk-CDO4DAP3.js → chunk-DOWBL4OI.js} +1 -1
  6. package/dist/{chunk-CF3ZDEZN.js → chunk-DPWHBIK2.js} +4 -4
  7. package/dist/{chunk-D24MIT4Q.js → chunk-HD7KVZLR.js} +1 -1
  8. package/dist/{chunk-EDVE6PRM.js → chunk-HDHVWGDA.js} +1 -1
  9. package/dist/{chunk-4MLJJJBB.js → chunk-K2TKTYEH.js} +7 -7
  10. package/dist/{chunk-Y6ACJOPX.js → chunk-LZJHXSR3.js} +7 -5
  11. package/dist/{chunk-U2AVVQBH.js → chunk-S73DO2G5.js} +1 -1
  12. package/dist/{chunk-LAJPEEKY.js → chunk-VUZCU6BH.js} +4 -4
  13. package/dist/{chunk-EW6L54LB.js → chunk-VZBBSBSN.js} +1 -1
  14. package/dist/{chunk-WZLANFAT.js → chunk-WJOINCVO.js} +1 -1
  15. package/dist/{chunk-CQARPUDD.js → chunk-X4GNEJNN.js} +1 -1
  16. package/dist/{ci-HVKHR7U6.js → ci-ED4EZGRM.js} +5 -5
  17. package/dist/{ci-format-R2UWFWZR.js → ci-format-2ORFD7KF.js} +2 -2
  18. package/dist/{constants-UAGXITSG.js → constants-N3AHLPRZ.js} +1 -1
  19. package/dist/{constants-QZQ2YE3L.js → constants-QX6K72OV.js} +1 -1
  20. package/dist/{doctor-cli-JFSBHSZG.js → doctor-cli-J6NQF6HS.js} +5 -5
  21. package/dist/electron-server.js +53 -16
  22. package/dist/{hub-J7IHT7RD.js → hub-B6SI42VX.js} +1 -1
  23. package/dist/index.js +18 -18
  24. package/dist/{persistent-memory-2SLKAT4R.js → persistent-memory-5VRVOD76.js} +2 -2
  25. package/dist/{persistent-memory-NZOSS27H.js → persistent-memory-6AEA7G2Q.js} +2 -2
  26. package/dist/{pr-OF6BU56Y.js → pr-D3A76PY6.js} +5 -5
  27. package/dist/{run-tests-3NXLGCLI.js → run-tests-J3N7IM4M.js} +2 -2
  28. package/dist/{run-tests-RQUL5Q5X.js → run-tests-UFL7ZB4U.js} +2 -2
  29. package/dist/{server-H4YA6CKT.js → server-FBIKTICF.js} +5 -5
  30. package/dist/{server-CTQ2UV6C.js → server-NOU4PXEC.js} +14 -14
  31. package/dist/{task-orchestrator-LX3QVW75.js → task-orchestrator-KT6G2WSM.js} +5 -5
  32. package/dist/{usage-SMWGYH6I.js → usage-QV3RTJ7B.js} +2 -2
  33. package/dist/web/client/vendor/purify.es.mjs +2380 -2638
  34. package/dist/web/client/vendor/purify.es.mjs.br +0 -0
  35. package/dist/web/client/vendor/purify.es.mjs.gz +0 -0
  36. package/package.json +4 -4
@@ -4,12 +4,12 @@ import {
4
4
  } from "./chunk-RS7SKYTS.js";
5
5
  import {
6
6
  ConfigManager
7
- } from "./chunk-EW6L54LB.js";
7
+ } from "./chunk-VZBBSBSN.js";
8
8
  import "./chunk-TU3L3PW7.js";
9
9
  import {
10
10
  atomicWriteFileSync
11
11
  } from "./chunk-BMLQPSHP.js";
12
- import "./chunk-CQARPUDD.js";
12
+ import "./chunk-X4GNEJNN.js";
13
13
 
14
14
  // src/cli/batch.ts
15
15
  import Anthropic from "@anthropic-ai/sdk";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-CQARPUDD.js";
4
+ } from "./chunk-X4GNEJNN.js";
5
5
  import {
6
6
  getExecutionConfigDir,
7
7
  getExecutionSignal
@@ -2159,13 +2159,13 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
2159
2159
  if (modelIds.length === 0) {
2160
2160
  return false;
2161
2161
  }
2162
- const contextWindows = await this.detectContextWindows(modelIds);
2162
+ const { contextWindows, thinkingModels } = await this.detectModelDetails(modelIds);
2163
2163
  this.dynamicModels = modelIds.map((id) => ({
2164
2164
  id,
2165
2165
  displayName: id,
2166
2166
  contextWindow: contextWindows.get(id) ?? this.estimateContextWindow(id),
2167
2167
  supportsStreaming: true,
2168
- supportsThinking: false
2168
+ supportsThinking: thinkingModels.has(id)
2169
2169
  }));
2170
2170
  const preferred = ["llama3.1", "llama3", "qwen2.5", "qwen3", "qwen2", "deepseek-r1", "mistral", "gemma2", "gemma3"];
2171
2171
  const defaultModel = this.dynamicModels.find(
@@ -2185,15 +2185,17 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
2185
2185
  }
2186
2186
  }
2187
2187
  /**
2188
- * 经原生 API 查每个模型的 contextWindow(规则见 resolveOllamaContextWindow)。
2188
+ * 经原生 API 查每个模型的 contextWindow(规则见 resolveOllamaContextWindow)与是否会思考。
2189
2189
  * 任何一步失败都只影响该模型、退回按名字猜,绝不让模型列表整体失败——
2190
2190
  * 模型列表拿到了就说明服务是通的,上下文探测只是锦上添花。
2191
2191
  */
2192
- async detectContextWindows(modelIds) {
2192
+ async detectModelDetails(modelIds) {
2193
2193
  const result = /* @__PURE__ */ new Map();
2194
+ const thinkingModels = /* @__PURE__ */ new Set();
2194
2195
  const [running, digests] = await Promise.all([this.fetchRunningContexts(), this.fetchDigests()]);
2195
2196
  await Promise.all(modelIds.map(async (id) => {
2196
2197
  const show = await this.fetchNative("/api/show", { model: id });
2198
+ if (show?.capabilities?.includes("thinking")) thinkingModels.add(id);
2197
2199
  if (running.size === 0 && !show) return;
2198
2200
  const digest = digests.get(id);
2199
2201
  const { contextWindow } = resolveOllamaContextWindow({
@@ -2203,7 +2205,7 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
2203
2205
  });
2204
2206
  result.set(id, contextWindow);
2205
2207
  }));
2206
- return result;
2208
+ return { contextWindows: result, thinkingModels };
2207
2209
  }
2208
2210
  /** `/api/ps`:已加载模型的名字与 digest → 实际上下文窗口。未加载的模型不在其中。 */
2209
2211
  async fetchRunningContexts() {
@@ -2264,6 +2266,39 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
2264
2266
  if (name.includes("codellama") || name.includes("code-llama")) return 16384;
2265
2267
  return 8192;
2266
2268
  }
2269
+ /**
2270
+ * 思考开关:未开启思考时对会思考的模型显式发 `reasoning_effort: 'none'`。
2271
+ *
2272
+ * 会思考的模型(qwen3.x 等)在 Ollama 上**默认开着思考**,而 aicli 此前对 Ollama 什么都不发,
2273
+ * `/think off` 与 `modelParams.thinking=false` 都传不到。实战(2026-10,本地 qwen27b,64K 上下文):
2274
+ * 排一份月度课表,8192 的输出预算全被思考吃光、正文为空(finish_reason=length),
2275
+ * 本地 27B 每秒十几个 token,一次就白等好几分钟。默认关与 DeepSeek 同一口径(v0.4.265):
2276
+ * 未配置 = 关,要思考用 `/think on`。
2277
+ *
2278
+ * 本机 Ollama 0.34.3 实测 `/v1/chat/completions`:
2279
+ * - `reasoning_effort: 'none'` → 思考 0 token,工具调用与流式照常;`none` 由 Ollama 自己
2280
+ * 转成 think=false,与模型模板无关;
2281
+ * - `think: false` 在 `/v1` 上被**忽略**(仍有思考输出)——那是原生 `/api/chat` 的字段;
2282
+ * - 其余档位由**各模型的聊天模板**定义:Qwen3.8 发 `max` 直接 500
2283
+ * (模板只认 xhigh/medium/low)。档位表随模型而变,所以这里**只做开关、不转发档位**,
2284
+ * `supportsReasoningEffort` 保持 false(`/think low|high|max` 只是打开思考)。
2285
+ *
2286
+ * 只对 `/api/show` 的 capabilities 里声明了 `thinking` 的模型发:不会思考的模型、
2287
+ * 或老版本 Ollama 拿不到 capabilities 时一律不发——拿不准就别发。
2288
+ */
2289
+ buildChatRequestParams(request) {
2290
+ const params = super.buildChatRequestParams(request);
2291
+ if (request.thinking !== true && this.isThinkingModel(request.model)) {
2292
+ params.reasoning_effort = "none";
2293
+ }
2294
+ return params;
2295
+ }
2296
+ /** `qwen27b` 与 `qwen27b:latest` 是同一个模型,两种写法都要认 */
2297
+ isThinkingModel(model) {
2298
+ const norm = (id) => id.replace(/:latest$/, "");
2299
+ const target = norm(model);
2300
+ return this.dynamicModels.some((m) => m.supportsThinking === true && norm(m.id) === target);
2301
+ }
2267
2302
  /** 实时刷新模型列表 */
2268
2303
  async listModels() {
2269
2304
  await this.tryConnect();
@@ -12,7 +12,7 @@ import {
12
12
  MEMORY_FILE_NAME,
13
13
  MEMORY_MAX_CHARS,
14
14
  MEMORY_STORE_FILE_NAME
15
- } from "./chunk-CDO4DAP3.js";
15
+ } from "./chunk-DOWBL4OI.js";
16
16
 
17
17
  // src/memory/persistent-memory.ts
18
18
  import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.316";
2
+ var VERSION = "0.4.317";
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-EDVE6PRM.js";
11
+ } from "./chunk-HDHVWGDA.js";
12
12
  import {
13
13
  ProviderRegistry
14
- } from "./chunk-RXQNA7IG.js";
14
+ } from "./chunk-2Z7SOAPR.js";
15
15
  import {
16
16
  ConfigManager
17
- } from "./chunk-EW6L54LB.js";
17
+ } from "./chunk-VZBBSBSN.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-CQARPUDD.js";
29
+ } from "./chunk-X4GNEJNN.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-CQARPUDD.js";
4
+ } from "./chunk-X4GNEJNN.js";
5
5
 
6
6
  // src/cli/ci-format.ts
7
7
  var DEFAULT_CI_THRESHOLDS = {
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  CONFIG_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-CQARPUDD.js";
11
+ } from "./chunk-X4GNEJNN.js";
12
12
 
13
13
  // src/diagnostics/tool-stats.ts
14
14
  import { mkdirSync } from "fs";
@@ -16,7 +16,7 @@ import {
16
16
  setPreferredAgentName,
17
17
  truncateForPersist,
18
18
  undoStack
19
- } from "./chunk-Y6ACJOPX.js";
19
+ } from "./chunk-LZJHXSR3.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-U2AVVQBH.js";
54
+ } from "./chunk-S73DO2G5.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-CF3ZDEZN.js";
68
+ } from "./chunk-DPWHBIK2.js";
69
69
  import {
70
70
  describePlugin,
71
71
  getActivePluginAssets,
@@ -80,7 +80,7 @@ import {
80
80
  trustHook,
81
81
  trustPlugin,
82
82
  untrustHook
83
- } from "./chunk-EDVE6PRM.js";
83
+ } from "./chunk-HDHVWGDA.js";
84
84
  import {
85
85
  isCleanDocumentBody,
86
86
  stripOuterCodeFence
@@ -109,7 +109,7 @@ import {
109
109
  MCP_TOOL_PREFIX,
110
110
  REPO_URL,
111
111
  VERSION
112
- } from "./chunk-CQARPUDD.js";
112
+ } from "./chunk-X4GNEJNN.js";
113
113
 
114
114
  // src/skills/manager.ts
115
115
  import { existsSync, readdirSync, mkdirSync, statSync } from "fs";
@@ -2426,7 +2426,7 @@ No tools match "${filter}".
2426
2426
  const { join: join6 } = await import("path");
2427
2427
  const { existsSync: existsSync6 } = await import("fs");
2428
2428
  const { getGitRoot } = await import("./git-context-EXOEHQSF.js");
2429
- const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-QZQ2YE3L.js");
2429
+ const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-QX6K72OV.js");
2430
2430
  const { approveProject, hashMcpFile } = await import("./project-trust-KGG2BWKC.js");
2431
2431
  const cwd = process.cwd();
2432
2432
  const projectRoot = getGitRoot(cwd) ?? cwd;
@@ -3534,7 +3534,7 @@ function createReviewCommands() {
3534
3534
  usage: "/test [command|filter]",
3535
3535
  async execute(args, ctx) {
3536
3536
  try {
3537
- const { executeTests } = await import("./run-tests-3NXLGCLI.js");
3537
+ const { executeTests } = await import("./run-tests-J3N7IM4M.js");
3538
3538
  const argStr = args.join(" ").trim();
3539
3539
  let testArgs = {};
3540
3540
  if (argStr) {
@@ -11,7 +11,7 @@ import {
11
11
  searchPersistentMemories,
12
12
  touchMemoryReferences,
13
13
  updateMemoryEntry
14
- } from "./chunk-U2AVVQBH.js";
14
+ } from "./chunk-S73DO2G5.js";
15
15
  import {
16
16
  indexProject
17
17
  } from "./chunk-RWRZVQCB.js";
@@ -30,7 +30,7 @@ import {
30
30
  runHook,
31
31
  runLifecycleHooks,
32
32
  runTool
33
- } from "./chunk-EDVE6PRM.js";
33
+ } from "./chunk-HDHVWGDA.js";
34
34
  import {
35
35
  buildTruncatedArgumentsError,
36
36
  getDangerLevel,
@@ -63,7 +63,7 @@ import {
63
63
  recoverGbkMojibake,
64
64
  runTestsTool,
65
65
  shellInvocation
66
- } from "./chunk-WHDKVCCD.js";
66
+ } from "./chunk-27RIJK3U.js";
67
67
  import {
68
68
  CONFIG_DIR_NAME,
69
69
  DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
@@ -72,7 +72,7 @@ import {
72
72
  SUBAGENT_ALLOWED_TOOLS,
73
73
  SUBAGENT_DEFAULT_MAX_ROUNDS,
74
74
  SUBAGENT_MAX_ROUNDS_LIMIT
75
- } from "./chunk-CQARPUDD.js";
75
+ } from "./chunk-X4GNEJNN.js";
76
76
  import {
77
77
  getCurrentSessionKey,
78
78
  getExecutionConfigDir,
@@ -124,7 +124,9 @@ function buildWrappedCommand(command, id, isWindows) {
124
124
  const markerStart = `AICLI_MARKER_START:${id}`;
125
125
  const markerEnd = `AICLI_MARKER_END:${id}`;
126
126
  if (!isWindows) {
127
- return `echo "${markerStart}"; ${command}; echo "${markerEnd}:$?"`;
127
+ return `echo "${markerStart}"
128
+ ${command}
129
+ echo "${markerEnd}:$?"`;
128
130
  }
129
131
  const b64 = Buffer.from(command, "utf-8").toString("base64");
130
132
  const decoded = `[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${b64}'))`;
@@ -13,7 +13,7 @@ import {
13
13
  MEMORY_FILE_NAME,
14
14
  MEMORY_MAX_CHARS,
15
15
  MEMORY_STORE_FILE_NAME
16
- } from "./chunk-CQARPUDD.js";
16
+ } from "./chunk-X4GNEJNN.js";
17
17
 
18
18
  // src/memory/persistent-memory.ts
19
19
  import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  evaluateCiGate,
4
4
  normalizeCiThresholds
5
- } from "./chunk-D24MIT4Q.js";
5
+ } from "./chunk-HD7KVZLR.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-RXQNA7IG.js";
16
+ } from "./chunk-2Z7SOAPR.js";
17
17
  import {
18
18
  ConfigManager
19
- } from "./chunk-EW6L54LB.js";
19
+ } from "./chunk-VZBBSBSN.js";
20
20
  import {
21
21
  VERSION
22
- } from "./chunk-CQARPUDD.js";
22
+ } from "./chunk-X4GNEJNN.js";
23
23
 
24
24
  // src/cli/ci.ts
25
25
  import { execFileSync } from "child_process";
@@ -11,7 +11,7 @@ import {
11
11
  CONFIG_FILE_NAME,
12
12
  HISTORY_DIR_NAME,
13
13
  PLUGINS_DIR_NAME
14
- } from "./chunk-CQARPUDD.js";
14
+ } from "./chunk-X4GNEJNN.js";
15
15
 
16
16
  // src/config/config-manager.ts
17
17
  import { readFileSync, existsSync, mkdirSync } from "fs";
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-QMFMST2T.js";
5
5
  import {
6
6
  TEST_TIMEOUT
7
- } from "./chunk-CDO4DAP3.js";
7
+ } from "./chunk-DOWBL4OI.js";
8
8
 
9
9
  // src/tools/builtin/run-tests.ts
10
10
  import { spawn as spawn2 } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.316";
4
+ var VERSION = "0.4.317";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -3,16 +3,16 @@ import {
3
3
  CI_COMMENT_MARKER,
4
4
  countSeverity,
5
5
  runCi
6
- } from "./chunk-LAJPEEKY.js";
7
- import "./chunk-D24MIT4Q.js";
6
+ } from "./chunk-VUZCU6BH.js";
7
+ import "./chunk-HD7KVZLR.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
9
  import "./chunk-6YZEZFX5.js";
10
- import "./chunk-RXQNA7IG.js";
11
- import "./chunk-EW6L54LB.js";
10
+ import "./chunk-2Z7SOAPR.js";
11
+ import "./chunk-VZBBSBSN.js";
12
12
  import "./chunk-6VBW3L57.js";
13
13
  import "./chunk-TU3L3PW7.js";
14
14
  import "./chunk-BMLQPSHP.js";
15
- import "./chunk-CQARPUDD.js";
15
+ import "./chunk-X4GNEJNN.js";
16
16
  export {
17
17
  CI_COMMENT_MARKER,
18
18
  countSeverity,
@@ -6,8 +6,8 @@ import {
6
6
  formatCiResult,
7
7
  formatCiSarif,
8
8
  normalizeCiThresholds
9
- } from "./chunk-D24MIT4Q.js";
10
- import "./chunk-CQARPUDD.js";
9
+ } from "./chunk-HD7KVZLR.js";
10
+ import "./chunk-X4GNEJNN.js";
11
11
  export {
12
12
  DEFAULT_CI_THRESHOLDS,
13
13
  detectCiGateSignals,
@@ -38,7 +38,7 @@ import {
38
38
  TEST_TIMEOUT,
39
39
  VERSION,
40
40
  buildUserIdentityPrompt
41
- } from "./chunk-CDO4DAP3.js";
41
+ } from "./chunk-DOWBL4OI.js";
42
42
  export {
43
43
  AGENTIC_BEHAVIOR_GUIDELINE,
44
44
  APP_NAME,
@@ -39,7 +39,7 @@ import {
39
39
  TEST_TIMEOUT,
40
40
  VERSION,
41
41
  buildUserIdentityPrompt
42
- } from "./chunk-CQARPUDD.js";
42
+ } from "./chunk-X4GNEJNN.js";
43
43
  export {
44
44
  AGENTIC_BEHAVIOR_GUIDELINE,
45
45
  APP_NAME,
@@ -2,16 +2,16 @@
2
2
  import {
3
3
  formatDoctorReport,
4
4
  runDoctorCli
5
- } from "./chunk-CF3ZDEZN.js";
6
- import "./chunk-EDVE6PRM.js";
5
+ } from "./chunk-DPWHBIK2.js";
6
+ import "./chunk-HDHVWGDA.js";
7
7
  import "./chunk-RS7SKYTS.js";
8
- import "./chunk-RXQNA7IG.js";
9
- import "./chunk-EW6L54LB.js";
8
+ import "./chunk-2Z7SOAPR.js";
9
+ import "./chunk-VZBBSBSN.js";
10
10
  import "./chunk-6VBW3L57.js";
11
11
  import "./chunk-TU3L3PW7.js";
12
12
  import "./chunk-HOSJZMQS.js";
13
13
  import "./chunk-BMLQPSHP.js";
14
- import "./chunk-CQARPUDD.js";
14
+ import "./chunk-X4GNEJNN.js";
15
15
  export {
16
16
  formatDoctorReport,
17
17
  runDoctorCli
@@ -55,7 +55,7 @@ import {
55
55
  touchMemoryReferences,
56
56
  updateMemoryApproval,
57
57
  updateMemoryEntry
58
- } from "./chunk-O3XKUPD6.js";
58
+ } from "./chunk-6EM2TRG5.js";
59
59
  import {
60
60
  DEFAULT_PATTERNS,
61
61
  redactJson,
@@ -80,7 +80,7 @@ import {
80
80
  recoverGbkMojibake,
81
81
  runTestsTool,
82
82
  shellInvocation
83
- } from "./chunk-WZLANFAT.js";
83
+ } from "./chunk-WJOINCVO.js";
84
84
  import {
85
85
  getCurrentSessionKey,
86
86
  getExecutionConfigDir,
@@ -122,7 +122,7 @@ import {
122
122
  SUBAGENT_MAX_ROUNDS_LIMIT,
123
123
  VERSION,
124
124
  buildUserIdentityPrompt
125
- } from "./chunk-CDO4DAP3.js";
125
+ } from "./chunk-DOWBL4OI.js";
126
126
 
127
127
  // src/web/access.ts
128
128
  import { randomBytes, timingSafeEqual } from "crypto";
@@ -4743,13 +4743,13 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
4743
4743
  if (modelIds.length === 0) {
4744
4744
  return false;
4745
4745
  }
4746
- const contextWindows = await this.detectContextWindows(modelIds);
4746
+ const { contextWindows, thinkingModels } = await this.detectModelDetails(modelIds);
4747
4747
  this.dynamicModels = modelIds.map((id) => ({
4748
4748
  id,
4749
4749
  displayName: id,
4750
4750
  contextWindow: contextWindows.get(id) ?? this.estimateContextWindow(id),
4751
4751
  supportsStreaming: true,
4752
- supportsThinking: false
4752
+ supportsThinking: thinkingModels.has(id)
4753
4753
  }));
4754
4754
  const preferred = ["llama3.1", "llama3", "qwen2.5", "qwen3", "qwen2", "deepseek-r1", "mistral", "gemma2", "gemma3"];
4755
4755
  const defaultModel = this.dynamicModels.find(
@@ -4769,15 +4769,17 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
4769
4769
  }
4770
4770
  }
4771
4771
  /**
4772
- * 经原生 API 查每个模型的 contextWindow(规则见 resolveOllamaContextWindow)。
4772
+ * 经原生 API 查每个模型的 contextWindow(规则见 resolveOllamaContextWindow)与是否会思考。
4773
4773
  * 任何一步失败都只影响该模型、退回按名字猜,绝不让模型列表整体失败——
4774
4774
  * 模型列表拿到了就说明服务是通的,上下文探测只是锦上添花。
4775
4775
  */
4776
- async detectContextWindows(modelIds) {
4776
+ async detectModelDetails(modelIds) {
4777
4777
  const result = /* @__PURE__ */ new Map();
4778
+ const thinkingModels = /* @__PURE__ */ new Set();
4778
4779
  const [running, digests] = await Promise.all([this.fetchRunningContexts(), this.fetchDigests()]);
4779
4780
  await Promise.all(modelIds.map(async (id) => {
4780
4781
  const show = await this.fetchNative("/api/show", { model: id });
4782
+ if (show?.capabilities?.includes("thinking")) thinkingModels.add(id);
4781
4783
  if (running.size === 0 && !show) return;
4782
4784
  const digest = digests.get(id);
4783
4785
  const { contextWindow } = resolveOllamaContextWindow({
@@ -4787,7 +4789,7 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
4787
4789
  });
4788
4790
  result.set(id, contextWindow);
4789
4791
  }));
4790
- return result;
4792
+ return { contextWindows: result, thinkingModels };
4791
4793
  }
4792
4794
  /** `/api/ps`:已加载模型的名字与 digest → 实际上下文窗口。未加载的模型不在其中。 */
4793
4795
  async fetchRunningContexts() {
@@ -4848,6 +4850,39 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
4848
4850
  if (name.includes("codellama") || name.includes("code-llama")) return 16384;
4849
4851
  return 8192;
4850
4852
  }
4853
+ /**
4854
+ * 思考开关:未开启思考时对会思考的模型显式发 `reasoning_effort: 'none'`。
4855
+ *
4856
+ * 会思考的模型(qwen3.x 等)在 Ollama 上**默认开着思考**,而 aicli 此前对 Ollama 什么都不发,
4857
+ * `/think off` 与 `modelParams.thinking=false` 都传不到。实战(2026-10,本地 qwen27b,64K 上下文):
4858
+ * 排一份月度课表,8192 的输出预算全被思考吃光、正文为空(finish_reason=length),
4859
+ * 本地 27B 每秒十几个 token,一次就白等好几分钟。默认关与 DeepSeek 同一口径(v0.4.265):
4860
+ * 未配置 = 关,要思考用 `/think on`。
4861
+ *
4862
+ * 本机 Ollama 0.34.3 实测 `/v1/chat/completions`:
4863
+ * - `reasoning_effort: 'none'` → 思考 0 token,工具调用与流式照常;`none` 由 Ollama 自己
4864
+ * 转成 think=false,与模型模板无关;
4865
+ * - `think: false` 在 `/v1` 上被**忽略**(仍有思考输出)——那是原生 `/api/chat` 的字段;
4866
+ * - 其余档位由**各模型的聊天模板**定义:Qwen3.8 发 `max` 直接 500
4867
+ * (模板只认 xhigh/medium/low)。档位表随模型而变,所以这里**只做开关、不转发档位**,
4868
+ * `supportsReasoningEffort` 保持 false(`/think low|high|max` 只是打开思考)。
4869
+ *
4870
+ * 只对 `/api/show` 的 capabilities 里声明了 `thinking` 的模型发:不会思考的模型、
4871
+ * 或老版本 Ollama 拿不到 capabilities 时一律不发——拿不准就别发。
4872
+ */
4873
+ buildChatRequestParams(request) {
4874
+ const params = super.buildChatRequestParams(request);
4875
+ if (request.thinking !== true && this.isThinkingModel(request.model)) {
4876
+ params.reasoning_effort = "none";
4877
+ }
4878
+ return params;
4879
+ }
4880
+ /** `qwen27b` 与 `qwen27b:latest` 是同一个模型,两种写法都要认 */
4881
+ isThinkingModel(model) {
4882
+ const norm2 = (id) => id.replace(/:latest$/, "");
4883
+ const target = norm2(model);
4884
+ return this.dynamicModels.some((m) => m.supportsThinking === true && norm2(m.id) === target);
4885
+ }
4851
4886
  /** 实时刷新模型列表 */
4852
4887
  async listModels() {
4853
4888
  await this.tryConnect();
@@ -6089,7 +6124,9 @@ function buildWrappedCommand(command, id, isWindows) {
6089
6124
  const markerStart = `AICLI_MARKER_START:${id}`;
6090
6125
  const markerEnd = `AICLI_MARKER_END:${id}`;
6091
6126
  if (!isWindows) {
6092
- return `echo "${markerStart}"; ${command}; echo "${markerEnd}:$?"`;
6127
+ return `echo "${markerStart}"
6128
+ ${command}
6129
+ echo "${markerEnd}:$?"`;
6093
6130
  }
6094
6131
  const b64 = Buffer.from(command, "utf-8").toString("base64");
6095
6132
  const decoded = `[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${b64}'))`;
@@ -17453,7 +17490,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
17453
17490
  Cost: ${formatCost(cost)}` : "";
17454
17491
  let memoryLine = "";
17455
17492
  try {
17456
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-NZOSS27H.js");
17493
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-6AEA7G2Q.js");
17457
17494
  const pending = countPendingMemories2(ctx.config.getConfigDir());
17458
17495
  if (pending > 0) memoryLine = `
17459
17496
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -18441,7 +18478,7 @@ async function handleTest(args, ctx) {
18441
18478
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
18442
18479
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
18443
18480
  }
18444
- const runTests = ctx.runTests ?? (await import("./run-tests-RQUL5Q5X.js")).executeTests;
18481
+ const runTests = ctx.runTests ?? (await import("./run-tests-UFL7ZB4U.js")).executeTests;
18445
18482
  const report = await runTests(testArgs);
18446
18483
  ctx.send({ type: "info", message: report });
18447
18484
  } catch (err) {
@@ -18832,7 +18869,7 @@ async function handleMemory(args, ctx) {
18832
18869
  }
18833
18870
  if (intent.kind === "status") {
18834
18871
  const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-RLVLQRRC.js");
18835
- const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-NZOSS27H.js");
18872
+ const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-6AEA7G2Q.js");
18836
18873
  const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
18837
18874
  const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
18838
18875
  const view = buildMemoryStatusView({
@@ -18855,7 +18892,7 @@ async function handleMemory(args, ctx) {
18855
18892
  return;
18856
18893
  }
18857
18894
  if (intent.kind === "recall") {
18858
- const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-NZOSS27H.js");
18895
+ const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-6AEA7G2Q.js");
18859
18896
  const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-RLVLQRRC.js");
18860
18897
  const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
18861
18898
  if (persistentHits.length > 0) {
@@ -18976,7 +19013,7 @@ async function handleMemory(args, ctx) {
18976
19013
  ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
18977
19014
  } else if (intent.kind === "export") {
18978
19015
  if (args[1] === "md") {
18979
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-NZOSS27H.js");
19016
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-6AEA7G2Q.js");
18980
19017
  ctx.send({
18981
19018
  type: "export_data",
18982
19019
  format: "md",
@@ -19981,7 +20018,7 @@ No tools match "${filter}".
19981
20018
  const { join: join26 } = await import("path");
19982
20019
  const { existsSync: existsSync32 } = await import("fs");
19983
20020
  const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
19984
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-UAGXITSG.js");
20021
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-N3AHLPRZ.js");
19985
20022
  const { approveProject, hashMcpFile } = await import("./project-trust-6CJB5ZMX.js");
19986
20023
  const cwd = process.cwd();
19987
20024
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -20900,7 +20937,7 @@ function createReviewCommands() {
20900
20937
  usage: "/test [command|filter]",
20901
20938
  async execute(args, ctx) {
20902
20939
  try {
20903
- const { executeTests } = await import("./run-tests-RQUL5Q5X.js");
20940
+ const { executeTests } = await import("./run-tests-UFL7ZB4U.js");
20904
20941
  const argStr = args.join(" ").trim();
20905
20942
  let testArgs = {};
20906
20943
  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-LX3QVW75.js");
161
+ const { TaskOrchestrator } = await import("./task-orchestrator-KT6G2WSM.js");
162
162
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
163
163
  let interrupted = false;
164
164
  const onSigint = () => {