jinzd-ai-cli 0.4.259 → 0.4.261

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 (33) hide show
  1. package/dist/{batch-74P2FQWX.js → batch-YUPAC4CK.js} +2 -2
  2. package/dist/{chunk-4TDVLTX2.js → chunk-323S2X5I.js} +1 -1
  3. package/dist/{chunk-PSH5O44I.js → chunk-GC4KA5LF.js} +1 -1
  4. package/dist/{chunk-G65I4DXP.js → chunk-H6FND2UG.js} +1 -1
  5. package/dist/{chunk-FGONEVTP.js → chunk-HGTDI5ME.js} +1 -1
  6. package/dist/{chunk-4RPJQJBI.js → chunk-HU3IYBU5.js} +11 -9
  7. package/dist/{chunk-V5FB72RK.js → chunk-KFNQESEG.js} +1 -1
  8. package/dist/{chunk-BWJYDG3C.js → chunk-KQQHMGK7.js} +1 -1
  9. package/dist/{chunk-ZZ5WTHKY.js → chunk-NOB2OPQI.js} +4 -4
  10. package/dist/{chunk-GDJII6TK.js → chunk-OIOTHBDB.js} +23 -5
  11. package/dist/{chunk-DLOOIAAD.js → chunk-R6DXWVVN.js} +1 -1
  12. package/dist/{chunk-KXAVUZKH.js → chunk-T7R7ILYT.js} +1 -1
  13. package/dist/{chunk-3KYUE2MD.js → chunk-W5XUZYQE.js} +1 -1
  14. package/dist/{chunk-XPNKMDBH.js → chunk-XZNRZGG2.js} +63 -26
  15. package/dist/{chunk-7DVIAK6J.js → chunk-YXMBP567.js} +2 -2
  16. package/dist/{chunk-3EWST6SE.js → chunk-Z5TCAE4L.js} +4 -4
  17. package/dist/{ci-6BANR65W.js → ci-FX26BNT2.js} +6 -6
  18. package/dist/{ci-format-2OVEQK6O.js → ci-format-GEWIAIZD.js} +2 -2
  19. package/dist/{constants-DKZEF3CE.js → constants-YN4B6C7B.js} +1 -1
  20. package/dist/{doctor-cli-6MHA7Q7M.js → doctor-cli-PXGXZYQB.js} +6 -6
  21. package/dist/electron-server.js +96 -40
  22. package/dist/{hub-L7RSDS4J.js → hub-RCANK6SK.js} +1 -1
  23. package/dist/index.js +145 -65
  24. package/dist/{persistent-memory-I4JV3CME.js → persistent-memory-P3COUZZM.js} +2 -2
  25. package/dist/{persistent-memory-WBR2DALU.js → persistent-memory-UARSSYAA.js} +2 -2
  26. package/dist/{pr-UNCWDVN3.js → pr-7LQTAUFK.js} +6 -6
  27. package/dist/{run-tests-HFT5RUXF.js → run-tests-7RYU4BK5.js} +2 -2
  28. package/dist/{run-tests-XBODGDFO.js → run-tests-YNHESHYY.js} +2 -2
  29. package/dist/{server-ILKG2672.js → server-SSAWGNT7.js} +13 -13
  30. package/dist/{server-RNBKZ6TP.js → server-YZ37TL46.js} +6 -6
  31. package/dist/{task-orchestrator-GXP5HNBZ.js → task-orchestrator-ZFL4E6NZ.js} +6 -6
  32. package/dist/{usage-KCPH75KI.js → usage-PDKM7J75.js} +2 -2
  33. package/package.json +1 -1
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager
4
- } from "./chunk-G65I4DXP.js";
4
+ } from "./chunk-H6FND2UG.js";
5
5
  import "./chunk-TU3L3PW7.js";
6
- import "./chunk-4TDVLTX2.js";
6
+ import "./chunk-323S2X5I.js";
7
7
  import {
8
8
  atomicWriteFileSync
9
9
  } from "./chunk-IW3Q7AE5.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.259";
4
+ var VERSION = "0.4.261";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-4TDVLTX2.js";
4
+ } from "./chunk-323S2X5I.js";
5
5
 
6
6
  // src/cli/ci-format.ts
7
7
  var DEFAULT_CI_THRESHOLDS = {
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-4TDVLTX2.js";
11
+ } from "./chunk-323S2X5I.js";
12
12
  import {
13
13
  atomicWriteFileSync
14
14
  } from "./chunk-IW3Q7AE5.js";
@@ -6,7 +6,7 @@ import {
6
6
  MEMORY_FILE_NAME,
7
7
  MEMORY_MAX_CHARS,
8
8
  MEMORY_STORE_FILE_NAME
9
- } from "./chunk-4TDVLTX2.js";
9
+ } from "./chunk-323S2X5I.js";
10
10
  import {
11
11
  DEFAULT_PATTERNS,
12
12
  redactString
@@ -7,7 +7,7 @@ import {
7
7
  searchPersistentMemories,
8
8
  touchMemoryReferences,
9
9
  updateMemoryEntry
10
- } from "./chunk-FGONEVTP.js";
10
+ } from "./chunk-HGTDI5ME.js";
11
11
  import {
12
12
  indexProject
13
13
  } from "./chunk-GLSR2NR3.js";
@@ -23,13 +23,13 @@ import {
23
23
  runHook,
24
24
  runLifecycleHooks,
25
25
  runTool
26
- } from "./chunk-3KYUE2MD.js";
26
+ } from "./chunk-W5XUZYQE.js";
27
27
  import {
28
28
  buildTruncatedArgumentsError,
29
29
  getDangerLevel,
30
30
  isFileWriteTool,
31
31
  runLeanAgentLoop
32
- } from "./chunk-XPNKMDBH.js";
32
+ } from "./chunk-XZNRZGG2.js";
33
33
  import {
34
34
  EnvLoader,
35
35
  NetworkError,
@@ -40,14 +40,14 @@ import {
40
40
  } from "./chunk-4BKXL7SM.js";
41
41
  import {
42
42
  runTestsTool
43
- } from "./chunk-BWJYDG3C.js";
43
+ } from "./chunk-KQQHMGK7.js";
44
44
  import {
45
45
  CONFIG_DIR_NAME,
46
46
  DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
47
47
  SUBAGENT_ALLOWED_TOOLS,
48
48
  SUBAGENT_DEFAULT_MAX_ROUNDS,
49
49
  SUBAGENT_MAX_ROUNDS_LIMIT
50
- } from "./chunk-4TDVLTX2.js";
50
+ } from "./chunk-323S2X5I.js";
51
51
  import {
52
52
  loadChatIndex,
53
53
  searchChatMemory
@@ -169,9 +169,9 @@ function buildWrappedCommand(command, id, isWindows) {
169
169
  if (!isWindows) {
170
170
  return `echo "${markerStart}"; ${command}; echo "${markerEnd}:$?"`;
171
171
  }
172
- const inner = `${WIN_UTF8_PREAMBLE} Write-Output "${markerStart}"; ${command}; $__ok = $?; $__ec = $LASTEXITCODE; $__code = if ($__ok) { 0 } elseif ($null -ne $__ec -and $__ec -ne 0) { $__ec } else { 1 }; Write-Output "${markerEnd}:$__code"`;
173
- const b64 = Buffer.from(inner, "utf-8").toString("base64");
174
- return `Invoke-Expression ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${b64}')))`;
172
+ const b64 = Buffer.from(command, "utf-8").toString("base64");
173
+ const decoded = `[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${b64}'))`;
174
+ return `${WIN_UTF8_PREAMBLE} Write-Output "${markerStart}"; $global:LASTEXITCODE = 0; Invoke-Expression (${decoded}); $__ok = $?; $__ec = $LASTEXITCODE; $__code = if ($null -ne $__ec -and $__ec -ne 0) { $__ec } elseif ($__ok) { 0 } else { 1 }; Write-Output "${markerEnd}:$__code"`;
175
175
  }
176
176
  async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
177
177
  let entry = pool.get(sessionKey);
@@ -3477,7 +3477,9 @@ Note: Path can be absolute or relative to cwd.`,
3477
3477
  }
3478
3478
  const lines = [];
3479
3479
  if (anyFailed && stopOnError) {
3480
- lines.push(`ERROR: Batch edit aborted \u2014 ${appliedCount}/${edits.length} applied, then edit #${appliedCount} failed. No changes written (stop_on_error=true).`);
3480
+ const failedIdx = reports.find((r) => !r.ok)?.index;
3481
+ const failedLabel = failedIdx != null ? `#${failedIdx + 1}` : "an edit";
3482
+ lines.push(`ERROR: Batch edit aborted \u2014 ${appliedCount}/${edits.length} applied, then edit ${failedLabel} failed. No changes written (stop_on_error=true).`);
3481
3483
  } else if (anyFailed) {
3482
3484
  lines.push(`Partial success: ${appliedCount}/${edits.length} edits applied to ${filePath} (stop_on_error=false).`);
3483
3485
  } else {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TEST_TIMEOUT
3
- } from "./chunk-DLOOIAAD.js";
3
+ } from "./chunk-R6DXWVVN.js";
4
4
 
5
5
  // src/tools/builtin/run-tests.ts
6
6
  import { execSync, spawnSync } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-4TDVLTX2.js";
4
+ } from "./chunk-323S2X5I.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ProviderRegistry
4
- } from "./chunk-GDJII6TK.js";
4
+ } from "./chunk-OIOTHBDB.js";
5
5
  import {
6
6
  ConfigManager
7
- } from "./chunk-G65I4DXP.js";
7
+ } from "./chunk-H6FND2UG.js";
8
8
  import {
9
9
  getActivePluginAssets,
10
10
  getPendingHookTrust,
@@ -14,7 +14,7 @@ import {
14
14
  listHooks,
15
15
  listInstalledPlugins,
16
16
  resetStats
17
- } from "./chunk-3KYUE2MD.js";
17
+ } from "./chunk-W5XUZYQE.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-4TDVLTX2.js";
29
+ } from "./chunk-323S2X5I.js";
30
30
 
31
31
  // src/diagnostics/doctor-report.ts
32
32
  import { existsSync as existsSync3, statSync as statSync2 } from "fs";
@@ -3,7 +3,7 @@ import {
3
3
  detectsHallucinatedFileOp,
4
4
  parseToolCallArguments,
5
5
  schemaToJsonSchema
6
- } from "./chunk-XPNKMDBH.js";
6
+ } from "./chunk-XZNRZGG2.js";
7
7
  import {
8
8
  AuthError,
9
9
  ProviderError,
@@ -230,7 +230,8 @@ var ClaudeProvider = class extends BaseProvider {
230
230
  max_tokens: request.maxTokens ?? 8192,
231
231
  temperature,
232
232
  thinking
233
- });
233
+ // 非流式路径必须收 signal,否则 Ctrl+C 期间请求不可中断(同 openai-compatible 的同类遗漏)
234
+ }, { signal: request.signal });
234
235
  const content = this.extractContent(response.content);
235
236
  return {
236
237
  content,
@@ -309,7 +310,8 @@ var ClaudeProvider = class extends BaseProvider {
309
310
  max_tokens: request.maxTokens ?? 8192,
310
311
  temperature,
311
312
  thinking
312
- });
313
+ // 轮次耗尽的总结轮对所有 provider 都走这条非流式路径——漏 signal 则 Ctrl+C 无效
314
+ }, { signal: request.signal });
313
315
  const usage = this.extractUsage(response.usage);
314
316
  const toolUseBlocks = response.content.filter(
315
317
  (b) => b.type === "tool_use"
@@ -1077,6 +1079,17 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1077
1079
  }
1078
1080
  return msgs;
1079
1081
  }
1082
+ /**
1083
+ * 非流式请求必须把 `request.signal` 交给 SDK —— 否则 Ctrl+C 完全无效。
1084
+ *
1085
+ * 实战(v0.4.260):东叔按建议把 `timeouts.deepseek` 提到 900000 后出卷,第 3 轮等了
1086
+ * 11 分钟,**按 Ctrl+C 退不出去**。DeepSeek/Kimi 的 `enableStreamingToolCalls=false`
1087
+ * 让整个 agentic 循环都走 `chatWithTools()` 这条阻塞路径,而这里此前只传了 `timeout`、
1088
+ * 没传 `signal`:REPL 的 AbortController 一路传到 `request.signal` 就断在这一跳,
1089
+ * 请求无法取消;`consumeToolCallStream()` 又只在**事件之间**检查 aborted,而回退路径
1090
+ * 要等这个 await 返回后才会吐第一个事件 —— 于是中断只能等满超时(被我调高到 15 分钟)。
1091
+ * 两个流式方法本来就传了 signal,唯独两个非流式方法漏了,属同一处遗漏的两半。
1092
+ */
1080
1093
  async chat(request) {
1081
1094
  try {
1082
1095
  const response = await this.client.chat.completions.create({
@@ -1087,7 +1100,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1087
1100
  stream: false,
1088
1101
  ...request.thinking ? { thinking: { type: "enabled" } } : {}
1089
1102
  }, {
1090
- timeout: request.timeout ?? this.defaultTimeout
1103
+ timeout: request.timeout ?? this.defaultTimeout,
1104
+ signal: request.signal
1091
1105
  });
1092
1106
  const firstChoice = response.choices?.[0];
1093
1107
  if (!firstChoice) {
@@ -1193,7 +1207,9 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1193
1207
  stream: false,
1194
1208
  ...request.thinking ? { thinking: { type: "enabled" } } : {}
1195
1209
  }, {
1196
- timeout: request.timeout ?? this.defaultTimeout
1210
+ timeout: request.timeout ?? this.defaultTimeout,
1211
+ // 非流式路径同样必须收 signal,否则 Ctrl+C 期间整个请求不可中断(见 chat() 上方注释)
1212
+ signal: request.signal
1197
1213
  });
1198
1214
  const firstChoice = response.choices?.[0];
1199
1215
  if (!firstChoice) {
@@ -1449,6 +1465,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1449
1465
  }
1450
1466
  }
1451
1467
  wrapError(err) {
1468
+ if (err instanceof OpenAI.APIUserAbortError) return err;
1469
+ if (err instanceof Error && err.name === "AbortError") return err;
1452
1470
  if (err instanceof OpenAI.AuthenticationError) {
1453
1471
  return new AuthError(this.info.id);
1454
1472
  }
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.259";
2
+ var VERSION = "0.4.261";
3
3
  var APP_NAME = "ai-cli";
4
4
  var CONFIG_DIR_NAME = ".aicli";
5
5
  var CONFIG_FILE_NAME = "config.json";
@@ -6,7 +6,7 @@ import {
6
6
  MEMORY_FILE_NAME,
7
7
  MEMORY_MAX_CHARS,
8
8
  MEMORY_STORE_FILE_NAME
9
- } from "./chunk-DLOOIAAD.js";
9
+ } from "./chunk-R6DXWVVN.js";
10
10
  import {
11
11
  atomicWriteFileSync
12
12
  } from "./chunk-6BUTA5VW.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CONFIG_DIR_NAME,
4
4
  PLUGINS_DIR_NAME
5
- } from "./chunk-4TDVLTX2.js";
5
+ } from "./chunk-323S2X5I.js";
6
6
  import {
7
7
  atomicWriteFileSync
8
8
  } from "./chunk-IW3Q7AE5.js";
@@ -188,6 +188,52 @@ function buildWriteRoundReminder(writtenCount) {
188
188
  You have successfully called write_file ${writtenCount} time(s) so far in this turn. If there are more files to write, call write_file NOW for the next file. Do NOT produce a text summary until ALL files have been written via tool calls.`;
189
189
  }
190
190
  var HALLUCINATION_CORRECTION_MESSAGE = "You did NOT actually call the write_file tool \u2014 the file was NOT created! Please immediately use the write_file tool via the function calling API to perform the actual file write. Do NOT describe file content in text \u2014 you MUST invoke write_file through the tool_calls mechanism.";
191
+ var ACTION_WORD_RE = /(?:已[生保写创]|saved|written|created|完成.*(?:写入|保存|创建|生成)|输出|file\s+(?:saved|written|created))/i;
192
+ var CLAUSE_BOUNDARY_RE = /[。.!?!?;;,,]/;
193
+ var LIST_LINE_RE = /^\s*(?:[-*+]|\d+[.)]|\|)/;
194
+ function hasWriteIntentNear(content, pathStart, pathEnd) {
195
+ const lineStart = content.lastIndexOf("\n", pathStart - 1) + 1;
196
+ const lineEndRaw = content.indexOf("\n", pathEnd);
197
+ const lineEnd = lineEndRaw === -1 ? content.length : lineEndRaw;
198
+ const currentLine = content.slice(lineStart, lineEnd);
199
+ const prevLineStart = lineStart === 0 ? 0 : content.lastIndexOf("\n", lineStart - 2) + 1;
200
+ const prevLine = lineStart === 0 ? "" : content.slice(prevLineStart, lineStart - 1);
201
+ const introColon = /[::]\s*$/.test(prevLine);
202
+ if (LIST_LINE_RE.test(currentLine) || introColon) {
203
+ let pos = pathStart;
204
+ let linesBack = 0;
205
+ while (linesBack < 9 && pos > 0) {
206
+ pos--;
207
+ if (content[pos] === "\n") linesBack++;
208
+ }
209
+ const windowStart = pos === 0 ? 0 : pos + 1;
210
+ return ACTION_WORD_RE.test(content.slice(windowStart, lineEnd));
211
+ }
212
+ const boundaryBefore = (from) => {
213
+ for (let i = from - 1; i >= lineStart; i--) {
214
+ if (CLAUSE_BOUNDARY_RE.test(content[i] ?? "")) return i + 1;
215
+ }
216
+ return lineStart;
217
+ };
218
+ let clauseEnd = lineEnd;
219
+ for (let i = pathEnd; i < lineEnd; i++) {
220
+ if (CLAUSE_BOUNDARY_RE.test(content[i] ?? "")) {
221
+ clauseEnd = i + 1;
222
+ break;
223
+ }
224
+ }
225
+ const isBareClause = (text2) => text2.replace(/`[^`\n]*`/g, "").replace(content.slice(pathStart, pathEnd), "").replace(/[\s'"“”‘’()()、,,。;;::+\-和与及]/g, "").length <= 2;
226
+ let start = boundaryBefore(pathStart);
227
+ let text = content.slice(start, clauseEnd);
228
+ if (ACTION_WORD_RE.test(text)) return true;
229
+ for (let step = 0; step < 6 && start > lineStart && isBareClause(text); step++) {
230
+ const prevEnd = start - 1;
231
+ start = boundaryBefore(prevEnd);
232
+ text = content.slice(start, prevEnd);
233
+ if (ACTION_WORD_RE.test(text)) return true;
234
+ }
235
+ return false;
236
+ }
191
237
  function extractClaimedFilePaths(content) {
192
238
  const paths = /* @__PURE__ */ new Set();
193
239
  const add = (p) => {
@@ -195,36 +241,19 @@ function extractClaimedFilePaths(content) {
195
241
  if (trimmed && /\.\w{1,6}$/.test(trimmed)) paths.add(trimmed);
196
242
  };
197
243
  let m;
198
- const actionLineRe = /(?:已[生保写创]|saved|written|created|完成.*(?:写入|保存|创建|生成)|输出|file\s+(?:saved|written|created))/i;
199
244
  const backtickRe = /`([^`\n]+?\.\w{1,6})`/g;
200
245
  while ((m = backtickRe.exec(content)) !== null) {
201
- let pos = m.index;
202
- let linesBack = 0;
203
- while (linesBack < 9 && pos > 0) {
204
- pos--;
205
- if (content[pos] === "\n") linesBack++;
206
- }
207
- const windowStart = pos === 0 ? 0 : pos + 1;
208
- const lineEndIdx = content.indexOf("\n", m.index + m[0].length);
209
- const window = content.slice(windowStart, lineEndIdx === -1 ? void 0 : lineEndIdx);
210
- if (actionLineRe.test(window)) add(m[1]);
246
+ const pathStart = m.index + m[0].indexOf(m[1]);
247
+ if (hasWriteIntentNear(content, pathStart, pathStart + m[1].length)) add(m[1]);
211
248
  }
212
- const zhRe = /(?:已保存(?:到)?|已写入(?:到)?|已创建|已生成|文件路径[::]|保存为|写入到)\s*[`'”””]?([^\s`'”””,,。\n]+?\.\w{1,6})/g;
249
+ const zhRe = /(?:已保存(?:到)?|已写入(?:到)?|已创建|已生成|文件路径[::]|保存为|写入到)\s*[`'”””]?([^\s`'”””,,。\n]+\.\w{1,6})/g;
213
250
  while ((m = zhRe.exec(content)) !== null) add(m[1]);
214
- const enRe = /(?:saved|written|created)\s+(?:to|as|at)\s+[`'”]?([^\s`'”\n,]+?\.\w{1,6})/gi;
251
+ const enRe = /(?:saved|written|created)\s+(?:to|as|at)\s+[`'”]?([^\s`'”\n,]+\.\w{1,6})/gi;
215
252
  while ((m = enRe.exec(content)) !== null) add(m[1]);
216
253
  const checkRe = /✅[^\n`]*?[`'”]?([^\s`'”\n,,。]+?\.\w{1,6})/g;
217
254
  while ((m = checkRe.exec(content)) !== null) {
218
- let pos = m.index;
219
- let linesBack = 0;
220
- while (linesBack < 9 && pos > 0) {
221
- pos--;
222
- if (content[pos] === "\n") linesBack++;
223
- }
224
- const windowStart = pos === 0 ? 0 : pos + 1;
225
- const lineEndIdx = content.indexOf("\n", m.index + m[0].length);
226
- const window = content.slice(windowStart, lineEndIdx === -1 ? void 0 : lineEndIdx);
227
- if (actionLineRe.test(window)) add(m[1]);
255
+ const pathStart = m.index + m[0].lastIndexOf(m[1]);
256
+ if (hasWriteIntentNear(content, pathStart, pathStart + m[1].length)) add(m[1]);
228
257
  }
229
258
  return Array.from(paths);
230
259
  }
@@ -337,7 +366,7 @@ function findPhantomClaims(content, extraMessages) {
337
366
  }
338
367
  function buildPhantomCorrectionMessage(phantoms) {
339
368
  const list = phantoms.map((p) => ` - ${p}`).join("\n");
340
- return "You claimed to have written the following file(s), but no matching write_file tool call was actually made in this turn:\n" + list + '\n\nEach of these files does NOT exist on disk. You MUST now invoke write_file (via the function calling API) for every missing file listed above. Do NOT output another "completion summary" until the tool calls have actually been made.';
369
+ return 'Your reply mentions the following file(s) alongside a "written / saved / created" claim, but no matching write_file or edit_file tool call was made in this turn:\n' + list + "\n\nIf you did intend to create or modify them, invoke write_file / edit_file NOW \u2014 they do not exist on disk yet, and you must not report the task as done until the tool calls return.\n\nIf you were only REFERENCING them (files you merely read, cited as examples, or named as prior art), then this was a false alarm: do NOT create them, do NOT overwrite anything. Simply restate your answer and say explicitly which of the listed paths you only read or cited. Creating a file that the user never asked for is worse than the false alarm.";
341
370
  }
342
371
  var DSML_PIPE_CLASS = "[|\\uFF5C\\u2502\\u2503\\u01C0]";
343
372
  var PSEUDO_TOOL_CALL_PATTERNS = [
@@ -770,7 +799,7 @@ async function consumeToolCallStream(stream, hooks = {}) {
770
799
  }
771
800
  }
772
801
  } catch (err) {
773
- if (err instanceof Error && (err.name === "AbortError" || err.message.includes("aborted"))) {
802
+ if (isAbortError(err)) {
774
803
  aborted = true;
775
804
  } else {
776
805
  throw err;
@@ -864,6 +893,10 @@ var BudgetWarner = class {
864
893
  return null;
865
894
  }
866
895
  };
896
+ function isAbortError(err) {
897
+ if (!(err instanceof Error)) return false;
898
+ return err.name === "AbortError" || err.name === "APIUserAbortError" || err.message.includes("aborted");
899
+ }
867
900
  var EMPTY_RESPONSE_NUDGE = "Your previous response was empty \u2014 no text and no tool calls. This usually means the context window is nearly full. Please either: (1) continue the task by calling the next tool you need, or (2) give a concise final text summary of what has been accomplished so far and what remains. Do NOT repeat earlier long outputs.";
868
901
  var LENGTH_LIMIT_NUDGE = "Your previous attempt hit the model output token limit (finish_reason=length) before producing ANY answer text or tool call \u2014 the entire output budget was consumed by extended reasoning. Retrying the same way will fail identically. Do NOT reason at length again: start producing output immediately. If the deliverable is long, do NOT try to emit it in one response \u2014 write it to disk in several smaller write_file calls (part 1, part 2, ...), each well under the output limit, and keep any thinking short.";
869
902
  function describeFinishReason(fr) {
@@ -968,6 +1001,8 @@ async function runAgentLoop(host) {
968
1001
  const freeRounds = new FreeRoundTracker();
969
1002
  const roundToolHistory = [];
970
1003
  const hasWriteTools = host.toolDefs.some((t) => t.name === "write_file" || t.name === "edit_file");
1004
+ let hallucinationRetries = 0;
1005
+ const MAX_HALLUCINATION_RETRIES = 2;
971
1006
  for (let round = 0; round < maxToolRounds; round++) {
972
1007
  if (host.signal?.aborted) return { reason: "aborted", usage };
973
1008
  host.onRoundStart?.(round, maxToolRounds);
@@ -1005,7 +1040,8 @@ async function runAgentLoop(host) {
1005
1040
  const phantomPaths = (coarseHallucination || alreadyWrote) && !host.planMode && hasWriteTools && content ? findPhantomClaims(content, extraMessages) : [];
1006
1041
  const bashRanThisTurn = extractBashCommands(extraMessages).length > 0;
1007
1042
  const coarseShouldFire = coarseHallucination && !bashRanThisTurn;
1008
- if ((phantomPaths.length > 0 || coarseShouldFire) && round < maxToolRounds - 1) {
1043
+ if ((phantomPaths.length > 0 || coarseShouldFire) && round < maxToolRounds - 1 && hallucinationRetries < MAX_HALLUCINATION_RETRIES) {
1044
+ hallucinationRetries++;
1009
1045
  host.onHallucinationRetry?.({ phantomPaths, round, alreadyRendered });
1010
1046
  const correctionMsg = phantomPaths.length > 0 ? buildPhantomCorrectionMessage(phantomPaths) : HALLUCINATION_CORRECTION_MESSAGE;
1011
1047
  const reasoningField = outcome.reasoningContent ? { reasoning_content: outcome.reasoningContent } : host.providerId === "deepseek" ? { reasoning_content: "" } : {};
@@ -1171,6 +1207,7 @@ export {
1171
1207
  parseToolCallArguments,
1172
1208
  buildTruncatedArgumentsError,
1173
1209
  consumeToolCallStream,
1210
+ isAbortError,
1174
1211
  accumulateUsage,
1175
1212
  buildRoundBudgetHint,
1176
1213
  runAgentLoop,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateForPersist
4
- } from "./chunk-4RPJQJBI.js";
4
+ } from "./chunk-HU3IYBU5.js";
5
5
  import {
6
6
  APP_NAME,
7
7
  CONFIG_DIR_NAME,
@@ -11,7 +11,7 @@ import {
11
11
  MCP_PROTOCOL_VERSION,
12
12
  MCP_TOOL_PREFIX,
13
13
  VERSION
14
- } from "./chunk-4TDVLTX2.js";
14
+ } from "./chunk-323S2X5I.js";
15
15
  import {
16
16
  atomicWriteFileSync
17
17
  } from "./chunk-IW3Q7AE5.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  evaluateCiGate,
4
4
  normalizeCiThresholds
5
- } from "./chunk-PSH5O44I.js";
5
+ } from "./chunk-GC4KA5LF.js";
6
6
  import {
7
7
  buildReviewPrompt,
8
8
  buildSecurityReviewPrompt,
@@ -10,13 +10,13 @@ import {
10
10
  } from "./chunk-HLWUDRBO.js";
11
11
  import {
12
12
  ProviderRegistry
13
- } from "./chunk-GDJII6TK.js";
13
+ } from "./chunk-OIOTHBDB.js";
14
14
  import {
15
15
  ConfigManager
16
- } from "./chunk-G65I4DXP.js";
16
+ } from "./chunk-H6FND2UG.js";
17
17
  import {
18
18
  VERSION
19
- } from "./chunk-4TDVLTX2.js";
19
+ } from "./chunk-323S2X5I.js";
20
20
 
21
21
  // src/cli/ci.ts
22
22
  import { execFileSync } from "child_process";
@@ -3,14 +3,14 @@ import {
3
3
  CI_COMMENT_MARKER,
4
4
  countSeverity,
5
5
  runCi
6
- } from "./chunk-3EWST6SE.js";
7
- import "./chunk-PSH5O44I.js";
6
+ } from "./chunk-Z5TCAE4L.js";
7
+ import "./chunk-GC4KA5LF.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
- import "./chunk-GDJII6TK.js";
10
- import "./chunk-G65I4DXP.js";
11
- import "./chunk-XPNKMDBH.js";
9
+ import "./chunk-OIOTHBDB.js";
10
+ import "./chunk-H6FND2UG.js";
11
+ import "./chunk-XZNRZGG2.js";
12
12
  import "./chunk-TU3L3PW7.js";
13
- import "./chunk-4TDVLTX2.js";
13
+ import "./chunk-323S2X5I.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
15
  export {
16
16
  CI_COMMENT_MARKER,
@@ -6,8 +6,8 @@ import {
6
6
  formatCiResult,
7
7
  formatCiSarif,
8
8
  normalizeCiThresholds
9
- } from "./chunk-PSH5O44I.js";
10
- import "./chunk-4TDVLTX2.js";
9
+ } from "./chunk-GC4KA5LF.js";
10
+ import "./chunk-323S2X5I.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-4TDVLTX2.js";
41
+ } from "./chunk-323S2X5I.js";
42
42
  export {
43
43
  AGENTIC_BEHAVIOR_GUIDELINE,
44
44
  APP_NAME,
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  formatDoctorReport,
4
4
  runDoctorCli
5
- } from "./chunk-ZZ5WTHKY.js";
6
- import "./chunk-GDJII6TK.js";
7
- import "./chunk-G65I4DXP.js";
8
- import "./chunk-3KYUE2MD.js";
9
- import "./chunk-XPNKMDBH.js";
5
+ } from "./chunk-NOB2OPQI.js";
6
+ import "./chunk-OIOTHBDB.js";
7
+ import "./chunk-H6FND2UG.js";
8
+ import "./chunk-W5XUZYQE.js";
9
+ import "./chunk-XZNRZGG2.js";
10
10
  import "./chunk-TU3L3PW7.js";
11
11
  import "./chunk-HOSJZMQS.js";
12
- import "./chunk-4TDVLTX2.js";
12
+ import "./chunk-323S2X5I.js";
13
13
  import "./chunk-IW3Q7AE5.js";
14
14
  export {
15
15
  formatDoctorReport,