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