jinzd-ai-cli 0.4.260 → 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-LBMJWMMO.js → batch-YUPAC4CK.js} +2 -2
  2. package/dist/{chunk-KRENSXPC.js → chunk-323S2X5I.js} +1 -1
  3. package/dist/{chunk-VJP2GLW5.js → chunk-GC4KA5LF.js} +1 -1
  4. package/dist/{chunk-K6WMQBUP.js → chunk-H6FND2UG.js} +1 -1
  5. package/dist/{chunk-3TE7ZWO5.js → chunk-HGTDI5ME.js} +1 -1
  6. package/dist/{chunk-NEYNE6UE.js → chunk-HU3IYBU5.js} +11 -9
  7. package/dist/{chunk-XTA3LSPQ.js → chunk-KFNQESEG.js} +1 -1
  8. package/dist/{chunk-HBR33J6J.js → chunk-KQQHMGK7.js} +1 -1
  9. package/dist/{chunk-63M2ELJS.js → chunk-NOB2OPQI.js} +4 -4
  10. package/dist/{chunk-U2HN3EW6.js → chunk-OIOTHBDB.js} +1 -1
  11. package/dist/{chunk-26C6YZ3A.js → chunk-R6DXWVVN.js} +1 -1
  12. package/dist/{chunk-CLJKNKUN.js → chunk-T7R7ILYT.js} +1 -1
  13. package/dist/{chunk-Y7UZSFGS.js → chunk-W5XUZYQE.js} +1 -1
  14. package/dist/{chunk-FCPYMBTA.js → chunk-XZNRZGG2.js} +57 -25
  15. package/dist/{chunk-AAWV4BP4.js → chunk-YXMBP567.js} +2 -2
  16. package/dist/{chunk-2BGNEVS5.js → chunk-Z5TCAE4L.js} +4 -4
  17. package/dist/{ci-PSA7F4EI.js → ci-FX26BNT2.js} +6 -6
  18. package/dist/{ci-format-WAHEZZMY.js → ci-format-GEWIAIZD.js} +2 -2
  19. package/dist/{constants-C55LGUR7.js → constants-YN4B6C7B.js} +1 -1
  20. package/dist/{doctor-cli-YANDJBHC.js → doctor-cli-PXGXZYQB.js} +6 -6
  21. package/dist/electron-server.js +69 -35
  22. package/dist/{hub-CBOC3TT3.js → hub-RCANK6SK.js} +1 -1
  23. package/dist/index.js +86 -39
  24. package/dist/{persistent-memory-DUFOZTDV.js → persistent-memory-P3COUZZM.js} +2 -2
  25. package/dist/{persistent-memory-KEYVKD54.js → persistent-memory-UARSSYAA.js} +2 -2
  26. package/dist/{pr-T6KCK5DT.js → pr-7LQTAUFK.js} +6 -6
  27. package/dist/{run-tests-S2RLPMCR.js → run-tests-7RYU4BK5.js} +2 -2
  28. package/dist/{run-tests-K43DLTA3.js → run-tests-YNHESHYY.js} +2 -2
  29. package/dist/{server-SV3TV5BJ.js → server-SSAWGNT7.js} +13 -13
  30. package/dist/{server-GTRCCOXN.js → server-YZ37TL46.js} +6 -6
  31. package/dist/{task-orchestrator-DW5AWW7J.js → task-orchestrator-ZFL4E6NZ.js} +6 -6
  32. package/dist/{usage-BP442V2Q.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-K6WMQBUP.js";
4
+ } from "./chunk-H6FND2UG.js";
5
5
  import "./chunk-TU3L3PW7.js";
6
- import "./chunk-KRENSXPC.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.260";
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-KRENSXPC.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-KRENSXPC.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-KRENSXPC.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-3TE7ZWO5.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-Y7UZSFGS.js";
26
+ } from "./chunk-W5XUZYQE.js";
27
27
  import {
28
28
  buildTruncatedArgumentsError,
29
29
  getDangerLevel,
30
30
  isFileWriteTool,
31
31
  runLeanAgentLoop
32
- } from "./chunk-FCPYMBTA.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-HBR33J6J.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-KRENSXPC.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-26C6YZ3A.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-KRENSXPC.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-U2HN3EW6.js";
4
+ } from "./chunk-OIOTHBDB.js";
5
5
  import {
6
6
  ConfigManager
7
- } from "./chunk-K6WMQBUP.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-Y7UZSFGS.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-KRENSXPC.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-FCPYMBTA.js";
6
+ } from "./chunk-XZNRZGG2.js";
7
7
  import {
8
8
  AuthError,
9
9
  ProviderError,
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.260";
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-26C6YZ3A.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-KRENSXPC.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 = [
@@ -972,6 +1001,8 @@ async function runAgentLoop(host) {
972
1001
  const freeRounds = new FreeRoundTracker();
973
1002
  const roundToolHistory = [];
974
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;
975
1006
  for (let round = 0; round < maxToolRounds; round++) {
976
1007
  if (host.signal?.aborted) return { reason: "aborted", usage };
977
1008
  host.onRoundStart?.(round, maxToolRounds);
@@ -1009,7 +1040,8 @@ async function runAgentLoop(host) {
1009
1040
  const phantomPaths = (coarseHallucination || alreadyWrote) && !host.planMode && hasWriteTools && content ? findPhantomClaims(content, extraMessages) : [];
1010
1041
  const bashRanThisTurn = extractBashCommands(extraMessages).length > 0;
1011
1042
  const coarseShouldFire = coarseHallucination && !bashRanThisTurn;
1012
- if ((phantomPaths.length > 0 || coarseShouldFire) && round < maxToolRounds - 1) {
1043
+ if ((phantomPaths.length > 0 || coarseShouldFire) && round < maxToolRounds - 1 && hallucinationRetries < MAX_HALLUCINATION_RETRIES) {
1044
+ hallucinationRetries++;
1013
1045
  host.onHallucinationRetry?.({ phantomPaths, round, alreadyRendered });
1014
1046
  const correctionMsg = phantomPaths.length > 0 ? buildPhantomCorrectionMessage(phantomPaths) : HALLUCINATION_CORRECTION_MESSAGE;
1015
1047
  const reasoningField = outcome.reasoningContent ? { reasoning_content: outcome.reasoningContent } : host.providerId === "deepseek" ? { reasoning_content: "" } : {};
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateForPersist
4
- } from "./chunk-NEYNE6UE.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-KRENSXPC.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-VJP2GLW5.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-U2HN3EW6.js";
13
+ } from "./chunk-OIOTHBDB.js";
14
14
  import {
15
15
  ConfigManager
16
- } from "./chunk-K6WMQBUP.js";
16
+ } from "./chunk-H6FND2UG.js";
17
17
  import {
18
18
  VERSION
19
- } from "./chunk-KRENSXPC.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-2BGNEVS5.js";
7
- import "./chunk-VJP2GLW5.js";
6
+ } from "./chunk-Z5TCAE4L.js";
7
+ import "./chunk-GC4KA5LF.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
- import "./chunk-U2HN3EW6.js";
10
- import "./chunk-K6WMQBUP.js";
11
- import "./chunk-FCPYMBTA.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-KRENSXPC.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-VJP2GLW5.js";
10
- import "./chunk-KRENSXPC.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-KRENSXPC.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-63M2ELJS.js";
6
- import "./chunk-U2HN3EW6.js";
7
- import "./chunk-K6WMQBUP.js";
8
- import "./chunk-Y7UZSFGS.js";
9
- import "./chunk-FCPYMBTA.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-KRENSXPC.js";
12
+ import "./chunk-323S2X5I.js";
13
13
  import "./chunk-IW3Q7AE5.js";
14
14
  export {
15
15
  formatDoctorReport,
@@ -34,14 +34,14 @@ import {
34
34
  touchMemoryReferences,
35
35
  updateMemoryApproval,
36
36
  updateMemoryEntry
37
- } from "./chunk-CLJKNKUN.js";
37
+ } from "./chunk-T7R7ILYT.js";
38
38
  import {
39
39
  redactJson,
40
40
  scanString
41
41
  } from "./chunk-YVTASHS5.js";
42
42
  import {
43
43
  runTestsTool
44
- } from "./chunk-XTA3LSPQ.js";
44
+ } from "./chunk-KFNQESEG.js";
45
45
  import {
46
46
  AGENTIC_BEHAVIOR_GUIDELINE,
47
47
  APP_NAME,
@@ -73,7 +73,7 @@ import {
73
73
  SUBAGENT_MAX_ROUNDS_LIMIT,
74
74
  VERSION,
75
75
  buildUserIdentityPrompt
76
- } from "./chunk-26C6YZ3A.js";
76
+ } from "./chunk-R6DXWVVN.js";
77
77
  import {
78
78
  hasSemanticIndex,
79
79
  semanticSearch
@@ -1813,6 +1813,52 @@ CRITICAL \u2014 Batch file generation rules:
1813
1813
  4. Only produce a text summary AFTER all write_file calls have been made and returned success.
1814
1814
  5. The system compares every "file saved" claim against actual tool calls. Phantom claims trigger an automatic retry \u2014 do not waste rounds.`;
1815
1815
  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.";
1816
+ var ACTION_WORD_RE = /(?:已[生保写创]|saved|written|created|完成.*(?:写入|保存|创建|生成)|输出|file\s+(?:saved|written|created))/i;
1817
+ var CLAUSE_BOUNDARY_RE = /[。.!?!?;;,,]/;
1818
+ var LIST_LINE_RE = /^\s*(?:[-*+]|\d+[.)]|\|)/;
1819
+ function hasWriteIntentNear(content, pathStart, pathEnd) {
1820
+ const lineStart = content.lastIndexOf("\n", pathStart - 1) + 1;
1821
+ const lineEndRaw = content.indexOf("\n", pathEnd);
1822
+ const lineEnd = lineEndRaw === -1 ? content.length : lineEndRaw;
1823
+ const currentLine = content.slice(lineStart, lineEnd);
1824
+ const prevLineStart = lineStart === 0 ? 0 : content.lastIndexOf("\n", lineStart - 2) + 1;
1825
+ const prevLine = lineStart === 0 ? "" : content.slice(prevLineStart, lineStart - 1);
1826
+ const introColon = /[::]\s*$/.test(prevLine);
1827
+ if (LIST_LINE_RE.test(currentLine) || introColon) {
1828
+ let pos = pathStart;
1829
+ let linesBack = 0;
1830
+ while (linesBack < 9 && pos > 0) {
1831
+ pos--;
1832
+ if (content[pos] === "\n") linesBack++;
1833
+ }
1834
+ const windowStart = pos === 0 ? 0 : pos + 1;
1835
+ return ACTION_WORD_RE.test(content.slice(windowStart, lineEnd));
1836
+ }
1837
+ const boundaryBefore = (from) => {
1838
+ for (let i = from - 1; i >= lineStart; i--) {
1839
+ if (CLAUSE_BOUNDARY_RE.test(content[i] ?? "")) return i + 1;
1840
+ }
1841
+ return lineStart;
1842
+ };
1843
+ let clauseEnd = lineEnd;
1844
+ for (let i = pathEnd; i < lineEnd; i++) {
1845
+ if (CLAUSE_BOUNDARY_RE.test(content[i] ?? "")) {
1846
+ clauseEnd = i + 1;
1847
+ break;
1848
+ }
1849
+ }
1850
+ const isBareClause = (text2) => text2.replace(/`[^`\n]*`/g, "").replace(content.slice(pathStart, pathEnd), "").replace(/[\s'"“”‘’()()、,,。;;::+\-和与及]/g, "").length <= 2;
1851
+ let start = boundaryBefore(pathStart);
1852
+ let text = content.slice(start, clauseEnd);
1853
+ if (ACTION_WORD_RE.test(text)) return true;
1854
+ for (let step = 0; step < 6 && start > lineStart && isBareClause(text); step++) {
1855
+ const prevEnd = start - 1;
1856
+ start = boundaryBefore(prevEnd);
1857
+ text = content.slice(start, prevEnd);
1858
+ if (ACTION_WORD_RE.test(text)) return true;
1859
+ }
1860
+ return false;
1861
+ }
1816
1862
  function extractClaimedFilePaths(content) {
1817
1863
  const paths = /* @__PURE__ */ new Set();
1818
1864
  const add = (p) => {
@@ -1820,36 +1866,19 @@ function extractClaimedFilePaths(content) {
1820
1866
  if (trimmed && /\.\w{1,6}$/.test(trimmed)) paths.add(trimmed);
1821
1867
  };
1822
1868
  let m;
1823
- const actionLineRe = /(?:已[生保写创]|saved|written|created|完成.*(?:写入|保存|创建|生成)|输出|file\s+(?:saved|written|created))/i;
1824
1869
  const backtickRe = /`([^`\n]+?\.\w{1,6})`/g;
1825
1870
  while ((m = backtickRe.exec(content)) !== null) {
1826
- let pos = m.index;
1827
- let linesBack = 0;
1828
- while (linesBack < 9 && pos > 0) {
1829
- pos--;
1830
- if (content[pos] === "\n") linesBack++;
1831
- }
1832
- const windowStart = pos === 0 ? 0 : pos + 1;
1833
- const lineEndIdx = content.indexOf("\n", m.index + m[0].length);
1834
- const window = content.slice(windowStart, lineEndIdx === -1 ? void 0 : lineEndIdx);
1835
- if (actionLineRe.test(window)) add(m[1]);
1871
+ const pathStart = m.index + m[0].indexOf(m[1]);
1872
+ if (hasWriteIntentNear(content, pathStart, pathStart + m[1].length)) add(m[1]);
1836
1873
  }
1837
- const zhRe = /(?:已保存(?:到)?|已写入(?:到)?|已创建|已生成|文件路径[::]|保存为|写入到)\s*[`'”””]?([^\s`'”””,,。\n]+?\.\w{1,6})/g;
1874
+ const zhRe = /(?:已保存(?:到)?|已写入(?:到)?|已创建|已生成|文件路径[::]|保存为|写入到)\s*[`'”””]?([^\s`'”””,,。\n]+\.\w{1,6})/g;
1838
1875
  while ((m = zhRe.exec(content)) !== null) add(m[1]);
1839
- const enRe = /(?:saved|written|created)\s+(?:to|as|at)\s+[`'”]?([^\s`'”\n,]+?\.\w{1,6})/gi;
1876
+ const enRe = /(?:saved|written|created)\s+(?:to|as|at)\s+[`'”]?([^\s`'”\n,]+\.\w{1,6})/gi;
1840
1877
  while ((m = enRe.exec(content)) !== null) add(m[1]);
1841
1878
  const checkRe = /✅[^\n`]*?[`'”]?([^\s`'”\n,,。]+?\.\w{1,6})/g;
1842
1879
  while ((m = checkRe.exec(content)) !== null) {
1843
- let pos = m.index;
1844
- let linesBack = 0;
1845
- while (linesBack < 9 && pos > 0) {
1846
- pos--;
1847
- if (content[pos] === "\n") linesBack++;
1848
- }
1849
- const windowStart = pos === 0 ? 0 : pos + 1;
1850
- const lineEndIdx = content.indexOf("\n", m.index + m[0].length);
1851
- const window = content.slice(windowStart, lineEndIdx === -1 ? void 0 : lineEndIdx);
1852
- if (actionLineRe.test(window)) add(m[1]);
1880
+ const pathStart = m.index + m[0].lastIndexOf(m[1]);
1881
+ if (hasWriteIntentNear(content, pathStart, pathStart + m[1].length)) add(m[1]);
1853
1882
  }
1854
1883
  return Array.from(paths);
1855
1884
  }
@@ -1962,7 +1991,7 @@ function findPhantomClaims(content, extraMessages) {
1962
1991
  }
1963
1992
  function buildPhantomCorrectionMessage(phantoms) {
1964
1993
  const list = phantoms.map((p) => ` - ${p}`).join("\n");
1965
- 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.';
1994
+ 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.";
1966
1995
  }
1967
1996
  var DSML_PIPE_CLASS = "[|\\uFF5C\\u2502\\u2503\\u01C0]";
1968
1997
  var PSEUDO_TOOL_CALL_PATTERNS = [
@@ -2597,6 +2626,8 @@ async function runAgentLoop(host) {
2597
2626
  const freeRounds = new FreeRoundTracker();
2598
2627
  const roundToolHistory = [];
2599
2628
  const hasWriteTools = host.toolDefs.some((t) => t.name === "write_file" || t.name === "edit_file");
2629
+ let hallucinationRetries = 0;
2630
+ const MAX_HALLUCINATION_RETRIES = 2;
2600
2631
  for (let round = 0; round < maxToolRounds; round++) {
2601
2632
  if (host.signal?.aborted) return { reason: "aborted", usage };
2602
2633
  host.onRoundStart?.(round, maxToolRounds);
@@ -2634,7 +2665,8 @@ async function runAgentLoop(host) {
2634
2665
  const phantomPaths = (coarseHallucination || alreadyWrote) && !host.planMode && hasWriteTools && content ? findPhantomClaims(content, extraMessages) : [];
2635
2666
  const bashRanThisTurn = extractBashCommands(extraMessages).length > 0;
2636
2667
  const coarseShouldFire = coarseHallucination && !bashRanThisTurn;
2637
- if ((phantomPaths.length > 0 || coarseShouldFire) && round < maxToolRounds - 1) {
2668
+ if ((phantomPaths.length > 0 || coarseShouldFire) && round < maxToolRounds - 1 && hallucinationRetries < MAX_HALLUCINATION_RETRIES) {
2669
+ hallucinationRetries++;
2638
2670
  host.onHallucinationRetry?.({ phantomPaths, round, alreadyRendered });
2639
2671
  const correctionMsg = phantomPaths.length > 0 ? buildPhantomCorrectionMessage(phantomPaths) : HALLUCINATION_CORRECTION_MESSAGE;
2640
2672
  const reasoningField = outcome.reasoningContent ? { reasoning_content: outcome.reasoningContent } : host.providerId === "deepseek" ? { reasoning_content: "" } : {};
@@ -5081,9 +5113,9 @@ function buildWrappedCommand(command, id, isWindows) {
5081
5113
  if (!isWindows) {
5082
5114
  return `echo "${markerStart}"; ${command}; echo "${markerEnd}:$?"`;
5083
5115
  }
5084
- 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"`;
5085
- const b64 = Buffer.from(inner, "utf-8").toString("base64");
5086
- return `Invoke-Expression ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${b64}')))`;
5116
+ const b64 = Buffer.from(command, "utf-8").toString("base64");
5117
+ const decoded = `[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${b64}'))`;
5118
+ 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"`;
5087
5119
  }
5088
5120
  async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5089
5121
  let entry = pool.get(sessionKey);
@@ -8446,7 +8478,9 @@ Note: Path can be absolute or relative to cwd.`,
8446
8478
  }
8447
8479
  const lines = [];
8448
8480
  if (anyFailed && stopOnError) {
8449
- lines.push(`ERROR: Batch edit aborted \u2014 ${appliedCount}/${edits.length} applied, then edit #${appliedCount} failed. No changes written (stop_on_error=true).`);
8481
+ const failedIdx = reports.find((r) => !r.ok)?.index;
8482
+ const failedLabel = failedIdx != null ? `#${failedIdx + 1}` : "an edit";
8483
+ lines.push(`ERROR: Batch edit aborted \u2014 ${appliedCount}/${edits.length} applied, then edit ${failedLabel} failed. No changes written (stop_on_error=true).`);
8450
8484
  } else if (anyFailed) {
8451
8485
  lines.push(`Partial success: ${appliedCount}/${edits.length} edits applied to ${filePath} (stop_on_error=false).`);
8452
8486
  } else {
@@ -15335,7 +15369,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
15335
15369
  Cost: ${formatCost(cost)}` : "";
15336
15370
  let memoryLine = "";
15337
15371
  try {
15338
- const { countPendingMemories } = await import("./persistent-memory-DUFOZTDV.js");
15372
+ const { countPendingMemories } = await import("./persistent-memory-P3COUZZM.js");
15339
15373
  const pending = countPendingMemories(ctx.config.getConfigDir());
15340
15374
  if (pending > 0) memoryLine = `
15341
15375
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -16144,7 +16178,7 @@ async function handleSecurityReview(args, ctx) {
16144
16178
  async function handleTest(args, ctx) {
16145
16179
  ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
16146
16180
  try {
16147
- const { executeTests } = await import("./run-tests-S2RLPMCR.js");
16181
+ const { executeTests } = await import("./run-tests-7RYU4BK5.js");
16148
16182
  const argStr = args.join(" ").trim();
16149
16183
  let testArgs = {};
16150
16184
  if (argStr) {
@@ -16408,7 +16442,7 @@ async function handleMemory(args, ctx) {
16408
16442
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
16409
16443
  } else if (sub === "export") {
16410
16444
  if (args[1] === "md") {
16411
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-DUFOZTDV.js");
16445
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-P3COUZZM.js");
16412
16446
  ctx.send({
16413
16447
  type: "export_data",
16414
16448
  format: "md",