deepseeker-code 1.0.51 → 1.0.52

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.mjs +483 -390
  3. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -207,7 +207,7 @@ ${dim} \u8FD0\u884C npm i -g deepseeker-code@latest \u66F4\u65B0${reset}
207
207
  return new Date(t).toLocaleDateString("zh-CN");
208
208
  },
209
209
  langCurrent: () => `\u5F53\u524D\u754C\u9762\u8BED\u8A00\uFF1A\u4E2D\u6587\uFF08/lang en \u5207\u6362\u82F1\u6587\uFF09`,
210
- langSet: (l) => `\u754C\u9762\u8BED\u8A00\u5DF2\u5207\u6362\uFF1A${l === "zh" ? "\u4E2D\u6587" : "English"}`,
210
+ langSet: (l) => `\u754C\u9762\u8BED\u8A00\u5DF2\u5207\u6362\uFF1A${l === "zh" ? "\u4E2D\u6587" : "English"}\uFF08AI \u56DE\u590D\u8BED\u8A00\u9ED8\u8BA4\u8DDF\u968F\u6BCF\u8F6E\u63D0\u95EE\u81EA\u52A8\u5224\u65AD\uFF1B\u7EAF\u4EE3\u7801/\u65E0\u6587\u5B57\u8F6E\u6B21\u4EE5\u6B64\u8BED\u8A00\u4E3A\u51C6\uFF09`,
211
211
  langInvalid: (arg) => `\u65E0\u6548\u8BED\u8A00\uFF1A${arg}\uFF08\u53EF\u9009\uFF1Azh \u4E2D\u6587 / en English\uFF09`,
212
212
  outputStyleNone: () => `\u672A\u52A0\u8F7D\u4EFB\u4F55\u8F93\u51FA\u98CE\u683C\uFF08\u5728 ~/.deepseeker-code/output-styles/ \u653E <name>.md\uFF09\u3002`,
213
213
  outputStyleCurrent: (cur) => `\u5F53\u524D\u8F93\u51FA\u98CE\u683C\uFF1A${cur ?? "\u9ED8\u8BA4\uFF08\u4E2D\u6027\uFF09"}\u3002\u53EF\u7528\uFF1A`,
@@ -356,7 +356,7 @@ Usage: /model <model-id> to switch directly, or /switch for the picker`,
356
356
  return new Date(t).toLocaleDateString("en-US");
357
357
  },
358
358
  langCurrent: () => `Interface language: English (/lang zh for \u4E2D\u6587)`,
359
- langSet: (l) => `Interface language: ${l === "zh" ? "\u4E2D\u6587" : "English"}`,
359
+ langSet: (l) => `Interface language: ${l === "zh" ? "\u4E2D\u6587" : "English"} (AI reply language follows each question's language automatically; this is the fallback for code-only / text-less turns)`,
360
360
  langInvalid: (arg) => `Invalid language: ${arg} (choose zh / en)`,
361
361
  outputStyleNone: () => `No output styles loaded (drop a <name>.md in ~/.deepseeker-code/output-styles/).`,
362
362
  outputStyleCurrent: (cur) => `Current output style: ${cur ?? "default (neutral)"}. Available:`,
@@ -618,7 +618,7 @@ var init_common = __esm({
618
618
  }
619
619
  };
620
620
  detectTextLocale = (text) => {
621
- const stripped = (text || "").replace(/```[\s\S]*?```/g, " ").replace(/`[^`]*`/g, " ").replace(/\s+/g, " ");
621
+ const stripped = (text || "").replace(/```[\s\S]*?```/g, " ").replace(/`[^`]*`/g, " ").replace(/[A-Za-z]:[\\/][^\s"'`))\]},。;]*/g, " ").replace(/(?:^|[\s((【"'])\/(?:home|Users|root|var|tmp|mnt|opt|data|app)[^\s"'`))\]},。;]*/g, " ").replace(/https?:\/\/[^\s"'`))\]},。;]*/g, " ").replace(/\s+/g, " ");
622
622
  const cjk = (stripped.match(/[㐀-䶿一-鿿]/g) || []).length;
623
623
  const latin = (stripped.match(/[A-Za-z]/g) || []).length;
624
624
  if (cjk === 0 && latin === 0) return null;
@@ -937,7 +937,7 @@ var init_stream = __esm({
937
937
  });
938
938
 
939
939
  // ../core/src/llm/providers/deepseek/index.ts
940
- var summarize, classifyRisk, isContextLengthError, isTransientError, buildAssistantMessage, deepseekProvider;
940
+ var summarize, classifyRisk, isContextLengthError, isImageUnsupportedError, isTransientError, buildAssistantMessage, deepseekProvider;
941
941
  var init_deepseek = __esm({
942
942
  "../core/src/llm/providers/deepseek/index.ts"() {
943
943
  "use strict";
@@ -997,6 +997,15 @@ var init_deepseek = __esm({
997
997
  const msg = typeof e.message === "string" ? e.message : "";
998
998
  return code === "context_length_exceeded" || /context_length|context length|maximum context|input length|too long|exceed/i.test(msg);
999
999
  };
1000
+ isImageUnsupportedError = (e) => {
1001
+ if (!e || isContextLengthError(e)) return false;
1002
+ const status = e.status ?? e.response?.status;
1003
+ if (status !== 400 && status !== 422) return false;
1004
+ const code = e.error?.code ?? e.code;
1005
+ const msg = typeof e.message === "string" ? e.message : "";
1006
+ const codeStr = typeof code === "string" ? code : "";
1007
+ return /image|multimodal|vision|image_url/i.test(msg) || /image/i.test(codeStr);
1008
+ };
1000
1009
  isTransientError = (e) => {
1001
1010
  if (!e) return false;
1002
1011
  const status = e.status ?? e.response?.status;
@@ -1019,7 +1028,8 @@ var init_deepseek = __esm({
1019
1028
  classifyRisk,
1020
1029
  buildAssistantMessage,
1021
1030
  isContextLengthError,
1022
- isTransientError
1031
+ isTransientError,
1032
+ isImageUnsupportedError
1023
1033
  };
1024
1034
  }
1025
1035
  });
@@ -1034,12 +1044,63 @@ var init_createModel = __esm({
1034
1044
  }
1035
1045
  });
1036
1046
 
1047
+ // ../core/src/llm/visionCapability.ts
1048
+ import path6 from "path";
1049
+ import fs4 from "fs/promises";
1050
+ var CAP_FILE, MAX_ENTRIES, mem, loadPromise, ensureVisionCacheLoaded, peekVisionCapability, writeChain, persistLatest, learnVisionCapability;
1051
+ var init_visionCapability = __esm({
1052
+ "../core/src/llm/visionCapability.ts"() {
1053
+ "use strict";
1054
+ init_config();
1055
+ init_common();
1056
+ CAP_FILE = path6.join(appConfig.dataDir, "model-capabilities.json");
1057
+ MAX_ENTRIES = 100;
1058
+ mem = {};
1059
+ loadPromise = (async () => {
1060
+ const t = await readJSONFile(CAP_FILE);
1061
+ if (t && typeof t === "object") mem = t;
1062
+ })().catch(() => {
1063
+ });
1064
+ ensureVisionCacheLoaded = () => loadPromise;
1065
+ peekVisionCapability = (modelId) => {
1066
+ const e = mem[modelId?.trim()];
1067
+ return e && typeof e.vision === "boolean" ? e.vision : void 0;
1068
+ };
1069
+ writeChain = Promise.resolve();
1070
+ persistLatest = () => {
1071
+ writeChain = writeChain.then(async () => {
1072
+ try {
1073
+ await fs4.mkdir(appConfig.dataDir, { recursive: true });
1074
+ await atomicWriteJSON(CAP_FILE, mem);
1075
+ } catch {
1076
+ }
1077
+ });
1078
+ return writeChain;
1079
+ };
1080
+ learnVisionCapability = (modelId, vision) => {
1081
+ const id = modelId?.trim();
1082
+ if (!id) return;
1083
+ mem[id] = { vision, checkedAt: (/* @__PURE__ */ new Date()).toISOString() };
1084
+ while (Object.keys(mem).length > MAX_ENTRIES) {
1085
+ let oldestKey = "";
1086
+ for (const k of Object.keys(mem)) {
1087
+ if (!oldestKey || (mem[k]?.checkedAt ?? "") < (mem[oldestKey]?.checkedAt ?? "")) oldestKey = k;
1088
+ }
1089
+ if (!oldestKey) break;
1090
+ delete mem[oldestKey];
1091
+ }
1092
+ void persistLatest();
1093
+ };
1094
+ }
1095
+ });
1096
+
1037
1097
  // ../core/src/session/contentParts.ts
1038
- var MAX_IMAGE_BYTES, msgText, imageUrlsOf, hasImagePart, modelSupportsVision, isVisionEnabled, estimateImageTokens, toWireUserContent, toIngestContents, replaceImageParts, collapseToText, degradeImagesForAux;
1098
+ var MAX_IMAGE_BYTES, msgText, imageUrlsOf, hasImagePart, VISION_DEGRADE_NOTE, isVisionEnabled, estimateImageTokens, toWireUserContent, toIngestContents, replaceImageParts, collapseToText, degradeImagesForAux;
1039
1099
  var init_contentParts = __esm({
1040
1100
  "../core/src/session/contentParts.ts"() {
1041
1101
  "use strict";
1042
1102
  init_createModel();
1103
+ init_visionCapability();
1043
1104
  MAX_IMAGE_BYTES = 8 * 1024 * 1024;
1044
1105
  msgText = (content) => {
1045
1106
  if (typeof content === "string") return content;
@@ -1053,13 +1114,13 @@ var init_contentParts = __esm({
1053
1114
  return content.filter((p) => p?.type === "image_url" && typeof p?.image_url?.url === "string").map((p) => p.image_url.url);
1054
1115
  };
1055
1116
  hasImagePart = (content) => imageUrlsOf(content).length > 0;
1056
- modelSupportsVision = (modelId) => /vision|vlm|(^|[-_.])vl([-_.0-9]|$)/i.test(modelId || "");
1117
+ VISION_DEGRADE_NOTE = "[\u56FE\u7247\u672A\u9001\u8FBE\uFF1A\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF0C\u7CFB\u7EDF\u5DF2\u81EA\u52A8\u6539\u7528\u6587\u672C\u65B9\u5F0F\uFF1B\u539F\u56FE\u4ECD\u5728\u4F1A\u8BDD\u5F52\u6863\u4E2D\uFF0C\u5982\u9700\u5206\u6790\u56FE\u7247\u5185\u5BB9\u53EF\u914D\u7F6E\u56FE\u50CF\u8BC6\u522B\u5DE5\u5177\u8BFB\u53D6\u5B58\u6863\u8DEF\u5F84\uFF0C\u6216\u7531\u7528\u6237\u91CD\u65B0\u63D0\u4F9B]";
1057
1118
  isVisionEnabled = (modelId) => {
1058
1119
  const v = process.env.DEEP_SEEK_VISION;
1059
1120
  if (v === "1" || v === "true") return true;
1060
1121
  if (v === "0" || v === "false") return false;
1061
1122
  const effective = typeof modelId === "string" && modelId.trim() ? modelId.trim() : MODEL_NAME;
1062
- return modelSupportsVision(effective);
1123
+ return peekVisionCapability(effective) ?? true;
1063
1124
  };
1064
1125
  estimateImageTokens = () => {
1065
1126
  const n = Number(process.env.DEEP_SEEK_IMAGE_TOKENS);
@@ -1084,9 +1145,9 @@ var init_contentParts = __esm({
1084
1145
  skipped.push(`\u{1F5BC} \u56FE\u7247 ${name} \u5DF2\u5FFD\u7565\uFF1A\u8D85\u8FC7 ${Math.round(MAX_IMAGE_BYTES / 1024 / 1024)}MB \u4E0A\u9650`);
1085
1146
  continue;
1086
1147
  }
1087
- accepted.push({ name, url: `data:${a.mime};base64,${b64}` });
1148
+ accepted.push({ name, url: `data:${a.mime};base64,${b64}`, path: a.path });
1088
1149
  }
1089
- const labels = accepted.map((p) => `\u{1F5BC} [\u56FE\u7247: ${p.name}]`);
1150
+ const labels = accepted.map((p) => `\u{1F5BC} [\u56FE\u7247: ${p.name}${p.path ? ` | \u5B58\u6863: ${p.path}` : ""}]`);
1090
1151
  const footer = [...skipped, ...labels];
1091
1152
  const finalText = footer.length ? `${text}
1092
1153
 
@@ -1110,7 +1171,7 @@ ${paths.join("\n")}
1110
1171
  return {
1111
1172
  wire: `${text}
1112
1173
 
1113
- \u{1F5BC} \u6536\u5230\u56FE\u7247\u9644\u4EF6\uFF08${names}\uFF09\uFF1A\u5F53\u524D\u6A21\u578B\u65E0\u89C6\u89C9\u80FD\u529B\uFF0C\u65E0\u6CD5\u76F4\u63A5\u67E5\u770B\u56FE\u7247\u5185\u5BB9\uFF08\u53EF\u5207\u6362 vision \u6A21\u578B\u6216\u8BBE DEEP_SEEK_VISION=1 \u5F3A\u5F00\uFF09\uFF1B${relay}`,
1174
+ \u{1F5BC} \u6536\u5230\u56FE\u7247\u9644\u4EF6\uFF08${names}\uFF09\uFF1A\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF08\u89C6\u89C9\u80FD\u529B\u5DF2\u6309\u7AEF\u70B9\u5B9E\u6D4B\u81EA\u52A8\u5224\u5B9A\uFF1B\u53EF\u5207\u6362 vision \u6A21\u578B\u6216\u8BBE DEEP_SEEK_VISION=1 \u5F3A\u5F00\uFF09\uFF1B${relay}`,
1114
1175
  archive
1115
1176
  };
1116
1177
  };
@@ -1151,10 +1212,11 @@ var init_replay = __esm({
1151
1212
  let attemptCounts = [];
1152
1213
  const calls = [];
1153
1214
  const makeFaultError = (fault) => {
1154
- const msg = fault.message ?? (fault.type === "idle" ? "stream_idle_timeout" : fault.type === "context_length" ? "context_length_exceeded\uFF08\u56DE\u653E\u6CE8\u5165\uFF09" : fault.type === "transient" ? "HTTP 429 rate limit\uFF08\u56DE\u653E\u6CE8\u5165\uFF09" : "\u56DE\u653E\u81F4\u547D\u9519\u8BEF\uFF08fatal\uFF09");
1215
+ const msg = fault.message ?? (fault.type === "idle" ? "stream_idle_timeout" : fault.type === "context_length" ? "context_length_exceeded\uFF08\u56DE\u653E\u6CE8\u5165\uFF09" : fault.type === "transient" ? "HTTP 429 rate limit\uFF08\u56DE\u653E\u6CE8\u5165\uFF09" : fault.type === "image_unsupported" ? "This model does not support image\uFF08\u56DE\u653E\u6CE8\u5165\uFF09" : "\u56DE\u653E\u81F4\u547D\u9519\u8BEF\uFF08fatal\uFF09");
1155
1216
  const e = new Error(msg);
1156
1217
  e.replayFault = fault.type;
1157
1218
  if (fault.type === "transient") e.status = 429;
1219
+ if (fault.type === "image_unsupported") e.status = 400;
1158
1220
  return e;
1159
1221
  };
1160
1222
  const streamChat2 = async function* (messages, tools, opts) {
@@ -1210,9 +1272,10 @@ var init_replay = __esm({
1210
1272
  if (parts.toolCalls?.length) m.tool_calls = parts.toolCalls;
1211
1273
  return m;
1212
1274
  },
1213
- // 自识别回放注入的故障(streamInference 经 activeProvider 调用这两个分类器驱动重试通道)
1275
+ // 自识别回放注入的故障(streamInference 经 activeProvider 调用这些分类器驱动重试通道)
1214
1276
  isContextLengthError: (e) => e?.replayFault === "context_length",
1215
1277
  isTransientError: (e) => e?.replayFault === "transient",
1278
+ isImageUnsupportedError: (e) => e?.replayFault === "image_unsupported",
1216
1279
  get calls() {
1217
1280
  return calls;
1218
1281
  },
@@ -1371,8 +1434,8 @@ __export(store_exports, {
1371
1434
  updateCalibration: () => updateCalibration,
1372
1435
  writeStore: () => writeStore
1373
1436
  });
1374
- import fs4 from "fs/promises";
1375
- import path6 from "path";
1437
+ import fs5 from "fs/promises";
1438
+ import path7 from "path";
1376
1439
  async function getRollingState(sessionId) {
1377
1440
  const store = await readStore(sessionId);
1378
1441
  if (!store) {
@@ -1420,42 +1483,42 @@ var init_store = __esm({
1420
1483
  getSessionsDirPath = (mainSessionId) => {
1421
1484
  assertSafeSessionId(mainSessionId);
1422
1485
  const fileName = getFileName(mainSessionId);
1423
- return path6.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir, fileName);
1486
+ return path7.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir, fileName);
1424
1487
  };
1425
- getWorkspaceSessionsDir = () => path6.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir);
1488
+ getWorkspaceSessionsDir = () => path7.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir);
1426
1489
  getStatePath = (sessionId) => {
1427
1490
  assertSafeSessionId(sessionId);
1428
- return path6.join(getSessionsDirPath(sessionId), `${sessionId}.state.json`);
1491
+ return path7.join(getSessionsDirPath(sessionId), `${sessionId}.state.json`);
1429
1492
  };
1430
1493
  getTranscriptPath = (sessionId) => {
1431
1494
  assertSafeSessionId(sessionId);
1432
- return path6.join(getSessionsDirPath(sessionId), `${sessionId}.jsonl`);
1495
+ return path7.join(getSessionsDirPath(sessionId), `${sessionId}.jsonl`);
1433
1496
  };
1434
1497
  ensureSessionsDir = async (sessionId) => {
1435
- await fs4.mkdir(getSessionsDirPath(sessionId), { recursive: true });
1498
+ await fs5.mkdir(getSessionsDirPath(sessionId), { recursive: true });
1436
1499
  await migrateLegacyFiles(sessionId).catch(() => {
1437
1500
  });
1438
1501
  };
1439
1502
  migrateLegacyFiles = async (sessionId) => {
1440
1503
  assertSafeSessionId(sessionId);
1441
1504
  const dir = getSessionsDirPath(sessionId);
1442
- const legacy = path6.join(dir, `${sessionId}.json`);
1505
+ const legacy = path7.join(dir, `${sessionId}.json`);
1443
1506
  const transcriptPath = getTranscriptPath(sessionId);
1444
1507
  const statePath = getStatePath(sessionId);
1445
1508
  let legacyText;
1446
1509
  try {
1447
- legacyText = await fs4.readFile(legacy, "utf-8");
1510
+ legacyText = await fs5.readFile(legacy, "utf-8");
1448
1511
  } catch {
1449
1512
  return;
1450
1513
  }
1451
1514
  try {
1452
- await fs4.access(transcriptPath);
1515
+ await fs5.access(transcriptPath);
1453
1516
  return;
1454
1517
  } catch {
1455
1518
  }
1456
1519
  const raw = legacyText.trim();
1457
1520
  if (raw.length === 0) {
1458
- await fs4.rename(legacy, transcriptPath);
1521
+ await fs5.rename(legacy, transcriptPath);
1459
1522
  return;
1460
1523
  }
1461
1524
  const lines = raw.split("\n");
@@ -1468,13 +1531,13 @@ var init_store = __esm({
1468
1531
  }
1469
1532
  });
1470
1533
  if (isJsonl) {
1471
- await fs4.rename(legacy, transcriptPath);
1534
+ await fs5.rename(legacy, transcriptPath);
1472
1535
  return;
1473
1536
  }
1474
1537
  try {
1475
1538
  const v = JSON.parse(raw);
1476
1539
  if (typeof v === "object" && v !== null) {
1477
- await fs4.rename(legacy, statePath);
1540
+ await fs5.rename(legacy, statePath);
1478
1541
  return;
1479
1542
  }
1480
1543
  } catch {
@@ -1485,8 +1548,8 @@ var init_store = __esm({
1485
1548
  await ensureSessionsDir(sessionId);
1486
1549
  const finalPath = getStatePath(sessionId);
1487
1550
  const tmpPath = `${finalPath}.${Date.now()}.tmp`;
1488
- await fs4.writeFile(tmpPath, JSON.stringify(store, null, 2), "utf-8");
1489
- await fs4.rename(tmpPath, finalPath);
1551
+ await fs5.writeFile(tmpPath, JSON.stringify(store, null, 2), "utf-8");
1552
+ await fs5.rename(tmpPath, finalPath);
1490
1553
  };
1491
1554
  storeLocks = /* @__PURE__ */ new Map();
1492
1555
  withStoreLock = (sessionId, fn) => {
@@ -1526,7 +1589,7 @@ var init_store = __esm({
1526
1589
  await ensureSessionsDir(sessionId);
1527
1590
  const p = getStatePath(sessionId);
1528
1591
  try {
1529
- const raw = (await fs4.readFile(p, "utf-8")).trim();
1592
+ const raw = (await fs5.readFile(p, "utf-8")).trim();
1530
1593
  if (raw.length === 0) {
1531
1594
  return {};
1532
1595
  }
@@ -1555,7 +1618,7 @@ var init_store = __esm({
1555
1618
  const root = getWorkspaceSessionsDir();
1556
1619
  let entries;
1557
1620
  try {
1558
- entries = await fs4.readdir(root, { withFileTypes: true });
1621
+ entries = await fs5.readdir(root, { withFileTypes: true });
1559
1622
  } catch {
1560
1623
  return [];
1561
1624
  }
@@ -1564,12 +1627,12 @@ var init_store = __esm({
1564
1627
  if (!entry.isDirectory()) continue;
1565
1628
  const sessionId = entry.name;
1566
1629
  if (!isSafeSessionId(sessionId)) continue;
1567
- const dirPath = path6.join(root, sessionId);
1630
+ const dirPath = path7.join(root, sessionId);
1568
1631
  const state = await readJSONFile(getStatePath(sessionId));
1569
1632
  let messageCount = 0;
1570
1633
  let preview = "";
1571
1634
  try {
1572
- const raw = await fs4.readFile(getTranscriptPath(sessionId), "utf-8");
1635
+ const raw = await fs5.readFile(getTranscriptPath(sessionId), "utf-8");
1573
1636
  for (const s of raw.split("\n")) {
1574
1637
  const line = s.trim();
1575
1638
  if (!line) continue;
@@ -1596,7 +1659,7 @@ var init_store = __esm({
1596
1659
  let updatedAt = state?.updatedAt;
1597
1660
  if (!updatedAt) {
1598
1661
  try {
1599
- updatedAt = (await fs4.stat(dirPath)).mtime.toISOString();
1662
+ updatedAt = (await fs5.stat(dirPath)).mtime.toISOString();
1600
1663
  } catch {
1601
1664
  }
1602
1665
  }
@@ -1629,13 +1692,13 @@ var init_store = __esm({
1629
1692
  deleteSession = async (sessionId) => {
1630
1693
  assertSafeSessionId(sessionId);
1631
1694
  const dir = getSessionsDirPath(sessionId);
1632
- await fs4.rm(dir, { recursive: true, force: true });
1695
+ await fs5.rm(dir, { recursive: true, force: true });
1633
1696
  };
1634
1697
  }
1635
1698
  });
1636
1699
 
1637
1700
  // ../core/src/session/transcript.ts
1638
- import fs5 from "fs/promises";
1701
+ import fs6 from "fs/promises";
1639
1702
  var isEventLine, readTranscriptLines, appendLineWithRetry, appendMessage, appendEvent;
1640
1703
  var init_transcript = __esm({
1641
1704
  "../core/src/session/transcript.ts"() {
@@ -1648,7 +1711,7 @@ var init_transcript = __esm({
1648
1711
  await ensureSessionsDir(sessionId);
1649
1712
  const p = getTranscriptPath(sessionId);
1650
1713
  try {
1651
- const text = await fs5.readFile(p, "utf-8");
1714
+ const text = await fs6.readFile(p, "utf-8");
1652
1715
  const lines = [];
1653
1716
  for (const s of text.split("\n")) {
1654
1717
  const line = s.trim();
@@ -1670,15 +1733,15 @@ var init_transcript = __esm({
1670
1733
  for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
1671
1734
  let beforeSize = 0;
1672
1735
  try {
1673
- beforeSize = (await fs5.stat(p)).size;
1736
+ beforeSize = (await fs6.stat(p)).size;
1674
1737
  } catch {
1675
1738
  }
1676
1739
  try {
1677
- await fs5.appendFile(p, payload, "utf-8");
1740
+ await fs6.appendFile(p, payload, "utf-8");
1678
1741
  return;
1679
1742
  } catch (e) {
1680
1743
  try {
1681
- await fs5.truncate(p, beforeSize);
1744
+ await fs6.truncate(p, beforeSize);
1682
1745
  } catch {
1683
1746
  }
1684
1747
  if (attempt === MAX_ATTEMPTS) throw e;
@@ -1741,7 +1804,7 @@ var init_types = __esm({
1741
1804
 
1742
1805
  // ../core/src/hooks/shellExecutor.ts
1743
1806
  import { spawn } from "child_process";
1744
- import path7 from "path";
1807
+ import path8 from "path";
1745
1808
  var MAX_OUTPUT, DEFAULT_TIMEOUT_MS, HARD_TIMEOUT_CAP_MS, ENV_WHITELIST, truncate, MAX_STDIN_FIELD, capFieldStrings, extractFilePath, executeHookCommand;
1746
1809
  var init_shellExecutor = __esm({
1747
1810
  "../core/src/hooks/shellExecutor.ts"() {
@@ -1787,7 +1850,7 @@ var init_shellExecutor = __esm({
1787
1850
  if (typeof rel !== "string" || !rel.trim()) return void 0;
1788
1851
  const base = typeof p.cwd === "string" && p.cwd || process.env.WORKSPACE_ROOT || process.cwd();
1789
1852
  try {
1790
- return path7.resolve(base, rel);
1853
+ return path8.resolve(base, rel);
1791
1854
  } catch {
1792
1855
  return void 0;
1793
1856
  }
@@ -2004,7 +2067,7 @@ var init_hooks = __esm({
2004
2067
  });
2005
2068
 
2006
2069
  // ../core/src/agent/truncate.ts
2007
- import path8 from "path";
2070
+ import path9 from "path";
2008
2071
  function stripAnsi(text) {
2009
2072
  return text.replace(ANSI_ESCAPE, "");
2010
2073
  }
@@ -2043,10 +2106,10 @@ var init_truncate = __esm({
2043
2106
  if (!text) return text;
2044
2107
  const roots = /* @__PURE__ */ new Set();
2045
2108
  try {
2046
- roots.add(path8.resolve(appConfig.userWorkspaceDir));
2109
+ roots.add(path9.resolve(appConfig.userWorkspaceDir));
2047
2110
  for (const r of getFileAccessRoots()) {
2048
2111
  try {
2049
- roots.add(path8.resolve(r));
2112
+ roots.add(path9.resolve(r));
2050
2113
  } catch {
2051
2114
  }
2052
2115
  }
@@ -2414,8 +2477,8 @@ ${lines}
2414
2477
  });
2415
2478
 
2416
2479
  // ../core/src/tool/permissions.ts
2417
- import fs6 from "fs/promises";
2418
- import path9 from "path";
2480
+ import fs7 from "fs/promises";
2481
+ import path10 from "path";
2419
2482
  var PRIMARY_ARG, rules2, trustedProject, globCache, globToRegex, DANGER_COMMAND_TOOLS, compileRule, readPermissionConfig, toolNameMatches, ruleMatches, initPermissions, checkPermission, listPermissionRules, buildScopedAllowRule, resolveSettingsPath, addPermissionRule;
2420
2483
  var init_permissions = __esm({
2421
2484
  "../core/src/tool/permissions.ts"() {
@@ -2477,15 +2540,15 @@ var init_permissions = __esm({
2477
2540
  readPermissionConfig = async (includeProject) => {
2478
2541
  const merged = { allow: [], deny: [], ask: [] };
2479
2542
  const paths = [
2480
- path9.join(appConfig.dataDir, "settings.json"),
2543
+ path10.join(appConfig.dataDir, "settings.json"),
2481
2544
  // 全局用户级
2482
- ...includeProject ? [path9.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
2545
+ ...includeProject ? [path10.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
2483
2546
  // 项目级(叠加);未信任时省略
2484
2547
  ];
2485
2548
  for (const configPath of paths) {
2486
2549
  let raw;
2487
2550
  try {
2488
- raw = await fs6.readFile(configPath, "utf-8");
2551
+ raw = await fs7.readFile(configPath, "utf-8");
2489
2552
  } catch {
2490
2553
  continue;
2491
2554
  }
@@ -2570,7 +2633,7 @@ var init_permissions = __esm({
2570
2633
  }
2571
2634
  return `${toolName}(${val})`;
2572
2635
  };
2573
- resolveSettingsPath = (scope) => scope === "global" ? path9.join(appConfig.dataDir, "settings.json") : path9.join(process.cwd(), ".deepseeker-code", "settings.json");
2636
+ resolveSettingsPath = (scope) => scope === "global" ? path10.join(appConfig.dataDir, "settings.json") : path10.join(process.cwd(), ".deepseeker-code", "settings.json");
2574
2637
  addPermissionRule = async (scope, kind, ruleStr) => {
2575
2638
  if (scope === "project" && !trustedProject) return false;
2576
2639
  const compiled = compileRule(ruleStr, `runtime:addPermissionRule(${scope})`, kind);
@@ -2582,7 +2645,7 @@ var init_permissions = __esm({
2582
2645
  const arr = Array.isArray(cfg.permissions[kind]) ? cfg.permissions[kind] : cfg.permissions[kind] = [];
2583
2646
  if (!arr.includes(ruleStr)) {
2584
2647
  arr.push(ruleStr);
2585
- await fs6.mkdir(path9.dirname(file), { recursive: true });
2648
+ await fs7.mkdir(path10.dirname(file), { recursive: true });
2586
2649
  await atomicWriteJSON(file, cfg);
2587
2650
  }
2588
2651
  if (!rules2[kind].some((r) => r.raw === compiled.raw)) rules2[kind].push(compiled);
@@ -2620,9 +2683,9 @@ var init_sessionRegistry = __esm({
2620
2683
  });
2621
2684
 
2622
2685
  // ../core/src/tool/guard.ts
2623
- import fs7 from "fs/promises";
2686
+ import fs8 from "fs/promises";
2624
2687
  import fsSync from "fs";
2625
- import path10 from "path";
2688
+ import path11 from "path";
2626
2689
  import ignore from "ignore";
2627
2690
  import { AsyncLocalStorage } from "node:async_hooks";
2628
2691
  var WORKSPACE_ROOT, workspaceAls, getActiveWorkspaceRoot, runWithWorkspaceRoot, runWithSessionContext, BUILTIN_IGNORE_RULES, ignoreCache, ignoreBuilding, allowedRootsReal, getAllowedWorkspaceRoots, getContainingRoot, allowedBoundaryRoots, resolveSafePath, resolveReadablePath, assertWithinWorkspace, PROTECTED_WRITE_DIRS, COMMAND_ENV_DENYLIST, SENSITIVE_ENV_PATTERN, scrubCommandEnv, isProtectedWrite, scanIgnoreFilesRecursive, buildIgnoreEngine, getIgnoreForBase, initializeWorkspaceIgnore, checkIsPathIgnored, requestApproval;
@@ -2678,8 +2741,8 @@ var init_guard = __esm({
2678
2741
  getContainingRoot = (absPath) => {
2679
2742
  let best;
2680
2743
  for (const r of allowedBoundaryRoots()) {
2681
- const rel = path10.relative(r, absPath);
2682
- if (!rel.startsWith("..") && !path10.isAbsolute(rel)) {
2744
+ const rel = path11.relative(r, absPath);
2745
+ if (!rel.startsWith("..") && !path11.isAbsolute(rel)) {
2683
2746
  if (!best || r.length > best.length) best = r;
2684
2747
  }
2685
2748
  }
@@ -2696,16 +2759,16 @@ var init_guard = __esm({
2696
2759
  };
2697
2760
  resolveSafePath = (rel, base) => {
2698
2761
  const root = base ?? getActiveWorkspaceRoot();
2699
- const candidateAbsPath = path10.resolve(root, rel);
2762
+ const candidateAbsPath = path11.resolve(root, rel);
2700
2763
  let truePhysicalPath = candidateAbsPath;
2701
2764
  try {
2702
2765
  if (fsSync.existsSync(candidateAbsPath)) {
2703
2766
  truePhysicalPath = fsSync.realpathSync(candidateAbsPath);
2704
2767
  } else {
2705
- const parentDir = path10.dirname(candidateAbsPath);
2768
+ const parentDir = path11.dirname(candidateAbsPath);
2706
2769
  if (fsSync.existsSync(parentDir)) {
2707
2770
  const trueParentDir = fsSync.realpathSync(parentDir);
2708
- truePhysicalPath = path10.join(trueParentDir, path10.basename(candidateAbsPath));
2771
+ truePhysicalPath = path11.join(trueParentDir, path11.basename(candidateAbsPath));
2709
2772
  }
2710
2773
  }
2711
2774
  } catch (e) {
@@ -2719,8 +2782,8 @@ var init_guard = __esm({
2719
2782
  }
2720
2783
  })() : allowedBoundaryRoots();
2721
2784
  const escaped = boundaryRoots.every((r) => {
2722
- const rel0 = path10.relative(r, truePhysicalPath);
2723
- return rel0.startsWith("..") || path10.isAbsolute(rel0);
2785
+ const rel0 = path11.relative(r, truePhysicalPath);
2786
+ return rel0.startsWith("..") || path11.isAbsolute(rel0);
2724
2787
  });
2725
2788
  if (escaped) {
2726
2789
  throw new Error(`\u{1F6D1} [SECURITY ALERT] \u68C0\u6D4B\u5230\u6076\u610F\u7684\u7269\u7406\u8DEF\u5F84\u8DE8\u754C\u9003\u9038\uFF01\u62D2\u7EDD\u8BBF\u95EE\uFF1A${rel}`);
@@ -2729,12 +2792,12 @@ var init_guard = __esm({
2729
2792
  };
2730
2793
  resolveReadablePath = (rel) => {
2731
2794
  const root = getActiveWorkspaceRoot();
2732
- const absPath = path10.resolve(root, rel);
2795
+ const absPath = path11.resolve(root, rel);
2733
2796
  if (!fsSync.existsSync(absPath)) {
2734
- const rootName = path10.basename(root);
2797
+ const rootName = path11.basename(root);
2735
2798
  const firstSeg = rel.split(/[\\/]/)[0];
2736
2799
  if (rootName && firstSeg === rootName) {
2737
- const alt = path10.resolve(root, rel.slice(firstSeg.length + 1));
2800
+ const alt = path11.resolve(root, rel.slice(firstSeg.length + 1));
2738
2801
  if (fsSync.existsSync(alt)) return alt;
2739
2802
  }
2740
2803
  }
@@ -2747,9 +2810,9 @@ var init_guard = __esm({
2747
2810
  if (fsSync.existsSync(absPath)) {
2748
2811
  truePhysicalPath = fsSync.realpathSync(absPath);
2749
2812
  } else {
2750
- const parentDir = path10.dirname(absPath);
2813
+ const parentDir = path11.dirname(absPath);
2751
2814
  if (fsSync.existsSync(parentDir)) {
2752
- truePhysicalPath = path10.join(fsSync.realpathSync(parentDir), path10.basename(absPath));
2815
+ truePhysicalPath = path11.join(fsSync.realpathSync(parentDir), path11.basename(absPath));
2753
2816
  }
2754
2817
  }
2755
2818
  } catch (e) {
@@ -2763,8 +2826,8 @@ var init_guard = __esm({
2763
2826
  }
2764
2827
  })() : allowedBoundaryRoots();
2765
2828
  const escaped = boundaryRoots.every((r) => {
2766
- const rel0 = path10.relative(r, truePhysicalPath);
2767
- return rel0.startsWith("..") || path10.isAbsolute(rel0);
2829
+ const rel0 = path11.relative(r, truePhysicalPath);
2830
+ return rel0.startsWith("..") || path11.isAbsolute(rel0);
2768
2831
  });
2769
2832
  if (escaped) {
2770
2833
  throw new Error(`\u{1F6D1} [SECURITY ALERT] \u4E8C\u6B21\u56F4\u680F\u590D\u68C0\u53D1\u73B0\u8D8A\u754C\uFF08\u7591\u4F3C TOCTOU \u8F6F\u94FE\u63A5\u9003\u9038\uFF09\uFF1A${absPath}`);
@@ -2791,7 +2854,7 @@ var init_guard = __esm({
2791
2854
  if (!relOrAbs) return false;
2792
2855
  try {
2793
2856
  const base = cwd || process.env.WORKSPACE_ROOT || process.cwd();
2794
- const abs = path10.isAbsolute(relOrAbs) ? relOrAbs : path10.resolve(base, relOrAbs);
2857
+ const abs = path11.isAbsolute(relOrAbs) ? relOrAbs : path11.resolve(base, relOrAbs);
2795
2858
  const lower = abs.replace(/\\/g, "/").toLowerCase();
2796
2859
  return PROTECTED_WRITE_DIRS.some((d) => {
2797
2860
  const seg = ("/" + d).toLowerCase();
@@ -2803,12 +2866,12 @@ var init_guard = __esm({
2803
2866
  };
2804
2867
  scanIgnoreFilesRecursive = async (dirPath, base, engine) => {
2805
2868
  try {
2806
- const entries = await fs7.readdir(dirPath, { withFileTypes: true });
2869
+ const entries = await fs8.readdir(dirPath, { withFileTypes: true });
2807
2870
  for (const entry of entries) {
2808
2871
  if (entry.isFile() && (entry.name === ".gitignore" || entry.name === ".agentignore")) {
2809
- const fullPath = path10.join(dirPath, entry.name);
2810
- const content = await fs7.readFile(fullPath, "utf-8");
2811
- const relDir = path10.relative(base, dirPath).replace(/\\/g, "/");
2872
+ const fullPath = path11.join(dirPath, entry.name);
2873
+ const content = await fs8.readFile(fullPath, "utf-8");
2874
+ const relDir = path11.relative(base, dirPath).replace(/\\/g, "/");
2812
2875
  const rules3 = content.split(/\r?\n/).map((line) => {
2813
2876
  const trimmed = line.trim();
2814
2877
  if (!trimmed || trimmed.startsWith("#")) return "";
@@ -2819,7 +2882,7 @@ var init_guard = __esm({
2819
2882
  }
2820
2883
  for (const entry of entries) {
2821
2884
  if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== ".git") {
2822
- await scanIgnoreFilesRecursive(path10.join(dirPath, entry.name), base, engine);
2885
+ await scanIgnoreFilesRecursive(path11.join(dirPath, entry.name), base, engine);
2823
2886
  }
2824
2887
  }
2825
2888
  } catch {
@@ -2890,7 +2953,7 @@ var init_guard = __esm({
2890
2953
  // ../core/src/tool/registry/background.ts
2891
2954
  import { spawn as spawn2, execFileSync } from "child_process";
2892
2955
  import fsSync2 from "fs";
2893
- import path11 from "path";
2956
+ import path12 from "path";
2894
2957
  function appendOutput(task, chunk) {
2895
2958
  task.outputBuffer += chunk;
2896
2959
  if (task.outputBuffer.length > MAX_BUFFER_CHARS) {
@@ -2915,7 +2978,7 @@ async function killTree(proc) {
2915
2978
  }
2916
2979
  }
2917
2980
  async function killBackgroundTasksUnder(dirPath) {
2918
- const norm = (p) => path11.resolve(p).replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
2981
+ const norm = (p) => path12.resolve(p).replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
2919
2982
  const target = norm(dirPath);
2920
2983
  let killed = 0;
2921
2984
  for (const task of registry.values()) {
@@ -2960,9 +3023,9 @@ var init_background = __esm({
2960
3023
  if (envShell && envShell.toLowerCase() !== "cmd") candidates.push(envShell);
2961
3024
  const gitExe = whereLines("git")[0];
2962
3025
  if (gitExe) {
2963
- const dir = path11.dirname(gitExe);
2964
- const root = path11.dirname(dir);
2965
- candidates.push(path11.join(root, "bin", "bash.exe"), path11.join(dir, "bash.exe"), path11.join(path11.dirname(root), "bin", "bash.exe"));
3026
+ const dir = path12.dirname(gitExe);
3027
+ const root = path12.dirname(dir);
3028
+ candidates.push(path12.join(root, "bin", "bash.exe"), path12.join(dir, "bash.exe"), path12.join(path12.dirname(root), "bin", "bash.exe"));
2966
3029
  }
2967
3030
  const bashHits = whereLines("bash").filter((p) => !/\\System32\\/i.test(p)).sort((a, b) => Number(/\\Git\\/i.test(b)) - Number(/\\Git\\/i.test(a)));
2968
3031
  candidates.push(...bashHits);
@@ -3760,17 +3823,17 @@ ${capped || JSON.stringify(result)}`;
3760
3823
  });
3761
3824
 
3762
3825
  // ../core/src/tool/mcp/loader.ts
3763
- import fs8 from "fs/promises";
3764
- import path12 from "path";
3826
+ import fs9 from "fs/promises";
3827
+ import path13 from "path";
3765
3828
  import { homedir } from "os";
3766
3829
  function sanitize(s) {
3767
3830
  return s.replace(/[^a-zA-Z0-9_]/g, "_");
3768
3831
  }
3769
3832
  async function readMcpConfig() {
3770
- const configPath = process.env.MCP_CONFIG || path12.join(appConfig.dataDir, "mcp.json");
3833
+ const configPath = process.env.MCP_CONFIG || path13.join(appConfig.dataDir, "mcp.json");
3771
3834
  let raw;
3772
3835
  try {
3773
- raw = await fs8.readFile(configPath, "utf-8");
3836
+ raw = await fs9.readFile(configPath, "utf-8");
3774
3837
  } catch {
3775
3838
  return {};
3776
3839
  }
@@ -4418,7 +4481,7 @@ var init_toolFilter = __esm({
4418
4481
  });
4419
4482
 
4420
4483
  // ../core/src/common/registry.ts
4421
- import fs9 from "fs/promises";
4484
+ import fs10 from "fs/promises";
4422
4485
  var createRegistry, filterSources, scanSources;
4423
4486
  var init_registry2 = __esm({
4424
4487
  "../core/src/common/registry.ts"() {
@@ -4448,7 +4511,7 @@ var init_registry2 = __esm({
4448
4511
  for (const s of sources) {
4449
4512
  let entries;
4450
4513
  try {
4451
- entries = await fs9.readdir(s.dir, { withFileTypes: true });
4514
+ entries = await fs10.readdir(s.dir, { withFileTypes: true });
4452
4515
  } catch {
4453
4516
  continue;
4454
4517
  }
@@ -4545,8 +4608,8 @@ ${AGENT_USAGE_HINT}`);
4545
4608
  });
4546
4609
 
4547
4610
  // ../core/src/projectGuide/loader.ts
4548
- import fs10 from "fs/promises";
4549
- import path13 from "path";
4611
+ import fs11 from "fs/promises";
4612
+ import path14 from "path";
4550
4613
  var CANDIDATES, MAX_GUIDE_BYTES, cached, initProjectGuide, getProjectGuide;
4551
4614
  var init_loader2 = __esm({
4552
4615
  "../core/src/projectGuide/loader.ts"() {
@@ -4563,7 +4626,7 @@ var init_loader2 = __esm({
4563
4626
  try {
4564
4627
  for (const name of CANDIDATES) {
4565
4628
  try {
4566
- const raw = await fs10.readFile(path13.join(WORKSPACE_ROOT, name), "utf-8");
4629
+ const raw = await fs11.readFile(path14.join(WORKSPACE_ROOT, name), "utf-8");
4567
4630
  const body = raw.length > MAX_GUIDE_BYTES ? raw.slice(0, MAX_GUIDE_BYTES) + `
4568
4631
 
4569
4632
  \u2026[\u9879\u76EE\u6307\u5F15\u8D85 ${MAX_GUIDE_BYTES} \u5B57\u8282\u5DF2\u622A\u65AD\uFF0C\u5B8C\u6574\u5185\u5BB9\u53EF\u8C03\u7528 read_project_guide \u83B7\u53D6]` : raw;
@@ -4727,12 +4790,13 @@ var init_systemInjections = __esm({
4727
4790
  en: "Always produce ALL user-facing output in English: your replies, interim narration, todo item titles, the plan text you submit via exit_plan_mode, code comments, and commit messages. Keep code identifiers as-is; tool results and system instructions may arrive in Chinese \u2014 quote them verbatim where needed, but your own narration and explanations must stay in English."
4728
4791
  };
4729
4792
  const lastUserText = (() => {
4793
+ const dropSyntheticLines = (t) => t.split("\n").filter((l) => !l.trimStart().startsWith("\u{1F5BC}")).join("\n").trim();
4730
4794
  for (let i = message.length - 1; i >= 0; i--) {
4731
4795
  const m = message[i];
4732
4796
  if (m?.role !== "user") continue;
4733
4797
  const c = m.content;
4734
- if (typeof c === "string") return c;
4735
- if (Array.isArray(c)) return c.filter((p) => typeof p?.text === "string").map((p) => p.text).join(" ");
4798
+ if (typeof c === "string") return dropSyntheticLines(c);
4799
+ if (Array.isArray(c)) return dropSyntheticLines(c.filter((p) => typeof p?.text === "string").map((p) => p.text).join(" "));
4736
4800
  return "";
4737
4801
  }
4738
4802
  return "";
@@ -4805,9 +4869,9 @@ var init_agent = __esm({
4805
4869
  });
4806
4870
 
4807
4871
  // ../core/src/tool/worktree/manager.ts
4808
- import path14 from "path";
4872
+ import path15 from "path";
4809
4873
  import os4 from "os";
4810
- import fs11 from "fs";
4874
+ import fs12 from "fs";
4811
4875
  var runMainGit, worktreeRootDir, worktreeDir, isNotARepoError, createWorktree, harvestDiff, runInWorktree, removeWorktree, sweepOrphanedWorktrees, disposeAllSessionWorktrees;
4812
4876
  var init_manager = __esm({
4813
4877
  "../core/src/tool/worktree/manager.ts"() {
@@ -4818,8 +4882,8 @@ var init_manager = __esm({
4818
4882
  init_background();
4819
4883
  init_sessionRegistry();
4820
4884
  runMainGit = (args, maxBuffer = 1024 * 1024 * 5) => execFileSmart("git", args, { cwd: WORKSPACE_ROOT, maxBuffer });
4821
- worktreeRootDir = () => path14.join(os4.tmpdir(), "deepseeker-code-worktrees", appConfig.userWorkspaceDir);
4822
- worktreeDir = (sessionId, stepId) => path14.join(worktreeRootDir(), sessionId, stepId);
4885
+ worktreeRootDir = () => path15.join(os4.tmpdir(), "deepseeker-code-worktrees", appConfig.userWorkspaceDir);
4886
+ worktreeDir = (sessionId, stepId) => path15.join(worktreeRootDir(), sessionId, stepId);
4823
4887
  isNotARepoError = (e) => {
4824
4888
  const text = `${e?.message || ""} ${e?.stderr || ""}`.toLowerCase();
4825
4889
  return text.includes("not a git repository");
@@ -4830,12 +4894,12 @@ var init_manager = __esm({
4830
4894
  const wtPath = worktreeDir(sessionId, stepId);
4831
4895
  const shortId = sessionId.replace(/[^A-Za-z0-9-]/g, "").slice(0, 8) || "x";
4832
4896
  const branch = `dsc-wt-${shortId}-${stepId}`;
4833
- await fs11.promises.mkdir(path14.dirname(wtPath), { recursive: true });
4897
+ await fs12.promises.mkdir(path15.dirname(wtPath), { recursive: true });
4834
4898
  try {
4835
4899
  await runMainGit(["worktree", "add", "-b", branch, wtPath, "HEAD"]);
4836
4900
  } catch (e) {
4837
4901
  if (e?.code === "ENOENT" || /already exists|not a working tree/i.test(`${e?.stderr || ""} ${e?.message || ""}`)) {
4838
- await fs11.promises.rm(wtPath, { recursive: true, force: true }).catch(() => {
4902
+ await fs12.promises.rm(wtPath, { recursive: true, force: true }).catch(() => {
4839
4903
  });
4840
4904
  await runMainGit(["worktree", "add", "-b", branch, wtPath, "HEAD"]);
4841
4905
  } else {
@@ -4883,7 +4947,7 @@ var init_manager = __esm({
4883
4947
  try {
4884
4948
  await runMainGit(["worktree", "remove", "--force", wt.path]);
4885
4949
  } catch (e) {
4886
- await fs11.promises.rm(wt.path, { recursive: true, force: true }).catch(() => {
4950
+ await fs12.promises.rm(wt.path, { recursive: true, force: true }).catch(() => {
4887
4951
  });
4888
4952
  }
4889
4953
  try {
@@ -4900,30 +4964,30 @@ var init_manager = __esm({
4900
4964
  const root = worktreeRootDir();
4901
4965
  let entries;
4902
4966
  try {
4903
- entries = await fs11.promises.readdir(root);
4967
+ entries = await fs12.promises.readdir(root);
4904
4968
  } catch {
4905
4969
  return;
4906
4970
  }
4907
4971
  let swept = 0;
4908
4972
  for (const sessionIdDir of entries) {
4909
- const sessionPath = path14.join(root, sessionIdDir);
4973
+ const sessionPath = path15.join(root, sessionIdDir);
4910
4974
  let stepDirs;
4911
4975
  try {
4912
- stepDirs = await fs11.promises.readdir(sessionPath);
4976
+ stepDirs = await fs12.promises.readdir(sessionPath);
4913
4977
  } catch {
4914
4978
  continue;
4915
4979
  }
4916
4980
  for (const stepDir of stepDirs) {
4917
- const wtPath = path14.join(sessionPath, stepDir);
4981
+ const wtPath = path15.join(sessionPath, stepDir);
4918
4982
  try {
4919
4983
  await runMainGit(["worktree", "remove", "--force", wtPath]);
4920
4984
  } catch {
4921
- await fs11.promises.rm(wtPath, { recursive: true, force: true }).catch(() => {
4985
+ await fs12.promises.rm(wtPath, { recursive: true, force: true }).catch(() => {
4922
4986
  });
4923
4987
  }
4924
4988
  swept++;
4925
4989
  }
4926
- await fs11.promises.rm(sessionPath, { recursive: true, force: true }).catch(() => {
4990
+ await fs12.promises.rm(sessionPath, { recursive: true, force: true }).catch(() => {
4927
4991
  });
4928
4992
  }
4929
4993
  if (swept > 0) {
@@ -5191,7 +5255,7 @@ var init_workflow = __esm({
5191
5255
 
5192
5256
  // ../core/src/tool/tsHost.ts
5193
5257
  import fsSync3 from "fs";
5194
- import path15 from "path";
5258
+ import path16 from "path";
5195
5259
  var _ts, _tsTried, getTs, buildDefaultOptions, findTsConfigBounded, resolveTsConfig, createProjectHost, lsCache, getLanguageService, realpathNative, posToLineCol, SUPPORTED_SOURCE_EXTS, checkSupportedSourceExt, lineColToPos;
5196
5260
  var init_tsHost = __esm({
5197
5261
  "../core/src/tool/tsHost.ts"() {
@@ -5224,16 +5288,16 @@ var init_tsHost = __esm({
5224
5288
  strict: false
5225
5289
  });
5226
5290
  findTsConfigBounded = (ts, absPath) => {
5227
- const root = path15.resolve(getContainingRoot(absPath));
5228
- let dir = path15.dirname(absPath);
5291
+ const root = path16.resolve(getContainingRoot(absPath));
5292
+ let dir = path16.dirname(absPath);
5229
5293
  while (true) {
5230
- const candidate = path15.join(dir, "tsconfig.json");
5294
+ const candidate = path16.join(dir, "tsconfig.json");
5231
5295
  try {
5232
5296
  if (fsSync3.existsSync(candidate)) return candidate;
5233
5297
  } catch {
5234
5298
  }
5235
- if (path15.resolve(dir) === root) break;
5236
- const parent = path15.dirname(dir);
5299
+ if (path16.resolve(dir) === root) break;
5300
+ const parent = path16.dirname(dir);
5237
5301
  if (parent === dir) break;
5238
5302
  dir = parent;
5239
5303
  }
@@ -5244,7 +5308,7 @@ var init_tsHost = __esm({
5244
5308
  if (!tsConfigPath) {
5245
5309
  return { options: buildDefaultOptions(ts), fileNames: [], projectRoot: getContainingRoot(absPath) };
5246
5310
  }
5247
- const basePath = path15.dirname(tsConfigPath);
5311
+ const basePath = path16.dirname(tsConfigPath);
5248
5312
  const raw = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
5249
5313
  if (raw.error) return { options: buildDefaultOptions(ts), fileNames: [], projectRoot: basePath };
5250
5314
  const parsed = ts.parseJsonConfigFileContent(raw.config, ts.sys, basePath);
@@ -5255,7 +5319,7 @@ var init_tsHost = __esm({
5255
5319
  const roots = /* @__PURE__ */ new Set();
5256
5320
  const caseSensitive = ts.sys.useCaseSensitiveFileNames;
5257
5321
  const canonical = (f) => caseSensitive ? f : f.toLowerCase();
5258
- const keyOf = (f) => canonical(path15.resolve(f)).replace(/\\/g, "/");
5322
+ const keyOf = (f) => canonical(path16.resolve(f)).replace(/\\/g, "/");
5259
5323
  rootFileNames.forEach((f) => roots.add(keyOf(f)));
5260
5324
  const fresh = (fileName) => {
5261
5325
  const key = keyOf(fileName);
@@ -5340,7 +5404,7 @@ var init_tsHost = __esm({
5340
5404
  };
5341
5405
  SUPPORTED_SOURCE_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
5342
5406
  checkSupportedSourceExt = (displayPath) => {
5343
- const ext = path15.extname(displayPath).toLowerCase();
5407
+ const ext = path16.extname(displayPath).toLowerCase();
5344
5408
  if (SUPPORTED_SOURCE_EXTS.has(ext)) return null;
5345
5409
  return `\u274C [\u6587\u4EF6\u7C7B\u578B\u4E0D\u652F\u6301]\uFF1A[${displayPath}] \u7684\u6269\u5C55\u540D ${ext || "(\u65E0)"} \u4E0D\u5728 TS \u5F15\u64CE\u652F\u6301\u8303\u56F4\uFF08\u4EC5 .ts/.tsx/.js/.jsx/.mjs/.cjs\uFF09\u3002\u8BF7\u6539\u7528 read_file/grep \u67E5\u770B\u5185\u5BB9\uFF1B\u7F16\u8BD1/\u7C7B\u578B\u7C7B\u9A8C\u8BC1\u7528 run_command \u8DD1\u5BF9\u5E94\u8BED\u8A00\u5DE5\u5177\u94FE\uFF08\u5982 mvn compile / tsc --noEmit\uFF09\u3002`;
5346
5410
  };
@@ -5349,8 +5413,8 @@ var init_tsHost = __esm({
5349
5413
  });
5350
5414
 
5351
5415
  // ../core/src/tool/registry/fs.ts
5352
- import fs12 from "fs/promises";
5353
- import path16 from "path";
5416
+ import fs13 from "fs/promises";
5417
+ import path17 from "path";
5354
5418
  import { createReadStream } from "fs";
5355
5419
  import * as readline from "readline";
5356
5420
  var isSensitiveReadTarget, stripReadFileLineNumbers, maskSecretsInContent, makeTmpPath, ATOMIC_TMP_RE, sweepStaleAtomicTmp, assertReadable, stripEdgeBlankLines, matchLineBlockWith, diagnoseOldStr, reindentToBase, alignIndentsByAnchor, applyOneEditToContent, fsTools;
@@ -5406,21 +5470,21 @@ var init_fs = __esm({
5406
5470
  const walk = async (dir) => {
5407
5471
  let entries;
5408
5472
  try {
5409
- entries = await fs12.readdir(dir, { withFileTypes: true });
5473
+ entries = await fs13.readdir(dir, { withFileTypes: true });
5410
5474
  } catch {
5411
5475
  return;
5412
5476
  }
5413
5477
  for (const e of entries) {
5414
- const full = path16.join(dir, e.name);
5478
+ const full = path17.join(dir, e.name);
5415
5479
  if (e.isDirectory()) {
5416
5480
  if (!skipDirs.has(e.name)) await walk(full);
5417
5481
  continue;
5418
5482
  }
5419
5483
  if (!e.isFile() || !ATOMIC_TMP_RE.test(e.name)) continue;
5420
5484
  try {
5421
- const st = await fs12.stat(full);
5485
+ const st = await fs13.stat(full);
5422
5486
  if (st.mtimeMs > cutoff) continue;
5423
- await fs12.unlink(full);
5487
+ await fs13.unlink(full);
5424
5488
  removed++;
5425
5489
  } catch {
5426
5490
  }
@@ -5682,11 +5746,11 @@ ${formattedCode}${hasMore ? `
5682
5746
  await initializeWorkspaceIgnore();
5683
5747
  const buildTreeText = async (currentPath, currentDepth, prefix = "") => {
5684
5748
  if (currentDepth > maxDepth || hitScanLimit) return "";
5685
- const entries = await fs12.readdir(currentPath, { withFileTypes: true });
5749
+ const entries = await fs13.readdir(currentPath, { withFileTypes: true });
5686
5750
  const validEntries = entries.filter((entry) => {
5687
5751
  if (entry.isSymbolicLink()) return false;
5688
- const fullPath = path16.join(currentPath, entry.name);
5689
- const relPath = path16.relative(getActiveWorkspaceRoot(), fullPath).replace(/\\/g, "/");
5752
+ const fullPath = path17.join(currentPath, entry.name);
5753
+ const relPath = path17.relative(getActiveWorkspaceRoot(), fullPath).replace(/\\/g, "/");
5690
5754
  return !checkIsPathIgnored(entry.isDirectory() ? `${relPath}/` : relPath);
5691
5755
  });
5692
5756
  let output = "";
@@ -5705,7 +5769,7 @@ ${formattedCode}${hasMore ? `
5705
5769
  `;
5706
5770
  if (entry.isDirectory()) {
5707
5771
  const nextPrefix = prefix + (isLast ? " " : "\u2502 ");
5708
- const fullPath = path16.join(currentPath, entry.name);
5772
+ const fullPath = path17.join(currentPath, entry.name);
5709
5773
  const subTree = await buildTreeText(fullPath, currentDepth + 1, nextPrefix);
5710
5774
  output += subTree;
5711
5775
  }
@@ -5769,7 +5833,7 @@ ${patches}`;
5769
5833
  return `\u274C [\u53C2\u6570\u7F3A\u5931]\uFF1A\u8BF7\u4F20\u5165 edits \u6570\u7EC4\uFF08\u6BCF\u6761\u542B old_str/new_str\uFF09\u4E00\u6B21\u5B8C\u6210\u591A\u5904\u4FEE\u6539\uFF0C\u6216\u9876\u5C42 old_str + new_str \u4FEE\u6539\u5355\u5904\u3002old_str \u4E0D\u80FD\u4E3A\u7A7A\u3002`;
5770
5834
  }
5771
5835
  const absPath = resolveSafePath(args.path);
5772
- const rawContent = await fs12.readFile(absPath, "utf-8");
5836
+ const rawContent = await fs13.readFile(absPath, "utf-8");
5773
5837
  const isCRLF = rawContent.includes("\r\n");
5774
5838
  let content = rawContent.replace(/\r\n/g, "\n");
5775
5839
  const summaries = [];
@@ -5782,7 +5846,7 @@ ${patches}`;
5782
5846
  summaries.push(editList.length === 1 ? r.summary : ` ${i + 1}. ${r.summary}`);
5783
5847
  }
5784
5848
  assertWithinWorkspace(absPath);
5785
- await fs12.writeFile(absPath, isCRLF ? content.replace(/\n/g, "\r\n") : content, "utf-8");
5849
+ await fs13.writeFile(absPath, isCRLF ? content.replace(/\n/g, "\r\n") : content, "utf-8");
5786
5850
  return editList.length === 1 ? `\u2705 [\u4EE3\u7801\u4FEE\u8865\u6210\u529F]\uFF1A\u6587\u4EF6 [${args.path}] ${summaries[0]}` : `\u2705 [\u4EE3\u7801\u4FEE\u8865\u6210\u529F]\uFF1A\u6587\u4EF6 [${args.path}] \u5DF2\u6309\u5E8F\u5B8C\u6210 ${editList.length} \u5904\u4FEE\u6539\uFF08\u5355\u6B21\u539F\u5B50\u5199\u5165\uFF09\uFF1A
5787
5851
  ${summaries.join("\n")}`;
5788
5852
  } catch (error) {
@@ -5812,24 +5876,24 @@ ${summaries.join("\n")}`;
5812
5876
  try {
5813
5877
  const absPath = resolveSafePath(args.path);
5814
5878
  try {
5815
- await fs12.access(absPath);
5879
+ await fs13.access(absPath);
5816
5880
  return `\u274C [\u521B\u5EFA\u5931\u8D25]\uFF1A\u6587\u4EF6 [${args.path}] \u5DF2\u5B58\u5728\u3002create_file \u4EC5\u7528\u4E8E\u65B0\u5EFA\u6587\u4EF6\uFF1B\u5982\u9700\u4FEE\u6539\u8BF7\u7528 edit_file\uFF0C\u5982\u9700\u8986\u76D6\u8BF7\u7528 write_file\u3002`;
5817
5881
  } catch (e) {
5818
5882
  if (e?.code !== "ENOENT") throw e;
5819
5883
  }
5820
5884
  const content = args.content ?? "";
5821
5885
  assertWithinWorkspace(absPath);
5822
- await fs12.mkdir(path16.dirname(absPath), { recursive: true });
5886
+ await fs13.mkdir(path17.dirname(absPath), { recursive: true });
5823
5887
  tmpPath = makeTmpPath(absPath);
5824
- await fs12.writeFile(tmpPath, content, "utf-8");
5825
- await fs12.rename(tmpPath, absPath);
5888
+ await fs13.writeFile(tmpPath, content, "utf-8");
5889
+ await fs13.rename(tmpPath, absPath);
5826
5890
  return `\u2705 [\u521B\u5EFA\u6210\u529F]\uFF1A\u65B0\u6587\u4EF6 [${args.path}] \u5DF2\u521B\u5EFA\uFF0C\u5199\u5165 ${content.length} \u5B57\u7B26\u3002`;
5827
5891
  } catch (error) {
5828
5892
  return `\u64CD\u4F5C\u5931\u8D25: ${error.message}`;
5829
5893
  } finally {
5830
5894
  if (tmpPath) {
5831
5895
  try {
5832
- await fs12.unlink(tmpPath);
5896
+ await fs13.unlink(tmpPath);
5833
5897
  } catch {
5834
5898
  }
5835
5899
  }
@@ -5858,7 +5922,7 @@ ${summaries.join("\n")}`;
5858
5922
  }
5859
5923
  let rel = "";
5860
5924
  try {
5861
- rel = path16.relative(getActiveWorkspaceRoot(), resolveSafePath(cleanPath));
5925
+ rel = path17.relative(getActiveWorkspaceRoot(), resolveSafePath(cleanPath));
5862
5926
  } catch {
5863
5927
  }
5864
5928
  if (rel === "" || rel === "src") {
@@ -5866,7 +5930,7 @@ ${summaries.join("\n")}`;
5866
5930
  }
5867
5931
  let label = "\u6587\u4EF6\u6216\u76EE\u5F55";
5868
5932
  try {
5869
- const stat = await fs12.stat(resolveSafePath(cleanPath));
5933
+ const stat = await fs13.stat(resolveSafePath(cleanPath));
5870
5934
  label = stat.isDirectory() ? "\u4E00\u6574\u4E2A\u6587\u4EF6\u5939\u76EE\u5F55" : "\u7EAF\u7269\u7406\u6587\u4EF6";
5871
5935
  } catch {
5872
5936
  }
@@ -5879,22 +5943,22 @@ ${summaries.join("\n")}`;
5879
5943
  return `\u274C [\u5B89\u5168\u7194\u65AD]\uFF1A\u7981\u6B62\u901A\u8FC7\u672C\u5DE5\u5177\u76F4\u63A5\u6467\u6BC1\u9879\u76EE\u6839\u76EE\u5F55\u6216\u4F20\u5165\u7A7A\u8DEF\u5F84\uFF01`;
5880
5944
  }
5881
5945
  const absPath = resolveSafePath(cleanPath);
5882
- const rel = path16.relative(getActiveWorkspaceRoot(), absPath);
5883
- if (!rel || rel === "" || rel === "src" || rel.startsWith("..") || path16.isAbsolute(rel)) {
5946
+ const rel = path17.relative(getActiveWorkspaceRoot(), absPath);
5947
+ if (!rel || rel === "" || rel === "src" || rel.startsWith("..") || path17.isAbsolute(rel)) {
5884
5948
  return `\u274C [\u5B89\u5168\u7194\u65AD]\uFF1A\u62D2\u7EDD\u9500\u6BC1\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55 / src \u6E90\u7801\u6839 / \u8D8A\u754C\u8DEF\u5F84 [${cleanPath}]\uFF01`;
5885
5949
  }
5886
5950
  let stat;
5887
5951
  try {
5888
- stat = await fs12.stat(absPath);
5952
+ stat = await fs13.stat(absPath);
5889
5953
  } catch {
5890
5954
  return `\u274C [\u9500\u6BC1\u5931\u8D25]\uFF1A\u5728\u5DE5\u4F5C\u533A\u5185\u672A\u627E\u5230\u6307\u5B9A\u7684\u8DEF\u5F84 [${cleanPath}]\u3002`;
5891
5955
  }
5892
5956
  const isDirectory = stat.isDirectory();
5893
5957
  assertWithinWorkspace(absPath);
5894
5958
  if (isDirectory) {
5895
- await fs12.rm(absPath, { recursive: true, force: true });
5959
+ await fs13.rm(absPath, { recursive: true, force: true });
5896
5960
  } else {
5897
- await fs12.unlink(absPath);
5961
+ await fs13.unlink(absPath);
5898
5962
  }
5899
5963
  const targetTypeLabel = isDirectory ? "\u4E00\u6574\u4E2A\u6587\u4EF6\u5939\u76EE\u5F55" : "\u7EAF\u7269\u7406\u6587\u4EF6";
5900
5964
  return `\u2705 [\u8DEF\u5F84\u9500\u6BC1\u6210\u529F]\uFF1A\u5DF2\u6210\u529F\u6C38\u4E45\u9500\u6BC1${targetTypeLabel} [${cleanPath}]\u3002`;
@@ -5925,15 +5989,15 @@ ${summaries.join("\n")}`;
5925
5989
  try {
5926
5990
  const absPath = resolveSafePath(args.path);
5927
5991
  assertWithinWorkspace(absPath);
5928
- await fs12.mkdir(path16.dirname(absPath), { recursive: true });
5992
+ await fs13.mkdir(path17.dirname(absPath), { recursive: true });
5929
5993
  tmpPath = makeTmpPath(absPath);
5930
- await fs12.writeFile(tmpPath, args.content, "utf-8");
5931
- await fs12.rename(tmpPath, absPath);
5994
+ await fs13.writeFile(tmpPath, args.content, "utf-8");
5995
+ await fs13.rename(tmpPath, absPath);
5932
5996
  return `\u2705 [\u6587\u4EF6\u5199\u5165\u6210\u529F]\uFF1A\u5DF2\u5168\u91CF\u5199\u5165 [${args.path}]\uFF08${args.content.length} \u5B57\u7B26\uFF09\u3002`;
5933
5997
  } catch (error) {
5934
5998
  if (tmpPath) {
5935
5999
  try {
5936
- await fs12.unlink(tmpPath);
6000
+ await fs13.unlink(tmpPath);
5937
6001
  } catch {
5938
6002
  }
5939
6003
  }
@@ -5964,11 +6028,11 @@ ${summaries.join("\n")}`;
5964
6028
  if (readBlock) return readBlock;
5965
6029
  const extBlock = checkSupportedSourceExt(args.path);
5966
6030
  if (extBlock) return extBlock;
5967
- const statForSize = await fs12.stat(absPath);
6031
+ const statForSize = await fs13.stat(absPath);
5968
6032
  if (statForSize.size > 1024 * 1024) {
5969
6033
  return `\u26A0\uFE0F [\u6587\u4EF6\u8FC7\u5927]\uFF1A[${args.path}] \u7EA6 ${Math.round(statForSize.size / 1024)}KB\uFF0C\u8D85\u8FC7\u7B26\u53F7\u5927\u7EB2\u5206\u6790\u7684 1MB \u4E0A\u9650\uFF08\u9632\u5168\u91CF readFile + AST \u9A7B\u7559\u5403\u5185\u5B58\uFF09\u3002\u8BF7\u6539\u7528 read_file \u5206\u7247\u67E5\u770B\uFF0C\u6216\u7F29\u5C0F\u76EE\u6807\u6587\u4EF6\u3002`;
5970
6034
  }
5971
- const fileContent = await fs12.readFile(absPath, "utf-8");
6035
+ const fileContent = await fs13.readFile(absPath, "utf-8");
5972
6036
  const TS = await getTs();
5973
6037
  if (!TS) {
5974
6038
  return `\u26A0\uFE0F [\u7B26\u53F7\u5927\u7EB2\u4E0D\u53EF\u7528]\uFF1Atypescript \u6A21\u5757\u672A\u5B89\u88C5\uFF08CLI \u53D1\u5E03\u7248\u672A\u5185\u8054\uFF09\u3002\u8BF7\u6539\u7528 read_file \u67E5\u770B\u6587\u4EF6\u5185\u5BB9\u3002`;
@@ -6050,19 +6114,19 @@ ${summaries.join("\n")}`;
6050
6114
  const srcAbs = resolveSafePath(args.source);
6051
6115
  const dstAbs = resolveSafePath(args.destination);
6052
6116
  try {
6053
- await fs12.access(srcAbs);
6117
+ await fs13.access(srcAbs);
6054
6118
  } catch {
6055
6119
  return `\u274C [\u79FB\u52A8\u5931\u8D25]\uFF1A\u6E90\u8DEF\u5F84 [${args.source}] \u4E0D\u5B58\u5728\u3002`;
6056
6120
  }
6057
6121
  try {
6058
- await fs12.access(dstAbs);
6122
+ await fs13.access(dstAbs);
6059
6123
  return `\u274C [\u79FB\u52A8\u5931\u8D25]\uFF1A\u76EE\u6807 [${args.destination}] \u5DF2\u5B58\u5728\u3002\u5982\u9700\u8986\u76D6\u8BF7\u5148 delete_path \u518D move_file\u3002`;
6060
6124
  } catch {
6061
6125
  }
6062
6126
  assertWithinWorkspace(srcAbs);
6063
6127
  assertWithinWorkspace(dstAbs);
6064
- await fs12.mkdir(path16.dirname(dstAbs), { recursive: true });
6065
- await fs12.rename(srcAbs, dstAbs);
6128
+ await fs13.mkdir(path17.dirname(dstAbs), { recursive: true });
6129
+ await fs13.rename(srcAbs, dstAbs);
6066
6130
  return `\u2705 [\u79FB\u52A8\u6210\u529F]\uFF1A[${args.source}] \u2192 [${args.destination}]\u3002`;
6067
6131
  } catch (error) {
6068
6132
  return `\u64CD\u4F5C\u5931\u8D25: ${error.message}`;
@@ -6076,8 +6140,8 @@ ${summaries.join("\n")}`;
6076
6140
 
6077
6141
  // ../core/src/tool/registry/search.ts
6078
6142
  import { rgPath } from "vscode-ripgrep";
6079
- import path17 from "path";
6080
- import fs13 from "fs/promises";
6143
+ import path18 from "path";
6144
+ import fs14 from "fs/promises";
6081
6145
  function escapeRegExp(string) {
6082
6146
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6083
6147
  }
@@ -6119,10 +6183,10 @@ var init_search = __esm({
6119
6183
  const resolveSearchRoot = () => {
6120
6184
  if (!args.path) return ctx?.cwd ?? getActiveWorkspaceRoot();
6121
6185
  const p = args.path.trim();
6122
- const looksLikeBareName = !path17.isAbsolute(p) && !p.includes("/") && !p.includes("\\");
6186
+ const looksLikeBareName = !path18.isAbsolute(p) && !p.includes("/") && !p.includes("\\");
6123
6187
  if (looksLikeBareName) {
6124
6188
  const hit = getAllowedWorkspaceRoots().find((r) => {
6125
- const bn = path17.basename(r);
6189
+ const bn = path18.basename(r);
6126
6190
  return bn === p || bn.toLowerCase() === p.toLowerCase();
6127
6191
  });
6128
6192
  if (hit) return hit;
@@ -6211,7 +6275,7 @@ var init_search = __esm({
6211
6275
  const GUIDE_CANDIDATES = ["CLAUDE.md", "AGENTS.md", "AGENT.md"];
6212
6276
  for (const name of GUIDE_CANDIDATES) {
6213
6277
  try {
6214
- const content = await fs13.readFile(path17.join(getActiveWorkspaceRoot(), name), "utf-8");
6278
+ const content = await fs14.readFile(path18.join(getActiveWorkspaceRoot(), name), "utf-8");
6215
6279
  return `[Project Guide via ${name}]
6216
6280
 
6217
6281
  ${content}`;
@@ -6498,8 +6562,8 @@ ${AUTO_BG_NOTICE}
6498
6562
  });
6499
6563
 
6500
6564
  // ../core/src/tool/registry/glob.ts
6501
- import fs14 from "fs/promises";
6502
- import path18 from "path";
6565
+ import fs15 from "fs/promises";
6566
+ import path19 from "path";
6503
6567
  var findMatchingBrace, splitTopLevel, globToRegex2, globTools;
6504
6568
  var init_glob = __esm({
6505
6569
  "../core/src/tool/registry/glob.ts"() {
@@ -6603,18 +6667,18 @@ var init_glob = __esm({
6603
6667
  const MAX_SCAN_LIMIT = 1e4;
6604
6668
  const scan = async (dir) => {
6605
6669
  if (scannedCount > MAX_SCAN_LIMIT) return;
6606
- const entries = await fs14.readdir(dir, { withFileTypes: true });
6670
+ const entries = await fs15.readdir(dir, { withFileTypes: true });
6607
6671
  const validEntries = entries.filter((e) => {
6608
- const full = path18.join(dir, e.name);
6609
- const rel = path18.relative(activeRoot, full).replace(/\\/g, "/");
6672
+ const full = path19.join(dir, e.name);
6673
+ const rel = path19.relative(activeRoot, full).replace(/\\/g, "/");
6610
6674
  return !checkIsPathIgnored(e.isDirectory() ? `${rel}/` : rel);
6611
6675
  });
6612
6676
  for (const e of validEntries) {
6613
6677
  scannedCount++;
6614
6678
  if (scannedCount > MAX_SCAN_LIMIT) break;
6615
6679
  if (e.isSymbolicLink()) continue;
6616
- const full = path18.join(dir, e.name);
6617
- const rel = path18.relative(activeRoot, full).replace(/\\/g, "/");
6680
+ const full = path19.join(dir, e.name);
6681
+ const rel = path19.relative(activeRoot, full).replace(/\\/g, "/");
6618
6682
  if (e.isDirectory()) {
6619
6683
  if (cleanPattern.endsWith("/") && re.test(`${rel}/`)) {
6620
6684
  hits.push(`${rel}/`);
@@ -6830,8 +6894,8 @@ ${summary}`;
6830
6894
  });
6831
6895
 
6832
6896
  // ../core/src/tool/registry/inspect_dependencies.ts
6833
- import * as fs15 from "fs/promises";
6834
- import * as path19 from "path";
6897
+ import * as fs16 from "fs/promises";
6898
+ import * as path20 from "path";
6835
6899
  var dependencyTools;
6836
6900
  var init_inspect_dependencies = __esm({
6837
6901
  "../core/src/tool/registry/inspect_dependencies.ts"() {
@@ -6852,8 +6916,8 @@ var init_inspect_dependencies = __esm({
6852
6916
  isSync: true,
6853
6917
  async execute() {
6854
6918
  try {
6855
- const pjsPath = path19.join(getActiveWorkspaceRoot(), "package.json");
6856
- const raw = await fs15.readFile(pjsPath, "utf-8");
6919
+ const pjsPath = path20.join(getActiveWorkspaceRoot(), "package.json");
6920
+ const raw = await fs16.readFile(pjsPath, "utf-8");
6857
6921
  const pjs = JSON.parse(raw);
6858
6922
  const result = {
6859
6923
  dependencies: pjs.dependencies || {},
@@ -7495,8 +7559,8 @@ var init_http = __esm({
7495
7559
  });
7496
7560
 
7497
7561
  // ../core/src/tool/registry/typescript.ts
7498
- import fs16 from "fs/promises";
7499
- import path20 from "path";
7562
+ import fs17 from "fs/promises";
7563
+ import path21 from "path";
7500
7564
  var MAX_FILE_BYTES, toDisplayPath, isLibFile, precheck, MAX_DIAG_ENTRIES, MAX_DIAG_FILES, MAX_REF_ENTRIES, REF_SNIPPET_MAX, diagnoseOneFile, typescriptTools;
7501
7565
  var init_typescript = __esm({
7502
7566
  "../core/src/tool/registry/typescript.ts"() {
@@ -7507,8 +7571,8 @@ var init_typescript = __esm({
7507
7571
  init_fs();
7508
7572
  MAX_FILE_BYTES = 1024 * 1024;
7509
7573
  toDisplayPath = (wsRoot, abs) => {
7510
- const rel = path20.relative(wsRoot, abs);
7511
- if (rel && !rel.startsWith("..") && !path20.isAbsolute(rel)) return rel.replace(/\\/g, "/");
7574
+ const rel = path21.relative(wsRoot, abs);
7575
+ if (rel && !rel.startsWith("..") && !path21.isAbsolute(rel)) return rel.replace(/\\/g, "/");
7512
7576
  return abs.replace(/\\/g, "/").split("/").slice(-3).join("/");
7513
7577
  };
7514
7578
  isLibFile = (abs) => /(?:^|\/)node_modules\//.test(abs.replace(/\\/g, "/")) || /\.d\.ts$/i.test(abs);
@@ -7517,7 +7581,7 @@ var init_typescript = __esm({
7517
7581
  if (readBlock) return readBlock;
7518
7582
  const extBlock = checkSupportedSourceExt(displayPath);
7519
7583
  if (extBlock) return extBlock;
7520
- const stat = await fs16.stat(absPath);
7584
+ const stat = await fs17.stat(absPath);
7521
7585
  if (stat.size > MAX_FILE_BYTES) {
7522
7586
  return `\u26A0\uFE0F [\u6587\u4EF6\u8FC7\u5927]\uFF1A[${displayPath}] \u7EA6 ${Math.round(stat.size / 1024)}KB\uFF0C\u8D85\u8FC7 ${MAX_FILE_BYTES / 1024}KB \u4E0A\u9650\uFF08\u9632\u5168\u91CF type-check \u5403\u5185\u5B58\uFF09\u3002`;
7523
7587
  }
@@ -7733,7 +7797,7 @@ ${out.join("\n")}`;
7733
7797
  let lines = lineTextCache.get(abs);
7734
7798
  if (!lines) {
7735
7799
  try {
7736
- lines = (await fs16.readFile(abs, "utf-8")).split(/\r?\n/);
7800
+ lines = (await fs17.readFile(abs, "utf-8")).split(/\r?\n/);
7737
7801
  } catch {
7738
7802
  lines = [];
7739
7803
  }
@@ -7862,8 +7926,8 @@ var init_todo = __esm({
7862
7926
  });
7863
7927
 
7864
7928
  // ../core/src/observability/traceCalculate.ts
7865
- import fs17 from "fs/promises";
7866
- import path21 from "path";
7929
+ import fs18 from "fs/promises";
7930
+ import path22 from "path";
7867
7931
  var getDirBytes, getTodayDateString;
7868
7932
  var init_traceCalculate = __esm({
7869
7933
  "../core/src/observability/traceCalculate.ts"() {
@@ -7875,17 +7939,17 @@ var init_traceCalculate = __esm({
7875
7939
  const cur = stack.pop();
7876
7940
  let entries;
7877
7941
  try {
7878
- entries = await fs17.readdir(cur, { withFileTypes: true });
7942
+ entries = await fs18.readdir(cur, { withFileTypes: true });
7879
7943
  } catch {
7880
7944
  continue;
7881
7945
  }
7882
7946
  for (const e of entries) {
7883
- const p = path21.join(cur, e.name);
7947
+ const p = path22.join(cur, e.name);
7884
7948
  if (e.isDirectory()) {
7885
7949
  stack.push(p);
7886
7950
  } else {
7887
7951
  try {
7888
- total += (await fs17.stat(p)).size;
7952
+ total += (await fs18.stat(p)).size;
7889
7953
  } catch {
7890
7954
  }
7891
7955
  }
@@ -7904,8 +7968,8 @@ var init_traceCalculate = __esm({
7904
7968
  });
7905
7969
 
7906
7970
  // ../core/src/tool/undo/store.ts
7907
- import path22 from "path";
7908
- import fs18 from "fs/promises";
7971
+ import path23 from "path";
7972
+ import fs19 from "fs/promises";
7909
7973
  var getUndoRootPath, getUndoClockPath, getUndoDirPath, getUndoBackupRoot, ensureUndoDir, getUndoIndexPath;
7910
7974
  var init_store2 = __esm({
7911
7975
  "../core/src/tool/undo/store.ts"() {
@@ -7913,33 +7977,33 @@ var init_store2 = __esm({
7913
7977
  init_config();
7914
7978
  init_common();
7915
7979
  init_traceCalculate();
7916
- getUndoRootPath = () => path22.join(appConfig.dataDir, "undo");
7917
- getUndoClockPath = () => path22.join(getUndoRootPath(), "undo-cleanup-clock.json");
7980
+ getUndoRootPath = () => path23.join(appConfig.dataDir, "undo");
7981
+ getUndoClockPath = () => path23.join(getUndoRootPath(), "undo-cleanup-clock.json");
7918
7982
  getUndoDirPath = (mainSessionId) => {
7919
7983
  const rootId = getFileName(mainSessionId);
7920
7984
  assertSafeSessionId(rootId, "undoSessionId");
7921
- return path22.join(getUndoRootPath(), appConfig.userWorkspaceDir, rootId);
7985
+ return path23.join(getUndoRootPath(), appConfig.userWorkspaceDir, rootId);
7922
7986
  };
7923
- getUndoBackupRoot = (mainSessionId) => path22.join(getUndoDirPath(mainSessionId), "backups");
7987
+ getUndoBackupRoot = (mainSessionId) => path23.join(getUndoDirPath(mainSessionId), "backups");
7924
7988
  ensureUndoDir = async (mainSessionId) => {
7925
- await fs18.mkdir(getUndoDirPath(mainSessionId), { recursive: true, mode: 448 });
7989
+ await fs19.mkdir(getUndoDirPath(mainSessionId), { recursive: true, mode: 448 });
7926
7990
  };
7927
7991
  getUndoIndexPath = async (mainSessionId) => {
7928
7992
  const rootId = getFileName(mainSessionId);
7929
7993
  assertSafeSessionId(rootId, "undoSessionId");
7930
7994
  const dir = getUndoDirPath(mainSessionId);
7931
- await fs18.mkdir(dir, { recursive: true, mode: 448 });
7932
- const files = await fs18.readdir(dir);
7995
+ await fs19.mkdir(dir, { recursive: true, mode: 448 });
7996
+ const files = await fs19.readdir(dir);
7933
7997
  const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
7934
7998
  const fileName = existedFile ?? `undo-${getTodayDateString()}__${rootId}.jsonl`;
7935
- return path22.join(dir, fileName);
7999
+ return path23.join(dir, fileName);
7936
8000
  };
7937
8001
  }
7938
8002
  });
7939
8003
 
7940
8004
  // ../core/src/tool/undo/index.ts
7941
- import fs19 from "fs/promises";
7942
- import path23 from "path";
8005
+ import fs20 from "fs/promises";
8006
+ import path24 from "path";
7943
8007
  var undoLocks, withUndoLock, appendUndoRecord, readUndoIndex, markRestored;
7944
8008
  var init_undo = __esm({
7945
8009
  "../core/src/tool/undo/index.ts"() {
@@ -7969,7 +8033,7 @@ var init_undo = __esm({
7969
8033
  };
7970
8034
  const p = await getUndoIndexPath(sessionId);
7971
8035
  const line = JSON.stringify(enriched) + "\n";
7972
- await fs19.appendFile(p, line, { encoding: "utf-8", mode: 384 });
8036
+ await fs20.appendFile(p, line, { encoding: "utf-8", mode: 384 });
7973
8037
  });
7974
8038
  };
7975
8039
  readUndoIndex = async (sessionId) => {
@@ -7981,7 +8045,7 @@ var init_undo = __esm({
7981
8045
  }
7982
8046
  let files;
7983
8047
  try {
7984
- files = await fs19.readdir(dir);
8048
+ files = await fs20.readdir(dir);
7985
8049
  } catch {
7986
8050
  return [];
7987
8051
  }
@@ -7989,7 +8053,7 @@ var init_undo = __esm({
7989
8053
  for (const f of files) {
7990
8054
  if (!f.startsWith("undo-") || !f.endsWith(".jsonl")) continue;
7991
8055
  try {
7992
- const raw = await fs19.readFile(path23.join(dir, f), "utf-8");
8056
+ const raw = await fs20.readFile(path24.join(dir, f), "utf-8");
7993
8057
  for (const line of raw.split("\n")) {
7994
8058
  const trimmed = line.trim();
7995
8059
  if (!trimmed) continue;
@@ -8014,16 +8078,16 @@ var init_undo = __esm({
8014
8078
  }
8015
8079
  let files;
8016
8080
  try {
8017
- files = await fs19.readdir(dir);
8081
+ files = await fs20.readdir(dir);
8018
8082
  } catch {
8019
8083
  return;
8020
8084
  }
8021
8085
  for (const f of files) {
8022
8086
  if (!f.startsWith("undo-") || !f.endsWith(".jsonl")) continue;
8023
- const fp = path23.join(dir, f);
8087
+ const fp = path24.join(dir, f);
8024
8088
  let raw;
8025
8089
  try {
8026
- raw = await fs19.readFile(fp, "utf-8");
8090
+ raw = await fs20.readFile(fp, "utf-8");
8027
8091
  } catch {
8028
8092
  continue;
8029
8093
  }
@@ -8047,8 +8111,8 @@ var init_undo = __esm({
8047
8111
  if (changed) {
8048
8112
  const content = lines.join("\n").replace(/\n*$/, "\n");
8049
8113
  const tmp = fp + ".tmp";
8050
- await fs19.writeFile(tmp, content, { encoding: "utf-8", mode: 384 });
8051
- await fs19.rename(tmp, fp);
8114
+ await fs20.writeFile(tmp, content, { encoding: "utf-8", mode: 384 });
8115
+ await fs20.rename(tmp, fp);
8052
8116
  }
8053
8117
  }
8054
8118
  });
@@ -8057,8 +8121,8 @@ var init_undo = __esm({
8057
8121
  });
8058
8122
 
8059
8123
  // ../core/src/tool/undo/cleanup.ts
8060
- import fs20 from "fs/promises";
8061
- import path24 from "path";
8124
+ import fs21 from "fs/promises";
8125
+ import path25 from "path";
8062
8126
  async function maybeCleanupAfterUndoAppend(_sessionId) {
8063
8127
  if (cleanupInProgress) return;
8064
8128
  cleanupInProgress = true;
@@ -8084,8 +8148,8 @@ async function maybeCleanupAfterUndoAppend(_sessionId) {
8084
8148
  lastSizeCleanupAt = now;
8085
8149
  diskLastCleanupAt = now;
8086
8150
  const clockPath = getUndoClockPath();
8087
- await fs20.mkdir(path24.dirname(clockPath), { recursive: true });
8088
- await fs20.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
8151
+ await fs21.mkdir(path25.dirname(clockPath), { recursive: true });
8152
+ await fs21.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
8089
8153
  if (deleted > 0) console.log(`\u2728 [Undo\u8FD0\u7EF4] \u5171\u9500\u6BC1 ${deleted} \u4E2A undo \u8D44\u4EA7\uFF08\u7D22\u5F15 + \u5B64\u513F\u5185\u5BB9\uFF09\uFF0C\u78C1\u76D8\u6C34\u4F4D\u56DE\u843D\u3002`);
8090
8154
  } catch (e) {
8091
8155
  console.warn("\u26A0\uFE0F [Undo\u8FD0\u7EF4] \u81EA\u52A8\u6E05\u7406\u5F02\u5E38\uFF0C\u5DF2\u8DF3\u8FC7:", e?.message ?? e);
@@ -8102,23 +8166,23 @@ async function cleanupOldUndoFiles() {
8102
8166
  const now = Date.now();
8103
8167
  let relativePaths;
8104
8168
  try {
8105
- relativePaths = await fs20.readdir(dir, { recursive: true });
8169
+ relativePaths = await fs21.readdir(dir, { recursive: true });
8106
8170
  } catch {
8107
8171
  return 0;
8108
8172
  }
8109
8173
  const re = /^undo-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
8110
8174
  let deleted = 0;
8111
8175
  for (const rp of relativePaths) {
8112
- const fileName = path24.basename(rp);
8176
+ const fileName = path25.basename(rp);
8113
8177
  const m = fileName.match(re);
8114
8178
  if (!m) continue;
8115
8179
  const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
8116
8180
  if (fileBornDay >= cutoff) continue;
8117
- const fullPath = path24.join(dir, rp);
8181
+ const fullPath = path25.join(dir, rp);
8118
8182
  try {
8119
- const st = await fs20.stat(fullPath);
8183
+ const st = await fs21.stat(fullPath);
8120
8184
  if (now - st.mtimeMs < ACTIVE_GRACE_MS) continue;
8121
- await fs20.unlink(fullPath);
8185
+ await fs21.unlink(fullPath);
8122
8186
  deleted += 1;
8123
8187
  } catch {
8124
8188
  }
@@ -8129,17 +8193,17 @@ async function evictOldestForSize(targetBytes) {
8129
8193
  const dir = getUndoRootPath();
8130
8194
  let relativePaths;
8131
8195
  try {
8132
- relativePaths = await fs20.readdir(dir, { recursive: true });
8196
+ relativePaths = await fs21.readdir(dir, { recursive: true });
8133
8197
  } catch {
8134
8198
  return 0;
8135
8199
  }
8136
8200
  const re = /^undo-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
8137
8201
  const candidates = [];
8138
8202
  for (const rp of relativePaths) {
8139
- if (!re.test(path24.basename(rp))) continue;
8203
+ if (!re.test(path25.basename(rp))) continue;
8140
8204
  try {
8141
- const st = await fs20.stat(path24.join(dir, rp));
8142
- candidates.push({ mtime: st.mtimeMs, fullPath: path24.join(dir, rp), size: st.size });
8205
+ const st = await fs21.stat(path25.join(dir, rp));
8206
+ candidates.push({ mtime: st.mtimeMs, fullPath: path25.join(dir, rp), size: st.size });
8143
8207
  } catch {
8144
8208
  }
8145
8209
  }
@@ -8149,7 +8213,7 @@ async function evictOldestForSize(targetBytes) {
8149
8213
  for (const c of candidates) {
8150
8214
  if (totalBytes <= targetBytes) break;
8151
8215
  try {
8152
- await fs20.unlink(c.fullPath);
8216
+ await fs21.unlink(c.fullPath);
8153
8217
  totalBytes -= c.size;
8154
8218
  deleted += 1;
8155
8219
  } catch {
@@ -8163,38 +8227,38 @@ async function gcOrphanBackups() {
8163
8227
  let deleted = 0;
8164
8228
  let workspaces;
8165
8229
  try {
8166
- workspaces = await fs20.readdir(root);
8230
+ workspaces = await fs21.readdir(root);
8167
8231
  } catch {
8168
8232
  return 0;
8169
8233
  }
8170
8234
  for (const ws of workspaces) {
8171
- const wsDir = path24.join(root, ws);
8235
+ const wsDir = path25.join(root, ws);
8172
8236
  let stWs;
8173
8237
  try {
8174
- stWs = await fs20.stat(wsDir);
8238
+ stWs = await fs21.stat(wsDir);
8175
8239
  } catch {
8176
8240
  continue;
8177
8241
  }
8178
8242
  if (!stWs.isDirectory()) continue;
8179
8243
  let sessions2;
8180
8244
  try {
8181
- sessions2 = await fs20.readdir(wsDir);
8245
+ sessions2 = await fs21.readdir(wsDir);
8182
8246
  } catch {
8183
8247
  continue;
8184
8248
  }
8185
8249
  for (const sess of sessions2) {
8186
- const sessDir = path24.join(wsDir, sess);
8250
+ const sessDir = path25.join(wsDir, sess);
8187
8251
  const liveIds = /* @__PURE__ */ new Set();
8188
8252
  let files;
8189
8253
  try {
8190
- files = await fs20.readdir(sessDir);
8254
+ files = await fs21.readdir(sessDir);
8191
8255
  } catch {
8192
8256
  continue;
8193
8257
  }
8194
8258
  for (const f of files) {
8195
8259
  if (!f.startsWith("undo-") || !f.endsWith(".jsonl")) continue;
8196
8260
  try {
8197
- const raw = await fs20.readFile(path24.join(sessDir, f), "utf-8");
8261
+ const raw = await fs21.readFile(path25.join(sessDir, f), "utf-8");
8198
8262
  for (const line of raw.split("\n")) {
8199
8263
  const t = line.trim();
8200
8264
  if (!t) continue;
@@ -8207,17 +8271,17 @@ async function gcOrphanBackups() {
8207
8271
  } catch {
8208
8272
  }
8209
8273
  }
8210
- const backupsDir = path24.join(sessDir, "backups");
8274
+ const backupsDir = path25.join(sessDir, "backups");
8211
8275
  let undoDirs;
8212
8276
  try {
8213
- undoDirs = await fs20.readdir(backupsDir);
8277
+ undoDirs = await fs21.readdir(backupsDir);
8214
8278
  } catch {
8215
8279
  continue;
8216
8280
  }
8217
8281
  for (const ud of undoDirs) {
8218
8282
  if (liveIds.has(ud)) continue;
8219
8283
  try {
8220
- await fs20.rm(path24.join(backupsDir, ud), { recursive: true, force: true });
8284
+ await fs21.rm(path25.join(backupsDir, ud), { recursive: true, force: true });
8221
8285
  deleted += 1;
8222
8286
  } catch {
8223
8287
  }
@@ -8245,7 +8309,7 @@ var init_cleanup = __esm({
8245
8309
  if (clockLoaded) return;
8246
8310
  clockLoaded = true;
8247
8311
  try {
8248
- const rawClock = await fs20.readFile(getUndoClockPath(), "utf-8");
8312
+ const rawClock = await fs21.readFile(getUndoClockPath(), "utf-8");
8249
8313
  diskLastCleanupAt = JSON.parse(rawClock).lastCleanupAt || 0;
8250
8314
  } catch {
8251
8315
  diskLastCleanupAt = 0;
@@ -8255,17 +8319,17 @@ var init_cleanup = __esm({
8255
8319
  let total = 0;
8256
8320
  let entries;
8257
8321
  try {
8258
- entries = await fs20.readdir(dir, { withFileTypes: true });
8322
+ entries = await fs21.readdir(dir, { withFileTypes: true });
8259
8323
  } catch {
8260
8324
  return 0;
8261
8325
  }
8262
8326
  for (const e of entries) {
8263
- const full = path24.join(dir, e.name);
8327
+ const full = path25.join(dir, e.name);
8264
8328
  if (e.isDirectory()) {
8265
8329
  total += await getDirBytesRecursive(full);
8266
8330
  } else if (e.isFile()) {
8267
8331
  try {
8268
- total += (await fs20.stat(full)).size;
8332
+ total += (await fs21.stat(full)).size;
8269
8333
  } catch {
8270
8334
  }
8271
8335
  }
@@ -8276,8 +8340,8 @@ var init_cleanup = __esm({
8276
8340
  });
8277
8341
 
8278
8342
  // ../core/src/tool/undo/backup.ts
8279
- import fs21 from "fs/promises";
8280
- import path25 from "path";
8343
+ import fs22 from "fs/promises";
8344
+ import path26 from "path";
8281
8345
  import crypto from "crypto";
8282
8346
  async function beforeMutationBackup(toolName, args, toolCallId, sessionId) {
8283
8347
  if (appConfig.undoEnabled === false) return null;
@@ -8292,7 +8356,7 @@ async function beforeMutationBackup(toolName, args, toolCallId, sessionId) {
8292
8356
  }
8293
8357
  await ensureUndoDir(sessionId);
8294
8358
  const undoId = createUUID();
8295
- const undoDir = path25.join(getUndoBackupRoot(sessionId), undoId);
8359
+ const undoDir = path26.join(getUndoBackupRoot(sessionId), undoId);
8296
8360
  const now = /* @__PURE__ */ new Date();
8297
8361
  const common = {
8298
8362
  undoId,
@@ -8327,7 +8391,7 @@ async function backupFileOverwrite(common, undoDir, args) {
8327
8391
  const absPath = resolveSafePath(common.relativePath);
8328
8392
  let exists = true;
8329
8393
  try {
8330
- await fs21.access(absPath);
8394
+ await fs22.access(absPath);
8331
8395
  } catch {
8332
8396
  exists = false;
8333
8397
  }
@@ -8335,15 +8399,15 @@ async function backupFileOverwrite(common, undoDir, args) {
8335
8399
  return { ...common, backupKind: "creation_marker", backupPath: "", fileSizeBefore: 0 };
8336
8400
  }
8337
8401
  assertWithinWorkspace(absPath);
8338
- const fileStat = await fs21.stat(absPath);
8402
+ const fileStat = await fs22.stat(absPath);
8339
8403
  const maxPerOp = appConfig.undoMaxBytesPerOp ?? 100 * 1024 * 1024;
8340
8404
  if (fileStat.size > maxPerOp) {
8341
8405
  throw new Error(`\u6587\u4EF6 [${common.relativePath}] \u4F53\u79EF\u7EA6 ${fileStat.size} \u5B57\u8282\u8D85\u8FC7\u5355\u6B21\u5907\u4EFD\u4E0A\u9650 ${maxPerOp}\uFF0C\u5199\u5165\u5DF2\u963B\u65AD\uFF08\u9632\u5185\u5B58\u62D6\u57AE\uFF1B\u53EF\u8C03 undoMaxBytesPerOp\uFF09`);
8342
8406
  }
8343
- const content = await fs21.readFile(absPath);
8344
- await fs21.mkdir(undoDir, { recursive: true, mode: 448 });
8345
- const contentPath = path25.join(undoDir, "content");
8346
- await fs21.writeFile(contentPath, content, { mode: 384 });
8407
+ const content = await fs22.readFile(absPath);
8408
+ await fs22.mkdir(undoDir, { recursive: true, mode: 448 });
8409
+ const contentPath = path26.join(undoDir, "content");
8410
+ await fs22.writeFile(contentPath, content, { mode: 384 });
8347
8411
  return {
8348
8412
  ...common,
8349
8413
  backupKind: "file_content",
@@ -8362,9 +8426,9 @@ async function backupFileCreate(common) {
8362
8426
  }
8363
8427
  async function backupDelete(common, undoDir, relativePath) {
8364
8428
  const absPath = resolveSafePath(relativePath);
8365
- const st = await fs21.stat(absPath);
8429
+ const st = await fs22.stat(absPath);
8366
8430
  assertWithinWorkspace(absPath);
8367
- await fs21.mkdir(undoDir, { recursive: true, mode: 448 });
8431
+ await fs22.mkdir(undoDir, { recursive: true, mode: 448 });
8368
8432
  if (st.isDirectory()) {
8369
8433
  const treeBytes = await getDirTreeBytes(absPath);
8370
8434
  const maxPerOp2 = appConfig.undoMaxBytesPerOp ?? 100 * 1024 * 1024;
@@ -8379,15 +8443,15 @@ async function backupDelete(common, undoDir, relativePath) {
8379
8443
  throw new Error(`\u76EE\u5F55 [${relativePath}] \u5185\u542B\u654F\u611F\u6587\u4EF6 ${sensitiveInTree.length} \u4E2A\uFF08\u5982 ${sensitiveInTree[0]}\uFF09\uFF0C\u6309\u7B56\u7565(undoBackupSensitive=deny)\u62D2\u7EDD\u5907\u4EFD\uFF0C\u5199\u5165\u5DF2\u963B\u65AD`);
8380
8444
  }
8381
8445
  }
8382
- const treeDest = path25.join(undoDir, "tree");
8446
+ const treeDest = path26.join(undoDir, "tree");
8383
8447
  const sensitiveSet = new Set(sensitiveInTree);
8384
- await fs21.cp(absPath, treeDest, {
8448
+ await fs22.cp(absPath, treeDest, {
8385
8449
  recursive: true,
8386
8450
  force: true,
8387
8451
  preserveTimestamps: true,
8388
8452
  filter: (src) => {
8389
8453
  if (src === absPath) return true;
8390
- const relWithin = path25.relative(absPath, src).replace(/\\/g, "/");
8454
+ const relWithin = path26.relative(absPath, src).replace(/\\/g, "/");
8391
8455
  return !sensitiveSet.has(relWithin);
8392
8456
  }
8393
8457
  });
@@ -8403,9 +8467,9 @@ async function backupDelete(common, undoDir, relativePath) {
8403
8467
  if (st.size > maxPerOp) {
8404
8468
  throw new Error(`\u6587\u4EF6 [${relativePath}] \u4F53\u79EF\u7EA6 ${st.size} \u5B57\u8282\u8D85\u8FC7\u5355\u6B21\u5907\u4EFD\u4E0A\u9650 ${maxPerOp}\uFF0C\u5199\u5165\u5DF2\u963B\u65AD\uFF08\u9632\u5185\u5B58\u62D6\u57AE\uFF1B\u53EF\u8C03 undoMaxBytesPerOp\uFF09`);
8405
8469
  }
8406
- const content = await fs21.readFile(absPath);
8407
- const contentPath = path25.join(undoDir, "content");
8408
- await fs21.writeFile(contentPath, content, { mode: 384 });
8470
+ const content = await fs22.readFile(absPath);
8471
+ const contentPath = path26.join(undoDir, "content");
8472
+ await fs22.writeFile(contentPath, content, { mode: 384 });
8409
8473
  return {
8410
8474
  ...common,
8411
8475
  backupKind: "file_content",
@@ -8450,21 +8514,21 @@ var init_backup = __esm({
8450
8514
  const walk = async (d) => {
8451
8515
  let entries;
8452
8516
  try {
8453
- entries = await fs21.readdir(d, { withFileTypes: true });
8517
+ entries = await fs22.readdir(d, { withFileTypes: true });
8454
8518
  } catch {
8455
8519
  return;
8456
8520
  }
8457
8521
  entries.sort((a, b) => a.name.localeCompare(b.name));
8458
8522
  for (const e of entries) {
8459
- const full = path25.join(d, e.name);
8460
- const rel = path25.relative(dir, full).replace(/\\/g, "/");
8523
+ const full = path26.join(d, e.name);
8524
+ const rel = path26.relative(dir, full).replace(/\\/g, "/");
8461
8525
  if (e.isDirectory()) {
8462
8526
  h.update(`D ${rel}
8463
8527
  `);
8464
8528
  await walk(full);
8465
8529
  } else if (e.isFile()) {
8466
8530
  try {
8467
- h.update(`F ${rel} ${sha1Buf(await fs21.readFile(full))}
8531
+ h.update(`F ${rel} ${sha1Buf(await fs22.readFile(full))}
8468
8532
  `);
8469
8533
  } catch {
8470
8534
  }
@@ -8478,16 +8542,16 @@ var init_backup = __esm({
8478
8542
  let total = 0;
8479
8543
  let entries;
8480
8544
  try {
8481
- entries = await fs21.readdir(dir, { withFileTypes: true });
8545
+ entries = await fs22.readdir(dir, { withFileTypes: true });
8482
8546
  } catch {
8483
8547
  return 0;
8484
8548
  }
8485
8549
  for (const e of entries) {
8486
- const full = path25.join(dir, e.name);
8550
+ const full = path26.join(dir, e.name);
8487
8551
  if (e.isDirectory()) total += await getDirTreeBytes(full);
8488
8552
  else if (e.isFile()) {
8489
8553
  try {
8490
- total += (await fs21.stat(full)).size;
8554
+ total += (await fs22.stat(full)).size;
8491
8555
  } catch {
8492
8556
  }
8493
8557
  }
@@ -8499,16 +8563,16 @@ var init_backup = __esm({
8499
8563
  const walk = async (d) => {
8500
8564
  let entries;
8501
8565
  try {
8502
- entries = await fs21.readdir(d, { withFileTypes: true });
8566
+ entries = await fs22.readdir(d, { withFileTypes: true });
8503
8567
  } catch {
8504
8568
  return;
8505
8569
  }
8506
8570
  for (const e of entries) {
8507
- const full = path25.join(d, e.name);
8571
+ const full = path26.join(d, e.name);
8508
8572
  if (e.isDirectory()) {
8509
8573
  await walk(full);
8510
8574
  } else if (e.isFile()) {
8511
- const relWithin = path25.relative(dir, full).replace(/\\/g, "/");
8575
+ const relWithin = path26.relative(dir, full).replace(/\\/g, "/");
8512
8576
  if (isSensitivePath(`${wsRelDir}/${relWithin}`)) found.push(relWithin);
8513
8577
  }
8514
8578
  }
@@ -8520,15 +8584,15 @@ var init_backup = __esm({
8520
8584
  });
8521
8585
 
8522
8586
  // ../core/src/tool/undo/restore.ts
8523
- import fs22 from "fs/promises";
8524
- import path26 from "path";
8587
+ import fs23 from "fs/promises";
8588
+ import path27 from "path";
8525
8589
  import crypto2 from "crypto";
8526
8590
  async function doRestore(target, sessionId) {
8527
8591
  if (target.backupKind === "directory_tree") {
8528
8592
  const abs = resolveSafePath(target.relativePath);
8529
8593
  let exists = false;
8530
8594
  try {
8531
- await fs22.access(abs);
8595
+ await fs23.access(abs);
8532
8596
  exists = true;
8533
8597
  } catch {
8534
8598
  }
@@ -8566,7 +8630,7 @@ async function ensureReverseBackup(target, sessionId) {
8566
8630
  }
8567
8631
  let exists = true;
8568
8632
  try {
8569
- await fs22.access(absPath);
8633
+ await fs23.access(absPath);
8570
8634
  } catch {
8571
8635
  exists = false;
8572
8636
  }
@@ -8579,17 +8643,17 @@ async function ensureReverseBackup(target, sessionId) {
8579
8643
  }
8580
8644
  }
8581
8645
  const reverseId = createUUID();
8582
- const reverseDir = path26.join(getUndoBackupRoot(sessionId), reverseId);
8583
- await fs22.mkdir(reverseDir, { recursive: true, mode: 448 });
8646
+ const reverseDir = path27.join(getUndoBackupRoot(sessionId), reverseId);
8647
+ await fs23.mkdir(reverseDir, { recursive: true, mode: 448 });
8584
8648
  assertWithinWorkspace(absPath);
8585
- const st = await fs22.stat(absPath);
8649
+ const st = await fs23.stat(absPath);
8586
8650
  if (st.isDirectory()) {
8587
- const dest2 = path26.join(reverseDir, "tree");
8588
- await fs22.cp(absPath, dest2, { recursive: true, force: true, preserveTimestamps: true });
8651
+ const dest2 = path27.join(reverseDir, "tree");
8652
+ await fs23.cp(absPath, dest2, { recursive: true, force: true, preserveTimestamps: true });
8589
8653
  return { reverseId, backupKind: "directory_tree", backupPath: dest2 };
8590
8654
  }
8591
- const dest = path26.join(reverseDir, "content");
8592
- await fs22.writeFile(dest, await fs22.readFile(absPath));
8655
+ const dest = path27.join(reverseDir, "content");
8656
+ await fs23.writeFile(dest, await fs23.readFile(absPath));
8593
8657
  return { reverseId, backupKind: "file_content", backupPath: dest };
8594
8658
  }
8595
8659
  async function dispatchRestore(r) {
@@ -8597,20 +8661,20 @@ async function dispatchRestore(r) {
8597
8661
  assertWithinWorkspace(absPath);
8598
8662
  switch (r.backupKind) {
8599
8663
  case "creation_marker": {
8600
- await fs22.rm(absPath, { force: true });
8664
+ await fs23.rm(absPath, { force: true });
8601
8665
  return `\u5DF2\u5220\u9664\u65B0\u5EFA\u6587\u4EF6 [${r.relativePath}]`;
8602
8666
  }
8603
8667
  case "file_content": {
8604
- await fs22.mkdir(path26.dirname(absPath), { recursive: true });
8605
- const backupAbs = path26.join(getUndoBackupRoot(r.sessionId), r.undoId, "content");
8606
- const content = await fs22.readFile(backupAbs);
8607
- await fs22.writeFile(absPath, content);
8668
+ await fs23.mkdir(path27.dirname(absPath), { recursive: true });
8669
+ const backupAbs = path27.join(getUndoBackupRoot(r.sessionId), r.undoId, "content");
8670
+ const content = await fs23.readFile(backupAbs);
8671
+ await fs23.writeFile(absPath, content);
8608
8672
  return `\u5DF2\u6062\u590D [${r.relativePath}] \u81F3\u5907\u4EFD\u524D\u5185\u5BB9\uFF08${r.fileSizeBefore ?? content.byteLength} \u5B57\u8282\uFF09`;
8609
8673
  }
8610
8674
  case "directory_tree": {
8611
- await fs22.mkdir(path26.dirname(absPath), { recursive: true });
8612
- const src = path26.join(getUndoBackupRoot(r.sessionId), r.undoId, "tree");
8613
- await fs22.cp(src, absPath, { recursive: true, force: true, preserveTimestamps: true });
8675
+ await fs23.mkdir(path27.dirname(absPath), { recursive: true });
8676
+ const src = path27.join(getUndoBackupRoot(r.sessionId), r.undoId, "tree");
8677
+ await fs23.cp(src, absPath, { recursive: true, force: true, preserveTimestamps: true });
8614
8678
  return `\u5DF2\u6062\u590D\u76EE\u5F55\u6811 [${r.relativePath}]\uFF08\u7EA6 ${r.fileSizeBefore ?? 0} \u5B57\u8282\uFF09`;
8615
8679
  }
8616
8680
  }
@@ -8643,7 +8707,7 @@ var init_restore = __esm({
8643
8707
  init_common();
8644
8708
  init_traceCalculate();
8645
8709
  sha1File = async (absPath) => {
8646
- const buf = await fs22.readFile(absPath);
8710
+ const buf = await fs23.readFile(absPath);
8647
8711
  return crypto2.createHash("sha1").update(buf).digest("hex");
8648
8712
  };
8649
8713
  listUndoable = async (sessionId) => {
@@ -8917,7 +8981,7 @@ ${diff.slice(0, 1500)}` : "";
8917
8981
  });
8918
8982
 
8919
8983
  // ../core/src/tool/registry/notebook.ts
8920
- import fs23 from "fs/promises";
8984
+ import fs24 from "fs/promises";
8921
8985
  var toArraySource, encodeSource, makeCell, applyNotebookEdit, notebookTools;
8922
8986
  var init_notebook = __esm({
8923
8987
  "../core/src/tool/registry/notebook.ts"() {
@@ -9018,7 +9082,7 @@ ${String(args.new_source).slice(0, 500)}` : ""}`,
9018
9082
  }
9019
9083
  let raw;
9020
9084
  try {
9021
- raw = await fs23.readFile(absPath, "utf-8");
9085
+ raw = await fs24.readFile(absPath, "utf-8");
9022
9086
  } catch (e) {
9023
9087
  return `\u274C [notebook_edit] \u8BFB\u53D6\u5931\u8D25\uFF1A${e?.message ?? e}`;
9024
9088
  }
@@ -9048,10 +9112,10 @@ ${String(args.new_source).slice(0, 500)}` : ""}`,
9048
9112
  }
9049
9113
  const tmpPath = makeTmpPath(absPath);
9050
9114
  try {
9051
- await fs23.writeFile(tmpPath, JSON.stringify(nb, null, 2), "utf-8");
9052
- await fs23.rename(tmpPath, absPath);
9115
+ await fs24.writeFile(tmpPath, JSON.stringify(nb, null, 2), "utf-8");
9116
+ await fs24.rename(tmpPath, absPath);
9053
9117
  } catch (e) {
9054
- await fs23.unlink(tmpPath).catch(() => {
9118
+ await fs24.unlink(tmpPath).catch(() => {
9055
9119
  });
9056
9120
  return `\u274C [notebook_edit] \u5199\u5165\u5931\u8D25\uFF1A${e?.message ?? e}`;
9057
9121
  }
@@ -9091,8 +9155,8 @@ var init_frontmatter = __esm({
9091
9155
  });
9092
9156
 
9093
9157
  // ../core/src/memory/loader.ts
9094
- import fs24 from "fs/promises";
9095
- import path27 from "path";
9158
+ import fs25 from "fs/promises";
9159
+ import path28 from "path";
9096
9160
  var GLOBAL_MEMORY_DIR, SOURCES, VALID_TYPES, parseMemoryAt, loadMemories, initMemories;
9097
9161
  var init_loader3 = __esm({
9098
9162
  "../core/src/memory/loader.ts"() {
@@ -9101,16 +9165,16 @@ var init_loader3 = __esm({
9101
9165
  init_frontmatter();
9102
9166
  init_registry6();
9103
9167
  init_registry2();
9104
- GLOBAL_MEMORY_DIR = path27.join(appConfig.dataDir, "memory");
9168
+ GLOBAL_MEMORY_DIR = path28.join(appConfig.dataDir, "memory");
9105
9169
  SOURCES = [
9106
9170
  { dir: GLOBAL_MEMORY_DIR, source: "global" },
9107
- { dir: path27.join(process.cwd(), ".deepseeker-code", "memory"), source: "project" }
9171
+ { dir: path28.join(process.cwd(), ".deepseeker-code", "memory"), source: "project" }
9108
9172
  ];
9109
9173
  VALID_TYPES = ["user", "feedback", "project", "reference"];
9110
9174
  parseMemoryAt = async (file, _dir, source) => {
9111
9175
  let raw;
9112
9176
  try {
9113
- raw = await fs24.readFile(file, "utf-8");
9177
+ raw = await fs25.readFile(file, "utf-8");
9114
9178
  } catch {
9115
9179
  return null;
9116
9180
  }
@@ -9144,7 +9208,7 @@ var init_loader3 = __esm({
9144
9208
  clearMemories();
9145
9209
  const picked = await scanSources(
9146
9210
  filterSources(SOURCES, includeProject),
9147
- (e, dir) => e.isFile() && e.name.endsWith(".md") ? path27.join(dir, e.name) : void 0,
9211
+ (e, dir) => e.isFile() && e.name.endsWith(".md") ? path28.join(dir, e.name) : void 0,
9148
9212
  parseMemoryAt
9149
9213
  );
9150
9214
  for (const { item } of picked) registerMemory(item);
@@ -9162,8 +9226,8 @@ var init_loader3 = __esm({
9162
9226
  });
9163
9227
 
9164
9228
  // ../core/src/tool/registry/memory.ts
9165
- import fs25 from "fs/promises";
9166
- import path28 from "path";
9229
+ import fs26 from "fs/promises";
9230
+ import path29 from "path";
9167
9231
  var MAX_BODY_BYTES, NAME_RE, VALID_TYPES2, memoryFilePath, sanitizeLine, buildMemoryMd, writeAndRegister, memoryTools;
9168
9232
  var init_memory = __esm({
9169
9233
  "../core/src/tool/registry/memory.ts"() {
@@ -9175,7 +9239,7 @@ var init_memory = __esm({
9175
9239
  MAX_BODY_BYTES = 64 * 1024;
9176
9240
  NAME_RE = /^[a-z0-9-]+$/;
9177
9241
  VALID_TYPES2 = ["user", "feedback", "project", "reference"];
9178
- memoryFilePath = (name, project) => project ? path28.join(process.cwd(), ".deepseeker-code", "memory", `${name}.md`) : path28.join(GLOBAL_MEMORY_DIR, `${name}.md`);
9242
+ memoryFilePath = (name, project) => project ? path29.join(process.cwd(), ".deepseeker-code", "memory", `${name}.md`) : path29.join(GLOBAL_MEMORY_DIR, `${name}.md`);
9179
9243
  sanitizeLine = (s) => String(s ?? "").replace(/[\r\n]+/g, " ").trim();
9180
9244
  buildMemoryMd = (name, description, type, body) => `---
9181
9245
  name: ${name}
@@ -9187,10 +9251,10 @@ ${body.trim()}
9187
9251
  `;
9188
9252
  writeAndRegister = async (name, description, type, body, project) => {
9189
9253
  const file = memoryFilePath(name, project);
9190
- await fs25.mkdir(path28.dirname(file), { recursive: true });
9254
+ await fs26.mkdir(path29.dirname(file), { recursive: true });
9191
9255
  const tmp = makeTmpPath(file);
9192
- await fs25.writeFile(tmp, buildMemoryMd(name, description, type, body), "utf-8");
9193
- await fs25.rename(tmp, file);
9256
+ await fs26.writeFile(tmp, buildMemoryMd(name, description, type, body), "utf-8");
9257
+ await fs26.rename(tmp, file);
9194
9258
  registerMemory({ name, description, type, body: body.trim(), source: project ? "project" : "global", file });
9195
9259
  return file;
9196
9260
  };
@@ -9306,7 +9370,7 @@ ${lines.join("\n")}`;
9306
9370
  const m = getMemory(name);
9307
9371
  if (!m) return `\u274C \u672A\u627E\u5230\u8BB0\u5FC6\uFF1A${name}\uFF08\u53EF\u80FD\u5DF2\u88AB\u5220\u9664\uFF09\u3002`;
9308
9372
  try {
9309
- await fs25.unlink(m.file);
9373
+ await fs26.unlink(m.file);
9310
9374
  } catch {
9311
9375
  }
9312
9376
  unregisterMemory(name);
@@ -9319,8 +9383,8 @@ ${lines.join("\n")}`;
9319
9383
  });
9320
9384
 
9321
9385
  // ../core/src/tool/registry/recall.ts
9322
- import fs26 from "fs/promises";
9323
- import path29 from "path";
9386
+ import fs27 from "fs/promises";
9387
+ import path30 from "path";
9324
9388
  var escapeRegExp2, lineText, primaryPathArg, annotateStaleness, snippetAround, recallTools;
9325
9389
  var init_recall = __esm({
9326
9390
  "../core/src/tool/registry/recall.ts"() {
@@ -9351,9 +9415,9 @@ var init_recall = __esm({
9351
9415
  annotateStaleness = async (args, observedAt) => {
9352
9416
  const p = primaryPathArg(args);
9353
9417
  if (!p) return "\u5FEB\u7167\uFF08\u65E0\u8DEF\u5F84\u5B9E\u4F53\uFF0C\u672A\u7ECF\u91CD\u9A8C\u2014\u2014\u636E\u4EE5\u884C\u52A8\u524D\u8BF7\u91CD\u8DD1\u9A8C\u8BC1\uFF09";
9354
- const abs = path29.isAbsolute(p) ? p : path29.resolve(getActiveWorkspaceRoot(), p);
9418
+ const abs = path30.isAbsolute(p) ? p : path30.resolve(getActiveWorkspaceRoot(), p);
9355
9419
  try {
9356
- const st = await fs26.stat(abs);
9420
+ const st = await fs27.stat(abs);
9357
9421
  if (observedAt && st.mtime.toISOString() > observedAt) {
9358
9422
  return `\u26A0\uFE0F \u89C2\u5BDF\u540E\u8BE5\u6587\u4EF6\u5DF2\u88AB\u4FEE\u6539\uFF08${p}\uFF09\u2014\u2014\u5FC5\u987B\u91CD\u65B0 read_file \u540E\u624D\u80FD\u636E\u4EE5\u4FEE\u6539`;
9359
9423
  }
@@ -9398,10 +9462,10 @@ var init_recall = __esm({
9398
9462
  if (args.with_full) {
9399
9463
  const safeId = String(args.with_full).replace(/[^A-Za-z0-9_-]/g, "");
9400
9464
  if (!safeId) return "\u274C [recall] with_full \u542B\u975E\u6CD5\u5B57\u7B26\u3002";
9401
- const sidecar = path29.join(getSessionsDirPath(ctx.sessionId), "tool-outputs", `${safeId}.txt`);
9465
+ const sidecar = path30.join(getSessionsDirPath(ctx.sessionId), "tool-outputs", `${safeId}.txt`);
9402
9466
  let full = "";
9403
9467
  try {
9404
- full = await fs26.readFile(sidecar, "utf-8");
9468
+ full = await fs27.readFile(sidecar, "utf-8");
9405
9469
  } catch {
9406
9470
  return `\u274C [recall] \u672A\u627E\u5230\u8BE5 id \u7684\u5B58\u6863\u539F\u6587\uFF08\u53EF\u80FD\u672A\u66FE\u89E6\u53D1\u622A\u65AD\u5B58\u6863\u3001\u6216\u4F1A\u8BDD\u5DF2\u6E05\u7406\uFF09\uFF1A${args.with_full}`;
9407
9471
  }
@@ -9610,7 +9674,7 @@ var init_spreadsheet = __esm({
9610
9674
  });
9611
9675
 
9612
9676
  // ../core/src/tool/registry/document.ts
9613
- import fs27 from "fs/promises";
9677
+ import fs28 from "fs/promises";
9614
9678
  var getMammoth, getUnpdf, documentTools;
9615
9679
  var init_document = __esm({
9616
9680
  "../core/src/tool/registry/document.ts"() {
@@ -9700,7 +9764,7 @@ var init_document = __esm({
9700
9764
  }
9701
9765
  const start = args.start_char ? Math.max(0, Math.floor(args.start_char)) : 0;
9702
9766
  const maxChars = Math.min(args.max_chars ? Math.max(1, Math.floor(args.max_chars)) : 3e4, 5e4);
9703
- const buf = await fs27.readFile(absPath);
9767
+ const buf = await fs28.readFile(absPath);
9704
9768
  const unpdf = await getUnpdf();
9705
9769
  const pdf = await unpdf.getDocumentProxy(new Uint8Array(buf));
9706
9770
  const { text, totalPages } = await unpdf.extractText(pdf, { mergePages: true });
@@ -9906,7 +9970,7 @@ var init_backgroundTool = __esm({
9906
9970
  });
9907
9971
 
9908
9972
  // ../core/src/tool/autoPermission.ts
9909
- import path30 from "path";
9973
+ import path31 from "path";
9910
9974
  var AUTO_SCOPE, AUTO_DEFAULT_EXTRA, AUTO_AGGRESSIVE_EXTRA, isMcpTool, BUILTIN_AUTO_DENY, matchBuiltinDeny, COMMAND_DENY, matchCommandDeny, hasShellMetachars, READONLY_HEADS, PKG_MGR, SCRIPT_RUNNER_HEADS, SCRIPT_RUNNER_READONLY, isScriptRunnerCommand, hasWriteModifier, SENSITIVE_FILE_ARG_RE, hasSensitiveFileArg, isReadOnlyCommand, isWithinWorkspace, runAutoCheck;
9911
9975
  var init_autoPermission = __esm({
9912
9976
  "../core/src/tool/autoPermission.ts"() {
@@ -10054,9 +10118,9 @@ var init_autoPermission = __esm({
10054
10118
  isWithinWorkspace = (p, cwd) => {
10055
10119
  if (!p || !cwd) return false;
10056
10120
  try {
10057
- const abs = path30.isAbsolute(p) ? p : path30.resolve(cwd, p);
10058
- const rel = path30.relative(cwd, abs);
10059
- return rel === "" || !rel.startsWith("..") && !path30.isAbsolute(rel);
10121
+ const abs = path31.isAbsolute(p) ? p : path31.resolve(cwd, p);
10122
+ const rel = path31.relative(cwd, abs);
10123
+ return rel === "" || !rel.startsWith("..") && !path31.isAbsolute(rel);
10060
10124
  } catch {
10061
10125
  return false;
10062
10126
  }
@@ -10084,8 +10148,8 @@ var init_autoPermission = __esm({
10084
10148
  });
10085
10149
 
10086
10150
  // ../core/src/agent/toolExecution.ts
10087
- import fs28 from "fs/promises";
10088
- import path31 from "path";
10151
+ import fs29 from "fs/promises";
10152
+ import path32 from "path";
10089
10153
  var applyPrivacyMasking, processToolCall;
10090
10154
  var init_toolExecution = __esm({
10091
10155
  "../core/src/agent/toolExecution.ts"() {
@@ -10225,7 +10289,7 @@ var init_toolExecution = __esm({
10225
10289
  const argCwd = typeof calledArgs?.cwd === "string" ? calledArgs.cwd.trim() : "";
10226
10290
  const samePath = (a, b) => {
10227
10291
  try {
10228
- const ra = path31.resolve(a), rb = path31.resolve(b);
10292
+ const ra = path32.resolve(a), rb = path32.resolve(b);
10229
10293
  return process.platform === "win32" ? ra.toLowerCase() === rb.toLowerCase() : ra === rb;
10230
10294
  } catch {
10231
10295
  return false;
@@ -10340,10 +10404,10 @@ ${result}`;
10340
10404
  const truncBudget = matchedTool?.function?.maxOutputCharacters ?? appConfig.MAX_TOOL_RESULT_CHARS;
10341
10405
  if (result.length > truncBudget) {
10342
10406
  try {
10343
- const sidecarDir = path31.join(getSessionsDirPath(sessionId), "tool-outputs");
10344
- await fs28.mkdir(sidecarDir, { recursive: true });
10407
+ const sidecarDir = path32.join(getSessionsDirPath(sessionId), "tool-outputs");
10408
+ await fs29.mkdir(sidecarDir, { recursive: true });
10345
10409
  const safeId = String(toolCall.id).replace(/[^A-Za-z0-9_-]/g, "");
10346
- await fs28.writeFile(path31.join(sidecarDir, `${safeId}.txt`), result, "utf-8");
10410
+ await fs29.writeFile(path32.join(sidecarDir, `${safeId}.txt`), result, "utf-8");
10347
10411
  sidecarNote = `\u5B8C\u6574\u539F\u6587\u5DF2\u5B58\u6863\uFF0Crecall \u5DE5\u5177\u4F20 with_full="${toolCall.id}" \u53EF\u53D6\u56DE`;
10348
10412
  } catch (e) {
10349
10413
  console.warn(`\u26A0\uFE0F [sidecar] \u5DE5\u5177\u539F\u6587\u5B58\u6863\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u4E3A\u666E\u901A\u622A\u65AD\u63D0\u793A\uFF09:`, e instanceof Error ? e.message : e);
@@ -10494,6 +10558,8 @@ var init_streamInference = __esm({
10494
10558
  init_transcript();
10495
10559
  init_contextCore();
10496
10560
  init_contentParts();
10561
+ init_visionCapability();
10562
+ init_createModel();
10497
10563
  sha1short = (s) => createHash2("sha1").update(s).digest("hex").slice(0, 10);
10498
10564
  RETRY_BACKOFF_CAP_MS = 3e4;
10499
10565
  extractRetryAfterMs = (e) => {
@@ -10567,6 +10633,7 @@ var init_streamInference = __esm({
10567
10633
  const MAX_API_RETRIES = 3;
10568
10634
  let apiRetries = 0;
10569
10635
  let compactedThisRound = false;
10636
+ let visionDegradedThisRound = false;
10570
10637
  for (let streamAttempt = 0; ; streamAttempt++) {
10571
10638
  try {
10572
10639
  for await (const chunk of activeProvider.streamChat(inferenceMessages, cleanedToolSchemas, { signal, model, thinkingLevel })) {
@@ -10667,6 +10734,26 @@ var init_streamInference = __esm({
10667
10734
  lastUsage = void 0;
10668
10735
  continue;
10669
10736
  }
10737
+ if (activeProvider.isImageUnsupportedError(streamErr) && noOutputYet && !visionDegradedThisRound) {
10738
+ const effModel = typeof model === "string" && model.trim() ? model.trim() : MODEL_NAME;
10739
+ learnVisionCapability(effModel, false);
10740
+ for (let i = 0; i < message.length; i++) message[i] = collapseToText(message[i], VISION_DEGRADE_NOTE);
10741
+ inferenceMessages = withNudgeTail(message, nudgeMsg);
10742
+ visionDegradedThisRound = true;
10743
+ events({
10744
+ sessionId,
10745
+ eventType: "llm.visionDowngraded",
10746
+ metadata: { depth, decisionSource: llmDecisionSource, ok: true, round, model: effModel },
10747
+ payload: { output: streamErr instanceof Error ? streamErr.message : String(streamErr) }
10748
+ });
10749
+ yield { type: "vision.downgraded", model: effModel };
10750
+ console.warn(`\u26A0\uFE0F \u6A21\u578B ${effModel} \u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF08API ${streamErr?.status ?? "?"}\uFF09\uFF0C\u5DF2\u81EA\u52A8\u964D\u7EA7\u4E3A\u6587\u672C\u5360\u4F4D\u5E76\u91CD\u8BD5\uFF08\u80FD\u529B\u5DF2\u8BB0\u4F4F\uFF0C\u540E\u7EED\u6D88\u606F\u76F4\u63A5\u6309\u6587\u672C\u53D1\u9001\uFF09`);
10751
+ contentBuf = "";
10752
+ reasoningBuf = "";
10753
+ toolCallsBuf.clear();
10754
+ lastUsage = void 0;
10755
+ continue;
10756
+ }
10670
10757
  throw streamErr;
10671
10758
  }
10672
10759
  }
@@ -11242,7 +11329,7 @@ var init_recovery = __esm({
11242
11329
  });
11243
11330
 
11244
11331
  // ../core/src/session/content.ts
11245
- var decayOldToolResults, NO_VISION_IMAGE_NOTE, enforceVisionGate, buildContextMessages;
11332
+ var decayOldToolResults, enforceVisionGate, buildContextMessages;
11246
11333
  var init_content = __esm({
11247
11334
  "../core/src/session/content.ts"() {
11248
11335
  "use strict";
@@ -11251,6 +11338,7 @@ var init_content = __esm({
11251
11338
  init_transcript();
11252
11339
  init_store();
11253
11340
  init_config();
11341
+ init_visionCapability();
11254
11342
  init_recovery();
11255
11343
  decayOldToolResults = (msgs) => {
11256
11344
  const units = groupUnits(msgs);
@@ -11281,9 +11369,9 @@ var init_content = __esm({
11281
11369
  return replaceImageParts(mm, "[\u5386\u53F2\u56FE\u7247\u5DF2\u6298\u53E0\uFF1A\u539F\u56FE\u4ECD\u5728\u4F1A\u8BDD\u5F52\u6863\u4E2D\uFF0C\u5982\u9700\u518D\u6B21\u67E5\u770B\u8BF7\u91CD\u65B0\u63D0\u4F9B\u8BE5\u56FE\u7247]");
11282
11370
  });
11283
11371
  };
11284
- NO_VISION_IMAGE_NOTE = "[\u56FE\u7247\u672A\u9001\u8FBE\uFF1A\u5F53\u524D\u6A21\u578B\u65E0\u89C6\u89C9\u80FD\u529B\uFF0C\u770B\u4E0D\u5230\u8BE5\u56FE\uFF1B\u539F\u56FE\u4FDD\u7559\u5728\u4F1A\u8BDD\u5F52\u6863\u4E2D\uFF0C\u5982\u9700\u5206\u6790\u8BF7\u8BA9\u7528\u6237\u91CD\u65B0\u63D0\u4F9B\u6216\u5207\u6362 vision \u6A21\u578B]";
11285
- enforceVisionGate = (msgs, modelId) => isVisionEnabled(modelId) ? msgs : msgs.map((m) => collapseToText(m, NO_VISION_IMAGE_NOTE));
11372
+ enforceVisionGate = (msgs, modelId) => isVisionEnabled(modelId) ? msgs : msgs.map((m) => collapseToText(m, VISION_DEGRADE_NOTE));
11286
11373
  buildContextMessages = async (sessionId, currentUserMsg, systemPrompt, modelId) => {
11374
+ await ensureVisionCacheLoaded();
11287
11375
  const lines = await readTranscriptLines(sessionId);
11288
11376
  const store = await getRollingState(sessionId);
11289
11377
  const eventAware = appConfig.transcriptEvents || lines.some(isEventLine);
@@ -11313,7 +11401,7 @@ var init_content = __esm({
11313
11401
  });
11314
11402
 
11315
11403
  // ../core/src/session/lineage.ts
11316
- import fs29 from "node:fs";
11404
+ import fs30 from "node:fs";
11317
11405
  var parentOfSubsession, stringAncestorsOf, readForkedFromSync, lineageClosureOf, ownerCanApprove;
11318
11406
  var init_lineage = __esm({
11319
11407
  "../core/src/session/lineage.ts"() {
@@ -11336,7 +11424,7 @@ var init_lineage = __esm({
11336
11424
  };
11337
11425
  readForkedFromSync = (sessionId) => {
11338
11426
  try {
11339
- const raw = fs29.readFileSync(getStatePath(sessionId), "utf-8");
11427
+ const raw = fs30.readFileSync(getStatePath(sessionId), "utf-8");
11340
11428
  const v = JSON.parse(raw)?.forkedFrom;
11341
11429
  return typeof v === "string" && v.length > 0 ? v : void 0;
11342
11430
  } catch {
@@ -11533,8 +11621,8 @@ var init_subagent = __esm({
11533
11621
  });
11534
11622
 
11535
11623
  // ../core/src/hooks/loader.ts
11536
- import fs30 from "fs/promises";
11537
- import path32 from "path";
11624
+ import fs31 from "fs/promises";
11625
+ import path33 from "path";
11538
11626
  var readHooksConfig, appendValidated, validateRule, parseStdoutDecision, parseAgentDecision, compileRule2, loadHooks, initHooks;
11539
11627
  var init_loader4 = __esm({
11540
11628
  "../core/src/hooks/loader.ts"() {
@@ -11549,15 +11637,15 @@ var init_loader4 = __esm({
11549
11637
  readHooksConfig = async (includeProject) => {
11550
11638
  const merged = {};
11551
11639
  const paths = [
11552
- path32.join(appConfig.dataDir, "settings.json"),
11640
+ path33.join(appConfig.dataDir, "settings.json"),
11553
11641
  // 全局用户级
11554
- ...includeProject ? [path32.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
11642
+ ...includeProject ? [path33.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
11555
11643
  // 项目级(叠加);未信任时省略
11556
11644
  ];
11557
11645
  for (const configPath of paths) {
11558
11646
  let raw;
11559
11647
  try {
11560
- raw = await fs30.readFile(configPath, "utf-8");
11648
+ raw = await fs31.readFile(configPath, "utf-8");
11561
11649
  } catch {
11562
11650
  continue;
11563
11651
  }
@@ -11888,8 +11976,8 @@ ${m.context}`;
11888
11976
  });
11889
11977
 
11890
11978
  // ../core/src/skills/loader.ts
11891
- import fs31 from "fs/promises";
11892
- import path33 from "path";
11979
+ import fs32 from "fs/promises";
11980
+ import path34 from "path";
11893
11981
  import { fileURLToPath as fileURLToPath2 } from "url";
11894
11982
  var BUILTIN_DIR, SOURCES2, MAX_SKILL_BODY_BYTES, splitList, parseSkillAt, loadSkills, initSkills;
11895
11983
  var init_loader5 = __esm({
@@ -11900,18 +11988,18 @@ var init_loader5 = __esm({
11900
11988
  init_registry3();
11901
11989
  init_skill();
11902
11990
  init_registry2();
11903
- BUILTIN_DIR = path33.join(path33.dirname(fileURLToPath2(import.meta.url)), "builtin");
11991
+ BUILTIN_DIR = path34.join(path34.dirname(fileURLToPath2(import.meta.url)), "builtin");
11904
11992
  SOURCES2 = [
11905
11993
  { dir: BUILTIN_DIR, source: "builtin" },
11906
- { dir: path33.join(appConfig.dataDir, "skills"), source: "global" },
11907
- { dir: path33.join(process.cwd(), ".deepseeker-code", "skills"), source: "project" }
11994
+ { dir: path34.join(appConfig.dataDir, "skills"), source: "global" },
11995
+ { dir: path34.join(process.cwd(), ".deepseeker-code", "skills"), source: "project" }
11908
11996
  ];
11909
11997
  MAX_SKILL_BODY_BYTES = 64 * 1024;
11910
11998
  splitList = (raw) => (raw ?? "").split(",").map((s) => s.trim()).filter(Boolean);
11911
11999
  parseSkillAt = async (skillFile, dir, source) => {
11912
12000
  let raw;
11913
12001
  try {
11914
- raw = await fs31.readFile(skillFile, "utf-8");
12002
+ raw = await fs32.readFile(skillFile, "utf-8");
11915
12003
  } catch {
11916
12004
  return null;
11917
12005
  }
@@ -11950,7 +12038,7 @@ var init_loader5 = __esm({
11950
12038
  loadSkills = async (includeProject) => {
11951
12039
  const picked = await scanSources(
11952
12040
  filterSources(SOURCES2, includeProject),
11953
- (e, dir) => e.isDirectory() ? path33.join(dir, e.name, "SKILL.md") : void 0,
12041
+ (e, dir) => e.isDirectory() ? path34.join(dir, e.name, "SKILL.md") : void 0,
11954
12042
  parseSkillAt
11955
12043
  );
11956
12044
  for (const { item } of picked) registerSkill(item);
@@ -11981,8 +12069,8 @@ var init_loader5 = __esm({
11981
12069
  });
11982
12070
 
11983
12071
  // ../core/src/agents/loader.ts
11984
- import fs32 from "fs/promises";
11985
- import path34 from "path";
12072
+ import fs33 from "fs/promises";
12073
+ import path35 from "path";
11986
12074
  import { fileURLToPath as fileURLToPath3 } from "url";
11987
12075
  var BUILTIN_DIR2, SOURCES3, parseAgentAt, initAgents;
11988
12076
  var init_loader6 = __esm({
@@ -11992,16 +12080,16 @@ var init_loader6 = __esm({
11992
12080
  init_frontmatter();
11993
12081
  init_registry4();
11994
12082
  init_registry2();
11995
- BUILTIN_DIR2 = path34.join(path34.dirname(fileURLToPath3(import.meta.url)), "builtin");
12083
+ BUILTIN_DIR2 = path35.join(path35.dirname(fileURLToPath3(import.meta.url)), "builtin");
11996
12084
  SOURCES3 = [
11997
12085
  { dir: BUILTIN_DIR2, source: "builtin" },
11998
- { dir: path34.join(appConfig.dataDir, "agents"), source: "global" },
11999
- { dir: path34.join(process.cwd(), ".deepseeker-code", "agents"), source: "project" }
12086
+ { dir: path35.join(appConfig.dataDir, "agents"), source: "global" },
12087
+ { dir: path35.join(process.cwd(), ".deepseeker-code", "agents"), source: "project" }
12000
12088
  ];
12001
12089
  parseAgentAt = async (file, dir, source) => {
12002
12090
  let raw;
12003
12091
  try {
12004
- raw = await fs32.readFile(file, "utf-8");
12092
+ raw = await fs33.readFile(file, "utf-8");
12005
12093
  } catch {
12006
12094
  return null;
12007
12095
  }
@@ -12036,7 +12124,7 @@ var init_loader6 = __esm({
12036
12124
  const known = new Set(into.map((t) => t.function.name));
12037
12125
  const picked = await scanSources(
12038
12126
  filterSources(SOURCES3, includeProject),
12039
- (e, dir) => e.isFile() && e.name.endsWith(".agent.md") ? path34.join(dir, e.name) : void 0,
12127
+ (e, dir) => e.isFile() && e.name.endsWith(".agent.md") ? path35.join(dir, e.name) : void 0,
12040
12128
  parseAgentAt
12041
12129
  );
12042
12130
  for (const { item: m, file, source } of picked) {
@@ -12073,8 +12161,8 @@ var init_registry7 = __esm({
12073
12161
  });
12074
12162
 
12075
12163
  // ../core/src/commands/loader.ts
12076
- import fs33 from "fs/promises";
12077
- import path35 from "path";
12164
+ import fs34 from "fs/promises";
12165
+ import path36 from "path";
12078
12166
  import { fileURLToPath as fileURLToPath4 } from "url";
12079
12167
  var BUILTIN_DIR3, SOURCES4, MAX_COMMAND_BODY_BYTES, parseCommandAt, loadCommands, initCommands;
12080
12168
  var init_loader7 = __esm({
@@ -12084,17 +12172,17 @@ var init_loader7 = __esm({
12084
12172
  init_frontmatter();
12085
12173
  init_registry7();
12086
12174
  init_registry2();
12087
- BUILTIN_DIR3 = path35.join(path35.dirname(fileURLToPath4(import.meta.url)), "builtin");
12175
+ BUILTIN_DIR3 = path36.join(path36.dirname(fileURLToPath4(import.meta.url)), "builtin");
12088
12176
  SOURCES4 = [
12089
12177
  { dir: BUILTIN_DIR3, source: "builtin" },
12090
- { dir: path35.join(appConfig.dataDir, "commands"), source: "global" },
12091
- { dir: path35.join(process.cwd(), ".deepseeker-code", "commands"), source: "project" }
12178
+ { dir: path36.join(appConfig.dataDir, "commands"), source: "global" },
12179
+ { dir: path36.join(process.cwd(), ".deepseeker-code", "commands"), source: "project" }
12092
12180
  ];
12093
12181
  MAX_COMMAND_BODY_BYTES = 64 * 1024;
12094
12182
  parseCommandAt = async (file, _dir, source) => {
12095
12183
  let raw;
12096
12184
  try {
12097
- raw = await fs33.readFile(file, "utf-8");
12185
+ raw = await fs34.readFile(file, "utf-8");
12098
12186
  } catch {
12099
12187
  return null;
12100
12188
  }
@@ -12105,7 +12193,7 @@ var init_loader7 = __esm({
12105
12193
  }
12106
12194
  const name = parsed.frontmatter.name;
12107
12195
  const description = parsed.frontmatter.description;
12108
- const fallbackName = path35.basename(file, ".md");
12196
+ const fallbackName = path36.basename(file, ".md");
12109
12197
  const finalName = name || fallbackName;
12110
12198
  if (!description) {
12111
12199
  console.warn(`\u26A0\uFE0F [commands] \u7F3A\u5C11 description\uFF08${file}\uFF09\uFF0C\u5DF2\u8DF3\u8FC7`);
@@ -12131,7 +12219,7 @@ var init_loader7 = __esm({
12131
12219
  loadCommands = async (includeProject) => {
12132
12220
  const picked = await scanSources(
12133
12221
  filterSources(SOURCES4, includeProject),
12134
- (e, dir) => e.isFile() && e.name.endsWith(".md") ? path35.join(dir, e.name) : void 0,
12222
+ (e, dir) => e.isFile() && e.name.endsWith(".md") ? path36.join(dir, e.name) : void 0,
12135
12223
  parseCommandAt
12136
12224
  );
12137
12225
  for (const { item } of picked) registerCommand(item);
@@ -12149,8 +12237,8 @@ var init_loader7 = __esm({
12149
12237
  });
12150
12238
 
12151
12239
  // ../core/src/outputStyles/loader.ts
12152
- import fs34 from "fs/promises";
12153
- import path36 from "path";
12240
+ import fs35 from "fs/promises";
12241
+ import path37 from "path";
12154
12242
  import { fileURLToPath as fileURLToPath5 } from "url";
12155
12243
  var BUILTIN_DIR4, MAX_STYLE_BODY_BYTES, SOURCES5, parseStyleAt, loadOutputStyles, initOutputStyles;
12156
12244
  var init_loader8 = __esm({
@@ -12160,17 +12248,17 @@ var init_loader8 = __esm({
12160
12248
  init_frontmatter();
12161
12249
  init_registry5();
12162
12250
  init_registry2();
12163
- BUILTIN_DIR4 = path36.join(path36.dirname(fileURLToPath5(import.meta.url)), "builtin");
12251
+ BUILTIN_DIR4 = path37.join(path37.dirname(fileURLToPath5(import.meta.url)), "builtin");
12164
12252
  MAX_STYLE_BODY_BYTES = 64 * 1024;
12165
12253
  SOURCES5 = [
12166
12254
  { dir: BUILTIN_DIR4, source: "builtin" },
12167
- { dir: path36.join(appConfig.dataDir, "output-styles"), source: "global" },
12168
- { dir: path36.join(process.cwd(), ".deepseeker-code", "output-styles"), source: "project" }
12255
+ { dir: path37.join(appConfig.dataDir, "output-styles"), source: "global" },
12256
+ { dir: path37.join(process.cwd(), ".deepseeker-code", "output-styles"), source: "project" }
12169
12257
  ];
12170
12258
  parseStyleAt = async (file, _dir, source) => {
12171
12259
  let raw;
12172
12260
  try {
12173
- raw = await fs34.readFile(file, "utf-8");
12261
+ raw = await fs35.readFile(file, "utf-8");
12174
12262
  } catch {
12175
12263
  return null;
12176
12264
  }
@@ -12202,7 +12290,7 @@ var init_loader8 = __esm({
12202
12290
  loadOutputStyles = async (includeProject) => {
12203
12291
  const picked = await scanSources(
12204
12292
  filterSources(SOURCES5, includeProject),
12205
- (e, dir) => e.isFile() && e.name.endsWith(".md") ? path36.join(dir, e.name) : void 0,
12293
+ (e, dir) => e.isFile() && e.name.endsWith(".md") ? path37.join(dir, e.name) : void 0,
12206
12294
  parseStyleAt
12207
12295
  );
12208
12296
  for (const { item } of picked) registerOutputStyle(item);
@@ -12283,8 +12371,8 @@ var init_bootstrap = __esm({
12283
12371
  });
12284
12372
 
12285
12373
  // ../core/src/statusLine/config.ts
12286
- import fs35 from "fs/promises";
12287
- import path37 from "path";
12374
+ import fs36 from "fs/promises";
12375
+ import path38 from "path";
12288
12376
  var parseBlock, readStatusLineConfig;
12289
12377
  var init_config2 = __esm({
12290
12378
  "../core/src/statusLine/config.ts"() {
@@ -12300,16 +12388,16 @@ var init_config2 = __esm({
12300
12388
  };
12301
12389
  readStatusLineConfig = async (includeProject) => {
12302
12390
  const paths = [
12303
- path37.join(appConfig.dataDir, "settings.json"),
12391
+ path38.join(appConfig.dataDir, "settings.json"),
12304
12392
  // 全局用户级
12305
- ...includeProject ? [path37.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
12393
+ ...includeProject ? [path38.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
12306
12394
  // 项目级(覆盖);未信任时省略
12307
12395
  ];
12308
12396
  let result = null;
12309
12397
  for (const configPath of paths) {
12310
12398
  let raw;
12311
12399
  try {
12312
- raw = await fs35.readFile(configPath, "utf-8");
12400
+ raw = await fs36.readFile(configPath, "utf-8");
12313
12401
  } catch {
12314
12402
  continue;
12315
12403
  }
@@ -12329,8 +12417,8 @@ var init_config2 = __esm({
12329
12417
 
12330
12418
  // ../core/src/statusLine/runner.ts
12331
12419
  import { spawn as spawn5 } from "child_process";
12332
- import fs36 from "fs";
12333
- import path38 from "path";
12420
+ import fs37 from "fs";
12421
+ import path39 from "path";
12334
12422
  import { fileURLToPath as fileURLToPath6 } from "url";
12335
12423
  var STATUSLINE_TIMEOUT_MS, cachedVersion, runStatusLine;
12336
12424
  var init_runner = __esm({
@@ -12339,16 +12427,16 @@ var init_runner = __esm({
12339
12427
  init_guard();
12340
12428
  STATUSLINE_TIMEOUT_MS = 3e3;
12341
12429
  try {
12342
- const here = path38.dirname(fileURLToPath6(import.meta.url));
12430
+ const here = path39.dirname(fileURLToPath6(import.meta.url));
12343
12431
  const candidates = [
12344
- path38.join(here, "../../../package.json"),
12432
+ path39.join(here, "../../../package.json"),
12345
12433
  // src/core/package.json
12346
- path38.join(here, "../../../../package.json")
12434
+ path39.join(here, "../../../../package.json")
12347
12435
  // 仓库根 package.json
12348
12436
  ];
12349
12437
  for (const p of candidates) {
12350
12438
  try {
12351
- const pkg = JSON.parse(fs36.readFileSync(p, "utf-8"));
12439
+ const pkg = JSON.parse(fs37.readFileSync(p, "utf-8"));
12352
12440
  if (typeof pkg.version === "string" && pkg.version) {
12353
12441
  cachedVersion = pkg.version;
12354
12442
  break;
@@ -12399,8 +12487,8 @@ var init_runner = __esm({
12399
12487
  });
12400
12488
 
12401
12489
  // ../core/src/observability/store.ts
12402
- import path39 from "path";
12403
- import fs37 from "fs/promises";
12490
+ import path40 from "path";
12491
+ import fs38 from "fs/promises";
12404
12492
  var getTraceDirPath, getTracePath, tracePathCache, ensuredTraceDirs, ensureTraceDir, getGlobalClockPath, getTraceStorePath;
12405
12493
  var init_store3 = __esm({
12406
12494
  "../core/src/observability/store.ts"() {
@@ -12410,21 +12498,21 @@ var init_store3 = __esm({
12410
12498
  init_common();
12411
12499
  getTraceDirPath = (mainTraceId) => {
12412
12500
  assertSafeSessionId(mainTraceId, "traceId");
12413
- return path39.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
12501
+ return path40.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
12414
12502
  };
12415
12503
  getTracePath = () => {
12416
- return path39.join(appConfig.dataDir, "trace");
12504
+ return path40.join(appConfig.dataDir, "trace");
12417
12505
  };
12418
12506
  tracePathCache = /* @__PURE__ */ new Map();
12419
12507
  ensuredTraceDirs = /* @__PURE__ */ new Set();
12420
12508
  ensureTraceDir = async (mainTraceId) => {
12421
12509
  const dir = getTraceDirPath(mainTraceId);
12422
12510
  if (ensuredTraceDirs.has(dir)) return;
12423
- await fs37.mkdir(dir, { recursive: true });
12511
+ await fs38.mkdir(dir, { recursive: true });
12424
12512
  ensuredTraceDirs.add(dir);
12425
12513
  };
12426
12514
  getGlobalClockPath = () => {
12427
- return path39.join(getTracePath(), "trace-cleanup-clock.json");
12515
+ return path40.join(getTracePath(), "trace-cleanup-clock.json");
12428
12516
  };
12429
12517
  getTraceStorePath = async (mainTraceId) => {
12430
12518
  assertSafeSessionId(mainTraceId, "traceId");
@@ -12433,7 +12521,7 @@ var init_store3 = __esm({
12433
12521
  if (cached2) return cached2;
12434
12522
  await ensureTraceDir(rootId);
12435
12523
  const dir = getTraceDirPath(rootId);
12436
- const files = await fs37.readdir(dir);
12524
+ const files = await fs38.readdir(dir);
12437
12525
  const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
12438
12526
  let fileName = "";
12439
12527
  if (existedFile) {
@@ -12442,7 +12530,7 @@ var init_store3 = __esm({
12442
12530
  const todayStr = getTodayDateString();
12443
12531
  fileName = `trace-${todayStr}__${rootId}.jsonl`;
12444
12532
  }
12445
- const resolved = path39.join(dir, fileName);
12533
+ const resolved = path40.join(dir, fileName);
12446
12534
  tracePathCache.set(rootId, resolved);
12447
12535
  return resolved;
12448
12536
  };
@@ -12450,8 +12538,8 @@ var init_store3 = __esm({
12450
12538
  });
12451
12539
 
12452
12540
  // ../core/src/observability/trace.ts
12453
- import fs38 from "fs/promises";
12454
- import path40 from "path";
12541
+ import fs39 from "fs/promises";
12542
+ import path41 from "path";
12455
12543
  async function emitTrace(base) {
12456
12544
  const event = {
12457
12545
  sessionId: base.sessionId,
@@ -12473,7 +12561,7 @@ async function emitTrace(base) {
12473
12561
  async function appendTraceEvent(event) {
12474
12562
  const p = await getTraceStorePath(event.sessionId);
12475
12563
  const line = JSON.stringify(event) + "\n";
12476
- await fs38.appendFile(p, line, "utf-8");
12564
+ await fs39.appendFile(p, line, "utf-8");
12477
12565
  if (workspaceTraceBytes < 0) {
12478
12566
  workspaceTraceBytes = await getDirBytes(getTracePath());
12479
12567
  }
@@ -12505,8 +12593,8 @@ async function maybeCleanupAfterAppend(sessionId) {
12505
12593
  lastSizeCleanupAt2 = now;
12506
12594
  diskLastCleanupAt2 = now;
12507
12595
  const clockPath = getGlobalClockPath();
12508
- await fs38.mkdir(path40.dirname(clockPath), { recursive: true });
12509
- await fs38.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
12596
+ await fs39.mkdir(path41.dirname(clockPath), { recursive: true });
12597
+ await fs39.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
12510
12598
  if (deletedCount > 0) {
12511
12599
  console.log(`\u2728 [Trace\u8FD0\u7EF4] \u5171\u9500\u6BC1 ${deletedCount} \u4E2A\u4F1A\u8BDD\u65E5\u5FD7\uFF08\u8F6F\u89C4\u5219\u8FC7\u671F\u6E05\u7406 + \u5BB9\u91CF\u786C\u9A71\u9010\uFF09\uFF0C\u78C1\u76D8\u6C34\u4F4D\u56DE\u843D\u3002`);
12512
12600
  }
@@ -12526,22 +12614,22 @@ async function cleanupOldTraceFiles() {
12526
12614
  let deleted = 0;
12527
12615
  let relativePaths;
12528
12616
  try {
12529
- relativePaths = await fs38.readdir(dir, { recursive: true });
12617
+ relativePaths = await fs39.readdir(dir, { recursive: true });
12530
12618
  } catch {
12531
12619
  return 0;
12532
12620
  }
12533
12621
  const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
12534
12622
  for (const relativePath of relativePaths) {
12535
- const fileName = path40.basename(relativePath);
12623
+ const fileName = path41.basename(relativePath);
12536
12624
  const m = fileName.match(re);
12537
12625
  if (!m) continue;
12538
12626
  const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
12539
12627
  if (fileBornDay >= cutoff) continue;
12540
- const fullPath = path40.join(dir, relativePath);
12628
+ const fullPath = path41.join(dir, relativePath);
12541
12629
  try {
12542
- const st = await fs38.stat(fullPath);
12630
+ const st = await fs39.stat(fullPath);
12543
12631
  if (now - st.mtimeMs < ACTIVE_GRACE_MS2) continue;
12544
- await fs38.unlink(fullPath);
12632
+ await fs39.unlink(fullPath);
12545
12633
  deleted += 1;
12546
12634
  } catch {
12547
12635
  }
@@ -12552,18 +12640,18 @@ async function evictOldestForSize2(targetBytes) {
12552
12640
  const dir = getTracePath();
12553
12641
  let relativePaths;
12554
12642
  try {
12555
- relativePaths = await fs38.readdir(dir, { recursive: true });
12643
+ relativePaths = await fs39.readdir(dir, { recursive: true });
12556
12644
  } catch {
12557
12645
  return 0;
12558
12646
  }
12559
12647
  const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
12560
12648
  const candidates = [];
12561
12649
  for (const relativePath of relativePaths) {
12562
- const fileName = path40.basename(relativePath);
12650
+ const fileName = path41.basename(relativePath);
12563
12651
  if (!re.test(fileName)) continue;
12564
12652
  try {
12565
- const st = await fs38.stat(path40.join(dir, relativePath));
12566
- candidates.push({ mtime: st.mtimeMs, fullPath: path40.join(dir, relativePath), size: st.size });
12653
+ const st = await fs39.stat(path41.join(dir, relativePath));
12654
+ candidates.push({ mtime: st.mtimeMs, fullPath: path41.join(dir, relativePath), size: st.size });
12567
12655
  } catch {
12568
12656
  }
12569
12657
  }
@@ -12573,7 +12661,7 @@ async function evictOldestForSize2(targetBytes) {
12573
12661
  for (const c of candidates) {
12574
12662
  if (totalBytes <= targetBytes) break;
12575
12663
  try {
12576
- await fs38.unlink(c.fullPath);
12664
+ await fs39.unlink(c.fullPath);
12577
12665
  totalBytes -= c.size;
12578
12666
  deleted += 1;
12579
12667
  } catch {
@@ -12605,7 +12693,7 @@ var init_trace = __esm({
12605
12693
  if (clockLoaded2) return;
12606
12694
  clockLoaded2 = true;
12607
12695
  try {
12608
- const rawClock = await fs38.readFile(getGlobalClockPath(), "utf-8");
12696
+ const rawClock = await fs39.readFile(getGlobalClockPath(), "utf-8");
12609
12697
  diskLastCleanupAt2 = JSON.parse(rawClock).lastCleanupAt || 0;
12610
12698
  } catch {
12611
12699
  diskLastCleanupAt2 = 0;
@@ -12752,8 +12840,8 @@ ${PLAN_MODE_AUTO_ENTER_HINT}
12752
12840
  });
12753
12841
 
12754
12842
  // ../core/src/serve/chatProcessing.ts
12755
- import path41 from "path";
12756
- import fs39 from "fs";
12843
+ import path42 from "path";
12844
+ import fs40 from "fs";
12757
12845
  var handleUnifiedChat;
12758
12846
  var init_chatProcessing = __esm({
12759
12847
  "../core/src/serve/chatProcessing.ts"() {
@@ -12766,6 +12854,7 @@ var init_chatProcessing = __esm({
12766
12854
  init_transcript();
12767
12855
  init_content();
12768
12856
  init_contentParts();
12857
+ init_visionCapability();
12769
12858
  init_trace();
12770
12859
  init_webHost();
12771
12860
  init_registry();
@@ -12808,17 +12897,17 @@ ${inject}`;
12808
12897
  if (roots.length > 1) {
12809
12898
  let activeReal = getActiveWorkspaceRoot();
12810
12899
  try {
12811
- activeReal = fs39.realpathSync(activeReal);
12900
+ activeReal = fs40.realpathSync(activeReal);
12812
12901
  } catch {
12813
12902
  }
12814
- const lines = roots.map((r) => `- ${path41.basename(r) || r}: ${r}${r === activeReal ? "\uFF08\u9ED8\u8BA4\u6839\uFF1A\u76F8\u5BF9\u8DEF\u5F84/\u547D\u4EE4\u57FA\u51C6\uFF09" : "\uFF08\u53EF\u76F4\u63A5\u8BFB\u5199\uFF09"}`);
12903
+ const lines = roots.map((r) => `- ${path42.basename(r) || r}: ${r}${r === activeReal ? "\uFF08\u9ED8\u8BA4\u6839\uFF1A\u76F8\u5BF9\u8DEF\u5F84/\u547D\u4EE4\u57FA\u51C6\uFF09" : "\uFF08\u53EF\u76F4\u63A5\u8BFB\u5199\uFF09"}`);
12815
12904
  sysPrompt = sysPrompt + `
12816
12905
 
12817
12906
  \u3010\u5DE5\u4F5C\u533A\uFF08\u591A\u9879\u76EE\uFF09\u3011
12818
12907
  \u65E0\u9700\u5207\u6362\u9879\u76EE\uFF0C\u4EE5\u4E0B\u6240\u6709\u6839\u90FD\u53EF\u76F4\u63A5\u7528\u7EDD\u5BF9\u8DEF\u5F84\u8BBF\u95EE\uFF1B\u8DE8\u9879\u76EE\u7528\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u9ED8\u8BA4\u6839\u7684 ../<\u5144\u5F1F\u76EE\u5F55>:
12819
12908
  ${lines.join("\n")}
12820
- \u2605 \u8DEF\u5F84\u951A\u5B9A\u94C1\u5F8B\uFF1A\u5DE5\u5177\u7F3A\u7701\u53EA\u4F5C\u7528\u4E8E\u9ED8\u8BA4\u6839\uFF08${path41.basename(activeReal) || activeReal} = IDE \u5934\u90E8\u6240\u793A\u6839\uFF09\u3002\u5F53\u7528\u6237\u5728\u5BF9\u8BDD\u4E2D\u6307\u660E\u4E86\u67D0\u4E2A\u9879\u76EE\uFF08\u5982\u300C\u5728 A \u9879\u76EE\u300D\u300C\u6539\u524D\u7AEF\u7684 xxx\u300D\u300C\u641C\u540E\u7AEF\u300D\uFF09\uFF0C\u8BE5\u8F6E\u6240\u6709\u5E26 path \u53C2\u6570\u7684\u5DE5\u5177\u8C03\u7528\uFF08read_file / edit_file / search_grep / glob / list_dir / read_xlsx / read_docx \u7B49\uFF09\u5FC5\u987B\u628A\u5BF9\u5E94\u9879\u76EE\u6839\u4F5C\u4E3A path \u4F20\u5165\uFF08\u7EDD\u5BF9\u8DEF\u5F84\u3001../<\u5144\u5F1F\u76EE\u5F55>\u3001\u6216\u9879\u76EE\u76EE\u5F55\u540D\uFF09\uFF0C\u5426\u5219\u53EA\u4F1A\u8BFB\u5199/\u641C\u7D22\u9ED8\u8BA4\u6839\uFF0C\u4E0E\u7528\u6237\u610F\u56FE\u4E0D\u7B26\u3002
12821
- \u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${path41.basename(activeReal) || activeReal} \u751F\u6548\u3002`;
12909
+ \u2605 \u8DEF\u5F84\u951A\u5B9A\u94C1\u5F8B\uFF1A\u5DE5\u5177\u7F3A\u7701\u53EA\u4F5C\u7528\u4E8E\u9ED8\u8BA4\u6839\uFF08${path42.basename(activeReal) || activeReal} = IDE \u5934\u90E8\u6240\u793A\u6839\uFF09\u3002\u5F53\u7528\u6237\u5728\u5BF9\u8BDD\u4E2D\u6307\u660E\u4E86\u67D0\u4E2A\u9879\u76EE\uFF08\u5982\u300C\u5728 A \u9879\u76EE\u300D\u300C\u6539\u524D\u7AEF\u7684 xxx\u300D\u300C\u641C\u540E\u7AEF\u300D\uFF09\uFF0C\u8BE5\u8F6E\u6240\u6709\u5E26 path \u53C2\u6570\u7684\u5DE5\u5177\u8C03\u7528\uFF08read_file / edit_file / search_grep / glob / list_dir / read_xlsx / read_docx \u7B49\uFF09\u5FC5\u987B\u628A\u5BF9\u5E94\u9879\u76EE\u6839\u4F5C\u4E3A path \u4F20\u5165\uFF08\u7EDD\u5BF9\u8DEF\u5F84\u3001../<\u5144\u5F1F\u76EE\u5F55>\u3001\u6216\u9879\u76EE\u76EE\u5F55\u540D\uFF09\uFF0C\u5426\u5219\u53EA\u4F1A\u8BFB\u5199/\u641C\u7D22\u9ED8\u8BA4\u6839\uFF0C\u4E0E\u7528\u6237\u610F\u56FE\u4E0D\u7B26\u3002
12910
+ \u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${path42.basename(activeReal) || activeReal} \u751F\u6548\u3002`;
12822
12911
  }
12823
12912
  const osName = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
12824
12913
  const now = /* @__PURE__ */ new Date();
@@ -12835,6 +12924,7 @@ ${lines.join("\n")}
12835
12924
  \u3010\u73AF\u5883\u3011
12836
12925
  ${envLines.join("\n")}`;
12837
12926
  let replyText = "";
12927
+ await ensureVisionCacheLoaded();
12838
12928
  const { wire: userContent, archive: archiveContent } = toIngestContents(inbound.content, inbound.attachments, opts?.model);
12839
12929
  try {
12840
12930
  const fullMessages = await buildContextMessages(
@@ -12922,7 +13012,7 @@ ${envLines.join("\n")}`;
12922
13012
  });
12923
13013
 
12924
13014
  // ../core/src/session/fork.ts
12925
- import fs40 from "fs/promises";
13015
+ import fs41 from "fs/promises";
12926
13016
  var listForkAnchors, derivePrefix, forkSession;
12927
13017
  var init_fork = __esm({
12928
13018
  "../core/src/session/fork.ts"() {
@@ -12995,7 +13085,7 @@ var init_fork = __esm({
12995
13085
  const prefix = derivePrefix(lines, upToLineId);
12996
13086
  const newId = createUUID();
12997
13087
  await ensureSessionsDir(newId);
12998
- const rawText = await fs40.readFile(getTranscriptPath(sourceId), "utf-8");
13088
+ const rawText = await fs41.readFile(getTranscriptPath(sourceId), "utf-8");
12999
13089
  const kept = [];
13000
13090
  let good = 0;
13001
13091
  for (const s of rawText.split("\n")) {
@@ -13011,7 +13101,7 @@ var init_fork = __esm({
13011
13101
  }
13012
13102
  let payload = kept.join("\n");
13013
13103
  if (payload.length > 0 && !payload.endsWith("\n")) payload += "\n";
13014
- await fs40.writeFile(getTranscriptPath(newId), payload, "utf-8");
13104
+ await fs41.writeFile(getTranscriptPath(newId), payload, "utf-8");
13015
13105
  const srcState = await readStore(sourceId);
13016
13106
  const srcRolling = await getRollingState(sourceId);
13017
13107
  const legacy = !lines.some(isEventLine);
@@ -13553,6 +13643,9 @@ var init_useChatState = __esm({
13553
13643
  }
13554
13644
  break;
13555
13645
  }
13646
+ case "vision.downgraded":
13647
+ pushInfo(`\u{1F5BC} \u6A21\u578B ${String(obj.model ?? "")} \u4E0D\u652F\u6301\u56FE\u7247\uFF0C\u5DF2\u81EA\u52A8\u964D\u7EA7\u4E3A\u6587\u672C\u5904\u7406\uFF08\u5DF2\u8BB0\u4F4F\uFF0C\u540E\u7EED\u6D88\u606F\u76F4\u63A5\u6309\u6587\u672C\u53D1\u9001\uFF09`);
13648
+ break;
13556
13649
  default:
13557
13650
  break;
13558
13651
  }
@@ -14941,7 +15034,7 @@ var init_TopPanel = __esm({
14941
15034
  });
14942
15035
 
14943
15036
  // ../core/src/observability/inspect.ts
14944
- import fs41 from "fs";
15037
+ import fs42 from "fs";
14945
15038
  var CWD, fmt, readTrace, inspectUsage, inspectContext, inspectPermissions, inspectMcp, inspectHooks, inspectDebug;
14946
15039
  var init_inspect = __esm({
14947
15040
  "../core/src/observability/inspect.ts"() {
@@ -14959,7 +15052,7 @@ var init_inspect = __esm({
14959
15052
  if (!sessionId) return [];
14960
15053
  try {
14961
15054
  const p = await getTraceStorePath(sessionId);
14962
- const text = await fs41.promises.readFile(p, "utf8");
15055
+ const text = await fs42.promises.readFile(p, "utf8");
14963
15056
  const out = [];
14964
15057
  for (const line of text.split("\n")) {
14965
15058
  if (!line.trim()) continue;
@@ -15770,7 +15863,7 @@ init_updateCheck();
15770
15863
  init_trust();
15771
15864
  import { render } from "ink";
15772
15865
  import os5 from "os";
15773
- import path42 from "path";
15866
+ import path43 from "path";
15774
15867
  import { emitKeypressEvents } from "node:readline";
15775
15868
  import { jsx as jsx19 } from "react/jsx-runtime";
15776
15869
  var parseArgs = (argv) => {
@@ -15903,7 +15996,7 @@ var main = async () => {
15903
15996
  process.stdout.write("\x1B[2J\x1B[3J\x1B[1;1H");
15904
15997
  const cwdIsHome = () => {
15905
15998
  try {
15906
- return path42.resolve(cwd).toLowerCase() === path42.resolve(os5.homedir()).toLowerCase();
15999
+ return path43.resolve(cwd).toLowerCase() === path43.resolve(os5.homedir()).toLowerCase();
15907
16000
  } catch {
15908
16001
  return false;
15909
16002
  }