dskcode 0.1.31 → 0.1.34
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/dist/index.js +203 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1175,7 +1175,7 @@ function formatArgsSummary(args) {
|
|
|
1175
1175
|
return ` ${truncated}`;
|
|
1176
1176
|
}
|
|
1177
1177
|
}
|
|
1178
|
-
function ToolCallBlock({ call
|
|
1178
|
+
function ToolCallBlock({ call }) {
|
|
1179
1179
|
const argsDisplay = formatArgsSummary(call.arguments);
|
|
1180
1180
|
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginLeft: 3, marginTop: 1, children: [
|
|
1181
1181
|
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
@@ -1188,8 +1188,7 @@ function ToolCallBlock({ call, showPendingHint = true }) {
|
|
|
1188
1188
|
"\u2500".repeat(Math.max(1, 30 - call.name.length))
|
|
1189
1189
|
] })
|
|
1190
1190
|
] }),
|
|
1191
|
-
/* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: /* @__PURE__ */ jsx3(Text4, { dimColor: true, children: argsDisplay }) })
|
|
1192
|
-
showPendingHint && /* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsx3(Text4, { dimColor: true, children: "\u23F3 \u7B49\u5F85\u6267\u884C" }) })
|
|
1191
|
+
/* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: /* @__PURE__ */ jsx3(Text4, { dimColor: true, children: argsDisplay }) })
|
|
1193
1192
|
] });
|
|
1194
1193
|
}
|
|
1195
1194
|
|
|
@@ -2099,6 +2098,79 @@ function TodoListPanel({ items }) {
|
|
|
2099
2098
|
] });
|
|
2100
2099
|
}
|
|
2101
2100
|
|
|
2101
|
+
// package.json
|
|
2102
|
+
var package_default = {
|
|
2103
|
+
name: "dskcode",
|
|
2104
|
+
version: "0.1.34",
|
|
2105
|
+
repository: {
|
|
2106
|
+
type: "git",
|
|
2107
|
+
url: "git+https://github.com/Awu12277/deepseek-agent-cli/tree/main"
|
|
2108
|
+
},
|
|
2109
|
+
keywords: [
|
|
2110
|
+
"cli",
|
|
2111
|
+
"ink",
|
|
2112
|
+
"commander",
|
|
2113
|
+
"deepseek",
|
|
2114
|
+
"asciichart"
|
|
2115
|
+
],
|
|
2116
|
+
description: "A DeepSeek-native AI coding agent for your terminal",
|
|
2117
|
+
type: "module",
|
|
2118
|
+
bin: {
|
|
2119
|
+
dskcode: "dist/index.js"
|
|
2120
|
+
},
|
|
2121
|
+
exports: {
|
|
2122
|
+
".": {
|
|
2123
|
+
import: "./dist/index.js",
|
|
2124
|
+
types: "./dist/index.d.ts"
|
|
2125
|
+
}
|
|
2126
|
+
},
|
|
2127
|
+
files: [
|
|
2128
|
+
"dist",
|
|
2129
|
+
"README.md",
|
|
2130
|
+
"LICENSE"
|
|
2131
|
+
],
|
|
2132
|
+
scripts: {
|
|
2133
|
+
dev: "tsup --watch",
|
|
2134
|
+
build: "tsup",
|
|
2135
|
+
"type-check": "tsc --noEmit",
|
|
2136
|
+
lint: "oxlint src/ tests/",
|
|
2137
|
+
"lint:fix": "oxlint --fix src/ tests/",
|
|
2138
|
+
format: "prettier --write src/ tests/",
|
|
2139
|
+
"format:check": "prettier --check src/ tests/",
|
|
2140
|
+
test: "vitest run",
|
|
2141
|
+
"test:watch": "vitest",
|
|
2142
|
+
"test:coverage": "vitest run --coverage",
|
|
2143
|
+
prepublishOnly: "npm run build && npm run test"
|
|
2144
|
+
},
|
|
2145
|
+
dependencies: {
|
|
2146
|
+
asciichart: "^1.5.25",
|
|
2147
|
+
chalk: "^5.6.2",
|
|
2148
|
+
commander: "^13.1.0",
|
|
2149
|
+
handlebars: "^4.7.9",
|
|
2150
|
+
ink: "^7.1.0",
|
|
2151
|
+
"ink-spinner": "^5.0.0",
|
|
2152
|
+
"ink-text-input": "^6.0.0",
|
|
2153
|
+
react: "^19.2.7"
|
|
2154
|
+
},
|
|
2155
|
+
devDependencies: {
|
|
2156
|
+
"@types/node": "^22.14.0",
|
|
2157
|
+
"@types/react": "^19.2.17",
|
|
2158
|
+
oxlint: "^1.71.0",
|
|
2159
|
+
"oxlint-tsgolint": "^0.23.0",
|
|
2160
|
+
prettier: "^3.5.3",
|
|
2161
|
+
tsup: "^8.4.0",
|
|
2162
|
+
typescript: "^5.8.3",
|
|
2163
|
+
vitest: "^3.1.1"
|
|
2164
|
+
},
|
|
2165
|
+
engines: {
|
|
2166
|
+
node: ">=22.0.0"
|
|
2167
|
+
},
|
|
2168
|
+
license: "MIT"
|
|
2169
|
+
};
|
|
2170
|
+
|
|
2171
|
+
// src/utils/version.ts
|
|
2172
|
+
var VERSION = package_default.version;
|
|
2173
|
+
|
|
2102
2174
|
// src/provider/registry.ts
|
|
2103
2175
|
var ProviderRegistry = class {
|
|
2104
2176
|
#factories = /* @__PURE__ */ new Map();
|
|
@@ -2658,7 +2730,7 @@ var Reflector = class {
|
|
|
2658
2730
|
const reflections = [];
|
|
2659
2731
|
for (const item of items) {
|
|
2660
2732
|
if (item.result.success) continue;
|
|
2661
|
-
const r = this.#ruleRepeatedFailure(item) ?? this.#ruleFileNotFound(item) ?? this.#rulePermissionDenied(item) ?? this.#ruleOutOfWriteRoot(item, ctx.writeRoots);
|
|
2733
|
+
const r = this.#ruleRepeatedFailure(item) ?? this.#ruleFileNotFound(item) ?? this.#ruleTextNotFound(item) ?? this.#rulePermissionDenied(item) ?? this.#ruleOutOfWriteRoot(item, ctx.writeRoots);
|
|
2662
2734
|
if (r) reflections.push(r);
|
|
2663
2735
|
if (reflections.length >= this.#maxReflections) break;
|
|
2664
2736
|
}
|
|
@@ -2734,6 +2806,26 @@ var Reflector = class {
|
|
|
2734
2806
|
hint: `\`${item.name}\` \u5931\u8D25\uFF1A\u6587\u4EF6\u4E0D\u5B58\u5728\u3002\u8BF7\u5148\u7528 \`ls\` / \`glob\` \u770B\u4E00\u4E0B\u76EE\u5F55\u7ED3\u6784\uFF0C\u6216\u786E\u8BA4\u8DEF\u5F84\u62FC\u5199\uFF08\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u89C1 system prompt\uFF09\u3002`
|
|
2735
2807
|
};
|
|
2736
2808
|
}
|
|
2809
|
+
/**
|
|
2810
|
+
* R2.5 文本未找到:edit_file / multi_edit 报 TEXT_NOT_FOUND 或 TEXT_MULTIPLE_MATCHES。
|
|
2811
|
+
*
|
|
2812
|
+
* 这是编辑工具最高频的失败。工具内部已对 CRLF 做归一化,仍报此错通常是
|
|
2813
|
+
* old_text 与当前文件内容不一致(缩进 / 已被改过 / 多次出现)。给一条明确
|
|
2814
|
+
* 的「重新读文件、逐字复制」指引,避免模型用同一份旧 old_text 反复重试。
|
|
2815
|
+
*
|
|
2816
|
+
* @pure 仅读入参
|
|
2817
|
+
*/
|
|
2818
|
+
#ruleTextNotFound(item) {
|
|
2819
|
+
const isTextErr = item.result.error === "TEXT_NOT_FOUND" || item.result.error === "TEXT_MULTIPLE_MATCHES";
|
|
2820
|
+
if (!isTextErr) return null;
|
|
2821
|
+
const multiple = item.result.error === "TEXT_MULTIPLE_MATCHES";
|
|
2822
|
+
const hint = multiple ? `\`${item.name}\`\uFF1Aold_text \u5728\u6587\u4EF6\u4E2D\u51FA\u73B0\u591A\u6B21\u3002\u8BF7\u8865\u5145\u4E0A\u4E0B\u6587\u8BA9 old_text \u552F\u4E00\uFF0C\u6216\u6539\u7528 multi_edit \u7684 replaceAll\u3002` : `\`${item.name}\`\uFF1A\u672A\u627E\u5230 old_text\u3002\u8BF7\u91CD\u65B0 \`read_file\` \u770B\u5F53\u524D\u5185\u5BB9\uFF0C\u9010\u5B57\u590D\u5236\u8981\u66FF\u6362\u7684\u7247\u6BB5\uFF08\u6CE8\u610F\u7F29\u8FDB\u4E0E\u7A7A\u683C\uFF09\uFF1B\u884C\u5C3E\u5DF2\u505A CRLF \u5F52\u4E00\u5316\uFF0C\u65E0\u9700\u624B\u5199 \\r\\n\u3002`;
|
|
2823
|
+
return {
|
|
2824
|
+
category: "text_not_found",
|
|
2825
|
+
toolName: item.name,
|
|
2826
|
+
hint
|
|
2827
|
+
};
|
|
2828
|
+
}
|
|
2737
2829
|
/**
|
|
2738
2830
|
* R3 权限拒绝:GATE_DENIED 错误码 或 data 含 EACCES / permission / denied(不区分大小写)。
|
|
2739
2831
|
*
|
|
@@ -2751,13 +2843,19 @@ var Reflector = class {
|
|
|
2751
2843
|
};
|
|
2752
2844
|
}
|
|
2753
2845
|
/**
|
|
2754
|
-
* R4 写根外:kind ∈ Edit/Delete/Move
|
|
2846
|
+
* R4 写根外:kind ∈ Edit/Delete/Move 且错误码为 OUTSIDE_WRITE_ROOTS。
|
|
2847
|
+
*
|
|
2848
|
+
* 仅在工具本身明确报「路径超出写根」时才命中。旧实现只要写类工具失败就
|
|
2849
|
+
* 触发,会把 TEXT_NOT_FOUND / EXECUTION_ERROR 等误报为「写根外」,注入
|
|
2850
|
+
* 误导性提示(见会话日志 e65f0205 round 13:edit_file 因 CRLF 失配返回
|
|
2851
|
+
* TEXT_NOT_FOUND,却被反射为 out_of_write_root)。
|
|
2755
2852
|
*
|
|
2756
2853
|
* @pure 仅读入参
|
|
2757
2854
|
*/
|
|
2758
2855
|
#ruleOutOfWriteRoot(item, writeRoots) {
|
|
2759
2856
|
const isWriteKind = item.kind === "edit" /* Edit */ || item.kind === "delete" /* Delete */ || item.kind === "move" /* Move */;
|
|
2760
2857
|
if (!isWriteKind) return null;
|
|
2858
|
+
if (item.result.error !== "OUTSIDE_WRITE_ROOTS") return null;
|
|
2761
2859
|
const primary = writeRoots[0] ?? "<\u672A\u914D\u7F6E>";
|
|
2762
2860
|
return {
|
|
2763
2861
|
category: "out_of_write_root",
|
|
@@ -3929,7 +4027,7 @@ var Session = class _Session {
|
|
|
3929
4027
|
};
|
|
3930
4028
|
});
|
|
3931
4029
|
for (const item of results.items) {
|
|
3932
|
-
const todoSnapshot = item.name.startsWith("todo_") && this.#todoList ? this.#todoList.items : void 0;
|
|
4030
|
+
const todoSnapshot = item.name.startsWith("todo_") && this.#todoList ? this.#todoList.items.map((it) => ({ ...it })) : void 0;
|
|
3933
4031
|
yield {
|
|
3934
4032
|
type: "tool_result",
|
|
3935
4033
|
name: item.name,
|
|
@@ -4335,8 +4433,13 @@ var DEFAULT_TIMEOUT_MS = 3e4;
|
|
|
4335
4433
|
var DEFAULT_MAX_OUTPUT_LENGTH = 5e4;
|
|
4336
4434
|
var DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
4337
4435
|
var isWindows = process2.platform === "win32";
|
|
4436
|
+
function stripMentionPrefix(inputPath) {
|
|
4437
|
+
if (inputPath.startsWith("@")) return inputPath.slice(1);
|
|
4438
|
+
return inputPath;
|
|
4439
|
+
}
|
|
4338
4440
|
function resolvePath(inputPath, cwd) {
|
|
4339
|
-
const
|
|
4441
|
+
const stripped = stripMentionPrefix(inputPath);
|
|
4442
|
+
const resolved = isAbsolute(stripped) ? stripped : resolve(cwd, stripped);
|
|
4340
4443
|
return resolve(resolved);
|
|
4341
4444
|
}
|
|
4342
4445
|
async function realPath(target) {
|
|
@@ -4732,6 +4835,10 @@ function detectEol(text) {
|
|
|
4732
4835
|
function hasTrailingNewline(text) {
|
|
4733
4836
|
return text.endsWith("\n") || text.endsWith("\r\n");
|
|
4734
4837
|
}
|
|
4838
|
+
function toLf(text) {
|
|
4839
|
+
if (!text.includes("\r")) return text;
|
|
4840
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
4841
|
+
}
|
|
4735
4842
|
function normalizeEol(originalContent, newContent) {
|
|
4736
4843
|
const targetEol = detectEol(originalContent);
|
|
4737
4844
|
const lines = newContent.replace(/\r\n/g, "\n").split("\n");
|
|
@@ -4823,7 +4930,7 @@ var readFileTool = {
|
|
|
4823
4930
|
}
|
|
4824
4931
|
}
|
|
4825
4932
|
const content = await readFile5(filePath, "utf-8");
|
|
4826
|
-
const lines = content.split("\n");
|
|
4933
|
+
const lines = toLf(content).split("\n");
|
|
4827
4934
|
if (lines.length > 0 && lines[lines.length - 1] === "" && content.endsWith("\n")) {
|
|
4828
4935
|
lines.pop();
|
|
4829
4936
|
}
|
|
@@ -4931,6 +5038,7 @@ var writeFileTool = {
|
|
|
4931
5038
|
|
|
4932
5039
|
// src/tool/builtins/edit-file.ts
|
|
4933
5040
|
import { readFile as readFile7 } from "fs/promises";
|
|
5041
|
+
import { writeFile as writeFile5 } from "fs/promises";
|
|
4934
5042
|
import { basename as basename3 } from "path";
|
|
4935
5043
|
var editFileTool = {
|
|
4936
5044
|
name: "edit_file",
|
|
@@ -4974,7 +5082,9 @@ var editFileTool = {
|
|
|
4974
5082
|
}
|
|
4975
5083
|
try {
|
|
4976
5084
|
const content = await readFile7(filePath, "utf-8");
|
|
4977
|
-
const
|
|
5085
|
+
const contentN = toLf(content);
|
|
5086
|
+
const oldTextN = toLf(args.old_text);
|
|
5087
|
+
const firstIndex = contentN.indexOf(oldTextN);
|
|
4978
5088
|
if (firstIndex === -1) {
|
|
4979
5089
|
return {
|
|
4980
5090
|
success: false,
|
|
@@ -4982,7 +5092,7 @@ var editFileTool = {
|
|
|
4982
5092
|
error: "TEXT_NOT_FOUND"
|
|
4983
5093
|
};
|
|
4984
5094
|
}
|
|
4985
|
-
const secondIndex =
|
|
5095
|
+
const secondIndex = contentN.indexOf(oldTextN, firstIndex + 1);
|
|
4986
5096
|
if (secondIndex !== -1) {
|
|
4987
5097
|
return {
|
|
4988
5098
|
success: false,
|
|
@@ -4990,14 +5100,15 @@ var editFileTool = {
|
|
|
4990
5100
|
error: "TEXT_MULTIPLE_MATCHES"
|
|
4991
5101
|
};
|
|
4992
5102
|
}
|
|
4993
|
-
const
|
|
4994
|
-
|
|
4995
|
-
|
|
5103
|
+
const newContentN = contentN.slice(0, firstIndex) + toLf(args.new_text) + contentN.slice(firstIndex + oldTextN.length);
|
|
5104
|
+
const writtenContent = normalizeEol(content, newContentN);
|
|
5105
|
+
await writeFile5(filePath, writtenContent, "utf-8");
|
|
5106
|
+
const diff = computeFileDiff(content, writtenContent, filePath);
|
|
4996
5107
|
diff.existedBefore = true;
|
|
4997
|
-
const beforeText =
|
|
5108
|
+
const beforeText = contentN.slice(0, firstIndex);
|
|
4998
5109
|
const startLine = beforeText.split("\n").length;
|
|
4999
|
-
const oldLines =
|
|
5000
|
-
const newLines = args.new_text.split("\n").length;
|
|
5110
|
+
const oldLines = oldTextN.split("\n").length;
|
|
5111
|
+
const newLines = toLf(args.new_text).split("\n").length;
|
|
5001
5112
|
const diffSummary = `+${diff.additions} -${diff.deletions}`;
|
|
5002
5113
|
const summary = `\u{1F4DD} \u4FEE\u6539: ${basename3(filePath)} (+${diff.additions} -${diff.deletions})`;
|
|
5003
5114
|
return {
|
|
@@ -5022,6 +5133,7 @@ ${oldLines} \u884C \u2192 ${newLines} \u884C
|
|
|
5022
5133
|
|
|
5023
5134
|
// src/tool/builtins/multi-edit.ts
|
|
5024
5135
|
import { readFile as readFile8 } from "fs/promises";
|
|
5136
|
+
import { writeFile as writeFile6 } from "fs/promises";
|
|
5025
5137
|
import { basename as basename4 } from "path";
|
|
5026
5138
|
var multiEditTool = {
|
|
5027
5139
|
name: "multi_edit",
|
|
@@ -5068,7 +5180,7 @@ var multiEditTool = {
|
|
|
5068
5180
|
}
|
|
5069
5181
|
try {
|
|
5070
5182
|
const originalContent = await readFile8(filePath, "utf-8");
|
|
5071
|
-
let currentContent = originalContent;
|
|
5183
|
+
let currentContent = toLf(originalContent);
|
|
5072
5184
|
for (let idx = 0; idx < args.edits.length; idx++) {
|
|
5073
5185
|
const step = args.edits[idx];
|
|
5074
5186
|
if (typeof step.oldText !== "string") {
|
|
@@ -5078,10 +5190,19 @@ var multiEditTool = {
|
|
|
5078
5190
|
error: "INVALID_STEP_ARGS"
|
|
5079
5191
|
};
|
|
5080
5192
|
}
|
|
5193
|
+
if (typeof step.newText !== "string") {
|
|
5194
|
+
return {
|
|
5195
|
+
success: false,
|
|
5196
|
+
data: `\u7B2C ${idx + 1} \u6B65\uFF1A\u7F3A\u5C11\u6709\u6548\u7684 newText`,
|
|
5197
|
+
error: "INVALID_STEP_ARGS"
|
|
5198
|
+
};
|
|
5199
|
+
}
|
|
5200
|
+
const oldTextN = toLf(step.oldText);
|
|
5201
|
+
const newTextN = toLf(step.newText);
|
|
5081
5202
|
if (step.replaceAll) {
|
|
5082
5203
|
let count = 0;
|
|
5083
5204
|
let pos = -1;
|
|
5084
|
-
while ((pos = currentContent.indexOf(
|
|
5205
|
+
while ((pos = currentContent.indexOf(oldTextN, pos + 1)) !== -1) {
|
|
5085
5206
|
count++;
|
|
5086
5207
|
}
|
|
5087
5208
|
if (count === 0) {
|
|
@@ -5091,9 +5212,9 @@ var multiEditTool = {
|
|
|
5091
5212
|
error: "TEXT_NOT_FOUND"
|
|
5092
5213
|
};
|
|
5093
5214
|
}
|
|
5094
|
-
currentContent = currentContent.split(
|
|
5215
|
+
currentContent = currentContent.split(oldTextN).join(newTextN);
|
|
5095
5216
|
} else {
|
|
5096
|
-
const firstIdx = currentContent.indexOf(
|
|
5217
|
+
const firstIdx = currentContent.indexOf(oldTextN);
|
|
5097
5218
|
if (firstIdx === -1) {
|
|
5098
5219
|
return {
|
|
5099
5220
|
success: false,
|
|
@@ -5101,7 +5222,7 @@ var multiEditTool = {
|
|
|
5101
5222
|
error: "TEXT_NOT_FOUND"
|
|
5102
5223
|
};
|
|
5103
5224
|
}
|
|
5104
|
-
const secondIdx = currentContent.indexOf(
|
|
5225
|
+
const secondIdx = currentContent.indexOf(oldTextN, firstIdx + 1);
|
|
5105
5226
|
if (secondIdx !== -1) {
|
|
5106
5227
|
return {
|
|
5107
5228
|
success: false,
|
|
@@ -5109,11 +5230,12 @@ var multiEditTool = {
|
|
|
5109
5230
|
error: "TEXT_MULTIPLE_MATCHES"
|
|
5110
5231
|
};
|
|
5111
5232
|
}
|
|
5112
|
-
currentContent = currentContent.
|
|
5233
|
+
currentContent = currentContent.slice(0, firstIdx) + newTextN + currentContent.slice(firstIdx + oldTextN.length);
|
|
5113
5234
|
}
|
|
5114
5235
|
}
|
|
5115
|
-
|
|
5116
|
-
|
|
5236
|
+
const writtenContent = normalizeEol(originalContent, currentContent);
|
|
5237
|
+
await writeFile6(filePath, writtenContent, "utf-8");
|
|
5238
|
+
const diff = computeFileDiff(originalContent, writtenContent, filePath);
|
|
5117
5239
|
diff.existedBefore = true;
|
|
5118
5240
|
return {
|
|
5119
5241
|
success: true,
|
|
@@ -5136,11 +5258,13 @@ var multiEditTool = {
|
|
|
5136
5258
|
|
|
5137
5259
|
// src/tool/builtins/delete-range.ts
|
|
5138
5260
|
import { readFile as readFile9 } from "fs/promises";
|
|
5261
|
+
import { writeFile as writeFile7 } from "fs/promises";
|
|
5139
5262
|
import { basename as basename5 } from "path";
|
|
5140
5263
|
function findUniqueLine(lines, anchor, label) {
|
|
5264
|
+
const anchorN = toLf(anchor);
|
|
5141
5265
|
const matches = [];
|
|
5142
5266
|
for (let i = 0; i < lines.length; i++) {
|
|
5143
|
-
if (lines[i] ===
|
|
5267
|
+
if (toLf(lines[i]) === anchorN) {
|
|
5144
5268
|
matches.push(i);
|
|
5145
5269
|
}
|
|
5146
5270
|
}
|
|
@@ -5199,7 +5323,7 @@ var deleteRangeTool = {
|
|
|
5199
5323
|
}
|
|
5200
5324
|
try {
|
|
5201
5325
|
const content = await readFile9(filePath, "utf-8");
|
|
5202
|
-
const lines = content.split("\n");
|
|
5326
|
+
const lines = toLf(content).split("\n");
|
|
5203
5327
|
const startResult = findUniqueLine(lines, args.startAnchor, "start_anchor");
|
|
5204
5328
|
if ("error" in startResult) {
|
|
5205
5329
|
return { success: false, data: startResult.error, error: "ANCHOR_NOT_FOUND" };
|
|
@@ -5227,9 +5351,10 @@ var deleteRangeTool = {
|
|
|
5227
5351
|
};
|
|
5228
5352
|
}
|
|
5229
5353
|
const newLines = [...lines.slice(0, rangeStart), ...lines.slice(rangeEnd + 1)];
|
|
5230
|
-
const
|
|
5231
|
-
|
|
5232
|
-
|
|
5354
|
+
const newContentN = newLines.join("\n");
|
|
5355
|
+
const writtenContent = normalizeEol(content, newContentN);
|
|
5356
|
+
await writeFile7(filePath, writtenContent, "utf-8");
|
|
5357
|
+
const diff = computeFileDiff(content, writtenContent, filePath);
|
|
5233
5358
|
diff.existedBefore = true;
|
|
5234
5359
|
const deletedLines = rangeEnd - rangeStart + 1;
|
|
5235
5360
|
const summary = `\u{1F4DD} \u4FEE\u6539: ${basename5(filePath)} (\u5220 ${deletedLines} \u884C, +${diff.additions} -${diff.deletions})`;
|
|
@@ -5425,7 +5550,8 @@ var globTool = {
|
|
|
5425
5550
|
if (!args?.pattern || typeof args.pattern !== "string") {
|
|
5426
5551
|
return { success: false, data: "\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570 pattern", error: "INVALID_ARGS" };
|
|
5427
5552
|
}
|
|
5428
|
-
const
|
|
5553
|
+
const dir = args.directory ? stripMentionPrefix(args.directory) : void 0;
|
|
5554
|
+
const searchDir = dir ? isAbsolute2(dir) ? dir : join7(ctx.cwd, dir) : ctx.cwd;
|
|
5429
5555
|
const regex = globToRegex(args.pattern);
|
|
5430
5556
|
try {
|
|
5431
5557
|
const dirStat = await stat2(searchDir);
|
|
@@ -5526,7 +5652,8 @@ var grepTool = {
|
|
|
5526
5652
|
if (!args?.pattern || typeof args.pattern !== "string") {
|
|
5527
5653
|
return { success: false, data: "\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570 pattern", error: "INVALID_ARGS" };
|
|
5528
5654
|
}
|
|
5529
|
-
const
|
|
5655
|
+
const dir = args.directory ? stripMentionPrefix(args.directory) : void 0;
|
|
5656
|
+
const searchDir = dir ? isAbsolute3(dir) ? dir : join8(ctx.cwd, dir) : ctx.cwd;
|
|
5530
5657
|
const maxFiles = args.max_files ?? 200;
|
|
5531
5658
|
try {
|
|
5532
5659
|
const flags = args.case_sensitive ? "g" : "gi";
|
|
@@ -5836,6 +5963,11 @@ var PHASE_CONFIG = {
|
|
|
5836
5963
|
function isFileMutatingTool(name) {
|
|
5837
5964
|
return name === "edit_file" || name === "write_file" || name === "multi_edit" || name === "delete_range";
|
|
5838
5965
|
}
|
|
5966
|
+
function filterTodoToolCalls(calls) {
|
|
5967
|
+
if (!calls) return void 0;
|
|
5968
|
+
const filtered = calls.filter((tc) => !tc.name.startsWith("todo_"));
|
|
5969
|
+
return filtered.length > 0 ? filtered : void 0;
|
|
5970
|
+
}
|
|
5839
5971
|
var commandRegistry = /* @__PURE__ */ new Map();
|
|
5840
5972
|
function registerCommand(name, cmd) {
|
|
5841
5973
|
commandRegistry.set(name, cmd);
|
|
@@ -5859,7 +5991,7 @@ registerCommand("/help", {
|
|
|
5859
5991
|
registerCommand("/clear", { desc: "\u6E05\u7A7A\u5BF9\u8BDD\u5386\u53F2", handler: () => ({ kind: "clear" }) });
|
|
5860
5992
|
registerCommand("/version", {
|
|
5861
5993
|
desc: "\u663E\u793A\u7248\u672C\u4FE1\u606F",
|
|
5862
|
-
handler: () => ({ kind: "text", content:
|
|
5994
|
+
handler: () => ({ kind: "text", content: `dskcode v${VERSION}` })
|
|
5863
5995
|
});
|
|
5864
5996
|
registerCommand("/model", {
|
|
5865
5997
|
desc: "\u5207\u6362\u6A21\u578B",
|
|
@@ -5957,6 +6089,8 @@ function ChatSession({
|
|
|
5957
6089
|
const [_streamingModel, setStreamingModel] = useState4(void 0);
|
|
5958
6090
|
const [streamError, setStreamError] = useState4(void 0);
|
|
5959
6091
|
const [todoSnapshot, setTodoSnapshot] = useState4([]);
|
|
6092
|
+
const [todoPanelVisible, setTodoPanelVisible] = useState4(true);
|
|
6093
|
+
const todoHideTimerRef = useRef3(null);
|
|
5960
6094
|
const [sessionMode, setSessionMode] = useState4("code");
|
|
5961
6095
|
const [thinkingEnabled, setThinkingEnabled] = useState4(true);
|
|
5962
6096
|
const [thinkingEffort, setThinkingEffort] = useState4("high");
|
|
@@ -6014,6 +6148,20 @@ function ChatSession({
|
|
|
6014
6148
|
}
|
|
6015
6149
|
};
|
|
6016
6150
|
}, []);
|
|
6151
|
+
useEffect4(() => {
|
|
6152
|
+
if (todoHideTimerRef.current) {
|
|
6153
|
+
clearTimeout(todoHideTimerRef.current);
|
|
6154
|
+
todoHideTimerRef.current = null;
|
|
6155
|
+
}
|
|
6156
|
+
if (todoSnapshot.length === 0) {
|
|
6157
|
+
setTodoPanelVisible(false);
|
|
6158
|
+
return;
|
|
6159
|
+
}
|
|
6160
|
+
const hasUnfinished = todoSnapshot.some(
|
|
6161
|
+
(it) => it.status === "pending" || it.status === "running" || it.status === "failed"
|
|
6162
|
+
);
|
|
6163
|
+
setTodoPanelVisible(hasUnfinished);
|
|
6164
|
+
}, [todoSnapshot]);
|
|
6017
6165
|
const getFilteredSkills = useCallback2(
|
|
6018
6166
|
(value) => {
|
|
6019
6167
|
const match = value.match(/(?:^|\s)\/([^/]*)$/);
|
|
@@ -6055,7 +6203,7 @@ function ChatSession({
|
|
|
6055
6203
|
content: m.content,
|
|
6056
6204
|
assistantDetail: {
|
|
6057
6205
|
content: m.content,
|
|
6058
|
-
toolCalls: m.toolCalls
|
|
6206
|
+
toolCalls: filterTodoToolCalls(m.toolCalls)
|
|
6059
6207
|
}
|
|
6060
6208
|
});
|
|
6061
6209
|
} else if (m.role === "tool") {
|
|
@@ -6664,6 +6812,7 @@ function ChatSession({
|
|
|
6664
6812
|
clearTimeout(rewindHintTimerRef.current);
|
|
6665
6813
|
rewindHintTimerRef.current = null;
|
|
6666
6814
|
}
|
|
6815
|
+
setTodoSnapshot([]);
|
|
6667
6816
|
const session = sessionRef.current;
|
|
6668
6817
|
const abortController = new AbortController();
|
|
6669
6818
|
abortRef.current = abortController;
|
|
@@ -6721,7 +6870,14 @@ function ChatSession({
|
|
|
6721
6870
|
currentToolCallsRef.current = [];
|
|
6722
6871
|
const r = event.result;
|
|
6723
6872
|
if (event.name.startsWith("todo_") && event.todoSnapshot) {
|
|
6724
|
-
|
|
6873
|
+
const allTerminated = event.todoSnapshot.length > 0 && event.todoSnapshot.every(
|
|
6874
|
+
(it) => it.status === "done" || it.status === "failed" || it.status === "skipped"
|
|
6875
|
+
);
|
|
6876
|
+
if (allTerminated) {
|
|
6877
|
+
setTodoSnapshot([]);
|
|
6878
|
+
} else {
|
|
6879
|
+
setTodoSnapshot(event.todoSnapshot);
|
|
6880
|
+
}
|
|
6725
6881
|
} else {
|
|
6726
6882
|
const line = r.success ? r.summary ?? `\u2705 ${event.name}: ${r.data.slice(0, 500)}${r.data.length > 500 ? "..." : ""}` : `\u274C ${event.name}: ${r.error ?? "\u6267\u884C\u5931\u8D25"}`;
|
|
6727
6883
|
setDisplayMessages((prev) => [
|
|
@@ -6769,7 +6925,7 @@ function ChatSession({
|
|
|
6769
6925
|
abortRef.current = null;
|
|
6770
6926
|
const finContent = currentContentRef.current;
|
|
6771
6927
|
const finReasoning = currentReasoningRef.current.map((s) => s.trim()).filter((s) => s.length > 0);
|
|
6772
|
-
const finToolCalls = currentToolCallsRef.current
|
|
6928
|
+
const finToolCalls = filterTodoToolCalls(currentToolCallsRef.current);
|
|
6773
6929
|
const finStreamError = streamErrorRef.current;
|
|
6774
6930
|
if (finContent || finToolCalls || finStreamError) {
|
|
6775
6931
|
const completed = {
|
|
@@ -6826,10 +6982,16 @@ function ChatSession({
|
|
|
6826
6982
|
}, [isStreaming, externalCostTracker]);
|
|
6827
6983
|
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: [
|
|
6828
6984
|
!hasConversationStarted && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "row", marginBottom: 1, children: [
|
|
6829
|
-
/* @__PURE__ */
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6985
|
+
/* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginRight: 4, children: [
|
|
6986
|
+
LOGO_LINES.map((line, i) => {
|
|
6987
|
+
const colorIndex = (i + offset) % CYBER_PALETTE.length;
|
|
6988
|
+
return /* @__PURE__ */ jsx10(Box10, { children: /* @__PURE__ */ jsx10(Text11, { bold: true, color: CYBER_PALETTE[colorIndex], children: line }) }, i);
|
|
6989
|
+
}),
|
|
6990
|
+
/* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsxs10(Text11, { color: "#808080", children: [
|
|
6991
|
+
" \u{1F4E6} v",
|
|
6992
|
+
VERSION
|
|
6993
|
+
] }) })
|
|
6994
|
+
] }),
|
|
6833
6995
|
/* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", justifyContent: "center", children: [
|
|
6834
6996
|
/* @__PURE__ */ jsxs10(Text11, { color: "#00ff41", children: [
|
|
6835
6997
|
" \u2714 ",
|
|
@@ -6944,7 +7106,7 @@ function ChatSession({
|
|
|
6944
7106
|
streamError
|
|
6945
7107
|
] }) })
|
|
6946
7108
|
] }),
|
|
6947
|
-
todoSnapshot.length > 0 && /* @__PURE__ */ jsx10(TodoListPanel, { items: todoSnapshot }),
|
|
7109
|
+
todoPanelVisible && todoSnapshot.length > 0 && /* @__PURE__ */ jsx10(TodoListPanel, { items: todoSnapshot }),
|
|
6948
7110
|
selectingModel ? /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
6949
7111
|
/* @__PURE__ */ jsx10(Text11, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }),
|
|
6950
7112
|
/* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, children: [
|
|
@@ -8708,7 +8870,7 @@ var SUBCOMMANDS = ["chat", "run", "setup", "init", "completion", "game", "stock"
|
|
|
8708
8870
|
function createCli() {
|
|
8709
8871
|
const program2 = new Command();
|
|
8710
8872
|
program2.exitOverride();
|
|
8711
|
-
program2.name("dskcode").description("\u57FA\u4E8E DeepSeek \u7684 AI \u7F16\u7A0B\u52A9\u624B\u7EC8\u7AEF\u5DE5\u5177").version(
|
|
8873
|
+
program2.name("dskcode").description("\u57FA\u4E8E DeepSeek \u7684 AI \u7F16\u7A0B\u52A9\u624B\u7EC8\u7AEF\u5DE5\u5177").version(VERSION, "-V, --version", "\u663E\u793A\u7248\u672C\u53F7").option("--verbose", "\u5F00\u542F\u8BE6\u7EC6\u65E5\u5FD7\u8F93\u51FA").option("--config <path>", "\u6307\u5B9A\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84");
|
|
8712
8874
|
program2.helpInformation = () => customHelp(program2);
|
|
8713
8875
|
program2.hook("preAction", async (thisCommand, actionCommand) => {
|
|
8714
8876
|
const ctx = await loadConfigMiddleware.call(thisCommand);
|