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.
- package/README.md +1 -1
- package/dist/cli.mjs +510 -193
- 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
|
|
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: "\
|
|
38
|
-
planPrompt: "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u786E\u8BA4\uFF08\
|
|
39
|
-
planAcceptAuto: "\
|
|
40
|
-
planAcceptManual: "\
|
|
41
|
-
planEdit: "\
|
|
42
|
-
planReject: "\
|
|
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
|
-
|
|
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: "
|
|
177
|
+
planTitle: "Ready to code?",
|
|
176
178
|
planPrompt: "\u2191\u2193 then Enter (edit opens the editor: Enter to save / Esc to cancel).",
|
|
177
|
-
planAcceptAuto: "
|
|
178
|
-
planAcceptManual: "
|
|
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: "
|
|
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
|
-
|
|
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
|
-
|
|
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"
|
|
5293
|
+
required: ["path"]
|
|
5213
5294
|
},
|
|
5214
5295
|
safetyLevel: "mutation" /* MUTATION */,
|
|
5215
5296
|
isSync: true,
|
|
5216
|
-
requireApproval: (args) =>
|
|
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
|
-
${
|
|
5301
|
+
${e.old_str}
|
|
5219
5302
|
\u3010\u589E\u52A0\u3011:
|
|
5220
|
-
${
|
|
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
|
-
|
|
5227
|
-
const
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
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
|
-
|
|
5262
|
-
|
|
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 ?
|
|
5274
|
-
return
|
|
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\
|
|
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
|
|
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
|
-
|
|
5628
|
-
// ★
|
|
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
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
if (
|
|
5944
|
-
|
|
5945
|
-
|
|
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
|
|
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
|
-
|
|
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'
|
|
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\
|
|
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: [
|
|
7072
|
+
required: []
|
|
6923
7073
|
},
|
|
6924
7074
|
safetyLevel: "safe" /* SAFE */,
|
|
6925
7075
|
isSync: true,
|
|
6926
|
-
maxOutputCharacters:
|
|
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
|
|
6934
|
-
|
|
6935
|
-
if (
|
|
6936
|
-
const
|
|
6937
|
-
const
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
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
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
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
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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:
|
|
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__ */
|
|
14072
|
-
|
|
14073
|
-
|
|
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
|
] });
|