deepseeker-code 1.0.45 → 1.0.47

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 +359 -103
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -9,7 +9,7 @@ cd 你的项目
9
9
  deepseeker-code
10
10
  ```
11
11
 
12
- DeepSeeker-Code 在你的终端里跑一个自主 agent:流式逐字输出、可折叠思考过程、工具调用卡(编辑类附红绿 diff 预览)、行内 Markdown 渲染(标题加粗、列表对齐)、审批模态、两阶段计划模式(计划 / 自动模式下输入框带边框与模式徽标)、会话恢复。**in-process 直驱引擎**——不走 HTTP/端口,工具审批走 Ink 原生模态。
12
+ DeepSeeker-Code 在你的终端里跑一个自主 agent:流式逐字输出、可折叠思考过程、工具调用卡(编辑类附红绿 diff 预览)、行内 Markdown 渲染(标题加粗、列表对齐)、审批模态、两阶段计划模式(计划 / 自动模式下输入框带边框与模式徽标)、会话恢复、长任务自动压缩且归档细节可经 recall 检索召回。**in-process 直驱引擎**——不走 HTTP/端口,工具审批走 Ink 原生模态。
13
13
 
14
14
  > 另有 **VS Code 插件**版本(同名 `deepseeker-code`),与终端版同源共享 core 引擎和 `~/.deepseeker-code/` 数据目录,同一项目下会话可互续。
15
15
 
package/dist/cli.mjs CHANGED
@@ -1139,7 +1139,7 @@ var init_contextCore = __esm({
1139
1139
  }, 0);
1140
1140
  };
1141
1141
  cleanMsg = (m) => {
1142
- const { id, sessionId, ...rest } = m;
1142
+ const { id, sessionId, ts, ...rest } = m;
1143
1143
  return rest;
1144
1144
  };
1145
1145
  groupUnits = (messagesArr) => {
@@ -1515,7 +1515,7 @@ var init_transcript = __esm({
1515
1515
  try {
1516
1516
  await ensureSessionsDir(entry.sessionId);
1517
1517
  const { sessionId, ...rest } = entry;
1518
- const line = { id: createUUID(), ...rest };
1518
+ const line = { id: createUUID(), ts: (/* @__PURE__ */ new Date()).toISOString(), ...rest };
1519
1519
  const p = getTranscriptPath(sessionId);
1520
1520
  const payload = JSON.stringify(line) + "\n";
1521
1521
  if (payload.includes("\uFFFD")) {
@@ -1831,7 +1831,7 @@ function microcompactTextContent(raw) {
1831
1831
  function isAsyncGenerator(x) {
1832
1832
  return x != null && typeof x[Symbol.asyncIterator] === "function";
1833
1833
  }
1834
- var ANSI_ESCAPE, getFileAccessRoots, relativizeWorkspacePathsInText, truncateToolResult, truncateApprovalDetail, compactBatch, compactToLine, ensureSummarySlot, SUMMARY_SELF_COMPACT_THRESHOLD, ensureFitsWindow, collectToolResult;
1834
+ var ANSI_ESCAPE, getFileAccessRoots, relativizeWorkspacePathsInText, truncateToolResult, truncateApprovalDetail, compactBatch, ARCHIVE_INDEX_MAX_ENTRIES, ARCHIVE_INDEX_BATCH_CAP, extractArchiveEntities, parseSummarySlot, mergeSummarySlot, compactSlotNarrative, compactToLine, ensureSummarySlot, SUMMARY_SELF_COMPACT_THRESHOLD, ensureFitsWindow, collectToolResult;
1835
1835
  var init_truncate = __esm({
1836
1836
  "../core/src/agent/truncate.ts"() {
1837
1837
  "use strict";
@@ -1878,7 +1878,7 @@ var init_truncate = __esm({
1878
1878
  }
1879
1879
  return out;
1880
1880
  };
1881
- truncateToolResult = (result, maxChars) => {
1881
+ truncateToolResult = (result, maxChars, sidecarNote) => {
1882
1882
  const finalMaxChars = maxChars ?? appConfig.MAX_TOOL_RESULT_CHARS;
1883
1883
  const newResult = microcompactTextContent(result);
1884
1884
  if (!newResult || newResult.length <= finalMaxChars) return newResult;
@@ -1887,7 +1887,8 @@ var init_truncate = __esm({
1887
1887
  const tail = newResult.slice(-half);
1888
1888
  const totalLines = newResult.split("\n").length;
1889
1889
  const omitted = Math.max(0, totalLines - head.split("\n").length - tail.split("\n").length);
1890
- return [head, "", `\u2026(\u5DF2\u7701\u7565\u4E2D\u95F4\u7EA6 ${omitted} \u884C\uFF0C\u5171 ${totalLines} \u884C)\u2026`, "", tail].join("\n");
1890
+ const note = sidecarNote ? `\uFF1B${sidecarNote}` : "";
1891
+ return [head, "", `\u2026(\u5DF2\u7701\u7565\u4E2D\u95F4\u7EA6 ${omitted} \u884C\uFF0C\u5171 ${totalLines} \u884C${note})\u2026`, "", tail].join("\n");
1891
1892
  };
1892
1893
  truncateApprovalDetail = (detail, maxChars = 2e3) => {
1893
1894
  if (!detail || detail.length <= maxChars) return detail;
@@ -1903,12 +1904,73 @@ ${tail}`;
1903
1904
  };
1904
1905
  compactBatch = async (batch, signal) => {
1905
1906
  const resp = await chatWithModelWithSummary(
1906
- [...batch, { role: "user", content: "\u7528\u4E00\u884C\u8BDD\u6982\u62EC\u4EE5\u4E0A\u5BF9\u8BDD\u4E0E\u5DE5\u5177\u8C03\u7528\uFF1A\u4EFB\u52A1\u76EE\u6807\u3001\u5173\u952E\u51B3\u7B56\u3001\u52A8\u8FC7\u7684\u6587\u4EF6\u3001\u5F53\u524D\u8FDB\u5EA6\u3002\u4E0D\u8981\u8C03\u7528\u5DE5\u5177\u3002" }],
1907
+ [...batch, { role: "user", content: '\u7528\u4E00\u884C\u8BDD\u6982\u62EC\u4EE5\u4E0A\u5BF9\u8BDD\u4E0E\u5DE5\u5177\u8C03\u7528\uFF1A\u4EFB\u52A1\u76EE\u6807\u3001\u5173\u952E\u51B3\u7B56\u3001\u52A8\u8FC7\u7684\u6587\u4EF6\u3001\u5F53\u524D\u8FDB\u5EA6\u3002\u5FC5\u987B\u539F\u6837\u4FDD\u7559\u5173\u952E\u5B9E\u4F53\u540D\uFF08\u6587\u4EF6\u8DEF\u5F84\u3001\u51FD\u6570/\u7C7B\u540D\u3001\u62A5\u9519\u5173\u952E\u8BCD\uFF09\u4EE5\u4FBF\u540E\u7EED\u68C0\u7D22\u3002\u5BF9\u8BB0\u4E0D\u51C6\u7684\u7EC6\u8282\u4E0D\u8981\u81C6\u6D4B\uFF0C\u6807\u6CE8"(\u7EC6\u8282\u5DF2\u5F52\u6863)"\u5373\u53EF\u3002\u4E0D\u8981\u8C03\u7528\u5DE5\u5177\u3002' }],
1907
1908
  [],
1908
1909
  { signal }
1909
1910
  );
1910
1911
  return `- ${resp.choices[0].message.content || ""}`;
1911
1912
  };
1913
+ ARCHIVE_INDEX_MAX_ENTRIES = 120;
1914
+ ARCHIVE_INDEX_BATCH_CAP = 60;
1915
+ extractArchiveEntities = (batch) => {
1916
+ let text = "";
1917
+ for (const m of batch) {
1918
+ if (m.content) text += ` ${typeof m.content === "string" ? m.content : JSON.stringify(m.content)}`;
1919
+ const calls = m.tool_calls;
1920
+ if (Array.isArray(calls)) for (const c of calls) text += ` ${c?.function?.name ?? ""} ${c?.function?.arguments ?? ""}`;
1921
+ }
1922
+ const found = [];
1923
+ const seen = /* @__PURE__ */ new Set();
1924
+ const push = (raw) => {
1925
+ const s = raw.trim();
1926
+ if (!s || s.length < 3 || s.length > 60 || seen.has(s)) return;
1927
+ seen.add(s);
1928
+ found.push(s);
1929
+ };
1930
+ for (const m of text.match(/(?:[A-Za-z]:)?[\w.\-]+(?:[/\\][\w.\-]+)+\.[A-Za-z0-9]{1,6}/g) ?? []) push(m);
1931
+ for (const m of text.match(/`([^`\n]{2,48})`/g) ?? []) push(m.slice(1, -1));
1932
+ return found.slice(0, ARCHIVE_INDEX_BATCH_CAP);
1933
+ };
1934
+ parseSummarySlot = (content) => {
1935
+ const raw = content ?? "";
1936
+ const idxMark = raw.indexOf("\u27E6DSC:ARCHIVE-INDEX\u27E7");
1937
+ const notesMark = raw.indexOf("\u27E6DSC:ARCHIVE-NOTES\u27E7");
1938
+ if (idxMark === -1 || notesMark === -1 || notesMark < idxMark) return { index: [], notes: raw };
1939
+ const indexText = raw.slice(idxMark + "\u27E6DSC:ARCHIVE-INDEX\u27E7".length, notesMark);
1940
+ const entityText = indexText.includes("\n") ? indexText.slice(indexText.indexOf("\n") + 1) : "";
1941
+ const notes = raw.slice(notesMark + "\u27E6DSC:ARCHIVE-NOTES\u27E7".length).replace(/^\n+/, "");
1942
+ const index = entityText.split("|").map((s) => s.trim()).filter(Boolean);
1943
+ return { index, notes };
1944
+ };
1945
+ mergeSummarySlot = (oldContent, noteLine, newEntities) => {
1946
+ const { index, notes } = parseSummarySlot(oldContent);
1947
+ const merged = [];
1948
+ const seen = /* @__PURE__ */ new Set();
1949
+ for (const e of [...newEntities, ...index]) {
1950
+ if (!e || seen.has(e)) continue;
1951
+ seen.add(e);
1952
+ merged.push(e);
1953
+ if (merged.length >= ARCHIVE_INDEX_MAX_ENTRIES) break;
1954
+ }
1955
+ const newNotes = notes ? `${notes}
1956
+ ${noteLine}` : noteLine;
1957
+ return [
1958
+ "\u27E6DSC:ARCHIVE-INDEX\u27E7 \u7CBE\u786E\u7EC6\u8282\u53EF\u7528 recall \u5DE5\u5177\u68C0\u7D22\u672C\u4F1A\u8BDD\u5168\u91CF\u5386\u53F2\uFF1B\u4EE5\u4E0B\u4E3A\u5F52\u6863\u5B9E\u4F53\u7D22\u5F15\uFF08\u68C0\u7D22\u5173\u952E\u8BCD\u7EBF\u7D22\uFF09\uFF1A",
1959
+ merged.join(" | "),
1960
+ "\u27E6DSC:ARCHIVE-NOTES\u27E7",
1961
+ newNotes
1962
+ ].join("\n");
1963
+ };
1964
+ compactSlotNarrative = async (slotContent, modelWindow, signal) => {
1965
+ const { index } = parseSummarySlot(slotContent);
1966
+ const compactedNotes = await compactToLine([{ role: "system", content: slotContent }], modelWindow, signal);
1967
+ return [
1968
+ "\u27E6DSC:ARCHIVE-INDEX\u27E7 \u7CBE\u786E\u7EC6\u8282\u53EF\u7528 recall \u5DE5\u5177\u68C0\u7D22\u672C\u4F1A\u8BDD\u5168\u91CF\u5386\u53F2\uFF1B\u4EE5\u4E0B\u4E3A\u5F52\u6863\u5B9E\u4F53\u7D22\u5F15\uFF08\u68C0\u7D22\u5173\u952E\u8BCD\u7EBF\u7D22\uFF09\uFF1A",
1969
+ index.join(" | "),
1970
+ "\u27E6DSC:ARCHIVE-NOTES\u27E7",
1971
+ compactedNotes
1972
+ ].join("\n");
1973
+ };
1912
1974
  compactToLine = async (toCompact, _modelWindow, signal) => {
1913
1975
  const MAX_BATCH_TOKENS = 16e3;
1914
1976
  const units = groupUnits(toCompact);
@@ -1963,11 +2025,9 @@ ${tail}`;
1963
2025
  try {
1964
2026
  if (toCompact.length > 0) {
1965
2027
  const line = await compactToLine(toCompact, event.modelWindow, event.signal);
1966
- const old = summaryMsg?.content || "";
1967
- summaryMsg.content = old ? `${old}
1968
- ${line}` : line;
2028
+ summaryMsg.content = mergeSummarySlot(summaryMsg?.content || "", line, extractArchiveEntities(toCompact));
1969
2029
  if (estimateTokens([summaryMsg]) > SUMMARY_SELF_COMPACT_THRESHOLD) {
1970
- summaryMsg.content = await compactToLine([summaryMsg], event.modelWindow, event.signal);
2030
+ summaryMsg.content = await compactSlotNarrative(summaryMsg.content, event.modelWindow, event.signal);
1971
2031
  }
1972
2032
  const endTime = performance.now();
1973
2033
  event.messageArr.length = 0;
@@ -2004,7 +2064,7 @@ ${line}` : line;
2004
2064
  keep--;
2005
2065
  continue;
2006
2066
  } else if (summaryMsg?.content) {
2007
- summaryMsg.content = await compactToLine([summaryMsg], event.modelWindow, event.signal);
2067
+ summaryMsg.content = await compactSlotNarrative(summaryMsg.content, event.modelWindow, event.signal);
2008
2068
  event.messageArr.length = 0;
2009
2069
  event.messageArr.push(systemMsg, summaryMsg, ...keepRecent);
2010
2070
  const store = await getRollingState(event.sessionId);
@@ -4016,6 +4076,8 @@ var init_planMode = __esm({
4016
4076
  "get_diagnostics",
4017
4077
  "goto_definition",
4018
4078
  // ★ P0-A 补漏:LSP 导航/诊断恰是调研阶段最需要的(原白名单漂移漏登记,schema 档与 runtime 档共用此表)
4079
+ "recall",
4080
+ // 只读检索本会话历史(长调研中早前轮次可能已被压缩归档,调研阶段恰是 recall 主场景)
4019
4081
  "web_fetch",
4020
4082
  "web_search"
4021
4083
  // 只读研究类(虽为 DANGER 但不写本地状态;仍走各自审批)
@@ -8824,6 +8886,182 @@ ${lines.join("\n")}`;
8824
8886
  }
8825
8887
  });
8826
8888
 
8889
+ // ../core/src/tool/registry/recall.ts
8890
+ import fs26 from "fs/promises";
8891
+ import path29 from "path";
8892
+ var escapeRegExp2, lineText, primaryPathArg, annotateStaleness, snippetAround, recallTools;
8893
+ var init_recall = __esm({
8894
+ "../core/src/tool/registry/recall.ts"() {
8895
+ "use strict";
8896
+ init_type();
8897
+ init_guard();
8898
+ init_transcript();
8899
+ init_store();
8900
+ escapeRegExp2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8901
+ lineText = (l) => {
8902
+ let t = "";
8903
+ if (typeof l.content === "string") t += l.content;
8904
+ else if (Array.isArray(l.content)) t += l.content.map((p) => typeof p?.text === "string" ? p.text : "").join(" ");
8905
+ if (Array.isArray(l.tool_calls)) {
8906
+ for (const c of l.tool_calls) {
8907
+ if (c?.function?.name === "recall") continue;
8908
+ t += ` ${c?.function?.name ?? ""} ${c?.function?.arguments ?? ""}`;
8909
+ }
8910
+ }
8911
+ return t;
8912
+ };
8913
+ primaryPathArg = (args) => {
8914
+ for (const k of ["path", "file_path", "source"]) {
8915
+ if (typeof args?.[k] === "string" && args[k]) return args[k];
8916
+ }
8917
+ return void 0;
8918
+ };
8919
+ annotateStaleness = async (args, observedAt) => {
8920
+ const p = primaryPathArg(args);
8921
+ 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";
8922
+ const abs = path29.isAbsolute(p) ? p : path29.resolve(getActiveWorkspaceRoot(), p);
8923
+ try {
8924
+ const st = await fs26.stat(abs);
8925
+ if (observedAt && st.mtime.toISOString() > observedAt) {
8926
+ 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`;
8927
+ }
8928
+ return `\u2713 \u6587\u4EF6\u672A\u53D8\uFF08${p}\uFF09`;
8929
+ } catch {
8930
+ return `\u26A0\uFE0F \u8BE5\u6587\u4EF6\u5DF2\u4E0D\u5B58\u5728\uFF08${p}\uFF09`;
8931
+ }
8932
+ };
8933
+ snippetAround = (text, re, maxChars) => {
8934
+ const m = re.exec(text);
8935
+ const start = Math.max(0, (m?.index ?? 0) - 120);
8936
+ const slice = text.slice(start, start + maxChars);
8937
+ const headMark = start > 0 ? "\u2026" : "";
8938
+ const tailMark = start + maxChars < text.length ? "\u2026\uFF08\u7247\u6BB5\u622A\u65AD\uFF0C\u5B8C\u6574\u5185\u5BB9\u53EF\u7528 with_full\uFF09" : "";
8939
+ return `${headMark}${slice}${tailMark}`;
8940
+ };
8941
+ recallTools = [
8942
+ {
8943
+ type: "function",
8944
+ function: {
8945
+ name: "recall",
8946
+ description: "\u68C0\u7D22\u3010\u672C\u4F1A\u8BDD\u3011\u5168\u91CF\u5386\u53F2\u8F6C\u5F55\uFF08transcript\uFF09\uFF0C\u5305\u62EC\u5DF2\u88AB\u4E0A\u4E0B\u6587\u538B\u7F29\u5F52\u6863\u7684\u539F\u59CB\u6D88\u606F\u4E0E\u5DE5\u5177\u7ED3\u679C\u3002\u4F7F\u7528\u65F6\u673A\uFF1A\u6EDA\u52A8\u6458\u8981\uFF08\u27E6DSC:ARCHIVE-INDEX\u27E7/\u27E6DSC:ARCHIVE-NOTES\u27E7\uFF09\u4E0D\u8DB3\u4EE5\u56DE\u7B54\u7EC6\u8282\u65F6\u2014\u2014\u5982\u5F52\u6863\u524D\u7684\u6587\u4EF6\u5185\u5BB9\u3001\u62A5\u9519\u539F\u6587\u3001\u7528\u6237\u65E9\u524D\u7684\u8981\u6C42\u2014\u2014\u5148\u7528\u672C\u5DE5\u5177\u68C0\u7D22\uFF0C\u4E0D\u8981\u51ED\u6458\u8981\u81C6\u6D4B\uFF0C\u4E5F\u4E0D\u8981\u91CD\u8DD1\u5DE5\u5177\u3002\u2605 \u9996\u67E5\u7B56\u7565\uFF1Aquery \u5FC5\u987B\u7528\u5177\u4F53\u5B9E\u4F53\u8BCD\u2014\u2014\u62A5\u9519\u5173\u952E\u8BCD\uFF08\u5982 TypeError\uFF09\u3001\u6587\u4EF6\u8DEF\u5F84\u3001\u51FD\u6570/\u7B26\u53F7\u540D\uFF08\u6458\u8981\u5B9E\u4F53\u7D22\u5F15\u91CC\u51FA\u73B0\u8FC7\u4EC0\u4E48\u5C31\u7528\u4EC0\u4E48\uFF09\uFF1B\u4E0D\u8981\u7528\u5DE5\u5177\u540D\uFF08read_file \u7B49\uFF09\u6216\u6CDB\u8BCD\uFF08\u4EE3\u7801/\u6587\u4EF6/\u95EE\u9898\uFF09\u4F5C query\uFF0C\u4F1A\u547D\u4E2D\u5927\u91CF\u65E0\u5173\u5DE5\u5177\u884C\u3002\u4E00\u6B21\u6CA1\u4E2D\u5C31\u6362\u66F4\u5177\u4F53\u7684\u8BCD\u6216\u7528 is_regex \u4EE5 | \u5408\u5E76\u591A\u4E2A\u5019\u9009\u8BCD\uFF0C\u901A\u5E38 1-2 \u6B21\u5185\u547D\u4E2D\u3002\u8FD4\u56DE\u6309\u65F6\u95F4\u65E7\u2192\u65B0\uFF08\u4F18\u5148\u5F52\u6863\u533A\uFF09\uFF1B\u6587\u4EF6\u7C7B\u5DE5\u5177\u7ED3\u679C\u9644\u5B9E\u65F6\u6821\u9A8C\uFF1A\u26A0\uFE0F \u5DF2\u4FEE\u6539/\u5DF2\u4E0D\u5B58\u5728 \u7684\u5FC5\u987B\u91CD\u65B0 read_file \u9A8C\u8BC1\u540E\u624D\u80FD\u636E\u4EE5\u4FEE\u6539\uFF0C\u2713 \u672A\u53D8 \u65B9\u53EF\u76F4\u63A5\u5F15\u7528\u3002\u7ED3\u679C\u66FE\u88AB\u622A\u65AD\u7684\u4F1A\u6807\u6CE8 with_full \u53EF\u53D6\u5B58\u6863\u5168\u6587\u3002\u6458\u8981\u5DF2\u591F\u7528\u65F6\u52FF\u8C03\u7528\uFF08\u7701 token\uFF09\u3002",
8947
+ parameters: {
8948
+ type: "object",
8949
+ properties: {
8950
+ query: { type: "string", description: "\u68C0\u7D22\u5173\u952E\u8BCD\u3002\u9ED8\u8BA4\u5B57\u9762\u91CF\u5339\u914D\uFF1Bis_regex=true \u65F6\u6309\u6B63\u5219\u89E3\u6790\uFF08\u591A\u5173\u952E\u8BCD\u7528 | \u5408\u5E76\uFF09" },
8951
+ is_regex: { type: "boolean", description: "query \u662F\u5426\u6309\u6B63\u5219\u89E3\u6790\uFF0C\u9ED8\u8BA4 false" },
8952
+ run_id: { type: "string", description: "\u9650\u5B9A\u67D0\u4E2A run\uFF08\u4E00\u6B21\u7528\u6237\u8F93\u5165\u7684\u56DE\u5408\uFF09\u5185\u68C0\u7D22\uFF1A\u4F20\u547D\u4E2D\u5934\u5C55\u793A\u7684 runId \u524D\u7F00\uFF08\u53EF\u9009\uFF09" },
8953
+ limit: { type: "number", description: "\u6700\u5927\u547D\u4E2D\u6761\u6570\uFF08\u9ED8\u8BA4 6\uFF0C\u4E0A\u9650 12\uFF09" },
8954
+ with_full: { type: "string", description: "\u53D6\u56DE\u67D0\u4E2A\u5DE5\u5177\u7ED3\u679C\u7684\u5B58\u6863\u5168\u6587\uFF08\u66FE\u88AB\u622A\u65AD\u7684\u8D85\u957F\u7ED3\u679C\uFF09\uFF1A\u4F20\u5176 tool_call_id\uFF08\u622A\u65AD\u6807\u8BB0\u884C\u4E2D\u7ED9\u51FA\uFF09\u3002\u4E0E query \u4E92\u65A5" },
8955
+ full_offset: { type: "number", description: "with_full \u5206\u9875\u504F\u79FB\uFF08\u5B57\u7B26\uFF09\uFF0C\u9ED8\u8BA4 0\uFF1B\u8FD4\u56DE\u5C3E\u6807\u63D0\u793A\u4E0B\u4E00\u9875\u504F\u79FB" }
8956
+ },
8957
+ required: []
8958
+ },
8959
+ safetyLevel: "safe" /* SAFE */,
8960
+ isSync: true,
8961
+ // ★ 检索结果预算与 web 等工具对齐 16000 口径;命中数 × 单片段双重限流防 context thrashing
8962
+ maxOutputCharacters: 16e3,
8963
+ async execute(args, ctx) {
8964
+ if (!ctx?.sessionId) return "\u274C [recall] \u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587\uFF08sessionId\uFF09\uFF0C\u65E0\u6CD5\u68C0\u7D22\u3002";
8965
+ try {
8966
+ if (args.with_full) {
8967
+ const safeId = String(args.with_full).replace(/[^A-Za-z0-9_-]/g, "");
8968
+ if (!safeId) return "\u274C [recall] with_full \u542B\u975E\u6CD5\u5B57\u7B26\u3002";
8969
+ const sidecar = path29.join(getSessionsDirPath(ctx.sessionId), "tool-outputs", `${safeId}.txt`);
8970
+ let full = "";
8971
+ try {
8972
+ full = await fs26.readFile(sidecar, "utf-8");
8973
+ } catch {
8974
+ 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}`;
8975
+ }
8976
+ const CHUNK = 14e3;
8977
+ const off = Math.max(0, Math.floor(args.full_offset ?? 0));
8978
+ const slice = full.slice(off, off + CHUNK);
8979
+ const more = off + CHUNK < full.length ? `
8980
+
8981
+ [\u672A\u5B8C\uFF0C\u5171 ${full.length} \u5B57\u7B26\u2014\u2014\u7EE7\u7EED\u4F20 full_offset=${off + CHUNK} \u53D6\u4E0B\u4E00\u6BB5]` : "\n\n[\u5168\u6587\u5B8C]";
8982
+ return `[\u5B58\u6863\u539F\u6587 ${args.with_full} \xB7 \u7B2C ${off}-${Math.min(off + CHUNK, full.length)} / ${full.length} \u5B57\u7B26]
8983
+
8984
+ ${slice}${more}`;
8985
+ }
8986
+ const cleanQuery = (args.query || "").trim();
8987
+ if (!cleanQuery) return "\u274C [recall] \u68C0\u7D22\u5173\u952E\u8BCD\u4E0D\u80FD\u4E3A\u7A7A\uFF08\u6216\u6539\u7528 with_full \u53D6\u5B58\u6863\u5168\u6587\uFF09\u3002";
8988
+ const re = new RegExp(args.is_regex ? cleanQuery : escapeRegExp2(cleanQuery), "i");
8989
+ const lines = await readTranscriptLines(ctx.sessionId);
8990
+ const toolCallInfo = /* @__PURE__ */ new Map();
8991
+ for (const l of lines) {
8992
+ if (isEventLine(l) || !Array.isArray(l.tool_calls)) continue;
8993
+ for (const c of l.tool_calls) {
8994
+ let a = {};
8995
+ try {
8996
+ a = JSON.parse(c?.function?.arguments || "{}");
8997
+ } catch {
8998
+ }
8999
+ toolCallInfo.set(c.id, { name: c?.function?.name ?? "", args: a, ts: l.ts });
9000
+ }
9001
+ }
9002
+ const limit = Math.min(Math.max(Math.floor(args.limit ?? 6), 1), 12);
9003
+ const runFilter = args.run_id?.trim();
9004
+ const blocks = [];
9005
+ let runN = 0;
9006
+ let runId = "";
9007
+ for (const l of lines) {
9008
+ if (isEventLine(l)) {
9009
+ if (l.dscEvent === "run.start") {
9010
+ runN++;
9011
+ runId = String(l.runId ?? "");
9012
+ }
9013
+ continue;
9014
+ }
9015
+ const role = l.role;
9016
+ if (role === "system") continue;
9017
+ if (runFilter && !(runId && runId.startsWith(runFilter))) continue;
9018
+ let info;
9019
+ if (role === "tool") {
9020
+ info = toolCallInfo.get(l.tool_call_id);
9021
+ if (info?.name === "recall") continue;
9022
+ }
9023
+ const text = lineText(l);
9024
+ if (!text || !re.test(text)) continue;
9025
+ const ts = l.ts;
9026
+ const roleDesc = role === "tool" ? `${info?.name ?? "tool"} \u8C03\u7528\u7ED3\u679C` : role === "assistant" ? "assistant\uFF08\u6587\u672C/\u5DE5\u5177\u8C03\u7528\u53C2\u6570\uFF09" : "\u7528\u6237\u6D88\u606F";
9027
+ let header = `\u2500\u2500 \u547D\u4E2D${blocks.length + 1} \xB7 run#${runN}${runId ? `(${runId.slice(0, 8)})` : ""} \xB7 ${roleDesc} \xB7 ${ts ?? "\u65F6\u95F4\u672A\u77E5"} \u2500\u2500`;
9028
+ if (role === "tool") {
9029
+ header += `
9030
+ \u6821\u9A8C\uFF1A${await annotateStaleness(info?.args, ts)}`;
9031
+ if (typeof l.content === "string" && l.content.includes("\u5B8C\u6574\u539F\u6587\u5DF2\u5B58\u6863")) {
9032
+ header += `
9033
+ \u2702\uFE0F \u8BE5\u7ED3\u679C\u66FE\u88AB\u622A\u65AD\uFF0C\u4F20 with_full="${l.tool_call_id}" \u53EF\u53D6\u5B58\u6863\u5168\u6587`;
9034
+ }
9035
+ }
9036
+ blocks.push(`${header}
9037
+ ${snippetAround(text, re, 700)}`);
9038
+ if (blocks.length >= limit) break;
9039
+ }
9040
+ if (blocks.length === 0) {
9041
+ return [
9042
+ `\u672A\u547D\u4E2D "${args.query}"\u3002\u5EFA\u8BAE\uFF1A`,
9043
+ "\xB7 \u6362\u7528\u6458\u8981\u69FD \u27E6DSC:ARCHIVE-INDEX\u27E7 \u4E2D\u51FA\u73B0\u8FC7\u7684\u5B9E\u4F53\u540D\uFF08\u6587\u4EF6\u8DEF\u5F84/\u51FD\u6570\u540D/\u62A5\u9519\u5173\u952E\u8BCD\uFF09",
9044
+ "\xB7 \u591A\u5173\u952E\u8BCD\u7528 is_regex=true \u4EE5 | \u5408\u5E76\u6269\u5927\u5339\u914D",
9045
+ "\xB7 \u8BB0\u5F97\u5F52\u6863\u533A\u5728\u6458\u8981\u69FD\u4E4B\u524D\u7684\u66F4\u65E9\u8F6E\u6B21\u2014\u2014\u7528\u66F4\u65E9\u9636\u6BB5\u51FA\u73B0\u8FC7\u7684\u8BCD"
9046
+ ].join("\n");
9047
+ }
9048
+ return [
9049
+ `[recall] \u672C\u4F1A\u8BDD\u5168\u91CF\u8F6C\u5F55\u547D\u4E2D ${blocks.length} \u6761\uFF08\u6309\u65F6\u95F4\u65E7\u2192\u65B0\uFF0C\u542B\u5DF2\u5F52\u6863\u6D88\u606F\uFF09\uFF1A`,
9050
+ "",
9051
+ blocks.join("\n\n"),
9052
+ "",
9053
+ "\u63D0\u793A\uFF1A\u26A0\uFE0F \u6807\u6CE8\u7684\u6587\u4EF6\u5FC5\u987B\u91CD\u65B0 read_file \u9A8C\u8BC1\u540E\u624D\u80FD\u636E\u4EE5\u4FEE\u6539\uFF1B\u672C\u5DE5\u5177\u7ED3\u679C\u4EC5\u4F5C\u5386\u53F2\u7EBF\u7D22\uFF0C\u4E0D\u66FF\u4EE3\u5F53\u524D\u6587\u4EF6\u72B6\u6001\u3002"
9054
+ ].join("\n");
9055
+ } catch (e) {
9056
+ return `\u274C [recall] \u68C0\u7D22\u5931\u8D25: ${e instanceof Error ? e.message : String(e)}`;
9057
+ }
9058
+ }
9059
+ }
9060
+ }
9061
+ ];
9062
+ }
9063
+ });
9064
+
8827
9065
  // ../core/src/tool/registry/spreadsheet.ts
8828
9066
  var getExcelJs, colLetter, cellToText, esc, spreadsheetTools;
8829
9067
  var init_spreadsheet = __esm({
@@ -8940,7 +9178,7 @@ var init_spreadsheet = __esm({
8940
9178
  });
8941
9179
 
8942
9180
  // ../core/src/tool/registry/document.ts
8943
- import fs26 from "fs/promises";
9181
+ import fs27 from "fs/promises";
8944
9182
  var getMammoth, getUnpdf, documentTools;
8945
9183
  var init_document = __esm({
8946
9184
  "../core/src/tool/registry/document.ts"() {
@@ -9030,7 +9268,7 @@ var init_document = __esm({
9030
9268
  }
9031
9269
  const start = args.start_char ? Math.max(0, Math.floor(args.start_char)) : 0;
9032
9270
  const maxChars = Math.min(args.max_chars ? Math.max(1, Math.floor(args.max_chars)) : 3e4, 5e4);
9033
- const buf = await fs26.readFile(absPath);
9271
+ const buf = await fs27.readFile(absPath);
9034
9272
  const unpdf = await getUnpdf();
9035
9273
  const pdf = await unpdf.getDocumentProxy(new Uint8Array(buf));
9036
9274
  const { text, totalPages } = await unpdf.extractText(pdf, { mergePages: true });
@@ -9085,6 +9323,7 @@ var init_tool = __esm({
9085
9323
  init_worktree();
9086
9324
  init_notebook();
9087
9325
  init_memory();
9326
+ init_recall();
9088
9327
  init_spreadsheet();
9089
9328
  init_document();
9090
9329
  init_type();
@@ -9110,6 +9349,7 @@ var init_tool = __esm({
9110
9349
  ...worktreeTools,
9111
9350
  ...notebookTools,
9112
9351
  ...memoryTools,
9352
+ ...recallTools,
9113
9353
  ...spreadsheetTools,
9114
9354
  ...documentTools
9115
9355
  // read_docx / read_pdf(Word / PDF 文档读取,补 read_file 读不了的二进制文档)
@@ -9233,7 +9473,7 @@ var init_backgroundTool = __esm({
9233
9473
  });
9234
9474
 
9235
9475
  // ../core/src/tool/autoPermission.ts
9236
- import path29 from "path";
9476
+ import path30 from "path";
9237
9477
  var AUTO_SCOPE, AUTO_DEFAULT_EXTRA, AUTO_AGGRESSIVE_EXTRA, isMcpTool, BUILTIN_AUTO_DENY, matchBuiltinDeny, COMMAND_DENY, matchCommandDeny, hasShellMetachars, READONLY_HEADS, hasWriteModifier, SENSITIVE_FILE_ARG_RE, hasSensitiveFileArg, isReadOnlyCommand, isWithinWorkspace, runAutoCheck;
9238
9478
  var init_autoPermission = __esm({
9239
9479
  "../core/src/tool/autoPermission.ts"() {
@@ -9368,9 +9608,9 @@ var init_autoPermission = __esm({
9368
9608
  isWithinWorkspace = (p, cwd) => {
9369
9609
  if (!p || !cwd) return false;
9370
9610
  try {
9371
- const abs = path29.isAbsolute(p) ? p : path29.resolve(cwd, p);
9372
- const rel = path29.relative(cwd, abs);
9373
- return rel === "" || !rel.startsWith("..") && !path29.isAbsolute(rel);
9611
+ const abs = path30.isAbsolute(p) ? p : path30.resolve(cwd, p);
9612
+ const rel = path30.relative(cwd, abs);
9613
+ return rel === "" || !rel.startsWith("..") && !path30.isAbsolute(rel);
9374
9614
  } catch {
9375
9615
  return false;
9376
9616
  }
@@ -9398,6 +9638,8 @@ var init_autoPermission = __esm({
9398
9638
  });
9399
9639
 
9400
9640
  // ../core/src/agent/toolExecution.ts
9641
+ import fs28 from "fs/promises";
9642
+ import path31 from "path";
9401
9643
  var applyPrivacyMasking, processToolCall;
9402
9644
  var init_toolExecution = __esm({
9403
9645
  "../core/src/agent/toolExecution.ts"() {
@@ -9413,6 +9655,7 @@ var init_toolExecution = __esm({
9413
9655
  init_autoPermission();
9414
9656
  init_loader();
9415
9657
  init_config();
9658
+ init_store();
9416
9659
  init_planMode();
9417
9660
  applyPrivacyMasking = (rules3, args, output) => {
9418
9661
  if (!rules3) return output;
@@ -9634,7 +9877,20 @@ ${result}`;
9634
9877
  events({ sessionId, eventType: "tool.validation.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round }, payload: { output: result } });
9635
9878
  }
9636
9879
  result = applyPrivacyMasking(matchedTool?.function?.privacyMaskingRules, calledArgs, result);
9637
- result = truncateToolResult(result, matchedTool?.function?.maxOutputCharacters);
9880
+ let sidecarNote;
9881
+ const truncBudget = matchedTool?.function?.maxOutputCharacters ?? appConfig.MAX_TOOL_RESULT_CHARS;
9882
+ if (result.length > truncBudget) {
9883
+ try {
9884
+ const sidecarDir = path31.join(getSessionsDirPath(sessionId), "tool-outputs");
9885
+ await fs28.mkdir(sidecarDir, { recursive: true });
9886
+ const safeId = String(toolCall.id).replace(/[^A-Za-z0-9_-]/g, "");
9887
+ await fs28.writeFile(path31.join(sidecarDir, `${safeId}.txt`), result, "utf-8");
9888
+ sidecarNote = `\u5B8C\u6574\u539F\u6587\u5DF2\u5B58\u6863\uFF0Crecall \u5DE5\u5177\u4F20 with_full="${toolCall.id}" \u53EF\u53D6\u56DE`;
9889
+ } catch (e) {
9890
+ 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);
9891
+ }
9892
+ }
9893
+ result = truncateToolResult(result, matchedTool?.function?.maxOutputCharacters, sidecarNote);
9638
9894
  const FAILED_PREFIXES = ["\u5DE5\u5177\u6267\u884C\u5931\u8D25", "\u53C2\u6570\u89E3\u6790\u5931\u8D25", "\u274C", "\u3010\u7CFB\u7EDF\u5224\u5B9A", "\u{1F512}", "\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25", "\u9879\u76EE\u6811\u626B\u63CF\u5931\u8D25", "\u7B26\u53F7\u5927\u7EB2\u5206\u6790\u5931\u8D25", "\u64CD\u4F5C\u5931\u8D25:"];
9639
9895
  const ok = explicitOk ?? !FAILED_PREFIXES.some((p) => result.startsWith(p));
9640
9896
  let resultForModel = result;
@@ -10540,7 +10796,7 @@ var init_content = __esm({
10540
10796
  });
10541
10797
 
10542
10798
  // ../core/src/session/lineage.ts
10543
- import fs27 from "node:fs";
10799
+ import fs29 from "node:fs";
10544
10800
  var parentOfSubsession, stringAncestorsOf, readForkedFromSync, lineageClosureOf, ownerCanApprove;
10545
10801
  var init_lineage = __esm({
10546
10802
  "../core/src/session/lineage.ts"() {
@@ -10563,7 +10819,7 @@ var init_lineage = __esm({
10563
10819
  };
10564
10820
  readForkedFromSync = (sessionId) => {
10565
10821
  try {
10566
- const raw = fs27.readFileSync(getStatePath(sessionId), "utf-8");
10822
+ const raw = fs29.readFileSync(getStatePath(sessionId), "utf-8");
10567
10823
  const v = JSON.parse(raw)?.forkedFrom;
10568
10824
  return typeof v === "string" && v.length > 0 ? v : void 0;
10569
10825
  } catch {
@@ -10760,8 +11016,8 @@ var init_subagent = __esm({
10760
11016
  });
10761
11017
 
10762
11018
  // ../core/src/hooks/loader.ts
10763
- import fs28 from "fs/promises";
10764
- import path30 from "path";
11019
+ import fs30 from "fs/promises";
11020
+ import path32 from "path";
10765
11021
  var readHooksConfig, appendValidated, validateRule, parseStdoutDecision, parseAgentDecision, compileRule2, loadHooks, initHooks;
10766
11022
  var init_loader4 = __esm({
10767
11023
  "../core/src/hooks/loader.ts"() {
@@ -10776,15 +11032,15 @@ var init_loader4 = __esm({
10776
11032
  readHooksConfig = async (includeProject) => {
10777
11033
  const merged = {};
10778
11034
  const paths = [
10779
- path30.join(appConfig.dataDir, "settings.json"),
11035
+ path32.join(appConfig.dataDir, "settings.json"),
10780
11036
  // 全局用户级
10781
- ...includeProject ? [path30.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
11037
+ ...includeProject ? [path32.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
10782
11038
  // 项目级(叠加);未信任时省略
10783
11039
  ];
10784
11040
  for (const configPath of paths) {
10785
11041
  let raw;
10786
11042
  try {
10787
- raw = await fs28.readFile(configPath, "utf-8");
11043
+ raw = await fs30.readFile(configPath, "utf-8");
10788
11044
  } catch {
10789
11045
  continue;
10790
11046
  }
@@ -11114,8 +11370,8 @@ ${m.context}`;
11114
11370
  });
11115
11371
 
11116
11372
  // ../core/src/skills/loader.ts
11117
- import fs29 from "fs/promises";
11118
- import path31 from "path";
11373
+ import fs31 from "fs/promises";
11374
+ import path33 from "path";
11119
11375
  import { fileURLToPath as fileURLToPath2 } from "url";
11120
11376
  var BUILTIN_DIR, SOURCES2, MAX_SKILL_BODY_BYTES, splitList, parseSkillAt, loadSkills, initSkills;
11121
11377
  var init_loader5 = __esm({
@@ -11126,18 +11382,18 @@ var init_loader5 = __esm({
11126
11382
  init_registry3();
11127
11383
  init_skill();
11128
11384
  init_registry2();
11129
- BUILTIN_DIR = path31.join(path31.dirname(fileURLToPath2(import.meta.url)), "builtin");
11385
+ BUILTIN_DIR = path33.join(path33.dirname(fileURLToPath2(import.meta.url)), "builtin");
11130
11386
  SOURCES2 = [
11131
11387
  { dir: BUILTIN_DIR, source: "builtin" },
11132
- { dir: path31.join(appConfig.dataDir, "skills"), source: "global" },
11133
- { dir: path31.join(process.cwd(), ".deepseeker-code", "skills"), source: "project" }
11388
+ { dir: path33.join(appConfig.dataDir, "skills"), source: "global" },
11389
+ { dir: path33.join(process.cwd(), ".deepseeker-code", "skills"), source: "project" }
11134
11390
  ];
11135
11391
  MAX_SKILL_BODY_BYTES = 64 * 1024;
11136
11392
  splitList = (raw) => (raw ?? "").split(",").map((s) => s.trim()).filter(Boolean);
11137
11393
  parseSkillAt = async (skillFile, dir, source) => {
11138
11394
  let raw;
11139
11395
  try {
11140
- raw = await fs29.readFile(skillFile, "utf-8");
11396
+ raw = await fs31.readFile(skillFile, "utf-8");
11141
11397
  } catch {
11142
11398
  return null;
11143
11399
  }
@@ -11176,7 +11432,7 @@ var init_loader5 = __esm({
11176
11432
  loadSkills = async (includeProject) => {
11177
11433
  const picked = await scanSources(
11178
11434
  filterSources(SOURCES2, includeProject),
11179
- (e, dir) => e.isDirectory() ? path31.join(dir, e.name, "SKILL.md") : void 0,
11435
+ (e, dir) => e.isDirectory() ? path33.join(dir, e.name, "SKILL.md") : void 0,
11180
11436
  parseSkillAt
11181
11437
  );
11182
11438
  for (const { item } of picked) registerSkill(item);
@@ -11207,8 +11463,8 @@ var init_loader5 = __esm({
11207
11463
  });
11208
11464
 
11209
11465
  // ../core/src/agents/loader.ts
11210
- import fs30 from "fs/promises";
11211
- import path32 from "path";
11466
+ import fs32 from "fs/promises";
11467
+ import path34 from "path";
11212
11468
  import { fileURLToPath as fileURLToPath3 } from "url";
11213
11469
  var BUILTIN_DIR2, SOURCES3, parseAgentAt, initAgents;
11214
11470
  var init_loader6 = __esm({
@@ -11218,16 +11474,16 @@ var init_loader6 = __esm({
11218
11474
  init_frontmatter();
11219
11475
  init_registry4();
11220
11476
  init_registry2();
11221
- BUILTIN_DIR2 = path32.join(path32.dirname(fileURLToPath3(import.meta.url)), "builtin");
11477
+ BUILTIN_DIR2 = path34.join(path34.dirname(fileURLToPath3(import.meta.url)), "builtin");
11222
11478
  SOURCES3 = [
11223
11479
  { dir: BUILTIN_DIR2, source: "builtin" },
11224
- { dir: path32.join(appConfig.dataDir, "agents"), source: "global" },
11225
- { dir: path32.join(process.cwd(), ".deepseeker-code", "agents"), source: "project" }
11480
+ { dir: path34.join(appConfig.dataDir, "agents"), source: "global" },
11481
+ { dir: path34.join(process.cwd(), ".deepseeker-code", "agents"), source: "project" }
11226
11482
  ];
11227
11483
  parseAgentAt = async (file, dir, source) => {
11228
11484
  let raw;
11229
11485
  try {
11230
- raw = await fs30.readFile(file, "utf-8");
11486
+ raw = await fs32.readFile(file, "utf-8");
11231
11487
  } catch {
11232
11488
  return null;
11233
11489
  }
@@ -11262,7 +11518,7 @@ var init_loader6 = __esm({
11262
11518
  const known = new Set(into.map((t) => t.function.name));
11263
11519
  const picked = await scanSources(
11264
11520
  filterSources(SOURCES3, includeProject),
11265
- (e, dir) => e.isFile() && e.name.endsWith(".agent.md") ? path32.join(dir, e.name) : void 0,
11521
+ (e, dir) => e.isFile() && e.name.endsWith(".agent.md") ? path34.join(dir, e.name) : void 0,
11266
11522
  parseAgentAt
11267
11523
  );
11268
11524
  for (const { item: m, file, source } of picked) {
@@ -11299,8 +11555,8 @@ var init_registry7 = __esm({
11299
11555
  });
11300
11556
 
11301
11557
  // ../core/src/commands/loader.ts
11302
- import fs31 from "fs/promises";
11303
- import path33 from "path";
11558
+ import fs33 from "fs/promises";
11559
+ import path35 from "path";
11304
11560
  import { fileURLToPath as fileURLToPath4 } from "url";
11305
11561
  var BUILTIN_DIR3, SOURCES4, MAX_COMMAND_BODY_BYTES, parseCommandAt, loadCommands, initCommands;
11306
11562
  var init_loader7 = __esm({
@@ -11310,17 +11566,17 @@ var init_loader7 = __esm({
11310
11566
  init_frontmatter();
11311
11567
  init_registry7();
11312
11568
  init_registry2();
11313
- BUILTIN_DIR3 = path33.join(path33.dirname(fileURLToPath4(import.meta.url)), "builtin");
11569
+ BUILTIN_DIR3 = path35.join(path35.dirname(fileURLToPath4(import.meta.url)), "builtin");
11314
11570
  SOURCES4 = [
11315
11571
  { dir: BUILTIN_DIR3, source: "builtin" },
11316
- { dir: path33.join(appConfig.dataDir, "commands"), source: "global" },
11317
- { dir: path33.join(process.cwd(), ".deepseeker-code", "commands"), source: "project" }
11572
+ { dir: path35.join(appConfig.dataDir, "commands"), source: "global" },
11573
+ { dir: path35.join(process.cwd(), ".deepseeker-code", "commands"), source: "project" }
11318
11574
  ];
11319
11575
  MAX_COMMAND_BODY_BYTES = 64 * 1024;
11320
11576
  parseCommandAt = async (file, _dir, source) => {
11321
11577
  let raw;
11322
11578
  try {
11323
- raw = await fs31.readFile(file, "utf-8");
11579
+ raw = await fs33.readFile(file, "utf-8");
11324
11580
  } catch {
11325
11581
  return null;
11326
11582
  }
@@ -11331,7 +11587,7 @@ var init_loader7 = __esm({
11331
11587
  }
11332
11588
  const name = parsed.frontmatter.name;
11333
11589
  const description = parsed.frontmatter.description;
11334
- const fallbackName = path33.basename(file, ".md");
11590
+ const fallbackName = path35.basename(file, ".md");
11335
11591
  const finalName = name || fallbackName;
11336
11592
  if (!description) {
11337
11593
  console.warn(`\u26A0\uFE0F [commands] \u7F3A\u5C11 description\uFF08${file}\uFF09\uFF0C\u5DF2\u8DF3\u8FC7`);
@@ -11357,7 +11613,7 @@ var init_loader7 = __esm({
11357
11613
  loadCommands = async (includeProject) => {
11358
11614
  const picked = await scanSources(
11359
11615
  filterSources(SOURCES4, includeProject),
11360
- (e, dir) => e.isFile() && e.name.endsWith(".md") ? path33.join(dir, e.name) : void 0,
11616
+ (e, dir) => e.isFile() && e.name.endsWith(".md") ? path35.join(dir, e.name) : void 0,
11361
11617
  parseCommandAt
11362
11618
  );
11363
11619
  for (const { item } of picked) registerCommand(item);
@@ -11375,8 +11631,8 @@ var init_loader7 = __esm({
11375
11631
  });
11376
11632
 
11377
11633
  // ../core/src/outputStyles/loader.ts
11378
- import fs32 from "fs/promises";
11379
- import path34 from "path";
11634
+ import fs34 from "fs/promises";
11635
+ import path36 from "path";
11380
11636
  import { fileURLToPath as fileURLToPath5 } from "url";
11381
11637
  var BUILTIN_DIR4, MAX_STYLE_BODY_BYTES, SOURCES5, parseStyleAt, loadOutputStyles, initOutputStyles;
11382
11638
  var init_loader8 = __esm({
@@ -11386,17 +11642,17 @@ var init_loader8 = __esm({
11386
11642
  init_frontmatter();
11387
11643
  init_registry5();
11388
11644
  init_registry2();
11389
- BUILTIN_DIR4 = path34.join(path34.dirname(fileURLToPath5(import.meta.url)), "builtin");
11645
+ BUILTIN_DIR4 = path36.join(path36.dirname(fileURLToPath5(import.meta.url)), "builtin");
11390
11646
  MAX_STYLE_BODY_BYTES = 64 * 1024;
11391
11647
  SOURCES5 = [
11392
11648
  { dir: BUILTIN_DIR4, source: "builtin" },
11393
- { dir: path34.join(appConfig.dataDir, "output-styles"), source: "global" },
11394
- { dir: path34.join(process.cwd(), ".deepseeker-code", "output-styles"), source: "project" }
11649
+ { dir: path36.join(appConfig.dataDir, "output-styles"), source: "global" },
11650
+ { dir: path36.join(process.cwd(), ".deepseeker-code", "output-styles"), source: "project" }
11395
11651
  ];
11396
11652
  parseStyleAt = async (file, _dir, source) => {
11397
11653
  let raw;
11398
11654
  try {
11399
- raw = await fs32.readFile(file, "utf-8");
11655
+ raw = await fs34.readFile(file, "utf-8");
11400
11656
  } catch {
11401
11657
  return null;
11402
11658
  }
@@ -11428,7 +11684,7 @@ var init_loader8 = __esm({
11428
11684
  loadOutputStyles = async (includeProject) => {
11429
11685
  const picked = await scanSources(
11430
11686
  filterSources(SOURCES5, includeProject),
11431
- (e, dir) => e.isFile() && e.name.endsWith(".md") ? path34.join(dir, e.name) : void 0,
11687
+ (e, dir) => e.isFile() && e.name.endsWith(".md") ? path36.join(dir, e.name) : void 0,
11432
11688
  parseStyleAt
11433
11689
  );
11434
11690
  for (const { item } of picked) registerOutputStyle(item);
@@ -11509,8 +11765,8 @@ var init_bootstrap = __esm({
11509
11765
  });
11510
11766
 
11511
11767
  // ../core/src/statusLine/config.ts
11512
- import fs33 from "fs/promises";
11513
- import path35 from "path";
11768
+ import fs35 from "fs/promises";
11769
+ import path37 from "path";
11514
11770
  var parseBlock, readStatusLineConfig;
11515
11771
  var init_config2 = __esm({
11516
11772
  "../core/src/statusLine/config.ts"() {
@@ -11526,16 +11782,16 @@ var init_config2 = __esm({
11526
11782
  };
11527
11783
  readStatusLineConfig = async (includeProject) => {
11528
11784
  const paths = [
11529
- path35.join(appConfig.dataDir, "settings.json"),
11785
+ path37.join(appConfig.dataDir, "settings.json"),
11530
11786
  // 全局用户级
11531
- ...includeProject ? [path35.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
11787
+ ...includeProject ? [path37.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
11532
11788
  // 项目级(覆盖);未信任时省略
11533
11789
  ];
11534
11790
  let result = null;
11535
11791
  for (const configPath of paths) {
11536
11792
  let raw;
11537
11793
  try {
11538
- raw = await fs33.readFile(configPath, "utf-8");
11794
+ raw = await fs35.readFile(configPath, "utf-8");
11539
11795
  } catch {
11540
11796
  continue;
11541
11797
  }
@@ -11555,8 +11811,8 @@ var init_config2 = __esm({
11555
11811
 
11556
11812
  // ../core/src/statusLine/runner.ts
11557
11813
  import { spawn as spawn5 } from "child_process";
11558
- import fs34 from "fs";
11559
- import path36 from "path";
11814
+ import fs36 from "fs";
11815
+ import path38 from "path";
11560
11816
  import { fileURLToPath as fileURLToPath6 } from "url";
11561
11817
  var STATUSLINE_TIMEOUT_MS, cachedVersion, runStatusLine;
11562
11818
  var init_runner = __esm({
@@ -11565,16 +11821,16 @@ var init_runner = __esm({
11565
11821
  init_guard();
11566
11822
  STATUSLINE_TIMEOUT_MS = 3e3;
11567
11823
  try {
11568
- const here = path36.dirname(fileURLToPath6(import.meta.url));
11824
+ const here = path38.dirname(fileURLToPath6(import.meta.url));
11569
11825
  const candidates = [
11570
- path36.join(here, "../../../package.json"),
11826
+ path38.join(here, "../../../package.json"),
11571
11827
  // src/core/package.json
11572
- path36.join(here, "../../../../package.json")
11828
+ path38.join(here, "../../../../package.json")
11573
11829
  // 仓库根 package.json
11574
11830
  ];
11575
11831
  for (const p of candidates) {
11576
11832
  try {
11577
- const pkg = JSON.parse(fs34.readFileSync(p, "utf-8"));
11833
+ const pkg = JSON.parse(fs36.readFileSync(p, "utf-8"));
11578
11834
  if (typeof pkg.version === "string" && pkg.version) {
11579
11835
  cachedVersion = pkg.version;
11580
11836
  break;
@@ -11633,8 +11889,8 @@ var init_createModel = __esm({
11633
11889
  });
11634
11890
 
11635
11891
  // ../core/src/observability/store.ts
11636
- import path37 from "path";
11637
- import fs35 from "fs/promises";
11892
+ import path39 from "path";
11893
+ import fs37 from "fs/promises";
11638
11894
  var getTraceDirPath, getTracePath, tracePathCache, ensuredTraceDirs, ensureTraceDir, getGlobalClockPath, getTraceStorePath;
11639
11895
  var init_store3 = __esm({
11640
11896
  "../core/src/observability/store.ts"() {
@@ -11644,21 +11900,21 @@ var init_store3 = __esm({
11644
11900
  init_common();
11645
11901
  getTraceDirPath = (mainTraceId) => {
11646
11902
  assertSafeSessionId(mainTraceId, "traceId");
11647
- return path37.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
11903
+ return path39.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
11648
11904
  };
11649
11905
  getTracePath = () => {
11650
- return path37.join(appConfig.dataDir, "trace");
11906
+ return path39.join(appConfig.dataDir, "trace");
11651
11907
  };
11652
11908
  tracePathCache = /* @__PURE__ */ new Map();
11653
11909
  ensuredTraceDirs = /* @__PURE__ */ new Set();
11654
11910
  ensureTraceDir = async (mainTraceId) => {
11655
11911
  const dir = getTraceDirPath(mainTraceId);
11656
11912
  if (ensuredTraceDirs.has(dir)) return;
11657
- await fs35.mkdir(dir, { recursive: true });
11913
+ await fs37.mkdir(dir, { recursive: true });
11658
11914
  ensuredTraceDirs.add(dir);
11659
11915
  };
11660
11916
  getGlobalClockPath = () => {
11661
- return path37.join(getTracePath(), "trace-cleanup-clock.json");
11917
+ return path39.join(getTracePath(), "trace-cleanup-clock.json");
11662
11918
  };
11663
11919
  getTraceStorePath = async (mainTraceId) => {
11664
11920
  assertSafeSessionId(mainTraceId, "traceId");
@@ -11667,7 +11923,7 @@ var init_store3 = __esm({
11667
11923
  if (cached2) return cached2;
11668
11924
  await ensureTraceDir(rootId);
11669
11925
  const dir = getTraceDirPath(rootId);
11670
- const files = await fs35.readdir(dir);
11926
+ const files = await fs37.readdir(dir);
11671
11927
  const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
11672
11928
  let fileName = "";
11673
11929
  if (existedFile) {
@@ -11676,7 +11932,7 @@ var init_store3 = __esm({
11676
11932
  const todayStr = getTodayDateString();
11677
11933
  fileName = `trace-${todayStr}__${rootId}.jsonl`;
11678
11934
  }
11679
- const resolved = path37.join(dir, fileName);
11935
+ const resolved = path39.join(dir, fileName);
11680
11936
  tracePathCache.set(rootId, resolved);
11681
11937
  return resolved;
11682
11938
  };
@@ -11684,8 +11940,8 @@ var init_store3 = __esm({
11684
11940
  });
11685
11941
 
11686
11942
  // ../core/src/observability/trace.ts
11687
- import fs36 from "fs/promises";
11688
- import path38 from "path";
11943
+ import fs38 from "fs/promises";
11944
+ import path40 from "path";
11689
11945
  async function emitTrace(base) {
11690
11946
  const event = {
11691
11947
  sessionId: base.sessionId,
@@ -11707,7 +11963,7 @@ async function emitTrace(base) {
11707
11963
  async function appendTraceEvent(event) {
11708
11964
  const p = await getTraceStorePath(event.sessionId);
11709
11965
  const line = JSON.stringify(event) + "\n";
11710
- await fs36.appendFile(p, line, "utf-8");
11966
+ await fs38.appendFile(p, line, "utf-8");
11711
11967
  if (workspaceTraceBytes < 0) {
11712
11968
  workspaceTraceBytes = await getDirBytes(getTracePath());
11713
11969
  }
@@ -11739,8 +11995,8 @@ async function maybeCleanupAfterAppend(sessionId) {
11739
11995
  lastSizeCleanupAt2 = now;
11740
11996
  diskLastCleanupAt2 = now;
11741
11997
  const clockPath = getGlobalClockPath();
11742
- await fs36.mkdir(path38.dirname(clockPath), { recursive: true });
11743
- await fs36.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
11998
+ await fs38.mkdir(path40.dirname(clockPath), { recursive: true });
11999
+ await fs38.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
11744
12000
  if (deletedCount > 0) {
11745
12001
  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`);
11746
12002
  }
@@ -11760,22 +12016,22 @@ async function cleanupOldTraceFiles() {
11760
12016
  let deleted = 0;
11761
12017
  let relativePaths;
11762
12018
  try {
11763
- relativePaths = await fs36.readdir(dir, { recursive: true });
12019
+ relativePaths = await fs38.readdir(dir, { recursive: true });
11764
12020
  } catch {
11765
12021
  return 0;
11766
12022
  }
11767
12023
  const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
11768
12024
  for (const relativePath of relativePaths) {
11769
- const fileName = path38.basename(relativePath);
12025
+ const fileName = path40.basename(relativePath);
11770
12026
  const m = fileName.match(re);
11771
12027
  if (!m) continue;
11772
12028
  const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
11773
12029
  if (fileBornDay >= cutoff) continue;
11774
- const fullPath = path38.join(dir, relativePath);
12030
+ const fullPath = path40.join(dir, relativePath);
11775
12031
  try {
11776
- const st = await fs36.stat(fullPath);
12032
+ const st = await fs38.stat(fullPath);
11777
12033
  if (now - st.mtimeMs < ACTIVE_GRACE_MS2) continue;
11778
- await fs36.unlink(fullPath);
12034
+ await fs38.unlink(fullPath);
11779
12035
  deleted += 1;
11780
12036
  } catch {
11781
12037
  }
@@ -11786,18 +12042,18 @@ async function evictOldestForSize2(targetBytes) {
11786
12042
  const dir = getTracePath();
11787
12043
  let relativePaths;
11788
12044
  try {
11789
- relativePaths = await fs36.readdir(dir, { recursive: true });
12045
+ relativePaths = await fs38.readdir(dir, { recursive: true });
11790
12046
  } catch {
11791
12047
  return 0;
11792
12048
  }
11793
12049
  const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
11794
12050
  const candidates = [];
11795
12051
  for (const relativePath of relativePaths) {
11796
- const fileName = path38.basename(relativePath);
12052
+ const fileName = path40.basename(relativePath);
11797
12053
  if (!re.test(fileName)) continue;
11798
12054
  try {
11799
- const st = await fs36.stat(path38.join(dir, relativePath));
11800
- candidates.push({ mtime: st.mtimeMs, fullPath: path38.join(dir, relativePath), size: st.size });
12055
+ const st = await fs38.stat(path40.join(dir, relativePath));
12056
+ candidates.push({ mtime: st.mtimeMs, fullPath: path40.join(dir, relativePath), size: st.size });
11801
12057
  } catch {
11802
12058
  }
11803
12059
  }
@@ -11807,7 +12063,7 @@ async function evictOldestForSize2(targetBytes) {
11807
12063
  for (const c of candidates) {
11808
12064
  if (totalBytes <= targetBytes) break;
11809
12065
  try {
11810
- await fs36.unlink(c.fullPath);
12066
+ await fs38.unlink(c.fullPath);
11811
12067
  totalBytes -= c.size;
11812
12068
  deleted += 1;
11813
12069
  } catch {
@@ -11839,7 +12095,7 @@ var init_trace = __esm({
11839
12095
  if (clockLoaded2) return;
11840
12096
  clockLoaded2 = true;
11841
12097
  try {
11842
- const rawClock = await fs36.readFile(getGlobalClockPath(), "utf-8");
12098
+ const rawClock = await fs38.readFile(getGlobalClockPath(), "utf-8");
11843
12099
  diskLastCleanupAt2 = JSON.parse(rawClock).lastCleanupAt || 0;
11844
12100
  } catch {
11845
12101
  diskLastCleanupAt2 = 0;
@@ -11985,8 +12241,8 @@ ${PLAN_MODE_AUTO_ENTER_HINT}
11985
12241
  });
11986
12242
 
11987
12243
  // ../core/src/serve/chatProcessing.ts
11988
- import path39 from "path";
11989
- import fs37 from "fs";
12244
+ import path41 from "path";
12245
+ import fs39 from "fs";
11990
12246
  var handleUnifiedChat;
11991
12247
  var init_chatProcessing = __esm({
11992
12248
  "../core/src/serve/chatProcessing.ts"() {
@@ -12040,17 +12296,17 @@ ${inject}`;
12040
12296
  if (roots.length > 1) {
12041
12297
  let activeReal = getActiveWorkspaceRoot();
12042
12298
  try {
12043
- activeReal = fs37.realpathSync(activeReal);
12299
+ activeReal = fs39.realpathSync(activeReal);
12044
12300
  } catch {
12045
12301
  }
12046
- const lines = roots.map((r) => `- ${path39.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"}`);
12302
+ 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"}`);
12047
12303
  sysPrompt = sysPrompt + `
12048
12304
 
12049
12305
  \u3010\u5DE5\u4F5C\u533A\uFF08\u591A\u9879\u76EE\uFF09\u3011
12050
12306
  \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>:
12051
12307
  ${lines.join("\n")}
12052
- \u2605 \u8DEF\u5F84\u951A\u5B9A\u94C1\u5F8B\uFF1A\u5DE5\u5177\u7F3A\u7701\u53EA\u4F5C\u7528\u4E8E\u9ED8\u8BA4\u6839\uFF08${path39.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
12053
- \u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${path39.basename(activeReal) || activeReal} \u751F\u6548\u3002`;
12308
+ \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
12309
+ \u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${path41.basename(activeReal) || activeReal} \u751F\u6548\u3002`;
12054
12310
  }
12055
12311
  let replyText = "";
12056
12312
  try {
@@ -12137,7 +12393,7 @@ ${lines.join("\n")}
12137
12393
  });
12138
12394
 
12139
12395
  // ../core/src/session/fork.ts
12140
- import fs38 from "fs/promises";
12396
+ import fs40 from "fs/promises";
12141
12397
  var listForkAnchors, derivePrefix, forkSession;
12142
12398
  var init_fork = __esm({
12143
12399
  "../core/src/session/fork.ts"() {
@@ -12209,7 +12465,7 @@ var init_fork = __esm({
12209
12465
  const prefix = derivePrefix(lines, upToLineId);
12210
12466
  const newId = createUUID();
12211
12467
  await ensureSessionsDir(newId);
12212
- const rawText = await fs38.readFile(getTranscriptPath(sourceId), "utf-8");
12468
+ const rawText = await fs40.readFile(getTranscriptPath(sourceId), "utf-8");
12213
12469
  const kept = [];
12214
12470
  let good = 0;
12215
12471
  for (const s of rawText.split("\n")) {
@@ -12225,7 +12481,7 @@ var init_fork = __esm({
12225
12481
  }
12226
12482
  let payload = kept.join("\n");
12227
12483
  if (payload.length > 0 && !payload.endsWith("\n")) payload += "\n";
12228
- await fs38.writeFile(getTranscriptPath(newId), payload, "utf-8");
12484
+ await fs40.writeFile(getTranscriptPath(newId), payload, "utf-8");
12229
12485
  const srcState = await readStore(sourceId);
12230
12486
  const srcRolling = await getRollingState(sourceId);
12231
12487
  const legacy = !lines.some(isEventLine);
@@ -13810,7 +14066,7 @@ var init_SlashMenu = __esm({
13810
14066
  const descMax = Math.max(12, cols - cmdW - 6);
13811
14067
  return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: THEME.coral, paddingX: 1, paddingY: 0, marginTop: 1, children: [
13812
14068
  visible.map((e, i) => {
13813
- const active = i === selectedIndex;
14069
+ const active = i + start === selectedIndex;
13814
14070
  const desc = e.description.length > descMax ? `${e.description.slice(0, descMax - 1)}\u2026` : e.description;
13815
14071
  const gap = Math.max(1, cmdW - e.name.length);
13816
14072
  return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", children: [
@@ -13924,7 +14180,7 @@ var init_TopPanel = __esm({
13924
14180
  });
13925
14181
 
13926
14182
  // ../core/src/observability/inspect.ts
13927
- import fs39 from "fs";
14183
+ import fs41 from "fs";
13928
14184
  var CWD, fmt, readTrace, inspectUsage, inspectContext, inspectPermissions, inspectMcp, inspectHooks, inspectDebug;
13929
14185
  var init_inspect = __esm({
13930
14186
  "../core/src/observability/inspect.ts"() {
@@ -13942,7 +14198,7 @@ var init_inspect = __esm({
13942
14198
  if (!sessionId) return [];
13943
14199
  try {
13944
14200
  const p = await getTraceStorePath(sessionId);
13945
- const text = await fs39.promises.readFile(p, "utf8");
14201
+ const text = await fs41.promises.readFile(p, "utf8");
13946
14202
  const out = [];
13947
14203
  for (const line of text.split("\n")) {
13948
14204
  if (!line.trim()) continue;
@@ -14701,7 +14957,7 @@ init_updateCheck();
14701
14957
  init_trust();
14702
14958
  import { render } from "ink";
14703
14959
  import os5 from "os";
14704
- import path40 from "path";
14960
+ import path42 from "path";
14705
14961
  import { emitKeypressEvents } from "node:readline";
14706
14962
  import { jsx as jsx18 } from "react/jsx-runtime";
14707
14963
  var parseArgs = (argv) => {
@@ -14834,7 +15090,7 @@ var main = async () => {
14834
15090
  process.stdout.write("\x1B[2J\x1B[3J\x1B[1;1H");
14835
15091
  const cwdIsHome = () => {
14836
15092
  try {
14837
- return path40.resolve(cwd).toLowerCase() === path40.resolve(os5.homedir()).toLowerCase();
15093
+ return path42.resolve(cwd).toLowerCase() === path42.resolve(os5.homedir()).toLowerCase();
14838
15094
  } catch {
14839
15095
  return false;
14840
15096
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepseeker-code",
3
- "version": "1.0.45",
3
+ "version": "1.0.47",
4
4
  "description": "DeepSeeker-Code 终端客户端(React Ink,in-process 直驱 runAgent)",
5
5
  "homepage": "https://github.com/xknk/deepSeekCode#readme",
6
6
  "repository": {