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
@@ -34,14 +34,14 @@ import {
34
34
  touchMemoryReferences,
35
35
  updateMemoryApproval,
36
36
  updateMemoryEntry
37
- } from "./chunk-BEER3VEB.js";
37
+ } from "./chunk-CLJKNKUN.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-GWXWAQVM.js";
44
+ } from "./chunk-XTA3LSPQ.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-S5YGYXAE.js";
76
+ } from "./chunk-26C6YZ3A.js";
77
77
  import {
78
78
  hasSemanticIndex,
79
79
  semanticSearch
@@ -92,7 +92,7 @@ import express from "express";
92
92
  import { createServer } from "http";
93
93
  import { WebSocketServer } from "ws";
94
94
  import { join as join25, dirname as dirname10, resolve as resolve10, relative as relative6, sep as sep4 } from "path";
95
- import { existsSync as existsSync30, readFileSync as readFileSync23, readdirSync as readdirSync15, statSync as statSync13, realpathSync as realpathSync3 } from "fs";
95
+ import { existsSync as existsSync30, readFileSync as readFileSync24, readdirSync as readdirSync15, statSync as statSync14, realpathSync as realpathSync3 } from "fs";
96
96
  import { networkInterfaces } from "os";
97
97
 
98
98
  // src/config/config-manager.ts
@@ -987,7 +987,8 @@ var ClaudeProvider = class extends BaseProvider {
987
987
  max_tokens: request.maxTokens ?? 8192,
988
988
  temperature,
989
989
  thinking
990
- });
990
+ // 非流式路径必须收 signal,否则 Ctrl+C 期间请求不可中断(同 openai-compatible 的同类遗漏)
991
+ }, { signal: request.signal });
991
992
  const content = this.extractContent(response.content);
992
993
  return {
993
994
  content,
@@ -1066,7 +1067,8 @@ var ClaudeProvider = class extends BaseProvider {
1066
1067
  max_tokens: request.maxTokens ?? 8192,
1067
1068
  temperature,
1068
1069
  thinking
1069
- });
1070
+ // 轮次耗尽的总结轮对所有 provider 都走这条非流式路径——漏 signal 则 Ctrl+C 无效
1071
+ }, { signal: request.signal });
1070
1072
  const usage = this.extractUsage(response.usage);
1071
1073
  const toolUseBlocks = response.content.filter(
1072
1074
  (b) => b.type === "tool_use"
@@ -2393,7 +2395,7 @@ async function consumeToolCallStream(stream, hooks = {}) {
2393
2395
  }
2394
2396
  }
2395
2397
  } catch (err) {
2396
- if (err instanceof Error && (err.name === "AbortError" || err.message.includes("aborted"))) {
2398
+ if (isAbortError(err)) {
2397
2399
  aborted = true;
2398
2400
  } else {
2399
2401
  throw err;
@@ -2487,6 +2489,10 @@ var BudgetWarner = class {
2487
2489
  return null;
2488
2490
  }
2489
2491
  };
2492
+ function isAbortError(err) {
2493
+ if (!(err instanceof Error)) return false;
2494
+ return err.name === "AbortError" || err.name === "APIUserAbortError" || err.message.includes("aborted");
2495
+ }
2490
2496
  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.";
2491
2497
  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.";
2492
2498
  function describeFinishReason(fr) {
@@ -2916,6 +2922,17 @@ var OpenAICompatibleProvider = class extends BaseProvider {
2916
2922
  }
2917
2923
  return msgs;
2918
2924
  }
2925
+ /**
2926
+ * 非流式请求必须把 `request.signal` 交给 SDK —— 否则 Ctrl+C 完全无效。
2927
+ *
2928
+ * 实战(v0.4.260):东叔按建议把 `timeouts.deepseek` 提到 900000 后出卷,第 3 轮等了
2929
+ * 11 分钟,**按 Ctrl+C 退不出去**。DeepSeek/Kimi 的 `enableStreamingToolCalls=false`
2930
+ * 让整个 agentic 循环都走 `chatWithTools()` 这条阻塞路径,而这里此前只传了 `timeout`、
2931
+ * 没传 `signal`:REPL 的 AbortController 一路传到 `request.signal` 就断在这一跳,
2932
+ * 请求无法取消;`consumeToolCallStream()` 又只在**事件之间**检查 aborted,而回退路径
2933
+ * 要等这个 await 返回后才会吐第一个事件 —— 于是中断只能等满超时(被我调高到 15 分钟)。
2934
+ * 两个流式方法本来就传了 signal,唯独两个非流式方法漏了,属同一处遗漏的两半。
2935
+ */
2919
2936
  async chat(request) {
2920
2937
  try {
2921
2938
  const response = await this.client.chat.completions.create({
@@ -2926,7 +2943,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
2926
2943
  stream: false,
2927
2944
  ...request.thinking ? { thinking: { type: "enabled" } } : {}
2928
2945
  }, {
2929
- timeout: request.timeout ?? this.defaultTimeout
2946
+ timeout: request.timeout ?? this.defaultTimeout,
2947
+ signal: request.signal
2930
2948
  });
2931
2949
  const firstChoice = response.choices?.[0];
2932
2950
  if (!firstChoice) {
@@ -3032,7 +3050,9 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3032
3050
  stream: false,
3033
3051
  ...request.thinking ? { thinking: { type: "enabled" } } : {}
3034
3052
  }, {
3035
- timeout: request.timeout ?? this.defaultTimeout
3053
+ timeout: request.timeout ?? this.defaultTimeout,
3054
+ // 非流式路径同样必须收 signal,否则 Ctrl+C 期间整个请求不可中断(见 chat() 上方注释)
3055
+ signal: request.signal
3036
3056
  });
3037
3057
  const firstChoice = response.choices?.[0];
3038
3058
  if (!firstChoice) {
@@ -3288,6 +3308,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3288
3308
  }
3289
3309
  }
3290
3310
  wrapError(err) {
3311
+ if (err instanceof OpenAI.APIUserAbortError) return err;
3312
+ if (err instanceof Error && err.name === "AbortError") return err;
3291
3313
  if (err instanceof OpenAI.AuthenticationError) {
3292
3314
  return new AuthError(this.info.id);
3293
3315
  }
@@ -6098,7 +6120,7 @@ ${content}`;
6098
6120
  };
6099
6121
 
6100
6122
  // src/tools/builtin/write-file.ts
6101
- import { appendFileSync, mkdirSync as mkdirSync6 } from "fs";
6123
+ import { appendFileSync, mkdirSync as mkdirSync6, readFileSync as readFileSync10, statSync as statSync4 } from "fs";
6102
6124
  import { dirname as dirname5 } from "path";
6103
6125
 
6104
6126
  // src/tools/executor.ts
@@ -6156,6 +6178,37 @@ async function runSafePhases(phase, execute, results, logTag = "executor") {
6156
6178
  return Date.now() - t0;
6157
6179
  }
6158
6180
 
6181
+ // src/tools/arg-aliases.ts
6182
+ function pickArg(args, canonical, aliases) {
6183
+ if (args[canonical] !== void 0 && args[canonical] !== null) return args[canonical];
6184
+ for (const alias of aliases) {
6185
+ if (args[alias] !== void 0 && args[alias] !== null) return args[alias];
6186
+ }
6187
+ return void 0;
6188
+ }
6189
+ var OLD_STR_ALIASES = ["old_string", "oldStr", "oldString", "old_text", "search"];
6190
+ var NEW_STR_ALIASES = ["new_string", "newStr", "newString", "new_text", "replace"];
6191
+ var CONTENT_ALIASES = ["file_text", "text", "contents", "data"];
6192
+ var INSERT_LINE_ALIASES = ["insert_line", "line", "after_line"];
6193
+ var INSERT_CONTENT_ALIASES = ["content", "new_str", "text"];
6194
+ function normalizeReplaceArgs(raw) {
6195
+ const oldStr = pickArg(raw, "old_str", OLD_STR_ALIASES);
6196
+ if (oldStr === void 0) return void 0;
6197
+ return { old_str: oldStr, new_str: pickArg(raw, "new_str", NEW_STR_ALIASES) };
6198
+ }
6199
+ function resolveWriteFileArgs(args) {
6200
+ return {
6201
+ path: String(pickArg(args, "path", ["file"]) ?? ""),
6202
+ content: String(pickArg(args, "content", CONTENT_ALIASES) ?? ""),
6203
+ append: String(args["append"] ?? "false").toLowerCase() === "true"
6204
+ };
6205
+ }
6206
+ function describeReceivedKeys(args) {
6207
+ const keys = Object.keys(args).filter((k) => args[k] !== void 0);
6208
+ if (keys.length === 0) return " (no arguments received)";
6209
+ return ` Received keys: ${keys.join(", ")}.`;
6210
+ }
6211
+
6159
6212
  // src/tools/diff-utils.ts
6160
6213
  import chalk from "chalk";
6161
6214
  function renderDiff(oldText, newText, opts = {}) {
@@ -7624,8 +7677,7 @@ var ToolExecutor = class {
7624
7677
  */
7625
7678
  printDiffPreview(call) {
7626
7679
  if (call.name === "write_file") {
7627
- const filePath = String(call.arguments["path"] ?? "");
7628
- const newContent = String(call.arguments["content"] ?? "");
7680
+ const { path: filePath, content: chunk, append } = resolveWriteFileArgs(call.arguments);
7629
7681
  if (!filePath) return;
7630
7682
  if (existsSync11(filePath)) {
7631
7683
  let oldContent;
@@ -7634,16 +7686,17 @@ var ToolExecutor = class {
7634
7686
  } catch {
7635
7687
  return;
7636
7688
  }
7689
+ const newContent = append ? oldContent + chunk : chunk;
7637
7690
  if (oldContent === newContent) {
7638
7691
  console.log(theme.dim(" (file content unchanged)"));
7639
7692
  return;
7640
7693
  }
7641
7694
  const diff = renderDiff(oldContent, newContent, { filePath, contextLines: 3 });
7642
- console.log(theme.dim(" \u2500\u2500 diff preview \u2500\u2500"));
7695
+ console.log(theme.dim(append ? " \u2500\u2500 append preview \u2500\u2500" : " \u2500\u2500 diff preview \u2500\u2500"));
7643
7696
  console.log(diff);
7644
7697
  console.log();
7645
7698
  } else {
7646
- const lines = newContent.split("\n");
7699
+ const lines = chunk.split("\n");
7647
7700
  const preview = lines.slice(0, 20).map((l) => theme.success(`+ ${l}`)).join("\n");
7648
7701
  const more = lines.length > 20 ? theme.dim(`
7649
7702
  ... (+${lines.length - 20} more lines)`) : "";
@@ -7864,31 +7917,10 @@ var subAgentGuard = {
7864
7917
  active: false
7865
7918
  };
7866
7919
 
7867
- // src/tools/arg-aliases.ts
7868
- function pickArg(args, canonical, aliases) {
7869
- if (args[canonical] !== void 0 && args[canonical] !== null) return args[canonical];
7870
- for (const alias of aliases) {
7871
- if (args[alias] !== void 0 && args[alias] !== null) return args[alias];
7872
- }
7873
- return void 0;
7874
- }
7875
- var OLD_STR_ALIASES = ["old_string", "oldStr", "oldString", "old_text", "search"];
7876
- var NEW_STR_ALIASES = ["new_string", "newStr", "newString", "new_text", "replace"];
7877
- var CONTENT_ALIASES = ["file_text", "text", "contents", "data"];
7878
- var INSERT_LINE_ALIASES = ["insert_line", "line", "after_line"];
7879
- var INSERT_CONTENT_ALIASES = ["content", "new_str", "text"];
7880
- function normalizeReplaceArgs(raw) {
7881
- const oldStr = pickArg(raw, "old_str", OLD_STR_ALIASES);
7882
- if (oldStr === void 0) return void 0;
7883
- return { old_str: oldStr, new_str: pickArg(raw, "new_str", NEW_STR_ALIASES) };
7884
- }
7885
- function describeReceivedKeys(args) {
7886
- const keys = Object.keys(args).filter((k) => args[k] !== void 0);
7887
- if (keys.length === 0) return " (no arguments received)";
7888
- return ` Received keys: ${keys.join(", ")}.`;
7889
- }
7890
-
7891
7920
  // src/tools/builtin/write-file.ts
7921
+ function countFileLines(filePath) {
7922
+ return readFileSync10(filePath, "utf-8").split("\n").length;
7923
+ }
7892
7924
  var writeFileTool = {
7893
7925
  definition: {
7894
7926
  name: "write_file",
@@ -7956,12 +7988,21 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
7956
7988
  } catch {
7957
7989
  }
7958
7990
  })();
7991
+ if (appendMode) {
7992
+ let total = "";
7993
+ try {
7994
+ const st = statSync4(filePath);
7995
+ total = `; file now ${countFileLines(filePath)} lines, ${st.size} bytes`;
7996
+ } catch {
7997
+ }
7998
+ return `File appended: ${filePath} (+${lines} lines, +${bytes} bytes${total})`;
7999
+ }
7959
8000
  return `File ${mode}: ${filePath} (${lines} lines, ${bytes} bytes)`;
7960
8001
  }
7961
8002
  };
7962
8003
 
7963
8004
  // src/tools/builtin/edit-file.ts
7964
- import { readFileSync as readFileSync10, existsSync as existsSync12 } from "fs";
8005
+ import { readFileSync as readFileSync11, existsSync as existsSync12 } from "fs";
7965
8006
 
7966
8007
  // src/tools/builtin/patch-apply.ts
7967
8008
  function parseUnifiedDiff(patch) {
@@ -8337,7 +8378,7 @@ Note: Path can be absolute or relative to cwd.`,
8337
8378
  `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.`
8338
8379
  );
8339
8380
  }
8340
- const original = readFileSync10(filePath, encoding);
8381
+ const original = readFileSync11(filePath, encoding);
8341
8382
  if (args["patch"] !== void 0) {
8342
8383
  const patchText = String(args["patch"] ?? "");
8343
8384
  const stopOnError = args["stop_on_error"] !== false;
@@ -8506,7 +8547,7 @@ function truncatePreview(str, maxLen = 80) {
8506
8547
  }
8507
8548
 
8508
8549
  // src/tools/builtin/list-dir.ts
8509
- import { readdirSync as readdirSync4, statSync as statSync4, existsSync as existsSync13 } from "fs";
8550
+ import { readdirSync as readdirSync4, statSync as statSync5, existsSync as existsSync13 } from "fs";
8510
8551
  import { join as join7, basename as basename4 } from "path";
8511
8552
  var listDirTool = {
8512
8553
  definition: {
@@ -8591,7 +8632,7 @@ function listRecursive(basePath, indent, recursive, lines) {
8591
8632
  }
8592
8633
  } else {
8593
8634
  try {
8594
- const stat = statSync4(join7(basePath, entry.name));
8635
+ const stat = statSync5(join7(basePath, entry.name));
8595
8636
  const size = formatSize(stat.size);
8596
8637
  lines.push(`${indent}\u{1F4C4} ${entry.name} (${size})`);
8597
8638
  } catch {
@@ -8607,7 +8648,7 @@ function formatSize(bytes) {
8607
8648
  }
8608
8649
 
8609
8650
  // src/tools/builtin/grep-files.ts
8610
- import { readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync5, existsSync as existsSync14 } from "fs";
8651
+ import { readdirSync as readdirSync5, readFileSync as readFileSync12, statSync as statSync6, existsSync as existsSync14 } from "fs";
8611
8652
  import { readFile } from "fs/promises";
8612
8653
  import { join as join8, relative } from "path";
8613
8654
  var grepFilesTool = {
@@ -8673,7 +8714,7 @@ Supports regex. Automatically skips node_modules, dist, .git directories.`,
8673
8714
  regex = new RegExp(escaped, ignoreCase ? "gi" : "g");
8674
8715
  }
8675
8716
  const results = [];
8676
- const stat = statSync5(rootPath);
8717
+ const stat = statSync6(rootPath);
8677
8718
  if (stat.isFile()) {
8678
8719
  searchInFile(rootPath, rootPath, regex, contextLines, maxResults, results);
8679
8720
  } else {
@@ -8760,7 +8801,7 @@ function collectFilePaths(rootPath, filePattern, maxFiles) {
8760
8801
  if (filePattern && !matchesFilePattern(entry.name, filePattern)) continue;
8761
8802
  const fullPath = join8(dirPath, entry.name);
8762
8803
  try {
8763
- if (statSync5(fullPath).size > 1e6) continue;
8804
+ if (statSync6(fullPath).size > 1e6) continue;
8764
8805
  } catch {
8765
8806
  continue;
8766
8807
  }
@@ -8806,14 +8847,14 @@ async function searchInFileAsync(fullPath, displayPath2, regex, contextLines, ma
8806
8847
  }
8807
8848
  function searchInFile(fullPath, displayPath2, regex, contextLines, maxResults, results) {
8808
8849
  try {
8809
- const stat = statSync5(fullPath);
8850
+ const stat = statSync6(fullPath);
8810
8851
  if (stat.size > 1e6) return;
8811
8852
  } catch {
8812
8853
  return;
8813
8854
  }
8814
8855
  let content;
8815
8856
  try {
8816
- content = readFileSync11(fullPath, "utf-8");
8857
+ content = readFileSync12(fullPath, "utf-8");
8817
8858
  } catch {
8818
8859
  return;
8819
8860
  }
@@ -8844,7 +8885,7 @@ function searchInFile(fullPath, displayPath2, regex, contextLines, maxResults, r
8844
8885
  }
8845
8886
 
8846
8887
  // src/tools/builtin/glob-files.ts
8847
- import { readdirSync as readdirSync6, statSync as statSync6, existsSync as existsSync15 } from "fs";
8888
+ import { readdirSync as readdirSync6, statSync as statSync7, existsSync as existsSync15 } from "fs";
8848
8889
  import { join as join9, relative as relative2, basename as basename5 } from "path";
8849
8890
  var globFilesTool = {
8850
8891
  definition: {
@@ -8963,7 +9004,7 @@ function collectMatchingFiles(dirPath, rootPath, regex, results, maxResults) {
8963
9004
  const relPath = relative2(rootPath, fullPath).replace(/\\/g, "/");
8964
9005
  if (regex.test(relPath) || regex.test(basename5(relPath))) {
8965
9006
  try {
8966
- const stat = statSync6(fullPath);
9007
+ const stat = statSync7(fullPath);
8967
9008
  results.push({ relPath, absPath: fullPath, mtime: stat.mtimeMs });
8968
9009
  } catch {
8969
9010
  results.push({ relPath, absPath: fullPath, mtime: 0 });
@@ -10149,12 +10190,12 @@ function formatResults2(query, data, _requested) {
10149
10190
  }
10150
10191
 
10151
10192
  // src/agents/agent-config.ts
10152
- import { existsSync as existsSync17, readdirSync as readdirSync8, readFileSync as readFileSync13 } from "fs";
10193
+ import { existsSync as existsSync17, readdirSync as readdirSync8, readFileSync as readFileSync14 } from "fs";
10153
10194
  import { join as join12 } from "path";
10154
10195
  import { homedir as homedir6 } from "os";
10155
10196
 
10156
10197
  // src/plugins/plugin-manager.ts
10157
- import { existsSync as existsSync16, mkdirSync as mkdirSync8, readdirSync as readdirSync7, readFileSync as readFileSync12, realpathSync as realpathSync2, cpSync, rmSync, statSync as statSync7 } from "fs";
10198
+ import { existsSync as existsSync16, mkdirSync as mkdirSync8, readdirSync as readdirSync7, readFileSync as readFileSync13, realpathSync as realpathSync2, cpSync, rmSync, statSync as statSync8 } from "fs";
10158
10199
  import { basename as basename6, dirname as dirname7, join as join11, relative as relative3, resolve as resolve6, sep as sep3 } from "path";
10159
10200
  import { createHash as createHash2 } from "crypto";
10160
10201
  import { z as z2 } from "zod";
@@ -10227,7 +10268,7 @@ function loadState(configDir) {
10227
10268
  const file = statePath(configDir);
10228
10269
  if (!existsSync16(file)) return { version: 2, plugins: [] };
10229
10270
  try {
10230
- const parsed = JSON.parse(readFileSync12(file, "utf-8"));
10271
+ const parsed = JSON.parse(readFileSync13(file, "utf-8"));
10231
10272
  const rawPlugins = Array.isArray(parsed.plugins) ? parsed.plugins : [];
10232
10273
  return { version: 2, plugins: rawPlugins.map((p) => migrateEntry(p)) };
10233
10274
  } catch {
@@ -10318,7 +10359,7 @@ function hashPluginContent(pluginDir, manifest) {
10318
10359
  const sorted = [...assetRels].sort();
10319
10360
  const hasher = createHash2("sha256");
10320
10361
  const manifestPath = join11(resolvedDir, MANIFEST_RELATIVE);
10321
- hasher.update(normalizeForHash(readFileSync12(manifestPath)));
10362
+ hasher.update(normalizeForHash(readFileSync13(manifestPath)));
10322
10363
  for (const rel of sorted) {
10323
10364
  const abs = resolve6(resolvedDir, rel);
10324
10365
  if (!abs.startsWith(resolvedDir + sep3)) {
@@ -10331,14 +10372,14 @@ function hashPluginContent(pluginDir, manifest) {
10331
10372
  continue;
10332
10373
  }
10333
10374
  try {
10334
- if (statSync7(realPath).isDirectory()) continue;
10375
+ if (statSync8(realPath).isDirectory()) continue;
10335
10376
  } catch {
10336
10377
  continue;
10337
10378
  }
10338
10379
  if (!realPath.startsWith(resolvedDir + sep3)) {
10339
10380
  throw new Error(`plugin asset symlink escapes plugin dir: ${rel} \u2192 ${realPath}`);
10340
10381
  }
10341
- hasher.update(normalizeForHash(readFileSync12(abs)));
10382
+ hasher.update(normalizeForHash(readFileSync13(abs)));
10342
10383
  }
10343
10384
  return hasher.digest("hex");
10344
10385
  }
@@ -10346,11 +10387,11 @@ function effectiveHash(entry) {
10346
10387
  return entry.contentHash ?? entry.hash ?? "";
10347
10388
  }
10348
10389
  function readPluginManifest(manifestPath) {
10349
- return PluginManifestSchema.parse(JSON.parse(readFileSync12(manifestPath, "utf-8")));
10390
+ return PluginManifestSchema.parse(JSON.parse(readFileSync13(manifestPath, "utf-8")));
10350
10391
  }
10351
10392
  function findPluginSourceDir(inputPath) {
10352
10393
  const abs = resolve6(inputPath);
10353
- const direct = statSync7(abs).isDirectory() ? abs : dirname7(abs);
10394
+ const direct = statSync8(abs).isDirectory() ? abs : dirname7(abs);
10354
10395
  if (existsSync16(pluginManifestPath(direct))) return direct;
10355
10396
  const nested = join11(direct, ".aicli-plugin");
10356
10397
  if (existsSync16(join11(nested, "plugin.json"))) return direct;
@@ -10425,7 +10466,7 @@ function listInstalledPlugins(configDir) {
10425
10466
  for (const entry of readdirSync7(root)) {
10426
10467
  const dir = join11(root, entry);
10427
10468
  try {
10428
- if (!statSync7(dir).isDirectory()) continue;
10469
+ if (!statSync8(dir).isDirectory()) continue;
10429
10470
  } catch {
10430
10471
  continue;
10431
10472
  }
@@ -10470,7 +10511,7 @@ function uniqueDirs(plugin, rels) {
10470
10511
  for (const rel of rels) {
10471
10512
  const abs = resolve6(plugin.dir, rel);
10472
10513
  if (!abs.startsWith(resolve6(plugin.dir))) continue;
10473
- if (existsSync16(abs)) dirs.add(statSync7(abs).isDirectory() ? abs : dirname7(abs));
10514
+ if (existsSync16(abs)) dirs.add(statSync8(abs).isDirectory() ? abs : dirname7(abs));
10474
10515
  }
10475
10516
  return [...dirs];
10476
10517
  }
@@ -10639,7 +10680,7 @@ function loadAgentDir(dir, source) {
10639
10680
  if (!file.endsWith(".json")) continue;
10640
10681
  const path3 = join12(dir, file);
10641
10682
  try {
10642
- const parsed = JSON.parse(readFileSync13(path3, "utf-8"));
10683
+ const parsed = JSON.parse(readFileSync14(path3, "utf-8"));
10643
10684
  const cfg = parseAgentConfig(parsed, source, path3);
10644
10685
  if (cfg) out.push(cfg);
10645
10686
  } catch {
@@ -11639,7 +11680,7 @@ ${commitOutput.trim()}`;
11639
11680
  };
11640
11681
 
11641
11682
  // src/tools/builtin/notebook-edit.ts
11642
- import { readFileSync as readFileSync14, existsSync as existsSync19 } from "fs";
11683
+ import { readFileSync as readFileSync15, existsSync as existsSync19 } from "fs";
11643
11684
  import { writeFile } from "fs/promises";
11644
11685
  import { resolve as resolve7, extname as extname2 } from "path";
11645
11686
  var notebookEditTool = {
@@ -11697,7 +11738,7 @@ var notebookEditTool = {
11697
11738
  if (!existsSync19(absPath)) {
11698
11739
  throw new ToolError("notebook_edit", `Notebook not found: ${filePath}`);
11699
11740
  }
11700
- const raw = readFileSync14(absPath, "utf-8");
11741
+ const raw = readFileSync15(absPath, "utf-8");
11701
11742
  const nb = parseNotebook(raw);
11702
11743
  const cellIdx0 = cellIndexRaw - 1;
11703
11744
  undoStack.push(absPath, `notebook_edit (${action}): ${filePath}`);
@@ -12866,11 +12907,11 @@ var McpManager = class {
12866
12907
  };
12867
12908
 
12868
12909
  // src/skills/manager.ts
12869
- import { existsSync as existsSync21, readdirSync as readdirSync10, mkdirSync as mkdirSync10, statSync as statSync8 } from "fs";
12910
+ import { existsSync as existsSync21, readdirSync as readdirSync10, mkdirSync as mkdirSync10, statSync as statSync9 } from "fs";
12870
12911
  import { join as join16 } from "path";
12871
12912
 
12872
12913
  // src/skills/types.ts
12873
- import { readFileSync as readFileSync15 } from "fs";
12914
+ import { readFileSync as readFileSync16 } from "fs";
12874
12915
  import { basename as basename7 } from "path";
12875
12916
  function parseSimpleYaml(yaml) {
12876
12917
  const result = {};
@@ -12892,7 +12933,7 @@ function parseYamlArray(value) {
12892
12933
  function parseSkillFile(filePath) {
12893
12934
  let raw;
12894
12935
  try {
12895
- raw = readFileSync15(filePath, "utf-8");
12936
+ raw = readFileSync16(filePath, "utf-8");
12896
12937
  } catch {
12897
12938
  return null;
12898
12939
  }
@@ -12962,7 +13003,7 @@ var SkillManager = class {
12962
13003
  filePath = fullPath;
12963
13004
  } else {
12964
13005
  try {
12965
- if (statSync8(fullPath).isDirectory()) {
13006
+ if (statSync9(fullPath).isDirectory()) {
12966
13007
  const skillMd = join16(fullPath, "SKILL.md");
12967
13008
  if (existsSync21(skillMd)) filePath = skillMd;
12968
13009
  else continue;
@@ -13023,7 +13064,7 @@ var SkillManager = class {
13023
13064
  // src/web/tool-executor-web.ts
13024
13065
  import { randomUUID as randomUUID2 } from "crypto";
13025
13066
  import { tmpdir as tmpdir2 } from "os";
13026
- import { existsSync as existsSync22, readFileSync as readFileSync16 } from "fs";
13067
+ import { existsSync as existsSync22, readFileSync as readFileSync17 } from "fs";
13027
13068
  var ToolExecutorWeb = class _ToolExecutorWeb {
13028
13069
  constructor(registry, ws) {
13029
13070
  this.registry = registry;
@@ -13162,18 +13203,17 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13162
13203
  }
13163
13204
  getDiffPreview(call) {
13164
13205
  if (call.name === "write_file") {
13165
- const filePath = String(call.arguments["path"] ?? "");
13166
- const newContent = String(call.arguments["content"] ?? "");
13206
+ const { path: filePath, content: chunk, append } = resolveWriteFileArgs(call.arguments);
13167
13207
  if (filePath && existsSync22(filePath)) {
13168
13208
  try {
13169
- const old = readFileSync16(filePath, "utf-8");
13170
- return renderDiff(old, newContent, { filePath });
13209
+ const old = readFileSync17(filePath, "utf-8");
13210
+ return renderDiff(old, append ? old + chunk : chunk, { filePath });
13171
13211
  } catch {
13172
13212
  }
13173
13213
  }
13174
- const lines = newContent.split("\n").slice(0, 20);
13175
- return lines.map((l) => `+ ${l}`).join("\n") + (newContent.split("\n").length > 20 ? `
13176
- ... (+${newContent.split("\n").length - 20} more lines)` : "");
13214
+ const lines = chunk.split("\n").slice(0, 20);
13215
+ return lines.map((l) => `+ ${l}`).join("\n") + (chunk.split("\n").length > 20 ? `
13216
+ ... (+${chunk.split("\n").length - 20} more lines)` : "");
13177
13217
  }
13178
13218
  if (call.name === "edit_file") {
13179
13219
  const oldStr = String(call.arguments["old_str"] ?? "");
@@ -13479,7 +13519,7 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13479
13519
  };
13480
13520
 
13481
13521
  // src/repl/dev-state.ts
13482
- import { existsSync as existsSync23, readFileSync as readFileSync17, unlinkSync as unlinkSync5, mkdirSync as mkdirSync11 } from "fs";
13522
+ import { existsSync as existsSync23, readFileSync as readFileSync18, unlinkSync as unlinkSync5, mkdirSync as mkdirSync11 } from "fs";
13483
13523
  import { join as join17 } from "path";
13484
13524
  import { homedir as homedir8 } from "os";
13485
13525
  function getDevStatePath() {
@@ -13488,7 +13528,7 @@ function getDevStatePath() {
13488
13528
  function loadDevState() {
13489
13529
  const path3 = getDevStatePath();
13490
13530
  if (!existsSync23(path3)) return null;
13491
- const content = readFileSync17(path3, "utf-8").trim();
13531
+ const content = readFileSync18(path3, "utf-8").trim();
13492
13532
  return content || null;
13493
13533
  }
13494
13534
 
@@ -13754,7 +13794,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
13754
13794
  }
13755
13795
 
13756
13796
  // src/core/context-files.ts
13757
- import { existsSync as existsSync24, readFileSync as readFileSync18 } from "fs";
13797
+ import { existsSync as existsSync24, readFileSync as readFileSync19 } from "fs";
13758
13798
  import { join as join18, relative as relative4, resolve as resolve8 } from "path";
13759
13799
  function uniqueNonEmpty(values) {
13760
13800
  const seen = /* @__PURE__ */ new Set();
@@ -13785,7 +13825,7 @@ function readContextFile(level, filePath, cwd, maxBytes) {
13785
13825
  const name = filePath.split(/[\\/]/).pop() ?? filePath;
13786
13826
  const shown = displayPath(filePath, cwd);
13787
13827
  try {
13788
- const raw = readFileSync18(filePath);
13828
+ const raw = readFileSync19(filePath);
13789
13829
  const byteCount = raw.byteLength;
13790
13830
  if (byteCount === 0) {
13791
13831
  return {
@@ -13915,7 +13955,7 @@ import { mkdirSync as mkdirSync14, createWriteStream as createWriteStream2 } fro
13915
13955
  import { dirname as dirname9 } from "path";
13916
13956
 
13917
13957
  // src/repl/commands/project-init.ts
13918
- import { existsSync as existsSync25, readFileSync as readFileSync19, readdirSync as readdirSync11, statSync as statSync9 } from "fs";
13958
+ import { existsSync as existsSync25, readFileSync as readFileSync20, readdirSync as readdirSync11, statSync as statSync10 } from "fs";
13919
13959
  import { join as join19 } from "path";
13920
13960
  var SCAN_SKIP_DIRS = /* @__PURE__ */ new Set([
13921
13961
  "node_modules",
@@ -13960,11 +14000,11 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
13960
14000
  const sorted = filtered.sort((a, b) => {
13961
14001
  let aIsDir = false, bIsDir = false;
13962
14002
  try {
13963
- aIsDir = statSync9(join19(d, a)).isDirectory();
14003
+ aIsDir = statSync10(join19(d, a)).isDirectory();
13964
14004
  } catch {
13965
14005
  }
13966
14006
  try {
13967
- bIsDir = statSync9(join19(d, b)).isDirectory();
14007
+ bIsDir = statSync10(join19(d, b)).isDirectory();
13968
14008
  } catch {
13969
14009
  }
13970
14010
  if (aIsDir !== bIsDir) return aIsDir ? -1 : 1;
@@ -13977,7 +14017,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
13977
14017
  const connector = isLast ? "+-- " : "|-- ";
13978
14018
  let isDir;
13979
14019
  try {
13980
- isDir = statSync9(fullPath).isDirectory();
14020
+ isDir = statSync10(fullPath).isDirectory();
13981
14021
  } catch {
13982
14022
  continue;
13983
14023
  }
@@ -14026,7 +14066,7 @@ function scanProject(cwd) {
14026
14066
  info.type = "node";
14027
14067
  info.language = check("tsconfig.json") ? "TypeScript" : "JavaScript";
14028
14068
  try {
14029
- const pkg = JSON.parse(readFileSync19(join19(cwd, "package.json"), "utf-8"));
14069
+ const pkg = JSON.parse(readFileSync20(join19(cwd, "package.json"), "utf-8"));
14030
14070
  const scripts = pkg.scripts ?? {};
14031
14071
  info.buildCommand = scripts.build ? "npm run build" : void 0;
14032
14072
  info.testCommand = scripts.test ? "npm test" : void 0;
@@ -14801,7 +14841,7 @@ async function handlePlan(args, ctx) {
14801
14841
  }
14802
14842
 
14803
14843
  // src/web/commands/_shared.ts
14804
- import { existsSync as existsSync28, readFileSync as readFileSync21, writeFileSync as writeFileSync3, mkdirSync as mkdirSync13, readdirSync as readdirSync13, statSync as statSync12, createWriteStream } from "fs";
14844
+ import { existsSync as existsSync28, readFileSync as readFileSync22, writeFileSync as writeFileSync3, mkdirSync as mkdirSync13, readdirSync as readdirSync13, statSync as statSync13, createWriteStream } from "fs";
14805
14845
  import { join as join23, resolve as resolve9, dirname as dirname8 } from "path";
14806
14846
 
14807
14847
  // src/cli/review-prompts.ts
@@ -14874,7 +14914,7 @@ function readGitDiff(options = {}) {
14874
14914
  }
14875
14915
 
14876
14916
  // src/diagnostics/doctor-report.ts
14877
- import { existsSync as existsSync27, statSync as statSync11 } from "fs";
14917
+ import { existsSync as existsSync27, statSync as statSync12 } from "fs";
14878
14918
  import { join as join22 } from "path";
14879
14919
  import { arch as arch2, platform as platform7, release as release2 } from "os";
14880
14920
 
@@ -14883,8 +14923,8 @@ import {
14883
14923
  existsSync as existsSync26,
14884
14924
  mkdirSync as mkdirSync12,
14885
14925
  readdirSync as readdirSync12,
14886
- readFileSync as readFileSync20,
14887
- statSync as statSync10,
14926
+ readFileSync as readFileSync21,
14927
+ statSync as statSync11,
14888
14928
  unlinkSync as unlinkSync6,
14889
14929
  writeFileSync as writeFileSync2
14890
14930
  } from "fs";
@@ -14913,8 +14953,8 @@ function listRecentCrashes(limit = 10, configDir) {
14913
14953
  if (!name.startsWith(CRASH_LOG_PREFIX) || !name.endsWith(".log")) continue;
14914
14954
  const full = join21(dir, name);
14915
14955
  try {
14916
- const st = statSync10(full);
14917
- const head = readFileSync20(full, "utf-8").split("\n").slice(0, 20);
14956
+ const st = statSync11(full);
14957
+ const head = readFileSync21(full, "utf-8").split("\n").slice(0, 20);
14918
14958
  const tsLine = head.find((l) => l.startsWith("timestamp:"));
14919
14959
  const kindLine = head.find((l) => l.startsWith("kind:"));
14920
14960
  const msgIdx = head.findIndex((l) => l.trim() === "## message");
@@ -14954,7 +14994,7 @@ function getConfigDirUsage(configDir) {
14954
14994
  }
14955
14995
  function dirSize(path3) {
14956
14996
  try {
14957
- const st = statSync10(path3);
14997
+ const st = statSync11(path3);
14958
14998
  if (st.isFile()) return st.size;
14959
14999
  if (!st.isDirectory()) return 0;
14960
15000
  let sum = 0;
@@ -14973,7 +15013,7 @@ function checkFile(label, path3) {
14973
15013
  let sizeBytes = null;
14974
15014
  if (exists) {
14975
15015
  try {
14976
- sizeBytes = statSync11(path3).size;
15016
+ sizeBytes = statSync12(path3).size;
14977
15017
  } catch {
14978
15018
  }
14979
15019
  }
@@ -15295,7 +15335,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
15295
15335
  Cost: ${formatCost(cost)}` : "";
15296
15336
  let memoryLine = "";
15297
15337
  try {
15298
- const { countPendingMemories } = await import("./persistent-memory-PAHA4R7U.js");
15338
+ const { countPendingMemories } = await import("./persistent-memory-DUFOZTDV.js");
15299
15339
  const pending = countPendingMemories(ctx.config.getConfigDir());
15300
15340
  if (pending > 0) memoryLine = `
15301
15341
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -16104,7 +16144,7 @@ async function handleSecurityReview(args, ctx) {
16104
16144
  async function handleTest(args, ctx) {
16105
16145
  ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
16106
16146
  try {
16107
- const { executeTests } = await import("./run-tests-WWJHCLFZ.js");
16147
+ const { executeTests } = await import("./run-tests-S2RLPMCR.js");
16108
16148
  const argStr = args.join(" ").trim();
16109
16149
  let testArgs = {};
16110
16150
  if (argStr) {
@@ -16136,7 +16176,7 @@ async function handleDiff(args, ctx) {
16136
16176
  for (const [filePath, { earliest }] of fileMap) {
16137
16177
  const currentContent = existsSync28(filePath) ? (() => {
16138
16178
  try {
16139
- return readFileSync21(filePath, "utf-8");
16179
+ return readFileSync22(filePath, "utf-8");
16140
16180
  } catch {
16141
16181
  return null;
16142
16182
  }
@@ -16368,7 +16408,7 @@ async function handleMemory(args, ctx) {
16368
16408
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
16369
16409
  } else if (sub === "export") {
16370
16410
  if (args[1] === "md") {
16371
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-PAHA4R7U.js");
16411
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-DUFOZTDV.js");
16372
16412
  ctx.send({
16373
16413
  type: "export_data",
16374
16414
  format: "md",
@@ -16410,7 +16450,7 @@ Use /add-dir remove to clear.` : "No directories added.\nUsage: /add-dir <path>
16410
16450
  ctx.send({ type: "error", message: `Directory not found: ${dirPath}` });
16411
16451
  return;
16412
16452
  }
16413
- if (!statSync12(dirPath).isDirectory()) {
16453
+ if (!statSync13(dirPath).isDirectory()) {
16414
16454
  ctx.send({ type: "error", message: `Not a directory: ${dirPath}` });
16415
16455
  return;
16416
16456
  }
@@ -18281,7 +18321,7 @@ async function setupProxy(configProxy) {
18281
18321
  }
18282
18322
 
18283
18323
  // src/web/auth.ts
18284
- import { existsSync as existsSync29, readFileSync as readFileSync22, writeFileSync as writeFileSync4, mkdirSync as mkdirSync15, readdirSync as readdirSync14, copyFileSync } from "fs";
18324
+ import { existsSync as existsSync29, readFileSync as readFileSync23, writeFileSync as writeFileSync4, mkdirSync as mkdirSync15, readdirSync as readdirSync14, copyFileSync } from "fs";
18285
18325
  import { isAbsolute as isAbsolute3, join as join24, relative as relative5 } from "path";
18286
18326
  import { createHmac, randomBytes, timingSafeEqual, pbkdf2Sync } from "crypto";
18287
18327
  var USERS_FILE = "users.json";
@@ -18482,7 +18522,7 @@ var AuthManager = class {
18482
18522
  const globalConfig = join24(this.baseDir, "config.json");
18483
18523
  if (existsSync29(globalConfig)) {
18484
18524
  try {
18485
- const content = readFileSync22(globalConfig, "utf-8");
18525
+ const content = readFileSync23(globalConfig, "utf-8");
18486
18526
  writeFileSync4(join24(userDir, "config.json"), content, "utf-8");
18487
18527
  } catch {
18488
18528
  }
@@ -18490,7 +18530,7 @@ var AuthManager = class {
18490
18530
  const globalMemory = join24(this.baseDir, "memory.md");
18491
18531
  if (existsSync29(globalMemory)) {
18492
18532
  try {
18493
- const content = readFileSync22(globalMemory, "utf-8");
18533
+ const content = readFileSync23(globalMemory, "utf-8");
18494
18534
  writeFileSync4(join24(userDir, "memory.md"), content, "utf-8");
18495
18535
  } catch {
18496
18536
  }
@@ -18515,7 +18555,7 @@ var AuthManager = class {
18515
18555
  loadOrCreate() {
18516
18556
  if (existsSync29(this.usersFile)) {
18517
18557
  try {
18518
- const parsed = JSON.parse(readFileSync22(this.usersFile, "utf-8"));
18558
+ const parsed = JSON.parse(readFileSync23(this.usersFile, "utf-8"));
18519
18559
  if (!this.isValidUsersDB(parsed)) {
18520
18560
  throw new Error("database structure is invalid");
18521
18561
  }
@@ -18892,7 +18932,7 @@ async function startWebServer(options = {}) {
18892
18932
  res.status(404).json({ error: "Session not found" });
18893
18933
  return;
18894
18934
  }
18895
- const data = JSON.parse(readFileSync23(filePath, "utf-8"));
18935
+ const data = JSON.parse(readFileSync24(filePath, "utf-8"));
18896
18936
  res.json({ session: data });
18897
18937
  } catch (err) {
18898
18938
  res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
@@ -18918,12 +18958,12 @@ async function startWebServer(options = {}) {
18918
18958
  return;
18919
18959
  }
18920
18960
  try {
18921
- const stat = statSync13(fullPath);
18961
+ const stat = statSync14(fullPath);
18922
18962
  if (stat.size > 512 * 1024) {
18923
18963
  res.json({ error: `File too large (${(stat.size / 1024).toFixed(0)} KB, max 512 KB)` });
18924
18964
  return;
18925
18965
  }
18926
- const content = readFileSync23(fullPath, "utf-8");
18966
+ const content = readFileSync24(fullPath, "utf-8");
18927
18967
  res.json({ content, size: stat.size });
18928
18968
  } catch {
18929
18969
  res.json({ error: "Cannot read file" });
@@ -19188,7 +19228,7 @@ function loadProjectMcpConfig() {
19188
19228
  const configPath = join25(projectRoot, MCP_PROJECT_CONFIG_NAME);
19189
19229
  if (!existsSync30(configPath)) return null;
19190
19230
  try {
19191
- const raw = JSON.parse(readFileSync23(configPath, "utf-8"));
19231
+ const raw = JSON.parse(readFileSync24(configPath, "utf-8"));
19192
19232
  return raw.mcpServers ?? raw;
19193
19233
  } catch {
19194
19234
  return null;