jinzd-ai-cli 0.4.258 → 0.4.260

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-B42DJMDJ.js → batch-LBMJWMMO.js} +2 -2
  2. package/dist/{chunk-S5YGYXAE.js → chunk-26C6YZ3A.js} +1 -1
  3. package/dist/{chunk-3ERLNXT2.js → chunk-2BGNEVS5.js} +4 -4
  4. package/dist/{chunk-HT5LC2PL.js → chunk-3TE7ZWO5.js} +1 -1
  5. package/dist/{chunk-GVLUGPIX.js → chunk-63M2ELJS.js} +4 -4
  6. package/dist/{chunk-BWZT74E3.js → chunk-AAWV4BP4.js} +2 -2
  7. package/dist/{chunk-BEER3VEB.js → chunk-CLJKNKUN.js} +1 -1
  8. package/dist/{chunk-XPNKMDBH.js → chunk-FCPYMBTA.js} +6 -1
  9. package/dist/{chunk-WLSK55ED.js → chunk-HBR33J6J.js} +1 -1
  10. package/dist/{chunk-XYNZVGUH.js → chunk-K6WMQBUP.js} +1 -1
  11. package/dist/{chunk-I7LBWY7E.js → chunk-KRENSXPC.js} +1 -1
  12. package/dist/{chunk-QJXUJFYD.js → chunk-NEYNE6UE.js} +69 -49
  13. package/dist/{chunk-GDJII6TK.js → chunk-U2HN3EW6.js} +23 -5
  14. package/dist/{chunk-PNQS67JC.js → chunk-VJP2GLW5.js} +1 -1
  15. package/dist/{chunk-GWXWAQVM.js → chunk-XTA3LSPQ.js} +1 -1
  16. package/dist/{chunk-BIXQHN77.js → chunk-Y7UZSFGS.js} +1 -1
  17. package/dist/{ci-MMXYIHYY.js → ci-PSA7F4EI.js} +6 -6
  18. package/dist/{ci-format-FG53M5V2.js → ci-format-WAHEZZMY.js} +2 -2
  19. package/dist/{constants-WROFKV3K.js → constants-C55LGUR7.js} +1 -1
  20. package/dist/{doctor-cli-USQ4HX7A.js → doctor-cli-YANDJBHC.js} +6 -6
  21. package/dist/electron-server.js +144 -104
  22. package/dist/{hub-MWEDYMK6.js → hub-CBOC3TT3.js} +1 -1
  23. package/dist/index.js +80 -47
  24. package/dist/{persistent-memory-PAHA4R7U.js → persistent-memory-DUFOZTDV.js} +2 -2
  25. package/dist/{persistent-memory-ZHYBVUGR.js → persistent-memory-KEYVKD54.js} +2 -2
  26. package/dist/{pr-4P7XC2RK.js → pr-T6KCK5DT.js} +6 -6
  27. package/dist/{run-tests-Y6CBCPFF.js → run-tests-K43DLTA3.js} +2 -2
  28. package/dist/{run-tests-WWJHCLFZ.js → run-tests-S2RLPMCR.js} +2 -2
  29. package/dist/{server-IMKKKH57.js → server-GTRCCOXN.js} +6 -6
  30. package/dist/{server-JDKLBBVN.js → server-SV3TV5BJ.js} +19 -19
  31. package/dist/{task-orchestrator-F534G7LG.js → task-orchestrator-DW5AWW7J.js} +6 -6
  32. package/dist/{usage-P4ORZDPV.js → usage-BP442V2Q.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-XYNZVGUH.js";
4
+ } from "./chunk-K6WMQBUP.js";
5
5
  import "./chunk-TU3L3PW7.js";
6
- import "./chunk-I7LBWY7E.js";
6
+ import "./chunk-KRENSXPC.js";
7
7
  import {
8
8
  atomicWriteFileSync
9
9
  } from "./chunk-IW3Q7AE5.js";
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.258";
2
+ var VERSION = "0.4.260";
3
3
  var APP_NAME = "ai-cli";
4
4
  var CONFIG_DIR_NAME = ".aicli";
5
5
  var CONFIG_FILE_NAME = "config.json";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  evaluateCiGate,
4
4
  normalizeCiThresholds
5
- } from "./chunk-PNQS67JC.js";
5
+ } from "./chunk-VJP2GLW5.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-U2HN3EW6.js";
14
14
  import {
15
15
  ConfigManager
16
- } from "./chunk-XYNZVGUH.js";
16
+ } from "./chunk-K6WMQBUP.js";
17
17
  import {
18
18
  VERSION
19
- } from "./chunk-I7LBWY7E.js";
19
+ } from "./chunk-KRENSXPC.js";
20
20
 
21
21
  // src/cli/ci.ts
22
22
  import { execFileSync } from "child_process";
@@ -6,7 +6,7 @@ import {
6
6
  MEMORY_FILE_NAME,
7
7
  MEMORY_MAX_CHARS,
8
8
  MEMORY_STORE_FILE_NAME
9
- } from "./chunk-I7LBWY7E.js";
9
+ } from "./chunk-KRENSXPC.js";
10
10
  import {
11
11
  DEFAULT_PATTERNS,
12
12
  redactString
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ProviderRegistry
4
- } from "./chunk-GDJII6TK.js";
4
+ } from "./chunk-U2HN3EW6.js";
5
5
  import {
6
6
  ConfigManager
7
- } from "./chunk-XYNZVGUH.js";
7
+ } from "./chunk-K6WMQBUP.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-BIXQHN77.js";
17
+ } from "./chunk-Y7UZSFGS.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-I7LBWY7E.js";
29
+ } from "./chunk-KRENSXPC.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
  truncateForPersist
4
- } from "./chunk-QJXUJFYD.js";
4
+ } from "./chunk-NEYNE6UE.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-I7LBWY7E.js";
14
+ } from "./chunk-KRENSXPC.js";
15
15
  import {
16
16
  atomicWriteFileSync
17
17
  } 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-S5YGYXAE.js";
9
+ } from "./chunk-26C6YZ3A.js";
10
10
  import {
11
11
  atomicWriteFileSync
12
12
  } from "./chunk-6BUTA5VW.js";
@@ -770,7 +770,7 @@ async function consumeToolCallStream(stream, hooks = {}) {
770
770
  }
771
771
  }
772
772
  } catch (err) {
773
- if (err instanceof Error && (err.name === "AbortError" || err.message.includes("aborted"))) {
773
+ if (isAbortError(err)) {
774
774
  aborted = true;
775
775
  } else {
776
776
  throw err;
@@ -864,6 +864,10 @@ var BudgetWarner = class {
864
864
  return null;
865
865
  }
866
866
  };
867
+ function isAbortError(err) {
868
+ if (!(err instanceof Error)) return false;
869
+ return err.name === "AbortError" || err.name === "APIUserAbortError" || err.message.includes("aborted");
870
+ }
867
871
  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
872
  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
873
  function describeFinishReason(fr) {
@@ -1171,6 +1175,7 @@ export {
1171
1175
  parseToolCallArguments,
1172
1176
  buildTruncatedArgumentsError,
1173
1177
  consumeToolCallStream,
1178
+ isAbortError,
1174
1179
  accumulateUsage,
1175
1180
  buildRoundBudgetHint,
1176
1181
  runAgentLoop,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-I7LBWY7E.js";
4
+ } from "./chunk-KRENSXPC.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-I7LBWY7E.js";
11
+ } from "./chunk-KRENSXPC.js";
12
12
  import {
13
13
  atomicWriteFileSync
14
14
  } 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.258";
4
+ var VERSION = "0.4.260";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -7,7 +7,7 @@ import {
7
7
  searchPersistentMemories,
8
8
  touchMemoryReferences,
9
9
  updateMemoryEntry
10
- } from "./chunk-HT5LC2PL.js";
10
+ } from "./chunk-3TE7ZWO5.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-BIXQHN77.js";
26
+ } from "./chunk-Y7UZSFGS.js";
27
27
  import {
28
28
  buildTruncatedArgumentsError,
29
29
  getDangerLevel,
30
30
  isFileWriteTool,
31
31
  runLeanAgentLoop
32
- } from "./chunk-XPNKMDBH.js";
32
+ } from "./chunk-FCPYMBTA.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-WLSK55ED.js";
43
+ } from "./chunk-HBR33J6J.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-I7LBWY7E.js";
50
+ } from "./chunk-KRENSXPC.js";
51
51
  import {
52
52
  loadChatIndex,
53
53
  searchChatMemory
@@ -1376,7 +1376,7 @@ ${content}`;
1376
1376
  };
1377
1377
 
1378
1378
  // src/tools/builtin/write-file.ts
1379
- import { appendFileSync, mkdirSync } from "fs";
1379
+ import { appendFileSync, mkdirSync, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
1380
1380
  import { dirname as dirname3 } from "path";
1381
1381
 
1382
1382
  // src/tools/executor.ts
@@ -1434,6 +1434,37 @@ async function runSafePhases(phase, execute, results, logTag = "executor") {
1434
1434
  return Date.now() - t0;
1435
1435
  }
1436
1436
 
1437
+ // src/tools/arg-aliases.ts
1438
+ function pickArg(args, canonical, aliases) {
1439
+ if (args[canonical] !== void 0 && args[canonical] !== null) return args[canonical];
1440
+ for (const alias of aliases) {
1441
+ if (args[alias] !== void 0 && args[alias] !== null) return args[alias];
1442
+ }
1443
+ return void 0;
1444
+ }
1445
+ var OLD_STR_ALIASES = ["old_string", "oldStr", "oldString", "old_text", "search"];
1446
+ var NEW_STR_ALIASES = ["new_string", "newStr", "newString", "new_text", "replace"];
1447
+ var CONTENT_ALIASES = ["file_text", "text", "contents", "data"];
1448
+ var INSERT_LINE_ALIASES = ["insert_line", "line", "after_line"];
1449
+ var INSERT_CONTENT_ALIASES = ["content", "new_str", "text"];
1450
+ function normalizeReplaceArgs(raw) {
1451
+ const oldStr = pickArg(raw, "old_str", OLD_STR_ALIASES);
1452
+ if (oldStr === void 0) return void 0;
1453
+ return { old_str: oldStr, new_str: pickArg(raw, "new_str", NEW_STR_ALIASES) };
1454
+ }
1455
+ function resolveWriteFileArgs(args) {
1456
+ return {
1457
+ path: String(pickArg(args, "path", ["file"]) ?? ""),
1458
+ content: String(pickArg(args, "content", CONTENT_ALIASES) ?? ""),
1459
+ append: String(args["append"] ?? "false").toLowerCase() === "true"
1460
+ };
1461
+ }
1462
+ function describeReceivedKeys(args) {
1463
+ const keys = Object.keys(args).filter((k) => args[k] !== void 0);
1464
+ if (keys.length === 0) return " (no arguments received)";
1465
+ return ` Received keys: ${keys.join(", ")}.`;
1466
+ }
1467
+
1437
1468
  // src/tools/diff-utils.ts
1438
1469
  import chalk from "chalk";
1439
1470
  function renderDiff(oldText, newText, opts = {}) {
@@ -2677,8 +2708,7 @@ var ToolExecutor = class {
2677
2708
  */
2678
2709
  printDiffPreview(call) {
2679
2710
  if (call.name === "write_file") {
2680
- const filePath = String(call.arguments["path"] ?? "");
2681
- const newContent = String(call.arguments["content"] ?? "");
2711
+ const { path: filePath, content: chunk, append } = resolveWriteFileArgs(call.arguments);
2682
2712
  if (!filePath) return;
2683
2713
  if (existsSync6(filePath)) {
2684
2714
  let oldContent;
@@ -2687,16 +2717,17 @@ var ToolExecutor = class {
2687
2717
  } catch {
2688
2718
  return;
2689
2719
  }
2720
+ const newContent = append ? oldContent + chunk : chunk;
2690
2721
  if (oldContent === newContent) {
2691
2722
  console.log(theme.dim(" (file content unchanged)"));
2692
2723
  return;
2693
2724
  }
2694
2725
  const diff = renderDiff(oldContent, newContent, { filePath, contextLines: 3 });
2695
- console.log(theme.dim(" \u2500\u2500 diff preview \u2500\u2500"));
2726
+ console.log(theme.dim(append ? " \u2500\u2500 append preview \u2500\u2500" : " \u2500\u2500 diff preview \u2500\u2500"));
2696
2727
  console.log(diff);
2697
2728
  console.log();
2698
2729
  } else {
2699
- const lines = newContent.split("\n");
2730
+ const lines = chunk.split("\n");
2700
2731
  const preview = lines.slice(0, 20).map((l) => theme.success(`+ ${l}`)).join("\n");
2701
2732
  const more = lines.length > 20 ? theme.dim(`
2702
2733
  ... (+${lines.length - 20} more lines)`) : "";
@@ -2917,31 +2948,10 @@ var subAgentGuard = {
2917
2948
  active: false
2918
2949
  };
2919
2950
 
2920
- // src/tools/arg-aliases.ts
2921
- function pickArg(args, canonical, aliases) {
2922
- if (args[canonical] !== void 0 && args[canonical] !== null) return args[canonical];
2923
- for (const alias of aliases) {
2924
- if (args[alias] !== void 0 && args[alias] !== null) return args[alias];
2925
- }
2926
- return void 0;
2927
- }
2928
- var OLD_STR_ALIASES = ["old_string", "oldStr", "oldString", "old_text", "search"];
2929
- var NEW_STR_ALIASES = ["new_string", "newStr", "newString", "new_text", "replace"];
2930
- var CONTENT_ALIASES = ["file_text", "text", "contents", "data"];
2931
- var INSERT_LINE_ALIASES = ["insert_line", "line", "after_line"];
2932
- var INSERT_CONTENT_ALIASES = ["content", "new_str", "text"];
2933
- function normalizeReplaceArgs(raw) {
2934
- const oldStr = pickArg(raw, "old_str", OLD_STR_ALIASES);
2935
- if (oldStr === void 0) return void 0;
2936
- return { old_str: oldStr, new_str: pickArg(raw, "new_str", NEW_STR_ALIASES) };
2937
- }
2938
- function describeReceivedKeys(args) {
2939
- const keys = Object.keys(args).filter((k) => args[k] !== void 0);
2940
- if (keys.length === 0) return " (no arguments received)";
2941
- return ` Received keys: ${keys.join(", ")}.`;
2942
- }
2943
-
2944
2951
  // src/tools/builtin/write-file.ts
2952
+ function countFileLines(filePath) {
2953
+ return readFileSync5(filePath, "utf-8").split("\n").length;
2954
+ }
2945
2955
  var writeFileTool = {
2946
2956
  definition: {
2947
2957
  name: "write_file",
@@ -3009,12 +3019,21 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
3009
3019
  } catch {
3010
3020
  }
3011
3021
  })();
3022
+ if (appendMode) {
3023
+ let total = "";
3024
+ try {
3025
+ const st = statSync3(filePath);
3026
+ total = `; file now ${countFileLines(filePath)} lines, ${st.size} bytes`;
3027
+ } catch {
3028
+ }
3029
+ return `File appended: ${filePath} (+${lines} lines, +${bytes} bytes${total})`;
3030
+ }
3012
3031
  return `File ${mode}: ${filePath} (${lines} lines, ${bytes} bytes)`;
3013
3032
  }
3014
3033
  };
3015
3034
 
3016
3035
  // src/tools/builtin/edit-file.ts
3017
- import { readFileSync as readFileSync5, existsSync as existsSync7 } from "fs";
3036
+ import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
3018
3037
 
3019
3038
  // src/tools/builtin/patch-apply.ts
3020
3039
  function parseUnifiedDiff(patch) {
@@ -3390,7 +3409,7 @@ Note: Path can be absolute or relative to cwd.`,
3390
3409
  `Refused: sub-agents cannot edit sensitive paths \u2014 ${verdict.reason}. If this is genuinely needed, ask the parent agent to perform the edit so the user can approve it.`
3391
3410
  );
3392
3411
  }
3393
- const original = readFileSync5(filePath, encoding);
3412
+ const original = readFileSync6(filePath, encoding);
3394
3413
  if (args["patch"] !== void 0) {
3395
3414
  const patchText = String(args["patch"] ?? "");
3396
3415
  const stopOnError = args["stop_on_error"] !== false;
@@ -3559,7 +3578,7 @@ function truncatePreview(str, maxLen = 80) {
3559
3578
  }
3560
3579
 
3561
3580
  // src/tools/builtin/list-dir.ts
3562
- import { readdirSync as readdirSync3, statSync as statSync3, existsSync as existsSync8 } from "fs";
3581
+ import { readdirSync as readdirSync3, statSync as statSync4, existsSync as existsSync8 } from "fs";
3563
3582
  import { join as join2, basename as basename4 } from "path";
3564
3583
  var listDirTool = {
3565
3584
  definition: {
@@ -3644,7 +3663,7 @@ function listRecursive(basePath, indent, recursive, lines) {
3644
3663
  }
3645
3664
  } else {
3646
3665
  try {
3647
- const stat = statSync3(join2(basePath, entry.name));
3666
+ const stat = statSync4(join2(basePath, entry.name));
3648
3667
  const size = formatSize(stat.size);
3649
3668
  lines.push(`${indent}\u{1F4C4} ${entry.name} (${size})`);
3650
3669
  } catch {
@@ -3660,7 +3679,7 @@ function formatSize(bytes) {
3660
3679
  }
3661
3680
 
3662
3681
  // src/tools/builtin/grep-files.ts
3663
- import { readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync4, existsSync as existsSync9 } from "fs";
3682
+ import { readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync5, existsSync as existsSync9 } from "fs";
3664
3683
  import { readFile } from "fs/promises";
3665
3684
  import { join as join3, relative } from "path";
3666
3685
  var grepFilesTool = {
@@ -3726,7 +3745,7 @@ Supports regex. Automatically skips node_modules, dist, .git directories.`,
3726
3745
  regex = new RegExp(escaped, ignoreCase ? "gi" : "g");
3727
3746
  }
3728
3747
  const results = [];
3729
- const stat = statSync4(rootPath);
3748
+ const stat = statSync5(rootPath);
3730
3749
  if (stat.isFile()) {
3731
3750
  searchInFile(rootPath, rootPath, regex, contextLines, maxResults, results);
3732
3751
  } else {
@@ -3813,7 +3832,7 @@ function collectFilePaths(rootPath, filePattern, maxFiles) {
3813
3832
  if (filePattern && !matchesFilePattern(entry.name, filePattern)) continue;
3814
3833
  const fullPath = join3(dirPath, entry.name);
3815
3834
  try {
3816
- if (statSync4(fullPath).size > 1e6) continue;
3835
+ if (statSync5(fullPath).size > 1e6) continue;
3817
3836
  } catch {
3818
3837
  continue;
3819
3838
  }
@@ -3859,14 +3878,14 @@ async function searchInFileAsync(fullPath, displayPath, regex, contextLines, max
3859
3878
  }
3860
3879
  function searchInFile(fullPath, displayPath, regex, contextLines, maxResults, results) {
3861
3880
  try {
3862
- const stat = statSync4(fullPath);
3881
+ const stat = statSync5(fullPath);
3863
3882
  if (stat.size > 1e6) return;
3864
3883
  } catch {
3865
3884
  return;
3866
3885
  }
3867
3886
  let content;
3868
3887
  try {
3869
- content = readFileSync6(fullPath, "utf-8");
3888
+ content = readFileSync7(fullPath, "utf-8");
3870
3889
  } catch {
3871
3890
  return;
3872
3891
  }
@@ -3897,7 +3916,7 @@ function searchInFile(fullPath, displayPath, regex, contextLines, maxResults, re
3897
3916
  }
3898
3917
 
3899
3918
  // src/tools/builtin/glob-files.ts
3900
- import { readdirSync as readdirSync5, statSync as statSync5, existsSync as existsSync10 } from "fs";
3919
+ import { readdirSync as readdirSync5, statSync as statSync6, existsSync as existsSync10 } from "fs";
3901
3920
  import { join as join4, relative as relative2, basename as basename5 } from "path";
3902
3921
  var globFilesTool = {
3903
3922
  definition: {
@@ -4016,7 +4035,7 @@ function collectMatchingFiles(dirPath, rootPath, regex, results, maxResults) {
4016
4035
  const relPath = relative2(rootPath, fullPath).replace(/\\/g, "/");
4017
4036
  if (regex.test(relPath) || regex.test(basename5(relPath))) {
4018
4037
  try {
4019
- const stat = statSync5(fullPath);
4038
+ const stat = statSync6(fullPath);
4020
4039
  results.push({ relPath, absPath: fullPath, mtime: stat.mtimeMs });
4021
4040
  } catch {
4022
4041
  results.push({ relPath, absPath: fullPath, mtime: 0 });
@@ -5202,7 +5221,7 @@ function formatResults2(query, data, _requested) {
5202
5221
  }
5203
5222
 
5204
5223
  // src/agents/agent-config.ts
5205
- import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync7 } from "fs";
5224
+ import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync8 } from "fs";
5206
5225
  import { join as join6 } from "path";
5207
5226
  import { homedir as homedir4 } from "os";
5208
5227
  var READ_ONLY_TOOLS2 = /* @__PURE__ */ new Set([
@@ -5304,7 +5323,7 @@ function loadAgentDir(dir, source) {
5304
5323
  if (!file.endsWith(".json")) continue;
5305
5324
  const path3 = join6(dir, file);
5306
5325
  try {
5307
- const parsed = JSON.parse(readFileSync7(path3, "utf-8"));
5326
+ const parsed = JSON.parse(readFileSync8(path3, "utf-8"));
5308
5327
  const cfg = parseAgentConfig(parsed, source, path3);
5309
5328
  if (cfg) out.push(cfg);
5310
5329
  } catch {
@@ -6304,7 +6323,7 @@ ${commitOutput.trim()}`;
6304
6323
  };
6305
6324
 
6306
6325
  // src/tools/builtin/notebook-edit.ts
6307
- import { readFileSync as readFileSync8, existsSync as existsSync13 } from "fs";
6326
+ import { readFileSync as readFileSync9, existsSync as existsSync13 } from "fs";
6308
6327
  import { writeFile } from "fs/promises";
6309
6328
  import { resolve as resolve6, extname as extname2 } from "path";
6310
6329
  var notebookEditTool = {
@@ -6362,7 +6381,7 @@ var notebookEditTool = {
6362
6381
  if (!existsSync13(absPath)) {
6363
6382
  throw new ToolError("notebook_edit", `Notebook not found: ${filePath}`);
6364
6383
  }
6365
- const raw = readFileSync8(absPath, "utf-8");
6384
+ const raw = readFileSync9(absPath, "utf-8");
6366
6385
  const nb = parseNotebook(raw);
6367
6386
  const cellIdx0 = cellIndexRaw - 1;
6368
6387
  undoStack.push(absPath, `notebook_edit (${action}): ${filePath}`);
@@ -7031,6 +7050,7 @@ export {
7031
7050
  rlInternal,
7032
7051
  groupCallsByPhase,
7033
7052
  runSafePhases,
7053
+ resolveWriteFileArgs,
7034
7054
  checkPermissionWithProfile,
7035
7055
  formatPermissionProfileWarning,
7036
7056
  checkNetworkPolicy,
@@ -3,7 +3,7 @@ import {
3
3
  detectsHallucinatedFileOp,
4
4
  parseToolCallArguments,
5
5
  schemaToJsonSchema
6
- } from "./chunk-XPNKMDBH.js";
6
+ } from "./chunk-FCPYMBTA.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,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-I7LBWY7E.js";
4
+ } from "./chunk-KRENSXPC.js";
5
5
 
6
6
  // src/cli/ci-format.ts
7
7
  var DEFAULT_CI_THRESHOLDS = {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TEST_TIMEOUT
3
- } from "./chunk-S5YGYXAE.js";
3
+ } from "./chunk-26C6YZ3A.js";
4
4
 
5
5
  // src/tools/builtin/run-tests.ts
6
6
  import { execSync, spawnSync } from "child_process";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CONFIG_DIR_NAME,
4
4
  PLUGINS_DIR_NAME
5
- } from "./chunk-I7LBWY7E.js";
5
+ } from "./chunk-KRENSXPC.js";
6
6
  import {
7
7
  atomicWriteFileSync
8
8
  } from "./chunk-IW3Q7AE5.js";
@@ -3,14 +3,14 @@ import {
3
3
  CI_COMMENT_MARKER,
4
4
  countSeverity,
5
5
  runCi
6
- } from "./chunk-3ERLNXT2.js";
7
- import "./chunk-PNQS67JC.js";
6
+ } from "./chunk-2BGNEVS5.js";
7
+ import "./chunk-VJP2GLW5.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
- import "./chunk-GDJII6TK.js";
10
- import "./chunk-XYNZVGUH.js";
11
- import "./chunk-XPNKMDBH.js";
9
+ import "./chunk-U2HN3EW6.js";
10
+ import "./chunk-K6WMQBUP.js";
11
+ import "./chunk-FCPYMBTA.js";
12
12
  import "./chunk-TU3L3PW7.js";
13
- import "./chunk-I7LBWY7E.js";
13
+ import "./chunk-KRENSXPC.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-PNQS67JC.js";
10
- import "./chunk-I7LBWY7E.js";
9
+ } from "./chunk-VJP2GLW5.js";
10
+ import "./chunk-KRENSXPC.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-I7LBWY7E.js";
41
+ } from "./chunk-KRENSXPC.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-GVLUGPIX.js";
6
- import "./chunk-GDJII6TK.js";
7
- import "./chunk-XYNZVGUH.js";
8
- import "./chunk-BIXQHN77.js";
9
- import "./chunk-XPNKMDBH.js";
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";
10
10
  import "./chunk-TU3L3PW7.js";
11
11
  import "./chunk-HOSJZMQS.js";
12
- import "./chunk-I7LBWY7E.js";
12
+ import "./chunk-KRENSXPC.js";
13
13
  import "./chunk-IW3Q7AE5.js";
14
14
  export {
15
15
  formatDoctorReport,