deepseeker-code 1.0.52 → 1.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +1571 -736
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -181,6 +181,9 @@ ${dim} \u8FD0\u884C npm i -g deepseeker-code@latest \u66F4\u65B0${reset}
|
|
|
181
181
|
sessionsPrompt: "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u8F7D\u5165 \xB7 Esc \u53D6\u6D88",
|
|
182
182
|
noHistory: "\uFF08\u6682\u65E0\u5386\u53F2\u4F1A\u8BDD\uFF09",
|
|
183
183
|
sessionLoaded: (id) => `\u5DF2\u8F7D\u5165\u4F1A\u8BDD ${id}\uFF08\u7EE7\u7EED\u5BF9\u8BDD\u5C06\u7EED\u63A5\u6B64\u4F1A\u8BDD\uFF09`,
|
|
184
|
+
cmdNew: "\u5F00\u542F\u65B0\u4F1A\u8BDD\uFF08\u6E05\u5C4F\uFF1B\u65E7\u4F1A\u8BDD\u4FDD\u7559\uFF0C/sessions \u53EF\u627E\u56DE\uFF09",
|
|
185
|
+
sessionNew: (id) => `\u{1F195} \u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD ${id}\uFF08\u65E7\u4F1A\u8BDD\u5B8C\u6574\u4FDD\u7559\uFF0C/sessions \u53EF\u627E\u56DE\uFF09`,
|
|
186
|
+
sessionNewBusy: "\u751F\u6210\u4E2D\u2014\u2014\u5148 Esc/Ctrl+G \u4E2D\u6B62\u5F53\u524D\u56DE\u590D\uFF0C\u518D\u5F00\u65B0\u4F1A\u8BDD",
|
|
184
187
|
cmdFork: "\u4ECE\u5F53\u524D\u4F1A\u8BDD\u7684\u67D0\u8F6E\u56DE\u590D\u5904\u5206\u53C9\u51FA\u65B0\u4F1A\u8BDD",
|
|
185
188
|
forkTitle: "\u{1F33F} \u5206\u53C9\u5F53\u524D\u4F1A\u8BDD\uFF08\u2191\u2193 \u9009\u68C0\u67E5\u70B9 \xB7 Enter \u5206\u53C9\uFF09",
|
|
186
189
|
forkPrompt: "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u5206\u53C9 \xB7 Esc \u53D6\u6D88",
|
|
@@ -229,6 +232,7 @@ DeepSeeker-Code \u5C06\u5728\u6B64\u76EE\u5F55\u8BFB\u53D6\u3001\u7F16\u8F91\u54
|
|
|
229
232
|
`/thinking [off|high|max] \u2014 \u5207\u6362\u601D\u8003\u7B49\u7EA7\uFF08\u5F53\u524D ${thinking}\uFF09`,
|
|
230
233
|
`/lang [zh|en] \u2014 \u5207\u6362\u754C\u9762\u8BED\u8A00\uFF08\u5F53\u524D ${locale2}\uFF09`,
|
|
231
234
|
"/sessions \u2014 \u9009\u62E9\u5E76\u8F7D\u5165\u5386\u53F2\u4F1A\u8BDD\uFF08\u7EED\u63A5\u5BF9\u8BDD\uFF09",
|
|
235
|
+
"/new \u2014 \u5F00\u542F\u65B0\u4F1A\u8BDD\uFF08\u65E7\u4F1A\u8BDD\u4FDD\u7559\uFF0C/sessions \u53EF\u627E\u56DE\uFF09",
|
|
232
236
|
"/fork \u2014 \u4ECE\u5F53\u524D\u4F1A\u8BDD\u7684\u67D0\u8F6E\u56DE\u590D\u5904\u5206\u53C9\u51FA\u65B0\u4F1A\u8BDD",
|
|
233
237
|
"/trust \u2014 \u7BA1\u7406\u5DF2\u4FE1\u4EFB\u76EE\u5F55\uFF08\u9879\u76EE\u7EA7 hooks/skills \u7B49\u4EC5\u5728\u4FE1\u4EFB\u76EE\u5F55\u52A0\u8F7D\uFF1BCI \u7528 --trust \u663E\u5F0F\u4FE1\u4EFB\uFF09",
|
|
234
238
|
"Ctrl+C \u9000\u51FA \xB7 Esc \u4E2D\u6B62/\u6E05\u8F93\u5165 \xB7 Ctrl+G \u4E2D\u6B62 \xB7 Ctrl+T \u5C55\u5F00/\u6536\u8D77\u601D\u8003"
|
|
@@ -330,6 +334,9 @@ ${dim} Run npm i -g deepseeker-code@latest to update${reset}
|
|
|
330
334
|
sessionsPrompt: "\u2191\u2193 pick \xB7 Enter resume \xB7 Esc cancel",
|
|
331
335
|
noHistory: "(no past sessions)",
|
|
332
336
|
sessionLoaded: (id) => `Resumed session ${id} (new messages continue it)`,
|
|
337
|
+
cmdNew: "Start a new session (clears screen; old ones remain via /sessions)",
|
|
338
|
+
sessionNew: (id) => `\u{1F195} New session ${id} started (old sessions kept, resume via /sessions)`,
|
|
339
|
+
sessionNewBusy: "Busy \u2014 abort the current reply first (Esc/Ctrl+G), then start a new session",
|
|
333
340
|
cmdFork: "Fork the current session from a past round",
|
|
334
341
|
forkTitle: "\u{1F33F} Fork current session (\u2191\u2193 to pick \xB7 Enter to fork)",
|
|
335
342
|
forkPrompt: "\u2191\u2193 pick \xB7 Enter fork \xB7 Esc cancel",
|
|
@@ -378,6 +385,7 @@ DeepSeeker-Code will read, edit, and execute files here.`,
|
|
|
378
385
|
`/thinking [off|high|max] \u2014 Switch thinking level (current ${thinking})`,
|
|
379
386
|
`/lang [zh|en] \u2014 Switch interface language (current ${locale2})`,
|
|
380
387
|
"/sessions \u2014 Pick a past session to resume",
|
|
388
|
+
"/new \u2014 Start a new session (old ones remain via /sessions)",
|
|
381
389
|
"/fork \u2014 Fork the current session from a past round",
|
|
382
390
|
"/trust \u2014 Manage trusted dirs (project hooks/skills load only when trusted; CI uses --trust)",
|
|
383
391
|
"Ctrl+C exit \xB7 Esc abort/clear input \xB7 Ctrl+G abort \xB7 Ctrl+T toggle thinking"
|
|
@@ -399,7 +407,7 @@ DeepSeeker-Code will read, edit, and execute files here.`,
|
|
|
399
407
|
S = new Proxy({}, {
|
|
400
408
|
get: (_t, k) => typeof k === "string" ? STRINGS[locale][k] : void 0
|
|
401
409
|
});
|
|
402
|
-
LOCAL_COMMAND_NAMES = ["help", "status", "plan", "auto", "model", "switch", "thinking", "lang", "output-style", "sessions", "fork", "usage", "context", "permissions", "mcp", "hooks", "trust", "debug", "clear", "exit"];
|
|
410
|
+
LOCAL_COMMAND_NAMES = ["help", "status", "plan", "auto", "model", "switch", "thinking", "lang", "output-style", "new", "sessions", "fork", "usage", "context", "permissions", "mcp", "hooks", "trust", "debug", "clear", "exit"];
|
|
403
411
|
}
|
|
404
412
|
});
|
|
405
413
|
|
|
@@ -498,7 +506,7 @@ var init_config = __esm({
|
|
|
498
506
|
* 最终聚合再受工具 maxOutputCharacters 兜底。 */
|
|
499
507
|
workflowPerStepChars: 6e3,
|
|
500
508
|
/** ★ P0-A 计划模式强制位置:'runtime'(默认)= 工具表全会话恒定(两态统一 appendPlanControlTools),
|
|
501
|
-
* 计划期写工具由 processToolCall
|
|
509
|
+
* 计划期写工具由 processToolCall 执行层按工具声明 planAllowed 拒绝——保 DeepSeek 前缀缓存
|
|
502
510
|
* (tools 参数序列化在请求头部,计划模式裁表翻转 = 全会话历史 re-prefill 两次);
|
|
503
511
|
* 'schema' = 旧路径(计划期裁成只读白名单子表)。env DEEP_SEEK_PLAN_ENFORCEMENT=schema 回退。 */
|
|
504
512
|
planEnforcement: process.env.DEEP_SEEK_PLAN_ENFORCEMENT === "schema" ? "schema" : "runtime",
|
|
@@ -783,7 +791,7 @@ var init_trust = __esm({
|
|
|
783
791
|
});
|
|
784
792
|
|
|
785
793
|
// ../core/src/tool/type.ts
|
|
786
|
-
var MAX_AGENT_DEPTH, ToolSafetyLevel, ToolExecutionResultStatus;
|
|
794
|
+
var MAX_AGENT_DEPTH, ToolSafetyLevel, ToolExecutionResultStatus, asToolFailure, toolFailure;
|
|
787
795
|
var init_type = __esm({
|
|
788
796
|
"../core/src/tool/type.ts"() {
|
|
789
797
|
"use strict";
|
|
@@ -797,10 +805,45 @@ var init_type = __esm({
|
|
|
797
805
|
ToolExecutionResultStatus = /* @__PURE__ */ ((ToolExecutionResultStatus2) => {
|
|
798
806
|
ToolExecutionResultStatus2["SUCCESS"] = "success";
|
|
799
807
|
ToolExecutionResultStatus2["FAILED"] = "failed";
|
|
800
|
-
ToolExecutionResultStatus2["TIMEOUT"] = "timeout";
|
|
801
|
-
ToolExecutionResultStatus2["ABORTED"] = "aborted";
|
|
802
808
|
return ToolExecutionResultStatus2;
|
|
803
809
|
})(ToolExecutionResultStatus || {});
|
|
810
|
+
asToolFailure = (content, errorCategory = "runtime") => ({ content, status: "failed", errorCategory });
|
|
811
|
+
toolFailure = (msg, errorCategory = "runtime") => asToolFailure(`\u274C ${msg}`, errorCategory);
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
|
|
815
|
+
// ../core/src/tool/argsValidator.ts
|
|
816
|
+
import { Ajv } from "ajv";
|
|
817
|
+
var ajv, compiled, validateToolArgs;
|
|
818
|
+
var init_argsValidator = __esm({
|
|
819
|
+
"../core/src/tool/argsValidator.ts"() {
|
|
820
|
+
"use strict";
|
|
821
|
+
ajv = new Ajv({
|
|
822
|
+
coerceTypes: true,
|
|
823
|
+
// 数字/布尔字符串化容错(就地修正 args)
|
|
824
|
+
strict: false,
|
|
825
|
+
// 手写 schema 可能含非严格关键字(注释性字段等),宽松编译防误伤
|
|
826
|
+
allErrors: false
|
|
827
|
+
// 首错即返:早退文案只报第一处,引导逐个修
|
|
828
|
+
});
|
|
829
|
+
compiled = /* @__PURE__ */ new WeakMap();
|
|
830
|
+
validateToolArgs = (schema, args) => {
|
|
831
|
+
let validate = compiled.get(schema);
|
|
832
|
+
if (!validate) {
|
|
833
|
+
try {
|
|
834
|
+
validate = ajv.compile(schema);
|
|
835
|
+
compiled.set(schema, validate);
|
|
836
|
+
} catch (e) {
|
|
837
|
+
console.warn(`\u26A0\uFE0F [argsValidator] schema \u7F16\u8BD1\u5931\u8D25\uFF08fail-open \u653E\u884C\uFF09: ${e?.message ?? e}`);
|
|
838
|
+
return { ok: true };
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
if (validate(args)) return { ok: true };
|
|
842
|
+
const err = validate.errors?.[0];
|
|
843
|
+
const where = err?.instancePath || "(\u9876\u5C42)";
|
|
844
|
+
const what = err?.message ?? "\u4E0D\u7B26\u5408\u5DE5\u5177 parameters schema";
|
|
845
|
+
return { ok: false, message: `${where} ${err?.keyword ? `[${err.keyword}] ` : ""}${what}` };
|
|
846
|
+
};
|
|
804
847
|
}
|
|
805
848
|
});
|
|
806
849
|
|
|
@@ -1095,7 +1138,7 @@ var init_visionCapability = __esm({
|
|
|
1095
1138
|
});
|
|
1096
1139
|
|
|
1097
1140
|
// ../core/src/session/contentParts.ts
|
|
1098
|
-
var MAX_IMAGE_BYTES, msgText, imageUrlsOf, hasImagePart, VISION_DEGRADE_NOTE, isVisionEnabled, estimateImageTokens, toWireUserContent, toIngestContents, replaceImageParts, collapseToText, degradeImagesForAux;
|
|
1141
|
+
var MAX_IMAGE_BYTES, msgText, imageUrlsOf, hasImagePart, VISION_DEGRADE_NOTE, isVisionEnabled, estimateImageTokens, toWireUserContent, toIngestContents, replaceImageParts, collapseToText, degradeImagesForAux, buildImageFollowUpParts;
|
|
1099
1142
|
var init_contentParts = __esm({
|
|
1100
1143
|
"../core/src/session/contentParts.ts"() {
|
|
1101
1144
|
"use strict";
|
|
@@ -1197,6 +1240,20 @@ ${paths.join("\n")}
|
|
|
1197
1240
|
return { ...m, content: text };
|
|
1198
1241
|
};
|
|
1199
1242
|
degradeImagesForAux = (m) => collapseToText(m, "[\u56FE\u7247\u5DF2\u5F52\u6863]");
|
|
1243
|
+
buildImageFollowUpParts = (images) => {
|
|
1244
|
+
const labels = images.map((img, i) => ` ${i + 1}. ${img.name || "image"}\uFF08${img.mime}\uFF09`).join("\n");
|
|
1245
|
+
return [
|
|
1246
|
+
{
|
|
1247
|
+
type: "text",
|
|
1248
|
+
text: `\uFF08\u7CFB\u7EDF\u6CE8\u5165\uFF1A\u4E0A\u4E00\u6761\u5DE5\u5177\u7ED3\u679C\u8BFB\u53D6\u4E86 ${images.length} \u5F20\u56FE\u7247\uFF0C\u9644\u4E8E\u672C\u6D88\u606F\u4F9B\u89C6\u89C9\u5206\u6790\u3002\u82E5\u770B\u4E0D\u6E05\u6216\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u8BF7\u544A\u77E5\u7528\u6237\u5F53\u524D\u6A21\u578B\u53EF\u80FD\u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\u3002\uFF09
|
|
1249
|
+
${labels}`
|
|
1250
|
+
},
|
|
1251
|
+
...images.map((img) => ({
|
|
1252
|
+
type: "image_url",
|
|
1253
|
+
image_url: { url: `data:${img.mime};base64,${img.base64}` }
|
|
1254
|
+
}))
|
|
1255
|
+
];
|
|
1256
|
+
};
|
|
1200
1257
|
}
|
|
1201
1258
|
});
|
|
1202
1259
|
|
|
@@ -1321,7 +1378,7 @@ var init_model = __esm({
|
|
|
1321
1378
|
});
|
|
1322
1379
|
|
|
1323
1380
|
// ../core/src/session/contextCore.ts
|
|
1324
|
-
var isCjkCodePoint, estimateTextTokens, estimateTokens, cleanMsg, groupUnits, splitUntils;
|
|
1381
|
+
var isCjkCodePoint, estimateTextTokens, computeMessageTokens, msgTokenCache, messageTokens, estimateTokens, cleanMsg, groupUnits, splitUntils;
|
|
1325
1382
|
var init_contextCore = __esm({
|
|
1326
1383
|
"../core/src/session/contextCore.ts"() {
|
|
1327
1384
|
"use strict";
|
|
@@ -1345,35 +1402,48 @@ var init_contextCore = __esm({
|
|
|
1345
1402
|
}
|
|
1346
1403
|
return cjk + Math.ceil(rest / divisor);
|
|
1347
1404
|
};
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
if (m.content) {
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1405
|
+
computeMessageTokens = (m) => {
|
|
1406
|
+
let pureText = "";
|
|
1407
|
+
let imageCount = 0;
|
|
1408
|
+
if (m.content) {
|
|
1409
|
+
if (typeof m.content === "string") {
|
|
1410
|
+
pureText += m.content;
|
|
1411
|
+
} else if (Array.isArray(m.content)) {
|
|
1412
|
+
pureText += msgText(m.content);
|
|
1413
|
+
imageCount += imageUrlsOf(m.content).length;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
if (m.tool_calls && Array.isArray(m.tool_calls)) {
|
|
1417
|
+
for (const call of m.tool_calls) {
|
|
1418
|
+
if (call.function) {
|
|
1419
|
+
pureText += ` ${call.function.name} ${call.function.arguments || ""}`;
|
|
1358
1420
|
}
|
|
1359
1421
|
}
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
const knownKeys = ["content", "tool_calls"];
|
|
1368
|
-
for (const key of Object.keys(m)) {
|
|
1369
|
-
if (!knownKeys.includes(key) && typeof m[key] === "string") {
|
|
1370
|
-
pureText += ` ${m[key]}`;
|
|
1371
|
-
}
|
|
1422
|
+
}
|
|
1423
|
+
const knownKeys = ["content", "tool_calls"];
|
|
1424
|
+
for (const key of Object.keys(m)) {
|
|
1425
|
+
if (!knownKeys.includes(key) && typeof m[key] === "string") {
|
|
1426
|
+
pureText += ` ${m[key]}`;
|
|
1372
1427
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1428
|
+
}
|
|
1429
|
+
const isStructured = m.role === "tool" || Array.isArray(m.tool_calls) && m.tool_calls.length > 0;
|
|
1430
|
+
const imagePrice = imageCount > 0 ? estimateImageTokens() : 0;
|
|
1431
|
+
const tokens = estimateTextTokens(pureText, isStructured ? 4 : 4.8) + imageCount * imagePrice + 4;
|
|
1432
|
+
return { tokens: isNaN(tokens) ? 0 : tokens, imageCount, imagePrice };
|
|
1433
|
+
};
|
|
1434
|
+
msgTokenCache = /* @__PURE__ */ new WeakMap();
|
|
1435
|
+
messageTokens = (m) => {
|
|
1436
|
+
const toolCalls = m.tool_calls;
|
|
1437
|
+
const cached2 = msgTokenCache.get(m);
|
|
1438
|
+
if (cached2 && cached2.role === m.role && cached2.toolCalls === toolCalls && cached2.content === m.content && (cached2.imageCount === 0 || cached2.imagePrice === estimateImageTokens())) {
|
|
1439
|
+
return cached2.tokens;
|
|
1440
|
+
}
|
|
1441
|
+
const { tokens, imageCount, imagePrice } = computeMessageTokens(m);
|
|
1442
|
+
msgTokenCache.set(m, { content: m.content, toolCalls, role: m.role, imageCount, imagePrice, tokens });
|
|
1443
|
+
return tokens;
|
|
1444
|
+
};
|
|
1445
|
+
estimateTokens = (messagesArr) => {
|
|
1446
|
+
return messagesArr.reduce((total, m) => total + messageTokens(m), 0);
|
|
1377
1447
|
};
|
|
1378
1448
|
cleanMsg = (m) => {
|
|
1379
1449
|
const { id, sessionId, ts, ...rest } = m;
|
|
@@ -1473,7 +1543,7 @@ async function setTodos(sessionId, todos) {
|
|
|
1473
1543
|
await writeStore(sessionId, store);
|
|
1474
1544
|
});
|
|
1475
1545
|
}
|
|
1476
|
-
var getSessionsDirPath, getWorkspaceSessionsDir, getStatePath, getTranscriptPath, ensureSessionsDir, migrateLegacyFiles, writeStore, storeLocks, withStoreLock, getOrCreateSessionId, readStore, updateCalibration, listSessions, getMostRecentSessionId, renameSession, deleteSession;
|
|
1546
|
+
var getSessionsDirPath, getWorkspaceSessionsDir, getStatePath, getTranscriptPath, ensuredSessionDirs, ensureSessionsDir, migrateLegacyFiles, writeStore, storeLocks, withStoreLock, getOrCreateSessionId, readStore, updateCalibration, listSessions, getMostRecentSessionId, renameSession, deleteSession;
|
|
1477
1547
|
var init_store = __esm({
|
|
1478
1548
|
"../core/src/session/store.ts"() {
|
|
1479
1549
|
"use strict";
|
|
@@ -1494,10 +1564,14 @@ var init_store = __esm({
|
|
|
1494
1564
|
assertSafeSessionId(sessionId);
|
|
1495
1565
|
return path7.join(getSessionsDirPath(sessionId), `${sessionId}.jsonl`);
|
|
1496
1566
|
};
|
|
1567
|
+
ensuredSessionDirs = /* @__PURE__ */ new Set();
|
|
1497
1568
|
ensureSessionsDir = async (sessionId) => {
|
|
1498
|
-
|
|
1569
|
+
const dir = getSessionsDirPath(sessionId);
|
|
1570
|
+
if (ensuredSessionDirs.has(dir)) return;
|
|
1571
|
+
await fs5.mkdir(dir, { recursive: true });
|
|
1499
1572
|
await migrateLegacyFiles(sessionId).catch(() => {
|
|
1500
1573
|
});
|
|
1574
|
+
ensuredSessionDirs.add(dir);
|
|
1501
1575
|
};
|
|
1502
1576
|
migrateLegacyFiles = async (sessionId) => {
|
|
1503
1577
|
assertSafeSessionId(sessionId);
|
|
@@ -1676,8 +1750,34 @@ var init_store = __esm({
|
|
|
1676
1750
|
return summaries;
|
|
1677
1751
|
};
|
|
1678
1752
|
getMostRecentSessionId = async () => {
|
|
1679
|
-
const
|
|
1680
|
-
|
|
1753
|
+
const root = getWorkspaceSessionsDir();
|
|
1754
|
+
let entries;
|
|
1755
|
+
try {
|
|
1756
|
+
entries = await fs5.readdir(root, { withFileTypes: true });
|
|
1757
|
+
} catch {
|
|
1758
|
+
return null;
|
|
1759
|
+
}
|
|
1760
|
+
let best;
|
|
1761
|
+
let noTimestampFirst;
|
|
1762
|
+
for (const entry of entries) {
|
|
1763
|
+
if (!entry.isDirectory()) continue;
|
|
1764
|
+
const sessionId = entry.name;
|
|
1765
|
+
if (!isSafeSessionId(sessionId)) continue;
|
|
1766
|
+
const state = await readJSONFile(getStatePath(sessionId));
|
|
1767
|
+
let updatedAt = state?.updatedAt;
|
|
1768
|
+
if (!updatedAt) {
|
|
1769
|
+
try {
|
|
1770
|
+
updatedAt = (await fs5.stat(path7.join(root, sessionId))).mtime.toISOString();
|
|
1771
|
+
} catch {
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
if (!updatedAt) {
|
|
1775
|
+
noTimestampFirst ??= sessionId;
|
|
1776
|
+
continue;
|
|
1777
|
+
}
|
|
1778
|
+
if (!best || updatedAt > best.updatedAt) best = { sessionId, updatedAt };
|
|
1779
|
+
}
|
|
1780
|
+
return best?.sessionId ?? noTimestampFirst ?? null;
|
|
1681
1781
|
};
|
|
1682
1782
|
renameSession = async (sessionId, title) => {
|
|
1683
1783
|
assertSafeSessionId(sessionId);
|
|
@@ -1693,13 +1793,14 @@ var init_store = __esm({
|
|
|
1693
1793
|
assertSafeSessionId(sessionId);
|
|
1694
1794
|
const dir = getSessionsDirPath(sessionId);
|
|
1695
1795
|
await fs5.rm(dir, { recursive: true, force: true });
|
|
1796
|
+
ensuredSessionDirs.delete(dir);
|
|
1696
1797
|
};
|
|
1697
1798
|
}
|
|
1698
1799
|
});
|
|
1699
1800
|
|
|
1700
1801
|
// ../core/src/session/transcript.ts
|
|
1701
1802
|
import fs6 from "fs/promises";
|
|
1702
|
-
var isEventLine, readTranscriptLines, appendLineWithRetry, appendMessage, appendEvent;
|
|
1803
|
+
var isEventLine, readTranscriptLines, appendSizeCache, appendLineWithRetry, appendMessage, appendEvent;
|
|
1703
1804
|
var init_transcript = __esm({
|
|
1704
1805
|
"../core/src/session/transcript.ts"() {
|
|
1705
1806
|
"use strict";
|
|
@@ -1728,22 +1829,29 @@ var init_transcript = __esm({
|
|
|
1728
1829
|
throw err;
|
|
1729
1830
|
}
|
|
1730
1831
|
};
|
|
1832
|
+
appendSizeCache = /* @__PURE__ */ new Map();
|
|
1731
1833
|
appendLineWithRetry = async (p, payload) => {
|
|
1732
1834
|
const MAX_ATTEMPTS = 3;
|
|
1835
|
+
const payloadBytes = Buffer.byteLength(payload, "utf-8");
|
|
1733
1836
|
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
1734
|
-
let beforeSize =
|
|
1735
|
-
|
|
1736
|
-
beforeSize =
|
|
1737
|
-
|
|
1837
|
+
let beforeSize = appendSizeCache.get(p);
|
|
1838
|
+
if (beforeSize === void 0) {
|
|
1839
|
+
beforeSize = 0;
|
|
1840
|
+
try {
|
|
1841
|
+
beforeSize = (await fs6.stat(p)).size;
|
|
1842
|
+
} catch {
|
|
1843
|
+
}
|
|
1738
1844
|
}
|
|
1739
1845
|
try {
|
|
1740
1846
|
await fs6.appendFile(p, payload, "utf-8");
|
|
1847
|
+
appendSizeCache.set(p, beforeSize + payloadBytes);
|
|
1741
1848
|
return;
|
|
1742
1849
|
} catch (e) {
|
|
1743
1850
|
try {
|
|
1744
1851
|
await fs6.truncate(p, beforeSize);
|
|
1745
1852
|
} catch {
|
|
1746
1853
|
}
|
|
1854
|
+
appendSizeCache.set(p, beforeSize);
|
|
1747
1855
|
if (attempt === MAX_ATTEMPTS) throw e;
|
|
1748
1856
|
await new Promise((r) => setTimeout(r, 50 * attempt));
|
|
1749
1857
|
}
|
|
@@ -1778,6 +1886,161 @@ var init_transcript = __esm({
|
|
|
1778
1886
|
}
|
|
1779
1887
|
});
|
|
1780
1888
|
|
|
1889
|
+
// ../core/src/session/recovery.ts
|
|
1890
|
+
var detectInterruption, repairOrphanToolCalls, reconcileCompaction, recoverSession;
|
|
1891
|
+
var init_recovery = __esm({
|
|
1892
|
+
"../core/src/session/recovery.ts"() {
|
|
1893
|
+
"use strict";
|
|
1894
|
+
init_transcript();
|
|
1895
|
+
init_store();
|
|
1896
|
+
detectInterruption = (lines) => {
|
|
1897
|
+
let sawEvents = false;
|
|
1898
|
+
let lastStart;
|
|
1899
|
+
const closed = /* @__PURE__ */ new Set();
|
|
1900
|
+
for (const l of lines) {
|
|
1901
|
+
if (!isEventLine(l)) continue;
|
|
1902
|
+
sawEvents = true;
|
|
1903
|
+
if (l.dscEvent === "run.start") lastStart = l;
|
|
1904
|
+
else if (l.dscEvent === "run.end" || l.dscEvent === "run.abandoned") closed.add(l.runId);
|
|
1905
|
+
}
|
|
1906
|
+
if (!sawEvents || !lastStart) return { kind: "legacy" };
|
|
1907
|
+
return closed.has(lastStart.runId) ? { kind: "clean" } : { kind: "crashed", runId: lastStart.runId };
|
|
1908
|
+
};
|
|
1909
|
+
repairOrphanToolCalls = (msgs, confirmedCrash) => {
|
|
1910
|
+
const placeholder = confirmedCrash ? "\uFF08\u4E0A\u6B21\u4F1A\u8BDD\u5728\u5DE5\u5177\u6267\u884C\u4E2D\u5D29\u6E83\uFF08run \u672A\u95ED\u5408\uFF09\uFF0C\u8BE5\u8C03\u7528\u672A\u6267\u884C\uFF0C\u5DF2\u8DF3\u8FC7\u3002\uFF09" : "\uFF08\u8BE5\u5DE5\u5177\u8C03\u7528\u56E0\u4E0A\u6B21\u4F1A\u8BDD\u5F02\u5E38\u4E2D\u65AD\u672A\u7559\u4E0B\u7ED3\u679C\uFF0C\u5DF2\u8DF3\u8FC7\u3002\uFF09";
|
|
1911
|
+
const out = [];
|
|
1912
|
+
const repairedToolCallIds = [];
|
|
1913
|
+
for (let i = 0; i < msgs.length; i++) {
|
|
1914
|
+
const m = msgs[i];
|
|
1915
|
+
out.push(m);
|
|
1916
|
+
if (m.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
|
|
1917
|
+
const answered = /* @__PURE__ */ new Set();
|
|
1918
|
+
let j = i + 1;
|
|
1919
|
+
while (j < msgs.length && msgs[j].role === "tool") {
|
|
1920
|
+
answered.add(msgs[j].tool_call_id);
|
|
1921
|
+
j++;
|
|
1922
|
+
}
|
|
1923
|
+
for (const tc of m.tool_calls) {
|
|
1924
|
+
if (tc.id && !answered.has(tc.id)) {
|
|
1925
|
+
out.push({ role: "tool", tool_call_id: tc.id, content: placeholder });
|
|
1926
|
+
repairedToolCallIds.push(tc.id);
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
return { msgs: out, repairedToolCallIds, confirmedCrash };
|
|
1932
|
+
};
|
|
1933
|
+
reconcileCompaction = (state, lines) => {
|
|
1934
|
+
let last;
|
|
1935
|
+
for (const l of lines) {
|
|
1936
|
+
if (isEventLine(l) && l.dscEvent === "compaction") last = l;
|
|
1937
|
+
}
|
|
1938
|
+
if (!last) return { archivedMessageCount: state.archivedMessageCount, rollingSummary: state.rollingSummary, desync: "legacy" };
|
|
1939
|
+
let desync = "none";
|
|
1940
|
+
if (last.archivedMessageCount !== state.archivedMessageCount) {
|
|
1941
|
+
desync = state.archivedMessageCount > last.archivedMessageCount ? "state-ahead" : "event-ahead";
|
|
1942
|
+
console.warn(
|
|
1943
|
+
`\u26A0\uFE0F [recovery] \u538B\u7F29\u72B6\u6001 desync\uFF08${desync}\uFF09\uFF1Astate.json archivedMessageCount=${state.archivedMessageCount} vs \u672B\u4E2A compaction \u4E8B\u4EF6=${last.archivedMessageCount}\u3002\u4EE5 state \u4E3A\u51C6\uFF08slice \u6267\u884C\u95F8\u95E8\uFF09\uFF0C\u4E8B\u4EF6\u4FA7\u4EC5\u955C\u50CF\u3002`
|
|
1944
|
+
);
|
|
1945
|
+
}
|
|
1946
|
+
return { archivedMessageCount: state.archivedMessageCount, rollingSummary: state.rollingSummary, desync };
|
|
1947
|
+
};
|
|
1948
|
+
recoverSession = async (sessionId, precomputed) => {
|
|
1949
|
+
const lines = precomputed?.lines ?? await readTranscriptLines(sessionId);
|
|
1950
|
+
const interruption = detectInterruption(lines);
|
|
1951
|
+
if (interruption.kind === "crashed") {
|
|
1952
|
+
await appendEvent(sessionId, {
|
|
1953
|
+
dscEvent: "run.abandoned",
|
|
1954
|
+
runId: interruption.runId,
|
|
1955
|
+
reason: "run.end missing: interrupted by process exit/kill"
|
|
1956
|
+
});
|
|
1957
|
+
console.warn(`\u27E6recovery\u27E7 \u68C0\u6D4B\u5230\u672A\u95ED\u5408 run\uFF08${interruption.runId.slice(0, 8)}\u2026\uFF09\u2192 \u5DF2\u8865 run.abandoned \u95ED\u5893\u6807\u8BB0\uFF1B\u5B64\u513F\u4FEE\u590D\u6309\u300C\u5D29\u6E83\u786E\u8BA4\u300D\u6863\u6267\u884C\u3002`);
|
|
1958
|
+
}
|
|
1959
|
+
const state = precomputed?.state ?? await getRollingState(sessionId);
|
|
1960
|
+
const compaction = reconcileCompaction(
|
|
1961
|
+
{ archivedMessageCount: state.archivedMessageCount, rollingSummary: state.rollingSummary },
|
|
1962
|
+
lines
|
|
1963
|
+
);
|
|
1964
|
+
return { interruption, compaction };
|
|
1965
|
+
};
|
|
1966
|
+
}
|
|
1967
|
+
});
|
|
1968
|
+
|
|
1969
|
+
// ../core/src/session/content.ts
|
|
1970
|
+
var decayOldToolResults, enforceVisionGate, buildContextMessages;
|
|
1971
|
+
var init_content = __esm({
|
|
1972
|
+
"../core/src/session/content.ts"() {
|
|
1973
|
+
"use strict";
|
|
1974
|
+
init_contextCore();
|
|
1975
|
+
init_contentParts();
|
|
1976
|
+
init_transcript();
|
|
1977
|
+
init_store();
|
|
1978
|
+
init_config();
|
|
1979
|
+
init_visionCapability();
|
|
1980
|
+
init_recovery();
|
|
1981
|
+
decayOldToolResults = (msgs) => {
|
|
1982
|
+
const units = groupUnits(msgs);
|
|
1983
|
+
const cutoffUnitIdx = Math.max(0, units.length - appConfig.KEEP_RECENT_UNITS);
|
|
1984
|
+
if (cutoffUnitIdx === 0) return msgs;
|
|
1985
|
+
const decayIds = /* @__PURE__ */ new Set();
|
|
1986
|
+
let hasOldImage = false;
|
|
1987
|
+
for (let u = 0; u < cutoffUnitIdx; u++) {
|
|
1988
|
+
for (const m of units[u]) {
|
|
1989
|
+
const mm = m;
|
|
1990
|
+
if (mm.role === "tool" && typeof mm.tool_call_id === "string") decayIds.add(mm.tool_call_id);
|
|
1991
|
+
if (hasImagePart(m.content)) hasOldImage = true;
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
if (decayIds.size === 0 && !hasOldImage) return msgs;
|
|
1995
|
+
const keep = appConfig.BOUNDARY_TOOL_KEEP_CHARS;
|
|
1996
|
+
const oldRefs = /* @__PURE__ */ new Set();
|
|
1997
|
+
for (let u = 0; u < cutoffUnitIdx; u++) for (const m of units[u]) oldRefs.add(m);
|
|
1998
|
+
return msgs.map((m) => {
|
|
1999
|
+
if (!oldRefs.has(m)) return m;
|
|
2000
|
+
const mm = m;
|
|
2001
|
+
if (mm.role === "tool" && decayIds.has(mm.tool_call_id) && typeof mm.content === "string" && mm.content.length > keep) {
|
|
2002
|
+
const head = mm.content.slice(0, keep);
|
|
2003
|
+
return { ...mm, content: `${head}
|
|
2004
|
+
|
|
2005
|
+
[\u2026 \u5386\u53F2\u5DE5\u5177\u8F93\u51FA\u5DF2\u6298\u53E0\uFF08\u5171 ${mm.content.length} \u5B57\u7B26\uFF09\uFF1A\u7EC6\u8282\u5148\u7528 recall \u5DE5\u5177\u6309\u5173\u952E\u8BCD\u68C0\u7D22\u672C\u4F1A\u8BDD\u5386\u53F2\uFF08\u539F\u6587\u82E5\u66FE\u622A\u65AD\u5B58\u6863\uFF0Crecall \u4F20 with_full="${mm.tool_call_id}" \u53EF\u53D6\u56DE\u5168\u6587\uFF09\uFF0C\u65E0\u679C\u518D\u91CD\u65B0\u8C03\u7528\u5DE5\u5177 \u2026]` };
|
|
2006
|
+
}
|
|
2007
|
+
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]");
|
|
2008
|
+
});
|
|
2009
|
+
};
|
|
2010
|
+
enforceVisionGate = (msgs, modelId) => isVisionEnabled(modelId) ? msgs : msgs.map((m) => collapseToText(m, VISION_DEGRADE_NOTE));
|
|
2011
|
+
buildContextMessages = async (sessionId, currentUserMsg, systemPrompt, modelId) => {
|
|
2012
|
+
await ensureVisionCacheLoaded();
|
|
2013
|
+
const lines = await readTranscriptLines(sessionId);
|
|
2014
|
+
const store = await getRollingState(sessionId);
|
|
2015
|
+
const eventAware = appConfig.transcriptEvents || lines.some(isEventLine);
|
|
2016
|
+
const recovery = eventAware ? await recoverSession(sessionId, {
|
|
2017
|
+
lines,
|
|
2018
|
+
state: { archivedMessageCount: store.archivedMessageCount, rollingSummary: store.rollingSummary }
|
|
2019
|
+
}) : {
|
|
2020
|
+
interruption: { kind: "legacy" },
|
|
2021
|
+
compaction: { archivedMessageCount: store.archivedMessageCount, rollingSummary: store.rollingSummary, desync: "legacy" }
|
|
2022
|
+
};
|
|
2023
|
+
const all = lines.filter((l) => !isEventLine(l)).map(cleanMsg);
|
|
2024
|
+
const result = [
|
|
2025
|
+
{ role: "system", content: systemPrompt },
|
|
2026
|
+
// 存储系统提示词
|
|
2027
|
+
{ role: "system", content: recovery.compaction.rollingSummary }
|
|
2028
|
+
// 后续存储摘要使用
|
|
2029
|
+
];
|
|
2030
|
+
const archivedMessageCount = recovery.compaction.archivedMessageCount;
|
|
2031
|
+
const messageAll = all.slice(archivedMessageCount);
|
|
2032
|
+
if (messageAll.length === 0) {
|
|
2033
|
+
result.push(currentUserMsg);
|
|
2034
|
+
return enforceVisionGate(result, modelId);
|
|
2035
|
+
}
|
|
2036
|
+
const repair = repairOrphanToolCalls(messageAll, recovery.interruption.kind === "crashed");
|
|
2037
|
+
result.push(...decayOldToolResults(repair.msgs));
|
|
2038
|
+
result.push(currentUserMsg);
|
|
2039
|
+
return enforceVisionGate(result, modelId);
|
|
2040
|
+
};
|
|
2041
|
+
}
|
|
2042
|
+
});
|
|
2043
|
+
|
|
1781
2044
|
// ../core/src/hooks/types.ts
|
|
1782
2045
|
var INTERCEPTABLE_EVENTS, TOOL_EVENTS, ALL_EVENTS, DEFAULT_TIMEOUT_BY_EVENT;
|
|
1783
2046
|
var init_types = __esm({
|
|
@@ -1964,7 +2227,7 @@ var init_registry = __esm({
|
|
|
1964
2227
|
if (m instanceof RegExp) return `${m.toString()}`;
|
|
1965
2228
|
return "[fn]";
|
|
1966
2229
|
};
|
|
1967
|
-
return rules.map((r) => ({ event: r.event, matcher: strMatcher(r.matcher), source: r.source, onError: r.onError }));
|
|
2230
|
+
return rules.map((r) => ({ event: r.event, matcher: strMatcher(r.matcher), source: r.source, onError: r.onError, firstRunApproval: r.firstRunApproval === true ? true : void 0 }));
|
|
1968
2231
|
};
|
|
1969
2232
|
isPlainObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
1970
2233
|
dispatch = async (event, ctx) => {
|
|
@@ -2069,6 +2332,7 @@ var init_hooks = __esm({
|
|
|
2069
2332
|
// ../core/src/agent/truncate.ts
|
|
2070
2333
|
import path9 from "path";
|
|
2071
2334
|
function stripAnsi(text) {
|
|
2335
|
+
if (!text || !text.includes(ANSI_ESC_CHAR)) return text;
|
|
2072
2336
|
return text.replace(ANSI_ESCAPE, "");
|
|
2073
2337
|
}
|
|
2074
2338
|
function microcompactTextContent(raw) {
|
|
@@ -2077,10 +2341,7 @@ function microcompactTextContent(raw) {
|
|
|
2077
2341
|
s = s.replace(/\n{3,}/g, "\n\n").trim();
|
|
2078
2342
|
return s;
|
|
2079
2343
|
}
|
|
2080
|
-
|
|
2081
|
-
return x != null && typeof x[Symbol.asyncIterator] === "function";
|
|
2082
|
-
}
|
|
2083
|
-
var ANSI_ESCAPE, getFileAccessRoots, relativizeWorkspacePathsInText, truncateToolResult, truncateApprovalDetail, batchSummaryPrompt, compactBatch, ARCHIVE_INDEX_MAX_ENTRIES, ARCHIVE_INDEX_BATCH_CAP, extractArchiveEntities, parseSummarySlot, mergeSummarySlot, CHECKPOINT_MAX_CHARS, SLOT_PLACEHOLDER, CHECKPOINT_FORMAT, checkpointRules, checkpointPrompt, checkpointDirectPrompt, assembleSlot, parseSlotNarrativeState, synthesizeSlotNarrative, synthesizeSlotNarrativeFromBatch, compactSlotNarrative, splitIntoBatches, compactBatches, ensureSummarySlot, SUMMARY_SELF_COMPACT_THRESHOLD, persistCompaction, ensureFitsWindow, collectToolResult;
|
|
2344
|
+
var ANSI_ESCAPE, getFileAccessRoots, rootPathRegexCache, relativizeWorkspacePathsInText, ANSI_ESC_CHAR, truncateToolResult, truncateApprovalDetail, batchSummaryPrompt, compactBatch, ARCHIVE_INDEX_MAX_ENTRIES, ARCHIVE_INDEX_BATCH_CAP, entityMinLen, extractArchiveEntities, parseSummarySlot, mergeSummarySlot, CHECKPOINT_MAX_CHARS, SLOT_PLACEHOLDER, CHECKPOINT_FORMAT, checkpointRules, checkpointPrompt, checkpointDirectPrompt, assembleSlot, parseSlotNarrativeState, synthesizeSlotNarrative, synthesizeSlotNarrativeFromBatch, compactSlotNarrative, MAX_BATCH_TOKENS, PRETRUNCATE_FLOOR_TOKENS, foldableTokensOf, foldTextToTarget, foldArguments, foldMessageTo, pretruncateOversizedUnit, splitIntoBatches, compactBatches, ensureSummarySlot, SUMMARY_SELF_COMPACT_THRESHOLD, persistCompaction, ensureFitsWindow;
|
|
2084
2345
|
var init_truncate = __esm({
|
|
2085
2346
|
"../core/src/agent/truncate.ts"() {
|
|
2086
2347
|
"use strict";
|
|
@@ -2088,6 +2349,7 @@ var init_truncate = __esm({
|
|
|
2088
2349
|
init_model();
|
|
2089
2350
|
init_contextCore();
|
|
2090
2351
|
init_contentParts();
|
|
2352
|
+
init_content();
|
|
2091
2353
|
init_store();
|
|
2092
2354
|
init_transcript();
|
|
2093
2355
|
init_hooks();
|
|
@@ -2102,6 +2364,7 @@ var init_truncate = __esm({
|
|
|
2102
2364
|
return norm;
|
|
2103
2365
|
});
|
|
2104
2366
|
};
|
|
2367
|
+
rootPathRegexCache = /* @__PURE__ */ new Map();
|
|
2105
2368
|
relativizeWorkspacePathsInText = (text) => {
|
|
2106
2369
|
if (!text) return text;
|
|
2107
2370
|
const roots = /* @__PURE__ */ new Set();
|
|
@@ -2114,20 +2377,25 @@ var init_truncate = __esm({
|
|
|
2114
2377
|
}
|
|
2115
2378
|
}
|
|
2116
2379
|
} catch {
|
|
2117
|
-
return text
|
|
2380
|
+
return stripAnsi(text);
|
|
2118
2381
|
}
|
|
2119
2382
|
let out = text;
|
|
2120
2383
|
for (const root of roots) {
|
|
2121
2384
|
const norm = root.replace(/\\/g, "/");
|
|
2122
2385
|
if (norm.length < 3) continue;
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2386
|
+
let re = rootPathRegexCache.get(norm);
|
|
2387
|
+
if (!re) {
|
|
2388
|
+
re = new RegExp(
|
|
2389
|
+
norm.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "(\\/|\\\\|$)",
|
|
2390
|
+
"gi"
|
|
2391
|
+
);
|
|
2392
|
+
rootPathRegexCache.set(norm, re);
|
|
2393
|
+
}
|
|
2127
2394
|
out = out.replace(re, "./$1");
|
|
2128
2395
|
}
|
|
2129
2396
|
return out;
|
|
2130
2397
|
};
|
|
2398
|
+
ANSI_ESC_CHAR = String.fromCharCode(27);
|
|
2131
2399
|
truncateToolResult = (result, maxChars, sidecarNote) => {
|
|
2132
2400
|
const finalMaxChars = maxChars ?? appConfig.MAX_TOOL_RESULT_CHARS;
|
|
2133
2401
|
const newResult = microcompactTextContent(result);
|
|
@@ -2164,25 +2432,36 @@ ${tail}`;
|
|
|
2164
2432
|
};
|
|
2165
2433
|
ARCHIVE_INDEX_MAX_ENTRIES = 120;
|
|
2166
2434
|
ARCHIVE_INDEX_BATCH_CAP = 60;
|
|
2435
|
+
entityMinLen = (s) => /[一-鿿]/.test(s) ? 2 : 3;
|
|
2167
2436
|
extractArchiveEntities = (batch) => {
|
|
2168
|
-
let
|
|
2437
|
+
let contentText = "";
|
|
2438
|
+
let argsText = "";
|
|
2169
2439
|
for (const m of batch) {
|
|
2170
|
-
if (m.content)
|
|
2440
|
+
if (m.content) contentText += ` ${msgText(m.content)}`;
|
|
2171
2441
|
const calls = m.tool_calls;
|
|
2172
|
-
if (Array.isArray(calls)) for (const c of calls)
|
|
2442
|
+
if (Array.isArray(calls)) for (const c of calls) argsText += ` ${c?.function?.name ?? ""} ${c?.function?.arguments ?? ""}`;
|
|
2173
2443
|
}
|
|
2174
2444
|
const found = [];
|
|
2175
2445
|
const seen = /* @__PURE__ */ new Set();
|
|
2176
2446
|
const push = (raw) => {
|
|
2177
2447
|
const s = raw.trim();
|
|
2178
|
-
if (!s || s.length <
|
|
2448
|
+
if (!s || s.length < entityMinLen(s) || s.length > 60 || seen.has(s.toLowerCase()) || s.includes("|")) return;
|
|
2179
2449
|
const lastSeg = s.split(/[\\/]/).pop() ?? "";
|
|
2180
2450
|
if (/^[\d.]+$/.test(lastSeg)) return;
|
|
2181
|
-
seen.add(s);
|
|
2451
|
+
seen.add(s.toLowerCase());
|
|
2182
2452
|
found.push(s);
|
|
2183
2453
|
};
|
|
2184
|
-
|
|
2185
|
-
for (const
|
|
2454
|
+
const scanSurfaces = [contentText, argsText];
|
|
2455
|
+
for (const text2 of scanSurfaces) {
|
|
2456
|
+
for (const m of text2.match(/(?:[A-Za-z]:)?[\w.\-一-鿿]+(?:[/\\][\w.\-一-鿿]+)+\.[A-Za-z0-9]{1,6}/g) ?? []) push(m);
|
|
2457
|
+
for (const m of text2.match(/`([^`\n]{2,48})`/g) ?? []) push(m.slice(1, -1));
|
|
2458
|
+
for (const m of text2.match(/https?:\/\/[^\s"'<>()【】,。]+/g) ?? []) push(m);
|
|
2459
|
+
}
|
|
2460
|
+
const text = contentText;
|
|
2461
|
+
for (const m of text.match(/"([^"\n]{2,48})"/g) ?? []) push(m.slice(1, -1));
|
|
2462
|
+
for (const m of text.match(/[「“]([^」”\n]{2,48})[」”]/g) ?? []) push(m.slice(1, -1));
|
|
2463
|
+
for (const m of text.match(/'([^'\n]{2,48})'/g) ?? []) if (!m.slice(1, -1).includes(" ")) push(m.slice(1, -1));
|
|
2464
|
+
for (const m of text.match(/[一-鿿][一-鿿0-9A-Za-z_]+/g) ?? []) if (m.length <= 14) push(m);
|
|
2186
2465
|
return found.slice(0, ARCHIVE_INDEX_BATCH_CAP);
|
|
2187
2466
|
};
|
|
2188
2467
|
parseSummarySlot = (content) => {
|
|
@@ -2201,8 +2480,8 @@ ${tail}`;
|
|
|
2201
2480
|
const merged = [];
|
|
2202
2481
|
const seen = /* @__PURE__ */ new Set();
|
|
2203
2482
|
for (const e of [...newEntities, ...index]) {
|
|
2204
|
-
if (!e || seen.has(e)) continue;
|
|
2205
|
-
seen.add(e);
|
|
2483
|
+
if (!e || seen.has(e.toLowerCase())) continue;
|
|
2484
|
+
seen.add(e.toLowerCase());
|
|
2206
2485
|
merged.push(e);
|
|
2207
2486
|
if (merged.length >= ARCHIVE_INDEX_MAX_ENTRIES) break;
|
|
2208
2487
|
}
|
|
@@ -2265,14 +2544,80 @@ ${lines}
|
|
|
2265
2544
|
return assembleSlot(index, newNotes);
|
|
2266
2545
|
};
|
|
2267
2546
|
compactSlotNarrative = async (slotContent, _modelWindow, signal) => synthesizeSlotNarrative(slotContent, "", signal);
|
|
2547
|
+
MAX_BATCH_TOKENS = 16e3;
|
|
2548
|
+
PRETRUNCATE_FLOOR_TOKENS = 512;
|
|
2549
|
+
foldableTokensOf = (m) => Math.max(0, estimateTokens([m]) - 4);
|
|
2550
|
+
foldTextToTarget = (text, curTokens, targetTokens) => {
|
|
2551
|
+
const density = text.length / Math.max(1, curTokens);
|
|
2552
|
+
const keepChars = Math.max(64, Math.floor(targetTokens * density));
|
|
2553
|
+
const half = Math.floor(keepChars / 2);
|
|
2554
|
+
const totalLines = text.split("\n").length;
|
|
2555
|
+
const omitted = Math.max(0, totalLines - text.slice(0, half).split("\n").length - text.slice(-half).split("\n").length);
|
|
2556
|
+
return [text.slice(0, half), "", `\u2026[\u538B\u7F29\u9884\u622A\u65AD\uFF1A\u8D85\u51FA\u5355\u6279\u538B\u7F29\u9884\u7B97\uFF0C\u5DF2\u53BB\u4E2D\u6BB5\u7EA6 ${omitted} \u884C\uFF08\u5171 ${totalLines} \u884C\uFF09\uFF1B\u5B8C\u6574\u5185\u5BB9\u53EF\u7ECF recall \u5DE5\u5177\u68C0\u7D22]\u2026`, "", text.slice(-half)].join("\n");
|
|
2557
|
+
};
|
|
2558
|
+
foldArguments = (args, maxChars) => {
|
|
2559
|
+
if (args.length <= maxChars) return args;
|
|
2560
|
+
try {
|
|
2561
|
+
const walk = (v) => {
|
|
2562
|
+
if (typeof v === "string") return v.length > maxChars ? `\u2026[\u5DF2\u6298\u53E0 ${v.length} \u5B57\u7B26]` : v;
|
|
2563
|
+
if (Array.isArray(v)) return v.map(walk);
|
|
2564
|
+
if (v && typeof v === "object") {
|
|
2565
|
+
for (const k of Object.keys(v)) v[k] = walk(v[k]);
|
|
2566
|
+
}
|
|
2567
|
+
return v;
|
|
2568
|
+
};
|
|
2569
|
+
return JSON.stringify(walk(JSON.parse(args)));
|
|
2570
|
+
} catch {
|
|
2571
|
+
return JSON.stringify(`[\u5DE5\u5177\u53C2\u6570\u8FC7\u957F\u5DF2\u6298\u53E0\uFF0C\u539F ${args.length} \u5B57\u7B26]`);
|
|
2572
|
+
}
|
|
2573
|
+
};
|
|
2574
|
+
foldMessageTo = (m, targetTokens) => {
|
|
2575
|
+
const mm = m;
|
|
2576
|
+
const keepChars = Math.max(256, targetTokens * 4);
|
|
2577
|
+
if (Array.isArray(mm.tool_calls) && mm.tool_calls.length > 0) {
|
|
2578
|
+
let content = mm.content;
|
|
2579
|
+
if (typeof content === "string" && content.length > keepChars) {
|
|
2580
|
+
content = foldTextToTarget(content, Math.max(1, foldableTokensOf(m)), targetTokens);
|
|
2581
|
+
}
|
|
2582
|
+
return {
|
|
2583
|
+
...mm,
|
|
2584
|
+
content,
|
|
2585
|
+
tool_calls: mm.tool_calls.map((c) => c?.function?.arguments ? { ...c, function: { ...c.function, arguments: foldArguments(String(c.function.arguments), keepChars) } } : c)
|
|
2586
|
+
};
|
|
2587
|
+
}
|
|
2588
|
+
if (typeof mm.content === "string" && mm.content.length > 0) {
|
|
2589
|
+
return { ...mm, content: foldTextToTarget(mm.content, Math.max(1, foldableTokensOf(m)), targetTokens) };
|
|
2590
|
+
}
|
|
2591
|
+
return m;
|
|
2592
|
+
};
|
|
2593
|
+
pretruncateOversizedUnit = (unit, budgetTokens = MAX_BATCH_TOKENS) => {
|
|
2594
|
+
let out = unit.map((m) => Array.isArray(m.content) ? collapseToText(m) : m);
|
|
2595
|
+
let guard = unit.length * 16 + 16;
|
|
2596
|
+
while (estimateTokens(out) > budgetTokens && guard-- > 0) {
|
|
2597
|
+
let idx = -1, maxT = 0;
|
|
2598
|
+
for (let i = 0; i < out.length; i++) {
|
|
2599
|
+
const t = foldableTokensOf(out[i]);
|
|
2600
|
+
if (t > maxT) {
|
|
2601
|
+
maxT = t;
|
|
2602
|
+
idx = i;
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
if (idx < 0 || maxT <= PRETRUNCATE_FLOOR_TOKENS) break;
|
|
2606
|
+
out[idx] = foldMessageTo(out[idx], Math.floor(maxT / 2));
|
|
2607
|
+
}
|
|
2608
|
+
return out;
|
|
2609
|
+
};
|
|
2268
2610
|
splitIntoBatches = (toCompact) => {
|
|
2269
|
-
const MAX_BATCH_TOKENS = 16e3;
|
|
2270
2611
|
const units = groupUnits(toCompact);
|
|
2271
2612
|
const batches = [];
|
|
2272
2613
|
let batch = [];
|
|
2273
2614
|
let batchTokens = 0;
|
|
2274
|
-
for (
|
|
2275
|
-
|
|
2615
|
+
for (let unit of units) {
|
|
2616
|
+
let size = estimateTokens(unit);
|
|
2617
|
+
if (size > MAX_BATCH_TOKENS) {
|
|
2618
|
+
unit = pretruncateOversizedUnit(unit);
|
|
2619
|
+
size = estimateTokens(unit);
|
|
2620
|
+
}
|
|
2276
2621
|
if (batchTokens + size > MAX_BATCH_TOKENS && batch.length > 0) {
|
|
2277
2622
|
batches.push(batch);
|
|
2278
2623
|
batch = [];
|
|
@@ -2318,6 +2663,16 @@ ${lines}
|
|
|
2318
2663
|
const cacheFactor = hitRate == null ? 1 : Math.min(1.1, Math.max(0.9, 0.9 + hitRate * 0.2));
|
|
2319
2664
|
const effectiveRatio = Math.min(event.compactRatio * cacheFactor, 0.82);
|
|
2320
2665
|
if (estReal(event.messageArr) <= event.modelWindow * effectiveRatio) return;
|
|
2666
|
+
const preDecaySize = estReal(event.messageArr);
|
|
2667
|
+
const decayedArr = decayOldToolResults(event.messageArr);
|
|
2668
|
+
if (decayedArr !== event.messageArr) {
|
|
2669
|
+
event.messageArr.length = 0;
|
|
2670
|
+
event.messageArr.push(...decayedArr);
|
|
2671
|
+
}
|
|
2672
|
+
if (estReal(event.messageArr) <= event.modelWindow * effectiveRatio) {
|
|
2673
|
+
console.log(`\u{1F4C9} [\u7A97\u53E3\u6CBB\u7406] \u514D\u8D39\u8870\u51CF\uFF08\u65E7\u5DE5\u5177\u7ED3\u679C\u6298\u53E0\uFF09\u540E\u56DE\u5230\u9608\u503C\u5185\uFF08${Math.round(preDecaySize)} \u2192 ${Math.round(estReal(event.messageArr))} token\uFF09\uFF0C\u8DF3\u8FC7 LLM \u538B\u7F29`);
|
|
2674
|
+
return;
|
|
2675
|
+
}
|
|
2321
2676
|
const tokensThreshold = Math.round(event.modelWindow * effectiveRatio);
|
|
2322
2677
|
await dispatch("PreCompact", { sessionId: event.sessionId, depth: event.depth, tokensBefore: Math.round(estReal(event.messageArr)), tokensThreshold });
|
|
2323
2678
|
const systemMsg = event.messageArr[0];
|
|
@@ -2408,7 +2763,9 @@ ${lines}
|
|
|
2408
2763
|
}
|
|
2409
2764
|
});
|
|
2410
2765
|
if (nextFailures >= 3) {
|
|
2411
|
-
throw new Error(
|
|
2766
|
+
throw new Error(
|
|
2767
|
+
`\u274C [\u538B\u7F29\u7194\u65AD] \u4E0A\u4E0B\u6587\u538B\u7F29\u8FDE\u7EED ${nextFailures} \u6B21\u5931\u8D25\uFF0C\u4E3A\u9632\u5929\u4EF7\u8D26\u5355\u6B7B\u5FAA\u73AF\u5DF2\u6682\u505C\u81EA\u52A8\u538B\u7F29\u3002\u5E38\u89C1\u6839\u56E0\uFF1A\u6458\u8981\u8F85\u52A9\u6A21\u578B\u670D\u52A1\u5F02\u5E38\u6216\u7F51\u7EDC\u4E0D\u901A\uFF08\u53EF\u67E5 DEEP_SEEK_AUX_MODEL \u670D\u52A1\u53EF\u7528\u6027\uFF1B\u8D85\u957F\u5DE5\u5177\u7ED3\u679C\u5DF2\u7531\u7CFB\u7EDF\u81EA\u52A8\u9884\u622A\u65AD\uFF0C\u4E00\u822C\u4E0D\u518D\u662F\u4E3B\u56E0\uFF09\u3002\u81EA\u6108\uFF1A\u76F4\u63A5\u91CD\u53D1\u6D88\u606F\u5373\u53EF\u91CD\u8BD5\uFF08\u6210\u529F\u538B\u7F29\u4E00\u6B21\u8BA1\u6570\u5373\u6E05\u96F6\uFF09\uFF1B\u6216 /fork \u5206\u53C9\u7EED\u63A5\u3001/new \u5F00\u65B0\u4F1A\u8BDD\u3002`
|
|
2768
|
+
);
|
|
2412
2769
|
}
|
|
2413
2770
|
break;
|
|
2414
2771
|
}
|
|
@@ -2424,83 +2781,18 @@ ${lines}
|
|
|
2424
2781
|
throw new Error(`\u4E0A\u4E0B\u6587\u8D85\u51FA\u6A21\u578B\u7A97\u53E3\u4E0A\u9650\uFF08\u6821\u51C6\u7EA6 ${Math.round(finalTokens)} / ${event.modelWindow} token\uFF0C\u515C\u5E95 ${hardLimitRatio}\xD7window\uFF09\uFF0C\u5373\u4F7F\u5168\u91CF\u538B\u7F29\u4ECD\u65E0\u6CD5\u5BB9\u7EB3\u3002\u4EFB\u52A1\u8FC7\u5927\uFF0C\u8BF7\u62C6\u5206\u4EFB\u52A1\u3001\u51CF\u5C0F\u5355\u6B21\u8BFB\u53D6\u91CF\uFF0C\u6216\u589E\u5927 modelWindow\u3002`);
|
|
2425
2782
|
}
|
|
2426
2783
|
};
|
|
2427
|
-
collectToolResult = async (ret, onChunk, signal) => {
|
|
2428
|
-
if (isAsyncGenerator(ret)) {
|
|
2429
|
-
let full = "";
|
|
2430
|
-
const idleMs = Number(process.env.DEEP_SEEK_STREAM_IDLE_TIMEOUT_MS) || 12e4;
|
|
2431
|
-
while (true) {
|
|
2432
|
-
let timer2;
|
|
2433
|
-
const outcome = await Promise.race([
|
|
2434
|
-
ret.next().then((step) => ({ timedOut: false, step })),
|
|
2435
|
-
new Promise((resolve) => {
|
|
2436
|
-
timer2 = setTimeout(() => resolve({ timedOut: true }), idleMs);
|
|
2437
|
-
})
|
|
2438
|
-
]);
|
|
2439
|
-
if (timer2) clearTimeout(timer2);
|
|
2440
|
-
if (outcome.timedOut) {
|
|
2441
|
-
full += `
|
|
2442
|
-
|
|
2443
|
-
[\u23F3 \u5DE5\u5177\u6D41\u5F0F\u8F93\u51FA idle \u8D85\u65F6\uFF08${Math.round(idleMs / 1e3)}s \u65E0\u65B0\u5757\uFF09\uFF0C\u5DF2\u7194\u65AD\u8FD4\u56DE\u5DF2\u6536\u96C6\u5185\u5BB9]`;
|
|
2444
|
-
try {
|
|
2445
|
-
await ret.return(void 0);
|
|
2446
|
-
} catch {
|
|
2447
|
-
}
|
|
2448
|
-
break;
|
|
2449
|
-
}
|
|
2450
|
-
if (outcome.step.done) break;
|
|
2451
|
-
full += outcome.step.value;
|
|
2452
|
-
onChunk?.(outcome.step.value);
|
|
2453
|
-
}
|
|
2454
|
-
return full;
|
|
2455
|
-
}
|
|
2456
|
-
const timeoutMs2 = Number(process.env.DEEP_SEEK_STREAM_IDLE_TIMEOUT_MS) || 12e4;
|
|
2457
|
-
let timer;
|
|
2458
|
-
const raced = await Promise.race([
|
|
2459
|
-
Promise.resolve(ret).then((v) => ({ kind: "ok", value: typeof v === "string" ? v : JSON.stringify(v) })),
|
|
2460
|
-
new Promise((resolve) => {
|
|
2461
|
-
timer = setTimeout(() => resolve({ kind: "timeout" }), timeoutMs2);
|
|
2462
|
-
}),
|
|
2463
|
-
...signal ? [new Promise((resolve) => {
|
|
2464
|
-
signal.addEventListener("abort", () => resolve({ kind: "abort" }), { once: true });
|
|
2465
|
-
})] : []
|
|
2466
|
-
]);
|
|
2467
|
-
if (timer) clearTimeout(timer);
|
|
2468
|
-
if (raced.kind === "timeout") {
|
|
2469
|
-
return `[\u23F3 \u5DE5\u5177\u6267\u884C\u8D85\u65F6\uFF08${Math.round(timeoutMs2 / 1e3)}s \u672A\u8FD4\u56DE\uFF09\uFF0C\u5DF2\u7194\u65AD\u8DF3\u8FC7\u3002\u8BE5\u5DE5\u5177\u53EF\u80FD hang \u6216\u4E0D\u54CD\u5E94\u4E2D\u6B62\u4FE1\u53F7\u3002]`;
|
|
2470
|
-
}
|
|
2471
|
-
if (raced.kind === "abort") {
|
|
2472
|
-
throw new Error("aborted");
|
|
2473
|
-
}
|
|
2474
|
-
return raced.value;
|
|
2475
|
-
};
|
|
2476
2784
|
}
|
|
2477
2785
|
});
|
|
2478
2786
|
|
|
2479
2787
|
// ../core/src/tool/permissions.ts
|
|
2480
2788
|
import fs7 from "fs/promises";
|
|
2481
2789
|
import path10 from "path";
|
|
2482
|
-
var
|
|
2790
|
+
var rules2, trustedProject, globCache, globToRegex, DANGER_COMMAND_TOOLS, compileRule, readPermissionConfig, toolNameMatches, ruleMatches, initPermissions, checkPermission, listPermissionRules, buildScopedAllowRule, resolveSettingsPath, addPermissionRule;
|
|
2483
2791
|
var init_permissions = __esm({
|
|
2484
2792
|
"../core/src/tool/permissions.ts"() {
|
|
2485
2793
|
"use strict";
|
|
2486
2794
|
init_config();
|
|
2487
2795
|
init_common();
|
|
2488
|
-
PRIMARY_ARG = {
|
|
2489
|
-
run_command: "command",
|
|
2490
|
-
run_in_background: "command",
|
|
2491
|
-
web_fetch: "url",
|
|
2492
|
-
web_search: "query",
|
|
2493
|
-
read_file: "path",
|
|
2494
|
-
list_dir: "path",
|
|
2495
|
-
edit_file: "path",
|
|
2496
|
-
create_file: "path",
|
|
2497
|
-
write_file: "path",
|
|
2498
|
-
delete_path: "path",
|
|
2499
|
-
notebook_edit: "path",
|
|
2500
|
-
move_file: "src",
|
|
2501
|
-
search_grep: "query",
|
|
2502
|
-
glob: "pattern"
|
|
2503
|
-
};
|
|
2504
2796
|
rules2 = { allow: [], deny: [], ask: [] };
|
|
2505
2797
|
trustedProject = false;
|
|
2506
2798
|
globCache = /* @__PURE__ */ new Map();
|
|
@@ -2566,8 +2858,8 @@ var init_permissions = __esm({
|
|
|
2566
2858
|
if (!Array.isArray(list)) continue;
|
|
2567
2859
|
for (const item of list) {
|
|
2568
2860
|
if (typeof item !== "string") continue;
|
|
2569
|
-
const
|
|
2570
|
-
if (
|
|
2861
|
+
const compiled2 = compileRule(item, configPath, key);
|
|
2862
|
+
if (compiled2) merged[key].push(compiled2);
|
|
2571
2863
|
}
|
|
2572
2864
|
}
|
|
2573
2865
|
}
|
|
@@ -2578,12 +2870,11 @@ var init_permissions = __esm({
|
|
|
2578
2870
|
if (pattern.endsWith("*") && name.startsWith(pattern.slice(0, -1))) return true;
|
|
2579
2871
|
return false;
|
|
2580
2872
|
};
|
|
2581
|
-
ruleMatches = (rule, toolName, args) => {
|
|
2873
|
+
ruleMatches = (rule, toolName, args, primaryArg) => {
|
|
2582
2874
|
if (!toolNameMatches(rule.toolName, toolName)) return false;
|
|
2583
2875
|
if (rule.argRegex === null) return true;
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
const val = args?.[argKey];
|
|
2876
|
+
if (!primaryArg) return true;
|
|
2877
|
+
const val = args?.[primaryArg];
|
|
2587
2878
|
if (typeof val !== "string") return false;
|
|
2588
2879
|
return rule.argRegex.test(val);
|
|
2589
2880
|
};
|
|
@@ -2600,11 +2891,11 @@ var init_permissions = __esm({
|
|
|
2600
2891
|
rules2 = { allow: [], deny: [], ask: [] };
|
|
2601
2892
|
}
|
|
2602
2893
|
};
|
|
2603
|
-
checkPermission = (toolName, args) => {
|
|
2894
|
+
checkPermission = (toolName, args, primaryArg) => {
|
|
2604
2895
|
try {
|
|
2605
|
-
for (const r of rules2.deny) if (ruleMatches(r, toolName, args)) return "deny";
|
|
2606
|
-
for (const r of rules2.ask) if (ruleMatches(r, toolName, args)) return "ask";
|
|
2607
|
-
for (const r of rules2.allow) if (ruleMatches(r, toolName, args)) return "allow";
|
|
2896
|
+
for (const r of rules2.deny) if (ruleMatches(r, toolName, args, primaryArg)) return "deny";
|
|
2897
|
+
for (const r of rules2.ask) if (ruleMatches(r, toolName, args, primaryArg)) return "ask";
|
|
2898
|
+
for (const r of rules2.allow) if (ruleMatches(r, toolName, args, primaryArg)) return "allow";
|
|
2608
2899
|
return null;
|
|
2609
2900
|
} catch {
|
|
2610
2901
|
return null;
|
|
@@ -2614,8 +2905,8 @@ var init_permissions = __esm({
|
|
|
2614
2905
|
const proj = (rs) => rs.map((r) => ({ toolName: r.toolName, raw: r.raw }));
|
|
2615
2906
|
return { allow: proj(rules2.allow), deny: proj(rules2.deny), ask: proj(rules2.ask) };
|
|
2616
2907
|
};
|
|
2617
|
-
buildScopedAllowRule = (toolName, args) => {
|
|
2618
|
-
const argKey =
|
|
2908
|
+
buildScopedAllowRule = (toolName, args, primaryArg) => {
|
|
2909
|
+
const argKey = primaryArg;
|
|
2619
2910
|
const val = argKey ? args?.[argKey] : void 0;
|
|
2620
2911
|
if (!argKey || typeof val !== "string" || !val) return null;
|
|
2621
2912
|
if (argKey === "command") {
|
|
@@ -2636,8 +2927,8 @@ var init_permissions = __esm({
|
|
|
2636
2927
|
resolveSettingsPath = (scope) => scope === "global" ? path10.join(appConfig.dataDir, "settings.json") : path10.join(process.cwd(), ".deepseeker-code", "settings.json");
|
|
2637
2928
|
addPermissionRule = async (scope, kind, ruleStr) => {
|
|
2638
2929
|
if (scope === "project" && !trustedProject) return false;
|
|
2639
|
-
const
|
|
2640
|
-
if (!
|
|
2930
|
+
const compiled2 = compileRule(ruleStr, `runtime:addPermissionRule(${scope})`, kind);
|
|
2931
|
+
if (!compiled2) return false;
|
|
2641
2932
|
try {
|
|
2642
2933
|
const file = resolveSettingsPath(scope);
|
|
2643
2934
|
const cfg = await readJSONFile(file, {}) ?? {};
|
|
@@ -2648,7 +2939,7 @@ var init_permissions = __esm({
|
|
|
2648
2939
|
await fs7.mkdir(path10.dirname(file), { recursive: true });
|
|
2649
2940
|
await atomicWriteJSON(file, cfg);
|
|
2650
2941
|
}
|
|
2651
|
-
if (!rules2[kind].some((r) => r.raw ===
|
|
2942
|
+
if (!rules2[kind].some((r) => r.raw === compiled2.raw)) rules2[kind].push(compiled2);
|
|
2652
2943
|
return true;
|
|
2653
2944
|
} catch (e) {
|
|
2654
2945
|
console.warn(`\u26A0\uFE0F [permissions] addPermissionRule \u5199\u5165\u5931\u8D25\uFF08${scope}/${kind} ${ruleStr}\uFF09: ${e?.message ?? e}`);
|
|
@@ -2688,7 +2979,7 @@ import fsSync from "fs";
|
|
|
2688
2979
|
import path11 from "path";
|
|
2689
2980
|
import ignore from "ignore";
|
|
2690
2981
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
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;
|
|
2982
|
+
var WORKSPACE_ROOT, workspaceAls, getActiveWorkspaceRoot, runWithWorkspaceRoot, runWithSessionContext, BUILTIN_IGNORE_RULES, ignoreCache, ignoreBuilding, allowedRootsReal, getAllowedWorkspaceRoots, realpathNativeSync, getContainingRoot, allowedBoundaryRoots, resolveSafePath, resolveReadablePath, assertWithinWorkspace, PROTECTED_WRITE_DIRS, COMMAND_ENV_DENYLIST, SENSITIVE_ENV_PATTERN, scrubCommandEnv, isProtectedWrite, SCAN_PRUNE_DIRS, scanIgnoreFilesRecursive, buildIgnoreEngine, getIgnoreForBase, initializeWorkspaceIgnore, checkIsPathIgnored, requestApproval;
|
|
2692
2983
|
var init_guard = __esm({
|
|
2693
2984
|
"../core/src/tool/guard.ts"() {
|
|
2694
2985
|
"use strict";
|
|
@@ -2738,15 +3029,24 @@ var init_guard = __esm({
|
|
|
2738
3029
|
ignoreBuilding = /* @__PURE__ */ new Map();
|
|
2739
3030
|
allowedRootsReal = [];
|
|
2740
3031
|
getAllowedWorkspaceRoots = () => [...allowedRootsReal];
|
|
3032
|
+
realpathNativeSync = (p) => {
|
|
3033
|
+
try {
|
|
3034
|
+
return fsSync.realpathSync.native(p);
|
|
3035
|
+
} catch {
|
|
3036
|
+
return p;
|
|
3037
|
+
}
|
|
3038
|
+
};
|
|
2741
3039
|
getContainingRoot = (absPath) => {
|
|
3040
|
+
const target = realpathNativeSync(absPath);
|
|
2742
3041
|
let best;
|
|
2743
3042
|
for (const r of allowedBoundaryRoots()) {
|
|
2744
|
-
const
|
|
3043
|
+
const rReal = realpathNativeSync(r);
|
|
3044
|
+
const rel = path11.relative(rReal, target);
|
|
2745
3045
|
if (!rel.startsWith("..") && !path11.isAbsolute(rel)) {
|
|
2746
|
-
if (!best ||
|
|
3046
|
+
if (!best || rReal.length > best.length) best = rReal;
|
|
2747
3047
|
}
|
|
2748
3048
|
}
|
|
2749
|
-
return best ?? getActiveWorkspaceRoot();
|
|
3049
|
+
return best ?? realpathNativeSync(getActiveWorkspaceRoot());
|
|
2750
3050
|
};
|
|
2751
3051
|
allowedBoundaryRoots = () => {
|
|
2752
3052
|
if (allowedRootsReal.length > 0) return allowedRootsReal;
|
|
@@ -2864,6 +3164,26 @@ var init_guard = __esm({
|
|
|
2864
3164
|
return false;
|
|
2865
3165
|
}
|
|
2866
3166
|
};
|
|
3167
|
+
SCAN_PRUNE_DIRS = /* @__PURE__ */ new Set([
|
|
3168
|
+
"node_modules",
|
|
3169
|
+
".git",
|
|
3170
|
+
"vendor",
|
|
3171
|
+
"__pycache__",
|
|
3172
|
+
".venv",
|
|
3173
|
+
".pytest_cache",
|
|
3174
|
+
".gradle",
|
|
3175
|
+
"build",
|
|
3176
|
+
"target",
|
|
3177
|
+
".settings",
|
|
3178
|
+
".vs",
|
|
3179
|
+
"Debug",
|
|
3180
|
+
"Release",
|
|
3181
|
+
"out",
|
|
3182
|
+
".DerivedData",
|
|
3183
|
+
"Pods",
|
|
3184
|
+
".idea",
|
|
3185
|
+
".vscode"
|
|
3186
|
+
]);
|
|
2867
3187
|
scanIgnoreFilesRecursive = async (dirPath, base, engine) => {
|
|
2868
3188
|
try {
|
|
2869
3189
|
const entries = await fs8.readdir(dirPath, { withFileTypes: true });
|
|
@@ -2881,7 +3201,7 @@ var init_guard = __esm({
|
|
|
2881
3201
|
}
|
|
2882
3202
|
}
|
|
2883
3203
|
for (const entry of entries) {
|
|
2884
|
-
if (entry.isDirectory() &&
|
|
3204
|
+
if (entry.isDirectory() && !SCAN_PRUNE_DIRS.has(entry.name)) {
|
|
2885
3205
|
await scanIgnoreFilesRecursive(path11.join(dirPath, entry.name), base, engine);
|
|
2886
3206
|
}
|
|
2887
3207
|
}
|
|
@@ -2923,7 +3243,7 @@ var init_guard = __esm({
|
|
|
2923
3243
|
return false;
|
|
2924
3244
|
}
|
|
2925
3245
|
};
|
|
2926
|
-
requestApproval = async (toolName, toolCallId, detail, ctx, safetyLevel, args) => {
|
|
3246
|
+
requestApproval = async (toolName, toolCallId, detail, ctx, safetyLevel, args, primaryArg) => {
|
|
2927
3247
|
const safeDetail = truncateApprovalDetail(detail);
|
|
2928
3248
|
if (!ctx.requestApproval) {
|
|
2929
3249
|
ctx.onUIEvent?.({ type: "tool.denied", toolsId: toolCallId, toolName });
|
|
@@ -2933,11 +3253,11 @@ var init_guard = __esm({
|
|
|
2933
3253
|
await dispatch("PermissionRequest", { sessionId: ctx.sessionId, cwd: ctx.cwd, toolName, toolCallId, detail: safeDetail, safetyLevel, args }).catch(() => {
|
|
2934
3254
|
});
|
|
2935
3255
|
const decision = await ctx.requestApproval(safeDetail, { toolName, toolCallId, sessionId: ctx.sessionId });
|
|
2936
|
-
const
|
|
2937
|
-
if (!
|
|
3256
|
+
const approved2 = decision !== "deny";
|
|
3257
|
+
if (!approved2) {
|
|
2938
3258
|
ctx.onUIEvent?.({ type: "tool.denied", toolsId: toolCallId, toolName });
|
|
2939
3259
|
} else if (decision === "allow-always") {
|
|
2940
|
-
const ruleStr = buildScopedAllowRule(toolName, args);
|
|
3260
|
+
const ruleStr = buildScopedAllowRule(toolName, args, primaryArg);
|
|
2941
3261
|
if (ruleStr) {
|
|
2942
3262
|
const persisted = await addPermissionRule("project", "allow", ruleStr).catch(() => false);
|
|
2943
3263
|
console.log(persisted ? `\u{1F4CC} [\u5BA1\u6279\u8BB0\u5FC6] \u5DF2\u5199\u6301\u4E45 allow \u89C4\u5219\uFF1A${ruleStr}\uFF08\u9879\u76EE .deepseeker-code/settings.json\uFF09\uFF0C\u540E\u7EED\u547D\u4E2D\u8BE5\u4F5C\u7528\u57DF\u514D\u5BA1` : `\u267B\uFE0F [\u5BA1\u6279] ${toolName} \u672C\u6B21\u653E\u884C${safetyLevel ? ` (${safetyLevel})` : ""}\uFF08\u672A\u6301\u4E45\u5316\uFF1A\u672A\u4FE1\u4EFB\u76EE\u5F55\u6216\u5199\u5165\u5931\u8D25\uFF09`);
|
|
@@ -2945,7 +3265,7 @@ var init_guard = __esm({
|
|
|
2945
3265
|
console.log(`\u267B\uFE0F [\u5BA1\u6279] ${toolName} \u672C\u6B21\u653E\u884C${safetyLevel ? ` (${safetyLevel})` : ""}\uFF08\u672A\u6301\u4E45\u5316\uFF1A\u65E0\u6CD5\u5B89\u5168\u751F\u6210\u4F5C\u7528\u57DF\uFF0C\u907F\u514D\u88F8\u5DE5\u5177\u540D\u9759\u9ED8\u653E\u884C\u5168\u90E8\u8C03\u7528\uFF09`);
|
|
2946
3266
|
}
|
|
2947
3267
|
}
|
|
2948
|
-
return
|
|
3268
|
+
return approved2;
|
|
2949
3269
|
};
|
|
2950
3270
|
}
|
|
2951
3271
|
});
|
|
@@ -3138,6 +3458,8 @@ var init_background = __esm({
|
|
|
3138
3458
|
type: "function",
|
|
3139
3459
|
function: {
|
|
3140
3460
|
name: "run_in_background",
|
|
3461
|
+
primaryArg: "command",
|
|
3462
|
+
autoApproval: "command",
|
|
3141
3463
|
description: "\u5728\u540E\u53F0\u542F\u52A8\u4E00\u4E2A\u957F\u65F6 shell \u547D\u4EE4\u5E76\u7ACB\u5373\u8FD4\u56DE task_id\uFF0C\u4E0D\u963B\u585E\u540E\u7EED\u63A8\u7406\u3002\u9002\u7528\u4E24\u7C7B\u573A\u666F\uFF1A\u2460 \u957F\u8FDE\u63A5/\u5E38\u9A7B\u8FDB\u7A0B\uFF08dev server\u3001watch\u3001tail -f\uFF09\u2014\u2014\u5148\u8D77\u670D\u52A1\u518D\u7EE7\u7EED\u5E72\u522B\u7684\u6D3B\uFF1B\u2461 \u9884\u8BA1\u8FD0\u884C\u6570\u5206\u949F\u4EE5\u4E0A\u3001\u65E0\u9700\u5B9E\u65F6\u76EF\u770B\u7684\u6709\u9650\u957F\u4EFB\u52A1\uFF08\u5168\u91CF\u6D4B\u8BD5 / \u5927\u6784\u5EFA / \u5927\u4F53\u79EF\u5B89\u88C5\u2014\u2014\u8DD1\u5B8C\u7528 get_background_output \u5E26 wait_seconds \u7B49\u7ED3\u679C\uFF0C\u4E0D\u8981\u7528\u524D\u53F0 run_command \u5E72\u7B49\uFF09\u3002\u7528 get_background_output \u67E5\u65E5\u5FD7\u4E0E\u72B6\u6001\uFF0Cstop_background_task \u7EC8\u6B62\u3002",
|
|
3142
3464
|
parameters: {
|
|
3143
3465
|
type: "object",
|
|
@@ -3185,7 +3507,7 @@ var init_background = __esm({
|
|
|
3185
3507
|
proc = spawn2(args.command, { shell: isWin ? resolveWinShell() ?? true : true, cwd, detached: !isWin, env: scrubCommandEnv() });
|
|
3186
3508
|
proc.unref?.();
|
|
3187
3509
|
} catch (e) {
|
|
3188
|
-
yield
|
|
3510
|
+
yield toolFailure(`[\u540E\u53F0\u542F\u52A8\u5931\u8D25]\uFF1A${e.message}`);
|
|
3189
3511
|
return;
|
|
3190
3512
|
}
|
|
3191
3513
|
const codec = {
|
|
@@ -3229,7 +3551,7 @@ task_id: ${taskId}
|
|
|
3229
3551
|
async execute(args, ctx) {
|
|
3230
3552
|
const task = registry.get(args.task_id);
|
|
3231
3553
|
if (!task || task.sessionId !== ctx?.sessionId) {
|
|
3232
|
-
return
|
|
3554
|
+
return toolFailure(`[\u67E5\u8BE2\u5931\u8D25]\uFF1A\u672A\u627E\u5230 task_id=${args.task_id}\uFF08\u53EF\u80FD\u5DF2\u968F\u670D\u52A1\u91CD\u542F\u4E22\u5931\uFF0C\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u4F1A\u8BDD\uFF09\u3002`);
|
|
3233
3555
|
}
|
|
3234
3556
|
const waitMs = Math.min(Math.max(0, args.wait_seconds ?? 0), 120) * 1e3;
|
|
3235
3557
|
if (waitMs > 0 && task.status === "running") {
|
|
@@ -3269,7 +3591,7 @@ task_id: ${taskId}
|
|
|
3269
3591
|
async execute(args, ctx) {
|
|
3270
3592
|
const task = registry.get(args.task_id);
|
|
3271
3593
|
if (!task || task.sessionId !== ctx?.sessionId) {
|
|
3272
|
-
return
|
|
3594
|
+
return toolFailure(`[\u7EC8\u6B62\u5931\u8D25]\uFF1A\u672A\u627E\u5230 task_id=${args.task_id}\uFF08\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u4F1A\u8BDD\uFF09\u3002`);
|
|
3273
3595
|
}
|
|
3274
3596
|
if (task.status !== "running") {
|
|
3275
3597
|
return `\u2139\uFE0F [stop]\uFF1A\u4EFB\u52A1 ${args.task_id} \u5F53\u524D\u72B6\u6001\u4E3A ${task.status}\uFF08\u5DF2\u4E0D\u5728\u8FD0\u884C\uFF09\uFF0C\u65E0\u9700\u7EC8\u6B62\u3002`;
|
|
@@ -3307,6 +3629,7 @@ var init_client2 = __esm({
|
|
|
3307
3629
|
"use strict";
|
|
3308
3630
|
init_background();
|
|
3309
3631
|
init_config();
|
|
3632
|
+
init_type();
|
|
3310
3633
|
REQUEST_TIMEOUT_MS = 3e4;
|
|
3311
3634
|
PROTOCOL_VERSION_STDIO = "2024-11-05";
|
|
3312
3635
|
PROTOCOL_VERSION_HTTP = "2025-03-26";
|
|
@@ -3320,8 +3643,8 @@ var init_client2 = __esm({
|
|
|
3320
3643
|
const text = content.filter((c) => c?.type === "text" && typeof c.text === "string").map((c) => c.text).join("\n");
|
|
3321
3644
|
const capped = capResultText(text);
|
|
3322
3645
|
if (result?.isError) {
|
|
3323
|
-
return
|
|
3324
|
-
${capped || JSON.stringify(result)}
|
|
3646
|
+
return toolFailure(`[MCP \u5DE5\u5177\u62A5\u9519]
|
|
3647
|
+
${capped || JSON.stringify(result)}`).content;
|
|
3325
3648
|
}
|
|
3326
3649
|
return capped || JSON.stringify(result);
|
|
3327
3650
|
};
|
|
@@ -3972,6 +4295,7 @@ var init_loader = __esm({
|
|
|
3972
4295
|
"../core/src/tool/mcp/loader.ts"() {
|
|
3973
4296
|
"use strict";
|
|
3974
4297
|
init_type();
|
|
4298
|
+
init_argsValidator();
|
|
3975
4299
|
init_config();
|
|
3976
4300
|
init_client2();
|
|
3977
4301
|
clients = [];
|
|
@@ -4050,10 +4374,10 @@ ${out.map((r) => `- [${r.server}] ${r.uri}\uFF08${r.name}${r.description ? `\uFF
|
|
|
4050
4374
|
\uFF08\u5C06\u628A MCP server \u63D0\u4F9B\u7684\u5185\u5BB9\u62C9\u5165\u6A21\u578B\u4E0A\u4E0B\u6587\uFF1B\u8BF7\u786E\u8BA4\u6765\u6E90\u53EF\u4FE1\u3001\u4E0D\u542B\u654F\u611F\u6570\u636E\uFF09`,
|
|
4051
4375
|
async execute(args) {
|
|
4052
4376
|
const { server, uri } = args ?? {};
|
|
4053
|
-
if (!server || !uri) return "
|
|
4377
|
+
if (!server || !uri) return toolFailure("[read_mcp_resource] \u7F3A\u5C11 server \u6216 uri\u3002");
|
|
4054
4378
|
const c = findClient(server);
|
|
4055
|
-
if (!c) return `\
|
|
4056
|
-
if (!c.supportsResources) return
|
|
4379
|
+
if (!c) return toolFailure(`\u672A\u8FDE\u63A5\u7684 MCP server\uFF1A${server}`);
|
|
4380
|
+
if (!c.supportsResources) return toolFailure(`server "${server}" \u4E0D\u652F\u6301 resources\u3002`);
|
|
4057
4381
|
const text = await c.readResource(uri);
|
|
4058
4382
|
return `[MCP resource ${server}${uri}]
|
|
4059
4383
|
${text}`;
|
|
@@ -4120,10 +4444,10 @@ ${out.map((p) => `- [${p.server}] ${p.name}${p.description ? `\uFF1A${p.descript
|
|
|
4120
4444
|
\uFF08\u5C06\u628A MCP server \u6E32\u67D3\u7684 prompt \u6587\u672C\u62C9\u5165\u6A21\u578B\u4E0A\u4E0B\u6587\uFF1B\u8BF7\u786E\u8BA4\u6765\u6E90\u53EF\u4FE1\uFF09`,
|
|
4121
4445
|
async execute(args) {
|
|
4122
4446
|
const { server, name, arguments: pargs } = args ?? {};
|
|
4123
|
-
if (!server || !name) return "
|
|
4447
|
+
if (!server || !name) return toolFailure("[get_mcp_prompt] \u7F3A\u5C11 server \u6216 name\u3002");
|
|
4124
4448
|
const c = findClient(server);
|
|
4125
|
-
if (!c) return `\
|
|
4126
|
-
if (!c.supportsPrompts) return
|
|
4449
|
+
if (!c) return toolFailure(`\u672A\u8FDE\u63A5\u7684 MCP server\uFF1A${server}`);
|
|
4450
|
+
if (!c.supportsPrompts) return toolFailure(`server "${server}" \u4E0D\u652F\u6301 prompts\u3002`);
|
|
4127
4451
|
const text = await c.getPrompt(name, pargs);
|
|
4128
4452
|
return `[MCP prompt ${server}/${name}]
|
|
4129
4453
|
${text}`;
|
|
@@ -4178,34 +4502,63 @@ ${lines.join("\n")}`;
|
|
|
4178
4502
|
type: "function",
|
|
4179
4503
|
function: {
|
|
4180
4504
|
name: "mcp_call",
|
|
4181
|
-
description:
|
|
4505
|
+
description: "\u8C03\u7528\u6307\u5B9A MCP server \u7684\u5916\u90E8\u5DE5\u5177\u3002server \u4E0E\u5DE5\u5177\u540D\u5FC5\u586B\u2014\u2014\u5747\u6765\u81EA mcp_list_tools \u7684\u76EE\u5F55\u8F93\u51FA\uFF08\u7528\u539F\u540D\uFF0C\u4E0D\u8981\u6539\u5199\uFF09\u3002args \u4E3A\u8BE5\u5DE5\u5177\u53C2\u6570\u7684\u5BF9\u8C61\uFF08\u53C2\u6570\u540D\u89C1\u76EE\u5F55\uFF1B\u65E0\u53C2\u6570\u4F20 {}\uFF09\uFF1B\u5386\u53F2\u517C\u5BB9\u4E5F\u63A5\u53D7 JSON \u5B57\u7B26\u4E32\u3002\u6267\u884C\u5916\u90E8\u903B\u8F91\uFF0C\u6BCF\u6B21\u8C03\u7528\u9700\u5BA1\u6279\u3002",
|
|
4182
4506
|
parameters: {
|
|
4183
4507
|
type: "object",
|
|
4184
4508
|
properties: {
|
|
4185
4509
|
server: { type: "string", description: "MCP server \u540D\uFF08\u89C1 mcp_list_tools \u8F93\u51FA\uFF09" },
|
|
4186
4510
|
tool: { type: "string", description: "\u5DE5\u5177\u540D\uFF08\u89C1 mcp_list_tools \u8F93\u51FA\uFF0C\u7528\u539F\u540D\uFF09" },
|
|
4187
|
-
args: {
|
|
4511
|
+
args: {
|
|
4512
|
+
// #8c:收回结构化 object(历史 JSON 字符串兼容保留——防旧 prompt 缓存/模型惯性)。
|
|
4513
|
+
// anyOf 双形态而非仅 object:否则旧形态调用会被执行层 #8c 参数校验早退,兼容形同虚设。
|
|
4514
|
+
anyOf: [
|
|
4515
|
+
{ type: "object", additionalProperties: true, description: '\u5DE5\u5177\u53C2\u6570\u5BF9\u8C61\uFF0C\u5982 {"query":"..."}\uFF1B\u65E0\u53C2\u6570\u4F20 {}' },
|
|
4516
|
+
{ type: "string", description: '\uFF08\u5386\u53F2\u517C\u5BB9\uFF09\u5DE5\u5177\u53C2\u6570\u7684 JSON \u5B57\u7B26\u4E32\uFF0C\u5982 "{\\"query\\":\\"...\\"}"\uFF1B\u65E0\u53C2\u6570\u4F20 "{}"' }
|
|
4517
|
+
]
|
|
4518
|
+
}
|
|
4188
4519
|
},
|
|
4189
4520
|
required: ["server", "tool"]
|
|
4190
4521
|
},
|
|
4191
4522
|
safetyLevel: "danger" /* DANGER */,
|
|
4192
4523
|
isSync: true,
|
|
4193
|
-
requireApproval: (args) =>
|
|
4524
|
+
requireApproval: (args) => {
|
|
4525
|
+
const a = args?.args;
|
|
4526
|
+
const rendered = a === void 0 || a === null ? "{}" : typeof a === "string" ? a : JSON.stringify(a);
|
|
4527
|
+
return `\u26A0\uFE0F\u3010MCP \u5DE5\u5177\u5BA1\u6279\u3011
|
|
4194
4528
|
\u670D\u52A1: ${args?.server} / \u5DE5\u5177: ${args?.tool}
|
|
4195
|
-
\u53C2\u6570: ${
|
|
4529
|
+
\u53C2\u6570: ${rendered}`;
|
|
4530
|
+
},
|
|
4196
4531
|
async execute(args) {
|
|
4197
4532
|
const { server, tool } = args ?? {};
|
|
4198
|
-
if (!server || !tool) return "
|
|
4533
|
+
if (!server || !tool) return toolFailure("[mcp_call] \u7F3A\u5C11 server \u6216 tool\uFF08\u5148\u7528 mcp_list_tools \u67E5\u76EE\u5F55\uFF09\u3002");
|
|
4199
4534
|
let parsed = {};
|
|
4200
|
-
if (
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4535
|
+
if (args.args !== void 0 && args.args !== null) {
|
|
4536
|
+
if (typeof args.args === "string") {
|
|
4537
|
+
if (args.args.trim() && args.args.trim() !== "{}") {
|
|
4538
|
+
try {
|
|
4539
|
+
parsed = JSON.parse(args.args);
|
|
4540
|
+
} catch {
|
|
4541
|
+
return toolFailure(`[mcp_call] args \u4E0D\u662F\u5408\u6CD5 JSON\uFF1A${String(args.args).slice(0, 200)}\u3002\u8BF7\u4F20\u8BE5\u5DE5\u5177\u53C2\u6570\u7684\u5BF9\u8C61\uFF08\u65E0\u53C2\u6570\u4F20 {}\uFF09\u3002`, "syntax");
|
|
4542
|
+
}
|
|
4543
|
+
}
|
|
4544
|
+
} else if (typeof args.args === "object" && !Array.isArray(args.args)) {
|
|
4545
|
+
parsed = args.args;
|
|
4546
|
+
} else {
|
|
4547
|
+
return toolFailure(`[mcp_call] args \u9700\u4E3A\u53C2\u6570\u5BF9\u8C61\u6216 JSON \u5B57\u7B26\u4E32\uFF0C\u6536\u5230 ${typeof args.args}\u3002\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002`, "syntax");
|
|
4205
4548
|
}
|
|
4206
4549
|
}
|
|
4207
4550
|
const c = findClient(server);
|
|
4208
|
-
if (!c) return `\
|
|
4551
|
+
if (!c) return toolFailure(`\u672A\u8FDE\u63A5\u7684 MCP server\uFF1A${server}\uFF08\u7528 mcp_list_tools \u67E5\u770B\u5DF2\u8FDE\u63A5\u5217\u8868\uFF09`);
|
|
4552
|
+
try {
|
|
4553
|
+
const target = (await c.listTools()).find((t) => t.name === tool);
|
|
4554
|
+
if (target?.inputSchema && typeof target.inputSchema === "object") {
|
|
4555
|
+
const verdict = validateToolArgs(target.inputSchema, parsed);
|
|
4556
|
+
if (!verdict.ok) {
|
|
4557
|
+
return toolFailure(`\u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF1A${server}/${tool} ${verdict.message}\uFF1B\u8BF7\u4FEE\u6B63 args \u540E\u91CD\u8BD5\uFF08schema \u89C1 mcp_list_tools \u76EE\u5F55\uFF09\u3002`, "syntax");
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
} catch {
|
|
4561
|
+
}
|
|
4209
4562
|
const result = await c.callTool(tool, parsed);
|
|
4210
4563
|
return `[MCP ${server}/${tool}]
|
|
4211
4564
|
${result}`;
|
|
@@ -4388,7 +4741,7 @@ var init_repeatBreaker = __esm({
|
|
|
4388
4741
|
|
|
4389
4742
|
// ../core/src/agent/planMode.ts
|
|
4390
4743
|
function filterToolsForPlanMode(tools) {
|
|
4391
|
-
const allowed = tools.filter((t) =>
|
|
4744
|
+
const allowed = tools.filter((t) => t.function.planAllowed === true);
|
|
4392
4745
|
return [...allowed, exitPlanModeToolSchema];
|
|
4393
4746
|
}
|
|
4394
4747
|
function appendPlanControlTools(tools) {
|
|
@@ -4398,30 +4751,10 @@ function appendPlanControlTools(tools) {
|
|
|
4398
4751
|
exitPlanModeToolSchema
|
|
4399
4752
|
];
|
|
4400
4753
|
}
|
|
4401
|
-
var
|
|
4754
|
+
var exitPlanModeToolSchema, enterPlanModeToolSchema, PLAN_MODE_AUTO_ENTER_HINT;
|
|
4402
4755
|
var init_planMode = __esm({
|
|
4403
4756
|
"../core/src/agent/planMode.ts"() {
|
|
4404
4757
|
"use strict";
|
|
4405
|
-
PLAN_ALLOWED_TOOLS = /* @__PURE__ */ new Set([
|
|
4406
|
-
"read_file",
|
|
4407
|
-
"list_dir",
|
|
4408
|
-
"view_symbol_outline",
|
|
4409
|
-
"read_project_guide",
|
|
4410
|
-
"search_grep",
|
|
4411
|
-
"glob",
|
|
4412
|
-
"get_git_diff",
|
|
4413
|
-
"git_status",
|
|
4414
|
-
"git_log",
|
|
4415
|
-
"inspect_dependencies",
|
|
4416
|
-
"get_diagnostics",
|
|
4417
|
-
"goto_definition",
|
|
4418
|
-
// ★ P0-A 补漏:LSP 导航/诊断恰是调研阶段最需要的(原白名单漂移漏登记,schema 档与 runtime 档共用此表)
|
|
4419
|
-
"recall",
|
|
4420
|
-
// 只读检索本会话历史(长调研中早前轮次可能已被压缩归档,调研阶段恰是 recall 主场景)
|
|
4421
|
-
"web_fetch",
|
|
4422
|
-
"web_search"
|
|
4423
|
-
// 只读研究类(虽为 DANGER 但不写本地状态;仍走各自审批)
|
|
4424
|
-
]);
|
|
4425
4758
|
exitPlanModeToolSchema = {
|
|
4426
4759
|
type: "function",
|
|
4427
4760
|
function: {
|
|
@@ -4702,7 +5035,7 @@ ${style.body}`);
|
|
|
4702
5035
|
});
|
|
4703
5036
|
|
|
4704
5037
|
// ../core/src/memory/registry.ts
|
|
4705
|
-
var memories, registerMemory, listMemories, getMemory, unregisterMemory, clearMemories, getMemoryIndex;
|
|
5038
|
+
var memories, registerMemory, listMemories, getMemory, unregisterMemory, clearMemories, memoryIndexLine, getMemoryIndex;
|
|
4706
5039
|
var init_registry6 = __esm({
|
|
4707
5040
|
"../core/src/memory/registry.ts"() {
|
|
4708
5041
|
"use strict";
|
|
@@ -4720,10 +5053,11 @@ var init_registry6 = __esm({
|
|
|
4720
5053
|
return true;
|
|
4721
5054
|
};
|
|
4722
5055
|
clearMemories = memories.clear;
|
|
5056
|
+
memoryIndexLine = (m) => `- **${m.name}** (${m.type}) \u2014 ${m.description}`;
|
|
4723
5057
|
getMemoryIndex = () => {
|
|
4724
5058
|
const all = memories.list();
|
|
4725
5059
|
if (all.length === 0) return null;
|
|
4726
|
-
return all.slice().sort((a, b) => a.name.localeCompare(b.name)).map(
|
|
5060
|
+
return all.slice().sort((a, b) => a.name.localeCompare(b.name)).map(memoryIndexLine).join("\n");
|
|
4727
5061
|
};
|
|
4728
5062
|
}
|
|
4729
5063
|
});
|
|
@@ -4747,7 +5081,7 @@ ${index}`);
|
|
|
4747
5081
|
});
|
|
4748
5082
|
|
|
4749
5083
|
// ../core/src/agent/systemInjections.ts
|
|
4750
|
-
var prepareToolsAndInjections;
|
|
5084
|
+
var cleanedSchemaCache, cleanToolSchema, prepareToolsAndInjections;
|
|
4751
5085
|
var init_systemInjections = __esm({
|
|
4752
5086
|
"../core/src/agent/systemInjections.ts"() {
|
|
4753
5087
|
"use strict";
|
|
@@ -4761,6 +5095,19 @@ var init_systemInjections = __esm({
|
|
|
4761
5095
|
init_inject4();
|
|
4762
5096
|
init_inject5();
|
|
4763
5097
|
init_common();
|
|
5098
|
+
cleanedSchemaCache = /* @__PURE__ */ new WeakMap();
|
|
5099
|
+
cleanToolSchema = (t) => {
|
|
5100
|
+
let entry = cleanedSchemaCache.get(t);
|
|
5101
|
+
if (!entry) {
|
|
5102
|
+
const cleaned = {
|
|
5103
|
+
type: t.type,
|
|
5104
|
+
function: { name: t.function.name, description: t.function.description, parameters: t.function.parameters }
|
|
5105
|
+
};
|
|
5106
|
+
entry = { cleaned, fragment: JSON.stringify(cleaned) };
|
|
5107
|
+
cleanedSchemaCache.set(t, entry);
|
|
5108
|
+
}
|
|
5109
|
+
return entry;
|
|
5110
|
+
};
|
|
4764
5111
|
prepareToolsAndInjections = async (message, options, events) => {
|
|
4765
5112
|
const { toolSchemas, planMode, locale: locale2, outputStyle } = options;
|
|
4766
5113
|
const rawToolsPreEnv = planMode && appConfig.planEnforcement === "schema" ? filterToolsForPlanMode(toolSchemas ?? []) : appendPlanControlTools(toolSchemas ?? []);
|
|
@@ -4779,11 +5126,10 @@ var init_systemInjections = __esm({
|
|
|
4779
5126
|
requestQuestion: options.requestQuestion
|
|
4780
5127
|
};
|
|
4781
5128
|
const rawTools = await filterByEnvironment(rawToolsPreEnv, validationCtx);
|
|
4782
|
-
const
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
const toolsTokens = Math.round(JSON.stringify(cleanedToolSchemas).length / 4);
|
|
5129
|
+
const cleanedEntries = rawTools.map((t) => cleanToolSchema(t));
|
|
5130
|
+
const cleanedToolSchemas = cleanedEntries.map((e) => e.cleaned);
|
|
5131
|
+
const schemaJsonLen = cleanedEntries.length === 0 ? 2 : cleanedEntries.reduce((sum, e) => sum + e.fragment.length, 0) + cleanedEntries.length + 1;
|
|
5132
|
+
const toolsTokens = Math.round(schemaJsonLen / 4);
|
|
4787
5133
|
ensureSummarySlot(message);
|
|
4788
5134
|
const LOCALE_HINTS = {
|
|
4789
5135
|
zh: "\u59CB\u7EC8\u7528\u4E2D\u6587\u8F93\u51FA\u6240\u6709\u9762\u5411\u7528\u6237\u7684\u5185\u5BB9\uFF1A\u4F60\u7684\u56DE\u590D\u3001\u4E2D\u95F4\u53D9\u8FF0\u3001todo \u4EFB\u52A1\u9879\u6807\u9898\u3001\u901A\u8FC7 exit_plan_mode \u63D0\u4EA4\u7684\u65B9\u6848\u6587\u672C\u3001\u4EE3\u7801\u6CE8\u91CA\u4E0E\u63D0\u4EA4\u4FE1\u606F\u3002\u4EE3\u7801\u6807\u8BC6\u7B26\u4FDD\u6301\u539F\u6837\uFF1B\u5DE5\u5177\u7ED3\u679C\u4E0E\u7CFB\u7EDF\u6307\u4EE4\u53EF\u80FD\u5939\u6742\u5176\u4ED6\u8BED\u8A00\u2014\u2014\u5FC5\u8981\u65F6\u7167\u5F15\u539F\u6587\uFF0C\u4F46\u4F60\u81EA\u5DF1\u7684\u53D9\u8FF0\u4E0E\u89E3\u91CA\u4E00\u5F8B\u7528\u4E2D\u6587\u3002",
|
|
@@ -4813,6 +5159,73 @@ var init_systemInjections = __esm({
|
|
|
4813
5159
|
}
|
|
4814
5160
|
});
|
|
4815
5161
|
|
|
5162
|
+
// ../core/src/agent/toolResultCollect.ts
|
|
5163
|
+
function isAsyncGenerator(x) {
|
|
5164
|
+
return x != null && typeof x[Symbol.asyncIterator] === "function";
|
|
5165
|
+
}
|
|
5166
|
+
var collectToolResult;
|
|
5167
|
+
var init_toolResultCollect = __esm({
|
|
5168
|
+
"../core/src/agent/toolResultCollect.ts"() {
|
|
5169
|
+
"use strict";
|
|
5170
|
+
collectToolResult = async (ret, onChunk, signal) => {
|
|
5171
|
+
if (isAsyncGenerator(ret)) {
|
|
5172
|
+
let full = "";
|
|
5173
|
+
const idleMs = Number(process.env.DEEP_SEEK_STREAM_IDLE_TIMEOUT_MS) || 12e4;
|
|
5174
|
+
while (true) {
|
|
5175
|
+
let timer2;
|
|
5176
|
+
const outcome = await Promise.race([
|
|
5177
|
+
ret.next().then((step) => ({ timedOut: false, step })),
|
|
5178
|
+
new Promise((resolve) => {
|
|
5179
|
+
timer2 = setTimeout(() => resolve({ timedOut: true }), idleMs);
|
|
5180
|
+
})
|
|
5181
|
+
]);
|
|
5182
|
+
if (timer2) clearTimeout(timer2);
|
|
5183
|
+
if (outcome.timedOut) {
|
|
5184
|
+
full += `
|
|
5185
|
+
|
|
5186
|
+
[\u23F3 \u5DE5\u5177\u6D41\u5F0F\u8F93\u51FA idle \u8D85\u65F6\uFF08${Math.round(idleMs / 1e3)}s \u65E0\u65B0\u5757\uFF09\uFF0C\u5DF2\u7194\u65AD\u8FD4\u56DE\u5DF2\u6536\u96C6\u5185\u5BB9]`;
|
|
5187
|
+
try {
|
|
5188
|
+
await ret.return(void 0);
|
|
5189
|
+
} catch {
|
|
5190
|
+
}
|
|
5191
|
+
return { content: full, status: "failed", errorCategory: "runtime" };
|
|
5192
|
+
}
|
|
5193
|
+
if (outcome.step.done) break;
|
|
5194
|
+
const chunk = typeof outcome.step.value === "string" ? outcome.step.value : String(outcome.step.value?.content ?? outcome.step.value ?? "");
|
|
5195
|
+
full += chunk;
|
|
5196
|
+
onChunk?.(chunk);
|
|
5197
|
+
}
|
|
5198
|
+
return { content: full, status: "success" };
|
|
5199
|
+
}
|
|
5200
|
+
const timeoutMs2 = Number(process.env.DEEP_SEEK_STREAM_IDLE_TIMEOUT_MS) || 12e4;
|
|
5201
|
+
let timer;
|
|
5202
|
+
let onAbort;
|
|
5203
|
+
const raced = await Promise.race([
|
|
5204
|
+
Promise.resolve(ret).then((v2) => ({ kind: "ok", value: v2 })),
|
|
5205
|
+
new Promise((resolve) => {
|
|
5206
|
+
timer = setTimeout(() => resolve({ kind: "timeout" }), timeoutMs2);
|
|
5207
|
+
}),
|
|
5208
|
+
...signal ? [new Promise((resolve) => {
|
|
5209
|
+
onAbort = () => resolve({ kind: "abort" });
|
|
5210
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
5211
|
+
})] : []
|
|
5212
|
+
]);
|
|
5213
|
+
if (timer) clearTimeout(timer);
|
|
5214
|
+
if (onAbort && signal) signal.removeEventListener("abort", onAbort);
|
|
5215
|
+
if (raced.kind === "timeout") {
|
|
5216
|
+
return { content: `[\u23F3 \u5DE5\u5177\u6267\u884C\u8D85\u65F6\uFF08${Math.round(timeoutMs2 / 1e3)}s \u672A\u8FD4\u56DE\uFF09\uFF0C\u5DF2\u7194\u65AD\u8DF3\u8FC7\u3002\u8BE5\u5DE5\u5177\u53EF\u80FD hang \u6216\u4E0D\u54CD\u5E94\u4E2D\u6B62\u4FE1\u53F7\u3002]`, status: "failed", errorCategory: "runtime" };
|
|
5217
|
+
}
|
|
5218
|
+
if (raced.kind === "abort") {
|
|
5219
|
+
throw new Error("aborted");
|
|
5220
|
+
}
|
|
5221
|
+
const v = raced.value;
|
|
5222
|
+
if (typeof v === "string") return { content: v, status: "success" };
|
|
5223
|
+
if (v && typeof v === "object" && typeof v.content === "string" && (v.status === "success" || v.status === "failed")) return v;
|
|
5224
|
+
return { content: JSON.stringify(v), status: "success" };
|
|
5225
|
+
};
|
|
5226
|
+
}
|
|
5227
|
+
});
|
|
5228
|
+
|
|
4816
5229
|
// ../core/src/tool/registry/agent.ts
|
|
4817
5230
|
var createAgentTools;
|
|
4818
5231
|
var init_agent = __esm({
|
|
@@ -4839,13 +5252,13 @@ var init_agent = __esm({
|
|
|
4839
5252
|
safetyLevel: "safe" /* SAFE */,
|
|
4840
5253
|
isSync: true,
|
|
4841
5254
|
async execute(args, ctx) {
|
|
4842
|
-
if (!ctx) return "
|
|
5255
|
+
if (!ctx) return toolFailure("[\u6D3E\u751F\u5931\u8D25]\uFF1Aspawn_agent \u7F3A\u5C11\u5FC5\u987B\u7684\u667A\u80FD\u4F53\u8FD0\u884C\u4E0A\u4E0B\u6587\u3002");
|
|
4843
5256
|
const res = await runSubagent(
|
|
4844
5257
|
{ task: args.task, name: args.name, role: args.role, resumeSessionId: args.resume_session_id },
|
|
4845
5258
|
ctx,
|
|
4846
5259
|
getGlobalTools
|
|
4847
5260
|
);
|
|
4848
|
-
if (!res.ok) return res.output;
|
|
5261
|
+
if (!res.ok) return asToolFailure(res.output);
|
|
4849
5262
|
return [
|
|
4850
5263
|
`\u{1F389} [\u5B50 Agent \u6267\u884C\u5B8C\u6BD5${args.resume_session_id ? "\xB7\u7EED\u8DD1" : ""}] \u6D3E\u751F\u5B50\u4EFB\u52A1\u6C47\u62A5\u5982\u4E0B\uFF1A
|
|
4851
5264
|
`,
|
|
@@ -5015,18 +5428,19 @@ var validateWorkflowArgs, stepLabel, buildPipelineTask, formatWorkflowResult;
|
|
|
5015
5428
|
var init_workflowHelpers = __esm({
|
|
5016
5429
|
"../core/src/tool/registry/workflowHelpers.ts"() {
|
|
5017
5430
|
"use strict";
|
|
5431
|
+
init_type();
|
|
5018
5432
|
validateWorkflowArgs = (args, maxSteps) => {
|
|
5019
5433
|
const steps = args?.steps;
|
|
5020
5434
|
if (!Array.isArray(steps) || steps.length === 0) {
|
|
5021
|
-
return "
|
|
5435
|
+
return toolFailure("[\u5DE5\u4F5C\u6D41] steps \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u81F3\u5C11 1 \u4E2A\u6B65\u9AA4\uFF09\u3002");
|
|
5022
5436
|
}
|
|
5023
5437
|
if (steps.length > maxSteps) {
|
|
5024
|
-
return
|
|
5438
|
+
return toolFailure(`[\u5DE5\u4F5C\u6D41] \u6B65\u9AA4\u6570 ${steps.length} \u8D85\u8FC7\u4E0A\u9650 ${maxSteps}\uFF08\u9632\u5931\u63A7\u6D3E\u751F\u70E7 token\uFF09\u3002\u8BF7\u62C6\u5206\u4E3A\u591A\u6B21 run_workflow \u8C03\u7528\uFF0C\u6216\u7CBE\u7B80\u6B65\u9AA4\u3002`);
|
|
5025
5439
|
}
|
|
5026
5440
|
for (let i = 0; i < steps.length; i++) {
|
|
5027
5441
|
const s = steps[i];
|
|
5028
5442
|
if (!s || typeof s.task !== "string" || !s.task.trim()) {
|
|
5029
|
-
return
|
|
5443
|
+
return toolFailure(`[\u5DE5\u4F5C\u6D41] steps[${i}].task \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u3002`);
|
|
5030
5444
|
}
|
|
5031
5445
|
}
|
|
5032
5446
|
return null;
|
|
@@ -5143,14 +5557,14 @@ var init_workflow = __esm({
|
|
|
5143
5557
|
// 聚合输出整体兜底截断(各子 agent 结果已按 workflowPerStepChars 单独截断)。
|
|
5144
5558
|
maxOutputCharacters: 18e3,
|
|
5145
5559
|
async execute(args, ctx) {
|
|
5146
|
-
if (!ctx) return "
|
|
5560
|
+
if (!ctx) return toolFailure("[\u5DE5\u4F5C\u6D41]\uFF1Arun_workflow \u7F3A\u5C11\u5FC5\u987B\u7684\u667A\u80FD\u4F53\u8FD0\u884C\u4E0A\u4E0B\u6587\u3002");
|
|
5147
5561
|
const maxSteps = appConfig.workflowMaxSteps;
|
|
5148
5562
|
const validationError = validateWorkflowArgs(args, maxSteps);
|
|
5149
5563
|
if (validationError) return validationError;
|
|
5150
5564
|
const mode = args.mode === "pipeline" ? "pipeline" : "parallel";
|
|
5151
5565
|
const isolation = args.isolation === "worktree" ? "worktree" : "none";
|
|
5152
5566
|
if (isolation === "worktree" && mode === "pipeline") {
|
|
5153
|
-
return '
|
|
5567
|
+
return toolFailure('[\u5DE5\u4F5C\u6D41]\uFF1Aisolation="worktree" \u6682\u4EC5\u652F\u6301 parallel \u6A21\u5F0F\uFF08pipeline \u4E32\u884C\u65E0\u9700\u9694\u79BB\uFF09\u3002\u8BF7\u6539 mode=parallel \u6216 isolation=none\u3002');
|
|
5154
5568
|
}
|
|
5155
5569
|
const steps = args.steps.map((s) => ({
|
|
5156
5570
|
task: String(s.task),
|
|
@@ -5159,7 +5573,7 @@ var init_workflow = __esm({
|
|
|
5159
5573
|
key: s.key ? String(s.key) : void 0
|
|
5160
5574
|
}));
|
|
5161
5575
|
if (ctx.depth >= MAX_AGENT_DEPTH) {
|
|
5162
|
-
return
|
|
5576
|
+
return toolFailure(`[\u5B89\u5168\u7194\u65AD]\uFF1A\u5DF2\u8FBE\u5230\u6700\u5927 Agent \u5D4C\u5957\u6DF1\u5EA6\uFF08${MAX_AGENT_DEPTH}\u5C42\uFF09\uFF0C\u65E0\u6CD5\u6D3E\u751F\u5DE5\u4F5C\u6D41\u5B50 agent\u3002\u8BF7\u5728\u672C\u5C42\u7EA7\u81EA\u884C\u6D88\u5316\u4EFB\u52A1\u3002`);
|
|
5163
5577
|
}
|
|
5164
5578
|
const approvalMutex = createSemaphore(1);
|
|
5165
5579
|
const serializedApproval = ctx.requestApproval ? async (...raArgs) => {
|
|
@@ -5193,7 +5607,7 @@ var init_workflow = __esm({
|
|
|
5193
5607
|
try {
|
|
5194
5608
|
wt = await createWorktree(ctx.sessionId, String(index));
|
|
5195
5609
|
} catch (e) {
|
|
5196
|
-
const msg =
|
|
5610
|
+
const msg = toolFailure(`[worktree \u521B\u5EFA\u5931\u8D25]\uFF1A${e?.message ?? e}\uFF08worktree \u9694\u79BB\u9700\u8981\u4E3B\u5DE5\u4F5C\u533A\u662F git \u4ED3\u5E93\uFF09\u3002\u8BE5\u6B65\u9AA4\u672A\u6267\u884C\u3002`).content;
|
|
5197
5611
|
done++;
|
|
5198
5612
|
ctx.emitProgress?.(`\u5E76\u884C\u7F16\u6392\uFF1A${done}/${total} worktree \u521B\u5EFA\u5931\u8D25\uFF08${stepLabel(step, index)}\uFF09`);
|
|
5199
5613
|
return { ok: false, output: msg, label: stepLabel(step, index) };
|
|
@@ -5243,7 +5657,7 @@ var init_workflow = __esm({
|
|
|
5243
5657
|
outcomes = await Promise.all(running);
|
|
5244
5658
|
}
|
|
5245
5659
|
} catch (err) {
|
|
5246
|
-
return
|
|
5660
|
+
return toolFailure(`[\u5DE5\u4F5C\u6D41\u7F16\u6392\u5F02\u5E38]\uFF1A${err?.message ?? err}`);
|
|
5247
5661
|
}
|
|
5248
5662
|
return formatWorkflowResult(mode, outcomes);
|
|
5249
5663
|
}
|
|
@@ -5256,11 +5670,12 @@ var init_workflow = __esm({
|
|
|
5256
5670
|
// ../core/src/tool/tsHost.ts
|
|
5257
5671
|
import fsSync3 from "fs";
|
|
5258
5672
|
import path16 from "path";
|
|
5259
|
-
var _ts, _tsTried, getTs, buildDefaultOptions, findTsConfigBounded, resolveTsConfig, createProjectHost, lsCache, getLanguageService, realpathNative, posToLineCol, SUPPORTED_SOURCE_EXTS, checkSupportedSourceExt, lineColToPos;
|
|
5673
|
+
var _ts, _tsTried, getTs, buildDefaultOptions, findTsConfigBounded, tsconfigWalkCache, tsconfigParseCache, resolveTsConfig, createProjectHost, lsCache, getLanguageService, realpathNative, posToLineCol, SUPPORTED_SOURCE_EXTS, checkSupportedSourceExt, lineColToPos;
|
|
5260
5674
|
var init_tsHost = __esm({
|
|
5261
5675
|
"../core/src/tool/tsHost.ts"() {
|
|
5262
5676
|
"use strict";
|
|
5263
5677
|
init_guard();
|
|
5678
|
+
init_type();
|
|
5264
5679
|
_ts = null;
|
|
5265
5680
|
_tsTried = false;
|
|
5266
5681
|
getTs = async () => {
|
|
@@ -5303,16 +5718,38 @@ var init_tsHost = __esm({
|
|
|
5303
5718
|
}
|
|
5304
5719
|
return void 0;
|
|
5305
5720
|
};
|
|
5721
|
+
tsconfigWalkCache = /* @__PURE__ */ new Map();
|
|
5722
|
+
tsconfigParseCache = /* @__PURE__ */ new Map();
|
|
5306
5723
|
resolveTsConfig = (ts, absPath) => {
|
|
5307
|
-
const
|
|
5724
|
+
const startDir = path16.dirname(absPath);
|
|
5725
|
+
let tsConfigPath = tsconfigWalkCache.get(startDir);
|
|
5726
|
+
if (!tsConfigPath) {
|
|
5727
|
+
tsConfigPath = findTsConfigBounded(ts, absPath) ?? "";
|
|
5728
|
+
if (tsConfigPath) tsconfigWalkCache.set(startDir, tsConfigPath);
|
|
5729
|
+
}
|
|
5308
5730
|
if (!tsConfigPath) {
|
|
5309
5731
|
return { options: buildDefaultOptions(ts), fileNames: [], projectRoot: getContainingRoot(absPath) };
|
|
5310
5732
|
}
|
|
5733
|
+
let st;
|
|
5734
|
+
try {
|
|
5735
|
+
st = fsSync3.statSync(tsConfigPath, { throwIfNoEntry: false });
|
|
5736
|
+
} catch {
|
|
5737
|
+
st = void 0;
|
|
5738
|
+
}
|
|
5739
|
+
const cached2 = tsconfigParseCache.get(tsConfigPath);
|
|
5740
|
+
if (cached2 && st && st.mtimeMs === cached2.mtimeMs) return cached2.resolved;
|
|
5741
|
+
if (!st) {
|
|
5742
|
+
tsconfigParseCache.delete(tsConfigPath);
|
|
5743
|
+
for (const [dir, p] of tsconfigWalkCache) if (p === tsConfigPath) tsconfigWalkCache.delete(dir);
|
|
5744
|
+
return resolveTsConfig(ts, absPath);
|
|
5745
|
+
}
|
|
5311
5746
|
const basePath = path16.dirname(tsConfigPath);
|
|
5312
5747
|
const raw = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
|
|
5313
5748
|
if (raw.error) return { options: buildDefaultOptions(ts), fileNames: [], projectRoot: basePath };
|
|
5314
5749
|
const parsed = ts.parseJsonConfigFileContent(raw.config, ts.sys, basePath);
|
|
5315
|
-
|
|
5750
|
+
const resolved = { options: parsed.options, fileNames: parsed.fileNames, projectRoot: basePath };
|
|
5751
|
+
tsconfigParseCache.set(tsConfigPath, { mtimeMs: st.mtimeMs, resolved });
|
|
5752
|
+
return resolved;
|
|
5316
5753
|
};
|
|
5317
5754
|
createProjectHost = (ts, projectRoot, options, rootFileNames) => {
|
|
5318
5755
|
const cache = /* @__PURE__ */ new Map();
|
|
@@ -5406,7 +5843,7 @@ var init_tsHost = __esm({
|
|
|
5406
5843
|
checkSupportedSourceExt = (displayPath) => {
|
|
5407
5844
|
const ext = path16.extname(displayPath).toLowerCase();
|
|
5408
5845
|
if (SUPPORTED_SOURCE_EXTS.has(ext)) return null;
|
|
5409
|
-
return
|
|
5846
|
+
return toolFailure(`[\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`);
|
|
5410
5847
|
};
|
|
5411
5848
|
lineColToPos = (ts, sf, line1, col1) => ts.getPositionOfLineAndCharacter(sf, Math.max(0, line1 - 1), Math.max(0, col1 - 1));
|
|
5412
5849
|
}
|
|
@@ -5417,13 +5854,22 @@ import fs13 from "fs/promises";
|
|
|
5417
5854
|
import path17 from "path";
|
|
5418
5855
|
import { createReadStream } from "fs";
|
|
5419
5856
|
import * as readline from "readline";
|
|
5420
|
-
var isSensitiveReadTarget, stripReadFileLineNumbers, maskSecretsInContent, makeTmpPath, ATOMIC_TMP_RE, sweepStaleAtomicTmp, assertReadable, stripEdgeBlankLines, matchLineBlockWith, diagnoseOldStr, reindentToBase, alignIndentsByAnchor, applyOneEditToContent, fsTools;
|
|
5857
|
+
var IMAGE_MIME_BY_EXT, isSensitiveReadTarget, stripReadFileLineNumbers, maskSecretsInContent, makeTmpPath, ATOMIC_TMP_RE, sweepStaleAtomicTmp, assertReadable, stripEdgeBlankLines, matchLineBlockWith, diagnoseOldStr, reindentToBase, alignIndentsByAnchor, applyOneEditToContent, fsTools;
|
|
5421
5858
|
var init_fs = __esm({
|
|
5422
5859
|
"../core/src/tool/registry/fs.ts"() {
|
|
5423
5860
|
"use strict";
|
|
5424
5861
|
init_type();
|
|
5425
5862
|
init_tsHost();
|
|
5426
5863
|
init_guard();
|
|
5864
|
+
init_contentParts();
|
|
5865
|
+
IMAGE_MIME_BY_EXT = {
|
|
5866
|
+
".png": "image/png",
|
|
5867
|
+
".jpg": "image/jpeg",
|
|
5868
|
+
".jpeg": "image/jpeg",
|
|
5869
|
+
".gif": "image/gif",
|
|
5870
|
+
".webp": "image/webp",
|
|
5871
|
+
".bmp": "image/bmp"
|
|
5872
|
+
};
|
|
5427
5873
|
isSensitiveReadTarget = (resolvedPath) => {
|
|
5428
5874
|
const p = resolvedPath.toLowerCase().replace(/\\/g, "/");
|
|
5429
5875
|
return [
|
|
@@ -5639,15 +6085,15 @@ var init_fs = __esm({
|
|
|
5639
6085
|
};
|
|
5640
6086
|
}
|
|
5641
6087
|
if (lm.reason === "conflict") {
|
|
5642
|
-
return { ok: false, error:
|
|
6088
|
+
return { ok: false, error: toolFailure(`[\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1A\u4EE3\u7801\u51B2\u7A81\uFF01old_str\uFF08${tag}\u5F52\u4E00\u540E\uFF09\u5728\u5168\u6587\u4E2D\u4E0D\u552F\u4E00\uFF08\u5171 ${lm.count} \u5904\uFF09\u3002\u8BF7\u591A\u5305\u88F9\u51E0\u884C\u4E0A\u4E0B\u6587\uFF0C\u6216\u663E\u5F0F\u8BBE replace_all=true \u6279\u91CF\u66FF\u6362\u3002`) };
|
|
5643
6089
|
}
|
|
5644
6090
|
}
|
|
5645
6091
|
const diag = diagnoseOldStr(normalizedContent, normalizedOldRaw);
|
|
5646
|
-
return { ok: false, error:
|
|
6092
|
+
return { ok: false, error: toolFailure(`[\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1A\u672A\u80FD\u5728\u6587\u4EF6\u4E2D\u627E\u5230\u6307\u5B9A\u7684 old_str \u65E7\u4EE3\u7801\u5757\u3002${diag}\u5E38\u89C1\u539F\u56E0\uFF1A\u2460 \u8BEF\u5E26\u4E86 read_file \u7684\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\uFF1B\u2461 \u7F29\u8FDB\uFF08Tab/\u7A7A\u683C\uFF09\u4E0D\u4E00\u81F4\uFF1B\u2462 \u884C\u5C3E\u591A\u4F59\u7A7A\u683C\uFF1B\u2463 \u6587\u4EF6\u5DF2\u88AB\u6539\u52A8/old_str \u975E\u8FDE\u7EED\u6574\u6BB5\u3002\u8BF7\u7528 read_file \u91CD\u65B0\u6838\u5BF9\u8BE5\u5904\u7247\u6BB5\uFF08\u53BB\u6389\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\u3001\u4FDD\u7559\u539F\u59CB Tab/\u7A7A\u683C\u7F29\u8FDB\uFF09\u540E\u91CD\u8BD5\u3002\u26A0\uFE0F \u4E25\u7981\u6539\u7528 run_command \u8C03\u7528 python/node/sed/awk \u7B49\u811A\u672C\u7ED5\u8FC7\u672C\u5DE5\u5177\u4FEE\u6539\u6587\u4EF6\u3002`) };
|
|
5647
6093
|
}
|
|
5648
6094
|
const matchCount = normalizedContent.split(normalizedOld).length - 1;
|
|
5649
6095
|
if (!replaceAll && matchCount > 1) {
|
|
5650
|
-
return { ok: false, error:
|
|
6096
|
+
return { ok: false, error: toolFailure(`[\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1A\u4EE3\u7801\u51B2\u7A81\uFF01old_str \u5728\u5168\u6587\u4E2D\u4E0D\u552F\u4E00\uFF08\u5171\u53D1\u73B0\u4E86 ${matchCount} \u5904\uFF09\u3002\u8BF7\u5411\u4E0A\u6216\u5411\u4E0B\u591A\u5305\u88F9\u51E0\u884C\u4E0A\u4E0B\u6587\u518D\u63D0\u8BF7\u4FEE\u6539\uFF0C\u6216\u663E\u5F0F\u8BBE replace_all=true \u6279\u91CF\u66FF\u6362\u3002`) };
|
|
5651
6097
|
}
|
|
5652
6098
|
const oldFirstNonBlank = normalizedOld.split("\n").find((l) => l.trim() !== "") ?? "";
|
|
5653
6099
|
const baseIndent = oldFirstNonBlank.match(/^[ \t]*/)?.[0] ?? "";
|
|
@@ -5664,7 +6110,10 @@ var init_fs = __esm({
|
|
|
5664
6110
|
type: "function",
|
|
5665
6111
|
function: {
|
|
5666
6112
|
name: "read_file",
|
|
5667
|
-
|
|
6113
|
+
// ★ #8a 策略声明:计划模式可用;权限规则作用域主参数
|
|
6114
|
+
planAllowed: true,
|
|
6115
|
+
primaryArg: "path",
|
|
6116
|
+
description: "\u8BFB\u53D6\u6307\u5B9A\u3010\u6587\u672C\u3011\u6587\u4EF6\u7684\u6587\u672C\u5185\u5BB9\uFF0C\u5E76\u81EA\u52A8\u5E26\u4E0A\u7528\u4E8E\u5BF9\u9F50\u5B9A\u4F4D\u7684\u7269\u7406\u884C\u53F7\u3002\u652F\u6301\u5927\u6587\u4EF6\u5206\u7247\u8BFB\u53D6\uFF0C\u9632\u6B62 Token \u7206\u70B8\u3002\u2605 \u4EC5\u5904\u7406\u6587\u672C\u6587\u4EF6\u2014\u2014\u4E8C\u8FDB\u5236\u6587\u4EF6\u4F1A\u8BFB\u51FA\u4E71\u7801\uFF1A.xlsx \u6539\u7528 read_xlsx\uFF0C.docx \u6539\u7528 read_docx\uFF0C.pdf \u6539\u7528 read_pdf\u3002\u2605 \u9700\u8BFB\u591A\u4E2A\u6587\u4EF6\u65F6\uFF0C\u628A\u591A\u4E2A read_file \u8C03\u7528\u653E\u8FDB\u540C\u4E00\u6761\u6D88\u606F\u5E76\u884C\u53D1\u51FA\uFF08\u81EA\u52A8\u5E76\u53D1\u6267\u884C\uFF09\uFF0C\u52FF\u8BFB\u5B8C\u4E00\u4E2A\u518D\u53D1\u4E0B\u4E00\u4E2A\u3002",
|
|
5668
6117
|
parameters: {
|
|
5669
6118
|
type: "object",
|
|
5670
6119
|
properties: {
|
|
@@ -5685,6 +6134,7 @@ var init_fs = __esm({
|
|
|
5685
6134
|
try {
|
|
5686
6135
|
const absPath = resolveReadablePath(args.path);
|
|
5687
6136
|
const lowerExt = absPath.toLowerCase();
|
|
6137
|
+
if (IMAGE_MIME_BY_EXT[path17.extname(lowerExt)]) return `\u{1F5BC} [${args.path}] \u662F\u56FE\u7247\u6587\u4EF6\uFF0Cread_file \u8BFB\u4E0D\u51FA\u6709\u7528\u5185\u5BB9\u3002\u8BF7\u6539\u7528 read_image \u8BFB\u53D6\uFF08\u56FE\u50CF\u4F1A\u4EE5\u89C6\u89C9\u9644\u4EF6\u76F4\u63A5\u63D0\u4F9B\u7ED9\u6A21\u578B\u5206\u6790\uFF09\u3002`;
|
|
5688
6138
|
if (lowerExt.endsWith(".xlsx")) return `\u26A0\uFE0F [${args.path}] \u662F Excel \u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0Cread_file \u8BFB\u4E0D\u4E86\uFF08UTF-8 \u89E3\u7801\u6EE1\u5C4F\u4E71\u7801\uFF09\u3002\u8BF7\u6539\u7528 read_xlsx\uFF08\u652F\u6301 sheet \u9009\u62E9 / \u7FFB\u9875 / Markdown \u8868\u683C\u8F93\u51FA\uFF09\u3002`;
|
|
5689
6139
|
if (lowerExt.endsWith(".docx")) return `\u26A0\uFE0F [${args.path}] \u662F Word \u4E8C\u8FDB\u5236\u6587\u6863\uFF0Cread_file \u8BFB\u4E0D\u4E86\u3002\u8BF7\u6539\u7528 read_docx \u63D0\u53D6\u6B63\u6587\u6587\u672C\u3002`;
|
|
5690
6140
|
if (lowerExt.endsWith(".pdf")) return `\u26A0\uFE0F [${args.path}] \u662F PDF \u4E8C\u8FDB\u5236\u6587\u6863\uFF0Cread_file \u8BFB\u4E0D\u4E86\u3002\u8BF7\u6539\u7528 read_pdf \u63D0\u53D6\u6587\u5B57\u5C42\u3002`;
|
|
@@ -5719,7 +6169,7 @@ ${formattedCode}${hasMore ? `
|
|
|
5719
6169
|
|
|
5720
6170
|
[... \u540E\u9762\u8FD8\u6709\u4EE3\u7801\u5DF2\u88AB\u9690\u85CF\uFF0C\u4F60\u53EF\u4EE5\u8C03\u6574 start_line \u7EE7\u7EED\u5206\u7247\u8BFB\u53D6\u3002]` : ""}`;
|
|
5721
6171
|
} catch (error) {
|
|
5722
|
-
return `\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25 [${args.path}]: ${error.message}
|
|
6172
|
+
return toolFailure(`\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25 [${args.path}]: ${error.message}`);
|
|
5723
6173
|
}
|
|
5724
6174
|
}
|
|
5725
6175
|
}
|
|
@@ -5728,7 +6178,9 @@ ${formattedCode}${hasMore ? `
|
|
|
5728
6178
|
type: "function",
|
|
5729
6179
|
function: {
|
|
5730
6180
|
name: "list_dir",
|
|
5731
|
-
|
|
6181
|
+
planAllowed: true,
|
|
6182
|
+
primaryArg: "path",
|
|
6183
|
+
description: "\u626B\u63CF\u5E76\u7CBE\u7B80\u5217\u51FA\u5F53\u524D\u9879\u76EE\u7684\u5DE5\u4F5C\u533A\u76EE\u5F55\u6811\u3002\u672C\u5DE5\u5177\u81EA\u52A8\u5408\u5E76\u901A\u7528\u5FFD\u7565\u89C4\u5219\u4E0E\u591A\u5C42\u5B50\u76EE\u5F55\u7EA7 .gitignore \u89C4\u8303\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
5732
6184
|
parameters: {
|
|
5733
6185
|
type: "object",
|
|
5734
6186
|
properties: {
|
|
@@ -5781,7 +6233,7 @@ ${formattedCode}${hasMore ? `
|
|
|
5781
6233
|
return `[Workspace Universal Tree | Max Depth: ${maxDepth}]
|
|
5782
6234
|
${treeResult}`;
|
|
5783
6235
|
} catch (error) {
|
|
5784
|
-
return `\u9879\u76EE\u6811\u626B\u63CF\u5931\u8D25: ${error.message}
|
|
6236
|
+
return toolFailure(`\u9879\u76EE\u6811\u626B\u63CF\u5931\u8D25: ${error.message}`);
|
|
5785
6237
|
}
|
|
5786
6238
|
}
|
|
5787
6239
|
}
|
|
@@ -5790,6 +6242,10 @@ ${treeResult}`;
|
|
|
5790
6242
|
type: "function",
|
|
5791
6243
|
function: {
|
|
5792
6244
|
name: "edit_file",
|
|
6245
|
+
// ★ #8a 策略声明:undo 备份(快照原内容)+ 分类器作用域 + 权限主参数;计划模式缺省拒绝
|
|
6246
|
+
triggersUndo: "overwrite",
|
|
6247
|
+
autoApproval: "file",
|
|
6248
|
+
primaryArg: "path",
|
|
5793
6249
|
description: "\u5BF9\u6587\u4EF6\u505A\u5C40\u90E8\u7CBE\u51C6\u4FEE\u6539\u3002\u2605 \u540C\u4E00\u6587\u4EF6\u591A\u5904\u8981\u6539\u65F6\u4E00\u6B21\u4F20 edits \u6570\u7EC4\u5168\u90E8\u5B8C\u6210\uFF08\u6309\u5E8F\u5E94\u7528\u3001\u6574\u4F53\u539F\u5B50\uFF1A\u4EFB\u4E00\u5904\u5931\u8D25\u5168\u90E8\u4E0D\u5199\u5165\uFF09\uFF0C\u52FF\u9010\u5904\u591A\u6B21\u8C03\u7528\u3002old_str \u987B\u4E0E\u6587\u4EF6\u539F\u6587\u9010\u5B57\u7B26\u4E00\u81F4\uFF1A\u53BB\u6389 read_file \u8FD4\u56DE\u7684\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\uFF0C\u4FDD\u7559\u539F\u7F29\u8FDB\uFF08Tab/\u7A7A\u683C\uFF09\u4E0E\u884C\u5C3E\u7A7A\u767D\u3002\u9ED8\u8BA4\u987B\u5168\u6587\u552F\u4E00\uFF1Breplace_all=true \u66FF\u6362\u5168\u90E8\u5339\u914D\uFF08\u6279\u91CF\u91CD\u547D\u540D/\u7EDF\u4E00\u6539\u5199\uFF09\u3002",
|
|
5794
6250
|
parameters: {
|
|
5795
6251
|
type: "object",
|
|
@@ -5830,7 +6286,7 @@ ${patches}`;
|
|
|
5830
6286
|
try {
|
|
5831
6287
|
const editList = args.edits && args.edits.length > 0 ? args.edits : [{ old_str: args.old_str ?? "", new_str: args.new_str ?? "", replace_all: args.replace_all }];
|
|
5832
6288
|
if (editList.length === 0 || editList.some((e) => typeof e.old_str !== "string" || e.old_str.length === 0)) {
|
|
5833
|
-
return
|
|
6289
|
+
return toolFailure(`[\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`);
|
|
5834
6290
|
}
|
|
5835
6291
|
const absPath = resolveSafePath(args.path);
|
|
5836
6292
|
const rawContent = await fs13.readFile(absPath, "utf-8");
|
|
@@ -5840,7 +6296,7 @@ ${patches}`;
|
|
|
5840
6296
|
for (let i = 0; i < editList.length; i++) {
|
|
5841
6297
|
const r = applyOneEditToContent(content, editList[i].old_str, editList[i].new_str ?? "", !!editList[i].replace_all);
|
|
5842
6298
|
if (!r.ok) {
|
|
5843
|
-
return editList.length === 1 ? r.error :
|
|
6299
|
+
return editList.length === 1 ? r.error : toolFailure(`[\u4EE3\u7801\u4FEE\u8865\u5931\u8D25]\uFF1Aedits \u7B2C ${i + 1}/${editList.length} \u6761\u672A\u547D\u4E2D\uFF0C\u5DF2\u6574\u4F53\u653E\u5F03\uFF08\u6587\u4EF6\u672A\u505A\u4EFB\u4F55\u6539\u52A8\uFF0C\u53EF\u4FEE\u6B63\u8BE5\u6761\u540E\u6574\u7EC4\u91CD\u8BD5\uFF09\u3002${r.error.content.replace(/^❌ \[代码修补失败\]:/, "")}`);
|
|
5844
6300
|
}
|
|
5845
6301
|
content = r.content;
|
|
5846
6302
|
summaries.push(editList.length === 1 ? r.summary : ` ${i + 1}. ${r.summary}`);
|
|
@@ -5850,7 +6306,7 @@ ${patches}`;
|
|
|
5850
6306
|
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
|
|
5851
6307
|
${summaries.join("\n")}`;
|
|
5852
6308
|
} catch (error) {
|
|
5853
|
-
return `\u64CD\u4F5C\u5931\u8D25: ${error.message}
|
|
6309
|
+
return toolFailure(`\u64CD\u4F5C\u5931\u8D25: ${error.message}`);
|
|
5854
6310
|
}
|
|
5855
6311
|
}
|
|
5856
6312
|
}
|
|
@@ -5859,6 +6315,9 @@ ${summaries.join("\n")}`;
|
|
|
5859
6315
|
type: "function",
|
|
5860
6316
|
function: {
|
|
5861
6317
|
name: "create_file",
|
|
6318
|
+
triggersUndo: "create",
|
|
6319
|
+
autoApproval: "file",
|
|
6320
|
+
primaryArg: "path",
|
|
5862
6321
|
description: "\u5728\u5DE5\u4F5C\u533A\u5185\u521B\u5EFA\u4E00\u4E2A\u5168\u65B0\u7684\u6587\u4EF6\uFF0C\u5E76\u5199\u5165\u521D\u59CB\u5185\u5BB9\u3002\u5982\u679C\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u672C\u5DE5\u5177\u4F1A\u62D2\u7EDD\u6267\u884C\u4EE5\u9632\u6B62\u6E90\u7801\u88AB\u5168\u91CF\u8BEF\u8986\u76D6\u3002\u8BF7\u76F4\u63A5\u5199\u5165\u7528\u6237\u6307\u5B9A\u7684\u6700\u7EC8\u8DEF\u5F84\uFF0C\u52FF\u81EA\u884C\u53D1\u660E\u6682\u5B58/\u4E34\u65F6\u76EE\u5F55\uFF08\u5982 .dsc_tmp\uFF09\u2014\u2014\u4EA7\u7269\u4F1A\u771F\u5B9E\u843D\u76D8\u4E14\u5BF9\u7528\u6237\u53EF\u89C1\u3002",
|
|
5863
6322
|
parameters: {
|
|
5864
6323
|
type: "object",
|
|
@@ -5877,7 +6336,7 @@ ${summaries.join("\n")}`;
|
|
|
5877
6336
|
const absPath = resolveSafePath(args.path);
|
|
5878
6337
|
try {
|
|
5879
6338
|
await fs13.access(absPath);
|
|
5880
|
-
return
|
|
6339
|
+
return toolFailure(`[\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`);
|
|
5881
6340
|
} catch (e) {
|
|
5882
6341
|
if (e?.code !== "ENOENT") throw e;
|
|
5883
6342
|
}
|
|
@@ -5889,7 +6348,7 @@ ${summaries.join("\n")}`;
|
|
|
5889
6348
|
await fs13.rename(tmpPath, absPath);
|
|
5890
6349
|
return `\u2705 [\u521B\u5EFA\u6210\u529F]\uFF1A\u65B0\u6587\u4EF6 [${args.path}] \u5DF2\u521B\u5EFA\uFF0C\u5199\u5165 ${content.length} \u5B57\u7B26\u3002`;
|
|
5891
6350
|
} catch (error) {
|
|
5892
|
-
return `\u64CD\u4F5C\u5931\u8D25: ${error.message}
|
|
6351
|
+
return toolFailure(`\u64CD\u4F5C\u5931\u8D25: ${error.message}`);
|
|
5893
6352
|
} finally {
|
|
5894
6353
|
if (tmpPath) {
|
|
5895
6354
|
try {
|
|
@@ -5905,6 +6364,9 @@ ${summaries.join("\n")}`;
|
|
|
5905
6364
|
type: "function",
|
|
5906
6365
|
function: {
|
|
5907
6366
|
name: "delete_path",
|
|
6367
|
+
triggersUndo: "delete",
|
|
6368
|
+
autoApproval: "file",
|
|
6369
|
+
primaryArg: "path",
|
|
5908
6370
|
description: "\u4ECE\u672C\u5730\u78C1\u76D8\u5185\u6C38\u4E45\u5220\u9664\u4E00\u4E2A\u6307\u5B9A\u7684\u6587\u4EF6\u6216\u8005\u4E00\u6574\u4E2A\u6587\u4EF6\u5939\u76EE\u5F55\u3002\u5982\u679C\u662F\u76EE\u5F55\uFF0C\u5DE5\u5177\u4F1A\u81EA\u52A8\u6267\u884C\u6DF1\u5EA6\u9012\u5F52\u5F3A\u884C\u9500\u6BC1\u3002\u6B64\u64CD\u4F5C\u4E0D\u53EF\u9006\uFF0C\u8BF7\u4E07\u5206\u5C0F\u5FC3\u3002",
|
|
5909
6371
|
parameters: {
|
|
5910
6372
|
type: "object",
|
|
@@ -5940,18 +6402,18 @@ ${summaries.join("\n")}`;
|
|
|
5940
6402
|
try {
|
|
5941
6403
|
const cleanPath = (args.path || "").trim();
|
|
5942
6404
|
if (!cleanPath || cleanPath === "." || cleanPath === "./" || cleanPath === "/") {
|
|
5943
|
-
return
|
|
6405
|
+
return toolFailure(`[\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`);
|
|
5944
6406
|
}
|
|
5945
6407
|
const absPath = resolveSafePath(cleanPath);
|
|
5946
6408
|
const rel = path17.relative(getActiveWorkspaceRoot(), absPath);
|
|
5947
6409
|
if (!rel || rel === "" || rel === "src" || rel.startsWith("..") || path17.isAbsolute(rel)) {
|
|
5948
|
-
return
|
|
6410
|
+
return toolFailure(`[\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`);
|
|
5949
6411
|
}
|
|
5950
6412
|
let stat;
|
|
5951
6413
|
try {
|
|
5952
6414
|
stat = await fs13.stat(absPath);
|
|
5953
6415
|
} catch {
|
|
5954
|
-
return
|
|
6416
|
+
return toolFailure(`[\u9500\u6BC1\u5931\u8D25]\uFF1A\u5728\u5DE5\u4F5C\u533A\u5185\u672A\u627E\u5230\u6307\u5B9A\u7684\u8DEF\u5F84 [${cleanPath}]\u3002`);
|
|
5955
6417
|
}
|
|
5956
6418
|
const isDirectory = stat.isDirectory();
|
|
5957
6419
|
assertWithinWorkspace(absPath);
|
|
@@ -5963,7 +6425,7 @@ ${summaries.join("\n")}`;
|
|
|
5963
6425
|
const targetTypeLabel = isDirectory ? "\u4E00\u6574\u4E2A\u6587\u4EF6\u5939\u76EE\u5F55" : "\u7EAF\u7269\u7406\u6587\u4EF6";
|
|
5964
6426
|
return `\u2705 [\u8DEF\u5F84\u9500\u6BC1\u6210\u529F]\uFF1A\u5DF2\u6210\u529F\u6C38\u4E45\u9500\u6BC1${targetTypeLabel} [${cleanPath}]\u3002`;
|
|
5965
6427
|
} catch (error) {
|
|
5966
|
-
return `\u64CD\u4F5C\u5931\u8D25: ${error.message}
|
|
6428
|
+
return toolFailure(`\u64CD\u4F5C\u5931\u8D25: ${error.message}`);
|
|
5967
6429
|
}
|
|
5968
6430
|
}
|
|
5969
6431
|
}
|
|
@@ -5972,6 +6434,9 @@ ${summaries.join("\n")}`;
|
|
|
5972
6434
|
type: "function",
|
|
5973
6435
|
function: {
|
|
5974
6436
|
name: "write_file",
|
|
6437
|
+
triggersUndo: "overwrite",
|
|
6438
|
+
autoApproval: "file",
|
|
6439
|
+
primaryArg: "path",
|
|
5975
6440
|
description: "\u5C06\u5B8C\u6574\u5185\u5BB9\u5168\u91CF\u5199\u5165\u6307\u5B9A\u6587\u4EF6\uFF08\u8986\u76D6\uFF09\u3002\u6587\u4EF6\u4E0D\u5B58\u5728\u5219\u65B0\u5EFA\uFF08\u542B\u7236\u76EE\u5F55\uFF09\uFF1B\u5DF2\u5B58\u5728\u5219\u6574\u4F53\u8986\u76D6\u3002\u2605 \u4EC5\u7528\u4E8E\u3010\u65B0\u5EFA\u6587\u4EF6\u3011\u6216\u3010\u5F7B\u5E95\u91CD\u5199\u6574\u4E2A\u6587\u4EF6\u3011\uFF1B\u4FEE\u6539\u65E2\u6709\u6587\u4EF6\u4E00\u5F8B\u6539\u7528 edit_file\uFF08\u5C40\u90E8\u7CBE\u51C6\u66FF\u6362\u3001\u6700\u5C0F diff\uFF09\u3002",
|
|
5976
6441
|
parameters: {
|
|
5977
6442
|
type: "object",
|
|
@@ -6001,7 +6466,7 @@ ${summaries.join("\n")}`;
|
|
|
6001
6466
|
} catch {
|
|
6002
6467
|
}
|
|
6003
6468
|
}
|
|
6004
|
-
return `\u64CD\u4F5C\u5931\u8D25: ${error.message}
|
|
6469
|
+
return toolFailure(`\u64CD\u4F5C\u5931\u8D25: ${error.message}`);
|
|
6005
6470
|
}
|
|
6006
6471
|
}
|
|
6007
6472
|
}
|
|
@@ -6010,7 +6475,8 @@ ${summaries.join("\n")}`;
|
|
|
6010
6475
|
type: "function",
|
|
6011
6476
|
function: {
|
|
6012
6477
|
name: "view_symbol_outline",
|
|
6013
|
-
|
|
6478
|
+
planAllowed: true,
|
|
6479
|
+
description: "\u901A\u8FC7\u62BD\u8C61\u8BED\u6CD5\u6811(AST)\u5FEB\u901F\u63D0\u53D6\u6307\u5B9A TS/JS \u6E90\u6587\u4EF6\u4E2D\u7684\u7B26\u53F7\u5927\u7EB2\uFF08\u7C7B\u3001\u63A5\u53E3\u3001\u51FD\u6570\u540D\u3001\u5BFC\u51FA\u9879\u3001\u5165\u53C2\u7B7E\u540D\u7B49\uFF09\u3002\u9002\u5408\u5728\u4E0D\u8BFB\u53D6\u51E0\u5343\u884C\u5177\u4F53\u4EE3\u7801\u7684\u524D\u63D0\u4E0B\uFF0C\u5B8F\u89C2\u4E86\u89E3\u6587\u4EF6\u67B6\u6784\u3002\u4EC5\u652F\u6301 .ts/.tsx/.js/.jsx/.mjs/.cjs\uFF1B\u5176\u4ED6\u7C7B\u578B\u6587\u4EF6\uFF08.java/.vue/.py \u7B49\uFF09\u76F4\u63A5\u62D2\u7EDD\uFF0C\u8BF7\u6539\u7528 read_file\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
6014
6480
|
parameters: {
|
|
6015
6481
|
type: "object",
|
|
6016
6482
|
properties: {
|
|
@@ -6084,7 +6550,7 @@ ${summaries.join("\n")}`;
|
|
|
6084
6550
|
return `[File Symbol Outline: ${args.path}]
|
|
6085
6551
|
` + outlineLines.join("\n");
|
|
6086
6552
|
} catch (error) {
|
|
6087
|
-
return `\u7B26\u53F7\u5927\u7EB2\u5206\u6790\u5931\u8D25 [${args.path}]: ${error.message}
|
|
6553
|
+
return toolFailure(`\u7B26\u53F7\u5927\u7EB2\u5206\u6790\u5931\u8D25 [${args.path}]: ${error.message}`);
|
|
6088
6554
|
}
|
|
6089
6555
|
}
|
|
6090
6556
|
}
|
|
@@ -6097,6 +6563,11 @@ ${summaries.join("\n")}`;
|
|
|
6097
6563
|
// 注:move 涉及双路径(source+destination),超出当前 Undo 单路径 schema,暂不纳入写前备份(不可回退),
|
|
6098
6564
|
// 已在描述中明示;后续若扩展 UndoRecord 双路径字段可再接入。
|
|
6099
6565
|
name: "move_file",
|
|
6566
|
+
// ★ #8a 策略声明:双路径都受保护路径硬规则检查(P0-3 洞的声明化收口;特判已退役)。
|
|
6567
|
+
// 刻意不声明 triggersUndo:move 语义可手动移回,维持「不在 Undo 回退范围」现状。
|
|
6568
|
+
primaryArg: "src",
|
|
6569
|
+
autoApproval: "file",
|
|
6570
|
+
pathArgs: ["source", "destination"],
|
|
6100
6571
|
description: "\u79FB\u52A8\u6216\u91CD\u547D\u540D\u6587\u4EF6/\u76EE\u5F55\uFF08\u540C\u5377\u539F\u5B50\u64CD\u4F5C\uFF09\u3002\u6E90\u4E0D\u5B58\u5728\u5219\u5931\u8D25\uFF1B\u76EE\u6807\u5DF2\u5B58\u5728\u5219\u62D2\u7EDD\uFF08\u9632\u8BEF\u8986\u76D6\uFF0C\u5982\u9700\u8986\u76D6\u8BF7\u5148 delete_path \u518D move_file\uFF09\u3002\u81EA\u52A8\u521B\u5EFA\u76EE\u6807\u7236\u76EE\u5F55\u3002\u26A0\uFE0F \u672C\u64CD\u4F5C\u6682\u4E0D\u5728 Undo \u56DE\u9000\u8303\u56F4\u5185\uFF08\u4E0D\u53EF\u64A4\u9500\uFF09\u3002",
|
|
6101
6572
|
parameters: {
|
|
6102
6573
|
type: "object",
|
|
@@ -6116,11 +6587,11 @@ ${summaries.join("\n")}`;
|
|
|
6116
6587
|
try {
|
|
6117
6588
|
await fs13.access(srcAbs);
|
|
6118
6589
|
} catch {
|
|
6119
|
-
return
|
|
6590
|
+
return toolFailure(`[\u79FB\u52A8\u5931\u8D25]\uFF1A\u6E90\u8DEF\u5F84 [${args.source}] \u4E0D\u5B58\u5728\u3002`);
|
|
6120
6591
|
}
|
|
6121
6592
|
try {
|
|
6122
6593
|
await fs13.access(dstAbs);
|
|
6123
|
-
return
|
|
6594
|
+
return toolFailure(`[\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`);
|
|
6124
6595
|
} catch {
|
|
6125
6596
|
}
|
|
6126
6597
|
assertWithinWorkspace(srcAbs);
|
|
@@ -6129,7 +6600,51 @@ ${summaries.join("\n")}`;
|
|
|
6129
6600
|
await fs13.rename(srcAbs, dstAbs);
|
|
6130
6601
|
return `\u2705 [\u79FB\u52A8\u6210\u529F]\uFF1A[${args.source}] \u2192 [${args.destination}]\u3002`;
|
|
6131
6602
|
} catch (error) {
|
|
6132
|
-
return `\u64CD\u4F5C\u5931\u8D25: ${error.message}
|
|
6603
|
+
return toolFailure(`\u64CD\u4F5C\u5931\u8D25: ${error.message}`);
|
|
6604
|
+
}
|
|
6605
|
+
}
|
|
6606
|
+
}
|
|
6607
|
+
},
|
|
6608
|
+
{
|
|
6609
|
+
type: "function",
|
|
6610
|
+
function: {
|
|
6611
|
+
name: "read_image",
|
|
6612
|
+
// ★ #8a 策略声明:计划模式可用(只读);权限规则作用域主参数
|
|
6613
|
+
planAllowed: true,
|
|
6614
|
+
primaryArg: "path",
|
|
6615
|
+
description: "\u8BFB\u53D6\u6307\u5B9A\u3010\u56FE\u7247\u3011\u6587\u4EF6\u5E76\u628A\u56FE\u50CF\u5185\u5BB9\u63D0\u4F9B\u7ED9\u6A21\u578B\u505A\u89C6\u89C9\u5206\u6790\uFF08png/jpg/jpeg/gif/webp/bmp\uFF0C\u22648MB\uFF09\u3002\u9002\u7528\uFF1A\u622A\u56FE\u8C03\u8BD5\u3001UI \u5BF9\u7167\u8FD8\u539F\u3001\u67E5\u770B\u56FE\u7247\u7D20\u6750\u3002\u56FE\u50CF\u4EE5\u89C6\u89C9\u9644\u4EF6\u6CE8\u5165\u5BF9\u8BDD\uFF08\u968F\u540E\u7684\u4E00\u6761\u6D88\u606F\uFF09\uFF0C\u4E0D\u8BA1\u5165\u672C\u5DE5\u5177\u7684\u6587\u672C\u8F93\u51FA\uFF1B\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u89C6\u89C9\u65F6\u4F1A\u660E\u786E\u63D0\u793A\u3002\u6587\u672C\u6587\u4EF6\u8BF7\u7528 read_file\u3002",
|
|
6616
|
+
parameters: {
|
|
6617
|
+
type: "object",
|
|
6618
|
+
properties: {
|
|
6619
|
+
path: { type: "string", description: "\u56FE\u7247\u8DEF\u5F84\uFF1A\u76F8\u5BF9\u6D3B\u52A8\u5DE5\u4F5C\u533A\u6839\uFF08\u652F\u6301 ../ \u8DE8\u5144\u5F1F\u9879\u76EE\uFF09\u3001\u6216\u7EDD\u5BF9\u8DEF\u5F84" }
|
|
6620
|
+
},
|
|
6621
|
+
required: ["path"]
|
|
6622
|
+
},
|
|
6623
|
+
safetyLevel: "safe" /* SAFE */,
|
|
6624
|
+
isSync: true,
|
|
6625
|
+
async execute(args) {
|
|
6626
|
+
try {
|
|
6627
|
+
const absPath = resolveReadablePath(args.path);
|
|
6628
|
+
const readBlock = await assertReadable(absPath, args.path);
|
|
6629
|
+
if (readBlock) return readBlock;
|
|
6630
|
+
const mime = IMAGE_MIME_BY_EXT[path17.extname(absPath).toLowerCase()];
|
|
6631
|
+
if (!mime) return toolFailure(`[read_image] \u4E0D\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F [${args.path}]\uFF1A\u4EC5\u652F\u6301 png/jpg/jpeg/gif/webp/bmp\u3002\u6587\u672C\u6587\u4EF6\u8BF7\u7528 read_file\u3002`);
|
|
6632
|
+
const st = await fs13.stat(absPath).catch(() => null);
|
|
6633
|
+
if (!st || !st.isFile()) return toolFailure(`[read_image] \u56FE\u7247\u4E0D\u5B58\u5728\u6216\u4E0D\u662F\u6587\u4EF6\uFF1A${args.path}`);
|
|
6634
|
+
if (st.size > MAX_IMAGE_BYTES) {
|
|
6635
|
+
return toolFailure(`[read_image] \u56FE\u7247 ${(st.size / 1024 / 1024).toFixed(1)}MB \u8D85\u8FC7 ${Math.round(MAX_IMAGE_BYTES / 1024 / 1024)}MB \u4E0A\u9650\uFF1A\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\uFF0C\u6216\u88C1\u526A\u5230\u9700\u8981\u7684\u533A\u57DF\u3002`);
|
|
6636
|
+
}
|
|
6637
|
+
if (!isVisionEnabled()) {
|
|
6638
|
+
return toolFailure(`[read_image] \u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF08\u89C6\u89C9\u80FD\u529B\u6309\u7AEF\u70B9\u5B9E\u6D4B\u81EA\u52A8\u5224\u5B9A\uFF1B\u53EF\u5207\u6362 vision \u6A21\u578B\u6216\u8BBE DEEP_SEEK_VISION=1 \u5F3A\u5F00\u540E\u91CD\u8BD5\uFF09\u3002\u56FE\u7247\u672A\u8BFB\u53D6\uFF1A${args.path}`);
|
|
6639
|
+
}
|
|
6640
|
+
const buf = await fs13.readFile(absPath);
|
|
6641
|
+
return {
|
|
6642
|
+
content: `\u{1F5BC} [read_image] \u5DF2\u8BFB\u53D6\u56FE\u7247 ${args.path}\uFF08${mime}\uFF0C${st.size} \u5B57\u8282\uFF09\u3002\u56FE\u50CF\u5185\u5BB9\u89C1\u968F\u540E\u7684\u9644\u4EF6\u6D88\u606F\uFF0C\u8BF7\u76F4\u63A5\u5BF9\u56FE\u7247\u8FDB\u884C\u5206\u6790/\u5BF9\u7167\u3002`,
|
|
6643
|
+
status: "success",
|
|
6644
|
+
images: [{ name: path17.basename(absPath), mime, base64: buf.toString("base64") }]
|
|
6645
|
+
};
|
|
6646
|
+
} catch (error) {
|
|
6647
|
+
return toolFailure(`\u8BFB\u53D6\u56FE\u7247\u5931\u8D25 [${args.path}]: ${error.message}`);
|
|
6133
6648
|
}
|
|
6134
6649
|
}
|
|
6135
6650
|
}
|
|
@@ -6158,7 +6673,9 @@ var init_search = __esm({
|
|
|
6158
6673
|
type: "function",
|
|
6159
6674
|
function: {
|
|
6160
6675
|
name: "search_grep",
|
|
6161
|
-
|
|
6676
|
+
planAllowed: true,
|
|
6677
|
+
primaryArg: "query",
|
|
6678
|
+
description: "\u5728\u5DE5\u4F5C\u533A\u6587\u4EF6\u4E2D\u68C0\u7D22\u5339\u914D\u7684\u4EE3\u7801\u884C\uFF0C\u6BCF\u4E2A\u547D\u4E2D\u9ED8\u8BA4\u5E26\u524D\u540E\u5404 2 \u884C\u4E0A\u4E0B\u6587\uFF08\u53EF\u76F4\u63A5\u5224\u65AD\u7528\u6CD5\uFF1B\u6784\u9020 edit_file \u7684 old_str \u524D\u53EF\u7528 context \u8C03\u5927\u4E00\u6B21\u62FF\u8DB3\uFF09\u3002\u9ED8\u8BA4\u5B57\u9762\u91CF\u5339\u914D\uFF0C\u6B63\u5219\u4F20 is_regex=true\u3002\u2605 \u591A\u5173\u952E\u8BCD\u7528 is_regex=true \u4EE5 | \u5408\u5E76\uFF08\u5982 'uploadVisible|uploadTip'\uFF09\u4E00\u6B21\u67E5\u5B8C\uFF0C\u52FF\u9010\u8BCD\u591A\u6B21\u8C03\u7528\u3002path \u53EF\u9650\u5B9A\u76EE\u5F55\u6216\u6587\u4EF6\uFF08\u5355\u5927\u6587\u4EF6\u591A\u5904\u5B9A\u4F4D\u4F20\u6587\u4EF6\u8DEF\u5F84\u6700\u9AD8\u6548\uFF09\u3002\u591A\u6839\u5DE5\u4F5C\u533A\uFF1Apath \u53EF\u4F20\u9879\u76EE\u76EE\u5F55\u540D\uFF08\u5982 'frontend'\uFF09\u3001\u7EDD\u5BF9\u8DEF\u5F84\u6216 ../\u5144\u5F1F\u76EE\u5F55\u3002\u2605 \u7528\u6237\u6307\u660E\u4E86\u9879\u76EE\u65F6\u52A1\u5FC5\u628A\u8BE5\u9879\u76EE\u4F5C\u4E3A path \u4F20\u5165\u2014\u2014\u7F3A\u7701\u53EA\u641C\u6D3B\u52A8\u6839\uFF0C\u5E38\u4E0E\u610F\u56FE\u4E0D\u7B26\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
6162
6679
|
parameters: {
|
|
6163
6680
|
type: "object",
|
|
6164
6681
|
properties: {
|
|
@@ -6178,7 +6695,7 @@ var init_search = __esm({
|
|
|
6178
6695
|
async execute(args, ctx) {
|
|
6179
6696
|
try {
|
|
6180
6697
|
const cleanQuery = (args.query || "").trim();
|
|
6181
|
-
if (!cleanQuery) return "
|
|
6698
|
+
if (!cleanQuery) return toolFailure("[\u68C0\u7D22\u5931\u8D25]\uFF1A\u4F20\u5165\u7684\u68C0\u7D22\u5173\u952E\u8BCD\u4E0D\u80FD\u4E3A\u7A7A\u3002");
|
|
6182
6699
|
const pattern = args.is_regex ? cleanQuery : escapeRegExp(cleanQuery);
|
|
6183
6700
|
const resolveSearchRoot = () => {
|
|
6184
6701
|
if (!args.path) return ctx?.cwd ?? getActiveWorkspaceRoot();
|
|
@@ -6253,8 +6770,8 @@ var init_search = __esm({
|
|
|
6253
6770
|
return resultLines.join("\n");
|
|
6254
6771
|
} catch (error) {
|
|
6255
6772
|
if (error.code === 1) return `\u672A\u627E\u5230\u4E0E "${args.query}" \u76F8\u5173\u7684\u4EFB\u4F55\u4EE3\u7801\u5339\u914D\u9879\u3002`;
|
|
6256
|
-
if (error.killed || error.signal) return `\u23F3 [\u68C0\u7D22\u8D85\u65F6]\uFF1A30s \u5185\u672A\u5B8C\u6210\uFF08\u7591\u4F3C\u547D\u4E2D\u5DE8\u578B/\u5F02\u5E38\u6587\u4EF6\uFF09\u3002\u5EFA\u8BAE\u7F29\u5C0F\u5173\u952E\u8BCD\u6216\u9650\u5B9A\u76EE\u5F55\u540E\u91CD\u8BD5\u3002
|
|
6257
|
-
return `\u68C0\u7D22\u5931\u8D25: ${error.message}
|
|
6773
|
+
if (error.killed || error.signal) return toolFailure(`\u23F3 [\u68C0\u7D22\u8D85\u65F6]\uFF1A30s \u5185\u672A\u5B8C\u6210\uFF08\u7591\u4F3C\u547D\u4E2D\u5DE8\u578B/\u5F02\u5E38\u6587\u4EF6\uFF09\u3002\u5EFA\u8BAE\u7F29\u5C0F\u5173\u952E\u8BCD\u6216\u9650\u5B9A\u76EE\u5F55\u540E\u91CD\u8BD5\u3002`);
|
|
6774
|
+
return toolFailure(`\u68C0\u7D22\u5931\u8D25: ${error.message}`);
|
|
6258
6775
|
}
|
|
6259
6776
|
}
|
|
6260
6777
|
}
|
|
@@ -6263,6 +6780,7 @@ var init_search = __esm({
|
|
|
6263
6780
|
type: "function",
|
|
6264
6781
|
function: {
|
|
6265
6782
|
name: "read_project_guide",
|
|
6783
|
+
planAllowed: true,
|
|
6266
6784
|
description: "\u8BFB\u53D6\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u7684\u4E13\u5C5E AI \u884C\u4E3A\u6307\u5F15\u4E0E\u5F00\u53D1\u6307\u5357\uFF08\u4F9D\u6B21\u5C1D\u8BD5 CLAUDE.md / AGENTS.md / AGENT.md\uFF0C\u547D\u4E2D\u7B2C\u4E00\u4E2A\uFF09\u3002\u8BE5\u6307\u5357\u56FA\u5316\u4E86\u672C\u9879\u76EE\u7684\u6784\u5EFA\u547D\u4EE4\u3001\u8FD0\u884C\u6D4B\u8BD5\u89C4\u8303\u3001\u6838\u5FC3\u6280\u672F\u6808\u53CA\u4EE3\u7801\u98CE\u683C\u9650\u5236\u3002\u5728\u5BF9\u964C\u751F\u9879\u76EE\u5B9E\u65BD\u4EFB\u4F55\u6784\u5EFA\u6216\u6D4B\u8BD5\u547D\u4EE4\u524D\uFF0C\u5FC5\u987B\u4F18\u5148\u8BFB\u53D6\u6B64\u5DE5\u5177\u3002",
|
|
6267
6785
|
parameters: {
|
|
6268
6786
|
type: "object",
|
|
@@ -6328,6 +6846,8 @@ var init_command = __esm({
|
|
|
6328
6846
|
type: "function",
|
|
6329
6847
|
function: {
|
|
6330
6848
|
name: "run_command",
|
|
6849
|
+
primaryArg: "command",
|
|
6850
|
+
autoApproval: "command",
|
|
6331
6851
|
description: "\u5728\u5DE5\u4F5C\u533A\u6267\u884C shell \u547D\u4EE4\uFF08\u77ED\u5E73\u5FEB\u7684\u6D4B\u8BD5 / \u6784\u5EFA / git \u7B49\uFF09\uFF0C\u6D41\u5F0F\u8FD4\u56DE stdout/stderr \u5E76\u9644\u5E26\u9000\u51FA\u7801\u3002\u5C5E\u4E8E\u9AD8\u5371\u64CD\u4F5C\uFF0C\u6BCF\u6B21\u6267\u884C\u90FD\u9700\u8981\u7528\u6237\u5BA1\u6279\u3002\u9884\u8BA1\u8FD0\u884C\u6570\u5206\u949F\u4EE5\u4E0A\u7684\u957F\u4EFB\u52A1\uFF08\u5168\u91CF\u6D4B\u8BD5 / \u5927\u6784\u5EFA / \u5927\u4F53\u79EF\u5B89\u88C5\uFF09\u8BF7\u6539\u7528 run_in_background \u540E\u53F0\u6267\u884C\uFF1B\u82E5\u672C\u5DE5\u5177\u6267\u884C\u8FC7\u4E45\u4ECD\u672A\u7ED3\u675F\uFF0C\u7CFB\u7EDF\u4F1A\u81EA\u52A8\u628A\u8FDB\u7A0B\u8F6C\u5165\u540E\u53F0\u5E76\u8FD4\u56DE task_id\uFF08\u7528 get_background_output \u67E5\u7ED3\u679C\u3001stop_background_task \u7EC8\u6B62\uFF09\u3002",
|
|
6332
6852
|
parameters: {
|
|
6333
6853
|
type: "object",
|
|
@@ -6384,7 +6904,7 @@ ${tail}`,
|
|
|
6384
6904
|
let degradeReason = null;
|
|
6385
6905
|
const isWin = process.platform === "win32";
|
|
6386
6906
|
if (ctx?.abortSignal?.aborted) {
|
|
6387
|
-
yield
|
|
6907
|
+
yield toolFailure(`[\u5DF2\u4E2D\u6B62]\uFF1A\u547D\u4EE4 [${args.command}] \u672A\u6267\u884C\uFF08\u7528\u6237\u5DF2\u4E2D\u65AD\uFF09\u3002`).content;
|
|
6388
6908
|
yield EXIT_SENTINEL(-1);
|
|
6389
6909
|
return;
|
|
6390
6910
|
}
|
|
@@ -6401,7 +6921,7 @@ ${tail}`,
|
|
|
6401
6921
|
signal: ctx?.abortSignal
|
|
6402
6922
|
});
|
|
6403
6923
|
} catch (e) {
|
|
6404
|
-
yield
|
|
6924
|
+
yield toolFailure(`[\u542F\u52A8\u5931\u8D25]\uFF1Aspawn \u629B\u51FA\u5F02\u5E38\uFF08signal \u5DF2\u4E2D\u6B62\u6216\u547D\u4EE4\u975E\u6CD5\uFF09: ${e?.message ?? e}`).content;
|
|
6405
6925
|
yield EXIT_SENTINEL(-1);
|
|
6406
6926
|
return;
|
|
6407
6927
|
}
|
|
@@ -6643,7 +7163,9 @@ var init_glob = __esm({
|
|
|
6643
7163
|
type: "function",
|
|
6644
7164
|
function: {
|
|
6645
7165
|
name: "glob",
|
|
6646
|
-
|
|
7166
|
+
planAllowed: true,
|
|
7167
|
+
primaryArg: "pattern",
|
|
7168
|
+
description: "\u6309\u6587\u4EF6\u540D glob \u6A21\u5F0F\u5FEB\u901F\u67E5\u627E\u6587\u4EF6\uFF08\u5982 '**/*.ts'\u3001'src/**/test*'\u3001'**/*.test.ts'\uFF09\u3002\u2605 \u652F\u6301\u82B1\u62EC\u53F7\u591A\u9009\uFF1A'**/*.{ts,tsx,vue}'\u3001'src/{api,components}/**' \u4E00\u6B21\u67E5\u591A\u7C7B\u578B/\u591A\u76EE\u5F55\uFF0C\u52FF\u5206\u591A\u6B21\u8C03\u7528\u3002\u4E0E search_grep\uFF08\u6309\u5185\u5BB9\u68C0\u7D22\uFF09\u4E92\u8865\u3002\u81EA\u52A8\u5957\u7528 .gitignore / \u901A\u7528\u9ED1\u540D\u5355\u8FC7\u6EE4\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
6647
7169
|
parameters: {
|
|
6648
7170
|
type: "object",
|
|
6649
7171
|
properties: {
|
|
@@ -6657,7 +7179,7 @@ var init_glob = __esm({
|
|
|
6657
7179
|
async execute(args, ctx) {
|
|
6658
7180
|
try {
|
|
6659
7181
|
const cleanPattern = (args.pattern || "").trim();
|
|
6660
|
-
if (!cleanPattern) return "
|
|
7182
|
+
if (!cleanPattern) return toolFailure("[Glob\u5931\u8D25]\uFF1A\u4F20\u5165\u7684\u68C0\u7D22 pattern \u4E0D\u80FD\u4E3A\u7A7A\u3002");
|
|
6661
7183
|
const activeRoot = ctx?.cwd ?? getActiveWorkspaceRoot();
|
|
6662
7184
|
const root = args.path ? resolveReadablePath(args.path) : activeRoot;
|
|
6663
7185
|
const re = globToRegex2(cleanPattern);
|
|
@@ -6701,7 +7223,7 @@ var init_glob = __esm({
|
|
|
6701
7223
|
return `${prefix}[Glob: ${cleanPattern} | ${hits.length} \u4E2A\u5339\u914D]
|
|
6702
7224
|
` + hits.join("\n");
|
|
6703
7225
|
} catch (error) {
|
|
6704
|
-
return `glob \u68C0\u7D22\u5931\u8D25: ${error.message}
|
|
7226
|
+
return toolFailure(`glob \u68C0\u7D22\u5931\u8D25: ${error.message}`);
|
|
6705
7227
|
}
|
|
6706
7228
|
}
|
|
6707
7229
|
}
|
|
@@ -6730,7 +7252,8 @@ var init_git = __esm({
|
|
|
6730
7252
|
type: "function",
|
|
6731
7253
|
function: {
|
|
6732
7254
|
name: "get_git_diff",
|
|
6733
|
-
|
|
7255
|
+
planAllowed: true,
|
|
7256
|
+
description: "\u83B7\u53D6\u5F53\u524D\u5DE5\u4F5C\u533A\u4E2D\u6240\u6709\u76F8\u6BD4\u4E8E Git \u6682\u5B58\u533A/\u6700\u8FD1\u4E00\u6B21\u63D0\u4EA4\u7684\u672A\u63D0\u4EA4\u4EE3\u7801\u6539\u52A8\uFF08\u7EA2\u7EFF\u8272 Diff \u5DEE\u5F02\uFF09\u3002\u9002\u5408\u5728\u4FEE\u6539\u4EE3\u7801\u540E\u3001\u6216\u8FD0\u884C\u6D4B\u8BD5\u524D\uFF0C\u81EA\u4E3B\u8D70\u67E5\u4FEE\u6539\u662F\u5426\u7CBE\u51C6\u65E0\u4F4E\u7EA7\u9519\u8BEF\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
6734
7257
|
parameters: {
|
|
6735
7258
|
type: "object",
|
|
6736
7259
|
properties: {
|
|
@@ -6774,9 +7297,9 @@ var init_git = __esm({
|
|
|
6774
7297
|
${stdout}`;
|
|
6775
7298
|
} catch (error) {
|
|
6776
7299
|
if (isNotARepoError2(error)) {
|
|
6777
|
-
return
|
|
7300
|
+
return toolFailure(`[Diff \u5931\u8D25]\uFF1A\u5F53\u524D\u5DE5\u4F5C\u533A\u5C1A\u672A\u521D\u59CB\u5316 Git \u4ED3\u5E93\uFF0C\u65E0\u6CD5\u55C5\u63A2\u4EE3\u7801\u7248\u672C\u6539\u52A8\u5DEE\u5F02\u3002`);
|
|
6778
7301
|
}
|
|
6779
|
-
return `\u8BFB\u53D6\u4EE3\u7801\u5DEE\u5F02\u5931\u8D25: ${error.message}
|
|
7302
|
+
return toolFailure(`\u8BFB\u53D6\u4EE3\u7801\u5DEE\u5F02\u5931\u8D25: ${error.message}`);
|
|
6780
7303
|
}
|
|
6781
7304
|
}
|
|
6782
7305
|
}
|
|
@@ -6785,7 +7308,8 @@ ${stdout}`;
|
|
|
6785
7308
|
type: "function",
|
|
6786
7309
|
function: {
|
|
6787
7310
|
name: "git_status",
|
|
6788
|
-
|
|
7311
|
+
planAllowed: true,
|
|
7312
|
+
description: "\u67E5\u770B\u5F53\u524D Git \u5DE5\u4F5C\u533A\u72B6\u6001\uFF08\u5F53\u524D\u5206\u652F\u3001\u4E0E\u8FDC\u7AEF\u7684\u9886\u5148/\u843D\u540E\u3001\u4EE5\u53CA\u6539\u52A8/\u6682\u5B58/\u672A\u8DDF\u8E2A\u6587\u4EF6\u7684\u7CBE\u7B80\u6E05\u5355\uFF09\u3002\u7EAF\u8BFB\uFF0C\u514D\u5BA1\u6279\uFF0C\u7528\u4E8E\u66FF\u4EE3\u8D70 run_command \u8DD1 git status \u7684\u7E41\u7410\u3002\u2605 \u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
6789
7313
|
parameters: {
|
|
6790
7314
|
type: "object",
|
|
6791
7315
|
properties: {}
|
|
@@ -6802,9 +7326,9 @@ ${stdout}`;
|
|
|
6802
7326
|
${stdout.trim()}`;
|
|
6803
7327
|
} catch (error) {
|
|
6804
7328
|
if (isNotARepoError2(error)) {
|
|
6805
|
-
return
|
|
7329
|
+
return toolFailure(`[Git Status \u5931\u8D25]\uFF1A\u5F53\u524D\u5DE5\u4F5C\u533A\u5C1A\u672A\u521D\u59CB\u5316 Git \u4ED3\u5E93\u3002`);
|
|
6806
7330
|
}
|
|
6807
|
-
return `\u8BFB\u53D6 Git \u72B6\u6001\u5931\u8D25: ${error.message}
|
|
7331
|
+
return toolFailure(`\u8BFB\u53D6 Git \u72B6\u6001\u5931\u8D25: ${error.message}`);
|
|
6808
7332
|
}
|
|
6809
7333
|
}
|
|
6810
7334
|
}
|
|
@@ -6813,7 +7337,8 @@ ${stdout.trim()}`;
|
|
|
6813
7337
|
type: "function",
|
|
6814
7338
|
function: {
|
|
6815
7339
|
name: "git_log",
|
|
6816
|
-
|
|
7340
|
+
planAllowed: true,
|
|
7341
|
+
description: "\u67E5\u770B\u5F53\u524D\u5206\u652F\u7684\u6700\u8FD1\u82E5\u5E72\u6761\u63D0\u4EA4\u5386\u53F2\uFF08\u77ED\u54C8\u5E0C + \u65E5\u671F + \u63D0\u4EA4\u8BF4\u660E\uFF09\u3002\u7EAF\u8BFB\uFF0C\u514D\u5BA1\u6279\u3002\u7528\u4E8E\u4E86\u89E3\u9879\u76EE\u6F14\u8FDB\u3001\u5B9A\u4F4D\u67D0\u6B21\u6539\u52A8\u6216\u786E\u8BA4\u63D0\u4EA4\u662F\u5426\u6210\u529F\u3002\u2605 \u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
6817
7342
|
parameters: {
|
|
6818
7343
|
type: "object",
|
|
6819
7344
|
properties: {
|
|
@@ -6840,9 +7365,9 @@ ${stdout.trim()}`;
|
|
|
6840
7365
|
${stdout.trim()}`;
|
|
6841
7366
|
} catch (error) {
|
|
6842
7367
|
if (isNotARepoError2(error)) {
|
|
6843
|
-
return
|
|
7368
|
+
return toolFailure(`[Git Log \u5931\u8D25]\uFF1A\u5F53\u524D\u5DE5\u4F5C\u533A\u5C1A\u672A\u521D\u59CB\u5316 Git \u4ED3\u5E93\u3002`);
|
|
6844
7369
|
}
|
|
6845
|
-
return `\u8BFB\u53D6 Git \u5386\u53F2\u5931\u8D25: ${error.message}
|
|
7370
|
+
return toolFailure(`\u8BFB\u53D6 Git \u5386\u53F2\u5931\u8D25: ${error.message}`);
|
|
6846
7371
|
}
|
|
6847
7372
|
}
|
|
6848
7373
|
}
|
|
@@ -6851,6 +7376,8 @@ ${stdout.trim()}`;
|
|
|
6851
7376
|
type: "function",
|
|
6852
7377
|
function: {
|
|
6853
7378
|
name: "git_commit",
|
|
7379
|
+
// ★ #8a:分类器仅 /auto 激进档纳入(不可 undo,显式 opt-in)
|
|
7380
|
+
autoApproval: "aggressive",
|
|
6854
7381
|
description: "\u5C06\u5F53\u524D\u6682\u5B58\u533A\u7684\u6539\u52A8\u63D0\u4EA4\u4E3A\u4E00\u6B21\u65B0\u7684 Git commit\u3002\u53EF\u9009 stage_all=true \u4E00\u5E76\u6267\u884C git add -A\uFF08\u6682\u5B58\u5168\u90E8\u6539\u52A8\u542B\u65B0\u589E/\u5220\u9664\uFF09\u540E\u518D\u63D0\u4EA4\u3002\u6CE8\u610F\uFF1A\u4E0D\u4F1A\u81EA\u52A8 push\u3002",
|
|
6855
7382
|
parameters: {
|
|
6856
7383
|
type: "object",
|
|
@@ -6878,13 +7405,13 @@ ${stdout.trim()}`;
|
|
|
6878
7405
|
${summary}`;
|
|
6879
7406
|
} catch (error) {
|
|
6880
7407
|
if (isNotARepoError2(error)) {
|
|
6881
|
-
return
|
|
7408
|
+
return toolFailure(`[Git Commit \u5931\u8D25]\uFF1A\u5F53\u524D\u5DE5\u4F5C\u533A\u5C1A\u672A\u521D\u59CB\u5316 Git \u4ED3\u5E93\u3002`);
|
|
6882
7409
|
}
|
|
6883
7410
|
const text = `${error?.stderr || error?.message || ""}`;
|
|
6884
7411
|
if (text.toLowerCase().includes("nothing to commit")) {
|
|
6885
7412
|
return `\u2139\uFE0F [git_commit]\uFF1A\u6CA1\u6709\u53EF\u63D0\u4EA4\u7684\u6539\u52A8\uFF08nothing to commit\uFF09\u3002\u5982\u9700\u63D0\u4EA4\u8BF7\u5148\u6682\u5B58\uFF08stage_all=true \u6216 git add\uFF09\u3002`;
|
|
6886
7413
|
}
|
|
6887
|
-
return
|
|
7414
|
+
return toolFailure(`[git_commit \u5931\u8D25]\uFF1A${text.trim()}`);
|
|
6888
7415
|
}
|
|
6889
7416
|
}
|
|
6890
7417
|
}
|
|
@@ -6925,7 +7452,7 @@ var init_inspect_dependencies = __esm({
|
|
|
6925
7452
|
};
|
|
6926
7453
|
return JSON.stringify(result, null, 2);
|
|
6927
7454
|
} catch (error) {
|
|
6928
|
-
return `\
|
|
7455
|
+
return toolFailure(`\u8BFB\u53D6\u4F9D\u8D56\u6E05\u5355\u5931\u8D25\uFF0C\u672A\u627E\u5230 package.json \u6216\u6587\u4EF6\u683C\u5F0F\u635F\u574F: ${error.message}`);
|
|
6929
7456
|
}
|
|
6930
7457
|
}
|
|
6931
7458
|
}
|
|
@@ -7325,6 +7852,9 @@ var init_web = __esm({
|
|
|
7325
7852
|
type: "function",
|
|
7326
7853
|
function: {
|
|
7327
7854
|
name: "web_fetch",
|
|
7855
|
+
planAllowed: true,
|
|
7856
|
+
primaryArg: "url",
|
|
7857
|
+
autoApproval: "aggressive",
|
|
7328
7858
|
description: "\u6293\u53D6\u6307\u5B9A\u516C\u5F00 URL \u7684\u7F51\u9875\u5185\u5BB9\u5E76\u8F6C\u4E3A\u5E72\u51C0\u7684 Markdown \u6587\u672C\uFF0C\u7528\u4E8E\u67E5\u9605 API \u6587\u6863\u3001\u62A5\u9519\u8BF4\u660E\u3001\u5B98\u65B9 changelog \u7B49\u5916\u90E8\u8D44\u6599\u3002\u4EC5\u652F\u6301 http/https\uFF0C\u9ED8\u8BA4\u62E6\u622A\u5185\u7F51/\u56DE\u73AF/\u94FE\u8DEF\u672C\u5730\u5730\u5740\uFF08\u9632 SSRF\uFF09\uFF1B\u672C\u5730\u5F00\u53D1/\u81EA\u52A8\u5316\u6D4B\u8BD5\u9700\u6293 localhost \u670D\u52A1\u6216\u5185\u7F51\u9875\u9762\u65F6\uFF0C\u4F20 allow_private=true \u653E\u884C\uFF08\u4E91\u5143\u6570\u636E\u7AEF\u70B9\u4ECD\u62E6\uFF09\u3002",
|
|
7329
7859
|
parameters: {
|
|
7330
7860
|
type: "object",
|
|
@@ -7349,10 +7879,10 @@ var init_web = __esm({
|
|
|
7349
7879
|
try {
|
|
7350
7880
|
parsed = new URL(args.url);
|
|
7351
7881
|
} catch {
|
|
7352
|
-
return
|
|
7882
|
+
return toolFailure(`[\u6293\u53D6\u5931\u8D25]\uFF1AURL \u683C\u5F0F\u4E0D\u5408\u6CD5\uFF1A${args.url}`);
|
|
7353
7883
|
}
|
|
7354
7884
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
7355
|
-
return
|
|
7885
|
+
return toolFailure(`[\u5B89\u5168\u7194\u65AD]\uFF1A\u4EC5\u5141\u8BB8 http/https \u534F\u8BAE\uFF0C\u62D2\u7EDD ${parsed.protocol}`);
|
|
7356
7886
|
}
|
|
7357
7887
|
const signals = [AbortSignal.timeout(FETCH_TIMEOUT_MS2)];
|
|
7358
7888
|
if (ctx?.abortSignal) signals.push(ctx.abortSignal);
|
|
@@ -7362,7 +7892,7 @@ var init_web = __esm({
|
|
|
7362
7892
|
"Accept": "text/html,application/xhtml+xml,text/plain,application/json,application/xml;q=0.9,*/*;q=0.8"
|
|
7363
7893
|
}, signals, allowPrivate);
|
|
7364
7894
|
if (!res.ok) {
|
|
7365
|
-
return
|
|
7895
|
+
return toolFailure(`[\u6293\u53D6\u5931\u8D25]\uFF1AHTTP ${res.status} ${res.statusText}\uFF08${parsed.href}\uFF09`);
|
|
7366
7896
|
}
|
|
7367
7897
|
const contentType = res.headers.get("content-type") || "";
|
|
7368
7898
|
if (!/(text|html|json|xml|plain|markdown)/i.test(contentType)) {
|
|
@@ -7391,12 +7921,12 @@ var init_web = __esm({
|
|
|
7391
7921
|
${body}${truncNote}`;
|
|
7392
7922
|
} catch (error) {
|
|
7393
7923
|
if (error?.name === "TimeoutError") {
|
|
7394
|
-
return
|
|
7924
|
+
return toolFailure(`[\u6293\u53D6\u8D85\u65F6]\uFF1A${FETCH_TIMEOUT_MS2 / 1e3}s \u5185\u672A\u54CD\u5E94\uFF1A${parsed.href}`);
|
|
7395
7925
|
}
|
|
7396
7926
|
if (error?.name === "AbortError") {
|
|
7397
7927
|
return `\u23F9\uFE0F [\u5DF2\u4E2D\u6B62]\uFF1A\u7528\u6237\u4E2D\u65AD\u4E86\u6293\u53D6\uFF1A${parsed.href}`;
|
|
7398
7928
|
}
|
|
7399
|
-
return
|
|
7929
|
+
return toolFailure(`[\u6293\u53D6\u5931\u8D25]\uFF1A${error.message}`);
|
|
7400
7930
|
}
|
|
7401
7931
|
}
|
|
7402
7932
|
}
|
|
@@ -7405,6 +7935,9 @@ ${body}${truncNote}`;
|
|
|
7405
7935
|
type: "function",
|
|
7406
7936
|
function: {
|
|
7407
7937
|
name: "web_search",
|
|
7938
|
+
planAllowed: true,
|
|
7939
|
+
primaryArg: "query",
|
|
7940
|
+
autoApproval: "aggressive",
|
|
7408
7941
|
description: "\u8054\u7F51\u641C\u7D22\u5916\u90E8\u8D44\u6599\uFF08API \u6587\u6863\u3001\u62A5\u9519\u89E3\u6CD5\u3001\u5E93\u7528\u6CD5\u3001\u6700\u65B0\u4FE1\u606F\u7B49\uFF09\uFF0C\u8FD4\u56DE\u7ED3\u679C\u5217\u8868\uFF08\u6807\u9898/URL/\u7247\u6BB5\uFF09\u3002\u9ED8\u8BA4\u7528 Bing\uFF08\u514D\u6CE8\u518C\u3001\u4E2D\u56FD/\u5168\u7403\u7686\u53EF\u7528\uFF09\uFF1B\u914D\u7F6E\u4E86 TAVILY_API_KEY \u4F1A\u81EA\u52A8\u5347\u7EA7\u5230 Tavily\uFF08\u7ED3\u679C\u66F4\u5E72\u51C0\u3001\u5E26\u6458\u8981\uFF09\uFF1B\u53EF\u7528\u73AF\u5883\u53D8\u91CF SEARCH_PROVIDER=bing|ddg|tavily \u5F3A\u5236\u6307\u5B9A\u3002\u67E5\u8BE2\u964C\u751F\u5E93\u6216\u62A5\u9519\u65F6\u4F18\u5148\u7528\u672C\u5DE5\u5177\u66FF\u4EE3\u51ED\u8BB0\u5FC6\u4F5C\u7B54\u3002\u7ED3\u679C\u6309\u957F\u5EA6\u7194\u65AD\u3002",
|
|
7409
7942
|
parameters: {
|
|
7410
7943
|
type: "object",
|
|
@@ -7432,12 +7965,12 @@ ${body}${truncNote}`;
|
|
|
7432
7965
|
return formatSearchResults(args.query, provider, resp);
|
|
7433
7966
|
} catch (error) {
|
|
7434
7967
|
if (error?.name === "TimeoutError") {
|
|
7435
|
-
return
|
|
7968
|
+
return toolFailure(`[web_search \u8D85\u65F6]\uFF1A${SEARCH_TIMEOUT_MS / 1e3}s \u5185\u672A\u54CD\u5E94\u3002`);
|
|
7436
7969
|
}
|
|
7437
7970
|
if (error?.name === "AbortError") {
|
|
7438
7971
|
return `\u23F9\uFE0F [\u5DF2\u4E2D\u6B62]\uFF1A\u7528\u6237\u4E2D\u65AD\u4E86\u641C\u7D22\u3002`;
|
|
7439
7972
|
}
|
|
7440
|
-
return
|
|
7973
|
+
return toolFailure(`[web_search \u5931\u8D25 | ${provider}]\uFF1A${error.message}`);
|
|
7441
7974
|
}
|
|
7442
7975
|
}
|
|
7443
7976
|
}
|
|
@@ -7495,17 +8028,17 @@ var init_http = __esm({
|
|
|
7495
8028
|
async execute(args, ctx) {
|
|
7496
8029
|
const method = (args.method || "GET").toUpperCase();
|
|
7497
8030
|
if (!ALLOWED_METHODS.includes(method)) {
|
|
7498
|
-
return
|
|
8031
|
+
return toolFailure(`[http_request] \u4E0D\u652F\u6301\u7684\u65B9\u6CD5\uFF1A${args.method}\uFF08\u5141\u8BB8 ${ALLOWED_METHODS.join("/")})`);
|
|
7499
8032
|
}
|
|
7500
8033
|
const maxChars = args.max_length && args.max_length > 0 ? args.max_length : DEFAULT_MAX_CHARS2;
|
|
7501
8034
|
let parsed;
|
|
7502
8035
|
try {
|
|
7503
8036
|
parsed = new URL(args.url);
|
|
7504
8037
|
} catch {
|
|
7505
|
-
return
|
|
8038
|
+
return toolFailure(`[http_request] URL \u4E0D\u5408\u6CD5\uFF1A${args.url}`);
|
|
7506
8039
|
}
|
|
7507
8040
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
7508
|
-
return
|
|
8041
|
+
return toolFailure(`[http_request] \u4EC5\u5141\u8BB8 http/https\uFF0C\u62D2\u7EDD ${parsed.protocol}`);
|
|
7509
8042
|
}
|
|
7510
8043
|
const headers = {
|
|
7511
8044
|
"User-Agent": USER_AGENT2,
|
|
@@ -7544,12 +8077,12 @@ var init_http = __esm({
|
|
|
7544
8077
|
].join("\n");
|
|
7545
8078
|
} catch (error) {
|
|
7546
8079
|
if (error?.name === "TimeoutError") {
|
|
7547
|
-
return
|
|
8080
|
+
return toolFailure(`[http_request \u8D85\u65F6]\uFF1A${HTTP_TIMEOUT_MS / 1e3}s \u5185\u672A\u54CD\u5E94\uFF1A${parsed.href}`);
|
|
7548
8081
|
}
|
|
7549
8082
|
if (error?.name === "AbortError") {
|
|
7550
8083
|
return `\u23F9\uFE0F [http_request \u5DF2\u4E2D\u6B62]\uFF1A\u7528\u6237\u4E2D\u65AD\uFF1A${parsed.href}`;
|
|
7551
8084
|
}
|
|
7552
|
-
return
|
|
8085
|
+
return toolFailure(`[http_request \u5931\u8D25 | ${method}]\uFF1A${error.message}`);
|
|
7553
8086
|
}
|
|
7554
8087
|
}
|
|
7555
8088
|
}
|
|
@@ -7595,7 +8128,7 @@ var init_typescript = __esm({
|
|
|
7595
8128
|
try {
|
|
7596
8129
|
const absPath = realpathNative(resolveReadablePath(displayPath));
|
|
7597
8130
|
const block = await precheck(displayPath, absPath);
|
|
7598
|
-
if (block) return { ok: false,
|
|
8131
|
+
if (block) return { ok: false, result: typeof block === "string" ? asToolFailure(block) : block };
|
|
7599
8132
|
const { ls } = await getLanguageService(TS, absPath, { checkJs });
|
|
7600
8133
|
const syntactic = ls.getSyntacticDiagnostics(absPath);
|
|
7601
8134
|
const semantic = ls.getSemanticDiagnostics(absPath);
|
|
@@ -7637,7 +8170,7 @@ var init_typescript = __esm({
|
|
|
7637
8170
|
return { ok: true, errors, warnings, text: `[Diagnostics: ${displayPath}] ${errors} error(s), ${warnings} warning(s)
|
|
7638
8171
|
${body}${tail}` };
|
|
7639
8172
|
} catch (e) {
|
|
7640
|
-
return { ok: false,
|
|
8173
|
+
return { ok: false, result: toolFailure(`\u7C7B\u578B\u8BCA\u65AD\u5931\u8D25 [${displayPath}]: ${e?.message ?? e}`) };
|
|
7641
8174
|
}
|
|
7642
8175
|
};
|
|
7643
8176
|
typescriptTools = [
|
|
@@ -7645,7 +8178,8 @@ ${body}${tail}` };
|
|
|
7645
8178
|
type: "function",
|
|
7646
8179
|
function: {
|
|
7647
8180
|
name: "get_diagnostics",
|
|
7648
|
-
|
|
8181
|
+
planAllowed: true,
|
|
8182
|
+
description: "\u5BF9\u4E00\u4E2A\u6216\u591A\u4E2A TS/JS \u6587\u4EF6\u53D6\u7C7B\u578B+\u8BED\u4E49\u8BCA\u65AD\uFF08\u7C7B\u578B\u9519\u8BEF/\u672A\u7528\u53D8\u91CF/\u4E0D\u53EF\u8FBE\u4EE3\u7801\uFF09\uFF0C\u8F93\u51FA\u884C:\u5217/\u4E25\u91CD\u5EA6/TS \u9519\u8BEF\u7801\uFF0C\u683C\u5F0F\u5BF9\u9F50 tsc\u3002\u2605 \u6539\u5B8C\u591A\u4E2A\u6587\u4EF6\u540E\u9A8C\u8BC1\uFF1A\u4F20 paths \u6570\u7EC4\u4E00\u6B21\u8BCA\u65AD\u5168\u90E8\uFF08\u6700\u591A 20 \u4E2A\uFF09\uFF0C\u52FF\u9010\u6587\u4EF6\u591A\u6B21\u8C03\u7528\u3002\u652F\u6301 .ts/.tsx/.js/.jsx/.mjs/.cjs\uFF1B.vue SFC \u4E0E\u5176\u4ED6\u8BED\u8A00\u6269\u5C55\u540D\uFF08.java/.py \u7B49\uFF09\u76F4\u63A5\u62D2\u7EDD\u3001\u52FF\u4F20\u5165\u3002\u9879\u76EE\u7EA7\u5168\u91CF\u8BCA\u65AD\u7528 run_command \u8DD1 `tsc --noEmit`\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
7649
8183
|
parameters: {
|
|
7650
8184
|
type: "object",
|
|
7651
8185
|
properties: {
|
|
@@ -7666,11 +8200,11 @@ ${body}${tail}` };
|
|
|
7666
8200
|
const TS = await getTs();
|
|
7667
8201
|
if (!TS) return `\u26A0\uFE0F [\u7C7B\u578B\u8BCA\u65AD\u4E0D\u53EF\u7528]\uFF1Atypescript \u6A21\u5757\u672A\u52A0\u8F7D\uFF08VSCode \u6269\u5C55\u5185\u53EF\u7528\uFF1BCLI \u73AF\u5883\u672A\u5FC5\u5B89\u88C5 typescript\uFF09\u3002\u53EF\u6539\u7528 run_command \u8DD1 \`tsc --noEmit\`\u3002`;
|
|
7668
8202
|
const targets = args.paths && args.paths.length > 0 ? args.paths : args.path ? [args.path] : [];
|
|
7669
|
-
if (targets.length === 0) return
|
|
7670
|
-
if (targets.length > MAX_DIAG_FILES) return
|
|
8203
|
+
if (targets.length === 0) return toolFailure(`[\u53C2\u6570\u7F3A\u5931]\uFF1A\u8BF7\u4F20 path\uFF08\u5355\u6587\u4EF6\uFF09\u6216 paths\uFF08\u6279\u91CF\uFF0C\u6539\u5B8C\u591A\u4E2A\u6587\u4EF6\u540E\u4E00\u6B21\u9A8C\u8BC1\uFF09\u3002`);
|
|
8204
|
+
if (targets.length > MAX_DIAG_FILES) return toolFailure(`[\u53C2\u6570\u8D85\u9650]\uFF1A\u5355\u6B21\u6279\u91CF\u8BCA\u65AD\u6700\u591A ${MAX_DIAG_FILES} \u4E2A\u6587\u4EF6\uFF08\u6536\u5230 ${targets.length} \u4E2A\uFF09\u3002\u8BF7\u5206\u6279\u8C03\u7528\uFF0C\u6216\u7528 run_command \u8DD1 \`tsc --noEmit\` \u505A\u9879\u76EE\u7EA7\u5168\u91CF\u8BCA\u65AD\u3002`);
|
|
7671
8205
|
const results = [];
|
|
7672
8206
|
for (const p of targets) results.push(await diagnoseOneFile(TS, p, args.check_js));
|
|
7673
|
-
if (results.length === 1) return results[0].text;
|
|
8207
|
+
if (results.length === 1) return results[0].ok ? results[0].text : results[0].result;
|
|
7674
8208
|
let totalErr = 0, totalWarn = 0, clean = 0, failed = 0;
|
|
7675
8209
|
const sections = [];
|
|
7676
8210
|
for (let i = 0; i < results.length; i++) {
|
|
@@ -7678,7 +8212,7 @@ ${body}${tail}` };
|
|
|
7678
8212
|
if (!r.ok) {
|
|
7679
8213
|
failed++;
|
|
7680
8214
|
sections.push(`\u2014\u2014 ${targets[i]}\uFF08\u8BCA\u65AD\u672A\u4EA7\u51FA\uFF09\u2014\u2014
|
|
7681
|
-
${r.
|
|
8215
|
+
${r.result.content}`);
|
|
7682
8216
|
continue;
|
|
7683
8217
|
}
|
|
7684
8218
|
totalErr += r.errors;
|
|
@@ -7691,7 +8225,7 @@ ${r.text}`);
|
|
|
7691
8225
|
|
|
7692
8226
|
${sections.join("\n\n")}`;
|
|
7693
8227
|
} catch (e) {
|
|
7694
|
-
return `\
|
|
8228
|
+
return toolFailure(`\u7C7B\u578B\u8BCA\u65AD\u5931\u8D25: ${e?.message ?? e}`);
|
|
7695
8229
|
}
|
|
7696
8230
|
}
|
|
7697
8231
|
}
|
|
@@ -7700,7 +8234,8 @@ ${sections.join("\n\n")}`;
|
|
|
7700
8234
|
type: "function",
|
|
7701
8235
|
function: {
|
|
7702
8236
|
name: "goto_definition",
|
|
7703
|
-
|
|
8237
|
+
planAllowed: true,
|
|
8238
|
+
description: "\u8DF3\u8F6C\u5230 TS/JS \u6587\u4EF6\u67D0\u884C\u67D0\u5217\u7B26\u53F7\u7684\u5B9A\u4E49\u4F4D\u7F6E\uFF0C\u8FD4\u56DE rel/path:line:col\uFF08\u53EF\u591A\u5904\uFF09\u3002\u8DE8\u6587\u4EF6\u8FFD\u8E2A\u51FD\u6570/\u7C7B\u578B/\u53D8\u91CF\u7684\u6765\u6E90\uFF0C\u66FF\u4EE3 grep \u731C\u6D4B\u3002\u843D\u70B9\u5728 node_modules/.d.ts \u65F6\u6807\u6CE8 (declaration/library)\u3002\u884C\u5217 1-based\u3002\u652F\u6301 .ts/.tsx/.js/.jsx/.mjs/.cjs\uFF1B.vue SFC \u4E0E\u5176\u4ED6\u8BED\u8A00\u6269\u5C55\u540D\u76F4\u63A5\u62D2\u7EDD\u3001\u52FF\u4F20\u5165\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
7704
8239
|
parameters: {
|
|
7705
8240
|
type: "object",
|
|
7706
8241
|
properties: {
|
|
@@ -7724,9 +8259,9 @@ ${sections.join("\n\n")}`;
|
|
|
7724
8259
|
if (block) return block;
|
|
7725
8260
|
const { ls } = await getLanguageService(TS, absPath);
|
|
7726
8261
|
const program = ls.getProgram();
|
|
7727
|
-
if (!program) return `\
|
|
8262
|
+
if (!program) return toolFailure(`\u65E0\u6CD5\u53D6\u5F97 TS program\uFF08\u5185\u90E8\u9519\u8BEF\uFF09\u3002`);
|
|
7728
8263
|
const sf = program.getSourceFile(absPath);
|
|
7729
|
-
if (!sf) return `\
|
|
8264
|
+
if (!sf) return toolFailure(`\u6587\u4EF6\u672A\u7EB3\u5165 program\uFF1A${displayPath}\uFF08\u53EF\u80FD\u65E0\u5BF9\u5E94 tsconfig \u6216\u89E3\u6790\u5931\u8D25\uFF09\u3002`);
|
|
7730
8265
|
const pos = lineColToPos(TS, sf, line, column);
|
|
7731
8266
|
const defs = ls.getDefinitionAtPosition(absPath, pos);
|
|
7732
8267
|
if (!defs || defs.length === 0) {
|
|
@@ -7748,7 +8283,7 @@ ${sections.join("\n\n")}`;
|
|
|
7748
8283
|
return `[Goto Definition: ${displayPath}:${line}:${column}]
|
|
7749
8284
|
${out.join("\n")}`;
|
|
7750
8285
|
} catch (e) {
|
|
7751
|
-
return `\
|
|
8286
|
+
return toolFailure(`\u8DF3\u8F6C\u5B9A\u4E49\u5931\u8D25 [${displayPath}:${line}:${column}]: ${e?.message ?? e}`);
|
|
7752
8287
|
}
|
|
7753
8288
|
}
|
|
7754
8289
|
}
|
|
@@ -7757,7 +8292,7 @@ ${out.join("\n")}`;
|
|
|
7757
8292
|
type: "function",
|
|
7758
8293
|
function: {
|
|
7759
8294
|
name: "find_references",
|
|
7760
|
-
description: "\u67E5\u627E TS/JS \u6587\u4EF6\u67D0\u884C\u67D0\u5217\u7B26\u53F7\u7684\u5168\u9879\u76EE\u5F15\u7528\uFF08\u8C03\u7528/\u5BFC\u5165/\u8BFB\u5199\uFF09\uFF0C\u8F93\u51FA rel/path:line:col + \u8BFB\u5199\u6807\u6CE8 + \u884C\u6458\u5F55\u3002\u7C7B\u578B\u611F\u77E5\uFF1A\u53EA\u8FD4\u56DE\u771F\u5B9E\u7ED1\u5B9A\uFF0C\u4E0D\u542B\u6CE8\u91CA/\u5B57\u7B26\u4E32\u91CC\u7684\u540C\u540D\u8BCD\uFF08grep \u6838\u5FC3\u8BEF\u62A5\u6E90\uFF09\u3002\u7528\u4E8E\u6539\u7B7E\u540D/\u91CD\u547D\u540D\u524D\u7684\u5F71\u54CD\u9762\u6392\u67E5\u3001\u8FFD\u8E2A\u8C03\u7528\u65B9\uFF1B\u4E0E goto_definition \u4E92\u4E3A\u53CD\u5411\u3002\u8986\u76D6\u4EE5 program \u5185\u6587\u4EF6\u4E3A\u754C\uFF08tsconfig include + import \u94FE\uFF09\uFF1B\u5355\u7B26\u53F7\u8D85 200 \u5904\u5F15\u7528\u622A\u65AD\u3002\u884C\u5217 1-based\u3002\u652F\u6301 .ts/.tsx/.js/.jsx/.mjs/.cjs\uFF1B.vue SFC \u4E0E\u5176\u4ED6\u8BED\u8A00\u6269\u5C55\u540D\u76F4\u63A5\u62D2\u7EDD\u3001\u52FF\u4F20\u5165\u3002",
|
|
8295
|
+
description: "\u67E5\u627E TS/JS \u6587\u4EF6\u67D0\u884C\u67D0\u5217\u7B26\u53F7\u7684\u5168\u9879\u76EE\u5F15\u7528\uFF08\u8C03\u7528/\u5BFC\u5165/\u8BFB\u5199\uFF09\uFF0C\u8F93\u51FA rel/path:line:col + \u8BFB\u5199\u6807\u6CE8 + \u884C\u6458\u5F55\u3002\u7C7B\u578B\u611F\u77E5\uFF1A\u53EA\u8FD4\u56DE\u771F\u5B9E\u7ED1\u5B9A\uFF0C\u4E0D\u542B\u6CE8\u91CA/\u5B57\u7B26\u4E32\u91CC\u7684\u540C\u540D\u8BCD\uFF08grep \u6838\u5FC3\u8BEF\u62A5\u6E90\uFF09\u3002\u7528\u4E8E\u6539\u7B7E\u540D/\u91CD\u547D\u540D\u524D\u7684\u5F71\u54CD\u9762\u6392\u67E5\u3001\u8FFD\u8E2A\u8C03\u7528\u65B9\uFF1B\u4E0E goto_definition \u4E92\u4E3A\u53CD\u5411\u3002\u8986\u76D6\u4EE5 program \u5185\u6587\u4EF6\u4E3A\u754C\uFF08tsconfig include + import \u94FE\uFF09\uFF1B\u5355\u7B26\u53F7\u8D85 200 \u5904\u5F15\u7528\u622A\u65AD\u3002\u884C\u5217 1-based\u3002\u652F\u6301 .ts/.tsx/.js/.jsx/.mjs/.cjs\uFF1B.vue SFC \u4E0E\u5176\u4ED6\u8BED\u8A00\u6269\u5C55\u540D\u76F4\u63A5\u62D2\u7EDD\u3001\u52FF\u4F20\u5165\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
7761
8296
|
parameters: {
|
|
7762
8297
|
type: "object",
|
|
7763
8298
|
properties: {
|
|
@@ -7783,9 +8318,9 @@ ${out.join("\n")}`;
|
|
|
7783
8318
|
if (block) return block;
|
|
7784
8319
|
const { ls } = await getLanguageService(TS, absPath);
|
|
7785
8320
|
const program = ls.getProgram();
|
|
7786
|
-
if (!program) return `\
|
|
8321
|
+
if (!program) return toolFailure(`\u65E0\u6CD5\u53D6\u5F97 TS program\uFF08\u5185\u90E8\u9519\u8BEF\uFF09\u3002`);
|
|
7787
8322
|
const sf = program.getSourceFile(absPath);
|
|
7788
|
-
if (!sf) return `\
|
|
8323
|
+
if (!sf) return toolFailure(`\u6587\u4EF6\u672A\u7EB3\u5165 program\uFF1A${displayPath}\uFF08\u53EF\u80FD\u65E0\u5BF9\u5E94 tsconfig \u6216\u89E3\u6790\u5931\u8D25\uFF09\u3002`);
|
|
7789
8324
|
const pos = lineColToPos(TS, sf, line, column);
|
|
7790
8325
|
const groups = ls.findReferences(absPath, pos);
|
|
7791
8326
|
if (!groups || groups.length === 0) {
|
|
@@ -7839,7 +8374,7 @@ ${out.join("\n")}`;
|
|
|
7839
8374
|
return `[References: ${displayPath}:${line}:${column}]
|
|
7840
8375
|
${sections.join("\n")}${tail}`;
|
|
7841
8376
|
} catch (e) {
|
|
7842
|
-
return `\
|
|
8377
|
+
return toolFailure(`\u67E5\u627E\u5F15\u7528\u5931\u8D25 [${displayPath}:${line}:${column}]: ${e?.message ?? e}`);
|
|
7843
8378
|
}
|
|
7844
8379
|
}
|
|
7845
8380
|
}
|
|
@@ -7887,11 +8422,11 @@ var init_todo = __esm({
|
|
|
7887
8422
|
isSync: true,
|
|
7888
8423
|
async execute(args, ctx) {
|
|
7889
8424
|
if (!ctx?.sessionId) {
|
|
7890
|
-
return
|
|
8425
|
+
return toolFailure(`[todo_write \u5931\u8D25]\uFF1A\u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587\uFF08sessionId\uFF09\uFF0C\u65E0\u6CD5\u6301\u4E45\u5316\u4EFB\u52A1\u6E05\u5355\u3002`);
|
|
7891
8426
|
}
|
|
7892
8427
|
const todos = Array.isArray(args.todos) ? args.todos : [];
|
|
7893
8428
|
if (todos.length > MAX_TODOS) {
|
|
7894
|
-
return
|
|
8429
|
+
return toolFailure(`[todo_write \u5931\u8D25]\uFF1A\u4EFB\u52A1\u6761\u6570 ${todos.length} \u8D85\u8FC7\u4E0A\u9650 ${MAX_TODOS}\uFF0C\u8BF7\u5408\u7406\u62C6\u5206\u3002`);
|
|
7895
8430
|
}
|
|
7896
8431
|
const cleaned = todos.map((t) => {
|
|
7897
8432
|
const item = {
|
|
@@ -7904,7 +8439,7 @@ var init_todo = __esm({
|
|
|
7904
8439
|
});
|
|
7905
8440
|
const emptyContent = cleaned.filter((t) => !t.content);
|
|
7906
8441
|
if (emptyContent.length) {
|
|
7907
|
-
return
|
|
8442
|
+
return toolFailure(`[todo_write \u5931\u8D25]\uFF1A\u6709 ${emptyContent.length} \u6761\u4EFB\u52A1\u7F3A\u5C11 content\uFF0C\u8BF7\u8865\u5168\u540E\u518D\u63D0\u4EA4\u3002`);
|
|
7908
8443
|
}
|
|
7909
8444
|
const inProgressCount = cleaned.filter((t) => t.status === "in_progress").length;
|
|
7910
8445
|
const completedCount = cleaned.filter((t) => t.status === "completed").length;
|
|
@@ -8343,11 +8878,8 @@ var init_cleanup = __esm({
|
|
|
8343
8878
|
import fs22 from "fs/promises";
|
|
8344
8879
|
import path26 from "path";
|
|
8345
8880
|
import crypto from "crypto";
|
|
8346
|
-
async function beforeMutationBackup(toolName, args, toolCallId, sessionId) {
|
|
8881
|
+
async function beforeMutationBackup(strategy, toolName, args, toolCallId, sessionId) {
|
|
8347
8882
|
if (appConfig.undoEnabled === false) return null;
|
|
8348
|
-
if (!MUTATION_TOOLS.has(toolName)) {
|
|
8349
|
-
throw new Error(`[undo] \u4E0D\u5728\u53D8\u66F4\u5DE5\u5177\u540D\u5355: ${toolName}`);
|
|
8350
|
-
}
|
|
8351
8883
|
const relativePath = String(args?.path ?? "").replace(/\\/g, "/");
|
|
8352
8884
|
if (relativePath && isSensitivePath(relativePath)) {
|
|
8353
8885
|
const policy = appConfig.undoBackupSensitive ?? "skip";
|
|
@@ -8368,20 +8900,18 @@ async function beforeMutationBackup(toolName, args, toolCallId, sessionId) {
|
|
|
8368
8900
|
bornDate: getTodayDateString()
|
|
8369
8901
|
};
|
|
8370
8902
|
let record;
|
|
8371
|
-
switch (
|
|
8372
|
-
case "
|
|
8373
|
-
case "write_file":
|
|
8374
|
-
case "notebook_edit":
|
|
8903
|
+
switch (strategy) {
|
|
8904
|
+
case "overwrite":
|
|
8375
8905
|
record = await backupFileOverwrite(common, undoDir, args);
|
|
8376
8906
|
break;
|
|
8377
|
-
case "
|
|
8907
|
+
case "create":
|
|
8378
8908
|
record = await backupFileCreate(common);
|
|
8379
8909
|
break;
|
|
8380
|
-
case "
|
|
8910
|
+
case "delete":
|
|
8381
8911
|
record = await backupDelete(common, undoDir, relativePath);
|
|
8382
8912
|
break;
|
|
8383
8913
|
default:
|
|
8384
|
-
throw new Error(`[undo] \u672A\u77E5\
|
|
8914
|
+
throw new Error(`[undo] \u672A\u77E5\u5907\u4EFD\u7B56\u7565: ${strategy}`);
|
|
8385
8915
|
}
|
|
8386
8916
|
await appendUndoRecord(record, sessionId);
|
|
8387
8917
|
void maybeCleanupAfterUndoAppend(sessionId);
|
|
@@ -8415,8 +8945,9 @@ async function backupFileOverwrite(common, undoDir, args) {
|
|
|
8415
8945
|
contentHashBefore: sha1Buf(content),
|
|
8416
8946
|
fileSizeBefore: content.byteLength,
|
|
8417
8947
|
argsSnapshot: {
|
|
8418
|
-
|
|
8419
|
-
|
|
8948
|
+
// ★ #8a:原按 operationType==='edit_file' 特判,改按参数存在性判定——行为不变,泛化到任何声明式 overwrite 写工具
|
|
8949
|
+
old_str: typeof args?.old_str === "string" ? truncate2(args.old_str) : void 0,
|
|
8950
|
+
new_str: typeof args?.new_str === "string" ? truncate2(args.new_str) : void 0,
|
|
8420
8951
|
contentLength: typeof args?.content === "string" ? args.content.length : void 0
|
|
8421
8952
|
}
|
|
8422
8953
|
};
|
|
@@ -8478,7 +9009,7 @@ async function backupDelete(common, undoDir, relativePath) {
|
|
|
8478
9009
|
fileSizeBefore: content.byteLength
|
|
8479
9010
|
};
|
|
8480
9011
|
}
|
|
8481
|
-
var
|
|
9012
|
+
var sha1Buf, truncate2, isSensitivePath, hashTreeManifest, getDirTreeBytes, collectSensitiveInDir;
|
|
8482
9013
|
var init_backup = __esm({
|
|
8483
9014
|
"../core/src/tool/undo/backup.ts"() {
|
|
8484
9015
|
"use strict";
|
|
@@ -8489,8 +9020,6 @@ var init_backup = __esm({
|
|
|
8489
9020
|
init_undo();
|
|
8490
9021
|
init_cleanup();
|
|
8491
9022
|
init_traceCalculate();
|
|
8492
|
-
MUTATION_TOOLS = /* @__PURE__ */ new Set(["edit_file", "write_file", "create_file", "delete_path", "notebook_edit"]);
|
|
8493
|
-
isUndoTrigger = (toolName) => MUTATION_TOOLS.has(toolName);
|
|
8494
9023
|
sha1Buf = (buf) => crypto.createHash("sha1").update(buf).digest("hex");
|
|
8495
9024
|
truncate2 = (s, n = 200) => s === void 0 ? void 0 : s.length > n ? s.slice(0, n) + "\u2026" : s;
|
|
8496
9025
|
isSensitivePath = (rel) => {
|
|
@@ -8760,7 +9289,7 @@ var init_undo2 = __esm({
|
|
|
8760
9289
|
safetyLevel: "safe" /* SAFE */,
|
|
8761
9290
|
isSync: true,
|
|
8762
9291
|
async execute(_args, ctx) {
|
|
8763
|
-
if (!ctx?.sessionId) return
|
|
9292
|
+
if (!ctx?.sessionId) return toolFailure(`[undo_list \u5931\u8D25]\uFF1A\u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587\u3002`);
|
|
8764
9293
|
const list = await listUndoable(ctx.sessionId);
|
|
8765
9294
|
if (!list.length) return `\uFF08\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u53EF\u56DE\u9000\u7684\u53D8\u66F4\u3002\uFF09`;
|
|
8766
9295
|
const lines = list.map(
|
|
@@ -8789,15 +9318,15 @@ ${lines.join("\n")}
|
|
|
8789
9318
|
isSync: true,
|
|
8790
9319
|
requireApproval: (args) => args?.restore_last ? `\u7533\u8BF7\u56DE\u9000\u6700\u8FD1\u4E00\u6B21\u6587\u4EF6\u53D8\u66F4\uFF08restore_last\uFF09\u3002\u8BE5\u64CD\u4F5C\u4F1A\u6539\u5199\u78C1\u76D8\u6587\u4EF6\u3002` : `\u7533\u8BF7\u56DE\u9000\u6587\u4EF6\u53D8\u66F4\uFF08undoId=${String(args?.undoId ?? "").slice(0, 8)}\uFF09\u3002\u8BE5\u64CD\u4F5C\u4F1A\u6539\u5199\u78C1\u76D8\u6587\u4EF6\u3002`,
|
|
8791
9320
|
async execute(args, ctx) {
|
|
8792
|
-
if (!ctx?.sessionId) return
|
|
9321
|
+
if (!ctx?.sessionId) return toolFailure(`[undo_restore \u5931\u8D25]\uFF1A\u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587\u3002`);
|
|
8793
9322
|
try {
|
|
8794
9323
|
if (args?.restore_last) return await restoreLast(ctx.sessionId);
|
|
8795
|
-
if (!args?.undoId) return
|
|
9324
|
+
if (!args?.undoId) return toolFailure(`[undo_restore \u5931\u8D25]\uFF1A\u9700\u63D0\u4F9B undoId\uFF0C\u6216\u8BBE restore_last=true\u3002`);
|
|
8796
9325
|
const target = await findByUndoIdPrefix(ctx.sessionId, String(args.undoId));
|
|
8797
|
-
if (!target) return
|
|
9326
|
+
if (!target) return toolFailure(`[undo_restore \u5931\u8D25]\uFF1A\u627E\u4E0D\u5230 undoId \u524D\u7F00 "${args.undoId}" \u5BF9\u5E94\u7684\u8BB0\u5F55\uFF0C\u8BF7\u7528 undo_list \u6838\u5BF9\u3002`);
|
|
8798
9327
|
return await restoreByUndoId(target.undoId, ctx.sessionId);
|
|
8799
9328
|
} catch (e) {
|
|
8800
|
-
return
|
|
9329
|
+
return toolFailure(`[undo_restore \u5931\u8D25]\uFF1A${e?.message ?? e}`);
|
|
8801
9330
|
}
|
|
8802
9331
|
}
|
|
8803
9332
|
}
|
|
@@ -8850,10 +9379,10 @@ var init_ask = __esm({
|
|
|
8850
9379
|
const question = (args?.question ?? "").trim();
|
|
8851
9380
|
const options = Array.isArray(args?.options) ? args.options : [];
|
|
8852
9381
|
const cleanOptions = options.map((o) => ({ label: String(o?.label ?? "").trim(), description: o?.description ? String(o.description).trim() : void 0 })).filter((o) => o.label);
|
|
8853
|
-
if (!question) return "
|
|
8854
|
-
if (cleanOptions.length < 2 || cleanOptions.length > 4) return "
|
|
9382
|
+
if (!question) return toolFailure("[\u63D0\u95EE\u5931\u8D25]\uFF1Aquestion \u4E0D\u80FD\u4E3A\u7A7A\u3002");
|
|
9383
|
+
if (cleanOptions.length < 2 || cleanOptions.length > 4) return toolFailure("[\u63D0\u95EE\u5931\u8D25]\uFF1Aoptions \u987B\u4E3A 2-4 \u4E2A\u975E\u7A7A\u9009\u9879\u3002");
|
|
8855
9384
|
if (!ctx?.requestQuestion) {
|
|
8856
|
-
return "
|
|
9385
|
+
return toolFailure("[\u63D0\u95EE\u4E0D\u652F\u6301]\uFF1A\u5F53\u524D\u5BBF\u4E3B\u4E0D\u652F\u6301\u7ED3\u6784\u5316\u63D0\u95EE\uFF08\u591A\u4E3A\u975E\u4EA4\u4E92\u73AF\u5883\uFF09\u3002\u8BF7\u6539\u7528\u7EAF\u6587\u672C\u76F4\u63A5\u5411\u7528\u6237\u5217\u51FA\u9009\u9879\u5E76\u63D0\u95EE\u3002");
|
|
8857
9386
|
}
|
|
8858
9387
|
let answer;
|
|
8859
9388
|
try {
|
|
@@ -8863,7 +9392,7 @@ var init_ask = __esm({
|
|
|
8863
9392
|
multiSelect: !!args?.multiSelect
|
|
8864
9393
|
});
|
|
8865
9394
|
} catch (e) {
|
|
8866
|
-
return
|
|
9395
|
+
return toolFailure(`[\u63D0\u95EE\u5F02\u5E38]\uFF1A${e?.message ?? e}\u3002\u8BF7\u6539\u7528\u7EAF\u6587\u672C\u5411\u7528\u6237\u63D0\u95EE\u3002`);
|
|
8867
9396
|
}
|
|
8868
9397
|
if (!answer.selected || answer.selected.length === 0) {
|
|
8869
9398
|
return "\uFF08\u7528\u6237\u53D6\u6D88\u4E86\u672C\u6B21\u63D0\u95EE\uFF0C\u672A\u4F5C\u9009\u62E9\u3002\u53EF\u6309\u9ED8\u8BA4\u7EE7\u7EED\uFF0C\u6216\u91CD\u65B0\u7EC4\u7EC7\u95EE\u9898\u518D\u6B21\u8BE2\u95EE\u3002\uFF09";
|
|
@@ -8904,7 +9433,7 @@ var init_worktree = __esm({
|
|
|
8904
9433
|
\uFF08\u5C06\u521B\u5EFA\u4E34\u65F6\u5206\u652F\u7684 git worktree \u5E76\u628A\u4F1A\u8BDD\u5DE5\u4F5C\u533A\u5207\u6362\u8FC7\u53BB\uFF1B\u6539\u52A8\u9694\u79BB\uFF0C\u9700 commit/merge \u624D\u80FD\u5E76\u56DE\u4E3B\u4ED3\uFF09`,
|
|
8905
9434
|
async execute(args, ctx) {
|
|
8906
9435
|
const sessionId = ctx?.sessionId;
|
|
8907
|
-
if (!sessionId) return "
|
|
9436
|
+
if (!sessionId) return toolFailure("[enter_worktree] \u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587\uFF08sessionId\uFF09\u3002");
|
|
8908
9437
|
if (getSessionWorktree(sessionId)) {
|
|
8909
9438
|
return `\u26A0\uFE0F \u5F53\u524D\u4F1A\u8BDD\u5DF2\u5728 worktree \u5185\uFF08${getSessionWorktree(sessionId)?.path}\uFF09\u3002\u8BF7\u5148 exit_worktree \u518D\u91CD\u65B0\u8FDB\u5165\uFF0C\u907F\u514D\u6CC4\u6F0F\u3002`;
|
|
8910
9439
|
}
|
|
@@ -8912,8 +9441,8 @@ var init_worktree = __esm({
|
|
|
8912
9441
|
try {
|
|
8913
9442
|
wt = await createWorktree(sessionId, "session");
|
|
8914
9443
|
} catch (e) {
|
|
8915
|
-
if (isNotARepoError(e)) return "
|
|
8916
|
-
return
|
|
9444
|
+
if (isNotARepoError(e)) return toolFailure("[enter_worktree] \u4E3B\u5DE5\u4F5C\u533A\u4E0D\u662F git \u4ED3\u5E93\uFF0C\u65E0\u6CD5\u521B\u5EFA worktree\u3002");
|
|
9445
|
+
return toolFailure(`[enter_worktree] \u521B\u5EFA worktree \u5931\u8D25\uFF1A${e?.message ?? e}`);
|
|
8917
9446
|
}
|
|
8918
9447
|
setSessionWorktree(sessionId, wt);
|
|
8919
9448
|
return [
|
|
@@ -8942,7 +9471,7 @@ var init_worktree = __esm({
|
|
|
8942
9471
|
\uFF08\u5C06\u5220\u9664\u5F53\u524D worktree \u53CA\u5176\u4E34\u65F6\u5206\u652F\uFF1B\u672A\u63D0\u4EA4\u6539\u52A8\u4F1A\u4E22\u5931\u3002\u5982\u9700\u4FDD\u7559\u8BF7\u5148 commit\u3002\uFF09`,
|
|
8943
9472
|
async execute(_args, ctx) {
|
|
8944
9473
|
const sessionId = ctx?.sessionId;
|
|
8945
|
-
if (!sessionId) return "
|
|
9474
|
+
if (!sessionId) return toolFailure("[exit_worktree] \u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587\uFF08sessionId\uFF09\u3002");
|
|
8946
9475
|
const wt = clearSessionWorktree(sessionId);
|
|
8947
9476
|
if (!wt) return "\u2139\uFE0F \u5F53\u524D\u4F1A\u8BDD\u4E0D\u5728\u4EFB\u4F55 worktree \u5185\uFF08\u65E0\u9700\u9000\u51FA\uFF09\u3002";
|
|
8948
9477
|
const diff = await harvestDiff(wt).catch(() => "");
|
|
@@ -9049,6 +9578,9 @@ var init_notebook = __esm({
|
|
|
9049
9578
|
type: "function",
|
|
9050
9579
|
function: {
|
|
9051
9580
|
name: "notebook_edit",
|
|
9581
|
+
// ★ #8a:undo 备份同 edit_file(快照原内容);刻意不声明 autoApproval——维持「分类器不覆盖、恒人工审批」现状
|
|
9582
|
+
triggersUndo: "overwrite",
|
|
9583
|
+
primaryArg: "path",
|
|
9052
9584
|
description: "\u7F16\u8F91 Jupyter notebook\uFF08.ipynb\uFF09\u7684\u5355\u5143\u683C\u3002\u652F\u6301\u4E09\u79CD\u6A21\u5F0F\uFF1Areplace\uFF08\u66FF\u6362\u67D0 cell \u5185\u5BB9/\u7C7B\u578B\uFF09\u3001insert\uFF08\u63D2\u5165\u65B0 cell\uFF09\u3001delete\uFF08\u5220\u9664 cell\uFF09\u3002\u7528 cell_id \u6216 cell_index \u5B9A\u4F4D\u3002\u4EC5\u652F\u6301 .ipynb \u6587\u4EF6\u3002",
|
|
9053
9585
|
parameters: {
|
|
9054
9586
|
type: "object",
|
|
@@ -9071,28 +9603,28 @@ var init_notebook = __esm({
|
|
|
9071
9603
|
${String(args.new_source).slice(0, 500)}` : ""}`,
|
|
9072
9604
|
async execute(args) {
|
|
9073
9605
|
const relPath = args?.path;
|
|
9074
|
-
if (typeof relPath !== "string" || !relPath.trim()) return "
|
|
9075
|
-
if (!relPath.toLowerCase().endsWith(".ipynb")) return
|
|
9606
|
+
if (typeof relPath !== "string" || !relPath.trim()) return toolFailure("[notebook_edit] \u7F3A\u5C11\u53C2\u6570 path\u3002");
|
|
9607
|
+
if (!relPath.toLowerCase().endsWith(".ipynb")) return toolFailure(`[notebook_edit] \u4EC5\u652F\u6301 .ipynb \u6587\u4EF6\uFF1A${relPath}`);
|
|
9076
9608
|
const edit_mode = args?.edit_mode === "insert" || args?.edit_mode === "delete" ? args.edit_mode : "replace";
|
|
9077
9609
|
let absPath;
|
|
9078
9610
|
try {
|
|
9079
9611
|
absPath = resolveSafePath(relPath);
|
|
9080
9612
|
} catch (e) {
|
|
9081
|
-
return
|
|
9613
|
+
return toolFailure(`[notebook_edit] \u8DEF\u5F84\u89E3\u6790\u5931\u8D25\uFF1A${e?.message ?? e}`);
|
|
9082
9614
|
}
|
|
9083
9615
|
let raw;
|
|
9084
9616
|
try {
|
|
9085
9617
|
raw = await fs24.readFile(absPath, "utf-8");
|
|
9086
9618
|
} catch (e) {
|
|
9087
|
-
return
|
|
9619
|
+
return toolFailure(`[notebook_edit] \u8BFB\u53D6\u5931\u8D25\uFF1A${e?.message ?? e}`);
|
|
9088
9620
|
}
|
|
9089
9621
|
let nb;
|
|
9090
9622
|
try {
|
|
9091
9623
|
nb = JSON.parse(raw);
|
|
9092
9624
|
} catch (e) {
|
|
9093
|
-
return
|
|
9625
|
+
return toolFailure(`[notebook_edit] JSON \u89E3\u6790\u5931\u8D25\uFF08\u975E\u5408\u6CD5 .ipynb\uFF09\uFF1A${e?.message ?? e}`);
|
|
9094
9626
|
}
|
|
9095
|
-
if (!nb || !Array.isArray(nb.cells)) return "
|
|
9627
|
+
if (!nb || !Array.isArray(nb.cells)) return toolFailure("[notebook_edit] \u975E\u5408\u6CD5 notebook\uFF08\u7F3A cells \u6570\u7EC4\uFF09\u3002");
|
|
9096
9628
|
let summary;
|
|
9097
9629
|
try {
|
|
9098
9630
|
summary = applyNotebookEdit(nb, {
|
|
@@ -9103,12 +9635,12 @@ ${String(args.new_source).slice(0, 500)}` : ""}`,
|
|
|
9103
9635
|
edit_mode
|
|
9104
9636
|
});
|
|
9105
9637
|
} catch (e) {
|
|
9106
|
-
return
|
|
9638
|
+
return toolFailure(`[notebook_edit] ${e?.message ?? e}`);
|
|
9107
9639
|
}
|
|
9108
9640
|
try {
|
|
9109
9641
|
assertWithinWorkspace(absPath);
|
|
9110
9642
|
} catch (e) {
|
|
9111
|
-
return
|
|
9643
|
+
return toolFailure(`[notebook_edit] \u4E8C\u6B21\u56F4\u680F\u590D\u68C0\u5931\u8D25\uFF1A${e?.message ?? e}`);
|
|
9112
9644
|
}
|
|
9113
9645
|
const tmpPath = makeTmpPath(absPath);
|
|
9114
9646
|
try {
|
|
@@ -9117,7 +9649,7 @@ ${String(args.new_source).slice(0, 500)}` : ""}`,
|
|
|
9117
9649
|
} catch (e) {
|
|
9118
9650
|
await fs24.unlink(tmpPath).catch(() => {
|
|
9119
9651
|
});
|
|
9120
|
-
return
|
|
9652
|
+
return toolFailure(`[notebook_edit] \u5199\u5165\u5931\u8D25\uFF1A${e?.message ?? e}`);
|
|
9121
9653
|
}
|
|
9122
9654
|
return `\u2705 [notebook_edit] ${summary}\uFF08${relPath}\uFF09`;
|
|
9123
9655
|
}
|
|
@@ -9225,10 +9757,41 @@ var init_loader3 = __esm({
|
|
|
9225
9757
|
}
|
|
9226
9758
|
});
|
|
9227
9759
|
|
|
9228
|
-
// ../core/src/
|
|
9760
|
+
// ../core/src/memory/usage.ts
|
|
9229
9761
|
import fs26 from "fs/promises";
|
|
9230
9762
|
import path29 from "path";
|
|
9231
|
-
var
|
|
9763
|
+
var USAGE_FILE, readUsage, recordMemoryUse;
|
|
9764
|
+
var init_usage = __esm({
|
|
9765
|
+
"../core/src/memory/usage.ts"() {
|
|
9766
|
+
"use strict";
|
|
9767
|
+
init_loader3();
|
|
9768
|
+
init_common();
|
|
9769
|
+
USAGE_FILE = path29.join(GLOBAL_MEMORY_DIR, ".usage.json");
|
|
9770
|
+
readUsage = async () => {
|
|
9771
|
+
const raw = await readJSONFile(USAGE_FILE);
|
|
9772
|
+
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
9773
|
+
};
|
|
9774
|
+
recordMemoryUse = async (name, kind) => {
|
|
9775
|
+
try {
|
|
9776
|
+
const map = await readUsage();
|
|
9777
|
+
const prev = map[name];
|
|
9778
|
+
map[name] = {
|
|
9779
|
+
lastUsed: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9780
|
+
reads: (prev?.reads ?? 0) + (kind === "read" ? 1 : 0)
|
|
9781
|
+
};
|
|
9782
|
+
await fs26.mkdir(GLOBAL_MEMORY_DIR, { recursive: true });
|
|
9783
|
+
await fs26.writeFile(USAGE_FILE, JSON.stringify(map, null, 2), "utf-8");
|
|
9784
|
+
} catch (e) {
|
|
9785
|
+
console.warn(`\u26A0\uFE0F [memory] \u4F7F\u7528\u753B\u50CF\u8BB0\u5F55\u5931\u8D25\uFF08\u5DF2\u5FFD\u7565\uFF09: ${e?.message ?? e}`);
|
|
9786
|
+
}
|
|
9787
|
+
};
|
|
9788
|
+
}
|
|
9789
|
+
});
|
|
9790
|
+
|
|
9791
|
+
// ../core/src/tool/registry/memory.ts
|
|
9792
|
+
import fs27 from "fs/promises";
|
|
9793
|
+
import path30 from "path";
|
|
9794
|
+
var MAX_BODY_BYTES, MAX_DESCRIPTION_CHARS, MEMORY_LIMITS, NAME_RE, VALID_TYPES2, memoryFilePath, sanitizeLine, buildMemoryMd, writeAndRegister, indexLineBytes, memoryTools;
|
|
9232
9795
|
var init_memory = __esm({
|
|
9233
9796
|
"../core/src/tool/registry/memory.ts"() {
|
|
9234
9797
|
"use strict";
|
|
@@ -9236,10 +9799,13 @@ var init_memory = __esm({
|
|
|
9236
9799
|
init_fs();
|
|
9237
9800
|
init_loader3();
|
|
9238
9801
|
init_registry6();
|
|
9802
|
+
init_usage();
|
|
9239
9803
|
MAX_BODY_BYTES = 64 * 1024;
|
|
9804
|
+
MAX_DESCRIPTION_CHARS = 200;
|
|
9805
|
+
MEMORY_LIMITS = { maxCount: 200, maxIndexBytes: 16 * 1024 };
|
|
9240
9806
|
NAME_RE = /^[a-z0-9-]+$/;
|
|
9241
9807
|
VALID_TYPES2 = ["user", "feedback", "project", "reference"];
|
|
9242
|
-
memoryFilePath = (name, project) => project ?
|
|
9808
|
+
memoryFilePath = (name, project) => project ? path30.join(process.cwd(), ".deepseeker-code", "memory", `${name}.md`) : path30.join(GLOBAL_MEMORY_DIR, `${name}.md`);
|
|
9243
9809
|
sanitizeLine = (s) => String(s ?? "").replace(/[\r\n]+/g, " ").trim();
|
|
9244
9810
|
buildMemoryMd = (name, description, type, body) => `---
|
|
9245
9811
|
name: ${name}
|
|
@@ -9251,13 +9817,14 @@ ${body.trim()}
|
|
|
9251
9817
|
`;
|
|
9252
9818
|
writeAndRegister = async (name, description, type, body, project) => {
|
|
9253
9819
|
const file = memoryFilePath(name, project);
|
|
9254
|
-
await
|
|
9820
|
+
await fs27.mkdir(path30.dirname(file), { recursive: true });
|
|
9255
9821
|
const tmp = makeTmpPath(file);
|
|
9256
|
-
await
|
|
9257
|
-
await
|
|
9822
|
+
await fs27.writeFile(tmp, buildMemoryMd(name, description, type, body), "utf-8");
|
|
9823
|
+
await fs27.rename(tmp, file);
|
|
9258
9824
|
registerMemory({ name, description, type, body: body.trim(), source: project ? "project" : "global", file });
|
|
9259
9825
|
return file;
|
|
9260
9826
|
};
|
|
9827
|
+
indexLineBytes = (m) => Buffer.byteLength(memoryIndexLine(m), "utf-8");
|
|
9261
9828
|
memoryTools = [
|
|
9262
9829
|
{
|
|
9263
9830
|
type: "function",
|
|
@@ -9273,7 +9840,7 @@ ${body.trim()}
|
|
|
9273
9840
|
},
|
|
9274
9841
|
description: {
|
|
9275
9842
|
type: "string",
|
|
9276
|
-
description: "\u4E00\u53E5\u8BDD\u6982\u62EC\uFF08\u6CE8\u5165\u7D22\u5F15\u4F9B\u65E5\u540E\u5224\u65AD\u662F\u5426\u53EC\u56DE\uFF09\u3002\u52FF\u6362\u884C"
|
|
9843
|
+
description: "\u4E00\u53E5\u8BDD\u6982\u62EC\uFF08\u6CE8\u5165\u7D22\u5F15\u4F9B\u65E5\u540E\u5224\u65AD\u662F\u5426\u53EC\u56DE\uFF09\u3002\u52FF\u6362\u884C\uFF0C\u4E0A\u9650 200 \u5B57\u7B26"
|
|
9277
9844
|
},
|
|
9278
9845
|
body: {
|
|
9279
9846
|
type: "string",
|
|
@@ -9299,13 +9866,25 @@ ${body.trim()}
|
|
|
9299
9866
|
const body = typeof args?.body === "string" ? args.body : "";
|
|
9300
9867
|
const type = sanitizeLine(args?.type) || "reference";
|
|
9301
9868
|
const project = args?.project === true;
|
|
9302
|
-
if (!NAME_RE.test(name)) return
|
|
9303
|
-
if (!description) return "
|
|
9304
|
-
if (
|
|
9305
|
-
if (!
|
|
9869
|
+
if (!NAME_RE.test(name)) return toolFailure(`[memory_save] name \u975E\u6CD5\uFF1A\u4EC5\u5141\u8BB8\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u8FDE\u5B57\u7B26\uFF0C\u6536\u5230 "${name}"\u3002`);
|
|
9870
|
+
if (!description) return toolFailure("[memory_save] description \u4E0D\u80FD\u4E3A\u7A7A\u3002");
|
|
9871
|
+
if (description.length > MAX_DESCRIPTION_CHARS) return toolFailure(`[memory_save] description \u8D85\u8FC7 ${MAX_DESCRIPTION_CHARS} \u5B57\u7B26\u4E0A\u9650\uFF08\u5F53\u524D ${description.length}\uFF09\u3002\u8BF7\u538B\u7F29\u4E3A\u4E00\u53E5\u8BDD\u3002`);
|
|
9872
|
+
if (!body.trim()) return toolFailure("[memory_save] body \u4E0D\u80FD\u4E3A\u7A7A\u3002");
|
|
9873
|
+
if (!VALID_TYPES2.includes(type)) return toolFailure(`[memory_save] type \u975E\u6CD5\uFF1A\u987B user/feedback/project/reference\uFF0C\u6536\u5230 "${type}"\u3002`);
|
|
9306
9874
|
const bodyBytes = Buffer.byteLength(body, "utf-8");
|
|
9307
|
-
if (bodyBytes > MAX_BODY_BYTES) return
|
|
9875
|
+
if (bodyBytes > MAX_BODY_BYTES) return toolFailure(`[memory_save] body \u8D85\u8FC7 ${MAX_BODY_BYTES} \u5B57\u8282\u4E0A\u9650\uFF08\u5F53\u524D ${bodyBytes}\uFF09\u3002\u8BF7\u7CBE\u7B80\u6216\u62C6\u5206\u3002`);
|
|
9876
|
+
const all = listMemories();
|
|
9877
|
+
const existing = getMemory(name);
|
|
9878
|
+
if (!existing && all.length >= MEMORY_LIMITS.maxCount) {
|
|
9879
|
+
return toolFailure(`[memory_save] \u8BB0\u5FC6\u6761\u6570\u5DF2\u8FBE\u4E0A\u9650 ${MEMORY_LIMITS.maxCount}\uFF08\u73B0\u6709 ${all.length} \u6761\uFF09\u3002\u7D22\u5F15\u6BCF\u8F6E\u6CE8\u5165\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF0C\u53EA\u589E\u4E0D\u51CF\u4F1A\u6301\u7EED\u4FB5\u8680\u4E0A\u4E0B\u6587\u2014\u2014\u8BF7\u5148 memory_list \u68C0\u67E5\uFF0C\u7528 memory_delete \u6E05\u7406\u5931\u6548\u6761\u76EE\u6216\u5408\u5E76\u76F8\u8FD1\u8BB0\u5FC6\u540E\u518D\u4FDD\u5B58\u3002`);
|
|
9880
|
+
}
|
|
9881
|
+
const curBytes = all.length === 0 ? 0 : Buffer.byteLength(all.map(memoryIndexLine).join("\n"), "utf-8");
|
|
9882
|
+
const delta = indexLineBytes({ name, type, description }) - (existing ? indexLineBytes(existing) : 0);
|
|
9883
|
+
if (delta > 0 && curBytes + delta > MEMORY_LIMITS.maxIndexBytes) {
|
|
9884
|
+
return toolFailure(`[memory_save] \u8BB0\u5FC6\u7D22\u5F15\u5C06\u8D85\u5B57\u8282\u4E0A\u9650\uFF08\u5F53\u524D ${curBytes}/${MEMORY_LIMITS.maxIndexBytes} \u5B57\u8282\uFF0C\u672C\u6761\u51C0\u589E ${delta} \u5B57\u8282\uFF09\u3002\u7D22\u5F15\u6BCF\u8F6E\u6CE8\u5165\u7CFB\u7EDF\u63D0\u793A\u8BCD\u2014\u2014\u8BF7\u7CBE\u7B80 description\uFF0C\u6216\u7528 memory_delete \u6E05\u7406/\u5408\u5E76\u65E7\u8BB0\u5FC6\u540E\u518D\u4FDD\u5B58\u3002`);
|
|
9885
|
+
}
|
|
9308
9886
|
const file = await writeAndRegister(name, description, type, body, project);
|
|
9887
|
+
await recordMemoryUse(name, "save");
|
|
9309
9888
|
return `\u2705 \u5DF2\u4FDD\u5B58\u8BB0\u5FC6 **${name}**\uFF08${type}${project ? "\uFF0C\u9879\u76EE\u6E90" : "\uFF0C\u5168\u5C40\u6E90"}\uFF09\u2192 ${file}`;
|
|
9310
9889
|
}
|
|
9311
9890
|
}
|
|
@@ -9327,7 +9906,8 @@ ${body.trim()}
|
|
|
9327
9906
|
async execute(args) {
|
|
9328
9907
|
const name = sanitizeLine(args?.name);
|
|
9329
9908
|
const m = getMemory(name);
|
|
9330
|
-
if (!m) return `\
|
|
9909
|
+
if (!m) return toolFailure(`\u672A\u627E\u5230\u8BB0\u5FC6\uFF1A${name}\u3002\u53EF\u8C03\u7528 memory_list \u67E5\u770B\u5168\u90E8\u8BB0\u5FC6\u540D\u3002`);
|
|
9910
|
+
await recordMemoryUse(name, "read");
|
|
9331
9911
|
return `## ${m.name}\uFF08${m.type}\uFF09
|
|
9332
9912
|
|
|
9333
9913
|
${m.body}`;
|
|
@@ -9345,7 +9925,7 @@ ${m.body}`;
|
|
|
9345
9925
|
async execute() {
|
|
9346
9926
|
const all = listMemories();
|
|
9347
9927
|
if (all.length === 0) return "\uFF08\u6682\u65E0\u8BB0\u5FC6\uFF09";
|
|
9348
|
-
const lines = all.slice().sort((a, b) => a.name.localeCompare(b.name)).map(
|
|
9928
|
+
const lines = all.slice().sort((a, b) => a.name.localeCompare(b.name)).map(memoryIndexLine);
|
|
9349
9929
|
return `\u5171 ${all.length} \u6761\u8BB0\u5FC6\uFF1A
|
|
9350
9930
|
${lines.join("\n")}`;
|
|
9351
9931
|
}
|
|
@@ -9355,7 +9935,7 @@ ${lines.join("\n")}`;
|
|
|
9355
9935
|
type: "function",
|
|
9356
9936
|
function: {
|
|
9357
9937
|
name: "memory_delete",
|
|
9358
|
-
description: "\u5220\u9664\u6307\u5B9A\u8BB0\u5FC6\uFF08\u5220\u9664\u78C1\u76D8\u6587\u4EF6\u5E76\u4ECE\u8FD0\u884C\u65F6\u6CE8\u518C\u8868\u6CE8\u9500\uFF09\u3002\u4EC5\u5F53\u4F60\u786E\u8BA4\u67D0\u6761\u8BB0\u5FC6\u5DF2\u5931\u6548/\u6709\u8BEF\u65F6\u4F7F\u7528\u3002",
|
|
9938
|
+
description: "\u5220\u9664\u6307\u5B9A\u8BB0\u5FC6\uFF08\u5220\u9664\u78C1\u76D8\u6587\u4EF6\u5E76\u4ECE\u8FD0\u884C\u65F6\u6CE8\u518C\u8868\u6CE8\u9500\uFF0C\u9700\u7528\u6237\u5BA1\u6279\uFF09\u3002\u4EC5\u5F53\u4F60\u786E\u8BA4\u67D0\u6761\u8BB0\u5FC6\u5DF2\u5931\u6548/\u6709\u8BEF\u65F6\u4F7F\u7528\u3002",
|
|
9359
9939
|
parameters: {
|
|
9360
9940
|
type: "object",
|
|
9361
9941
|
properties: {
|
|
@@ -9363,14 +9943,19 @@ ${lines.join("\n")}`;
|
|
|
9363
9943
|
},
|
|
9364
9944
|
required: ["name"]
|
|
9365
9945
|
},
|
|
9366
|
-
|
|
9946
|
+
// ★ #9①(2026-09-16):SAFE → MUTATION。记忆目录在工作区沙箱外,被注入的工具结果可诱导
|
|
9947
|
+
// 删除跨会话记忆;删除又不可 undo(不在工作区备份范围)——必须人工过目。未声明
|
|
9948
|
+
// autoApproval → 分类器恒 'ask' → 转人工;allow-always 经 primaryArg 落精确名作用域规则。
|
|
9949
|
+
safetyLevel: "mutation" /* MUTATION */,
|
|
9367
9950
|
isSync: true,
|
|
9951
|
+
primaryArg: "name",
|
|
9952
|
+
requireApproval: (args) => `\u5220\u9664\u6301\u4E45\u8BB0\u5FC6 **${sanitizeLine(args?.name)}**\uFF08\u8DE8\u4F1A\u8BDD\u751F\u6548\uFF0C\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\uFF09`,
|
|
9368
9953
|
async execute(args) {
|
|
9369
9954
|
const name = sanitizeLine(args?.name);
|
|
9370
9955
|
const m = getMemory(name);
|
|
9371
|
-
if (!m) return `\
|
|
9956
|
+
if (!m) return toolFailure(`\u672A\u627E\u5230\u8BB0\u5FC6\uFF1A${name}\uFF08\u53EF\u80FD\u5DF2\u88AB\u5220\u9664\uFF09\u3002`);
|
|
9372
9957
|
try {
|
|
9373
|
-
await
|
|
9958
|
+
await fs27.unlink(m.file);
|
|
9374
9959
|
} catch {
|
|
9375
9960
|
}
|
|
9376
9961
|
unregisterMemory(name);
|
|
@@ -9382,9 +9967,74 @@ ${lines.join("\n")}`;
|
|
|
9382
9967
|
}
|
|
9383
9968
|
});
|
|
9384
9969
|
|
|
9970
|
+
// ../core/src/session/sidecar.ts
|
|
9971
|
+
import fs28 from "fs/promises";
|
|
9972
|
+
import path31 from "path";
|
|
9973
|
+
var SIDECAR_ARCHIVED_MARK, sidecarArchivedNote, safeSidecarId, getToolOutputSidecarPath, getToolOutputSidecarDir, ensuredSidecarDirs, SIDECAR_SESSION_CAP_BYTES, listSidecarFiles, writeSidecarArchive;
|
|
9974
|
+
var init_sidecar = __esm({
|
|
9975
|
+
"../core/src/session/sidecar.ts"() {
|
|
9976
|
+
"use strict";
|
|
9977
|
+
init_store();
|
|
9978
|
+
SIDECAR_ARCHIVED_MARK = "\u5B8C\u6574\u539F\u6587\u5DF2\u5B58\u6863";
|
|
9979
|
+
sidecarArchivedNote = (toolCallId) => `${SIDECAR_ARCHIVED_MARK}\uFF0Crecall \u5DE5\u5177\u4F20 with_full="${toolCallId}" \u53EF\u53D6\u56DE`;
|
|
9980
|
+
safeSidecarId = (id) => String(id).replace(/[^A-Za-z0-9_-]/g, "");
|
|
9981
|
+
getToolOutputSidecarPath = (sessionId, toolCallId) => path31.join(getSessionsDirPath(sessionId), "tool-outputs", `${safeSidecarId(toolCallId)}.txt`);
|
|
9982
|
+
getToolOutputSidecarDir = (sessionId) => path31.join(getSessionsDirPath(sessionId), "tool-outputs");
|
|
9983
|
+
ensuredSidecarDirs = /* @__PURE__ */ new Set();
|
|
9984
|
+
SIDECAR_SESSION_CAP_BYTES = 64 * 1024 * 1024;
|
|
9985
|
+
listSidecarFiles = async (dir) => {
|
|
9986
|
+
let names;
|
|
9987
|
+
try {
|
|
9988
|
+
names = await fs28.readdir(dir);
|
|
9989
|
+
} catch {
|
|
9990
|
+
return [];
|
|
9991
|
+
}
|
|
9992
|
+
const out = [];
|
|
9993
|
+
for (const name of names) {
|
|
9994
|
+
try {
|
|
9995
|
+
const st = await fs28.stat(path31.join(dir, name));
|
|
9996
|
+
if (st.isFile()) out.push({ name, size: st.size, mtimeMs: st.mtimeMs });
|
|
9997
|
+
} catch {
|
|
9998
|
+
}
|
|
9999
|
+
}
|
|
10000
|
+
return out;
|
|
10001
|
+
};
|
|
10002
|
+
writeSidecarArchive = async (sessionId, toolCallId, content, opts) => {
|
|
10003
|
+
try {
|
|
10004
|
+
const dir = getToolOutputSidecarDir(sessionId);
|
|
10005
|
+
if (!ensuredSidecarDirs.has(dir)) {
|
|
10006
|
+
await fs28.mkdir(dir, { recursive: true });
|
|
10007
|
+
ensuredSidecarDirs.add(dir);
|
|
10008
|
+
}
|
|
10009
|
+
const cap = opts?.capBytes ?? SIDECAR_SESSION_CAP_BYTES;
|
|
10010
|
+
const incoming = Buffer.byteLength(content, "utf-8");
|
|
10011
|
+
const files = await listSidecarFiles(dir);
|
|
10012
|
+
const total = files.reduce((s, f) => s + f.size, 0);
|
|
10013
|
+
if (total + incoming > cap) {
|
|
10014
|
+
const byOldest = [...files].sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
10015
|
+
let freed = 0;
|
|
10016
|
+
for (const f of byOldest) {
|
|
10017
|
+
if (total - freed + incoming <= cap) break;
|
|
10018
|
+
try {
|
|
10019
|
+
await fs28.unlink(path31.join(dir, f.name));
|
|
10020
|
+
freed += f.size;
|
|
10021
|
+
} catch {
|
|
10022
|
+
}
|
|
10023
|
+
}
|
|
10024
|
+
}
|
|
10025
|
+
await fs28.writeFile(getToolOutputSidecarPath(sessionId, toolCallId), content, "utf-8");
|
|
10026
|
+
return sidecarArchivedNote(toolCallId);
|
|
10027
|
+
} catch (e) {
|
|
10028
|
+
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);
|
|
10029
|
+
return void 0;
|
|
10030
|
+
}
|
|
10031
|
+
};
|
|
10032
|
+
}
|
|
10033
|
+
});
|
|
10034
|
+
|
|
9385
10035
|
// ../core/src/tool/registry/recall.ts
|
|
9386
|
-
import
|
|
9387
|
-
import
|
|
10036
|
+
import fs29 from "fs/promises";
|
|
10037
|
+
import path32 from "path";
|
|
9388
10038
|
var escapeRegExp2, lineText, primaryPathArg, annotateStaleness, snippetAround, recallTools;
|
|
9389
10039
|
var init_recall = __esm({
|
|
9390
10040
|
"../core/src/tool/registry/recall.ts"() {
|
|
@@ -9392,7 +10042,7 @@ var init_recall = __esm({
|
|
|
9392
10042
|
init_type();
|
|
9393
10043
|
init_guard();
|
|
9394
10044
|
init_transcript();
|
|
9395
|
-
|
|
10045
|
+
init_sidecar();
|
|
9396
10046
|
escapeRegExp2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9397
10047
|
lineText = (l) => {
|
|
9398
10048
|
let t = "";
|
|
@@ -9415,9 +10065,9 @@ var init_recall = __esm({
|
|
|
9415
10065
|
annotateStaleness = async (args, observedAt) => {
|
|
9416
10066
|
const p = primaryPathArg(args);
|
|
9417
10067
|
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";
|
|
9418
|
-
const abs =
|
|
10068
|
+
const abs = path32.isAbsolute(p) ? p : path32.resolve(getActiveWorkspaceRoot(), p);
|
|
9419
10069
|
try {
|
|
9420
|
-
const st = await
|
|
10070
|
+
const st = await fs29.stat(abs);
|
|
9421
10071
|
if (observedAt && st.mtime.toISOString() > observedAt) {
|
|
9422
10072
|
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`;
|
|
9423
10073
|
}
|
|
@@ -9457,17 +10107,17 @@ var init_recall = __esm({
|
|
|
9457
10107
|
// ★ 检索结果预算与 web 等工具对齐 16000 口径;命中数 × 单片段双重限流防 context thrashing
|
|
9458
10108
|
maxOutputCharacters: 16e3,
|
|
9459
10109
|
async execute(args, ctx) {
|
|
9460
|
-
if (!ctx?.sessionId) return "
|
|
10110
|
+
if (!ctx?.sessionId) return toolFailure("[recall] \u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587\uFF08sessionId\uFF09\uFF0C\u65E0\u6CD5\u68C0\u7D22\u3002");
|
|
9461
10111
|
try {
|
|
9462
10112
|
if (args.with_full) {
|
|
9463
|
-
const safeId =
|
|
9464
|
-
if (!safeId) return "
|
|
9465
|
-
const sidecar =
|
|
10113
|
+
const safeId = safeSidecarId(args.with_full);
|
|
10114
|
+
if (!safeId) return toolFailure("[recall] with_full \u542B\u975E\u6CD5\u5B57\u7B26\u3002");
|
|
10115
|
+
const sidecar = getToolOutputSidecarPath(ctx.sessionId, args.with_full);
|
|
9466
10116
|
let full = "";
|
|
9467
10117
|
try {
|
|
9468
|
-
full = await
|
|
10118
|
+
full = await fs29.readFile(sidecar, "utf-8");
|
|
9469
10119
|
} catch {
|
|
9470
|
-
return
|
|
10120
|
+
return toolFailure(`[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}`);
|
|
9471
10121
|
}
|
|
9472
10122
|
const CHUNK = 14e3;
|
|
9473
10123
|
const off = Math.max(0, Math.floor(args.full_offset ?? 0));
|
|
@@ -9480,7 +10130,7 @@ var init_recall = __esm({
|
|
|
9480
10130
|
${slice}${more}`;
|
|
9481
10131
|
}
|
|
9482
10132
|
const cleanQuery = (args.query || "").trim();
|
|
9483
|
-
if (!cleanQuery) return "
|
|
10133
|
+
if (!cleanQuery) return toolFailure("[recall] \u68C0\u7D22\u5173\u952E\u8BCD\u4E0D\u80FD\u4E3A\u7A7A\uFF08\u6216\u6539\u7528 with_full \u53D6\u5B58\u6863\u5168\u6587\uFF09\u3002");
|
|
9484
10134
|
const re = new RegExp(args.is_regex ? cleanQuery : escapeRegExp2(cleanQuery), "i");
|
|
9485
10135
|
const lines = await readTranscriptLines(ctx.sessionId);
|
|
9486
10136
|
const toolCallInfo = /* @__PURE__ */ new Map();
|
|
@@ -9497,6 +10147,7 @@ ${slice}${more}`;
|
|
|
9497
10147
|
}
|
|
9498
10148
|
const limit = Math.min(Math.max(Math.floor(args.limit ?? 6), 1), 12);
|
|
9499
10149
|
const runFilter = args.run_id?.trim();
|
|
10150
|
+
const hasRunEvents = lines.some((l) => isEventLine(l) && l.dscEvent === "run.start");
|
|
9500
10151
|
const blocks = [];
|
|
9501
10152
|
let runN = 0;
|
|
9502
10153
|
let runId = "";
|
|
@@ -9510,7 +10161,7 @@ ${slice}${more}`;
|
|
|
9510
10161
|
}
|
|
9511
10162
|
const role = l.role;
|
|
9512
10163
|
if (role === "system") continue;
|
|
9513
|
-
if (runFilter && !(runId && runId.startsWith(runFilter))) continue;
|
|
10164
|
+
if (runFilter && hasRunEvents && !(runId && runId.startsWith(runFilter))) continue;
|
|
9514
10165
|
let info;
|
|
9515
10166
|
if (role === "tool") {
|
|
9516
10167
|
info = toolCallInfo.get(l.tool_call_id);
|
|
@@ -9524,7 +10175,7 @@ ${slice}${more}`;
|
|
|
9524
10175
|
if (role === "tool") {
|
|
9525
10176
|
header += `
|
|
9526
10177
|
\u6821\u9A8C\uFF1A${await annotateStaleness(info?.args, ts)}`;
|
|
9527
|
-
if (typeof l.content === "string" && l.content.includes(
|
|
10178
|
+
if (typeof l.content === "string" && l.content.includes(SIDECAR_ARCHIVED_MARK)) {
|
|
9528
10179
|
header += `
|
|
9529
10180
|
\u2702\uFE0F \u8BE5\u7ED3\u679C\u66FE\u88AB\u622A\u65AD\uFF0C\u4F20 with_full="${l.tool_call_id}" \u53EF\u53D6\u5B58\u6863\u5168\u6587`;
|
|
9530
10181
|
}
|
|
@@ -9549,7 +10200,7 @@ ${snippetAround(text, re, 700)}`);
|
|
|
9549
10200
|
"\u63D0\u793A\uFF1A\u26A0\uFE0F \u6807\u6CE8\u7684\u6587\u4EF6\u5FC5\u987B\u91CD\u65B0 read_file \u9A8C\u8BC1\u540E\u624D\u80FD\u636E\u4EE5\u4FEE\u6539\uFF1B\u672C\u5DE5\u5177\u7ED3\u679C\u4EC5\u4F5C\u5386\u53F2\u7EBF\u7D22\uFF0C\u4E0D\u66FF\u4EE3\u5F53\u524D\u6587\u4EF6\u72B6\u6001\u3002"
|
|
9550
10201
|
].join("\n");
|
|
9551
10202
|
} catch (e) {
|
|
9552
|
-
return
|
|
10203
|
+
return toolFailure(`[recall] \u68C0\u7D22\u5931\u8D25: ${e instanceof Error ? e.message : String(e)}`);
|
|
9553
10204
|
}
|
|
9554
10205
|
}
|
|
9555
10206
|
}
|
|
@@ -9620,7 +10271,7 @@ var init_spreadsheet = __esm({
|
|
|
9620
10271
|
const readBlock = await assertReadable(absPath, args.path);
|
|
9621
10272
|
if (readBlock) return readBlock;
|
|
9622
10273
|
if (!absPath.toLowerCase().endsWith(".xlsx")) {
|
|
9623
|
-
return
|
|
10274
|
+
return toolFailure(`[\u683C\u5F0F\u4E0D\u652F\u6301]\uFF1A[${args.path}] \u4E0D\u662F .xlsx\u3002read_xlsx \u4EC5\u89E3\u6790 Excel \u5DE5\u4F5C\u7C3F\uFF08.xls \u8BF7\u5148\u53E6\u5B58\u4E3A .xlsx\uFF09\uFF1B\u5176\u5B83\u6587\u4EF6\u8BF7\u7528 read_file\u3002`);
|
|
9624
10275
|
}
|
|
9625
10276
|
const startRow = args.start_row ? Math.max(1, Math.floor(args.start_row)) : 1;
|
|
9626
10277
|
const maxRows = Math.min(args.max_rows ? Math.max(1, Math.floor(args.max_rows)) : 200, 1e3);
|
|
@@ -9664,7 +10315,7 @@ var init_spreadsheet = __esm({
|
|
|
9664
10315
|
[... \u540E\u9762\u8FD8\u6709 ${rowCount - endRow} \u884C\uFF0C\u53EF\u628A start_row \u8BBE\u4E3A ${endRow + 1} \u7EE7\u7EED\u7FFB\u9875\u3002]`);
|
|
9665
10316
|
return lines.join("\n");
|
|
9666
10317
|
} catch (error) {
|
|
9667
|
-
return `\u8BFB\u53D6 Excel \u5931\u8D25 [${args.path}]: ${error.message}
|
|
10318
|
+
return toolFailure(`\u8BFB\u53D6 Excel \u5931\u8D25 [${args.path}]: ${error.message}`);
|
|
9668
10319
|
}
|
|
9669
10320
|
}
|
|
9670
10321
|
}
|
|
@@ -9674,7 +10325,7 @@ var init_spreadsheet = __esm({
|
|
|
9674
10325
|
});
|
|
9675
10326
|
|
|
9676
10327
|
// ../core/src/tool/registry/document.ts
|
|
9677
|
-
import
|
|
10328
|
+
import fs30 from "fs/promises";
|
|
9678
10329
|
var getMammoth, getUnpdf, documentTools;
|
|
9679
10330
|
var init_document = __esm({
|
|
9680
10331
|
"../core/src/tool/registry/document.ts"() {
|
|
@@ -9713,7 +10364,7 @@ var init_document = __esm({
|
|
|
9713
10364
|
const readBlock = await assertReadable(absPath, args.path);
|
|
9714
10365
|
if (readBlock) return readBlock;
|
|
9715
10366
|
if (!absPath.toLowerCase().endsWith(".docx")) {
|
|
9716
|
-
return
|
|
10367
|
+
return toolFailure(`[\u683C\u5F0F\u4E0D\u652F\u6301]\uFF1A[${args.path}] \u4E0D\u662F .docx\u3002read_docx \u4EC5\u89E3\u6790 Word \u6587\u6863\uFF08.doc \u8001\u683C\u5F0F\u8BF7\u5148\u53E6\u5B58\u4E3A .docx\uFF09\uFF1B\u5176\u5B83\u6587\u4EF6\u7528 read_file\u3002`);
|
|
9717
10368
|
}
|
|
9718
10369
|
const start = args.start_char ? Math.max(0, Math.floor(args.start_char)) : 0;
|
|
9719
10370
|
const maxChars = Math.min(args.max_chars ? Math.max(1, Math.floor(args.max_chars)) : 3e4, 5e4);
|
|
@@ -9731,7 +10382,7 @@ var init_document = __esm({
|
|
|
9731
10382
|
[... \u540E\u9762\u8FD8\u6709 ${total - (start + slice.length)} \u5B57\u7B26\uFF0C\u53EF\u628A start_char \u8BBE\u4E3A ${start + slice.length} \u7EE7\u7EED\u7FFB\u9875\u3002]`);
|
|
9732
10383
|
return lines.join("\n");
|
|
9733
10384
|
} catch (error) {
|
|
9734
|
-
return `\u8BFB\u53D6 Word \u6587\u6863\u5931\u8D25 [${args.path}]: ${error.message}
|
|
10385
|
+
return toolFailure(`\u8BFB\u53D6 Word \u6587\u6863\u5931\u8D25 [${args.path}]: ${error.message}`);
|
|
9735
10386
|
}
|
|
9736
10387
|
}
|
|
9737
10388
|
}
|
|
@@ -9760,11 +10411,11 @@ var init_document = __esm({
|
|
|
9760
10411
|
const readBlock = await assertReadable(absPath, args.path);
|
|
9761
10412
|
if (readBlock) return readBlock;
|
|
9762
10413
|
if (!absPath.toLowerCase().endsWith(".pdf")) {
|
|
9763
|
-
return
|
|
10414
|
+
return toolFailure(`[\u683C\u5F0F\u4E0D\u652F\u6301]\uFF1A[${args.path}] \u4E0D\u662F .pdf\u3002read_pdf \u4EC5\u89E3\u6790 PDF \u6587\u6863\uFF1B\u5176\u5B83\u6587\u4EF6\u7528 read_file\u3002`);
|
|
9764
10415
|
}
|
|
9765
10416
|
const start = args.start_char ? Math.max(0, Math.floor(args.start_char)) : 0;
|
|
9766
10417
|
const maxChars = Math.min(args.max_chars ? Math.max(1, Math.floor(args.max_chars)) : 3e4, 5e4);
|
|
9767
|
-
const buf = await
|
|
10418
|
+
const buf = await fs30.readFile(absPath);
|
|
9768
10419
|
const unpdf = await getUnpdf();
|
|
9769
10420
|
const pdf = await unpdf.getDocumentProxy(new Uint8Array(buf));
|
|
9770
10421
|
const { text, totalPages } = await unpdf.extractText(pdf, { mergePages: true });
|
|
@@ -9780,7 +10431,7 @@ var init_document = __esm({
|
|
|
9780
10431
|
[... \u540E\u9762\u8FD8\u6709 ${total - (start + slice.length)} \u5B57\u7B26\uFF0C\u53EF\u628A start_char \u8BBE\u4E3A ${start + slice.length} \u7EE7\u7EED\u7FFB\u9875\u3002]`);
|
|
9781
10432
|
return lines.join("\n");
|
|
9782
10433
|
} catch (error) {
|
|
9783
|
-
return `\u8BFB\u53D6 PDF \u5931\u8D25 [${args.path}]: ${error.message}
|
|
10434
|
+
return toolFailure(`\u8BFB\u53D6 PDF \u5931\u8D25 [${args.path}]: ${error.message}`);
|
|
9784
10435
|
}
|
|
9785
10436
|
}
|
|
9786
10437
|
}
|
|
@@ -9795,7 +10446,9 @@ __export(tool_exports, {
|
|
|
9795
10446
|
MAX_AGENT_DEPTH: () => MAX_AGENT_DEPTH,
|
|
9796
10447
|
ToolExecutionResultStatus: () => ToolExecutionResultStatus,
|
|
9797
10448
|
ToolSafetyLevel: () => ToolSafetyLevel,
|
|
9798
|
-
agentTools: () => agentTools
|
|
10449
|
+
agentTools: () => agentTools,
|
|
10450
|
+
asToolFailure: () => asToolFailure,
|
|
10451
|
+
toolFailure: () => toolFailure
|
|
9799
10452
|
});
|
|
9800
10453
|
var agentTools, agentSubTools, workflowTools;
|
|
9801
10454
|
var init_tool = __esm({
|
|
@@ -9887,9 +10540,9 @@ var init_lockManager = __esm({
|
|
|
9887
10540
|
|
|
9888
10541
|
// ../core/src/agent/backgroundTool.ts
|
|
9889
10542
|
function normalizeYield(v) {
|
|
9890
|
-
if (typeof v === "string") return v;
|
|
9891
|
-
if (v && typeof v === "object" &&
|
|
9892
|
-
return String(v ?? "");
|
|
10543
|
+
if (typeof v === "string") return { content: v, status: "success" };
|
|
10544
|
+
if (v && typeof v === "object" && typeof v.content === "string" && (v.status === "success" || v.status === "failed")) return v;
|
|
10545
|
+
return { content: String(v ?? ""), status: "success" };
|
|
9893
10546
|
}
|
|
9894
10547
|
async function runBackgroundTool(gen, lockKey, toolName, signal) {
|
|
9895
10548
|
let aborted = false;
|
|
@@ -9922,11 +10575,11 @@ async function runBackgroundTool(gen, lockKey, toolName, signal) {
|
|
|
9922
10575
|
} catch (e) {
|
|
9923
10576
|
console.warn("\u26A0\uFE0F \u5173\u95ED\u672A\u6D88\u8D39\u7684\u540E\u53F0 generator \u5931\u8D25:", e instanceof Error ? e.message : e);
|
|
9924
10577
|
}
|
|
9925
|
-
return `\u{1F512} [\u4E92\u65A5\u9501\u963B\u585E]\uFF1A\u9501 [${lockKey}] \u5DF2\u88AB\u5360\u7528\uFF0C[${toolName}] \u672A\u542F\u52A8\u3002
|
|
10578
|
+
return { content: `\u{1F512} [\u4E92\u65A5\u9501\u963B\u585E]\uFF1A\u9501 [${lockKey}] \u5DF2\u88AB\u5360\u7528\uFF0C[${toolName}] \u672A\u542F\u52A8\u3002`, status: "failed", errorCategory: "runtime" };
|
|
9926
10579
|
}
|
|
9927
10580
|
if (signal?.aborted) {
|
|
9928
10581
|
await finalize();
|
|
9929
|
-
return
|
|
10582
|
+
return toolFailure(`[\u5DF2\u4E2D\u6B62]\uFF1A[${toolName}] \u540E\u53F0\u4EFB\u52A1\u672A\u542F\u52A8\uFF08\u7528\u6237\u5DF2\u4E2D\u65AD\uFF09\u3002`);
|
|
9930
10583
|
}
|
|
9931
10584
|
if (signal) signal.addEventListener("abort", onAbort, { once: true });
|
|
9932
10585
|
let first;
|
|
@@ -9934,9 +10587,9 @@ async function runBackgroundTool(gen, lockKey, toolName, signal) {
|
|
|
9934
10587
|
first = await gen.next();
|
|
9935
10588
|
} catch (e) {
|
|
9936
10589
|
await finalize();
|
|
9937
|
-
return
|
|
10590
|
+
return toolFailure(`[\u540E\u53F0\u542F\u52A8\u5931\u8D25]\uFF1A${e?.message ?? e}`);
|
|
9938
10591
|
}
|
|
9939
|
-
const immediate = first.done ? "(\u540E\u53F0\u4EFB\u52A1\u672A\u4EA7\u51FA\u5373\u65F6\u7ED3\u679C\uFF0C\u5DF2\u76F4\u63A5\u7ED3\u675F)" : normalizeYield(first.value);
|
|
10592
|
+
const immediate = first.done ? { content: "(\u540E\u53F0\u4EFB\u52A1\u672A\u4EA7\u51FA\u5373\u65F6\u7ED3\u679C\uFF0C\u5DF2\u76F4\u63A5\u7ED3\u675F)", status: "success" } : normalizeYield(first.value);
|
|
9940
10593
|
if (first.done) {
|
|
9941
10594
|
await finalize();
|
|
9942
10595
|
return immediate;
|
|
@@ -9966,19 +10619,17 @@ var init_backgroundTool = __esm({
|
|
|
9966
10619
|
"use strict";
|
|
9967
10620
|
init_lockManager();
|
|
9968
10621
|
init_config();
|
|
10622
|
+
init_type();
|
|
9969
10623
|
}
|
|
9970
10624
|
});
|
|
9971
10625
|
|
|
9972
10626
|
// ../core/src/tool/autoPermission.ts
|
|
9973
|
-
import
|
|
9974
|
-
var
|
|
10627
|
+
import path33 from "path";
|
|
10628
|
+
var 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;
|
|
9975
10629
|
var init_autoPermission = __esm({
|
|
9976
10630
|
"../core/src/tool/autoPermission.ts"() {
|
|
9977
10631
|
"use strict";
|
|
9978
10632
|
init_model();
|
|
9979
|
-
AUTO_SCOPE = /* @__PURE__ */ new Set(["edit_file", "write_file", "create_file", "delete_path", "move_file"]);
|
|
9980
|
-
AUTO_DEFAULT_EXTRA = /* @__PURE__ */ new Set(["run_command", "run_in_background"]);
|
|
9981
|
-
AUTO_AGGRESSIVE_EXTRA = /* @__PURE__ */ new Set(["web_fetch", "web_search", "git_commit"]);
|
|
9982
10633
|
isMcpTool = (name) => name.startsWith("mcp__");
|
|
9983
10634
|
BUILTIN_AUTO_DENY = [
|
|
9984
10635
|
/(^|[\\/])\.env(\.|$)/i,
|
|
@@ -10118,27 +10769,28 @@ var init_autoPermission = __esm({
|
|
|
10118
10769
|
isWithinWorkspace = (p, cwd) => {
|
|
10119
10770
|
if (!p || !cwd) return false;
|
|
10120
10771
|
try {
|
|
10121
|
-
const abs =
|
|
10122
|
-
const rel =
|
|
10123
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
10772
|
+
const abs = path33.isAbsolute(p) ? p : path33.resolve(cwd, p);
|
|
10773
|
+
const rel = path33.relative(cwd, abs);
|
|
10774
|
+
return rel === "" || !rel.startsWith("..") && !path33.isAbsolute(rel);
|
|
10124
10775
|
} catch {
|
|
10125
10776
|
return false;
|
|
10126
10777
|
}
|
|
10127
10778
|
};
|
|
10128
|
-
runAutoCheck = async (name, args, ctx, aggressive = false) => {
|
|
10129
|
-
const isFileTool =
|
|
10130
|
-
const inScope = isFileTool ||
|
|
10779
|
+
runAutoCheck = async (name, args, ctx, aggressive = false, decl) => {
|
|
10780
|
+
const isFileTool = decl?.autoApproval === "file";
|
|
10781
|
+
const inScope = isFileTool || decl?.autoApproval === "command" || aggressive && (decl?.autoApproval === "aggressive" || isMcpTool(name));
|
|
10131
10782
|
if (!inScope) return "ask";
|
|
10132
10783
|
if (isFileTool) {
|
|
10133
|
-
const paths =
|
|
10784
|
+
const paths = (decl.pathArgs ?? ["path"]).map((k) => args?.[k]);
|
|
10134
10785
|
for (const p of paths) {
|
|
10135
10786
|
const s = typeof p === "string" ? p : "";
|
|
10136
10787
|
if (!isWithinWorkspace(s, ctx.cwd)) return "ask";
|
|
10137
10788
|
if (matchBuiltinDeny(s)) return "deny";
|
|
10138
10789
|
}
|
|
10139
10790
|
}
|
|
10140
|
-
if (
|
|
10141
|
-
const
|
|
10791
|
+
if (decl?.autoApproval === "command") {
|
|
10792
|
+
const argKey = decl.primaryArg ?? "command";
|
|
10793
|
+
const cmd = typeof args?.[argKey] === "string" ? args[argKey] : "";
|
|
10142
10794
|
if (matchCommandDeny(cmd)) return "deny";
|
|
10143
10795
|
}
|
|
10144
10796
|
const v = await classifyToolRisk(name, args, "", ctx.abortSignal);
|
|
@@ -10148,14 +10800,15 @@ var init_autoPermission = __esm({
|
|
|
10148
10800
|
});
|
|
10149
10801
|
|
|
10150
10802
|
// ../core/src/agent/toolExecution.ts
|
|
10151
|
-
import
|
|
10152
|
-
import path32 from "path";
|
|
10803
|
+
import path34 from "path";
|
|
10153
10804
|
var applyPrivacyMasking, processToolCall;
|
|
10154
10805
|
var init_toolExecution = __esm({
|
|
10155
10806
|
"../core/src/agent/toolExecution.ts"() {
|
|
10156
10807
|
"use strict";
|
|
10157
10808
|
init_truncate();
|
|
10809
|
+
init_toolResultCollect();
|
|
10158
10810
|
init_tool();
|
|
10811
|
+
init_argsValidator();
|
|
10159
10812
|
init_guard();
|
|
10160
10813
|
init_permissions();
|
|
10161
10814
|
init_hooks();
|
|
@@ -10165,8 +10818,7 @@ var init_toolExecution = __esm({
|
|
|
10165
10818
|
init_autoPermission();
|
|
10166
10819
|
init_loader();
|
|
10167
10820
|
init_config();
|
|
10168
|
-
|
|
10169
|
-
init_planMode();
|
|
10821
|
+
init_sidecar();
|
|
10170
10822
|
applyPrivacyMasking = (rules3, args, output) => {
|
|
10171
10823
|
if (!rules3) return output;
|
|
10172
10824
|
try {
|
|
@@ -10231,18 +10883,25 @@ var init_toolExecution = __esm({
|
|
|
10231
10883
|
const placeholder = "\uFF08\u5DF2\u4E2D\u6B62\uFF0C\u672A\u6267\u884C\uFF09";
|
|
10232
10884
|
return { toolCallId: toolCall.id, calledName, calledArgs, resultForModel: placeholder, resultForUser: placeholder, ok: false, aborted: true };
|
|
10233
10885
|
}
|
|
10234
|
-
|
|
10886
|
+
const matchedTool = rawTools.find((t) => t.function.name === calledName);
|
|
10887
|
+
if (!parseFailed && planMode && appConfig.planEnforcement === "runtime" && calledName !== "enter_plan_mode" && calledName !== "exit_plan_mode" && matchedTool?.function?.planAllowed !== true) {
|
|
10235
10888
|
const note = `\u274C [\u8BA1\u5212\u6A21\u5F0F] \u5F53\u524D\u4E3A\u53EA\u8BFB\u8C03\u7814\u9636\u6BB5\uFF0C\u7981\u6B62 ${calledName}\u3002\u5B8C\u6210\u65B9\u6848\u8BF7\u8C03 exit_plan_mode \u63D0\u4EA4\uFF0C\u7ECF\u7528\u6237\u5BA1\u6279\u540E\u8FDB\u5165\u5B9E\u73B0\u9636\u6BB5\u3002`;
|
|
10236
10889
|
events({ sessionId, eventType: "tool.validation.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round }, payload: { output: note } });
|
|
10237
10890
|
return { toolCallId: toolCall.id, calledName, calledArgs, resultForModel: note, resultForUser: note, ok: false };
|
|
10238
10891
|
}
|
|
10239
|
-
const matchedTool = rawTools.find((t) => t.function.name === calledName);
|
|
10240
10892
|
const toolCtx = { sessionId, cwd: getActiveWorkspaceRoot(), abortSignal: signal, depth, keepRecentUnits, compactRatio, modelWindow, parentSystemPrompt, events, onUIEvent, requestApproval: hostRequestApproval, requestQuestion: hostRequestQuestion, emitProgress: (m) => onUIEvent?.({ type: "tool.progress", toolsId: toolCall.id, toolName: calledName, message: m }), permissionMode };
|
|
10241
10893
|
let result = "";
|
|
10242
|
-
let
|
|
10894
|
+
let resultStatus = "success";
|
|
10895
|
+
let errorCategory;
|
|
10896
|
+
const failResult = (text, cat = "runtime") => {
|
|
10897
|
+
result = text;
|
|
10898
|
+
resultStatus = "failed";
|
|
10899
|
+
errorCategory = cat;
|
|
10900
|
+
};
|
|
10243
10901
|
let postHookOverride;
|
|
10902
|
+
let imageAttachments;
|
|
10244
10903
|
if (parseFailed) {
|
|
10245
|
-
|
|
10904
|
+
failResult(`\u53C2\u6570\u89E3\u6790\u5931\u8D25\uFF1A\u6A21\u578B\u8FD4\u56DE\u7684 arguments \u4E0D\u662F\u5408\u6CD5 JSON${JSON.stringify(toolCall).slice(0, 300)}`, "syntax");
|
|
10246
10905
|
events({ sessionId, eventType: "tool.validation.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round }, payload: { output: result } });
|
|
10247
10906
|
} else if (matchedTool && typeof matchedTool.function.execute === "function") {
|
|
10248
10907
|
const level = matchedTool.function.safetyLevel;
|
|
@@ -10259,24 +10918,36 @@ var init_toolExecution = __esm({
|
|
|
10259
10918
|
}
|
|
10260
10919
|
if (veto.deny) {
|
|
10261
10920
|
denied = true;
|
|
10262
|
-
|
|
10921
|
+
failResult(veto.reason || `\u274C [Hook \u62E6\u622A]\uFF1Apre-hook \u62D2\u7EDD\u4E86 [${calledName}] \u7684\u6267\u884C\u3002`, "permission");
|
|
10263
10922
|
} else if (veto.argsOverride !== void 0 && veto.argsOverride !== null && typeof veto.argsOverride === "object" && !Array.isArray(veto.argsOverride)) {
|
|
10264
10923
|
console.log(`\u270F\uFE0F [Pre-hook] [${calledName}] args \u5DF2\u88AB hook \u6539\u5199`);
|
|
10265
10924
|
calledArgs = veto.argsOverride;
|
|
10266
10925
|
}
|
|
10267
10926
|
}
|
|
10268
|
-
|
|
10927
|
+
{
|
|
10928
|
+
const paramsSchema = matchedTool.function.parameters;
|
|
10929
|
+
if (paramsSchema && typeof paramsSchema === "object" && !Array.isArray(paramsSchema)) {
|
|
10930
|
+
const verdict = validateToolArgs(paramsSchema, calledArgs);
|
|
10931
|
+
if (!verdict.ok) {
|
|
10932
|
+
denied = true;
|
|
10933
|
+
failResult(`\u274C \u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF1A${verdict.message}\uFF1B\u8BF7\u4FEE\u6B63\u53C2\u6570\u540E\u91CD\u8BD5\uFF08schema \u8981\u6C42\u89C1\u5DE5\u5177 parameters\uFF09\u3002`, "syntax");
|
|
10934
|
+
events({ sessionId, eventType: "tool.validation.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round }, payload: { output: result } });
|
|
10935
|
+
}
|
|
10936
|
+
}
|
|
10937
|
+
}
|
|
10938
|
+
const pathArgs = matchedTool.function.pathArgs ?? (matchedTool.function.triggersUndo ? ["path"] : []);
|
|
10939
|
+
const protectedPaths = pathArgs.map((k) => calledArgs?.[k]);
|
|
10269
10940
|
const hitProtected = protectedPaths.find((p) => typeof p === "string" && isProtectedWrite(p, toolCtx.cwd));
|
|
10270
10941
|
if (hitProtected) {
|
|
10271
10942
|
denied = true;
|
|
10272
|
-
|
|
10943
|
+
failResult(`\u274C [\u4FDD\u62A4\u8DEF\u5F84] \u7981\u6B62\u4FEE\u6539\u53D7\u4FDD\u62A4\u76EE\u5F55\uFF08.git/.ssh/.aws/.deepseeker-code \u7B49 VCS/\u51ED\u8BC1/\u914D\u7F6E\uFF09\uFF1A${hitProtected}\u3002`, "permission");
|
|
10273
10944
|
}
|
|
10274
10945
|
let perm = null;
|
|
10275
10946
|
try {
|
|
10276
|
-
perm = checkPermission(resolveMcpPermissionName(calledName, calledArgs), calledArgs);
|
|
10947
|
+
perm = checkPermission(resolveMcpPermissionName(calledName, calledArgs), calledArgs, matchedTool.function.primaryArg);
|
|
10277
10948
|
if (perm === "deny") {
|
|
10278
10949
|
denied = true;
|
|
10279
|
-
|
|
10950
|
+
failResult(`\u274C [\u6743\u9650\u89C4\u5219]\uFF1A[${calledName}] \u88AB\u6743\u9650\u89C4\u5219 deny \u62D2\u7EDD\u3002`, "permission");
|
|
10280
10951
|
} else if (perm === "allow") {
|
|
10281
10952
|
needApproval = false;
|
|
10282
10953
|
} else if (perm === "ask") {
|
|
@@ -10289,7 +10960,7 @@ var init_toolExecution = __esm({
|
|
|
10289
10960
|
const argCwd = typeof calledArgs?.cwd === "string" ? calledArgs.cwd.trim() : "";
|
|
10290
10961
|
const samePath = (a, b) => {
|
|
10291
10962
|
try {
|
|
10292
|
-
const ra =
|
|
10963
|
+
const ra = path34.resolve(a), rb = path34.resolve(b);
|
|
10293
10964
|
return process.platform === "win32" ? ra.toLowerCase() === rb.toLowerCase() : ra === rb;
|
|
10294
10965
|
} catch {
|
|
10295
10966
|
return false;
|
|
@@ -10303,21 +10974,27 @@ var init_toolExecution = __esm({
|
|
|
10303
10974
|
}
|
|
10304
10975
|
if ((calledName === "run_command" || calledName === "run_in_background") && matchCommandDeny(typeof calledArgs?.command === "string" ? calledArgs.command : "")) {
|
|
10305
10976
|
denied = true;
|
|
10306
|
-
|
|
10977
|
+
failResult(`\u274C [\u5B89\u5168] \u707E\u96BE\u547D\u4EE4\u6E05\u5355\u62E6\u622A\uFF08\u4E0D\u53EF\u88AB allow \u89C4\u5219\u7ED5\u8FC7\uFF09\uFF1A[${calledName}] ${String(calledArgs?.command ?? "").slice(0, 100)}`, "permission");
|
|
10307
10978
|
}
|
|
10308
10979
|
const isBgTool = matchedTool.function.isSync === false;
|
|
10309
10980
|
const lockKey = isBgTool ? computeLockKey(matchedTool.function.exclusiveLock, calledArgs, toolCtx) : null;
|
|
10310
10981
|
if (lockKey && isLockHeld(lockKey)) {
|
|
10311
10982
|
denied = true;
|
|
10312
|
-
|
|
10983
|
+
failResult(`\u{1F512} [\u4E92\u65A5\u9501\u963B\u585E]\uFF1A\u5DF2\u6709\u540E\u53F0\u4EFB\u52A1\u6301\u6709\u9501 [${lockKey}]\uFF0C[${calledName}] \u8C03\u7528\u88AB\u8DF3\u8FC7\u3002`);
|
|
10313
10984
|
}
|
|
10314
10985
|
if (needApproval && !denied && !scriptRunnerBlocked) {
|
|
10315
|
-
const auto = await runAutoCheck(
|
|
10986
|
+
const auto = await runAutoCheck(
|
|
10987
|
+
resolveMcpPermissionName(calledName, calledArgs),
|
|
10988
|
+
calledArgs,
|
|
10989
|
+
toolCtx,
|
|
10990
|
+
permissionMode === "auto",
|
|
10991
|
+
{ autoApproval: matchedTool.function.autoApproval, pathArgs: matchedTool.function.pathArgs, primaryArg: matchedTool.function.primaryArg }
|
|
10992
|
+
);
|
|
10316
10993
|
if (auto === "allow") {
|
|
10317
10994
|
needApproval = false;
|
|
10318
10995
|
} else if (auto === "deny") {
|
|
10319
10996
|
denied = true;
|
|
10320
|
-
|
|
10997
|
+
failResult(`\u274C [auto] \u5185\u7F6E\u9AD8\u5371\u6E05\u5355\u62E6\u622A\uFF1A[${calledName}] ${calledArgs?.path ?? ""}\u3002`, "permission");
|
|
10321
10998
|
}
|
|
10322
10999
|
}
|
|
10323
11000
|
if (needApproval && !denied) {
|
|
@@ -10327,19 +11004,19 @@ var init_toolExecution = __esm({
|
|
|
10327
11004
|
if (ra) detail = typeof ra === "function" ? await ra(calledArgs, toolCtx) : ra;
|
|
10328
11005
|
} catch (e) {
|
|
10329
11006
|
denied = true;
|
|
10330
|
-
|
|
11007
|
+
failResult(`\u274C [\u5BA1\u6279\u63CF\u8FF0\u751F\u6210\u5F02\u5E38]\uFF1A${e?.message ?? e}\u3002\u51FA\u4E8E\u5B89\u5168\u9ED8\u8BA4\u62D2\u7EDD [${calledName}] \u7684\u6267\u884C\u3002`, "permission");
|
|
10331
11008
|
}
|
|
10332
11009
|
if (!denied) {
|
|
10333
|
-
let
|
|
11010
|
+
let approved2 = false;
|
|
10334
11011
|
try {
|
|
10335
|
-
|
|
11012
|
+
approved2 = await requestApproval(calledName, toolCall.id, detail, toolCtx, level, calledArgs, matchedTool.function.primaryArg);
|
|
10336
11013
|
} catch (e) {
|
|
10337
11014
|
denied = true;
|
|
10338
|
-
|
|
11015
|
+
failResult(`\u274C [\u5BA1\u6279\u6D41\u7A0B\u5F02\u5E38]\uFF1A${e?.message ?? e}\u3002\u51FA\u4E8E\u5B89\u5168\u9ED8\u8BA4\u62D2\u7EDD [${calledName}] \u7684\u6267\u884C\u3002`, "permission");
|
|
10339
11016
|
}
|
|
10340
|
-
if (!
|
|
11017
|
+
if (!approved2 && !denied) {
|
|
10341
11018
|
denied = true;
|
|
10342
|
-
|
|
11019
|
+
failResult(`\u274C [\u5B89\u5168\u7194\u65AD]\uFF1A\u7528\u6237\u62D2\u7EDD\u4E86 [${calledName}] \u7684\u6267\u884C\u7533\u8BF7\u3002`, "permission");
|
|
10343
11020
|
}
|
|
10344
11021
|
}
|
|
10345
11022
|
}
|
|
@@ -10352,26 +11029,26 @@ var init_toolExecution = __esm({
|
|
|
10352
11029
|
}
|
|
10353
11030
|
if (veto.deny) {
|
|
10354
11031
|
denied = true;
|
|
10355
|
-
|
|
11032
|
+
failResult(veto.reason || `\u274C [Hook \u62E6\u622A]\uFF1Apre-hook \u62D2\u7EDD\u4E86 [${calledName}] \u7684\u6267\u884C\u3002`, "permission");
|
|
10356
11033
|
}
|
|
10357
11034
|
}
|
|
10358
|
-
if (!denied &&
|
|
11035
|
+
if (!denied && matchedTool.function.triggersUndo) {
|
|
10359
11036
|
try {
|
|
10360
|
-
await beforeMutationBackup(calledName, calledArgs, toolCall.id, sessionId);
|
|
11037
|
+
await beforeMutationBackup(matchedTool.function.triggersUndo, calledName, calledArgs, toolCall.id, sessionId);
|
|
10361
11038
|
} catch (e) {
|
|
10362
11039
|
denied = true;
|
|
10363
|
-
|
|
11040
|
+
failResult(`\u274C [Undo \u5907\u4EFD\u5931\u8D25\xB7\u5B89\u5168\u7194\u65AD]\uFF1A${e?.message ?? e}\u3002\u5199\u5165\u5DF2\u963B\u6B62\uFF08\u51E1\u6539\u5FC5\u53EF\u56DE\u9000\u539F\u5219\uFF09\u3002`);
|
|
10364
11041
|
}
|
|
10365
11042
|
}
|
|
10366
11043
|
if (!denied) {
|
|
10367
11044
|
try {
|
|
10368
11045
|
events({ sessionId, eventType: "tool.execute.start", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin" }, payload: { output: JSON.stringify(calledArgs) } });
|
|
10369
11046
|
const execRet = matchedTool.function.execute(calledArgs, toolCtx);
|
|
10370
|
-
|
|
10371
|
-
|
|
10372
|
-
|
|
10373
|
-
|
|
10374
|
-
|
|
11047
|
+
const collected = isBgTool ? await runBackgroundTool(execRet, lockKey, calledName, signal) : await collectToolResult(execRet, (chunk) => toolCtx.emitProgress?.(chunk), signal);
|
|
11048
|
+
result = collected.content;
|
|
11049
|
+
resultStatus = collected.status;
|
|
11050
|
+
imageAttachments = collected.images;
|
|
11051
|
+
if (collected.status === "failed") errorCategory = collected.errorCategory ?? "runtime";
|
|
10375
11052
|
if (matchedTool.function.verifyResult) {
|
|
10376
11053
|
const verdict = matchedTool.function.verifyResult(result, toolCtx);
|
|
10377
11054
|
if (verdict.status === "failed" /* FAILED */) {
|
|
@@ -10379,13 +11056,19 @@ var init_toolExecution = __esm({
|
|
|
10379
11056
|
\u8BF7\u6B63\u89C6\u4E0B\u65B9\u8F93\u51FA\uFF0C\u4E0D\u8981\u4E50\u89C2\u5047\u8BBE\u6210\u529F\u3002
|
|
10380
11057
|
|
|
10381
11058
|
${result}`;
|
|
11059
|
+
resultStatus = "failed";
|
|
11060
|
+
errorCategory = verdict.errorCategory ?? "unknown";
|
|
10382
11061
|
}
|
|
10383
11062
|
}
|
|
10384
|
-
|
|
11063
|
+
if (resultStatus === "success") {
|
|
11064
|
+
events({ sessionId, eventType: "tool.execute.end", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: true }, payload: { output: result } });
|
|
11065
|
+
} else {
|
|
11066
|
+
events({ sessionId, eventType: "tool.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round, errorCategory: errorCategory ?? "unknown" }, payload: { output: result } });
|
|
11067
|
+
}
|
|
10385
11068
|
} catch (err) {
|
|
10386
11069
|
console.error(`\u274C \u6267\u884C\u5DE5\u5177 ${calledName} \u65F6\u53D1\u751F\u9519\u8BEF:`, err);
|
|
10387
|
-
|
|
10388
|
-
events({ sessionId, eventType: "tool.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round }, payload: { output: result } });
|
|
11070
|
+
failResult(`\u5DE5\u5177\u6267\u884C\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
11071
|
+
events({ sessionId, eventType: "tool.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round, errorCategory: errorCategory ?? "runtime" }, payload: { output: result } });
|
|
10389
11072
|
}
|
|
10390
11073
|
try {
|
|
10391
11074
|
const post = await runPostHooks(resolveMcpPermissionName(calledName, calledArgs), calledArgs, result, toolCtx);
|
|
@@ -10395,27 +11078,14 @@ ${result}`;
|
|
|
10395
11078
|
}
|
|
10396
11079
|
}
|
|
10397
11080
|
} else {
|
|
10398
|
-
|
|
10399
|
-
explicitOk = false;
|
|
11081
|
+
failResult(`\u9519\u8BEF\uFF1A\u672A\u77E5\u5DE5\u5177 "${calledName}" \u6216\u8BE5\u5DE5\u5177\u65E0\u53EF\u6267\u884C\u51FD\u6570`, "syntax");
|
|
10400
11082
|
events({ sessionId, eventType: "tool.validation.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round }, payload: { output: result } });
|
|
10401
11083
|
}
|
|
10402
11084
|
result = applyPrivacyMasking(matchedTool?.function?.privacyMaskingRules, calledArgs, result);
|
|
10403
|
-
let sidecarNote;
|
|
10404
11085
|
const truncBudget = matchedTool?.function?.maxOutputCharacters ?? appConfig.MAX_TOOL_RESULT_CHARS;
|
|
10405
|
-
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
await fs29.mkdir(sidecarDir, { recursive: true });
|
|
10409
|
-
const safeId = String(toolCall.id).replace(/[^A-Za-z0-9_-]/g, "");
|
|
10410
|
-
await fs29.writeFile(path32.join(sidecarDir, `${safeId}.txt`), result, "utf-8");
|
|
10411
|
-
sidecarNote = `\u5B8C\u6574\u539F\u6587\u5DF2\u5B58\u6863\uFF0Crecall \u5DE5\u5177\u4F20 with_full="${toolCall.id}" \u53EF\u53D6\u56DE`;
|
|
10412
|
-
} catch (e) {
|
|
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);
|
|
10414
|
-
}
|
|
10415
|
-
}
|
|
10416
|
-
result = truncateToolResult(result, matchedTool?.function?.maxOutputCharacters, sidecarNote);
|
|
10417
|
-
const FAILED_PREFIXES = ["\u5DE5\u5177\u6267\u884C\u5931\u8D25", "\u53C2\u6570\u89E3\u6790\u5931\u8D25", "\u274C", "\u3010\u7CFB\u7EDF\u5224\u5B9A", "\u{1F512}", "\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25", "\u9879\u76EE\u6811\u626B\u63CF\u5931\u8D25", "\u7B26\u53F7\u5927\u7EB2\u5206\u6790\u5931\u8D25", "\u64CD\u4F5C\u5931\u8D25:"];
|
|
10418
|
-
const ok = explicitOk ?? !FAILED_PREFIXES.some((p) => result.startsWith(p));
|
|
11086
|
+
const sidecarNote = result.length > truncBudget ? await writeSidecarArchive(sessionId, String(toolCall.id), result) : void 0;
|
|
11087
|
+
result = truncateToolResult(result, matchedTool?.function.maxOutputCharacters, sidecarNote);
|
|
11088
|
+
const ok = resultStatus === "success";
|
|
10419
11089
|
let resultForModel = result;
|
|
10420
11090
|
let resultForUser = result;
|
|
10421
11091
|
if (matchedTool?.function?.outputFilter) {
|
|
@@ -10428,9 +11098,11 @@ ${result}`;
|
|
|
10428
11098
|
}
|
|
10429
11099
|
if (postHookOverride !== void 0) {
|
|
10430
11100
|
console.log(`\u270F\uFE0F [Post-hook] [${calledName}] \u6A21\u578B\u89C6\u56FE\u7ED3\u679C\u5DF2\u88AB hook \u6539\u5199`);
|
|
10431
|
-
|
|
11101
|
+
const overrideBudget = matchedTool?.function?.maxOutputCharacters ?? appConfig.MAX_TOOL_RESULT_CHARS;
|
|
11102
|
+
const overrideNote = postHookOverride.length > overrideBudget ? await writeSidecarArchive(sessionId, String(toolCall.id), postHookOverride) : void 0;
|
|
11103
|
+
resultForModel = truncateToolResult(postHookOverride, matchedTool?.function?.maxOutputCharacters, overrideNote);
|
|
10432
11104
|
}
|
|
10433
|
-
return { toolCallId: toolCall.id, calledName, calledArgs, resultForModel, resultForUser, ok };
|
|
11105
|
+
return { toolCallId: toolCall.id, calledName, calledArgs, resultForModel, resultForUser, ok, imageAttachments };
|
|
10434
11106
|
};
|
|
10435
11107
|
}
|
|
10436
11108
|
});
|
|
@@ -10442,13 +11114,14 @@ var init_toolScheduling = __esm({
|
|
|
10442
11114
|
"use strict";
|
|
10443
11115
|
init_toolExecution();
|
|
10444
11116
|
init_transcript();
|
|
11117
|
+
init_contentParts();
|
|
10445
11118
|
init_config();
|
|
10446
11119
|
init_tool();
|
|
10447
11120
|
init_permissions();
|
|
10448
|
-
init_backup();
|
|
10449
11121
|
scheduleToolCalls = async function* (assistantMessage, message, ctx) {
|
|
10450
11122
|
const { sessionId, signal, rawTools } = ctx;
|
|
10451
11123
|
let abortedDuringTools = false;
|
|
11124
|
+
const pendingImages = [];
|
|
10452
11125
|
const fillRestPlaceholders = async (fromIdx) => {
|
|
10453
11126
|
const tcs2 = assistantMessage.tool_calls;
|
|
10454
11127
|
for (let j = fromIdx + 1; j < tcs2.length; j++) {
|
|
@@ -10472,13 +11145,13 @@ var init_toolScheduling = __esm({
|
|
|
10472
11145
|
const canParallelize = (name, args, parseFailed) => {
|
|
10473
11146
|
if (!parallelSafeToolsEnabled || parseFailed || signal?.aborted) return false;
|
|
10474
11147
|
if (name === "exit_plan_mode" || name === "enter_plan_mode" || name === "ask_question") return false;
|
|
10475
|
-
if (isUndoTrigger(name)) return false;
|
|
10476
11148
|
const matched = rawTools.find((t) => t.function.name === name);
|
|
10477
11149
|
if (!matched) return false;
|
|
11150
|
+
if (matched.function.triggersUndo) return false;
|
|
10478
11151
|
if (matched.function.safetyLevel !== "safe" /* SAFE */) return false;
|
|
10479
11152
|
if (matched.function.isSync === false) return false;
|
|
10480
11153
|
try {
|
|
10481
|
-
const perm = checkPermission(name, args);
|
|
11154
|
+
const perm = checkPermission(name, args, matched.function.primaryArg);
|
|
10482
11155
|
if (perm === "ask" || perm === "deny") return false;
|
|
10483
11156
|
} catch {
|
|
10484
11157
|
return false;
|
|
@@ -10516,6 +11189,7 @@ var init_toolScheduling = __esm({
|
|
|
10516
11189
|
yield { type: "tool.end", toolCallId: oc.toolCallId, toolName: oc.calledName, result: oc.resultForUser, ok: oc.ok };
|
|
10517
11190
|
message.push({ role: "tool", tool_call_id: oc.toolCallId, content: oc.resultForModel });
|
|
10518
11191
|
await appendMessage({ sessionId, role: "tool", tool_call_id: oc.toolCallId, content: oc.resultForModel });
|
|
11192
|
+
if (oc.imageAttachments?.length) pendingImages.push(...oc.imageAttachments);
|
|
10519
11193
|
if (oc.aborted) abortedDuringTools = true;
|
|
10520
11194
|
}
|
|
10521
11195
|
} else {
|
|
@@ -10537,10 +11211,16 @@ var init_toolScheduling = __esm({
|
|
|
10537
11211
|
yield { type: "tool.end", toolCallId: oc.toolCallId, toolName: oc.calledName, result: oc.resultForUser, ok: oc.ok };
|
|
10538
11212
|
message.push({ role: "tool", tool_call_id: oc.toolCallId, content: oc.resultForModel });
|
|
10539
11213
|
await appendMessage({ sessionId, role: "tool", tool_call_id: oc.toolCallId, content: oc.resultForModel });
|
|
11214
|
+
if (oc.imageAttachments?.length) pendingImages.push(...oc.imageAttachments);
|
|
10540
11215
|
if (oc.aborted) abortedDuringTools = true;
|
|
10541
11216
|
idx++;
|
|
10542
11217
|
}
|
|
10543
11218
|
}
|
|
11219
|
+
if (!abortedDuringTools && pendingImages.length > 0) {
|
|
11220
|
+
const parts = buildImageFollowUpParts(pendingImages);
|
|
11221
|
+
message.push({ role: "user", content: parts });
|
|
11222
|
+
await appendMessage({ sessionId, role: "user", content: parts });
|
|
11223
|
+
}
|
|
10544
11224
|
if (abortedDuringTools) return { kind: "aborted" };
|
|
10545
11225
|
return { kind: "completed" };
|
|
10546
11226
|
};
|
|
@@ -10549,7 +11229,7 @@ var init_toolScheduling = __esm({
|
|
|
10549
11229
|
|
|
10550
11230
|
// ../core/src/agent/streamInference.ts
|
|
10551
11231
|
import { createHash as createHash2 } from "node:crypto";
|
|
10552
|
-
var sha1short, RETRY_BACKOFF_CAP_MS, extractRetryAfterMs, withNudgeTail, streamInference;
|
|
11232
|
+
var sha1short, toolsFingerprintCache, RETRY_BACKOFF_CAP_MS, extractRetryAfterMs, withNudgeTail, streamInference;
|
|
10553
11233
|
var init_streamInference = __esm({
|
|
10554
11234
|
"../core/src/agent/streamInference.ts"() {
|
|
10555
11235
|
"use strict";
|
|
@@ -10561,6 +11241,7 @@ var init_streamInference = __esm({
|
|
|
10561
11241
|
init_visionCapability();
|
|
10562
11242
|
init_createModel();
|
|
10563
11243
|
sha1short = (s) => createHash2("sha1").update(s).digest("hex").slice(0, 10);
|
|
11244
|
+
toolsFingerprintCache = /* @__PURE__ */ new WeakMap();
|
|
10564
11245
|
RETRY_BACKOFF_CAP_MS = 3e4;
|
|
10565
11246
|
extractRetryAfterMs = (e) => {
|
|
10566
11247
|
try {
|
|
@@ -10610,7 +11291,14 @@ var init_streamInference = __esm({
|
|
|
10610
11291
|
let assistantMessage = { role: "assistant", content: null };
|
|
10611
11292
|
try {
|
|
10612
11293
|
const prefixFingerprint = {
|
|
10613
|
-
toolsHash:
|
|
11294
|
+
toolsHash: (() => {
|
|
11295
|
+
let h = toolsFingerprintCache.get(cleanedToolSchemas);
|
|
11296
|
+
if (h === void 0) {
|
|
11297
|
+
h = sha1short(JSON.stringify(cleanedToolSchemas));
|
|
11298
|
+
toolsFingerprintCache.set(cleanedToolSchemas, h);
|
|
11299
|
+
}
|
|
11300
|
+
return h;
|
|
11301
|
+
})(),
|
|
10614
11302
|
sysHash: sha1short(String(message[0]?.content ?? "")),
|
|
10615
11303
|
sumHash: sha1short(String(message[1]?.content ?? "")),
|
|
10616
11304
|
msgCount: message.length
|
|
@@ -10701,11 +11389,15 @@ var init_streamInference = __esm({
|
|
|
10701
11389
|
const raHint = retryAfterMs != null ? `\uFF0C\u9075 Retry-After=${retryAfterMs}ms` : "";
|
|
10702
11390
|
console.warn(`\u26A0\uFE0F API \u77AC\u65F6\u9519\u8BEF\uFF08${statusHint}${streamErr instanceof Error ? streamErr.message : String(streamErr)}\uFF09\uFF0C${backoffMs}ms \u540E\u7B2C ${apiRetries}/${MAX_API_RETRIES} \u6B21\u91CD\u8BD5${raHint}...`);
|
|
10703
11391
|
await new Promise((resolve, reject) => {
|
|
10704
|
-
const
|
|
10705
|
-
signal?.addEventListener("abort", () => {
|
|
11392
|
+
const onAbort = () => {
|
|
10706
11393
|
clearTimeout(t);
|
|
10707
11394
|
reject(new Error("aborted"));
|
|
10708
|
-
}
|
|
11395
|
+
};
|
|
11396
|
+
const t = setTimeout(() => {
|
|
11397
|
+
signal?.removeEventListener("abort", onAbort);
|
|
11398
|
+
resolve();
|
|
11399
|
+
}, backoffMs);
|
|
11400
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
10709
11401
|
});
|
|
10710
11402
|
contentBuf = "";
|
|
10711
11403
|
reasoningBuf = "";
|
|
@@ -10806,7 +11498,7 @@ var init_streamInference = __esm({
|
|
|
10806
11498
|
});
|
|
10807
11499
|
|
|
10808
11500
|
// ../core/src/agent/agentNudges.ts
|
|
10809
|
-
var NUDGE_EVERY, NUDGE_FENCE, PHANTOM_FENCE, PHANTOM_RETRY_MAX, EARLY_FINAL_FENCE, EARLY_FINAL_TURN_THRESHOLD, EARLY_FINAL_MAX, TOOL_DIGEST_FENCE, TOOL_DIGEST_MAX, TOOL_DIGEST_WINDOW, TOOL_DIGEST_TEXT_MAX_LEN, PLAN_FIRST_FENCE, REPEAT_FENCE, READ_REPEAT_THRESHOLD, GREP_REPEAT_THRESHOLD, REPEAT_NUDGE_MAX, PHANTOM_TEXT, EARLY_FINAL_TEXT, TOOL_DIGEST_TEXT, NUDGE_TEXT, COMPLEX_VERBS, COMPLEX_OBJECTS, COMPLEX_MARKERS, QUERY_LEAD, looksComplex, PLAN_FIRST_TEXT, looksComplete, parseToolCall, normPath, normQuery, REPEAT_READ_TEXT, REPEAT_GREP_TEXT, createNudgeScheduler;
|
|
11501
|
+
var NUDGE_EVERY, NUDGE_FENCE, PHANTOM_FENCE, PHANTOM_RETRY_MAX, EARLY_FINAL_FENCE, EARLY_FINAL_TURN_THRESHOLD, EARLY_FINAL_MAX, TOOL_DIGEST_FENCE, TOOL_DIGEST_MAX, TOOL_DIGEST_WINDOW, TOOL_DIGEST_TEXT_MAX_LEN, PLAN_FIRST_FENCE, REPEAT_FENCE, READ_REPEAT_THRESHOLD, GREP_REPEAT_THRESHOLD, REPEAT_NUDGE_MAX, TODO_INCOMPLETE_FENCE, TODO_INCOMPLETE_MAX, PHANTOM_TEXT, EARLY_FINAL_TEXT, TOOL_DIGEST_TEXT, NUDGE_TEXT, COMPLEX_VERBS, COMPLEX_OBJECTS, COMPLEX_MARKERS, QUERY_LEAD, looksComplex, PLAN_FIRST_TEXT, looksComplete, parseToolCall, normPath, normQuery, REPEAT_READ_TEXT, REPEAT_GREP_TEXT, TODO_INCOMPLETE_TEXT, createNudgeScheduler;
|
|
10810
11502
|
var init_agentNudges = __esm({
|
|
10811
11503
|
"../core/src/agent/agentNudges.ts"() {
|
|
10812
11504
|
"use strict";
|
|
@@ -10826,6 +11518,8 @@ var init_agentNudges = __esm({
|
|
|
10826
11518
|
READ_REPEAT_THRESHOLD = 3;
|
|
10827
11519
|
GREP_REPEAT_THRESHOLD = 2;
|
|
10828
11520
|
REPEAT_NUDGE_MAX = 3;
|
|
11521
|
+
TODO_INCOMPLETE_FENCE = "\u27E6DSC:TODO_INCOMPLETE\u27E7";
|
|
11522
|
+
TODO_INCOMPLETE_MAX = 1;
|
|
10829
11523
|
PHANTOM_TEXT = "\u4F60\u7684\u4E0A\u4E00\u6761\u56DE\u590D\u6CA1\u6709\u4EFB\u4F55\u5185\u5BB9\u3001\u4E5F\u6CA1\u6709\u8C03\u7528\u4EFB\u4F55\u5DE5\u5177\uFF0C\u4F46\u4EFB\u52A1\u5C1A\u672A\u5B8C\u6210\u3002\u8BF7\u7EE7\u7EED\u63A8\u8FDB\uFF08\u8C03\u7528\u5DE5\u5177\u6216\u7ED9\u51FA\u5B9E\u8D28\u56DE\u7B54\uFF09\uFF1B\u82E5\u786E\u5B9E\u53D7\u963B\u3001\u9700\u8981\u7528\u6237\u51B3\u7B56\uFF0C\u7528 ask_question \u8BF4\u660E\u5177\u4F53\u963B\u585E\u70B9\u3002\u4E0D\u8981\u8FD4\u56DE\u7A7A\u56DE\u590D\u3002";
|
|
10830
11524
|
EARLY_FINAL_TEXT = (round) => `\u4F60\u4EC5 ${round} \u8F6E\u5C31\u51C6\u5907\u6536\u5C3E\uFF0C\u4E14\u56DE\u7B54\u4E2D\u6CA1\u6709\u660E\u786E\u7684\u5B8C\u6210\u58F0\u660E\u3002\u8BF7\u81EA\u68C0\uFF1A\u82E5\u7528\u6237\u8F93\u5165\u672C\u5C31\u65E0\u9700\u5DE5\u5177\uFF08\u5BD2\u6684/\u95F2\u804A/\u7EAF\u95EE\u7B54\uFF09\u3001\u6216\u4F60\u5728\u7B49\u7528\u6237\u6F84\u6E05\u51B3\u7B56\uFF0C\u76F4\u63A5\u6B63\u5E38\u56DE\u5E94\u5373\u53EF\uFF0C\u5FFD\u7565\u672C\u81EA\u68C0\u3001\u4E0D\u8981\u8F93\u51FA\u4EFB\u4F55\u81EA\u68C0\u8BF4\u660E\uFF1B\u82E5\u786E\u6709\u4EFB\u52A1\u672A\u843D\u5730\uFF08\u6240\u9700\u4FE1\u606F\u672A\u83B7\u53D6\u9F50 / \u8BE5\u6539\u7684\u6587\u4EF6\u672A\u6539\u5B8C / \u672A\u9A8C\u8BC1\uFF09\uFF0C\u7ACB\u5373\u7EE7\u7EED\u8C03\u7528\u5DE5\u5177\u63A8\u8FDB\uFF0C\u4E0D\u8981\u8349\u7387\u603B\u7ED3\u6536\u5C3E\uFF1B\u82E5\u786E\u5DF2\u5168\u90E8\u5B8C\u6210\uFF0C\u8BF7\u660E\u786E\u56DE\u590D\u300C\u5DF2\u5B8C\u6210\u300D\u5E76\u7B80\u8FF0\u6210\u679C\u3002`;
|
|
10831
11525
|
TOOL_DIGEST_TEXT = "\u4F60\u521A\u6267\u884C\u5B8C\u5DE5\u5177\u62FF\u5230\u7ED3\u679C\uFF0C\u5374\u672A\u57FA\u4E8E\u8BE5\u7ED3\u679C\u7ED9\u51FA\u5B9E\u8D28\u56DE\u5E94\u5C31\u51C6\u5907\u6536\u5C3E\u3002\u8BF7\u7ED3\u5408\u5DE5\u5177\u8FD4\u56DE\u7ED3\u679C\u7EE7\u7EED\u63A8\u8FDB\uFF1B\u82E5\u7ED3\u679C\u8868\u660E\u4EFB\u52A1\u5C1A\u672A\u5B8C\u6210\uFF08\u5982\u4ECD\u5728\u7F16\u8BD1/\u8FD0\u884C\u3001\u9700\u7EE7\u7EED\u8F6E\u8BE2\uFF09\uFF0C\u7ACB\u5373\u91C7\u53D6\u4E0B\u4E00\u6B65\u884C\u52A8\uFF0C\u4E0D\u8981\u7A7A\u624B\u6536\u5C3E\u3002\u82E5\u786E\u5DF2\u5168\u90E8\u5B8C\u6210\uFF0C\u8BF7\u660E\u786E\u56DE\u590D\u300C\u5DF2\u5B8C\u6210\u300D\u5E76\u7B80\u8FF0\u6210\u679C\u3002";
|
|
@@ -10862,6 +11556,7 @@ var init_agentNudges = __esm({
|
|
|
10862
11556
|
normQuery = (q) => String(q ?? "").trim().toLowerCase().replace(/\s+/g, " ");
|
|
10863
11557
|
REPEAT_READ_TEXT = (p, n) => `\u4F60\u5DF2\u7B2C ${n} \u6B21\u8BFB\u53D6\u300C${p}\u300D\u2014\u2014\u8BE5\u6587\u4EF6\u5185\u5BB9\u4F60\u65E9\u5DF2\u62E5\u6709\uFF0C\u65E0\u9700\u6574\u6587\u4EF6\u91CD\u8BFB\u3002\u5982\u9700\u67D0\u5904\u7EC6\u8282\u8BF7\u56DE\u770B\u4E4B\u524D\u7684\u5DE5\u5177\u7ED3\u679C\uFF08\u65E9\u524D\u8BFB\u53D6\u53EF\u80FD\u5DF2\u88AB\u5F52\u6863\uFF0C\u53EF\u7528 recall \u5DE5\u5177\u68C0\u7D22\u53D6\u56DE\u539F\u6587\uFF09\uFF1B\u82E5\u8BE5\u6587\u4EF6\u521A\u88AB\u6539\u52A8\u3001\u786E\u9700\u786E\u8BA4\uFF0C\u53EA\u8BFB\u6539\u52A8\u9644\u8FD1\u51E0\u884C\u5373\u53EF\uFF0C\u4E0D\u8981\u6574\u6587\u4EF6\u91CD\u8BFB\u3002`;
|
|
10864
11558
|
REPEAT_GREP_TEXT = (q, n) => `\u4F60\u5DF2\u7B2C ${n} \u6B21\u68C0\u7D22\u300C${q}\u300D\u2014\u2014\u4E4B\u524D\u7684\u7ED3\u679C\u4F60\u5DF2\u62E5\u6709\u3002\u8BF7\u6539\u7528 read_file \u8BFB\u5B8C\u6574\u76EE\u6807\u6587\u4EF6\u7406\u89E3\u4E0A\u4E0B\u6587\uFF0C\u6216\u7F29\u5C0F/\u8C03\u6574\u68C0\u7D22\u8303\u56F4\uFF0C\u4E0D\u8981\u91CD\u590D\u540C\u4E00\u68C0\u7D22\u3002`;
|
|
11559
|
+
TODO_INCOMPLETE_TEXT = (openItems) => `\u4F60\u7684\u4EFB\u52A1\u6E05\u5355\u4ECD\u6709 ${openItems.length} \u9879\u672A\u5B8C\u6210${openItems.length ? `\uFF08\u5982\uFF1A${openItems.slice(0, 3).join("\uFF1B")}\uFF09` : ""}\u3002\u8BF7\u6838\u5BF9\uFF1A\u82E5\u8FD9\u4E9B\u5B50\u76EE\u6807\u786E\u5DF2\u843D\u5730\uFF0C\u5148\u8C03 todo_write \u628A\u5BF9\u5E94\u9879\u7F6E completed \u518D\u6536\u5C3E\uFF1B\u82E5\u786E\u672A\u5B8C\u6210\uFF0C\u7EE7\u7EED\u63A8\u8FDB\uFF0C\u4E0D\u8981\u62FF\u7740\u672A\u52FE\u5B8C\u7684\u6E05\u5355\u8349\u7387\u603B\u7ED3\uFF1B\u82E5\u4EFB\u52A1\u5DF2\u88AB\u7528\u6237\u53D6\u6D88\u6216\u53D8\u66F4\uFF0C\u4E5F\u7528 todo_write \u66F4\u65B0\u6E05\u5355\u4EE5\u53CD\u6620\u6700\u65B0\u8BA1\u5212\u3002`;
|
|
10865
11560
|
createNudgeScheduler = (opts = {}) => {
|
|
10866
11561
|
const firstPrompt = opts.firstPrompt ?? "";
|
|
10867
11562
|
const planMode = !!opts.planMode;
|
|
@@ -10881,6 +11576,10 @@ var init_agentNudges = __esm({
|
|
|
10881
11576
|
const nudgedGreps = /* @__PURE__ */ new Set();
|
|
10882
11577
|
let repeatNudges = 0;
|
|
10883
11578
|
let repeatRetrievalPending = null;
|
|
11579
|
+
let todosTouchedThisRun = false;
|
|
11580
|
+
let lastTodos = [];
|
|
11581
|
+
let todoNudges = 0;
|
|
11582
|
+
let todoPending = null;
|
|
10884
11583
|
return {
|
|
10885
11584
|
pickNudge(round) {
|
|
10886
11585
|
if (!planFirstSent && round === 1 && !planMode && looksComplex(firstPrompt)) {
|
|
@@ -10903,6 +11602,11 @@ ${PLAN_FIRST_TEXT}` };
|
|
|
10903
11602
|
earlyFinalPending = null;
|
|
10904
11603
|
return m;
|
|
10905
11604
|
}
|
|
11605
|
+
if (todoPending) {
|
|
11606
|
+
const m = todoPending;
|
|
11607
|
+
todoPending = null;
|
|
11608
|
+
return m;
|
|
11609
|
+
}
|
|
10906
11610
|
if (repeatRetrievalPending) {
|
|
10907
11611
|
const m = repeatRetrievalPending;
|
|
10908
11612
|
repeatRetrievalPending = null;
|
|
@@ -10934,6 +11638,15 @@ ${PHANTOM_TEXT}` };
|
|
|
10934
11638
|
${EARLY_FINAL_TEXT(round)}` };
|
|
10935
11639
|
return true;
|
|
10936
11640
|
}
|
|
11641
|
+
if (todosTouchedThisRun && todoNudges < TODO_INCOMPLETE_MAX) {
|
|
11642
|
+
const open = lastTodos.filter((t) => t && t.status !== "completed" && t.content).map((t) => t.content);
|
|
11643
|
+
if (open.length > 0) {
|
|
11644
|
+
todoNudges++;
|
|
11645
|
+
todoPending = { role: "system", content: `${TODO_INCOMPLETE_FENCE}
|
|
11646
|
+
${TODO_INCOMPLETE_TEXT(open)}` };
|
|
11647
|
+
return true;
|
|
11648
|
+
}
|
|
11649
|
+
}
|
|
10937
11650
|
return false;
|
|
10938
11651
|
},
|
|
10939
11652
|
noteToolCall(round, toolCalls) {
|
|
@@ -10943,6 +11656,11 @@ ${EARLY_FINAL_TEXT(round)}` };
|
|
|
10943
11656
|
if (!Array.isArray(toolCalls)) return;
|
|
10944
11657
|
for (const tc of toolCalls) {
|
|
10945
11658
|
const { name, args } = parseToolCall(tc);
|
|
11659
|
+
if (name === "todo_write") {
|
|
11660
|
+
todosTouchedThisRun = true;
|
|
11661
|
+
lastTodos = Array.isArray(args?.todos) ? args.todos : [];
|
|
11662
|
+
continue;
|
|
11663
|
+
}
|
|
10946
11664
|
if (name === "edit_file" || name === "write_file" || name === "create_file") {
|
|
10947
11665
|
const p = normPath(args?.path);
|
|
10948
11666
|
if (p) {
|
|
@@ -10985,6 +11703,113 @@ ${REPEAT_GREP_TEXT(q, n)}` };
|
|
|
10985
11703
|
}
|
|
10986
11704
|
});
|
|
10987
11705
|
|
|
11706
|
+
// ../core/src/observability/usageLog.ts
|
|
11707
|
+
import fs31 from "fs/promises";
|
|
11708
|
+
import path35 from "path";
|
|
11709
|
+
var USAGE_DISABLED, usageDir, ensuredDir, getUsageLogPath, recordUsageRun, USAGE_FILE_RE, SYNTHETIC_SESSION_RE, readUsageRecords, summarizeUsage, topTools;
|
|
11710
|
+
var init_usageLog = __esm({
|
|
11711
|
+
"../core/src/observability/usageLog.ts"() {
|
|
11712
|
+
"use strict";
|
|
11713
|
+
init_config();
|
|
11714
|
+
USAGE_DISABLED = process.env.DEEPSEEKER_CODE_USAGE_LOG === "0";
|
|
11715
|
+
usageDir = () => path35.join(appConfig.dataDir, "usage");
|
|
11716
|
+
ensuredDir = null;
|
|
11717
|
+
getUsageLogPath = (month) => path35.join(usageDir(), `usage-${month}.jsonl`);
|
|
11718
|
+
recordUsageRun = async (rec) => {
|
|
11719
|
+
if (USAGE_DISABLED) return;
|
|
11720
|
+
try {
|
|
11721
|
+
const full = { workspace: appConfig.userWorkspaceDir, ...rec };
|
|
11722
|
+
const month = (full.ts || (/* @__PURE__ */ new Date()).toISOString()).slice(0, 7);
|
|
11723
|
+
const dir = usageDir();
|
|
11724
|
+
if (ensuredDir !== dir) {
|
|
11725
|
+
await fs31.mkdir(dir, { recursive: true });
|
|
11726
|
+
ensuredDir = dir;
|
|
11727
|
+
}
|
|
11728
|
+
await fs31.appendFile(getUsageLogPath(month), JSON.stringify(full) + "\n", "utf-8");
|
|
11729
|
+
} catch (e) {
|
|
11730
|
+
console.warn("\u26A0\uFE0F [usageLog] \u4F7F\u7528\u65E5\u5FD7\u843D\u76D8\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u4E3B\u4E1A\u52A1\uFF09:", e instanceof Error ? e.message : e);
|
|
11731
|
+
}
|
|
11732
|
+
};
|
|
11733
|
+
USAGE_FILE_RE = /^usage-\d{4}-\d{2}\.jsonl$/;
|
|
11734
|
+
SYNTHETIC_SESSION_RE = /^(selftest-|eval-)/;
|
|
11735
|
+
readUsageRecords = async (days) => {
|
|
11736
|
+
let files;
|
|
11737
|
+
try {
|
|
11738
|
+
files = (await fs31.readdir(usageDir())).filter((f) => USAGE_FILE_RE.test(f)).sort();
|
|
11739
|
+
} catch {
|
|
11740
|
+
return [];
|
|
11741
|
+
}
|
|
11742
|
+
let cutoff = null;
|
|
11743
|
+
if (days && days > 0) {
|
|
11744
|
+
cutoff = /* @__PURE__ */ new Date();
|
|
11745
|
+
cutoff.setHours(0, 0, 0, 0);
|
|
11746
|
+
cutoff.setDate(cutoff.getDate() - (days - 1));
|
|
11747
|
+
}
|
|
11748
|
+
const out = [];
|
|
11749
|
+
for (const f of files) {
|
|
11750
|
+
let text;
|
|
11751
|
+
try {
|
|
11752
|
+
text = await fs31.readFile(path35.join(usageDir(), f), "utf-8");
|
|
11753
|
+
} catch {
|
|
11754
|
+
continue;
|
|
11755
|
+
}
|
|
11756
|
+
for (const line of text.split("\n")) {
|
|
11757
|
+
if (!line.trim()) continue;
|
|
11758
|
+
let rec;
|
|
11759
|
+
try {
|
|
11760
|
+
rec = JSON.parse(line);
|
|
11761
|
+
} catch {
|
|
11762
|
+
continue;
|
|
11763
|
+
}
|
|
11764
|
+
if (!rec || typeof rec !== "object" || !rec.sessionId || !rec.ts) continue;
|
|
11765
|
+
if (SYNTHETIC_SESSION_RE.test(rec.sessionId)) continue;
|
|
11766
|
+
if (cutoff && new Date(rec.ts) < cutoff) continue;
|
|
11767
|
+
out.push(rec);
|
|
11768
|
+
}
|
|
11769
|
+
}
|
|
11770
|
+
return out.sort((a, b) => String(a.ts).localeCompare(String(b.ts)));
|
|
11771
|
+
};
|
|
11772
|
+
summarizeUsage = (records) => {
|
|
11773
|
+
const s = {
|
|
11774
|
+
runs: 0,
|
|
11775
|
+
mainRuns: 0,
|
|
11776
|
+
subRuns: 0,
|
|
11777
|
+
stopReasons: { normal: 0, aborted: 0, error: 0, repeat: 0, limit: 0 },
|
|
11778
|
+
rounds: 0,
|
|
11779
|
+
mainRounds: 0,
|
|
11780
|
+
durationMs: 0,
|
|
11781
|
+
promptTokens: 0,
|
|
11782
|
+
completionTokens: 0,
|
|
11783
|
+
totalTokens: 0,
|
|
11784
|
+
cachedTokens: 0,
|
|
11785
|
+
toolCalls: 0,
|
|
11786
|
+
tools: {}
|
|
11787
|
+
};
|
|
11788
|
+
for (const r of records) {
|
|
11789
|
+
s.runs++;
|
|
11790
|
+
if (r.depth > 0) s.subRuns++;
|
|
11791
|
+
else s.mainRuns++;
|
|
11792
|
+
if (r.stopReason in s.stopReasons) s.stopReasons[r.stopReason]++;
|
|
11793
|
+
s.rounds += r.rounds || 0;
|
|
11794
|
+
if (r.depth === 0) s.mainRounds += r.rounds || 0;
|
|
11795
|
+
s.durationMs += r.durationMs || 0;
|
|
11796
|
+
s.promptTokens += r.promptTokens ?? 0;
|
|
11797
|
+
s.completionTokens += r.completionTokens ?? 0;
|
|
11798
|
+
s.totalTokens += r.totalTokens ?? 0;
|
|
11799
|
+
s.cachedTokens += r.cachedTokens ?? 0;
|
|
11800
|
+
for (const [name, n] of Object.entries(r.tools ?? {})) {
|
|
11801
|
+
s.tools[name] = (s.tools[name] ?? 0) + (n || 0);
|
|
11802
|
+
s.toolCalls += n || 0;
|
|
11803
|
+
}
|
|
11804
|
+
if (!s.firstTs || r.ts < s.firstTs) s.firstTs = r.ts;
|
|
11805
|
+
if (!s.lastTs || r.ts > s.lastTs) s.lastTs = r.ts;
|
|
11806
|
+
}
|
|
11807
|
+
return s;
|
|
11808
|
+
};
|
|
11809
|
+
topTools = (tools, n) => Object.entries(tools).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, n);
|
|
11810
|
+
}
|
|
11811
|
+
});
|
|
11812
|
+
|
|
10988
11813
|
// ../core/src/agent/runAgent.ts
|
|
10989
11814
|
async function* runAgent(message, options) {
|
|
10990
11815
|
const sessionId = options.sessionId;
|
|
@@ -11033,6 +11858,7 @@ async function* runAgent(message, options) {
|
|
|
11033
11858
|
cached_tokens: (usageSum?.cached_tokens ?? 0) + (u.cached_tokens ?? 0)
|
|
11034
11859
|
};
|
|
11035
11860
|
};
|
|
11861
|
+
const toolCounts = {};
|
|
11036
11862
|
await appendEvent(sessionId, { dscEvent: "run.start", runId, depth });
|
|
11037
11863
|
try {
|
|
11038
11864
|
while (true) {
|
|
@@ -11153,6 +11979,10 @@ async function* runAgent(message, options) {
|
|
|
11153
11979
|
return;
|
|
11154
11980
|
}
|
|
11155
11981
|
nudges.noteToolCall(round, assistantMessage.tool_calls);
|
|
11982
|
+
for (const tc of assistantMessage.tool_calls) {
|
|
11983
|
+
const name = tc?.function?.name || "unknown";
|
|
11984
|
+
toolCounts[name] = (toolCounts[name] ?? 0) + 1;
|
|
11985
|
+
}
|
|
11156
11986
|
const repeatVerdict = breaker.check(assistantMessage.tool_calls, round, lastContent);
|
|
11157
11987
|
if (repeatVerdict.tripped) {
|
|
11158
11988
|
stopReason = "repeat";
|
|
@@ -11216,6 +12046,25 @@ async function* runAgent(message, options) {
|
|
|
11216
12046
|
await appendEvent(sessionId, { dscEvent: "run.end", runId, stopReason: signal?.aborted ? "aborted" : stopReason, rounds: round, usage: usageSum });
|
|
11217
12047
|
} catch {
|
|
11218
12048
|
}
|
|
12049
|
+
try {
|
|
12050
|
+
void recordUsageRun({
|
|
12051
|
+
v: 1,
|
|
12052
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12053
|
+
sessionId,
|
|
12054
|
+
runId,
|
|
12055
|
+
depth,
|
|
12056
|
+
model: options.model?.trim() || MODEL_NAME,
|
|
12057
|
+
stopReason: signal?.aborted ? "aborted" : stopReason,
|
|
12058
|
+
rounds: round,
|
|
12059
|
+
durationMs: Math.round(performance.now() - startTime),
|
|
12060
|
+
promptTokens: usageSum?.prompt_tokens,
|
|
12061
|
+
completionTokens: usageSum?.completion_tokens,
|
|
12062
|
+
totalTokens: usageSum?.total_tokens,
|
|
12063
|
+
cachedTokens: usageSum?.cached_tokens,
|
|
12064
|
+
tools: toolCounts
|
|
12065
|
+
});
|
|
12066
|
+
} catch {
|
|
12067
|
+
}
|
|
11219
12068
|
try {
|
|
11220
12069
|
const reason = signal?.aborted ? "aborted" : stopReason;
|
|
11221
12070
|
await dispatch("Stop", { sessionId, cwd, lastText: lastContent || "", reason });
|
|
@@ -11245,163 +12094,13 @@ var init_runAgent = __esm({
|
|
|
11245
12094
|
init_toolScheduling();
|
|
11246
12095
|
init_streamInference();
|
|
11247
12096
|
init_agentNudges();
|
|
11248
|
-
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
// ../core/src/session/recovery.ts
|
|
11252
|
-
var detectInterruption, repairOrphanToolCalls, reconcileCompaction, recoverSession;
|
|
11253
|
-
var init_recovery = __esm({
|
|
11254
|
-
"../core/src/session/recovery.ts"() {
|
|
11255
|
-
"use strict";
|
|
11256
|
-
init_transcript();
|
|
11257
|
-
init_store();
|
|
11258
|
-
detectInterruption = (lines) => {
|
|
11259
|
-
let sawEvents = false;
|
|
11260
|
-
let lastStart;
|
|
11261
|
-
const closed = /* @__PURE__ */ new Set();
|
|
11262
|
-
for (const l of lines) {
|
|
11263
|
-
if (!isEventLine(l)) continue;
|
|
11264
|
-
sawEvents = true;
|
|
11265
|
-
if (l.dscEvent === "run.start") lastStart = l;
|
|
11266
|
-
else if (l.dscEvent === "run.end" || l.dscEvent === "run.abandoned") closed.add(l.runId);
|
|
11267
|
-
}
|
|
11268
|
-
if (!sawEvents || !lastStart) return { kind: "legacy" };
|
|
11269
|
-
return closed.has(lastStart.runId) ? { kind: "clean" } : { kind: "crashed", runId: lastStart.runId };
|
|
11270
|
-
};
|
|
11271
|
-
repairOrphanToolCalls = (msgs, confirmedCrash) => {
|
|
11272
|
-
const placeholder = confirmedCrash ? "\uFF08\u4E0A\u6B21\u4F1A\u8BDD\u5728\u5DE5\u5177\u6267\u884C\u4E2D\u5D29\u6E83\uFF08run \u672A\u95ED\u5408\uFF09\uFF0C\u8BE5\u8C03\u7528\u672A\u6267\u884C\uFF0C\u5DF2\u8DF3\u8FC7\u3002\uFF09" : "\uFF08\u8BE5\u5DE5\u5177\u8C03\u7528\u56E0\u4E0A\u6B21\u4F1A\u8BDD\u5F02\u5E38\u4E2D\u65AD\u672A\u7559\u4E0B\u7ED3\u679C\uFF0C\u5DF2\u8DF3\u8FC7\u3002\uFF09";
|
|
11273
|
-
const out = [];
|
|
11274
|
-
const repairedToolCallIds = [];
|
|
11275
|
-
for (let i = 0; i < msgs.length; i++) {
|
|
11276
|
-
const m = msgs[i];
|
|
11277
|
-
out.push(m);
|
|
11278
|
-
if (m.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
|
|
11279
|
-
const answered = /* @__PURE__ */ new Set();
|
|
11280
|
-
let j = i + 1;
|
|
11281
|
-
while (j < msgs.length && msgs[j].role === "tool") {
|
|
11282
|
-
answered.add(msgs[j].tool_call_id);
|
|
11283
|
-
j++;
|
|
11284
|
-
}
|
|
11285
|
-
for (const tc of m.tool_calls) {
|
|
11286
|
-
if (tc.id && !answered.has(tc.id)) {
|
|
11287
|
-
out.push({ role: "tool", tool_call_id: tc.id, content: placeholder });
|
|
11288
|
-
repairedToolCallIds.push(tc.id);
|
|
11289
|
-
}
|
|
11290
|
-
}
|
|
11291
|
-
}
|
|
11292
|
-
}
|
|
11293
|
-
return { msgs: out, repairedToolCallIds, confirmedCrash };
|
|
11294
|
-
};
|
|
11295
|
-
reconcileCompaction = (state, lines) => {
|
|
11296
|
-
let last;
|
|
11297
|
-
for (const l of lines) {
|
|
11298
|
-
if (isEventLine(l) && l.dscEvent === "compaction") last = l;
|
|
11299
|
-
}
|
|
11300
|
-
if (!last) return { archivedMessageCount: state.archivedMessageCount, rollingSummary: state.rollingSummary, desync: "legacy" };
|
|
11301
|
-
let desync = "none";
|
|
11302
|
-
if (last.archivedMessageCount !== state.archivedMessageCount) {
|
|
11303
|
-
desync = state.archivedMessageCount > last.archivedMessageCount ? "state-ahead" : "event-ahead";
|
|
11304
|
-
console.warn(
|
|
11305
|
-
`\u26A0\uFE0F [recovery] \u538B\u7F29\u72B6\u6001 desync\uFF08${desync}\uFF09\uFF1Astate.json archivedMessageCount=${state.archivedMessageCount} vs \u672B\u4E2A compaction \u4E8B\u4EF6=${last.archivedMessageCount}\u3002\u4EE5 state \u4E3A\u51C6\uFF08slice \u6267\u884C\u95F8\u95E8\uFF09\uFF0C\u4E8B\u4EF6\u4FA7\u4EC5\u955C\u50CF\u3002`
|
|
11306
|
-
);
|
|
11307
|
-
}
|
|
11308
|
-
return { archivedMessageCount: state.archivedMessageCount, rollingSummary: state.rollingSummary, desync };
|
|
11309
|
-
};
|
|
11310
|
-
recoverSession = async (sessionId) => {
|
|
11311
|
-
const lines = await readTranscriptLines(sessionId);
|
|
11312
|
-
const interruption = detectInterruption(lines);
|
|
11313
|
-
if (interruption.kind === "crashed") {
|
|
11314
|
-
await appendEvent(sessionId, {
|
|
11315
|
-
dscEvent: "run.abandoned",
|
|
11316
|
-
runId: interruption.runId,
|
|
11317
|
-
reason: "run.end missing: interrupted by process exit/kill"
|
|
11318
|
-
});
|
|
11319
|
-
console.warn(`\u27E6recovery\u27E7 \u68C0\u6D4B\u5230\u672A\u95ED\u5408 run\uFF08${interruption.runId.slice(0, 8)}\u2026\uFF09\u2192 \u5DF2\u8865 run.abandoned \u95ED\u5893\u6807\u8BB0\uFF1B\u5B64\u513F\u4FEE\u590D\u6309\u300C\u5D29\u6E83\u786E\u8BA4\u300D\u6863\u6267\u884C\u3002`);
|
|
11320
|
-
}
|
|
11321
|
-
const state = await getRollingState(sessionId);
|
|
11322
|
-
const compaction = reconcileCompaction(
|
|
11323
|
-
{ archivedMessageCount: state.archivedMessageCount, rollingSummary: state.rollingSummary },
|
|
11324
|
-
lines
|
|
11325
|
-
);
|
|
11326
|
-
return { interruption, compaction };
|
|
11327
|
-
};
|
|
11328
|
-
}
|
|
11329
|
-
});
|
|
11330
|
-
|
|
11331
|
-
// ../core/src/session/content.ts
|
|
11332
|
-
var decayOldToolResults, enforceVisionGate, buildContextMessages;
|
|
11333
|
-
var init_content = __esm({
|
|
11334
|
-
"../core/src/session/content.ts"() {
|
|
11335
|
-
"use strict";
|
|
11336
|
-
init_contextCore();
|
|
11337
|
-
init_contentParts();
|
|
11338
|
-
init_transcript();
|
|
11339
|
-
init_store();
|
|
11340
|
-
init_config();
|
|
11341
|
-
init_visionCapability();
|
|
11342
|
-
init_recovery();
|
|
11343
|
-
decayOldToolResults = (msgs) => {
|
|
11344
|
-
const units = groupUnits(msgs);
|
|
11345
|
-
const cutoffUnitIdx = Math.max(0, units.length - appConfig.KEEP_RECENT_UNITS);
|
|
11346
|
-
if (cutoffUnitIdx === 0) return msgs;
|
|
11347
|
-
const decayIds = /* @__PURE__ */ new Set();
|
|
11348
|
-
let hasOldImage = false;
|
|
11349
|
-
for (let u = 0; u < cutoffUnitIdx; u++) {
|
|
11350
|
-
for (const m of units[u]) {
|
|
11351
|
-
const mm = m;
|
|
11352
|
-
if (mm.role === "tool" && typeof mm.tool_call_id === "string") decayIds.add(mm.tool_call_id);
|
|
11353
|
-
if (hasImagePart(m.content)) hasOldImage = true;
|
|
11354
|
-
}
|
|
11355
|
-
}
|
|
11356
|
-
if (decayIds.size === 0 && !hasOldImage) return msgs;
|
|
11357
|
-
const keep = appConfig.BOUNDARY_TOOL_KEEP_CHARS;
|
|
11358
|
-
const oldRefs = /* @__PURE__ */ new Set();
|
|
11359
|
-
for (let u = 0; u < cutoffUnitIdx; u++) for (const m of units[u]) oldRefs.add(m);
|
|
11360
|
-
return msgs.map((m) => {
|
|
11361
|
-
if (!oldRefs.has(m)) return m;
|
|
11362
|
-
const mm = m;
|
|
11363
|
-
if (mm.role === "tool" && decayIds.has(mm.tool_call_id) && typeof mm.content === "string" && mm.content.length > keep) {
|
|
11364
|
-
const head = mm.content.slice(0, keep);
|
|
11365
|
-
return { ...mm, content: `${head}
|
|
11366
|
-
|
|
11367
|
-
[\u2026 \u8BE5\u5386\u53F2\u5DE5\u5177\u8F93\u51FA\u5DF2\u6298\u53E0\uFF08\u5171 ${mm.content.length} \u5B57\u7B26\uFF09\uFF0C\u5982\u9700\u7EC6\u8282\u8BF7\u91CD\u65B0\u8C03\u7528\u5DE5\u5177 \u2026]` };
|
|
11368
|
-
}
|
|
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]");
|
|
11370
|
-
});
|
|
11371
|
-
};
|
|
11372
|
-
enforceVisionGate = (msgs, modelId) => isVisionEnabled(modelId) ? msgs : msgs.map((m) => collapseToText(m, VISION_DEGRADE_NOTE));
|
|
11373
|
-
buildContextMessages = async (sessionId, currentUserMsg, systemPrompt, modelId) => {
|
|
11374
|
-
await ensureVisionCacheLoaded();
|
|
11375
|
-
const lines = await readTranscriptLines(sessionId);
|
|
11376
|
-
const store = await getRollingState(sessionId);
|
|
11377
|
-
const eventAware = appConfig.transcriptEvents || lines.some(isEventLine);
|
|
11378
|
-
const recovery = eventAware ? await recoverSession(sessionId) : {
|
|
11379
|
-
interruption: { kind: "legacy" },
|
|
11380
|
-
compaction: { archivedMessageCount: store.archivedMessageCount, rollingSummary: store.rollingSummary, desync: "legacy" }
|
|
11381
|
-
};
|
|
11382
|
-
const all = lines.filter((l) => !isEventLine(l)).map(cleanMsg);
|
|
11383
|
-
const result = [
|
|
11384
|
-
{ role: "system", content: systemPrompt },
|
|
11385
|
-
// 存储系统提示词
|
|
11386
|
-
{ role: "system", content: recovery.compaction.rollingSummary }
|
|
11387
|
-
// 后续存储摘要使用
|
|
11388
|
-
];
|
|
11389
|
-
const archivedMessageCount = recovery.compaction.archivedMessageCount;
|
|
11390
|
-
const messageAll = all.slice(archivedMessageCount);
|
|
11391
|
-
if (messageAll.length === 0) {
|
|
11392
|
-
result.push(currentUserMsg);
|
|
11393
|
-
return enforceVisionGate(result, modelId);
|
|
11394
|
-
}
|
|
11395
|
-
const repair = repairOrphanToolCalls(messageAll, recovery.interruption.kind === "crashed");
|
|
11396
|
-
result.push(...decayOldToolResults(repair.msgs));
|
|
11397
|
-
result.push(currentUserMsg);
|
|
11398
|
-
return enforceVisionGate(result, modelId);
|
|
11399
|
-
};
|
|
12097
|
+
init_usageLog();
|
|
12098
|
+
init_createModel();
|
|
11400
12099
|
}
|
|
11401
12100
|
});
|
|
11402
12101
|
|
|
11403
12102
|
// ../core/src/session/lineage.ts
|
|
11404
|
-
import
|
|
12103
|
+
import fs32 from "node:fs";
|
|
11405
12104
|
var parentOfSubsession, stringAncestorsOf, readForkedFromSync, lineageClosureOf, ownerCanApprove;
|
|
11406
12105
|
var init_lineage = __esm({
|
|
11407
12106
|
"../core/src/session/lineage.ts"() {
|
|
@@ -11424,7 +12123,7 @@ var init_lineage = __esm({
|
|
|
11424
12123
|
};
|
|
11425
12124
|
readForkedFromSync = (sessionId) => {
|
|
11426
12125
|
try {
|
|
11427
|
-
const raw =
|
|
12126
|
+
const raw = fs32.readFileSync(getStatePath(sessionId), "utf-8");
|
|
11428
12127
|
const v = JSON.parse(raw)?.forkedFrom;
|
|
11429
12128
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
11430
12129
|
} catch {
|
|
@@ -11454,7 +12153,7 @@ var init_lineage = __esm({
|
|
|
11454
12153
|
});
|
|
11455
12154
|
|
|
11456
12155
|
// ../core/src/agent/subagent.ts
|
|
11457
|
-
var SUBAGENT_DENYLIST, activeSubagents, RESUME_NOTE, runSubagent;
|
|
12156
|
+
var SUBAGENT_DENYLIST, activeSubagents, failText, RESUME_NOTE, runSubagent;
|
|
11458
12157
|
var init_subagent = __esm({
|
|
11459
12158
|
"../core/src/agent/subagent.ts"() {
|
|
11460
12159
|
"use strict";
|
|
@@ -11468,6 +12167,7 @@ var init_subagent = __esm({
|
|
|
11468
12167
|
init_lineage();
|
|
11469
12168
|
SUBAGENT_DENYLIST = /* @__PURE__ */ new Set(["run_command", "delete_path"]);
|
|
11470
12169
|
activeSubagents = /* @__PURE__ */ new Set();
|
|
12170
|
+
failText = (msg) => toolFailure(msg).content;
|
|
11471
12171
|
RESUME_NOTE = [
|
|
11472
12172
|
`
|
|
11473
12173
|
# \u3010\u7EED\u8DD1\u8BF4\u660E\u3011`,
|
|
@@ -11480,7 +12180,7 @@ var init_subagent = __esm({
|
|
|
11480
12180
|
if (ctx.depth >= MAX_AGENT_DEPTH) {
|
|
11481
12181
|
return {
|
|
11482
12182
|
ok: false,
|
|
11483
|
-
output:
|
|
12183
|
+
output: failText(`[\u5B89\u5168\u7194\u65AD]\uFF1A\u5DF2\u8FBE\u5230\u6700\u5927 Agent \u5D4C\u5957\u6DF1\u5EA6\uFF08${MAX_AGENT_DEPTH}\u5C42\uFF09\u3002\u7981\u6B62\u7EE7\u7EED\u65E0\u9650\u5411\u4E0B\u5D4C\u5957\uFF0C\u8BF7\u7236\u5C42\u7EA7 Agent \u81EA\u884C\u6D88\u5316\u5F53\u524D\u4EFB\u52A1\u3002`),
|
|
11484
12184
|
sessionId: ""
|
|
11485
12185
|
};
|
|
11486
12186
|
}
|
|
@@ -11489,21 +12189,21 @@ var init_subagent = __esm({
|
|
|
11489
12189
|
if (!target.includes("__sub__")) {
|
|
11490
12190
|
return {
|
|
11491
12191
|
ok: false,
|
|
11492
|
-
output:
|
|
12192
|
+
output: failText(`[\u7EED\u8DD1\u5931\u8D25]\uFF1A${target} \u4E0D\u662F\u5B50 Agent \u4F1A\u8BDD ID\uFF08\u5E94\u5F62\u5982 <\u4F1A\u8BDD>__sub__<uuid>\uFF0C\u6765\u81EA\u6B64\u524D spawn_agent \u8FD4\u56DE\u7684 agent_id\uFF09\u3002`),
|
|
11493
12193
|
sessionId: ""
|
|
11494
12194
|
};
|
|
11495
12195
|
}
|
|
11496
12196
|
if (!ownerCanApprove(target, ctx.sessionId)) {
|
|
11497
12197
|
return {
|
|
11498
12198
|
ok: false,
|
|
11499
|
-
output:
|
|
12199
|
+
output: failText(`[\u7EED\u8DD1\u5931\u8D25]\uFF1A\u5B50\u4F1A\u8BDD ${target} \u4E0D\u5C5E\u4E8E\u5F53\u524D\u4F1A\u8BDD\uFF08\u53CA\u5176 fork \u8840\u7F18\uFF09\uFF0C\u7981\u6B62\u8DE8\u4F1A\u8BDD\u590D\u6D3B\u3002\u8BF7\u6838\u5BF9 agent_id \u6216\u6539\u7528\u65B0\u5EFA\u6D3E\u751F\u3002`),
|
|
11500
12200
|
sessionId: ""
|
|
11501
12201
|
};
|
|
11502
12202
|
}
|
|
11503
12203
|
if (activeSubagents.has(target)) {
|
|
11504
12204
|
return {
|
|
11505
12205
|
ok: false,
|
|
11506
|
-
output:
|
|
12206
|
+
output: failText(`[\u7EED\u8DD1\u5931\u8D25]\uFF1A\u5B50 Agent ${target} \u6B63\u5728\u6267\u884C\u4E2D\uFF0C\u7981\u6B62\u5E76\u53D1\u7EED\u8DD1\u540C\u4E00\u5B50\u4F1A\u8BDD\uFF08\u4F1A\u4EA4\u53C9\u5199\u574F\u8F6C\u5F55\uFF09\u3002\u8BF7\u7B49\u5F85\u5176\u5B8C\u6210\u540E\u518D\u8BD5\u3002`),
|
|
11507
12207
|
sessionId: ""
|
|
11508
12208
|
};
|
|
11509
12209
|
}
|
|
@@ -11511,7 +12211,7 @@ var init_subagent = __esm({
|
|
|
11511
12211
|
if (existing.length === 0) {
|
|
11512
12212
|
return {
|
|
11513
12213
|
ok: false,
|
|
11514
|
-
output:
|
|
12214
|
+
output: failText(`[\u7EED\u8DD1\u5931\u8D25]\uFF1A\u5B50\u4F1A\u8BDD ${target} \u7684\u8F6C\u5F55\u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A\uFF0C\u65E0\u6CD5\u7EED\u8DD1\u3002\u8BF7\u6539\u7528\u65B0\u5EFA\u6D3E\u751F\u3002`),
|
|
11515
12215
|
sessionId: ""
|
|
11516
12216
|
};
|
|
11517
12217
|
}
|
|
@@ -11522,7 +12222,7 @@ var init_subagent = __esm({
|
|
|
11522
12222
|
if (name && !manifest) {
|
|
11523
12223
|
return {
|
|
11524
12224
|
ok: false,
|
|
11525
|
-
output:
|
|
12225
|
+
output: failText(`[\u6D3E\u751F\u5931\u8D25]\uFF1A\u672A\u627E\u5230\u58F0\u660E\u5F0F\u5B50 Agent "${name}"\u3002\u8BF7\u6838\u5BF9\u7CFB\u7EDF\u63D0\u793A\u8BCD\u4E2D\u3010\u53EF\u7528\u5B50 Agent \u76EE\u5F55\u3011\u7684\u540D\u79F0\u62FC\u5199\u3002`),
|
|
11526
12226
|
sessionId: ""
|
|
11527
12227
|
};
|
|
11528
12228
|
}
|
|
@@ -11589,7 +12289,7 @@ var init_subagent = __esm({
|
|
|
11589
12289
|
try {
|
|
11590
12290
|
for await (const e of runAgent(subMessages, subOptions)) {
|
|
11591
12291
|
if (ctx.abortSignal?.aborted) {
|
|
11592
|
-
result = { ok: false, output:
|
|
12292
|
+
result = { ok: false, output: failText(`[\u5B50Agent\u4E2D\u65AD]\uFF1A\u6267\u884C\u5DF2\u88AB\u7528\u6237\u4E3B\u52A8\u53D1\u8D77\u7684 AbortSignal \u5F3A\u884C\u7194\u65AD\u3002`), sessionId: subSessionId, manifestName: manifest?.name };
|
|
11593
12293
|
break;
|
|
11594
12294
|
}
|
|
11595
12295
|
if (e.type === "final") {
|
|
@@ -11604,15 +12304,15 @@ var init_subagent = __esm({
|
|
|
11604
12304
|
result = { ok: true, output: subResult, sessionId: subSessionId, manifestName: manifest?.name };
|
|
11605
12305
|
}
|
|
11606
12306
|
} catch (streamError) {
|
|
11607
|
-
result = { ok: false, output:
|
|
12307
|
+
result = { ok: false, output: failText(`[\u5B50Agent\u5D29\u6E83]\uFF1A\u5B50 Agent \u5728\u8FED\u4EE3\u63A8\u7406\u4E3B\u5FAA\u73AF\u65F6\u906D\u9047\u5E95\u5C42\u5F02\u5E38: ${streamError.message}`), sessionId: subSessionId, manifestName: manifest?.name };
|
|
11608
12308
|
} finally {
|
|
11609
12309
|
if (result) {
|
|
11610
12310
|
await dispatch("SubagentStop", { ...startCtx, ok: result.ok, output: result.output.slice(0, 2e3) }).catch((e) => console.warn(`\u26A0\uFE0F SubagentStop hook \u5F02\u5E38\uFF08\u5DF2\u5FFD\u7565\uFF09: ${e?.message ?? e}`));
|
|
11611
12311
|
}
|
|
11612
12312
|
}
|
|
11613
|
-
return result ?? { ok: false, output:
|
|
12313
|
+
return result ?? { ok: false, output: failText(`[\u6D3E\u751F\u6267\u884C\u5931\u8D25]: \u672A\u77E5\u9519\u8BEF`), sessionId: subSessionId, manifestName: manifest?.name };
|
|
11614
12314
|
} catch (error) {
|
|
11615
|
-
return { ok: false, output:
|
|
12315
|
+
return { ok: false, output: failText(`[\u6D3E\u751F\u6267\u884C\u5931\u8D25]: ${error.message}`), sessionId: subSessionId, manifestName: manifest?.name };
|
|
11616
12316
|
} finally {
|
|
11617
12317
|
activeSubagents.delete(subSessionId);
|
|
11618
12318
|
}
|
|
@@ -11620,10 +12320,48 @@ var init_subagent = __esm({
|
|
|
11620
12320
|
}
|
|
11621
12321
|
});
|
|
11622
12322
|
|
|
12323
|
+
// ../core/src/hooks/trust.ts
|
|
12324
|
+
import path36 from "path";
|
|
12325
|
+
import fs33 from "fs/promises";
|
|
12326
|
+
var TRUSTED_HOOKS_FILE, approved, loaded, ensureLoaded, isHookCommandApproved, approveHookCommand;
|
|
12327
|
+
var init_trust2 = __esm({
|
|
12328
|
+
"../core/src/hooks/trust.ts"() {
|
|
12329
|
+
"use strict";
|
|
12330
|
+
init_config();
|
|
12331
|
+
init_common();
|
|
12332
|
+
TRUSTED_HOOKS_FILE = path36.join(appConfig.dataDir, "trusted_hooks.json");
|
|
12333
|
+
approved = /* @__PURE__ */ new Set();
|
|
12334
|
+
loaded = false;
|
|
12335
|
+
ensureLoaded = async () => {
|
|
12336
|
+
if (loaded) return;
|
|
12337
|
+
const list = await readJSONFile(TRUSTED_HOOKS_FILE);
|
|
12338
|
+
if (Array.isArray(list)) {
|
|
12339
|
+
for (const x of list) if (typeof x === "string") approved.add(x);
|
|
12340
|
+
}
|
|
12341
|
+
loaded = true;
|
|
12342
|
+
};
|
|
12343
|
+
isHookCommandApproved = async (ident) => {
|
|
12344
|
+
await ensureLoaded();
|
|
12345
|
+
return approved.has(ident);
|
|
12346
|
+
};
|
|
12347
|
+
approveHookCommand = async (ident) => {
|
|
12348
|
+
await ensureLoaded();
|
|
12349
|
+
if (approved.has(ident)) return;
|
|
12350
|
+
approved.add(ident);
|
|
12351
|
+
try {
|
|
12352
|
+
await fs33.mkdir(appConfig.dataDir, { recursive: true });
|
|
12353
|
+
await atomicWriteJSON(TRUSTED_HOOKS_FILE, [...approved]);
|
|
12354
|
+
} catch (e) {
|
|
12355
|
+
console.warn(`\u26A0\uFE0F [hooks] \u5BA1\u6279\u8BB0\u5FC6\u843D\u76D8\u5931\u8D25\uFF08\u672C\u6B21\u5DF2\u653E\u884C\uFF0C\u4E0B\u6B21\u9996\u8DD1\u4F1A\u518D\u95EE\uFF09: ${e?.message ?? e}`);
|
|
12356
|
+
}
|
|
12357
|
+
};
|
|
12358
|
+
}
|
|
12359
|
+
});
|
|
12360
|
+
|
|
11623
12361
|
// ../core/src/hooks/loader.ts
|
|
11624
|
-
import
|
|
11625
|
-
import
|
|
11626
|
-
var readHooksConfig, appendValidated, validateRule, parseStdoutDecision, parseAgentDecision, compileRule2, loadHooks, initHooks;
|
|
12362
|
+
import fs34 from "fs/promises";
|
|
12363
|
+
import path37 from "path";
|
|
12364
|
+
var slimHookContext, readHooksConfig, appendValidated, validateRule, parseStdoutDecision, parseAgentDecision, gateSeq, firstRunGate, compileRule2, loadHooks, initHooks;
|
|
11627
12365
|
var init_loader4 = __esm({
|
|
11628
12366
|
"../core/src/hooks/loader.ts"() {
|
|
11629
12367
|
"use strict";
|
|
@@ -11634,18 +12372,32 @@ var init_loader4 = __esm({
|
|
|
11634
12372
|
init_subagent();
|
|
11635
12373
|
init_tool();
|
|
11636
12374
|
init_types();
|
|
12375
|
+
init_trust2();
|
|
12376
|
+
slimHookContext = (ctx) => {
|
|
12377
|
+
if (!ctx || typeof ctx !== "object" || !ctx.toolContext) return ctx;
|
|
12378
|
+
const { toolContext, ...rest } = ctx;
|
|
12379
|
+
return {
|
|
12380
|
+
...rest,
|
|
12381
|
+
toolContext: {
|
|
12382
|
+
sessionId: toolContext.sessionId,
|
|
12383
|
+
cwd: toolContext.cwd,
|
|
12384
|
+
depth: toolContext.depth,
|
|
12385
|
+
permissionMode: toolContext.permissionMode
|
|
12386
|
+
}
|
|
12387
|
+
};
|
|
12388
|
+
};
|
|
11637
12389
|
readHooksConfig = async (includeProject) => {
|
|
11638
12390
|
const merged = {};
|
|
11639
12391
|
const paths = [
|
|
11640
|
-
|
|
12392
|
+
path37.join(appConfig.dataDir, "settings.json"),
|
|
11641
12393
|
// 全局用户级
|
|
11642
|
-
...includeProject ? [
|
|
12394
|
+
...includeProject ? [path37.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
|
|
11643
12395
|
// 项目级(叠加);未信任时省略
|
|
11644
12396
|
];
|
|
11645
12397
|
for (const configPath of paths) {
|
|
11646
12398
|
let raw;
|
|
11647
12399
|
try {
|
|
11648
|
-
raw = await
|
|
12400
|
+
raw = await fs34.readFile(configPath, "utf-8");
|
|
11649
12401
|
} catch {
|
|
11650
12402
|
continue;
|
|
11651
12403
|
}
|
|
@@ -11658,14 +12410,14 @@ var init_loader4 = __esm({
|
|
|
11658
12410
|
}
|
|
11659
12411
|
const hooksBlock = parsed?.hooks;
|
|
11660
12412
|
if (!hooksBlock || typeof hooksBlock !== "object") continue;
|
|
11661
|
-
appendValidated(merged, hooksBlock, configPath);
|
|
12413
|
+
appendValidated(merged, hooksBlock, configPath, configPath === paths[1]);
|
|
11662
12414
|
if (configPath === paths[1] && Object.keys(hooksBlock).length > 0) {
|
|
11663
12415
|
console.warn(`\u26A0\uFE0F\u3010\u5B89\u5168\u63D0\u793A\u3011\u5DF2\u52A0\u8F7D\u9879\u76EE\u7EA7 hook \u914D\u7F6E [${configPath}]\uFF0C\u5176 command \u5C06\u4EE5 shell \u6267\u884C\u3002\u4EC5\u5728\u4FE1\u4EFB\u8BE5\u9879\u76EE\u65F6\u542F\u7528\uFF1B\u514B\u9686\u672A\u77E5\u4ED3\u5E93\u524D\u8BF7\u6838\u67E5\u8BE5\u6587\u4EF6\u4EE5\u9632\u4EFB\u610F\u547D\u4EE4\u6267\u884C\u3002`);
|
|
11664
12416
|
}
|
|
11665
12417
|
}
|
|
11666
12418
|
return merged;
|
|
11667
12419
|
};
|
|
11668
|
-
appendValidated = (merged, hooksBlock, src) => {
|
|
12420
|
+
appendValidated = (merged, hooksBlock, src, isProject) => {
|
|
11669
12421
|
for (const [key, val] of Object.entries(hooksBlock)) {
|
|
11670
12422
|
if (!ALL_EVENTS.includes(key)) {
|
|
11671
12423
|
console.warn(`\u26A0\uFE0F [hooks] \u672A\u77E5\u4E8B\u4EF6\u7C7B\u578B "${key}"\uFF08${src}\uFF09\uFF0C\u5DF2\u8DF3\u8FC7`);
|
|
@@ -11679,7 +12431,7 @@ var init_loader4 = __esm({
|
|
|
11679
12431
|
const list = merged[event] ??= [];
|
|
11680
12432
|
val.forEach((item, i) => {
|
|
11681
12433
|
const rule = validateRule(item, event, src, i);
|
|
11682
|
-
if (rule) list.push(rule);
|
|
12434
|
+
if (rule) list.push(isProject ? { ...rule, projectSource: true } : rule);
|
|
11683
12435
|
});
|
|
11684
12436
|
}
|
|
11685
12437
|
};
|
|
@@ -11802,10 +12554,52 @@ var init_loader4 = __esm({
|
|
|
11802
12554
|
}
|
|
11803
12555
|
return { deny: false, explicit: false };
|
|
11804
12556
|
};
|
|
12557
|
+
gateSeq = 0;
|
|
12558
|
+
firstRunGate = (raw, ident, run) => {
|
|
12559
|
+
const gated = raw.requireApproval === true || raw.projectSource === true;
|
|
12560
|
+
if (!gated) return run;
|
|
12561
|
+
return async (ctx) => {
|
|
12562
|
+
if (await isHookCommandApproved(ident)) return run(ctx);
|
|
12563
|
+
const req = ctx?.toolContext?.requestApproval;
|
|
12564
|
+
if (typeof req !== "function") {
|
|
12565
|
+
console.warn(`\u23ED\uFE0F [hooks] ${raw.type ?? "command"} hook \u9996\u8DD1\u5F85\u5BA1\u6279\u4E14\u5F53\u524D\u4E8B\u4EF6\u65E0\u5BA1\u6279\u901A\u9053\uFF0C\u5DF2\u8DF3\u8FC7\uFF1A${ident.slice(0, 120)}\uFF08\u53EF\u5728 CLI \u5DE5\u5177\u4E8B\u4EF6\u89E6\u53D1\u65F6\u6279\u51C6\u300C\u59CB\u7EC8\u5141\u8BB8\u300D\uFF0C\u6216\u624B\u52A8\u52A0\u5165 ~/.deepseeker-code/trusted_hooks.json\uFF09`);
|
|
12566
|
+
return { deny: false };
|
|
12567
|
+
}
|
|
12568
|
+
const kindLabel = raw.projectSource ? "\u9879\u76EE\u7EA7" : "\u5168\u5C40";
|
|
12569
|
+
const detail = raw.type === "http" ? `${kindLabel} hook \u9996\u6B21\u8FD0\u884C\uFF1A\u8BF7\u6C42\u5C06\u4E0A\u4E0B\u6587 POST \u5230\u5916\u90E8 URL
|
|
12570
|
+
${ident}` : raw.type === "agent" ? `${kindLabel} hook \u9996\u6B21\u8FD0\u884C\uFF1A\u6D3E\u5B50 agent \u8BC4\u5224\u5DE5\u5177\u8C03\u7528
|
|
12571
|
+
\u4EFB\u52A1\uFF1A${ident}` : `${kindLabel} hook \u9996\u6B21\u8FD0\u884C\uFF1A\u6267\u884C shell \u547D\u4EE4
|
|
12572
|
+
${ident}`;
|
|
12573
|
+
let decision;
|
|
12574
|
+
try {
|
|
12575
|
+
decision = await req(detail, {
|
|
12576
|
+
toolName: `hook:${raw.type ?? "command"}`,
|
|
12577
|
+
toolCallId: `hook-${++gateSeq}`,
|
|
12578
|
+
sessionId: ctx?.toolContext?.sessionId ?? ""
|
|
12579
|
+
});
|
|
12580
|
+
} catch (e) {
|
|
12581
|
+
console.warn(`\u23ED\uFE0F [hooks] \u9996\u8DD1\u5BA1\u6279\u901A\u9053\u5F02\u5E38\uFF0C\u5DF2\u8DF3\u8FC7\u8BE5 hook: ${e?.message ?? e}`);
|
|
12582
|
+
return { deny: false };
|
|
12583
|
+
}
|
|
12584
|
+
if (decision === "deny") {
|
|
12585
|
+
console.warn(`\u23ED\uFE0F [hooks] \u9996\u8DD1\u5BA1\u6279\u88AB\u62D2\u7EDD\uFF0C\u672C\u6B21\u8DF3\u8FC7\u8BE5 hook\uFF1A${ident.slice(0, 120)}`);
|
|
12586
|
+
return { deny: false };
|
|
12587
|
+
}
|
|
12588
|
+
if (decision === "allow-always") await approveHookCommand(ident);
|
|
12589
|
+
return run(ctx);
|
|
12590
|
+
};
|
|
12591
|
+
};
|
|
11805
12592
|
compileRule2 = (event, raw) => {
|
|
11806
12593
|
const denyOnNonZero = raw.denyOnNonZero ?? event === "PreToolUse";
|
|
11807
12594
|
const timeoutMs2 = raw.timeoutMs ?? DEFAULT_TIMEOUT_BY_EVENT[event];
|
|
11808
|
-
const base = {
|
|
12595
|
+
const base = {
|
|
12596
|
+
event,
|
|
12597
|
+
matcher: raw.matcher,
|
|
12598
|
+
source: "config",
|
|
12599
|
+
onError: raw.onError,
|
|
12600
|
+
// #9 可观测:首跑审批门是否启用(/hooks 展示)
|
|
12601
|
+
firstRunApproval: raw.requireApproval === true || raw.projectSource === true
|
|
12602
|
+
};
|
|
11809
12603
|
if (raw.type === "prompt") {
|
|
11810
12604
|
const text = raw.text;
|
|
11811
12605
|
return { ...base, run: async () => ({ contextAdditions: [text] }) };
|
|
@@ -11814,7 +12608,7 @@ var init_loader4 = __esm({
|
|
|
11814
12608
|
const task = raw.task;
|
|
11815
12609
|
return {
|
|
11816
12610
|
...base,
|
|
11817
|
-
run: async (ctx) => {
|
|
12611
|
+
run: firstRunGate(raw, task, async (ctx) => {
|
|
11818
12612
|
const tc = ctx?.toolContext;
|
|
11819
12613
|
if (!tc || typeof tc.depth === "number" && tc.depth > 0) return { deny: false };
|
|
11820
12614
|
const fullTask = [
|
|
@@ -11835,20 +12629,20 @@ var init_loader4 = __esm({
|
|
|
11835
12629
|
return decision.deny ? { deny: true, reason: decision.reason ?? "hook agent \u62D2\u7EDD\uFF08\u672A\u7ED9\u7406\u7531\uFF09" } : { deny: false };
|
|
11836
12630
|
}
|
|
11837
12631
|
return denyOnNonZero ? { deny: true, reason: "hook agent \u672A\u8F93\u51FA\u660E\u786E\u51B3\u7B56\uFF08DENY/ALLOW\uFF09\uFF0C\u6309 fail-closed \u62D2\u7EDD" } : { deny: false };
|
|
11838
|
-
}
|
|
12632
|
+
})
|
|
11839
12633
|
};
|
|
11840
12634
|
}
|
|
11841
12635
|
if (raw.type === "http") {
|
|
11842
12636
|
const url = raw.url;
|
|
11843
12637
|
return {
|
|
11844
12638
|
...base,
|
|
11845
|
-
run: async (ctx) => {
|
|
12639
|
+
run: firstRunGate(raw, url, async (ctx) => {
|
|
11846
12640
|
const res = await executeHttpHook({
|
|
11847
12641
|
url,
|
|
11848
12642
|
method: raw.method,
|
|
11849
12643
|
headers: raw.headers,
|
|
11850
|
-
body: ctx,
|
|
11851
|
-
//
|
|
12644
|
+
body: slimHookContext(ctx),
|
|
12645
|
+
// hook 上下文 JSON 化发出(含 sessionId/toolName/args/prompt 等;toolContext 走瘦投影)
|
|
11852
12646
|
timeoutMs: timeoutMs2
|
|
11853
12647
|
});
|
|
11854
12648
|
if (!res.ok) {
|
|
@@ -11872,19 +12666,19 @@ var init_loader4 = __esm({
|
|
|
11872
12666
|
return { deny: true, reason: `hook http \u72B6\u6001\u7801 ${res.status}` };
|
|
11873
12667
|
}
|
|
11874
12668
|
return { deny: false };
|
|
11875
|
-
}
|
|
12669
|
+
})
|
|
11876
12670
|
};
|
|
11877
12671
|
}
|
|
11878
12672
|
const command = raw.command;
|
|
11879
12673
|
return {
|
|
11880
12674
|
...base,
|
|
11881
|
-
run: async (ctx) => {
|
|
12675
|
+
run: firstRunGate(raw, command, async (ctx) => {
|
|
11882
12676
|
const res = await executeHookCommand({
|
|
11883
12677
|
command,
|
|
11884
12678
|
cwd: ctx?.cwd,
|
|
11885
12679
|
env: ctx?.env,
|
|
11886
12680
|
timeoutMs: timeoutMs2,
|
|
11887
|
-
stdinPayload: ctx
|
|
12681
|
+
stdinPayload: slimHookContext(ctx)
|
|
11888
12682
|
});
|
|
11889
12683
|
if (res.timedOut) {
|
|
11890
12684
|
return denyOnNonZero ? { deny: true, reason: `hook \u6267\u884C\u8D85\u65F6\uFF08>${timeoutMs2}ms\uFF09` } : { deny: false };
|
|
@@ -11898,19 +12692,19 @@ var init_loader4 = __esm({
|
|
|
11898
12692
|
if (out) return out;
|
|
11899
12693
|
}
|
|
11900
12694
|
return { deny: false };
|
|
11901
|
-
}
|
|
12695
|
+
})
|
|
11902
12696
|
};
|
|
11903
12697
|
};
|
|
11904
12698
|
loadHooks = async (includeProject) => {
|
|
11905
12699
|
const cfg = await readHooksConfig(includeProject);
|
|
11906
|
-
const
|
|
12700
|
+
const compiled2 = [];
|
|
11907
12701
|
for (const event of ALL_EVENTS) {
|
|
11908
12702
|
const list = cfg[event];
|
|
11909
12703
|
if (!list || list.length === 0) continue;
|
|
11910
|
-
for (const raw of list)
|
|
12704
|
+
for (const raw of list) compiled2.push(compileRule2(event, raw));
|
|
11911
12705
|
}
|
|
11912
|
-
replaceDeclarativeHooks(
|
|
11913
|
-
return
|
|
12706
|
+
replaceDeclarativeHooks(compiled2);
|
|
12707
|
+
return compiled2.length;
|
|
11914
12708
|
};
|
|
11915
12709
|
initHooks = async (includeProject) => {
|
|
11916
12710
|
try {
|
|
@@ -11961,11 +12755,11 @@ ${m.context}`;
|
|
|
11961
12755
|
async execute(args) {
|
|
11962
12756
|
const name = args?.name;
|
|
11963
12757
|
if (typeof name !== "string" || !name.trim()) {
|
|
11964
|
-
return "
|
|
12758
|
+
return toolFailure("[load_skill] \u7F3A\u5C11\u53C2\u6570 name\u3002\u8BF7\u5148\u67E5\u770B\u3010\u53EF\u7528\u6280\u80FD\u76EE\u5F55\u3011\u4E2D\u7684\u6280\u80FD\u540D\u3002");
|
|
11965
12759
|
}
|
|
11966
12760
|
const manifest = getSkillManifest(name.trim());
|
|
11967
12761
|
if (!manifest) {
|
|
11968
|
-
return `\
|
|
12762
|
+
return toolFailure(`\u672A\u627E\u5230\u6280\u80FD\uFF1A${name}\u3002\u8BF7\u6838\u5BF9\u3010\u53EF\u7528\u6280\u80FD\u76EE\u5F55\u3011\u4E2D\u7684\u540D\u79F0\u62FC\u5199\u3002`);
|
|
11969
12763
|
}
|
|
11970
12764
|
return assembleSkillContent(manifest);
|
|
11971
12765
|
}
|
|
@@ -11976,8 +12770,8 @@ ${m.context}`;
|
|
|
11976
12770
|
});
|
|
11977
12771
|
|
|
11978
12772
|
// ../core/src/skills/loader.ts
|
|
11979
|
-
import
|
|
11980
|
-
import
|
|
12773
|
+
import fs35 from "fs/promises";
|
|
12774
|
+
import path38 from "path";
|
|
11981
12775
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11982
12776
|
var BUILTIN_DIR, SOURCES2, MAX_SKILL_BODY_BYTES, splitList, parseSkillAt, loadSkills, initSkills;
|
|
11983
12777
|
var init_loader5 = __esm({
|
|
@@ -11988,18 +12782,18 @@ var init_loader5 = __esm({
|
|
|
11988
12782
|
init_registry3();
|
|
11989
12783
|
init_skill();
|
|
11990
12784
|
init_registry2();
|
|
11991
|
-
BUILTIN_DIR =
|
|
12785
|
+
BUILTIN_DIR = path38.join(path38.dirname(fileURLToPath2(import.meta.url)), "builtin");
|
|
11992
12786
|
SOURCES2 = [
|
|
11993
12787
|
{ dir: BUILTIN_DIR, source: "builtin" },
|
|
11994
|
-
{ dir:
|
|
11995
|
-
{ dir:
|
|
12788
|
+
{ dir: path38.join(appConfig.dataDir, "skills"), source: "global" },
|
|
12789
|
+
{ dir: path38.join(process.cwd(), ".deepseeker-code", "skills"), source: "project" }
|
|
11996
12790
|
];
|
|
11997
12791
|
MAX_SKILL_BODY_BYTES = 64 * 1024;
|
|
11998
12792
|
splitList = (raw) => (raw ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
11999
12793
|
parseSkillAt = async (skillFile, dir, source) => {
|
|
12000
12794
|
let raw;
|
|
12001
12795
|
try {
|
|
12002
|
-
raw = await
|
|
12796
|
+
raw = await fs35.readFile(skillFile, "utf-8");
|
|
12003
12797
|
} catch {
|
|
12004
12798
|
return null;
|
|
12005
12799
|
}
|
|
@@ -12038,7 +12832,7 @@ var init_loader5 = __esm({
|
|
|
12038
12832
|
loadSkills = async (includeProject) => {
|
|
12039
12833
|
const picked = await scanSources(
|
|
12040
12834
|
filterSources(SOURCES2, includeProject),
|
|
12041
|
-
(e, dir) => e.isDirectory() ?
|
|
12835
|
+
(e, dir) => e.isDirectory() ? path38.join(dir, e.name, "SKILL.md") : void 0,
|
|
12042
12836
|
parseSkillAt
|
|
12043
12837
|
);
|
|
12044
12838
|
for (const { item } of picked) registerSkill(item);
|
|
@@ -12069,8 +12863,8 @@ var init_loader5 = __esm({
|
|
|
12069
12863
|
});
|
|
12070
12864
|
|
|
12071
12865
|
// ../core/src/agents/loader.ts
|
|
12072
|
-
import
|
|
12073
|
-
import
|
|
12866
|
+
import fs36 from "fs/promises";
|
|
12867
|
+
import path39 from "path";
|
|
12074
12868
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
12075
12869
|
var BUILTIN_DIR2, SOURCES3, parseAgentAt, initAgents;
|
|
12076
12870
|
var init_loader6 = __esm({
|
|
@@ -12080,16 +12874,16 @@ var init_loader6 = __esm({
|
|
|
12080
12874
|
init_frontmatter();
|
|
12081
12875
|
init_registry4();
|
|
12082
12876
|
init_registry2();
|
|
12083
|
-
BUILTIN_DIR2 =
|
|
12877
|
+
BUILTIN_DIR2 = path39.join(path39.dirname(fileURLToPath3(import.meta.url)), "builtin");
|
|
12084
12878
|
SOURCES3 = [
|
|
12085
12879
|
{ dir: BUILTIN_DIR2, source: "builtin" },
|
|
12086
|
-
{ dir:
|
|
12087
|
-
{ dir:
|
|
12880
|
+
{ dir: path39.join(appConfig.dataDir, "agents"), source: "global" },
|
|
12881
|
+
{ dir: path39.join(process.cwd(), ".deepseeker-code", "agents"), source: "project" }
|
|
12088
12882
|
];
|
|
12089
12883
|
parseAgentAt = async (file, dir, source) => {
|
|
12090
12884
|
let raw;
|
|
12091
12885
|
try {
|
|
12092
|
-
raw = await
|
|
12886
|
+
raw = await fs36.readFile(file, "utf-8");
|
|
12093
12887
|
} catch {
|
|
12094
12888
|
return null;
|
|
12095
12889
|
}
|
|
@@ -12124,7 +12918,7 @@ var init_loader6 = __esm({
|
|
|
12124
12918
|
const known = new Set(into.map((t) => t.function.name));
|
|
12125
12919
|
const picked = await scanSources(
|
|
12126
12920
|
filterSources(SOURCES3, includeProject),
|
|
12127
|
-
(e, dir) => e.isFile() && e.name.endsWith(".agent.md") ?
|
|
12921
|
+
(e, dir) => e.isFile() && e.name.endsWith(".agent.md") ? path39.join(dir, e.name) : void 0,
|
|
12128
12922
|
parseAgentAt
|
|
12129
12923
|
);
|
|
12130
12924
|
for (const { item: m, file, source } of picked) {
|
|
@@ -12161,8 +12955,8 @@ var init_registry7 = __esm({
|
|
|
12161
12955
|
});
|
|
12162
12956
|
|
|
12163
12957
|
// ../core/src/commands/loader.ts
|
|
12164
|
-
import
|
|
12165
|
-
import
|
|
12958
|
+
import fs37 from "fs/promises";
|
|
12959
|
+
import path40 from "path";
|
|
12166
12960
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
12167
12961
|
var BUILTIN_DIR3, SOURCES4, MAX_COMMAND_BODY_BYTES, parseCommandAt, loadCommands, initCommands;
|
|
12168
12962
|
var init_loader7 = __esm({
|
|
@@ -12172,17 +12966,17 @@ var init_loader7 = __esm({
|
|
|
12172
12966
|
init_frontmatter();
|
|
12173
12967
|
init_registry7();
|
|
12174
12968
|
init_registry2();
|
|
12175
|
-
BUILTIN_DIR3 =
|
|
12969
|
+
BUILTIN_DIR3 = path40.join(path40.dirname(fileURLToPath4(import.meta.url)), "builtin");
|
|
12176
12970
|
SOURCES4 = [
|
|
12177
12971
|
{ dir: BUILTIN_DIR3, source: "builtin" },
|
|
12178
|
-
{ dir:
|
|
12179
|
-
{ dir:
|
|
12972
|
+
{ dir: path40.join(appConfig.dataDir, "commands"), source: "global" },
|
|
12973
|
+
{ dir: path40.join(process.cwd(), ".deepseeker-code", "commands"), source: "project" }
|
|
12180
12974
|
];
|
|
12181
12975
|
MAX_COMMAND_BODY_BYTES = 64 * 1024;
|
|
12182
12976
|
parseCommandAt = async (file, _dir, source) => {
|
|
12183
12977
|
let raw;
|
|
12184
12978
|
try {
|
|
12185
|
-
raw = await
|
|
12979
|
+
raw = await fs37.readFile(file, "utf-8");
|
|
12186
12980
|
} catch {
|
|
12187
12981
|
return null;
|
|
12188
12982
|
}
|
|
@@ -12193,7 +12987,7 @@ var init_loader7 = __esm({
|
|
|
12193
12987
|
}
|
|
12194
12988
|
const name = parsed.frontmatter.name;
|
|
12195
12989
|
const description = parsed.frontmatter.description;
|
|
12196
|
-
const fallbackName =
|
|
12990
|
+
const fallbackName = path40.basename(file, ".md");
|
|
12197
12991
|
const finalName = name || fallbackName;
|
|
12198
12992
|
if (!description) {
|
|
12199
12993
|
console.warn(`\u26A0\uFE0F [commands] \u7F3A\u5C11 description\uFF08${file}\uFF09\uFF0C\u5DF2\u8DF3\u8FC7`);
|
|
@@ -12219,7 +13013,7 @@ var init_loader7 = __esm({
|
|
|
12219
13013
|
loadCommands = async (includeProject) => {
|
|
12220
13014
|
const picked = await scanSources(
|
|
12221
13015
|
filterSources(SOURCES4, includeProject),
|
|
12222
|
-
(e, dir) => e.isFile() && e.name.endsWith(".md") ?
|
|
13016
|
+
(e, dir) => e.isFile() && e.name.endsWith(".md") ? path40.join(dir, e.name) : void 0,
|
|
12223
13017
|
parseCommandAt
|
|
12224
13018
|
);
|
|
12225
13019
|
for (const { item } of picked) registerCommand(item);
|
|
@@ -12237,8 +13031,8 @@ var init_loader7 = __esm({
|
|
|
12237
13031
|
});
|
|
12238
13032
|
|
|
12239
13033
|
// ../core/src/outputStyles/loader.ts
|
|
12240
|
-
import
|
|
12241
|
-
import
|
|
13034
|
+
import fs38 from "fs/promises";
|
|
13035
|
+
import path41 from "path";
|
|
12242
13036
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
12243
13037
|
var BUILTIN_DIR4, MAX_STYLE_BODY_BYTES, SOURCES5, parseStyleAt, loadOutputStyles, initOutputStyles;
|
|
12244
13038
|
var init_loader8 = __esm({
|
|
@@ -12248,17 +13042,17 @@ var init_loader8 = __esm({
|
|
|
12248
13042
|
init_frontmatter();
|
|
12249
13043
|
init_registry5();
|
|
12250
13044
|
init_registry2();
|
|
12251
|
-
BUILTIN_DIR4 =
|
|
13045
|
+
BUILTIN_DIR4 = path41.join(path41.dirname(fileURLToPath5(import.meta.url)), "builtin");
|
|
12252
13046
|
MAX_STYLE_BODY_BYTES = 64 * 1024;
|
|
12253
13047
|
SOURCES5 = [
|
|
12254
13048
|
{ dir: BUILTIN_DIR4, source: "builtin" },
|
|
12255
|
-
{ dir:
|
|
12256
|
-
{ dir:
|
|
13049
|
+
{ dir: path41.join(appConfig.dataDir, "output-styles"), source: "global" },
|
|
13050
|
+
{ dir: path41.join(process.cwd(), ".deepseeker-code", "output-styles"), source: "project" }
|
|
12257
13051
|
];
|
|
12258
13052
|
parseStyleAt = async (file, _dir, source) => {
|
|
12259
13053
|
let raw;
|
|
12260
13054
|
try {
|
|
12261
|
-
raw = await
|
|
13055
|
+
raw = await fs38.readFile(file, "utf-8");
|
|
12262
13056
|
} catch {
|
|
12263
13057
|
return null;
|
|
12264
13058
|
}
|
|
@@ -12290,7 +13084,7 @@ var init_loader8 = __esm({
|
|
|
12290
13084
|
loadOutputStyles = async (includeProject) => {
|
|
12291
13085
|
const picked = await scanSources(
|
|
12292
13086
|
filterSources(SOURCES5, includeProject),
|
|
12293
|
-
(e, dir) => e.isFile() && e.name.endsWith(".md") ?
|
|
13087
|
+
(e, dir) => e.isFile() && e.name.endsWith(".md") ? path41.join(dir, e.name) : void 0,
|
|
12294
13088
|
parseStyleAt
|
|
12295
13089
|
);
|
|
12296
13090
|
for (const { item } of picked) registerOutputStyle(item);
|
|
@@ -12371,8 +13165,8 @@ var init_bootstrap = __esm({
|
|
|
12371
13165
|
});
|
|
12372
13166
|
|
|
12373
13167
|
// ../core/src/statusLine/config.ts
|
|
12374
|
-
import
|
|
12375
|
-
import
|
|
13168
|
+
import fs39 from "fs/promises";
|
|
13169
|
+
import path42 from "path";
|
|
12376
13170
|
var parseBlock, readStatusLineConfig;
|
|
12377
13171
|
var init_config2 = __esm({
|
|
12378
13172
|
"../core/src/statusLine/config.ts"() {
|
|
@@ -12388,16 +13182,16 @@ var init_config2 = __esm({
|
|
|
12388
13182
|
};
|
|
12389
13183
|
readStatusLineConfig = async (includeProject) => {
|
|
12390
13184
|
const paths = [
|
|
12391
|
-
|
|
13185
|
+
path42.join(appConfig.dataDir, "settings.json"),
|
|
12392
13186
|
// 全局用户级
|
|
12393
|
-
...includeProject ? [
|
|
13187
|
+
...includeProject ? [path42.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
|
|
12394
13188
|
// 项目级(覆盖);未信任时省略
|
|
12395
13189
|
];
|
|
12396
13190
|
let result = null;
|
|
12397
13191
|
for (const configPath of paths) {
|
|
12398
13192
|
let raw;
|
|
12399
13193
|
try {
|
|
12400
|
-
raw = await
|
|
13194
|
+
raw = await fs39.readFile(configPath, "utf-8");
|
|
12401
13195
|
} catch {
|
|
12402
13196
|
continue;
|
|
12403
13197
|
}
|
|
@@ -12417,8 +13211,8 @@ var init_config2 = __esm({
|
|
|
12417
13211
|
|
|
12418
13212
|
// ../core/src/statusLine/runner.ts
|
|
12419
13213
|
import { spawn as spawn5 } from "child_process";
|
|
12420
|
-
import
|
|
12421
|
-
import
|
|
13214
|
+
import fs40 from "fs";
|
|
13215
|
+
import path43 from "path";
|
|
12422
13216
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
12423
13217
|
var STATUSLINE_TIMEOUT_MS, cachedVersion, runStatusLine;
|
|
12424
13218
|
var init_runner = __esm({
|
|
@@ -12427,16 +13221,16 @@ var init_runner = __esm({
|
|
|
12427
13221
|
init_guard();
|
|
12428
13222
|
STATUSLINE_TIMEOUT_MS = 3e3;
|
|
12429
13223
|
try {
|
|
12430
|
-
const here =
|
|
13224
|
+
const here = path43.dirname(fileURLToPath6(import.meta.url));
|
|
12431
13225
|
const candidates = [
|
|
12432
|
-
|
|
13226
|
+
path43.join(here, "../../../package.json"),
|
|
12433
13227
|
// src/core/package.json
|
|
12434
|
-
|
|
13228
|
+
path43.join(here, "../../../../package.json")
|
|
12435
13229
|
// 仓库根 package.json
|
|
12436
13230
|
];
|
|
12437
13231
|
for (const p of candidates) {
|
|
12438
13232
|
try {
|
|
12439
|
-
const pkg = JSON.parse(
|
|
13233
|
+
const pkg = JSON.parse(fs40.readFileSync(p, "utf-8"));
|
|
12440
13234
|
if (typeof pkg.version === "string" && pkg.version) {
|
|
12441
13235
|
cachedVersion = pkg.version;
|
|
12442
13236
|
break;
|
|
@@ -12487,8 +13281,8 @@ var init_runner = __esm({
|
|
|
12487
13281
|
});
|
|
12488
13282
|
|
|
12489
13283
|
// ../core/src/observability/store.ts
|
|
12490
|
-
import
|
|
12491
|
-
import
|
|
13284
|
+
import path44 from "path";
|
|
13285
|
+
import fs41 from "fs/promises";
|
|
12492
13286
|
var getTraceDirPath, getTracePath, tracePathCache, ensuredTraceDirs, ensureTraceDir, getGlobalClockPath, getTraceStorePath;
|
|
12493
13287
|
var init_store3 = __esm({
|
|
12494
13288
|
"../core/src/observability/store.ts"() {
|
|
@@ -12498,21 +13292,21 @@ var init_store3 = __esm({
|
|
|
12498
13292
|
init_common();
|
|
12499
13293
|
getTraceDirPath = (mainTraceId) => {
|
|
12500
13294
|
assertSafeSessionId(mainTraceId, "traceId");
|
|
12501
|
-
return
|
|
13295
|
+
return path44.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
|
|
12502
13296
|
};
|
|
12503
13297
|
getTracePath = () => {
|
|
12504
|
-
return
|
|
13298
|
+
return path44.join(appConfig.dataDir, "trace");
|
|
12505
13299
|
};
|
|
12506
13300
|
tracePathCache = /* @__PURE__ */ new Map();
|
|
12507
13301
|
ensuredTraceDirs = /* @__PURE__ */ new Set();
|
|
12508
13302
|
ensureTraceDir = async (mainTraceId) => {
|
|
12509
13303
|
const dir = getTraceDirPath(mainTraceId);
|
|
12510
13304
|
if (ensuredTraceDirs.has(dir)) return;
|
|
12511
|
-
await
|
|
13305
|
+
await fs41.mkdir(dir, { recursive: true });
|
|
12512
13306
|
ensuredTraceDirs.add(dir);
|
|
12513
13307
|
};
|
|
12514
13308
|
getGlobalClockPath = () => {
|
|
12515
|
-
return
|
|
13309
|
+
return path44.join(getTracePath(), "trace-cleanup-clock.json");
|
|
12516
13310
|
};
|
|
12517
13311
|
getTraceStorePath = async (mainTraceId) => {
|
|
12518
13312
|
assertSafeSessionId(mainTraceId, "traceId");
|
|
@@ -12521,7 +13315,7 @@ var init_store3 = __esm({
|
|
|
12521
13315
|
if (cached2) return cached2;
|
|
12522
13316
|
await ensureTraceDir(rootId);
|
|
12523
13317
|
const dir = getTraceDirPath(rootId);
|
|
12524
|
-
const files = await
|
|
13318
|
+
const files = await fs41.readdir(dir);
|
|
12525
13319
|
const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
|
|
12526
13320
|
let fileName = "";
|
|
12527
13321
|
if (existedFile) {
|
|
@@ -12530,7 +13324,7 @@ var init_store3 = __esm({
|
|
|
12530
13324
|
const todayStr = getTodayDateString();
|
|
12531
13325
|
fileName = `trace-${todayStr}__${rootId}.jsonl`;
|
|
12532
13326
|
}
|
|
12533
|
-
const resolved =
|
|
13327
|
+
const resolved = path44.join(dir, fileName);
|
|
12534
13328
|
tracePathCache.set(rootId, resolved);
|
|
12535
13329
|
return resolved;
|
|
12536
13330
|
};
|
|
@@ -12538,8 +13332,8 @@ var init_store3 = __esm({
|
|
|
12538
13332
|
});
|
|
12539
13333
|
|
|
12540
13334
|
// ../core/src/observability/trace.ts
|
|
12541
|
-
import
|
|
12542
|
-
import
|
|
13335
|
+
import fs42 from "fs/promises";
|
|
13336
|
+
import path45 from "path";
|
|
12543
13337
|
async function emitTrace(base) {
|
|
12544
13338
|
const event = {
|
|
12545
13339
|
sessionId: base.sessionId,
|
|
@@ -12561,7 +13355,7 @@ async function emitTrace(base) {
|
|
|
12561
13355
|
async function appendTraceEvent(event) {
|
|
12562
13356
|
const p = await getTraceStorePath(event.sessionId);
|
|
12563
13357
|
const line = JSON.stringify(event) + "\n";
|
|
12564
|
-
await
|
|
13358
|
+
await fs42.appendFile(p, line, "utf-8");
|
|
12565
13359
|
if (workspaceTraceBytes < 0) {
|
|
12566
13360
|
workspaceTraceBytes = await getDirBytes(getTracePath());
|
|
12567
13361
|
}
|
|
@@ -12593,8 +13387,8 @@ async function maybeCleanupAfterAppend(sessionId) {
|
|
|
12593
13387
|
lastSizeCleanupAt2 = now;
|
|
12594
13388
|
diskLastCleanupAt2 = now;
|
|
12595
13389
|
const clockPath = getGlobalClockPath();
|
|
12596
|
-
await
|
|
12597
|
-
await
|
|
13390
|
+
await fs42.mkdir(path45.dirname(clockPath), { recursive: true });
|
|
13391
|
+
await fs42.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
|
|
12598
13392
|
if (deletedCount > 0) {
|
|
12599
13393
|
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`);
|
|
12600
13394
|
}
|
|
@@ -12614,22 +13408,22 @@ async function cleanupOldTraceFiles() {
|
|
|
12614
13408
|
let deleted = 0;
|
|
12615
13409
|
let relativePaths;
|
|
12616
13410
|
try {
|
|
12617
|
-
relativePaths = await
|
|
13411
|
+
relativePaths = await fs42.readdir(dir, { recursive: true });
|
|
12618
13412
|
} catch {
|
|
12619
13413
|
return 0;
|
|
12620
13414
|
}
|
|
12621
13415
|
const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
12622
13416
|
for (const relativePath of relativePaths) {
|
|
12623
|
-
const fileName =
|
|
13417
|
+
const fileName = path45.basename(relativePath);
|
|
12624
13418
|
const m = fileName.match(re);
|
|
12625
13419
|
if (!m) continue;
|
|
12626
13420
|
const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
|
|
12627
13421
|
if (fileBornDay >= cutoff) continue;
|
|
12628
|
-
const fullPath =
|
|
13422
|
+
const fullPath = path45.join(dir, relativePath);
|
|
12629
13423
|
try {
|
|
12630
|
-
const st = await
|
|
13424
|
+
const st = await fs42.stat(fullPath);
|
|
12631
13425
|
if (now - st.mtimeMs < ACTIVE_GRACE_MS2) continue;
|
|
12632
|
-
await
|
|
13426
|
+
await fs42.unlink(fullPath);
|
|
12633
13427
|
deleted += 1;
|
|
12634
13428
|
} catch {
|
|
12635
13429
|
}
|
|
@@ -12640,18 +13434,18 @@ async function evictOldestForSize2(targetBytes) {
|
|
|
12640
13434
|
const dir = getTracePath();
|
|
12641
13435
|
let relativePaths;
|
|
12642
13436
|
try {
|
|
12643
|
-
relativePaths = await
|
|
13437
|
+
relativePaths = await fs42.readdir(dir, { recursive: true });
|
|
12644
13438
|
} catch {
|
|
12645
13439
|
return 0;
|
|
12646
13440
|
}
|
|
12647
13441
|
const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
12648
13442
|
const candidates = [];
|
|
12649
13443
|
for (const relativePath of relativePaths) {
|
|
12650
|
-
const fileName =
|
|
13444
|
+
const fileName = path45.basename(relativePath);
|
|
12651
13445
|
if (!re.test(fileName)) continue;
|
|
12652
13446
|
try {
|
|
12653
|
-
const st = await
|
|
12654
|
-
candidates.push({ mtime: st.mtimeMs, fullPath:
|
|
13447
|
+
const st = await fs42.stat(path45.join(dir, relativePath));
|
|
13448
|
+
candidates.push({ mtime: st.mtimeMs, fullPath: path45.join(dir, relativePath), size: st.size });
|
|
12655
13449
|
} catch {
|
|
12656
13450
|
}
|
|
12657
13451
|
}
|
|
@@ -12661,7 +13455,7 @@ async function evictOldestForSize2(targetBytes) {
|
|
|
12661
13455
|
for (const c of candidates) {
|
|
12662
13456
|
if (totalBytes <= targetBytes) break;
|
|
12663
13457
|
try {
|
|
12664
|
-
await
|
|
13458
|
+
await fs42.unlink(c.fullPath);
|
|
12665
13459
|
totalBytes -= c.size;
|
|
12666
13460
|
deleted += 1;
|
|
12667
13461
|
} catch {
|
|
@@ -12693,7 +13487,7 @@ var init_trace = __esm({
|
|
|
12693
13487
|
if (clockLoaded2) return;
|
|
12694
13488
|
clockLoaded2 = true;
|
|
12695
13489
|
try {
|
|
12696
|
-
const rawClock = await
|
|
13490
|
+
const rawClock = await fs42.readFile(getGlobalClockPath(), "utf-8");
|
|
12697
13491
|
diskLastCleanupAt2 = JSON.parse(rawClock).lastCleanupAt || 0;
|
|
12698
13492
|
} catch {
|
|
12699
13493
|
diskLastCleanupAt2 = 0;
|
|
@@ -12819,7 +13613,7 @@ var init_systemPrompt = __esm({
|
|
|
12819
13613
|
- **\u6539\u5B8C\u52FF\u7ACB\u523B\u91CD\u8BFB\uFF08\u53CD\u788E\u6B65\xB7\u91CD\u8981\uFF09**\uFF1Aedit_file / write_file \u6210\u529F\u8FD4\u56DE\u540E\uFF0C\u5DE5\u5177\u7ED3\u679C\u5DF2\u8BF4\u660E\u6539\u4E86\u4EC0\u4E48\uFF0C\u4E0D\u8981\u9A6C\u4E0A read_file \u628A\u6574\u4E2A\u6587\u4EF6\u91CD\u8BFB\u4E00\u904D\u6765"\u786E\u8BA4"\u3002\u786E\u9700\u6838\u9A8C\u65F6\uFF0C\u53EA\u8BFB\u6539\u52A8\u9644\u8FD1\u51E0\u884C\u6216\u8DD1\u7C7B\u578B\u68C0\u67E5/\u6D4B\u8BD5\uFF0C\u800C\u975E\u6574\u6587\u4EF6\u91CD\u8BFB\u3002
|
|
12820
13614
|
- \u4E0D\u91CD\u590D\u6293\u53D6\u5DF2\u6293\u53D6\u8FC7\u7684 URL\uFF1B\u4E0D\u7528\u8FD1\u4E49\u5173\u952E\u8BCD\u53CD\u590D\u641C\u7D22\u540C\u4E00\u4E2A\u610F\u56FE\u3002
|
|
12821
13615
|
- \u8054\u7F51/\u641C\u7D22\u7C7B\u8C03\u7814\u4EFB\u52A1\uFF0C\u901A\u5E38 1~3 \u4E2A\u6765\u6E90\u5DF2\u8DB3\u591F\u652F\u6491\u56DE\u7B54\u2014\u2014\u62FF\u5230\u5373\u7EFC\u5408\u4F5C\u7B54\uFF0C\u4E0D\u8981\u4E3A\u8FFD\u6C42"\u66F4\u5168\u9762"\u800C\u65E0\u9650\u8FFD\u52A0\u68C0\u7D22\u8F6E\u6B21\u3002
|
|
12822
|
-
- \
|
|
13616
|
+
- **\u72EC\u7ACB\u8BFB\u64CD\u4F5C\u5E76\u884C\u6253\u5305\uFF08\u91CD\u8981\uFF09**\uFF1A\u591A\u4E2A\u4E92\u4E0D\u4F9D\u8D56\u7684\u53EA\u8BFB\u8C03\u7528\uFF08\u8BFB\u591A\u4E2A\u6587\u4EF6\u3001\u591A\u4E2A\u68C0\u7D22\u3001\u591A\u4E2A\u5B9A\u4E49\u67E5\u8BE2\uFF09\u5E94\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u4E00\u6B21\u6027\u5168\u90E8\u53D1\u51FA\uFF0C\u6267\u884C\u5C42\u4F1A\u81EA\u52A8\u5E76\u53D1\u6267\u884C\uFF0C\u4E00\u8F6E\u9876\u591A\u8F6E\uFF1B\u6709\u4F9D\u8D56\uFF08\u540E\u4E00\u6B65\u8981\u7528\u524D\u4E00\u6B65\u7ED3\u679C\uFF09\u6216\u4F1A\u6539\u72B6\u6001\u7684\u64CD\u4F5C\uFF0C\u5FC5\u987B\u7B49\u524D\u5E8F\u7ED3\u679C\u8FD4\u56DE\u518D\u53D1\u3002
|
|
12823
13617
|
- \u591A\u6B65\u9AA4\u7684\u590D\u6742\u4EFB\u52A1\uFF08\u22653 \u6B65\u3001\u8DE8\u591A\u6587\u4EF6\u6216\u591A\u9636\u6BB5\uFF09\u5148\u8C03\u7528 todo_write \u628A\u8BA1\u5212\u62C6\u6210\u53EF\u52FE\u9009\u7684\u4EFB\u52A1\u6E05\u5355\uFF0C\u518D\u9010\u6B65\u63A8\u8FDB\u5E76\u5373\u65F6\u66F4\u65B0\u72B6\u6001\u2014\u2014\u8BA9\u4F60\u548C\u7528\u6237\u90FD\u770B\u6E05\u8FDB\u5EA6\u3001\u4E0D\u9057\u6F0F\u6B65\u9AA4\uFF1B\u7B80\u5355 1-2 \u6B65\u7684\u4EFB\u52A1\u65E0\u9700\u5EFA\u6E05\u5355\u3002
|
|
12824
13618
|
|
|
12825
13619
|
\u3010\u64CD\u4F5C\u786E\u8BA4\u7EA6\u5B9A\u3011
|
|
@@ -12840,8 +13634,8 @@ ${PLAN_MODE_AUTO_ENTER_HINT}
|
|
|
12840
13634
|
});
|
|
12841
13635
|
|
|
12842
13636
|
// ../core/src/serve/chatProcessing.ts
|
|
12843
|
-
import
|
|
12844
|
-
import
|
|
13637
|
+
import path46 from "path";
|
|
13638
|
+
import fs43 from "fs";
|
|
12845
13639
|
var handleUnifiedChat;
|
|
12846
13640
|
var init_chatProcessing = __esm({
|
|
12847
13641
|
"../core/src/serve/chatProcessing.ts"() {
|
|
@@ -12897,17 +13691,17 @@ ${inject}`;
|
|
|
12897
13691
|
if (roots.length > 1) {
|
|
12898
13692
|
let activeReal = getActiveWorkspaceRoot();
|
|
12899
13693
|
try {
|
|
12900
|
-
activeReal =
|
|
13694
|
+
activeReal = fs43.realpathSync(activeReal);
|
|
12901
13695
|
} catch {
|
|
12902
13696
|
}
|
|
12903
|
-
const lines = roots.map((r) => `- ${
|
|
13697
|
+
const lines = roots.map((r) => `- ${path46.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"}`);
|
|
12904
13698
|
sysPrompt = sysPrompt + `
|
|
12905
13699
|
|
|
12906
13700
|
\u3010\u5DE5\u4F5C\u533A\uFF08\u591A\u9879\u76EE\uFF09\u3011
|
|
12907
13701
|
\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>:
|
|
12908
13702
|
${lines.join("\n")}
|
|
12909
|
-
\u2605 \u8DEF\u5F84\u951A\u5B9A\u94C1\u5F8B\uFF1A\u5DE5\u5177\u7F3A\u7701\u53EA\u4F5C\u7528\u4E8E\u9ED8\u8BA4\u6839\uFF08${
|
|
12910
|
-
\u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${
|
|
13703
|
+
\u2605 \u8DEF\u5F84\u951A\u5B9A\u94C1\u5F8B\uFF1A\u5DE5\u5177\u7F3A\u7701\u53EA\u4F5C\u7528\u4E8E\u9ED8\u8BA4\u6839\uFF08${path46.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
|
|
13704
|
+
\u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${path46.basename(activeReal) || activeReal} \u751F\u6548\u3002`;
|
|
12911
13705
|
}
|
|
12912
13706
|
const osName = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
|
|
12913
13707
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -13012,7 +13806,7 @@ ${envLines.join("\n")}`;
|
|
|
13012
13806
|
});
|
|
13013
13807
|
|
|
13014
13808
|
// ../core/src/session/fork.ts
|
|
13015
|
-
import
|
|
13809
|
+
import fs44 from "fs/promises";
|
|
13016
13810
|
var listForkAnchors, derivePrefix, forkSession;
|
|
13017
13811
|
var init_fork = __esm({
|
|
13018
13812
|
"../core/src/session/fork.ts"() {
|
|
@@ -13085,7 +13879,7 @@ var init_fork = __esm({
|
|
|
13085
13879
|
const prefix = derivePrefix(lines, upToLineId);
|
|
13086
13880
|
const newId = createUUID();
|
|
13087
13881
|
await ensureSessionsDir(newId);
|
|
13088
|
-
const rawText = await
|
|
13882
|
+
const rawText = await fs44.readFile(getTranscriptPath(sourceId), "utf-8");
|
|
13089
13883
|
const kept = [];
|
|
13090
13884
|
let good = 0;
|
|
13091
13885
|
for (const s of rawText.split("\n")) {
|
|
@@ -13101,7 +13895,7 @@ var init_fork = __esm({
|
|
|
13101
13895
|
}
|
|
13102
13896
|
let payload = kept.join("\n");
|
|
13103
13897
|
if (payload.length > 0 && !payload.endsWith("\n")) payload += "\n";
|
|
13104
|
-
await
|
|
13898
|
+
await fs44.writeFile(getTranscriptPath(newId), payload, "utf-8");
|
|
13105
13899
|
const srcState = await readStore(sourceId);
|
|
13106
13900
|
const srcRolling = await getRollingState(sourceId);
|
|
13107
13901
|
const legacy = !lines.some(isEventLine);
|
|
@@ -13864,6 +14658,11 @@ ${r.output.trim() || "(\u65E0\u8F93\u51FA)"}`);
|
|
|
13864
14658
|
const picked = await new Promise((resolve) => setPendingSessions({ sessions: sessions2, resolve }));
|
|
13865
14659
|
if (picked) await loadSession(picked);
|
|
13866
14660
|
}, [pushInfo, loadSession]);
|
|
14661
|
+
const newSession = useCallback(async () => {
|
|
14662
|
+
sessionIdRef.current = await getOrCreateSessionId(void 0);
|
|
14663
|
+
clearRows();
|
|
14664
|
+
pushInfo(S.sessionNew(truncateMiddle(sessionIdRef.current, 12)));
|
|
14665
|
+
}, [clearRows, pushInfo]);
|
|
13867
14666
|
const resolveFork = useCallback((anchor) => {
|
|
13868
14667
|
setPendingFork((prev) => {
|
|
13869
14668
|
prev?.resolve(anchor);
|
|
@@ -13971,6 +14770,7 @@ ${r.output.trim() || "(\u65E0\u8F93\u51FA)"}`);
|
|
|
13971
14770
|
loadSession,
|
|
13972
14771
|
openForkPicker,
|
|
13973
14772
|
resolveFork,
|
|
14773
|
+
newSession,
|
|
13974
14774
|
openModelPicker,
|
|
13975
14775
|
resolveModel
|
|
13976
14776
|
};
|
|
@@ -15034,8 +15834,8 @@ var init_TopPanel = __esm({
|
|
|
15034
15834
|
});
|
|
15035
15835
|
|
|
15036
15836
|
// ../core/src/observability/inspect.ts
|
|
15037
|
-
import
|
|
15038
|
-
var CWD, fmt, readTrace, inspectUsage, inspectContext, inspectPermissions, inspectMcp, inspectHooks, inspectDebug;
|
|
15837
|
+
import fs45 from "fs";
|
|
15838
|
+
var CWD, fmt, readTrace, STOP_LABEL, fmtK, inspectUsage, inspectContext, inspectPermissions, inspectMcp, inspectHooks, inspectDebug;
|
|
15039
15839
|
var init_inspect = __esm({
|
|
15040
15840
|
"../core/src/observability/inspect.ts"() {
|
|
15041
15841
|
"use strict";
|
|
@@ -15044,6 +15844,7 @@ var init_inspect = __esm({
|
|
|
15044
15844
|
init_registry();
|
|
15045
15845
|
init_loader();
|
|
15046
15846
|
init_store3();
|
|
15847
|
+
init_usageLog();
|
|
15047
15848
|
init_store();
|
|
15048
15849
|
init_createModel();
|
|
15049
15850
|
CWD = process.cwd();
|
|
@@ -15052,7 +15853,7 @@ var init_inspect = __esm({
|
|
|
15052
15853
|
if (!sessionId) return [];
|
|
15053
15854
|
try {
|
|
15054
15855
|
const p = await getTraceStorePath(sessionId);
|
|
15055
|
-
const text = await
|
|
15856
|
+
const text = await fs45.promises.readFile(p, "utf8");
|
|
15056
15857
|
const out = [];
|
|
15057
15858
|
for (const line of text.split("\n")) {
|
|
15058
15859
|
if (!line.trim()) continue;
|
|
@@ -15066,10 +15867,13 @@ var init_inspect = __esm({
|
|
|
15066
15867
|
return [];
|
|
15067
15868
|
}
|
|
15068
15869
|
};
|
|
15870
|
+
STOP_LABEL = { normal: "\u5B8C\u6210", aborted: "\u4E2D\u6B62", error: "\u9519\u8BEF", repeat: "\u7194\u65AD", limit: "\u8D85\u9650" };
|
|
15871
|
+
fmtK = (n) => n >= 1e4 ? `${(n / 1e3).toFixed(1)}k` : fmt(n);
|
|
15069
15872
|
inspectUsage = async (sessionId) => {
|
|
15070
15873
|
const trace = await readTrace(sessionId);
|
|
15071
15874
|
const responses = trace.filter((t) => t?.eventType === "llm.response" && t?.usage);
|
|
15072
|
-
|
|
15875
|
+
const sessionRuns = (await readUsageRecords()).filter((r) => r.sessionId === sessionId);
|
|
15876
|
+
if (responses.length === 0 && sessionRuns.length === 0) return `\u{1F4CA} Token \u7528\u91CF\uFF1A\u6682\u65E0\u6570\u636E\uFF08\u672C\u4F1A\u8BDD\u5C1A\u65E0 LLM \u54CD\u5E94\u843D\u76D8\uFF09\u3002`;
|
|
15073
15877
|
let prompt = 0, completion = 0, total = 0, cacheHit = 0, cacheMiss = 0;
|
|
15074
15878
|
let mainTotal = 0, subTotal = 0;
|
|
15075
15879
|
for (const r of responses) {
|
|
@@ -15085,13 +15889,35 @@ var init_inspect = __esm({
|
|
|
15085
15889
|
}
|
|
15086
15890
|
const cacheRate = prompt > 0 ? (cacheHit / prompt * 100).toFixed(1) : "0.0";
|
|
15087
15891
|
const rounds = responses.length;
|
|
15088
|
-
|
|
15892
|
+
const lines = [
|
|
15089
15893
|
`\u{1F4CA} Token \u7528\u91CF\uFF08\u672C\u4F1A\u8BDD\uFF0C${rounds} \u6B21 LLM \u54CD\u5E94\uFF09`,
|
|
15090
15894
|
` \u8F93\u5165(prompt): ${fmt(prompt)} | \u8F93\u51FA(completion): ${fmt(completion)} | \u5408\u8BA1: ${fmt(total)}`,
|
|
15091
15895
|
` \u7F13\u5B58\u547D\u4E2D: ${fmt(cacheHit)}\uFF08${cacheRate}%\uFF09 | \u7F13\u5B58\u672A\u547D\u4E2D: ${fmt(cacheMiss)}`,
|
|
15092
|
-
` \u4E3B agent: ${fmt(mainTotal)} | \u5B50 agent(spawn/workflow): ${fmt(subTotal)}
|
|
15093
|
-
|
|
15094
|
-
|
|
15896
|
+
` \u4E3B agent: ${fmt(mainTotal)} | \u5B50 agent(spawn/workflow): ${fmt(subTotal)}`
|
|
15897
|
+
];
|
|
15898
|
+
if (sessionRuns.length > 0) {
|
|
15899
|
+
const ss = summarizeUsage(sessionRuns);
|
|
15900
|
+
const abortedPct = ss.mainRuns > 0 ? Math.round(ss.stopReasons.aborted / ss.mainRuns * 100) : 0;
|
|
15901
|
+
const avgRounds = ss.mainRuns > 0 ? (ss.mainRounds / ss.mainRuns).toFixed(1) : "0";
|
|
15902
|
+
lines.push(` \u258E\u672C\u4F1A\u8BDD ${ss.mainRuns} \u4E2A run\uFF1A${ss.mainRounds} \u8F6E\uFF08\u5747 ${avgRounds} \u8F6E/run\uFF09\xB7 \u4E2D\u6B62 ${ss.stopReasons.aborted}/${ss.mainRuns}\uFF08${abortedPct}%\uFF09`);
|
|
15903
|
+
for (const r of sessionRuns.filter((x) => x.depth === 0).slice(-6)) {
|
|
15904
|
+
const tools = topTools(r.tools, 3).map(([n, c]) => `${n}\xD7${c}`).join(" ") || "\uFF08\u65E0\u5DE5\u5177\u8C03\u7528\uFF09";
|
|
15905
|
+
lines.push(` ${String(r.ts).slice(5, 16).replace("T", " ")} ${r.rounds}\u8F6E ${fmtK(r.totalTokens ?? 0)} tok ${STOP_LABEL[r.stopReason] ?? r.stopReason} ${tools}`);
|
|
15906
|
+
}
|
|
15907
|
+
}
|
|
15908
|
+
const week = summarizeUsage(await readUsageRecords(7));
|
|
15909
|
+
if (week.runs > 0) {
|
|
15910
|
+
const weekHit = week.promptTokens > 0 ? (week.cachedTokens / week.promptTokens * 100).toFixed(1) : "0.0";
|
|
15911
|
+
const weekAbort = week.mainRuns > 0 ? Math.round(week.stopReasons.aborted / week.mainRuns * 100) : 0;
|
|
15912
|
+
const weekAvg = week.mainRuns > 0 ? (week.mainRounds / week.mainRuns).toFixed(1) : "0";
|
|
15913
|
+
const tools = topTools(week.tools, 4).map(([n, c]) => `${n}\xD7${c}`).join("\u3001");
|
|
15914
|
+
lines.push(
|
|
15915
|
+
` \u258E\u8FD1 7 \u5929\uFF08\u4F7F\u7528\u65E5\u5FD7 \xB7 \u5168\u9879\u76EE\uFF09\uFF1A${week.mainRuns} runs \xB7 ${week.mainRounds} \u8F6E\uFF08\u5747 ${weekAvg} \u8F6E/run\uFF09\xB7 \u4E2D\u6B62 ${weekAbort}% \xB7 ${fmtK(week.totalTokens)} tok\uFF08\u7F13\u5B58\u547D\u4E2D ${weekHit}%\uFF09`,
|
|
15916
|
+
` \u5E38\u7528\u5DE5\u5177: ${tools || "\uFF08\u65E0\uFF09"}`
|
|
15917
|
+
);
|
|
15918
|
+
}
|
|
15919
|
+
lines.push(` \u63D0\u793A\uFF1A\u5E76\u884C workflow \u4F1A\u653E\u5927\u5B50 agent \u7528\u91CF\uFF1B\u7F13\u5B58\u547D\u4E2D\u7387\u8D8A\u9AD8\uFF0C\u8F93\u5165\u6210\u672C\u8D8A\u4F4E\u3002`);
|
|
15920
|
+
return lines.join("\n");
|
|
15095
15921
|
};
|
|
15096
15922
|
inspectContext = async (sessionId) => {
|
|
15097
15923
|
const trace = await readTrace(sessionId);
|
|
@@ -15339,6 +16165,8 @@ var init_App = __esm({
|
|
|
15339
16165
|
return S.cmdLang;
|
|
15340
16166
|
case "output-style":
|
|
15341
16167
|
return S.cmdOutputStyle;
|
|
16168
|
+
case "new":
|
|
16169
|
+
return S.cmdNew;
|
|
15342
16170
|
case "sessions":
|
|
15343
16171
|
return S.cmdSessions;
|
|
15344
16172
|
case "fork":
|
|
@@ -15421,6 +16249,13 @@ var init_App = __esm({
|
|
|
15421
16249
|
case "/clear":
|
|
15422
16250
|
state.clearRows();
|
|
15423
16251
|
return true;
|
|
16252
|
+
case "/new":
|
|
16253
|
+
if (state.busy) {
|
|
16254
|
+
state.pushInfo(S.sessionNewBusy);
|
|
16255
|
+
return true;
|
|
16256
|
+
}
|
|
16257
|
+
void state.newSession();
|
|
16258
|
+
return true;
|
|
15424
16259
|
case "/sessions":
|
|
15425
16260
|
void state.openSessionPicker();
|
|
15426
16261
|
return true;
|
|
@@ -15863,7 +16698,7 @@ init_updateCheck();
|
|
|
15863
16698
|
init_trust();
|
|
15864
16699
|
import { render } from "ink";
|
|
15865
16700
|
import os5 from "os";
|
|
15866
|
-
import
|
|
16701
|
+
import path47 from "path";
|
|
15867
16702
|
import { emitKeypressEvents } from "node:readline";
|
|
15868
16703
|
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
15869
16704
|
var parseArgs = (argv) => {
|
|
@@ -15996,7 +16831,7 @@ var main = async () => {
|
|
|
15996
16831
|
process.stdout.write("\x1B[2J\x1B[3J\x1B[1;1H");
|
|
15997
16832
|
const cwdIsHome = () => {
|
|
15998
16833
|
try {
|
|
15999
|
-
return
|
|
16834
|
+
return path47.resolve(cwd).toLowerCase() === path47.resolve(os5.homedir()).toLowerCase();
|
|
16000
16835
|
} catch {
|
|
16001
16836
|
return false;
|
|
16002
16837
|
}
|