deepseeker-code 1.0.4 → 1.0.41

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 +510 -193
  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:流式逐字输出、可折叠思考过程、工具调用卡、审批模态、两阶段计划模式、会话恢复。**in-process 直驱引擎**——不走 HTTP/端口,工具审批走 Ink 原生模态。
12
+ DeepSeeker-Code 在你的终端里跑一个自主 agent:流式逐字输出、可折叠思考过程、工具调用卡(编辑类附红绿 diff 预览)、行内 Markdown 渲染(标题加粗、列表对齐)、审批模态、两阶段计划模式(计划 / 自动模式下输入框带边框与模式徽标)、会话恢复。**in-process 直驱引擎**——不走 HTTP/端口,工具审批走 Ink 原生模态。
13
13
 
14
14
  > 另有 **VS Code 插件**版本(同名 `deepseeker-code`),与终端版同源共享 core 引擎和 `~/.deepseeker-code/` 数据目录,同一项目下会话可互续。
15
15
 
package/dist/cli.mjs CHANGED
@@ -34,17 +34,19 @@ var init_strings = __esm({
34
34
  toolRunning: (name) => `\u23FA ${name} \u8FD0\u884C\u4E2D\u2026`,
35
35
  toolDone: (name, ok) => `\u23FA ${name} \xB7 ${ok ? "\u6210\u529F" : "\u5931\u8D25"}`,
36
36
  toolDenied: (name) => `\u{1F6AB} ${name} \u5DF2\u88AB\u62D2\u7EDD`,
37
- planTitle: "\u2705 \u5B9E\u73B0\u65B9\u6848\uFF08\u8BA1\u5212\u6A21\u5F0F\uFF09",
38
- planPrompt: "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u786E\u8BA4\uFF08\u4FEE\u6539\u9879\u8FDB\u5165\u7F16\u8F91\uFF0CEnter \u63D0\u4EA4 / Esc \u53D6\u6D88\uFF09\u3002",
39
- planAcceptAuto: "\u63A5\u53D7\u5E76\u81EA\u52A8\u6267\u884C\uFF08\u5B9E\u73B0\u9636\u6BB5\u514D\u5BA1\u6279\uFF09",
40
- planAcceptManual: "\u63A5\u53D7\u5E76\u624B\u52A8\u6267\u884C\uFF08\u9010\u6B65\u5BA1\u6279\u6BCF\u4E2A\u5DE5\u5177\uFF09",
41
- planEdit: "\u4FEE\u6539\u65B9\u6848",
42
- planReject: "\u62D2\u7EDD\uFF0C\u56DE\u5230\u8F93\u5165\u6846",
37
+ planTitle: "\u51C6\u5907\u5F00\u59CB\u7F16\u7801\uFF1F",
38
+ planPrompt: "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u786E\u8BA4\uFF08\u7F16\u8F91\u9879\u8FDB\u5165\u7F16\u8F91\u5668\uFF0CEnter \u63D0\u4EA4 / Esc \u53D6\u6D88\uFF09\u3002",
39
+ planAcceptAuto: "\u662F\uFF0C\u5E76\u81EA\u52A8\u63A5\u53D7\u7F16\u8F91\uFF08\u5B9E\u73B0\u9636\u6BB5\u514D\u5BA1\u6279\uFF09",
40
+ planAcceptManual: "\u662F\uFF0C\u5E76\u624B\u52A8\u5BA1\u6279\u7F16\u8F91\uFF08\u9010\u6B65\u5BA1\u6279\u6BCF\u4E2A\u5DE5\u5177\uFF09",
41
+ planEdit: "\u7F16\u8F91\u65B9\u6848",
42
+ planReject: "\u5426\uFF0C\u7EE7\u7EED\u89C4\u5212",
43
43
  planEditTitle: "\u270F\uFE0F \u7F16\u8F91\u65B9\u6848",
44
44
  planEditHint: "Enter \u6309\u6B64\u65B9\u6848\u6267\u884C \xB7 Esc \u53D6\u6D88\u56DE\u5230\u9009\u9879",
45
- planRejected: "\u270B \u5DF2\u62D2\u7EDD\u65B9\u6848\uFF0C\u672C\u8F6E\u672A\u6267\u884C\u3002",
45
+ planKeepPlanning: "\u270B \u5DF2\u7559\u5728\u8BA1\u5212\u6A21\u5F0F\uFF1A\u7EE7\u7EED\u8F93\u5165\u8865\u5145\u8981\u6C42\uFF0C\u6A21\u578B\u5C06\u4FEE\u8BA2\u65B9\u6848\u540E\u518D\u6B21\u63D0\u4EA4\uFF08/plan \u53EF\u9000\u51FA\uFF09\u3002",
46
46
  planEditEmpty: "\u65B9\u6848\u4E0D\u80FD\u4E3A\u7A7A",
47
47
  planAutoExecute: "\u26A1 \u5DF2\u8FDB\u5165\u81EA\u52A8\u6267\u884C\uFF1A\u5B9E\u73B0\u9636\u6BB5\u5DE5\u5177\u5C06\u514D\u5BA1\u6279\u76F4\u63A5\u8FD0\u884C\u3002",
48
+ inputBadgePlan: "plan mode on\uFF08\u53EA\u8BFB\u8C03\u7814 \u2192 \u65B9\u6848\u5BA1\u6279 \u2192 \u5B9E\u73B0\uFF09",
49
+ inputBadgeAuto: "auto-accept edits on",
48
50
  approvalTitle: "\u{1F510} \u64CD\u4F5C\u5BA1\u6279",
49
51
  approvalPrompt: "\u2191\u2193 \u9009\u62E9\u540E Enter\uFF08Esc \u62D2\u7EDD\uFF09\uFF1A\u5141\u8BB8\u672C\u6B21 / \u603B\u662F\u5141\u8BB8\uFF08\u5199\u6301\u4E45\u89C4\u5219\uFF09/ \u62D2\u7EDD\u3002",
50
52
  approvalAllow: "\u5141\u8BB8\u672C\u6B21",
@@ -172,17 +174,19 @@ DeepSeeker-Code \u5C06\u5728\u6B64\u76EE\u5F55\u8BFB\u53D6\u3001\u7F16\u8F91\u54
172
174
  toolRunning: (name) => `\u23FA ${name} running\u2026`,
173
175
  toolDone: (name, ok) => `\u23FA ${name} \xB7 ${ok ? "ok" : "failed"}`,
174
176
  toolDenied: (name) => `\u{1F6AB} ${name} denied`,
175
- planTitle: "\u2705 Implementation plan (plan mode)",
177
+ planTitle: "Ready to code?",
176
178
  planPrompt: "\u2191\u2193 then Enter (edit opens the editor: Enter to save / Esc to cancel).",
177
- planAcceptAuto: "Accept & auto-run (skip impl approvals)",
178
- planAcceptManual: "Accept & step-by-step (approve each tool)",
179
+ planAcceptAuto: "Yes, and auto-accept edits (skip impl approvals)",
180
+ planAcceptManual: "Yes, and manually approve edits (step-by-step)",
179
181
  planEdit: "Edit plan",
180
- planReject: "Reject, back to prompt",
182
+ planReject: "No, keep planning",
181
183
  planEditTitle: "\u270F\uFE0F Edit plan",
182
184
  planEditHint: "Enter to implement with this plan \xB7 Esc back to options",
183
- planRejected: "\u270B Plan rejected, nothing executed this turn.",
185
+ planKeepPlanning: "\u270B Staying in plan mode: add feedback and the plan will be revised and resubmitted (/plan to exit).",
184
186
  planEditEmpty: "Plan cannot be empty",
185
187
  planAutoExecute: "\u26A1 Auto-run: implementation tools will execute without approval.",
188
+ inputBadgePlan: "plan mode on (read-only research \u2192 approve \u2192 implement)",
189
+ inputBadgeAuto: "auto-accept edits on",
186
190
  approvalTitle: "\u{1F510} Action approval",
187
191
  approvalPrompt: "\u2191\u2193 then Enter (Esc to deny): allow once / always allow (persist rule) / deny.",
188
192
  approvalAllow: "Allow once",
@@ -2397,9 +2401,14 @@ var init_guard = __esm({
2397
2401
  SENSITIVE_ENV_PATTERN = /(KEY|TOKEN|SECRET|PASSWORD|PASSPHRASE|CREDENTIAL|PRIVATE|AUTH)/i;
2398
2402
  scrubCommandEnv = (env = process.env) => {
2399
2403
  const next = {};
2404
+ const GIT_CONFIG_MEMBER = /^GIT_CONFIG_(KEY|VALUE)_\d+$/;
2405
+ const gitConfigFamilyHit = Object.keys(env).some(
2406
+ (k) => GIT_CONFIG_MEMBER.test(k) && (COMMAND_ENV_DENYLIST.includes(k) || SENSITIVE_ENV_PATTERN.test(k))
2407
+ );
2400
2408
  for (const [k, v] of Object.entries(env)) {
2401
2409
  if (COMMAND_ENV_DENYLIST.includes(k)) continue;
2402
2410
  if (SENSITIVE_ENV_PATTERN.test(k)) continue;
2411
+ if (gitConfigFamilyHit && (k === "GIT_CONFIG_COUNT" || GIT_CONFIG_MEMBER.test(k))) continue;
2403
2412
  next[k] = v;
2404
2413
  }
2405
2414
  return next;
@@ -3899,7 +3908,6 @@ var init_planMode = __esm({
3899
3908
  "../core/src/agent/planMode.ts"() {
3900
3909
  "use strict";
3901
3910
  PLAN_ALLOWED_TOOLS = /* @__PURE__ */ new Set([
3902
- "getTime",
3903
3911
  "read_file",
3904
3912
  "list_dir",
3905
3913
  "view_symbol_outline",
@@ -4293,36 +4301,6 @@ var init_systemInjections = __esm({
4293
4301
  }
4294
4302
  });
4295
4303
 
4296
- // ../core/src/tool/registry/system.ts
4297
- var systemTools;
4298
- var init_system = __esm({
4299
- "../core/src/tool/registry/system.ts"() {
4300
- "use strict";
4301
- init_type();
4302
- systemTools = [
4303
- {
4304
- type: "function",
4305
- function: {
4306
- name: "getTime",
4307
- description: "\u8FD4\u56DE\u5F53\u524D\u670D\u52A1\u5668\u7684\u65E5\u671F\u4E0E\u65F6\u95F4\uFF08\u672C\u5730\u65F6\u533A\uFF09",
4308
- parameters: {
4309
- type: "object",
4310
- properties: {
4311
- // Q-7:location 改为可选——旧版 required 却完全不消费,迫使模型填无意义城市名。
4312
- location: { type: "string", description: "\u57CE\u5E02\u540D\u79F0\uFF08\u53EF\u9009\uFF0C\u4EC5\u4F5C\u8BB0\u5F55\uFF1B\u670D\u52A1\u5668\u59CB\u7EC8\u8FD4\u56DE\u5176\u672C\u5730\u65F6\u95F4\uFF09" }
4313
- }
4314
- },
4315
- safetyLevel: "safe" /* SAFE */,
4316
- isSync: true,
4317
- async execute() {
4318
- return (/* @__PURE__ */ new Date()).toLocaleString("zh-CN", { dateStyle: "medium", timeStyle: "medium" });
4319
- }
4320
- }
4321
- }
4322
- ];
4323
- }
4324
- });
4325
-
4326
4304
  // ../core/src/tool/registry/agent.ts
4327
4305
  var createAgentTools;
4328
4306
  var init_agent = __esm({
@@ -4917,7 +4895,7 @@ import fs12 from "fs/promises";
4917
4895
  import path15 from "path";
4918
4896
  import { createReadStream } from "fs";
4919
4897
  import * as readline from "readline";
4920
- var isSensitiveReadTarget, stripReadFileLineNumbers, maskSecretsInContent, makeTmpPath, ATOMIC_TMP_RE, sweepStaleAtomicTmp, assertReadable, stripEdgeBlankLines, matchLineBlockWith, diagnoseOldStr, reindentToBase, fsTools;
4898
+ var isSensitiveReadTarget, stripReadFileLineNumbers, maskSecretsInContent, makeTmpPath, ATOMIC_TMP_RE, sweepStaleAtomicTmp, assertReadable, stripEdgeBlankLines, matchLineBlockWith, diagnoseOldStr, reindentToBase, alignIndentsByAnchor, applyOneEditToContent, fsTools;
4921
4899
  var init_fs = __esm({
4922
4900
  "../core/src/tool/registry/fs.ts"() {
4923
4901
  "use strict";
@@ -5005,7 +4983,7 @@ var init_fs = __esm({
5005
4983
  while (lines.length > 1 && lines[lines.length - 1].trim() === "") lines.pop();
5006
4984
  return lines.join("\n");
5007
4985
  };
5008
- matchLineBlockWith = (content, oldBlock, newBlock, replaceAll, norm) => {
4986
+ matchLineBlockWith = (content, oldBlock, newBlock, replaceAll, norm, anchorAlign) => {
5009
4987
  const contentLines = content.split("\n");
5010
4988
  const oldLines = oldBlock.split("\n");
5011
4989
  if (oldLines.length === 0 || oldLines.length > contentLines.length) {
@@ -5034,7 +5012,11 @@ var init_fs = __esm({
5034
5012
  break;
5035
5013
  }
5036
5014
  }
5037
- const aligned = baseIndent ? reindentToBase(newBlock, baseIndent) : newBlock;
5015
+ let aligned = baseIndent ? reindentToBase(newBlock, baseIndent) : newBlock;
5016
+ if (anchorAlign) {
5017
+ const anchored = alignIndentsByAnchor(newBlock, oldLines, contentLines, start);
5018
+ if (anchored !== null) aligned = anchored;
5019
+ }
5038
5020
  out.splice(start, oldLines.length, ...aligned.split("\n"));
5039
5021
  }
5040
5022
  return { ok: true, content: out.join("\n"), count: hits.length };
@@ -5069,6 +5051,92 @@ var init_fs = __esm({
5069
5051
  return baseIndent + (l.startsWith(common) ? l.slice(common.length) : l);
5070
5052
  }).join("\n");
5071
5053
  };
5054
+ alignIndentsByAnchor = (newBlock, oldLines, contentLines, start) => {
5055
+ const stripLead = (l) => l.replace(/^[ \t]+/, "");
5056
+ const out = [];
5057
+ let cursor = 0;
5058
+ let lastIndent = null;
5059
+ let anchors = 0;
5060
+ for (const line of newBlock.split("\n")) {
5061
+ if (line.trim() === "") {
5062
+ out.push(line);
5063
+ continue;
5064
+ }
5065
+ const bare = stripLead(line);
5066
+ let idx = -1;
5067
+ for (let i = cursor; i < oldLines.length; i++) {
5068
+ if (oldLines[i].trim() !== "" && stripLead(oldLines[i]) === bare) {
5069
+ idx = i;
5070
+ break;
5071
+ }
5072
+ }
5073
+ if (idx === -1) {
5074
+ out.push(lastIndent === null ? line : lastIndent + bare);
5075
+ continue;
5076
+ }
5077
+ cursor = idx + 1;
5078
+ lastIndent = contentLines[start + idx].match(/^[ \t]*/)?.[0] ?? "";
5079
+ anchors++;
5080
+ out.push(lastIndent + bare);
5081
+ }
5082
+ return anchors > 0 ? out.join("\n") : null;
5083
+ };
5084
+ applyOneEditToContent = (normalizedContent, oldStr, newStr, replaceAll) => {
5085
+ const normalizedNew = newStr.replace(/\r\n/g, "\n");
5086
+ const normalizedOldRaw = oldStr.replace(/\r\n/g, "\n");
5087
+ const lnStripped = stripReadFileLineNumbers(normalizedOldRaw);
5088
+ const candidates = [
5089
+ { old: normalizedOldRaw, note: "" },
5090
+ { old: stripEdgeBlankLines(normalizedOldRaw), note: "\uFF08\u5DF2\u5BB9\u9519\u9996\u5C3E\u7A7A\u884C\uFF09" }
5091
+ ];
5092
+ if (lnStripped !== normalizedOldRaw) candidates.push({ old: lnStripped, note: "\uFF08\u5DF2\u5265\u79BB read_file \u884C\u53F7\u524D\u7F00\uFF09" });
5093
+ let normalizedOld = null;
5094
+ let note = "";
5095
+ for (const c of candidates) {
5096
+ if (c.old.length > 0 && normalizedContent.includes(c.old)) {
5097
+ normalizedOld = c.old;
5098
+ note = c.note;
5099
+ break;
5100
+ }
5101
+ }
5102
+ if (normalizedOld == null) {
5103
+ const base = lnStripped !== normalizedOldRaw ? lnStripped : normalizedOldRaw;
5104
+ const norms = [
5105
+ // 行尾空白归一:old_str 前导缩进与文件一致(可信)→ 只对齐基线(anchor=false)
5106
+ { norm: (l) => l.replace(/[ \t]+$/, ""), tag: "\u9010\u884C\u5C3E\u7A7A\u767D\u5BB9\u9519", anchor: false },
5107
+ // 全空白归一:模型前导缩进已证明不符(不可信)→ 逐行锚定文件真实缩进(anchor=true)
5108
+ { norm: (l) => l.trim(), tag: "\u9010\u884C\u5168\u7A7A\u767D\u5BB9\u9519\uFF08\u524D\u5BFC Tab/\u7A7A\u683C\uFF09", anchor: true }
5109
+ ];
5110
+ for (const { norm, tag, anchor } of norms) {
5111
+ const lm = matchLineBlockWith(normalizedContent, base, normalizedNew, replaceAll, norm, anchor);
5112
+ if (lm.ok) {
5113
+ return {
5114
+ ok: true,
5115
+ content: lm.content,
5116
+ summary: replaceAll ? `\u5DF2\u6279\u91CF\u66FF\u6362\u5168\u90E8 ${lm.count} \u5904\u5339\u914D\uFF08${tag}\uFF09\u3002` : `\u5DF2\u6210\u529F\u5B8C\u6210\u5C40\u90E8\u91CD\u6784\uFF08${tag}\uFF09\u3002`
5117
+ };
5118
+ }
5119
+ if (lm.reason === "conflict") {
5120
+ return { ok: false, error: `\u274C [\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1A\u4EE3\u7801\u51B2\u7A81\uFF01old_str\uFF08${tag}\u5F52\u4E00\u540E\uFF09\u5728\u5168\u6587\u4E2D\u4E0D\u552F\u4E00\uFF08\u5171 ${lm.count} \u5904\uFF09\u3002\u8BF7\u591A\u5305\u88F9\u51E0\u884C\u4E0A\u4E0B\u6587\uFF0C\u6216\u663E\u5F0F\u8BBE replace_all=true \u6279\u91CF\u66FF\u6362\u3002` };
5121
+ }
5122
+ }
5123
+ const diag = diagnoseOldStr(normalizedContent, normalizedOldRaw);
5124
+ return { ok: false, error: `\u274C [\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1A\u672A\u80FD\u5728\u6587\u4EF6\u4E2D\u627E\u5230\u6307\u5B9A\u7684 old_str \u65E7\u4EE3\u7801\u5757\u3002${diag}\u5E38\u89C1\u539F\u56E0\uFF1A\u2460 \u8BEF\u5E26\u4E86 read_file \u7684\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\uFF1B\u2461 \u7F29\u8FDB\uFF08Tab/\u7A7A\u683C\uFF09\u4E0D\u4E00\u81F4\uFF1B\u2462 \u884C\u5C3E\u591A\u4F59\u7A7A\u683C\uFF1B\u2463 \u6587\u4EF6\u5DF2\u88AB\u6539\u52A8/old_str \u975E\u8FDE\u7EED\u6574\u6BB5\u3002\u8BF7\u7528 read_file \u91CD\u65B0\u6838\u5BF9\u8BE5\u5904\u7247\u6BB5\uFF08\u53BB\u6389\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\u3001\u4FDD\u7559\u539F\u59CB Tab/\u7A7A\u683C\u7F29\u8FDB\uFF09\u540E\u91CD\u8BD5\u3002\u26A0\uFE0F \u4E25\u7981\u6539\u7528 run_command \u8C03\u7528 python/node/sed/awk \u7B49\u811A\u672C\u7ED5\u8FC7\u672C\u5DE5\u5177\u4FEE\u6539\u6587\u4EF6\u3002` };
5125
+ }
5126
+ const matchCount = normalizedContent.split(normalizedOld).length - 1;
5127
+ if (!replaceAll && matchCount > 1) {
5128
+ return { ok: false, error: `\u274C [\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1A\u4EE3\u7801\u51B2\u7A81\uFF01old_str \u5728\u5168\u6587\u4E2D\u4E0D\u552F\u4E00\uFF08\u5171\u53D1\u73B0\u4E86 ${matchCount} \u5904\uFF09\u3002\u8BF7\u5411\u4E0A\u6216\u5411\u4E0B\u591A\u5305\u88F9\u51E0\u884C\u4E0A\u4E0B\u6587\u518D\u63D0\u8BF7\u4FEE\u6539\uFF0C\u6216\u663E\u5F0F\u8BBE replace_all=true \u6279\u91CF\u66FF\u6362\u3002` };
5129
+ }
5130
+ const oldFirstNonBlank = normalizedOld.split("\n").find((l) => l.trim() !== "") ?? "";
5131
+ const baseIndent = oldFirstNonBlank.match(/^[ \t]*/)?.[0] ?? "";
5132
+ const alignedNew = baseIndent ? reindentToBase(normalizedNew, baseIndent) : normalizedNew;
5133
+ const updatedContent = replaceAll ? normalizedContent.split(normalizedOld).join(alignedNew) : normalizedContent.replace(normalizedOld, () => alignedNew);
5134
+ return {
5135
+ ok: true,
5136
+ content: updatedContent,
5137
+ summary: replaceAll ? `\u5DF2\u6279\u91CF\u66FF\u6362\u5168\u90E8 ${matchCount} \u5904\u5339\u914D\u3002${note}` : `\u5DF2\u6210\u529F\u5B8C\u6210\u552F\u4E00\u6027\u5C40\u90E8\u91CD\u6784\u3002${note}`
5138
+ };
5139
+ };
5072
5140
  fsTools = [
5073
5141
  {
5074
5142
  type: "function",
@@ -5200,78 +5268,65 @@ ${treeResult}`;
5200
5268
  type: "function",
5201
5269
  function: {
5202
5270
  name: "edit_file",
5203
- description: "\u9488\u5BF9\u6307\u5B9A\u7684\u6587\u4EF6\u8FDB\u884C\u5C40\u90E8\u7CBE\u51C6\u4FEE\u6539\u3002old_str \u5FC5\u987B\u4E0E\u6587\u4EF6\u4E2D\u7684\u539F\u59CB\u4EE3\u7801\u9010\u5B57\u7B26\u4E00\u81F4\uFF1A\u8BF7\u53BB\u6389 read_file \u8FD4\u56DE\u7684\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\uFF0C\u5E76\u4FDD\u7559\u539F\u6709\u7F29\u8FDB\uFF08Tab/\u7A7A\u683C\uFF09\u4E0E\u884C\u5C3E\u7A7A\u767D\uFF1B\u9ED8\u8BA4\u8981\u6C42\u5728\u5168\u6587\u4E2D\u552F\u4E00\uFF0C\u82E5\u8BBE replace_all=true \u5219\u66FF\u6362\u5168\u90E8\u5339\u914D\u5904\uFF08\u9002\u5408\u6279\u91CF\u91CD\u547D\u540D/\u7EDF\u4E00\u6539\u5199\uFF09\u3002",
5271
+ description: "\u9488\u5BF9\u6307\u5B9A\u7684\u6587\u4EF6\u8FDB\u884C\u5C40\u90E8\u7CBE\u51C6\u4FEE\u6539\u3002\u2605 \u540C\u4E00\u6587\u4EF6\u6709\u591A\u5904\u8981\u6539\u65F6\uFF0C\u52A1\u5FC5\u4E00\u6B21\u8C03\u7528\u4F20 edits \u6570\u7EC4\u5168\u90E8\u5B8C\u6210\uFF08\u6309\u5E8F\u5E94\u7528\u3001\u6574\u4F53\u539F\u5B50\uFF1A\u4EFB\u4E00\u5904\u5931\u8D25\u5219\u5168\u90E8\u4E0D\u5199\u5165\uFF09\uFF0C\u52FF\u9010\u5904\u591A\u6B21\u8C03\u7528\u3002old_str \u5FC5\u987B\u4E0E\u6587\u4EF6\u4E2D\u7684\u539F\u59CB\u4EE3\u7801\u9010\u5B57\u7B26\u4E00\u81F4\uFF1A\u8BF7\u53BB\u6389 read_file \u8FD4\u56DE\u7684\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\uFF0C\u5E76\u4FDD\u7559\u539F\u6709\u7F29\u8FDB\uFF08Tab/\u7A7A\u683C\uFF09\u4E0E\u884C\u5C3E\u7A7A\u767D\uFF1B\u9ED8\u8BA4\u8981\u6C42\u5728\u5168\u6587\u4E2D\u552F\u4E00\uFF0C\u82E5\u8BBE replace_all=true \u5219\u66FF\u6362\u5168\u90E8\u5339\u914D\u5904\uFF08\u9002\u5408\u6279\u91CF\u91CD\u547D\u540D/\u7EDF\u4E00\u6539\u5199\uFF09\u3002",
5204
5272
  parameters: {
5205
5273
  type: "object",
5206
5274
  properties: {
5207
5275
  path: { type: "string", description: "\u51C6\u5907\u4FEE\u6539\u7684\u6587\u4EF6\u76F8\u5BF9\u8DEF\u5F84" },
5208
- old_str: { type: "string", description: "\u6587\u4EF6\u4E2D\u73B0\u6709\u7684\u5B8C\u6574\u65E7\u4EE3\u7801\u5757" },
5209
- new_str: { type: "string", description: "\u51C6\u5907\u66FF\u6362\u8FDB\u53BB\u7684\u65B0\u4EE3\u7801\u5757" },
5210
- replace_all: { type: "boolean", description: "\u662F\u5426\u66FF\u6362\u5168\u6587\u6240\u6709\u5339\u914D\u5904\uFF08\u9ED8\u8BA4 false \u4EC5\u66FF\u6362\u552F\u4E00\u5339\u914D\uFF1B\u6279\u91CF\u91CD\u547D\u540D/\u7EDF\u4E00\u6539\u5199\u65F6\u8BBE true\uFF09" }
5276
+ old_str: { type: "string", description: "\u6587\u4EF6\u4E2D\u73B0\u6709\u7684\u5B8C\u6574\u65E7\u4EE3\u7801\u5757\uFF08\u5355\u5904\u4FEE\u6539\u7528\uFF1B\u591A\u5904\u4FEE\u6539\u8BF7\u6539\u7528 edits \u6570\u7EC4\u4E00\u6B21\u5B8C\u6210\uFF09" },
5277
+ new_str: { type: "string", description: "\u51C6\u5907\u66FF\u6362\u8FDB\u53BB\u7684\u65B0\u4EE3\u7801\u5757\uFF08\u5355\u5904\u4FEE\u6539\u7528\uFF09" },
5278
+ replace_all: { type: "boolean", description: "\u662F\u5426\u66FF\u6362\u5168\u6587\u6240\u6709\u5339\u914D\u5904\uFF08\u9ED8\u8BA4 false \u4EC5\u66FF\u6362\u552F\u4E00\u5339\u914D\uFF1B\u6279\u91CF\u91CD\u547D\u540D/\u7EDF\u4E00\u6539\u5199\u65F6\u8BBE true\uFF09\u3002\u9876\u5C42\u53C2\u6570\u4EC5\u4F5C\u7528\u4E8E\u5355\u6761 old_str/new_str\uFF1Bedits \u5185\u6BCF\u6761\u53EF\u72EC\u7ACB\u8BBE\u7F6E" },
5279
+ edits: {
5280
+ type: "array",
5281
+ description: "\u2605 \u540C\u4E00\u6587\u4EF6\u591A\u5904\u4FEE\u6539\u65F6\u4F18\u5148\u4F7F\u7528\uFF1A\u4E00\u6B21\u8C03\u7528\u6309\u5E8F\u5B8C\u6210\u5168\u90E8\u66FF\u6362\uFF0C\u7701\u53BB\u9010\u5904\u5F80\u8FD4\u3002\u7B2C N \u6761\u7684 old_str \u987B\u57FA\u4E8E\u524D N-1 \u6761\u5E94\u7528\u540E\u7684\u6587\u4EF6\u5185\u5BB9\u6784\u9020\uFF1B\u4EFB\u4E00\u6761\u672A\u547D\u4E2D\u5219\u6574\u4F53\u4E0D\u5199\u5165\uFF08\u539F\u5B50\uFF09\uFF0C\u4FEE\u6B63\u8BE5\u6761\u540E\u6574\u7EC4\u91CD\u8BD5",
5282
+ items: {
5283
+ type: "object",
5284
+ properties: {
5285
+ old_str: { type: "string", description: "\u6587\u4EF6\u4E2D\u73B0\u6709\u7684\u5B8C\u6574\u65E7\u4EE3\u7801\u5757" },
5286
+ new_str: { type: "string", description: "\u51C6\u5907\u66FF\u6362\u8FDB\u53BB\u7684\u65B0\u4EE3\u7801\u5757" },
5287
+ replace_all: { type: "boolean", description: "\u8BE5\u6761\u662F\u5426\u66FF\u6362\u5168\u6587\u6240\u6709\u5339\u914D\u5904\uFF08\u9ED8\u8BA4 false\uFF09" }
5288
+ },
5289
+ required: ["old_str", "new_str"]
5290
+ }
5291
+ }
5211
5292
  },
5212
- required: ["path", "old_str", "new_str"]
5293
+ required: ["path"]
5213
5294
  },
5214
5295
  safetyLevel: "mutation" /* MUTATION */,
5215
5296
  isSync: true,
5216
- requireApproval: (args) => `\u7533\u8BF7\u4FEE\u6539\u6587\u4EF6 [${args.path}]${args.replace_all ? "\uFF08\u{1F525} \u6279\u91CF\u66FF\u6362\u5168\u90E8\u5339\u914D\u5904\uFF09" : ""}
5297
+ requireApproval: (args) => {
5298
+ const list = args.edits && args.edits.length > 0 ? args.edits : [{ old_str: args.old_str ?? "", new_str: args.new_str ?? "", replace_all: args.replace_all }];
5299
+ const patches = list.map((e, i) => `\u2014\u2014 \u7B2C ${i + 1} \u5904${e.replace_all ? "\uFF08\u{1F525} \u6279\u91CF\u66FF\u6362\u5168\u90E8\u5339\u914D\u5904\uFF09" : ""} \u2014\u2014
5217
5300
  \u3010\u51CF\u5C11\u3011:
5218
- ${args.old_str}
5301
+ ${e.old_str}
5219
5302
  \u3010\u589E\u52A0\u3011:
5220
- ${args.new_str}`,
5303
+ ${e.new_str}`).join("\n\n");
5304
+ return `\u7533\u8BF7\u4FEE\u6539\u6587\u4EF6 [${args.path}]\uFF08\u5171 ${list.length} \u5904\u4FEE\u6539\uFF0C\u4EFB\u4E00\u5904\u5931\u8D25\u5C06\u6574\u4F53\u4E0D\u5199\u5165\uFF09
5305
+ ${patches}`;
5306
+ },
5221
5307
  async execute(args) {
5222
5308
  try {
5309
+ const editList = args.edits && args.edits.length > 0 ? args.edits : [{ old_str: args.old_str ?? "", new_str: args.new_str ?? "", replace_all: args.replace_all }];
5310
+ if (editList.length === 0 || editList.some((e) => typeof e.old_str !== "string" || e.old_str.length === 0)) {
5311
+ 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`;
5312
+ }
5223
5313
  const absPath = resolveSafePath(args.path);
5224
5314
  const rawContent = await fs12.readFile(absPath, "utf-8");
5225
5315
  const isCRLF = rawContent.includes("\r\n");
5226
- const normalizedContent = rawContent.replace(/\r\n/g, "\n");
5227
- const normalizedNew = args.new_str.replace(/\r\n/g, "\n");
5228
- const normalizedOldRaw = args.old_str.replace(/\r\n/g, "\n");
5229
- const lnStripped = stripReadFileLineNumbers(normalizedOldRaw);
5230
- const candidates = [
5231
- { old: normalizedOldRaw, note: "" },
5232
- { old: stripEdgeBlankLines(normalizedOldRaw), note: "\uFF08\u5DF2\u5BB9\u9519\u9996\u5C3E\u7A7A\u884C\uFF09" }
5233
- ];
5234
- if (lnStripped !== normalizedOldRaw) candidates.push({ old: lnStripped, note: "\uFF08\u5DF2\u5265\u79BB read_file \u884C\u53F7\u524D\u7F00\uFF09" });
5235
- let normalizedOld = null;
5236
- let note = "";
5237
- for (const c of candidates) {
5238
- if (c.old.length > 0 && normalizedContent.includes(c.old)) {
5239
- normalizedOld = c.old;
5240
- note = c.note;
5241
- break;
5242
- }
5243
- }
5244
- if (normalizedOld == null) {
5245
- const base = lnStripped !== normalizedOldRaw ? lnStripped : normalizedOldRaw;
5246
- const norms = [
5247
- { norm: (l) => l.replace(/[ \t]+$/, ""), tag: "\u9010\u884C\u5C3E\u7A7A\u767D\u5BB9\u9519" },
5248
- { norm: (l) => l.trim(), tag: "\u9010\u884C\u5168\u7A7A\u767D\u5BB9\u9519\uFF08\u524D\u5BFC Tab/\u7A7A\u683C\uFF09" }
5249
- ];
5250
- for (const { norm, tag } of norms) {
5251
- const lm = matchLineBlockWith(normalizedContent, base, normalizedNew, !!args.replace_all, norm);
5252
- if (lm.ok) {
5253
- assertWithinWorkspace(absPath);
5254
- await fs12.writeFile(absPath, isCRLF ? lm.content.replace(/\n/g, "\r\n") : lm.content, "utf-8");
5255
- return args.replace_all ? `\u2705 [\u4EE3\u7801\u4FEE\u8865\u6210\u529F]\uFF1A\u6587\u4EF6 [${args.path}] \u5DF2\u6279\u91CF\u66FF\u6362\u5168\u90E8 ${lm.count} \u5904\u5339\u914D\uFF08${tag}\uFF09\u3002` : `\u2705 [\u4EE3\u7801\u4FEE\u8865\u6210\u529F]\uFF1A\u6587\u4EF6 [${args.path}] \u5DF2\u6210\u529F\u5B8C\u6210\u5C40\u90E8\u91CD\u6784\uFF08${tag}\uFF09\u3002`;
5256
- }
5257
- if (lm.reason === "conflict") {
5258
- return `\u274C [\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1A\u4EE3\u7801\u51B2\u7A81\uFF01old_str\uFF08${tag}\u5F52\u4E00\u540E\uFF09\u5728\u5168\u6587\u4E2D\u4E0D\u552F\u4E00\uFF08\u5171 ${lm.count} \u5904\uFF09\u3002\u8BF7\u591A\u5305\u88F9\u51E0\u884C\u4E0A\u4E0B\u6587\uFF0C\u6216\u663E\u5F0F\u8BBE replace_all=true \u6279\u91CF\u66FF\u6362\u3002`;
5259
- }
5316
+ let content = rawContent.replace(/\r\n/g, "\n");
5317
+ const summaries = [];
5318
+ for (let i = 0; i < editList.length; i++) {
5319
+ const r = applyOneEditToContent(content, editList[i].old_str, editList[i].new_str ?? "", !!editList[i].replace_all);
5320
+ if (!r.ok) {
5321
+ return editList.length === 1 ? r.error : `\u274C [\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1Aedits \u7B2C ${i + 1}/${editList.length} \u6761\u672A\u547D\u4E2D\uFF0C\u5DF2\u6574\u4F53\u653E\u5F03\uFF08\u6587\u4EF6\u672A\u505A\u4EFB\u4F55\u6539\u52A8\uFF0C\u53EF\u4FEE\u6B63\u8BE5\u6761\u540E\u6574\u7EC4\u91CD\u8BD5\uFF09\u3002${r.error.replace(/^❌ \[代码修补失败\]:/, "")}`;
5260
5322
  }
5261
- const diag = diagnoseOldStr(normalizedContent, normalizedOldRaw);
5262
- return `\u274C [\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1A\u672A\u80FD\u5728\u6587\u4EF6\u4E2D\u627E\u5230\u6307\u5B9A\u7684 old_str \u65E7\u4EE3\u7801\u5757\u3002${diag}\u5E38\u89C1\u539F\u56E0\uFF1A\u2460 \u8BEF\u5E26\u4E86 read_file \u7684\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\uFF1B\u2461 \u7F29\u8FDB\uFF08Tab/\u7A7A\u683C\uFF09\u4E0D\u4E00\u81F4\uFF1B\u2462 \u884C\u5C3E\u591A\u4F59\u7A7A\u683C\uFF1B\u2463 \u6587\u4EF6\u5DF2\u88AB\u6539\u52A8/old_str \u975E\u8FDE\u7EED\u6574\u6BB5\u3002\u8BF7\u7528 read_file \u91CD\u65B0\u6838\u5BF9\u5E94\u8D34\u7247\u6BB5\u3002\u26A0\uFE0F \u4E25\u7981\u6539\u7528 run_command \u8C03\u7528 python/node/sed/awk \u7B49\u811A\u672C\u7ED5\u8FC7\u672C\u5DE5\u5177\u4FEE\u6539\u6587\u4EF6\u2014\u2014\u8BF7\u7528 read_file \u91CD\u65B0\u8BFB\u53D6\u76EE\u6807\u7247\u6BB5\uFF08\u53BB\u6389\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\u3001\u4FDD\u7559\u539F\u59CB Tab/\u7A7A\u683C\u7F29\u8FDB\uFF09\uFF0C\u518D\u6B21\u8C03\u7528 edit_file \u91CD\u8BD5\u3002`;
5323
+ content = r.content;
5324
+ summaries.push(editList.length === 1 ? r.summary : ` ${i + 1}. ${r.summary}`);
5263
5325
  }
5264
- const matchCount = normalizedContent.split(normalizedOld).length - 1;
5265
- if (!args.replace_all && matchCount > 1) {
5266
- return `\u274C [\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1A\u4EE3\u7801\u51B2\u7A81\uFF01old_str \u5728\u5168\u6587\u4E2D\u4E0D\u552F\u4E00\uFF08\u5171\u53D1\u73B0\u4E86 ${matchCount} \u5904\uFF09\u3002\u8BF7\u5411\u4E0A\u6216\u5411\u4E0B\u591A\u5305\u88F9\u51E0\u884C\u4E0A\u4E0B\u6587\u518D\u63D0\u8BF7\u4FEE\u6539\uFF0C\u6216\u663E\u5F0F\u8BBE replace_all=true \u6279\u91CF\u66FF\u6362\u3002`;
5267
- }
5268
- const oldFirstNonBlank = normalizedOld.split("\n").find((l) => l.trim() !== "") ?? "";
5269
- const baseIndent = oldFirstNonBlank.match(/^[ \t]*/)?.[0] ?? "";
5270
- const alignedNew = baseIndent ? reindentToBase(normalizedNew, baseIndent) : normalizedNew;
5271
- const updatedContent = args.replace_all ? normalizedContent.split(normalizedOld).join(alignedNew) : normalizedContent.replace(normalizedOld, () => alignedNew);
5272
5326
  assertWithinWorkspace(absPath);
5273
- await fs12.writeFile(absPath, isCRLF ? updatedContent.replace(/\n/g, "\r\n") : updatedContent, "utf-8");
5274
- return args.replace_all ? `\u2705 [\u4EE3\u7801\u4FEE\u8865\u6210\u529F]\uFF1A\u6587\u4EF6 [${args.path}] \u5DF2\u6279\u91CF\u66FF\u6362\u5168\u90E8 ${matchCount} \u5904\u5339\u914D\u3002${note}` : `\u2705 [\u4EE3\u7801\u4FEE\u8865\u6210\u529F]\uFF1A\u6587\u4EF6 [${args.path}] \u5DF2\u6210\u529F\u5B8C\u6210\u552F\u4E00\u6027\u5C40\u90E8\u91CD\u6784\u3002${note}`;
5327
+ await fs12.writeFile(absPath, isCRLF ? content.replace(/\n/g, "\r\n") : content, "utf-8");
5328
+ 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
5329
+ ${summaries.join("\n")}`;
5275
5330
  } catch (error) {
5276
5331
  return `\u64CD\u4F5C\u5931\u8D25: ${error.message}`;
5277
5332
  }
@@ -5579,13 +5634,14 @@ var init_search = __esm({
5579
5634
  type: "function",
5580
5635
  function: {
5581
5636
  name: "search_grep",
5582
- description: "\u5728\u5DE5\u4F5C\u533A\u7684\u6240\u6709\u6587\u4EF6\u4E2D\u68C0\u7D22\u5339\u914D\u7684\u4EE3\u7801\u884C\uFF0C\u6BCF\u4E2A\u547D\u4E2D\u5E26\u524D\u540E\u5404 2 \u884C\u4E0A\u4E0B\u6587\uFF08\u53EF\u76F4\u63A5\u5224\u65AD\u7528\u6CD5\u3001\u514D\u7D27\u8DDF\u4E00\u6B21 read_file\uFF09\uFF1B\u9ED8\u8BA4\u6309\u5B57\u9762\u91CF\u5173\u952E\u8BCD\u5339\u914D\uFF0C\u5982\u9700\u6B63\u5219\u4F20 is_regex=true\u3002\u591A\u6839\u5DE5\u4F5C\u533A\u4E0B\u7528 path \u9650\u5B9A\u641C\u7D22\u76EE\u5F55\uFF1A\u53EF\u4F20\u9879\u76EE\u76EE\u5F55\u540D\uFF08\u5982 'frontend'\uFF09\u81EA\u52A8\u5339\u914D\u5DE5\u4F5C\u533A\u6839\uFF0C\u6216\u4F20\u7EDD\u5BF9\u8DEF\u5F84 / \u76F8\u5BF9\u9ED8\u8BA4\u6839\u7684 ../\u5144\u5F1F\u76EE\u5F55\u3002\u2605 \u5F53\u7528\u6237\u5728\u5BF9\u8BDD\u91CC\u6307\u660E\u4E86\u67D0\u4E2A\u9879\u76EE\u65F6\uFF0C\u52A1\u5FC5\u628A\u8BE5\u9879\u76EE\u4F5C\u4E3A path \u4F20\u5165\u2014\u2014\u5426\u5219\u53EA\u4F1A\u641C\u7D22 IDE \u5934\u90E8\u6240\u793A\u7684\u6D3B\u52A8\u6839\uFF0C\u5E38\u4E0E\u7528\u6237\u610F\u56FE\u4E0D\u7B26\u3002",
5637
+ description: "\u5728\u5DE5\u4F5C\u533A\u7684\u6240\u6709\u6587\u4EF6\u4E2D\u68C0\u7D22\u5339\u914D\u7684\u4EE3\u7801\u884C\uFF0C\u6BCF\u4E2A\u547D\u4E2D\u9ED8\u8BA4\u5E26\u524D\u540E\u5404 2 \u884C\u4E0A\u4E0B\u6587\uFF08\u53EF\u76F4\u63A5\u5224\u65AD\u7528\u6CD5\u3001\u514D\u7D27\u8DDF\u4E00\u6B21 read_file\uFF1B\u6784\u9020 edit_file \u7684 old_str \u524D\u53EF\u7528 context \u53C2\u6570\u8C03\u5927\u4E00\u6B21\u62FF\u8DB3\uFF09\uFF1B\u9ED8\u8BA4\u6309\u5B57\u9762\u91CF\u5173\u952E\u8BCD\u5339\u914D\uFF0C\u5982\u9700\u6B63\u5219\u4F20 is_regex=true\u3002\u2605 \u68C0\u7D22\u591A\u4E2A\u5173\u952E\u8BCD\u65F6\uFF0C\u7528 is_regex=true \u4EE5 | \u5408\u5E76\uFF08\u5982 'uploadVisible|uploadTip'\uFF09\u4E00\u6B21\u67E5\u5B8C\uFF0C\u52FF\u9010\u4E2A\u5173\u952E\u8BCD\u591A\u6B21\u8C03\u7528\u3002path \u53EF\u9650\u5B9A\u5230\u76EE\u5F55\u6216\u5177\u4F53\u6587\u4EF6\uFF08\u5728\u5355\u4E2A\u5927\u6587\u4EF6\u5185\u591A\u5904\u5B9A\u4F4D\u65F6\u4F20\u6587\u4EF6\u8DEF\u5F84\u6700\u9AD8\u6548\uFF09\u3002\u591A\u6839\u5DE5\u4F5C\u533A\u4E0B\uFF1A\u53EF\u4F20\u9879\u76EE\u76EE\u5F55\u540D\uFF08\u5982 'frontend'\uFF09\u81EA\u52A8\u5339\u914D\u5DE5\u4F5C\u533A\u6839\uFF0C\u6216\u4F20\u7EDD\u5BF9\u8DEF\u5F84 / \u76F8\u5BF9\u9ED8\u8BA4\u6839\u7684 ../\u5144\u5F1F\u76EE\u5F55\u3002\u2605 \u5F53\u7528\u6237\u5728\u5BF9\u8BDD\u91CC\u6307\u660E\u4E86\u67D0\u4E2A\u9879\u76EE\u65F6\uFF0C\u52A1\u5FC5\u628A\u8BE5\u9879\u76EE\u4F5C\u4E3A path \u4F20\u5165\u2014\u2014\u5426\u5219\u53EA\u4F1A\u641C\u7D22 IDE \u5934\u90E8\u6240\u793A\u7684\u6D3B\u52A8\u6839\uFF0C\u5E38\u4E0E\u7528\u6237\u610F\u56FE\u4E0D\u7B26\u3002",
5583
5638
  parameters: {
5584
5639
  type: "object",
5585
5640
  properties: {
5586
- query: { type: "string", description: "\u68C0\u7D22\u5185\u5BB9\u3002\u9ED8\u8BA4\u4E3A\u5B57\u9762\u91CF\u5173\u952E\u8BCD\uFF08\u5982 'function runAgent'\uFF09\uFF1Bis_regex=true \u65F6\u6309\u6B63\u5219\u89E3\u6790\uFF08\u5982 'function\\s+runAgent'\uFF09\u3002" },
5641
+ query: { type: "string", description: "\u68C0\u7D22\u5185\u5BB9\u3002\u9ED8\u8BA4\u4E3A\u5B57\u9762\u91CF\u5173\u952E\u8BCD\uFF08\u5982 'function runAgent'\uFF09\uFF1Bis_regex=true \u65F6\u6309\u6B63\u5219\u89E3\u6790\uFF08\u5982 'function\\s+runAgent'\uFF0C\u591A\u5173\u952E\u8BCD\u7528 | \u5408\u5E76\uFF09" },
5587
5642
  is_regex: { type: "boolean", description: "\u662F\u5426\u5C06 query \u4F5C\u4E3A\u6B63\u5219\u8868\u8FBE\u5F0F\u89E3\u6790\uFF0C\u9ED8\u8BA4 false\uFF08\u5B57\u9762\u91CF\u5339\u914D\uFF0C\u81EA\u52A8\u8F6C\u4E49\u7279\u6B8A\u5B57\u7B26\uFF09" },
5588
- path: { type: "string", description: "\u9650\u5B9A\u641C\u7D22\u7684\u76EE\u5F55\uFF08\u53EF\u9009\uFF09\u3002\u9ED8\u8BA4\u641C\u7D22 IDE \u5934\u90E8\u6240\u793A\u6D3B\u52A8\u6839\u3002\u591A\u6839\u573A\u666F\u4E0B\uFF1A\u4F20\u9879\u76EE\u76EE\u5F55\u540D\uFF08\u5982 'frontend'\uFF09\u81EA\u52A8\u5339\u914D\u5DE5\u4F5C\u533A\u6839\uFF1B\u6216\u4F20\u7EDD\u5BF9\u8DEF\u5F84 / \u76F8\u5BF9\u9ED8\u8BA4\u6839\u7684 ../<\u5144\u5F1F\u76EE\u5F55>\uFF1B\u5747\u7ECF\u6C99\u7BB1\u6821\u9A8C\u3002\u7528\u6237\u63D0\u5230\u5177\u4F53\u9879\u76EE\u65F6\u5FC5\u586B\u3002" }
5643
+ path: { type: "string", description: "\u9650\u5B9A\u641C\u7D22\u7684\u76EE\u5F55\u6216\u5177\u4F53\u6587\u4EF6\uFF08\u53EF\u9009\uFF09\u3002\u4F20\u5177\u4F53\u6587\u4EF6\u8DEF\u5F84\u65F6\u76F8\u5F53\u4E8E\u8BE5\u6587\u4EF6\u5185\u5168\u6587\u68C0\u7D22\uFF08\u5927\u6587\u4EF6\u591A\u5904\u5B9A\u4F4D\u9996\u9009\uFF09\u3002\u9ED8\u8BA4\u641C\u7D22 IDE \u5934\u90E8\u6240\u793A\u6D3B\u52A8\u6839\u3002\u591A\u6839\u573A\u666F\u4E0B\uFF1A\u4F20\u9879\u76EE\u76EE\u5F55\u540D\uFF08\u5982 'frontend'\uFF09\u81EA\u52A8\u5339\u914D\u5DE5\u4F5C\u533A\u6839\uFF1B\u6216\u4F20\u7EDD\u5BF9\u8DEF\u5F84 / \u76F8\u5BF9\u9ED8\u8BA4\u6839\u7684 ../<\u5144\u5F1F\u76EE\u5F55>\uFF1B\u5747\u7ECF\u6C99\u7BB1\u6821\u9A8C\u3002\u7528\u6237\u63D0\u5230\u5177\u4F53\u9879\u76EE\u65F6\u5FC5\u586B\u3002" },
5644
+ context: { type: "number", description: "\u6BCF\u4E2A\u547D\u4E2D\u9644\u5E26\u7684\u524D\u540E\u4E0A\u4E0B\u6587\u884C\u6570\uFF080-10\uFF0C\u9ED8\u8BA4 2\uFF09\u3002\u9700\u8981\u62FF\u8DB3\u4E00\u6BB5\u5B8C\u6574\u4EE3\u7801\u4F5C edit_file \u7684 old_str \u65F6\u53EF\u8C03\u5927\uFF08\u5982 5-8\uFF09\uFF0C\u514D\u5F97\u4E8C\u6B21\u68C0\u7D22" }
5589
5645
  },
5590
5646
  required: ["query"]
5591
5647
  },
@@ -5614,6 +5670,7 @@ var init_search = __esm({
5614
5670
  return resolveReadablePath(args.path);
5615
5671
  };
5616
5672
  const searchRoot = resolveSearchRoot().replace(/\\/g, "/");
5673
+ const contextLines = Math.min(Math.max(args.context ?? 2, 0), 10);
5617
5674
  const rgArgs = [
5618
5675
  "--threads",
5619
5676
  "1",
@@ -5624,8 +5681,8 @@ var init_search = __esm({
5624
5681
  "--color",
5625
5682
  "never",
5626
5683
  "-C",
5627
- "2",
5628
- // ★ 每个命中带前后各 2 行上下文:模型一次看懂用法,免去紧跟的 read_file 往返(减调用次数的关键)
5684
+ String(contextLines),
5685
+ // ★ 每个命中带前后上下文:模型一次看懂用法,免去紧跟的 read_file 往返(减调用次数的关键)
5629
5686
  "--max-count",
5630
5687
  "10",
5631
5688
  "--glob",
@@ -5928,48 +5985,90 @@ ${tail}`,
5928
5985
  // ../core/src/tool/registry/glob.ts
5929
5986
  import fs14 from "fs/promises";
5930
5987
  import path17 from "path";
5931
- var globToRegex2, globTools;
5988
+ var findMatchingBrace, splitTopLevel, globToRegex2, globTools;
5932
5989
  var init_glob = __esm({
5933
5990
  "../core/src/tool/registry/glob.ts"() {
5934
5991
  "use strict";
5935
5992
  init_type();
5936
5993
  init_guard();
5994
+ findMatchingBrace = (s, start) => {
5995
+ let depth = 0;
5996
+ for (let i = start; i < s.length; i++) {
5997
+ if (s[i] === "{") depth++;
5998
+ else if (s[i] === "}") {
5999
+ depth--;
6000
+ if (depth === 0) return i;
6001
+ }
6002
+ }
6003
+ return -1;
6004
+ };
6005
+ splitTopLevel = (s) => {
6006
+ const parts = [];
6007
+ let depth = 0, cur = "";
6008
+ for (const ch of s) {
6009
+ if (ch === "{") depth++;
6010
+ else if (ch === "}") depth--;
6011
+ if (ch === "," && depth === 0) {
6012
+ parts.push(cur);
6013
+ cur = "";
6014
+ continue;
6015
+ }
6016
+ cur += ch;
6017
+ }
6018
+ parts.push(cur);
6019
+ return parts;
6020
+ };
5937
6021
  globToRegex2 = (pattern) => {
5938
- let re = "";
5939
- let i = 0;
5940
- while (i < pattern.length) {
5941
- const c = pattern[i];
5942
- if (c === "*" && pattern[i + 1] === "*") {
5943
- if (pattern[i + 2] === "/") {
5944
- re += "(?:.*/)?";
5945
- i += 3;
6022
+ const walk = (s) => {
6023
+ let re = "";
6024
+ let i = 0;
6025
+ while (i < s.length) {
6026
+ const c = s[i];
6027
+ if (c === "{") {
6028
+ const close = findMatchingBrace(s, i);
6029
+ if (close === -1) {
6030
+ re += "\\{";
6031
+ i++;
6032
+ continue;
6033
+ }
6034
+ const alts = splitTopLevel(s.slice(i + 1, close));
6035
+ re += `(?:${alts.map((a) => walk(a)).join("|")})`;
6036
+ i = close + 1;
6037
+ continue;
6038
+ }
6039
+ if (c === "*" && s[i + 1] === "*") {
6040
+ if (s[i + 2] === "/") {
6041
+ re += "(?:.*/)?";
6042
+ i += 3;
6043
+ } else {
6044
+ re += ".*";
6045
+ i += 2;
6046
+ }
6047
+ } else if (c === "*") {
6048
+ re += "[^/]*";
6049
+ i++;
6050
+ } else if (c === "?") {
6051
+ re += ".";
6052
+ i++;
5946
6053
  } else {
5947
- re += ".*";
5948
- i += 2;
6054
+ re += /[.+^$}()|[\]\\]/.test(c) ? "\\" + c : c;
6055
+ i++;
5949
6056
  }
5950
- } else if (c === "*") {
5951
- re += "[^/]*";
5952
- i++;
5953
- } else if (c === "?") {
5954
- re += ".";
5955
- i++;
5956
- } else {
5957
- re += /[.+^${}()|[\]\\]/.test(c) ? "\\" + c : c;
5958
- i++;
5959
6057
  }
5960
- }
5961
- return new RegExp(`^${re}$`);
6058
+ return re;
6059
+ };
6060
+ return new RegExp(`^${walk(pattern)}$`);
5962
6061
  };
5963
6062
  globTools = [
5964
6063
  {
5965
6064
  type: "function",
5966
6065
  function: {
5967
6066
  name: "glob",
5968
- description: "\u6309\u6587\u4EF6\u540D glob \u6A21\u5F0F\u5FEB\u901F\u67E5\u627E\u6587\u4EF6\uFF08\u5982 '**/*.ts'\u3001'src/**/test*'\u3001'**/*.test.ts'\uFF09\u3002\u4E0E search_grep\uFF08\u6309\u5185\u5BB9\u68C0\u7D22\uFF09\u4E92\u8865\u3002\u81EA\u52A8\u5957\u7528 .gitignore / \u901A\u7528\u9ED1\u540D\u5355\u8FC7\u6EE4\u3002",
6067
+ description: "\u6309\u6587\u4EF6\u540D glob \u6A21\u5F0F\u5FEB\u901F\u67E5\u627E\u6587\u4EF6\uFF08\u5982 '**/*.ts'\u3001'src/**/test*'\u3001'**/*.test.ts'\uFF09\u3002\u2605 \u652F\u6301\u82B1\u62EC\u53F7\u591A\u9009\uFF1A'**/*.{ts,tsx,vue}'\u3001'src/{api,components}/**' \u4E00\u6B21\u67E5\u591A\u7C7B\u578B/\u591A\u76EE\u5F55\uFF0C\u52FF\u5206\u591A\u6B21\u8C03\u7528\u3002\u4E0E search_grep\uFF08\u6309\u5185\u5BB9\u68C0\u7D22\uFF09\u4E92\u8865\u3002\u81EA\u52A8\u5957\u7528 .gitignore / \u901A\u7528\u9ED1\u540D\u5355\u8FC7\u6EE4\u3002",
5969
6068
  parameters: {
5970
6069
  type: "object",
5971
6070
  properties: {
5972
- pattern: { type: "string", description: "glob \u6A21\u5F0F\uFF0C\u5982 '**/*.ts' \u6216 'src/**/*.test.ts'" },
6071
+ pattern: { type: "string", description: "glob \u6A21\u5F0F\uFF0C\u652F\u6301 * / ** / ? \u4E0E\u82B1\u62EC\u53F7\u591A\u9009 {a,b}\uFF08\u5982 '**/*.{ts,vue}'\u3001'src/{api,components}/**'\uFF09" },
5973
6072
  path: { type: "string", description: "\u9650\u5B9A\u641C\u7D22\u7684\u8D77\u59CB\u76EE\u5F55\uFF08\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u53EF\u9009\uFF0C\u9ED8\u8BA4\u5DE5\u4F5C\u533A\u6839\uFF09" }
5974
6073
  },
5975
6074
  required: ["pattern"]
@@ -6883,7 +6982,7 @@ var init_http = __esm({
6883
6982
  // ../core/src/tool/registry/typescript.ts
6884
6983
  import fs16 from "fs/promises";
6885
6984
  import path19 from "path";
6886
- var MAX_FILE_BYTES, toDisplayPath, precheck, MAX_DIAG_ENTRIES, typescriptTools;
6985
+ var MAX_FILE_BYTES, toDisplayPath, precheck, MAX_DIAG_ENTRIES, MAX_DIAG_FILES, diagnoseOneFile, typescriptTools;
6887
6986
  var init_typescript = __esm({
6888
6987
  "../core/src/tool/registry/typescript.ts"() {
6889
6988
  "use strict";
@@ -6907,74 +7006,108 @@ var init_typescript = __esm({
6907
7006
  return null;
6908
7007
  };
6909
7008
  MAX_DIAG_ENTRIES = 300;
7009
+ MAX_DIAG_FILES = 20;
7010
+ diagnoseOneFile = async (TS, displayPath, checkJs) => {
7011
+ try {
7012
+ const absPath = realpathNative(resolveReadablePath(displayPath));
7013
+ const block = await precheck(displayPath, absPath);
7014
+ if (block) return { ok: false, text: block };
7015
+ const { ls } = await getLanguageService(TS, absPath, { checkJs });
7016
+ const syntactic = ls.getSyntacticDiagnostics(absPath);
7017
+ const semantic = ls.getSemanticDiagnostics(absPath);
7018
+ const all = [...syntactic, ...semantic];
7019
+ if (all.length === 0) return { ok: true, errors: 0, warnings: 0, text: `\u2713 No diagnostics (0 errors, 0 warnings) for ${displayPath}` };
7020
+ const entries = [];
7021
+ let errors = 0, warnings = 0;
7022
+ for (const d of all) {
7023
+ const cat = d.category;
7024
+ let label;
7025
+ if (cat === TS.DiagnosticCategory.Error) {
7026
+ label = "error";
7027
+ errors++;
7028
+ } else if (cat === TS.DiagnosticCategory.Warning) {
7029
+ label = "warning";
7030
+ warnings++;
7031
+ } else if (cat === TS.DiagnosticCategory.Suggestion) label = "suggestion";
7032
+ else label = "info";
7033
+ let line = 0, column = 0;
7034
+ if (d.file && typeof d.start === "number") {
7035
+ ({ line, column } = posToLineCol(TS, d.file, d.start));
7036
+ }
7037
+ entries.push({
7038
+ line,
7039
+ column,
7040
+ label,
7041
+ code: typeof d.code === "number" ? `TS${d.code}` : "",
7042
+ msg: TS.flattenDiagnosticMessageText(d.messageText, "\n")
7043
+ });
7044
+ }
7045
+ entries.sort((a, b) => a.line - b.line || a.column - b.column);
7046
+ const overflow = entries.length > MAX_DIAG_ENTRIES ? entries.length - MAX_DIAG_ENTRIES : 0;
7047
+ const shown = overflow ? entries.slice(0, MAX_DIAG_ENTRIES) : entries;
7048
+ const body = shown.map(
7049
+ (e) => `${displayPath}:${e.line}:${e.column} ${e.label}${e.code ? " " + e.code : ""} ${e.msg}`
7050
+ ).join("\n");
7051
+ const tail = overflow ? `
7052
+ \u2026(\u53E6\u6709 ${overflow} \u6761\u8BCA\u65AD\u672A\u663E\u793A\uFF0C\u8BF7\u7F29\u5C0F\u8303\u56F4\u6216\u7528 run_command \u8DD1 tsc \u770B\u5168\u91CF)\u2026` : "";
7053
+ return { ok: true, errors, warnings, text: `[Diagnostics: ${displayPath}] ${errors} error(s), ${warnings} warning(s)
7054
+ ${body}${tail}` };
7055
+ } catch (e) {
7056
+ return { ok: false, text: `\u274C \u7C7B\u578B\u8BCA\u65AD\u5931\u8D25 [${displayPath}]: ${e?.message ?? e}` };
7057
+ }
7058
+ };
6910
7059
  typescriptTools = [
6911
7060
  {
6912
7061
  type: "function",
6913
7062
  function: {
6914
7063
  name: "get_diagnostics",
6915
- description: "\u5BF9\u5355\u4E2A TS/JS \u6587\u4EF6\u53D6 TypeScript \u8BED\u6CD5 + \u8BED\u4E49\u8BCA\u65AD\uFF08\u7C7B\u578B\u9519\u8BEF\u3001\u672A\u7528\u53D8\u91CF\u3001\u4E0D\u53EF\u8FBE\u4EE3\u7801\u7B49\uFF09\uFF0C\u8F93\u51FA\u5E26\u884C\u53F7/\u5217/\u4E25\u91CD\u5EA6/TS \u9519\u8BEF\u7801\uFF0C\u683C\u5F0F\u5BF9\u9F50 tsc\u3002\u7528\u4E8E\u7CBE\u51C6\u5B9A\u4F4D\u7F16\u8BD1/\u7C7B\u578B\u95EE\u9898\uFF0C\u66FF\u4EE3\u624B\u52A8\u8DD1 tsc \u518D\u89E3\u6790\u8F93\u51FA\u3002\u652F\u6301 .ts/.tsx/.js/.jsx/.mjs/.cjs\uFF1B.vue SFC \u4E0D\u652F\u6301\uFF08\u9700 vue-tsc\uFF09\u3002\u9879\u76EE\u7EA7\u5168\u91CF\u8BCA\u65AD\u8BF7\u7528 run_command \u8DD1 `tsc --noEmit`\u3002\u4F9D\u8D56 typescript \u6A21\u5757\uFF08VSCode \u6269\u5C55\u5185\u53EF\u7528\uFF1B\u7F3A\u5931\u5219\u672C\u5DE5\u5177\u81EA\u52A8\u9690\u85CF\uFF09\u3002",
7064
+ description: "\u5BF9\u4E00\u4E2A\u6216\u591A\u4E2A TS/JS \u6587\u4EF6\u53D6 TypeScript \u8BED\u6CD5 + \u8BED\u4E49\u8BCA\u65AD\uFF08\u7C7B\u578B\u9519\u8BEF\u3001\u672A\u7528\u53D8\u91CF\u3001\u4E0D\u53EF\u8FBE\u4EE3\u7801\u7B49\uFF09\uFF0C\u8F93\u51FA\u5E26\u884C\u53F7/\u5217/\u4E25\u91CD\u5EA6/TS \u9519\u8BEF\u7801\uFF0C\u683C\u5F0F\u5BF9\u9F50 tsc\u3002\u7528\u4E8E\u7CBE\u51C6\u5B9A\u4F4D\u7F16\u8BD1/\u7C7B\u578B\u95EE\u9898\uFF0C\u66FF\u4EE3\u624B\u52A8\u8DD1 tsc \u518D\u89E3\u6790\u8F93\u51FA\u3002\u2605 \u6539\u5B8C\u591A\u4E2A\u6587\u4EF6\u540E\u9A8C\u8BC1\uFF1A\u4F20 paths \u6570\u7EC4\u4E00\u6B21\u8BCA\u65AD\u5168\u90E8\uFF08\u6700\u591A 20 \u4E2A\uFF09\uFF0C\u52FF\u9010\u6587\u4EF6\u591A\u6B21\u8C03\u7528\u3002\u652F\u6301 .ts/.tsx/.js/.jsx/.mjs/.cjs\uFF1B.vue SFC \u4E0D\u652F\u6301\uFF08\u9700 vue-tsc\uFF09\u3002\u9879\u76EE\u7EA7\u5168\u91CF\u8BCA\u65AD\u8BF7\u7528 run_command \u8DD1 `tsc --noEmit`\u3002\u4F9D\u8D56 typescript \u6A21\u5757\uFF08VSCode \u6269\u5C55\u5185\u53EF\u7528\uFF1B\u7F3A\u5931\u5219\u672C\u5DE5\u5177\u81EA\u52A8\u9690\u85CF\uFF09\u3002",
6916
7065
  parameters: {
6917
7066
  type: "object",
6918
7067
  properties: {
6919
- path: { type: "string", description: "\u76EE\u6807\u6587\u4EF6\u76F8\u5BF9\u8DEF\u5F84\uFF08\u5982 'src/services/user.ts'\uFF09" },
7068
+ path: { type: "string", description: "\u76EE\u6807\u6587\u4EF6\u76F8\u5BF9\u8DEF\u5F84\uFF08\u5982 'src/services/user.ts'\uFF09\u3002\u5355\u6587\u4EF6\u8BCA\u65AD\u7528\uFF1B\u6279\u91CF\u8BF7\u6539\u7528 paths" },
7069
+ paths: { type: "array", items: { type: "string" }, description: "\u2605 \u6279\u91CF\u8BCA\u65AD\uFF1A\u591A\u4E2A\u6587\u4EF6\u4E00\u6B21\u9A8C\u8BC1\uFF08\u5355\u6B21\u6700\u591A 20 \u4E2A\uFF0C\u8D85\u51FA\u4F1A\u62D2\u7EDD\uFF09\u3002\u4F20\u4E86 paths \u5219\u5FFD\u7565 path" },
6920
7070
  check_js: { type: "boolean", description: "\u5BF9 .js/.jsx \u6587\u4EF6\u5F00\u542F\u8BED\u4E49\u68C0\u67E5\uFF08\u9ED8\u8BA4\u9075 tsconfig \u7684 checkJs\uFF1B\u76EE\u6807\u4E3A JS \u4E14\u60F3\u8981\u7C7B\u578B\u8BCA\u65AD\u65F6\u6309\u9700\u7F6E true\uFF09" }
6921
7071
  },
6922
- required: ["path"]
7072
+ required: []
6923
7073
  },
6924
7074
  safetyLevel: "safe" /* SAFE */,
6925
7075
  isSync: true,
6926
- maxOutputCharacters: 24e3,
7076
+ maxOutputCharacters: 48e3,
7077
+ // ★ 批量多文件后上调(原单文件 24K;中心 truncateToolResult 仍是最终兜底)
6927
7078
  privacyMaskingRules: maskSecretsInContent,
6928
7079
  validateEnvironment: async () => !!await getTs(),
6929
7080
  async execute(args, _ctx) {
6930
7081
  try {
6931
7082
  const TS = await getTs();
6932
7083
  if (!TS) return `\u26A0\uFE0F [\u7C7B\u578B\u8BCA\u65AD\u4E0D\u53EF\u7528]\uFF1Atypescript \u6A21\u5757\u672A\u52A0\u8F7D\uFF08VSCode \u6269\u5C55\u5185\u53EF\u7528\uFF1BCLI \u73AF\u5883\u672A\u5FC5\u5B89\u88C5 typescript\uFF09\u3002\u53EF\u6539\u7528 run_command \u8DD1 \`tsc --noEmit\`\u3002`;
6933
- const absPath = realpathNative(resolveReadablePath(args.path));
6934
- const block = await precheck(args.path, absPath);
6935
- if (block) return block;
6936
- const { ls } = await getLanguageService(TS, absPath, { checkJs: args.check_js });
6937
- const syntactic = ls.getSyntacticDiagnostics(absPath);
6938
- const semantic = ls.getSemanticDiagnostics(absPath);
6939
- const all = [...syntactic, ...semantic];
6940
- if (all.length === 0) return `\u2713 No diagnostics (0 errors, 0 warnings) for ${args.path}`;
6941
- const entries = [];
6942
- let errors = 0, warnings = 0;
6943
- for (const d of all) {
6944
- const cat = d.category;
6945
- let label;
6946
- if (cat === TS.DiagnosticCategory.Error) {
6947
- label = "error";
6948
- errors++;
6949
- } else if (cat === TS.DiagnosticCategory.Warning) {
6950
- label = "warning";
6951
- warnings++;
6952
- } else if (cat === TS.DiagnosticCategory.Suggestion) label = "suggestion";
6953
- else label = "info";
6954
- let line = 0, column = 0;
6955
- if (d.file && typeof d.start === "number") {
6956
- ({ line, column } = posToLineCol(TS, d.file, d.start));
7084
+ const targets = args.paths && args.paths.length > 0 ? args.paths : args.path ? [args.path] : [];
7085
+ if (targets.length === 0) return `\u274C [\u53C2\u6570\u7F3A\u5931]\uFF1A\u8BF7\u4F20 path\uFF08\u5355\u6587\u4EF6\uFF09\u6216 paths\uFF08\u6279\u91CF\uFF0C\u6539\u5B8C\u591A\u4E2A\u6587\u4EF6\u540E\u4E00\u6B21\u9A8C\u8BC1\uFF09\u3002`;
7086
+ if (targets.length > MAX_DIAG_FILES) return `\u274C [\u53C2\u6570\u8D85\u9650]\uFF1A\u5355\u6B21\u6279\u91CF\u8BCA\u65AD\u6700\u591A ${MAX_DIAG_FILES} \u4E2A\u6587\u4EF6\uFF08\u6536\u5230 ${targets.length} \u4E2A\uFF09\u3002\u8BF7\u5206\u6279\u8C03\u7528\uFF0C\u6216\u7528 run_command \u8DD1 \`tsc --noEmit\` \u505A\u9879\u76EE\u7EA7\u5168\u91CF\u8BCA\u65AD\u3002`;
7087
+ const results = [];
7088
+ for (const p of targets) results.push(await diagnoseOneFile(TS, p, args.check_js));
7089
+ if (results.length === 1) return results[0].text;
7090
+ let totalErr = 0, totalWarn = 0, clean = 0, failed = 0;
7091
+ const sections = [];
7092
+ for (let i = 0; i < results.length; i++) {
7093
+ const r = results[i];
7094
+ if (!r.ok) {
7095
+ failed++;
7096
+ sections.push(`\u2014\u2014 ${targets[i]}\uFF08\u8BCA\u65AD\u672A\u4EA7\u51FA\uFF09\u2014\u2014
7097
+ ${r.text}`);
7098
+ continue;
6957
7099
  }
6958
- entries.push({
6959
- line,
6960
- column,
6961
- label,
6962
- code: typeof d.code === "number" ? `TS${d.code}` : "",
6963
- msg: TS.flattenDiagnosticMessageText(d.messageText, "\n")
6964
- });
7100
+ totalErr += r.errors;
7101
+ totalWarn += r.warnings;
7102
+ if (r.errors === 0 && r.warnings === 0) clean++;
7103
+ sections.push(`\u2014\u2014 ${targets[i]} \u2014\u2014
7104
+ ${r.text}`);
6965
7105
  }
6966
- entries.sort((a, b) => a.line - b.line || a.column - b.column);
6967
- const overflow = entries.length > MAX_DIAG_ENTRIES ? entries.length - MAX_DIAG_ENTRIES : 0;
6968
- const shown = overflow ? entries.slice(0, MAX_DIAG_ENTRIES) : entries;
6969
- const body = shown.map(
6970
- (e) => `${args.path}:${e.line}:${e.column} ${e.label}${e.code ? " " + e.code : ""} ${e.msg}`
6971
- ).join("\n");
6972
- const tail = overflow ? `
6973
- \u2026(\u53E6\u6709 ${overflow} \u6761\u8BCA\u65AD\u672A\u663E\u793A\uFF0C\u8BF7\u7F29\u5C0F\u8303\u56F4\u6216\u7528 run_command \u8DD1 tsc \u770B\u5168\u91CF)\u2026` : "";
6974
- return `[Diagnostics: ${args.path}] ${errors} error(s), ${warnings} warning(s)
6975
- ${body}${tail}`;
7106
+ return `[\u6279\u91CF\u8BCA\u65AD: ${targets.length} \u4E2A\u6587\u4EF6] \u5171 ${totalErr} error(s), ${totalWarn} warning(s)\uFF1B${clean} \u4E2A\u6587\u4EF6\u5E72\u51C0${failed ? `\uFF0C${failed} \u4E2A\u8BCA\u65AD\u5931\u8D25` : ""}
7107
+
7108
+ ${sections.join("\n\n")}`;
6976
7109
  } catch (e) {
6977
- return `\u274C \u7C7B\u578B\u8BCA\u65AD\u5931\u8D25 [${args.path}]: ${e?.message ?? e}`;
7110
+ return `\u274C \u7C7B\u578B\u8BCA\u65AD\u5931\u8D25: ${e?.message ?? e}`;
6978
7111
  }
6979
7112
  }
6980
7113
  }
@@ -8818,7 +8951,6 @@ var agentTools, agentSubTools, workflowTools;
8818
8951
  var init_tool = __esm({
8819
8952
  "../core/src/tool/index.ts"() {
8820
8953
  "use strict";
8821
- init_system();
8822
8954
  init_agent();
8823
8955
  init_workflow();
8824
8956
  init_fs();
@@ -8844,7 +8976,6 @@ var init_tool = __esm({
8844
8976
  agentSubTools = createAgentTools(() => agentTools);
8845
8977
  workflowTools = createWorkflowTools(() => agentTools);
8846
8978
  agentTools.push(
8847
- ...systemTools,
8848
8979
  ...agentSubTools,
8849
8980
  ...workflowTools,
8850
8981
  ...fsTools,
@@ -12442,14 +12573,17 @@ var init_useChatState = __esm({
12442
12573
  await runOnce(sid, `\uFF08\u7528\u6237\u5DF2\u6279\u51C6\u4EE5\u4E0B\u65B9\u6848\uFF0C\u8BF7\u4E25\u683C\u6309\u65B9\u6848\u5F00\u59CB\u5B9E\u73B0\uFF09\uFF1A
12443
12574
 
12444
12575
  ${finalPlan}`, false, res.autoExecute);
12445
- } else {
12446
- pushInfo(S.planRejected);
12576
+ return true;
12447
12577
  }
12578
+ planModeRef.current = true;
12579
+ pushInfo(S.planKeepPlanning);
12580
+ return false;
12448
12581
  }, [runOnce, setPlan, pushInfo]);
12449
12582
  const runPlanStage = useCallback(async (sid, researchPrompt) => {
12450
12583
  await runOnce(sid, researchPrompt, true);
12451
12584
  const plan = takeProposedPlan();
12452
- if (plan != null) await approveAndImplement(sid, plan);
12585
+ if (plan == null) return false;
12586
+ return await approveAndImplement(sid, plan);
12453
12587
  }, [runOnce, takeProposedPlan, approveAndImplement]);
12454
12588
  const queueInput = useCallback((content) => {
12455
12589
  const text = content.trim();
@@ -12472,7 +12606,8 @@ ${finalPlan}`, false, res.autoExecute);
12472
12606
  const sid = sessionIdRef.current;
12473
12607
  pushUser(text);
12474
12608
  if (planModeRef.current) {
12475
- await runPlanStage(sid, text);
12609
+ const kept = await runPlanStage(sid, text);
12610
+ if (kept) planModeRef.current = false;
12476
12611
  } else {
12477
12612
  await runOnce(sid, text, false);
12478
12613
  const proposedPlan = takeProposedPlan();
@@ -12483,8 +12618,8 @@ ${finalPlan}`, false, res.autoExecute);
12483
12618
  if (enterReason != null) {
12484
12619
  pushInfo(`\u{1F4CB} \u6A21\u578B\u8BF7\u6C42\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F${enterReason ? `\uFF1A${enterReason}` : ""}\uFF0C\u5DF2\u5207\u6362\u2026`);
12485
12620
  planModeRef.current = true;
12486
- await runPlanStage(sid, ENTER_PLAN_RESEARCH_PROMPT);
12487
- planModeRef.current = false;
12621
+ const kept = await runPlanStage(sid, ENTER_PLAN_RESEARCH_PROMPT);
12622
+ if (kept) planModeRef.current = false;
12488
12623
  }
12489
12624
  }
12490
12625
  }
@@ -12748,6 +12883,8 @@ var init_MessageBlock = __esm({
12748
12883
  return { bullet: `${m[2]} `, rest: m[3] };
12749
12884
  };
12750
12885
  AssistantLine = ({ line }) => {
12886
+ const heading = line.match(/^#{1,6}\s+(.*)$/);
12887
+ if (heading) return /* @__PURE__ */ jsx3(Text3, { bold: true, color: "#ffffff", children: heading[1] });
12751
12888
  const list = listPrefix(line);
12752
12889
  if (list) {
12753
12890
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
@@ -12897,6 +13034,149 @@ var init_ThinkingBlock = __esm({
12897
13034
  }
12898
13035
  });
12899
13036
 
13037
+ // src/lineDiff.ts
13038
+ var splitLines, lineDiff, collapseContext;
13039
+ var init_lineDiff = __esm({
13040
+ "src/lineDiff.ts"() {
13041
+ "use strict";
13042
+ splitLines = (s) => {
13043
+ const t = String(s ?? "").replace(/\r\n/g, "\n");
13044
+ return t === "" ? [] : t.split("\n");
13045
+ };
13046
+ lineDiff = (oldStr, newStr) => {
13047
+ const a = splitLines(oldStr);
13048
+ const b = splitLines(newStr);
13049
+ let s = 0;
13050
+ while (s < a.length && s < b.length && a[s] === b[s]) s++;
13051
+ let e = 0;
13052
+ while (e < a.length - s && e < b.length - s && a[a.length - 1 - e] === b[b.length - 1 - e]) e++;
13053
+ const m1 = a.slice(s, a.length - e);
13054
+ const m2 = b.slice(s, b.length - e);
13055
+ const rows = [];
13056
+ for (let i = 0; i < s; i++) rows.push({ t: "ctx", s: a[i] });
13057
+ const n = m1.length, m = m2.length;
13058
+ if (n === 0 && m === 0) {
13059
+ } else if (n * m > 4e6) {
13060
+ for (const l of m1) rows.push({ t: "del", s: l });
13061
+ for (const l of m2) rows.push({ t: "add", s: l });
13062
+ } else {
13063
+ const w = m + 1;
13064
+ const dp = new Uint32Array((n + 1) * w);
13065
+ for (let i2 = n - 1; i2 >= 0; i2--) {
13066
+ for (let j2 = m - 1; j2 >= 0; j2--) {
13067
+ dp[i2 * w + j2] = m1[i2] === m2[j2] ? dp[(i2 + 1) * w + j2 + 1] + 1 : Math.max(dp[(i2 + 1) * w + j2], dp[i2 * w + j2 + 1]);
13068
+ }
13069
+ }
13070
+ let i = 0, j = 0;
13071
+ while (i < n && j < m) {
13072
+ if (m1[i] === m2[j]) {
13073
+ rows.push({ t: "ctx", s: m1[i] });
13074
+ i++;
13075
+ j++;
13076
+ } else if (dp[(i + 1) * w + j] >= dp[i * w + j + 1]) {
13077
+ rows.push({ t: "del", s: m1[i] });
13078
+ i++;
13079
+ } else {
13080
+ rows.push({ t: "add", s: m2[j] });
13081
+ j++;
13082
+ }
13083
+ }
13084
+ while (i < n) {
13085
+ rows.push({ t: "del", s: m1[i] });
13086
+ i++;
13087
+ }
13088
+ while (j < m) {
13089
+ rows.push({ t: "add", s: m2[j] });
13090
+ j++;
13091
+ }
13092
+ }
13093
+ for (let k = 0; k < e; k++) rows.push({ t: "ctx", s: a[a.length - e + k] });
13094
+ return rows;
13095
+ };
13096
+ collapseContext = (rows, keep = 2) => {
13097
+ const out = [];
13098
+ let i = 0;
13099
+ while (i < rows.length) {
13100
+ if (rows[i].t !== "ctx") {
13101
+ out.push(rows[i]);
13102
+ i++;
13103
+ continue;
13104
+ }
13105
+ let j = i;
13106
+ while (j < rows.length && rows[j].t === "ctx") j++;
13107
+ const run = j - i;
13108
+ if (run > keep * 2 + 1) {
13109
+ for (let k = 0; k < keep; k++) out.push(rows[i + k]);
13110
+ out.push({ t: "ellip", n: run - keep * 2 });
13111
+ for (let k = run - keep; k < run; k++) out.push(rows[i + k]);
13112
+ } else {
13113
+ for (let k = 0; k < run; k++) out.push(rows[i + k]);
13114
+ }
13115
+ i = j;
13116
+ }
13117
+ return out;
13118
+ };
13119
+ }
13120
+ });
13121
+
13122
+ // src/diffView.ts
13123
+ var EDIT_TOOL_NAMES, extractEditPairs, pairsToDisplayRows, parseApprovalDiff;
13124
+ var init_diffView = __esm({
13125
+ "src/diffView.ts"() {
13126
+ "use strict";
13127
+ init_lineDiff();
13128
+ EDIT_TOOL_NAMES = ["edit_file", "create_file", "write_file"];
13129
+ extractEditPairs = (toolName, args) => {
13130
+ if (args == null || typeof args !== "object") return null;
13131
+ const o = args;
13132
+ if (toolName === "edit_file") {
13133
+ const list = Array.isArray(o.edits) && o.edits.length > 0 ? o.edits : [o];
13134
+ const pairs = list.filter((e) => typeof e.old_str === "string" && e.old_str.length > 0);
13135
+ if (pairs.length === 0) return null;
13136
+ return pairs.map((e, i) => ({
13137
+ label: pairs.length > 1 ? `\u7B2C ${i + 1} \u5904${e.replace_all ? "\uFF08\u6279\u91CF\u66FF\u6362\u5168\u90E8\u5339\u914D\uFF09" : ""}` : "",
13138
+ old: e.old_str,
13139
+ new: typeof e.new_str === "string" ? e.new_str : ""
13140
+ }));
13141
+ }
13142
+ if (toolName === "create_file" || toolName === "write_file") {
13143
+ return typeof o.content === "string" && o.content.length > 0 ? [{ label: "", old: "", new: o.content }] : null;
13144
+ }
13145
+ return null;
13146
+ };
13147
+ pairsToDisplayRows = (pairs, keep = 2) => {
13148
+ const out = [];
13149
+ let changed = false;
13150
+ for (const p of pairs) {
13151
+ const collapsed = collapseContext(lineDiff(p.old, p.new), keep);
13152
+ if (!collapsed.some((r) => r.t !== "ctx" && r.t !== "ellip")) continue;
13153
+ changed = true;
13154
+ if (p.label) {
13155
+ if (out.length > 0) out.push({ t: "ellip", n: 0 });
13156
+ out.push({ t: "ctx", s: `\u2014\u2014 ${p.label} \u2014\u2014` });
13157
+ }
13158
+ out.push(...collapsed);
13159
+ }
13160
+ return changed ? out : null;
13161
+ };
13162
+ parseApprovalDiff = (detail, toolName) => {
13163
+ if (toolName !== "edit_file" || !detail.includes("\u3010\u51CF\u5C11\u3011:")) return null;
13164
+ const parts = detail.split(/\n(?=—— 第 )/);
13165
+ const sections = [];
13166
+ for (const part of parts.slice(1)) {
13167
+ const label = (part.match(/^—— (第 \d+ 处[^\n]*)——/)?.[1] ?? "").trim();
13168
+ const rIdx = part.indexOf("\u3010\u51CF\u5C11\u3011:");
13169
+ const aIdx = part.indexOf("\u3010\u589E\u52A0\u3011:");
13170
+ if (rIdx < 0 || aIdx < 0 || aIdx < rIdx) continue;
13171
+ const old = part.slice(rIdx + "\u3010\u51CF\u5C11\u3011:".length, aIdx).replace(/^\n+|\n+$/g, "");
13172
+ const neu = part.slice(aIdx + "\u3010\u589E\u52A0\u3011:".length).replace(/^\n+|\n+$/g, "");
13173
+ sections.push({ label, old, new: neu });
13174
+ }
13175
+ return sections.length > 0 ? { header: parts[0], sections } : null;
13176
+ };
13177
+ }
13178
+ });
13179
+
12900
13180
  // src/components/ToolCard.tsx
12901
13181
  import { Box as Box3, Text as Text5 } from "ink";
12902
13182
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
@@ -12906,6 +13186,7 @@ var init_ToolCard = __esm({
12906
13186
  "use strict";
12907
13187
  init_theme();
12908
13188
  init_util();
13189
+ init_diffView();
12909
13190
  ToolCard = ({ toolName, args, result, ok, status, progress, wrapW }) => {
12910
13191
  const tool = findTool(toolName);
12911
13192
  const level = tool?.function?.safetyLevel;
@@ -12922,6 +13203,15 @@ var init_ToolCard = __esm({
12922
13203
  const last = progress.replace(/\r/g, "").split("\n").map((s) => s.trim()).filter(Boolean).pop() ?? "";
12923
13204
  return truncateMiddle(last, Math.max(20, wrapW - 6));
12924
13205
  })();
13206
+ const MAX_DIFF_LINES2 = 14;
13207
+ const diffAll = (() => {
13208
+ if (status !== "done" || !ok) return null;
13209
+ if (!EDIT_TOOL_NAMES.includes(toolName)) return null;
13210
+ const pairs = extractEditPairs(toolName, args);
13211
+ return pairs ? pairsToDisplayRows(pairs) : null;
13212
+ })();
13213
+ const diffRows = diffAll ? diffAll.slice(0, MAX_DIFF_LINES2) : null;
13214
+ const diffHidden = diffAll ? Math.max(0, diffAll.length - MAX_DIFF_LINES2) : 0;
12925
13215
  return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 0.3, marginBottom: 0.3, children: [
12926
13216
  /* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", flexShrink: 0, children: [
12927
13217
  /* @__PURE__ */ jsx5(Text5, { color: markerColor, bold: true, children: "\u23FA " }),
@@ -12935,6 +13225,14 @@ var init_ToolCard = __esm({
12935
13225
  ] }, i)) : status === "running" ? /* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", flexShrink: 0, children: [
12936
13226
  /* @__PURE__ */ jsx5(Text5, { color: THEME.grayDim, children: " \u23BF " }),
12937
13227
  /* @__PURE__ */ jsx5(Text5, { color: THEME.gray, children: runningLine || "\u8FD0\u884C\u4E2D\u2026" })
13228
+ ] }) : null,
13229
+ diffRows && diffRows.length > 0 ? diffRows.map((r, i) => /* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", flexShrink: 0, children: [
13230
+ /* @__PURE__ */ jsx5(Text5, { color: THEME.grayDim, children: " " }),
13231
+ r.t === "ellip" ? /* @__PURE__ */ jsx5(Text5, { color: THEME.grayDim, children: r.n > 0 ? ` \u22EF ${r.n} \u884C\u672A\u53D8` : " \u22EF" }) : /* @__PURE__ */ jsx5(Text5, { color: r.t === "del" ? THEME.danger : r.t === "add" ? THEME.ok : THEME.grayDim, children: `${r.t === "del" ? "- " : r.t === "add" ? "+ " : " "}${truncateMiddle(r.s, Math.max(20, wrapW - 8))}` })
13232
+ ] }, `diff-${i}`)) : null,
13233
+ diffHidden > 0 ? /* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", flexShrink: 0, children: [
13234
+ /* @__PURE__ */ jsx5(Text5, { color: THEME.grayDim, children: " " }),
13235
+ /* @__PURE__ */ jsx5(Text5, { color: THEME.grayDim, children: ` \u2026\uFF08\u53E6\u6709 ${diffHidden} \u884C\u6539\u52A8\u672A\u663E\u793A\uFF09` })
12938
13236
  ] }) : null
12939
13237
  ] });
12940
13238
  };
@@ -12978,28 +13276,36 @@ var init_TodosPanel = __esm({
12978
13276
 
12979
13277
  // src/components/ApprovalModal.tsx
12980
13278
  import { Box as Box5, Text as Text7 } from "ink";
12981
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
12982
- var OPTIONS, ApprovalModal;
13279
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
13280
+ var OPTIONS, MAX_DIFF_LINES, ApprovalModal;
12983
13281
  var init_ApprovalModal = __esm({
12984
13282
  "src/components/ApprovalModal.tsx"() {
12985
13283
  "use strict";
12986
13284
  init_theme();
12987
13285
  init_strings();
12988
13286
  init_util();
13287
+ init_diffView();
12989
13288
  OPTIONS = [
12990
13289
  { label: S.approvalAllow, value: "allow-once", color: THEME.ok },
12991
13290
  { label: S.approvalAllowAlways, value: "allow-always", color: THEME.warn },
12992
13291
  { label: S.approvalDeny, value: "deny", color: THEME.danger }
12993
13292
  ];
13293
+ MAX_DIFF_LINES = 18;
12994
13294
  ApprovalModal = ({ toolName, detail, selectedIndex, wrapW }) => {
12995
13295
  const contentW = Math.max(16, wrapW);
13296
+ const parsed = parseApprovalDiff(detail, toolName);
13297
+ const diffRows = parsed ? pairsToDisplayRows(parsed.sections) : null;
12996
13298
  return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: THEME.warn, paddingX: 1, paddingY: 1, marginTop: 1, children: [
12997
13299
  /* @__PURE__ */ jsxs5(Text7, { color: THEME.warn, bold: true, children: [
12998
13300
  S.approvalTitle,
12999
13301
  " \xB7 ",
13000
13302
  toolName
13001
13303
  ] }),
13002
- /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", marginTop: 0.5, marginBottom: 0.5, children: wrapText(detail || "(\u65E0\u8BF4\u660E)", contentW).map((line, j) => /* @__PURE__ */ jsx7(Text7, { color: THEME.white, children: line }, j)) }),
13304
+ /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", marginTop: 0.5, marginBottom: 0.5, children: parsed && diffRows ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
13305
+ wrapText(parsed.header, contentW).map((line, j) => /* @__PURE__ */ jsx7(Text7, { color: THEME.white, children: line }, `h-${j}`)),
13306
+ diffRows.slice(0, MAX_DIFF_LINES).map((r, i) => /* @__PURE__ */ jsx7(Text7, { color: r.t === "del" ? THEME.danger : r.t === "add" ? THEME.ok : THEME.grayDim, children: r.t === "ellip" ? r.n > 0 ? ` \u22EF ${r.n} \u884C\u672A\u53D8` : " \u22EF" : `${r.t === "del" ? "- " : r.t === "add" ? "+ " : " "}${truncateMiddle(r.s, Math.max(20, contentW - 2))}` }, `d-${i}`)),
13307
+ diffRows.length > MAX_DIFF_LINES ? /* @__PURE__ */ jsx7(Text7, { color: THEME.grayDim, children: ` \u2026\uFF08\u53E6\u6709 ${diffRows.length - MAX_DIFF_LINES} \u884C\u672A\u663E\u793A\uFF09` }) : null
13308
+ ] }) : wrapText(detail || "(\u65E0\u8BF4\u660E)", contentW).map((line, j) => /* @__PURE__ */ jsx7(Text7, { color: THEME.white, children: line }, j)) }),
13003
13309
  /* @__PURE__ */ jsx7(Text7, { color: THEME.grayDim, children: S.approvalPrompt }),
13004
13310
  OPTIONS.map((opt, i) => {
13005
13311
  const active = i === selectedIndex;
@@ -13539,7 +13845,7 @@ __export(App_exports, {
13539
13845
  });
13540
13846
  import { useCallback as useCallback2, useEffect as useEffect4, useMemo, useRef as useRef2, useState as useState4 } from "react";
13541
13847
  import { Box as Box15, Static, Text as Text17, useApp, useInput as useInput2, useStdout } from "ink";
13542
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
13848
+ import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
13543
13849
  var KNOWN_MODELS, CWD2, RowView, isDynamicRow, App;
13544
13850
  var init_App = __esm({
13545
13851
  "src/App.tsx"() {
@@ -14068,9 +14374,10 @@ ${listText}`);
14068
14374
  state.pendingFork ? /* @__PURE__ */ jsx17(ForkPicker, { anchors: state.pendingFork.anchors, selectedIndex: selectIdx, wrapW }) : null,
14069
14375
  slashVisible ? /* @__PURE__ */ jsx17(SlashMenu, { entries: filteredCommands, selectedIndex: selectIdx, cols }) : null
14070
14376
  ] }),
14071
- /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", paddingX: 1, marginTop: 1, flexShrink: 0, children: [
14072
- /* @__PURE__ */ jsx17(Text17, { dimColor: true, color: THEME.gray, children: dimRule(cols) }),
14073
- /* @__PURE__ */ jsx17(
14377
+ /* @__PURE__ */ jsx17(Box15, { flexDirection: "column", paddingX: 1, marginTop: 1, flexShrink: 0, children: (() => {
14378
+ const planOn = state.getPlanMode();
14379
+ const autoOn = !planOn && state.getAutoMode();
14380
+ const inputEl = /* @__PURE__ */ jsx17(
14074
14381
  MultilineInput,
14075
14382
  {
14076
14383
  value: input,
@@ -14086,8 +14393,18 @@ ${listText}`);
14086
14393
  suppressSubmit: slashVisible,
14087
14394
  placeholder: S.placeholder
14088
14395
  }
14089
- )
14090
- ] }),
14396
+ );
14397
+ if (planOn || autoOn) {
14398
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: planOn ? THEME.thinking : THEME.warn, paddingX: 1, children: [
14399
+ /* @__PURE__ */ jsx17(Text17, { color: planOn ? THEME.thinking : THEME.warn, children: planOn ? S.inputBadgePlan : S.inputBadgeAuto }),
14400
+ inputEl
14401
+ ] });
14402
+ }
14403
+ return /* @__PURE__ */ jsxs15(Fragment3, { children: [
14404
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, color: THEME.gray, children: dimRule(cols) }),
14405
+ inputEl
14406
+ ] });
14407
+ })() }),
14091
14408
  /* @__PURE__ */ jsx17(Box15, { paddingX: 1, marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx17(StatusStrip, { model: modelDisplay, busy: state.busy, aborting: state.aborting, planMode: state.getPlanMode(), autoMode: state.getAutoMode(), sessionShort, cols, customLine: statusLineText }) })
14092
14409
  ] })
14093
14410
  ] });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepseeker-code",
3
- "version": "1.0.4",
3
+ "version": "1.0.41",
4
4
  "description": "DeepSeeker-Code 终端客户端(React Ink,in-process 直驱 runAgent)",
5
5
  "homepage": "https://github.com/xknk/deepSeekCode#readme",
6
6
  "repository": {