deepseeker-code 1.0.47 → 1.0.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/cli.mjs +316 -98
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -139,6 +139,8 @@ DeepSeeker-Code 支持三种配置来源,优先级 **环境变量 > config.jso
|
|
|
139
139
|
| `DEEP_SEEK_REASONING_EFFORT` | 推理强度,仅 `high` / `max` | `high` |
|
|
140
140
|
| `DEEP_SEEK_THINKING` | 深度思考开关,设 `0` 关闭 | 开 |
|
|
141
141
|
| `DEEP_SEEK_STREAM_IDLE_TIMEOUT_MS` | 流式 idle 超时(ms) | `120000` |
|
|
142
|
+
| `DEEP_SEEK_VISION` | 视觉多模态开关,设 `1`/`true` 开启(开启后聊天支持贴图附件) | 关 |
|
|
143
|
+
| `DEEP_SEEK_IMAGE_TOKENS` | 单张图片折算 token 数(下限 100) | `1500` |
|
|
142
144
|
|
|
143
145
|
#### 产品行为
|
|
144
146
|
|
|
@@ -148,6 +150,7 @@ DeepSeeker-Code 支持三种配置来源,优先级 **环境变量 > config.jso
|
|
|
148
150
|
| `DEEP_SEEK_PARALLEL_SAFE_TOOLS` | 设 `0` 关闭同轮只读工具并发(默认开) | 开(并发) |
|
|
149
151
|
| `DEEP_SEEK_WORKFLOW_CONCURRENCY` | run_workflow 子 agent 并发上限 | `4` |
|
|
150
152
|
| `DEEP_SEEK_WORKFLOW_MAX_STEPS` | run_workflow 单次步数上限 | `8` |
|
|
153
|
+
| `RUN_COMMAND_AUTO_BG_MS` | run_command 前台超时自动转后台阈值(ms);到期进程收编进后台注册表返回 task_id,不杀进程 | `120000` |
|
|
151
154
|
| `SEARCH_PROVIDER` | 搜索后端 `tavily` / `bing` / `ddg` | 自动(有 Tavily key 用 Tavily,否则 Bing) |
|
|
152
155
|
| `TAVILY_API_KEY` | Tavily 搜索密钥 | — |
|
|
153
156
|
| `WEB_FETCH_ALLOW_PRIVATE` | 设 `1` 放行 web_fetch 访问内网/回环(云元数据端点仍硬拦) | 关(SSRF 安全) |
|
package/dist/cli.mjs
CHANGED
|
@@ -423,6 +423,12 @@ var init_config = __esm({
|
|
|
423
423
|
/** 后台工具(isSync:false)兜底超时(ms):超时强制收尾释放互斥锁,防 generator 卡死导致锁永久泄漏。
|
|
424
424
|
* abort 仍是主取消通道,此值仅作最后防线;默认 30min 远超合理后台任务时长,正常任务不受影响。 */
|
|
425
425
|
MAX_BACKGROUND_TOOL_MS: 30 * 60 * 1e3,
|
|
426
|
+
/** ★ run_command 运行时看门狗(自动转后台阈值 ms):前台流式超过此时长仍未退出 → 进程自动收编进
|
|
427
|
+
* 后台任务注册表并返回 task_id(get_background_output / stop_background_task 接管),不再阻塞主循环、
|
|
428
|
+
* 也不杀进程。与内部空闲看门狗(RUN_COMMAND_IDLE_TIMEOUT_MS,默认 60s)共用降级路径。
|
|
429
|
+
* env RUN_COMMAND_AUTO_BG_MS 覆盖。勿把 IDLE 调到高于 DEEP_SEEK_STREAM_IDLE_TIMEOUT_MS
|
|
430
|
+
* (空闲分支到期会产出降级消息喂流,不会饿死 collectToolResult 的 idle 熔断)。 */
|
|
431
|
+
runCommandAutoBgMs: Number(process.env.RUN_COMMAND_AUTO_BG_MS) || 12e4,
|
|
426
432
|
userWorkspaceDir: (() => {
|
|
427
433
|
let cwd = process.cwd().replace(/\\/g, "/");
|
|
428
434
|
if (/^[a-z]:/i.test(cwd)) {
|
|
@@ -506,6 +512,7 @@ var init_config = __esm({
|
|
|
506
512
|
parallelSafeTools: "DEEP_SEEK_PARALLEL_SAFE_TOOLS",
|
|
507
513
|
workflowConcurrency: "DEEP_SEEK_WORKFLOW_CONCURRENCY",
|
|
508
514
|
workflowMaxSteps: "DEEP_SEEK_WORKFLOW_MAX_STEPS",
|
|
515
|
+
runCommandAutoBgMs: "RUN_COMMAND_AUTO_BG_MS",
|
|
509
516
|
planEnforcement: "DEEP_SEEK_PLAN_ENFORCEMENT",
|
|
510
517
|
mcpExposeMode: "DEEP_SEEK_MCP_EXPOSE_MODE",
|
|
511
518
|
transcriptEvents: "DEEP_SEEK_TRANSCRIPT_EVENTS",
|
|
@@ -973,11 +980,96 @@ var init_deepseek = __esm({
|
|
|
973
980
|
}
|
|
974
981
|
});
|
|
975
982
|
|
|
983
|
+
// ../core/src/session/contentParts.ts
|
|
984
|
+
var MAX_IMAGE_BYTES, msgText, imageUrlsOf, hasImagePart, isVisionEnabled, estimateImageTokens, toWireUserContent, replaceImageParts, collapseToText, degradeImagesForAux;
|
|
985
|
+
var init_contentParts = __esm({
|
|
986
|
+
"../core/src/session/contentParts.ts"() {
|
|
987
|
+
"use strict";
|
|
988
|
+
MAX_IMAGE_BYTES = 8 * 1024 * 1024;
|
|
989
|
+
msgText = (content) => {
|
|
990
|
+
if (typeof content === "string") return content;
|
|
991
|
+
if (Array.isArray(content)) {
|
|
992
|
+
return content.filter((p) => typeof p?.text === "string").map((p) => p.text).join(" ");
|
|
993
|
+
}
|
|
994
|
+
return "";
|
|
995
|
+
};
|
|
996
|
+
imageUrlsOf = (content) => {
|
|
997
|
+
if (!Array.isArray(content)) return [];
|
|
998
|
+
return content.filter((p) => p?.type === "image_url" && typeof p?.image_url?.url === "string").map((p) => p.image_url.url);
|
|
999
|
+
};
|
|
1000
|
+
hasImagePart = (content) => imageUrlsOf(content).length > 0;
|
|
1001
|
+
isVisionEnabled = () => {
|
|
1002
|
+
const v = process.env.DEEP_SEEK_VISION;
|
|
1003
|
+
return v === "1" || v === "true";
|
|
1004
|
+
};
|
|
1005
|
+
estimateImageTokens = () => {
|
|
1006
|
+
const n = Number(process.env.DEEP_SEEK_IMAGE_TOKENS);
|
|
1007
|
+
return Number.isFinite(n) && n >= 100 ? Math.floor(n) : 1500;
|
|
1008
|
+
};
|
|
1009
|
+
toWireUserContent = (text, attachments) => {
|
|
1010
|
+
if (!Array.isArray(attachments) || attachments.length === 0) return text;
|
|
1011
|
+
const accepted = [];
|
|
1012
|
+
const skipped = [];
|
|
1013
|
+
for (const a of attachments) {
|
|
1014
|
+
const name = typeof a?.name === "string" && a.name.trim() ? a.name : "image";
|
|
1015
|
+
const b64 = typeof a?.base64 === "string" ? a.base64 : "";
|
|
1016
|
+
if (!b64) {
|
|
1017
|
+
skipped.push(`\u{1F5BC} \u56FE\u7247 ${name} \u5DF2\u5FFD\u7565\uFF1A\u7A7A\u6570\u636E`);
|
|
1018
|
+
continue;
|
|
1019
|
+
}
|
|
1020
|
+
if (!/^image\//.test(a?.mime || "")) {
|
|
1021
|
+
skipped.push(`\u{1F5BC} \u56FE\u7247 ${name} \u5DF2\u5FFD\u7565\uFF1A\u975E\u56FE\u7247\u7C7B\u578B`);
|
|
1022
|
+
continue;
|
|
1023
|
+
}
|
|
1024
|
+
if (b64.length * 3 / 4 > MAX_IMAGE_BYTES) {
|
|
1025
|
+
skipped.push(`\u{1F5BC} \u56FE\u7247 ${name} \u5DF2\u5FFD\u7565\uFF1A\u8D85\u8FC7 ${Math.round(MAX_IMAGE_BYTES / 1024 / 1024)}MB \u4E0A\u9650`);
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
accepted.push({ name, url: `data:${a.mime};base64,${b64}` });
|
|
1029
|
+
}
|
|
1030
|
+
const labels = accepted.map((p) => `\u{1F5BC} [\u56FE\u7247: ${p.name}]`);
|
|
1031
|
+
const footer = [...skipped, ...labels];
|
|
1032
|
+
const finalText = footer.length ? `${text}
|
|
1033
|
+
|
|
1034
|
+
${footer.join("\n")}` : text;
|
|
1035
|
+
if (accepted.length === 0) return finalText;
|
|
1036
|
+
const parts = [
|
|
1037
|
+
{ type: "text", text: finalText },
|
|
1038
|
+
...accepted.map((p) => ({ type: "image_url", image_url: { url: p.url } }))
|
|
1039
|
+
];
|
|
1040
|
+
return parts;
|
|
1041
|
+
};
|
|
1042
|
+
replaceImageParts = (m, note) => {
|
|
1043
|
+
if (!m || !Array.isArray(m.content)) return m;
|
|
1044
|
+
let touched = false;
|
|
1045
|
+
const parts = m.content.map((p) => {
|
|
1046
|
+
if (p?.type === "image_url") {
|
|
1047
|
+
touched = true;
|
|
1048
|
+
return { type: "text", text: note };
|
|
1049
|
+
}
|
|
1050
|
+
return p;
|
|
1051
|
+
});
|
|
1052
|
+
if (!touched) return m;
|
|
1053
|
+
return { ...m, content: parts };
|
|
1054
|
+
};
|
|
1055
|
+
collapseToText = (m, imageNote) => {
|
|
1056
|
+
if (!m || !Array.isArray(m.content)) return m;
|
|
1057
|
+
const text = msgText(m.content);
|
|
1058
|
+
if (imageNote && hasImagePart(m.content)) {
|
|
1059
|
+
return { ...m, content: text ? `${text} ${imageNote}` : imageNote };
|
|
1060
|
+
}
|
|
1061
|
+
return { ...m, content: text };
|
|
1062
|
+
};
|
|
1063
|
+
degradeImagesForAux = (m) => collapseToText(m, "[\u56FE\u7247\u5DF2\u5F52\u6863]");
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
|
|
976
1067
|
// ../core/src/llm/providers/replay/index.ts
|
|
977
1068
|
var createReplayProvider;
|
|
978
1069
|
var init_replay = __esm({
|
|
979
1070
|
"../core/src/llm/providers/replay/index.ts"() {
|
|
980
1071
|
"use strict";
|
|
1072
|
+
init_contentParts();
|
|
981
1073
|
createReplayProvider = (script) => {
|
|
982
1074
|
const turns = Array.isArray(script.turns) ? script.turns : [];
|
|
983
1075
|
let cursor = 0;
|
|
@@ -1095,6 +1187,7 @@ var isCjkCodePoint, estimateTextTokens, estimateTokens, cleanMsg, groupUnits, sp
|
|
|
1095
1187
|
var init_contextCore = __esm({
|
|
1096
1188
|
"../core/src/session/contextCore.ts"() {
|
|
1097
1189
|
"use strict";
|
|
1190
|
+
init_contentParts();
|
|
1098
1191
|
isCjkCodePoint = (c) => c >= 19968 && c <= 40959 || // CJK 统一表意文字(基本区)
|
|
1099
1192
|
c >= 13312 && c <= 19903 || // CJK 扩展 A
|
|
1100
1193
|
c >= 12352 && c <= 12543 || // 日文假名(平假名 + 片假名)
|
|
@@ -1117,8 +1210,14 @@ var init_contextCore = __esm({
|
|
|
1117
1210
|
estimateTokens = (messagesArr) => {
|
|
1118
1211
|
return messagesArr.reduce((total, m) => {
|
|
1119
1212
|
let pureText = "";
|
|
1213
|
+
let imageCount = 0;
|
|
1120
1214
|
if (m.content) {
|
|
1121
|
-
|
|
1215
|
+
if (typeof m.content === "string") {
|
|
1216
|
+
pureText += m.content;
|
|
1217
|
+
} else if (Array.isArray(m.content)) {
|
|
1218
|
+
pureText += msgText(m.content);
|
|
1219
|
+
imageCount += imageUrlsOf(m.content).length;
|
|
1220
|
+
}
|
|
1122
1221
|
}
|
|
1123
1222
|
if (m.tool_calls && Array.isArray(m.tool_calls)) {
|
|
1124
1223
|
for (const call of m.tool_calls) {
|
|
@@ -1134,7 +1233,7 @@ var init_contextCore = __esm({
|
|
|
1134
1233
|
}
|
|
1135
1234
|
}
|
|
1136
1235
|
const isStructured = m.role === "tool" || Array.isArray(m.tool_calls) && m.tool_calls.length > 0;
|
|
1137
|
-
const tokens = estimateTextTokens(pureText, isStructured ? 4 : 4.8) + 4;
|
|
1236
|
+
const tokens = estimateTextTokens(pureText, isStructured ? 4 : 4.8) + imageCount * estimateImageTokens() + 4;
|
|
1138
1237
|
return total + (isNaN(tokens) ? 0 : tokens);
|
|
1139
1238
|
}, 0);
|
|
1140
1239
|
};
|
|
@@ -1242,6 +1341,7 @@ var init_store = __esm({
|
|
|
1242
1341
|
"use strict";
|
|
1243
1342
|
init_config();
|
|
1244
1343
|
init_common();
|
|
1344
|
+
init_contentParts();
|
|
1245
1345
|
getSessionsDirPath = (mainSessionId) => {
|
|
1246
1346
|
assertSafeSessionId(mainSessionId);
|
|
1247
1347
|
const fileName = getFileName(mainSessionId);
|
|
@@ -1406,8 +1506,8 @@ var init_store = __esm({
|
|
|
1406
1506
|
}
|
|
1407
1507
|
if (typeof msg?.dscEvent === "string") continue;
|
|
1408
1508
|
messageCount++;
|
|
1409
|
-
if (!preview && msg?.role === "user" &&
|
|
1410
|
-
const t = msg.content.replace(/\s+/g, " ").trim();
|
|
1509
|
+
if (!preview && msg?.role === "user" && msg.content != null) {
|
|
1510
|
+
const t = (msgText(msg.content) || "\uFF08\u8BE5\u6761\u6D88\u606F\u5E26\u56FE\u7247\u9644\u4EF6\uFF09").replace(/\s+/g, " ").trim();
|
|
1411
1511
|
if (t.includes("\uFFFD")) {
|
|
1412
1512
|
const cleaned = t.replace(/\uFFFD+/g, "").trim();
|
|
1413
1513
|
preview = cleaned ? `\uFF08\u542B\u4E71\u7801\u7247\u6BB5\uFF09${cleaned}` : "\uFF08\u8BE5\u6761\u6D88\u606F\u5185\u5BB9\u4E3A\u4E71\u7801\uFF0C\u65E0\u6CD5\u6B63\u5E38\u663E\u793A\uFF09";
|
|
@@ -1838,6 +1938,7 @@ var init_truncate = __esm({
|
|
|
1838
1938
|
init_config();
|
|
1839
1939
|
init_model();
|
|
1840
1940
|
init_contextCore();
|
|
1941
|
+
init_contentParts();
|
|
1841
1942
|
init_store();
|
|
1842
1943
|
init_transcript();
|
|
1843
1944
|
init_hooks();
|
|
@@ -1904,7 +2005,8 @@ ${tail}`;
|
|
|
1904
2005
|
};
|
|
1905
2006
|
compactBatch = async (batch, signal) => {
|
|
1906
2007
|
const resp = await chatWithModelWithSummary(
|
|
1907
|
-
|
|
2008
|
+
// ★ 辅助模型是 text-only:送前把 image part 降级为占位符——base64 绝不能进摘要批(烧钱且无意义)
|
|
2009
|
+
[...batch.map(degradeImagesForAux), { role: "user", content: '\u7528\u4E00\u884C\u8BDD\u6982\u62EC\u4EE5\u4E0A\u5BF9\u8BDD\u4E0E\u5DE5\u5177\u8C03\u7528\uFF1A\u4EFB\u52A1\u76EE\u6807\u3001\u5173\u952E\u51B3\u7B56\u3001\u52A8\u8FC7\u7684\u6587\u4EF6\u3001\u5F53\u524D\u8FDB\u5EA6\u3002\u5FC5\u987B\u539F\u6837\u4FDD\u7559\u5173\u952E\u5B9E\u4F53\u540D\uFF08\u6587\u4EF6\u8DEF\u5F84\u3001\u51FD\u6570/\u7C7B\u540D\u3001\u62A5\u9519\u5173\u952E\u8BCD\uFF09\u4EE5\u4FBF\u540E\u7EED\u68C0\u7D22\u3002\u5BF9\u8BB0\u4E0D\u51C6\u7684\u7EC6\u8282\u4E0D\u8981\u81C6\u6D4B\uFF0C\u6807\u6CE8"(\u7EC6\u8282\u5DF2\u5F52\u6863)"\u5373\u53EF\u3002\u4E0D\u8981\u8C03\u7528\u5DE5\u5177\u3002' }],
|
|
1908
2010
|
[],
|
|
1909
2011
|
{ signal }
|
|
1910
2012
|
);
|
|
@@ -1915,7 +2017,7 @@ ${tail}`;
|
|
|
1915
2017
|
extractArchiveEntities = (batch) => {
|
|
1916
2018
|
let text = "";
|
|
1917
2019
|
for (const m of batch) {
|
|
1918
|
-
if (m.content) text += ` ${
|
|
2020
|
+
if (m.content) text += ` ${msgText(m.content)}`;
|
|
1919
2021
|
const calls = m.tool_calls;
|
|
1920
2022
|
if (Array.isArray(calls)) for (const c of calls) text += ` ${c?.function?.name ?? ""} ${c?.function?.arguments ?? ""}`;
|
|
1921
2023
|
}
|
|
@@ -2702,7 +2804,7 @@ async function killBackgroundTasksUnder(dirPath) {
|
|
|
2702
2804
|
}
|
|
2703
2805
|
return killed;
|
|
2704
2806
|
}
|
|
2705
|
-
var _winShellCache, resolveWinShell, MAX_BUFFER_CHARS, registry, backgroundTools, killAllBackgroundTasks;
|
|
2807
|
+
var _winShellCache, resolveWinShell, MAX_BUFFER_CHARS, registry, createBgTask, attachTaskLifecycle, adoptRunningProcess, backgroundTools, killAllBackgroundTasks;
|
|
2706
2808
|
var init_background = __esm({
|
|
2707
2809
|
"../core/src/tool/registry/background.ts"() {
|
|
2708
2810
|
"use strict";
|
|
@@ -2743,12 +2845,110 @@ var init_background = __esm({
|
|
|
2743
2845
|
};
|
|
2744
2846
|
MAX_BUFFER_CHARS = 1e5;
|
|
2745
2847
|
registry = /* @__PURE__ */ new Map();
|
|
2848
|
+
createBgTask = (proc, command, cwd, sessionId) => {
|
|
2849
|
+
const task = {
|
|
2850
|
+
taskId: createUUID(),
|
|
2851
|
+
command,
|
|
2852
|
+
cwd,
|
|
2853
|
+
sessionId: sessionId ?? "",
|
|
2854
|
+
proc,
|
|
2855
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2856
|
+
status: "running",
|
|
2857
|
+
exitCode: null,
|
|
2858
|
+
outputBuffer: ""
|
|
2859
|
+
};
|
|
2860
|
+
registry.set(task.taskId, task);
|
|
2861
|
+
return task;
|
|
2862
|
+
};
|
|
2863
|
+
attachTaskLifecycle = (task, proc, opts = {}) => {
|
|
2864
|
+
return new Promise((resolve) => {
|
|
2865
|
+
let finished = false;
|
|
2866
|
+
const finish = (apply) => {
|
|
2867
|
+
if (finished) return;
|
|
2868
|
+
finished = true;
|
|
2869
|
+
apply();
|
|
2870
|
+
setTimeout(() => registry.delete(task.taskId), 6e4);
|
|
2871
|
+
opts.signal?.removeEventListener("abort", onAbort);
|
|
2872
|
+
try {
|
|
2873
|
+
proc?.stdout?.removeAllListeners?.();
|
|
2874
|
+
} catch {
|
|
2875
|
+
}
|
|
2876
|
+
try {
|
|
2877
|
+
proc?.stderr?.removeAllListeners?.();
|
|
2878
|
+
} catch {
|
|
2879
|
+
}
|
|
2880
|
+
try {
|
|
2881
|
+
proc?.removeAllListeners?.();
|
|
2882
|
+
} catch {
|
|
2883
|
+
}
|
|
2884
|
+
resolve();
|
|
2885
|
+
};
|
|
2886
|
+
const onAbort = () => {
|
|
2887
|
+
killTree(proc).finally(() => {
|
|
2888
|
+
finish(() => {
|
|
2889
|
+
if (task.status === "running") task.status = "killed";
|
|
2890
|
+
task.exitCode = task.exitCode ?? -1;
|
|
2891
|
+
appendOutput(task, `
|
|
2892
|
+
[\u7528\u6237\u4E2D\u6B62\uFF0C\u8FDB\u7A0B\u6811\u5DF2\u7EC8\u6B62]`);
|
|
2893
|
+
});
|
|
2894
|
+
});
|
|
2895
|
+
};
|
|
2896
|
+
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
2897
|
+
proc.on("close", (code) => {
|
|
2898
|
+
finish(() => {
|
|
2899
|
+
if (opts.codec) {
|
|
2900
|
+
try {
|
|
2901
|
+
appendOutput(task, opts.codec.flush());
|
|
2902
|
+
} catch {
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
task.status = task.status === "killed" ? "killed" : "exited";
|
|
2906
|
+
task.exitCode ??= code ?? 0;
|
|
2907
|
+
appendOutput(task, `
|
|
2908
|
+
[\u8FDB\u7A0B\u7ED3\u675F exit=${code}]`);
|
|
2909
|
+
});
|
|
2910
|
+
});
|
|
2911
|
+
proc.on("error", (e) => {
|
|
2912
|
+
finish(() => {
|
|
2913
|
+
if (task.status === "running") task.status = "exited";
|
|
2914
|
+
task.exitCode = task.exitCode ?? -1;
|
|
2915
|
+
appendOutput(task, `
|
|
2916
|
+
[spawn error: ${e.message}]`);
|
|
2917
|
+
});
|
|
2918
|
+
});
|
|
2919
|
+
});
|
|
2920
|
+
};
|
|
2921
|
+
adoptRunningProcess = (proc, meta, seedOutput, codec) => {
|
|
2922
|
+
const task = createBgTask(proc, meta.command, meta.cwd, meta.sessionId);
|
|
2923
|
+
if (seedOutput) appendOutput(task, seedOutput);
|
|
2924
|
+
try {
|
|
2925
|
+
proc?.stdout?.removeAllListeners?.("data");
|
|
2926
|
+
} catch {
|
|
2927
|
+
}
|
|
2928
|
+
try {
|
|
2929
|
+
proc?.stderr?.removeAllListeners?.("data");
|
|
2930
|
+
} catch {
|
|
2931
|
+
}
|
|
2932
|
+
try {
|
|
2933
|
+
proc?.removeAllListeners?.("close");
|
|
2934
|
+
} catch {
|
|
2935
|
+
}
|
|
2936
|
+
try {
|
|
2937
|
+
proc?.removeAllListeners?.("error");
|
|
2938
|
+
} catch {
|
|
2939
|
+
}
|
|
2940
|
+
const onData = (d) => appendOutput(task, codec.decode(d));
|
|
2941
|
+
proc.stdout?.on("data", onData);
|
|
2942
|
+
proc.stderr?.on("data", onData);
|
|
2943
|
+
void attachTaskLifecycle(task, proc, { signal: meta.signal, codec });
|
|
2944
|
+
return task.taskId;
|
|
2945
|
+
};
|
|
2746
2946
|
backgroundTools = [
|
|
2747
2947
|
{
|
|
2748
2948
|
type: "function",
|
|
2749
2949
|
function: {
|
|
2750
2950
|
name: "run_in_background",
|
|
2751
|
-
description: "\u5728\u540E\u53F0\u542F\u52A8\u4E00\u4E2A\u957F\
|
|
2951
|
+
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",
|
|
2752
2952
|
parameters: {
|
|
2753
2953
|
type: "object",
|
|
2754
2954
|
properties: {
|
|
@@ -2798,75 +2998,25 @@ var init_background = __esm({
|
|
|
2798
2998
|
yield `\u274C [\u540E\u53F0\u542F\u52A8\u5931\u8D25]\uFF1A${e.message}`;
|
|
2799
2999
|
return;
|
|
2800
3000
|
}
|
|
2801
|
-
const
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
exitCode: null,
|
|
2811
|
-
outputBuffer: ""
|
|
3001
|
+
const codec = {
|
|
3002
|
+
decode: decodeChunk,
|
|
3003
|
+
// flush:close 时收尾两个 stream 解码器的尾字节(GBK/UTF-8 残留,不 flush 丢最后一个字符)
|
|
3004
|
+
flush: () => {
|
|
3005
|
+
let s = "";
|
|
3006
|
+
if (decoder) s += decoder.decode();
|
|
3007
|
+
s += pendingUtf8.decode();
|
|
3008
|
+
return s;
|
|
3009
|
+
}
|
|
2812
3010
|
};
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
proc.
|
|
3011
|
+
const task = createBgTask(proc, args.command, cwd, ctx?.sessionId);
|
|
3012
|
+
const taskId = task.taskId;
|
|
3013
|
+
proc.stdout?.on("data", (d) => appendOutput(task, codec.decode(d)));
|
|
3014
|
+
proc.stderr?.on("data", (d) => appendOutput(task, codec.decode(d)));
|
|
2816
3015
|
yield `\u2705 [\u540E\u53F0\u4EFB\u52A1\u5DF2\u542F\u52A8]
|
|
2817
3016
|
task_id: ${taskId}
|
|
2818
3017
|
\u547D\u4EE4: ${args.command}
|
|
2819
3018
|
\u7528 get_background_output(task_id="${taskId}") \u67E5\u65E5\u5FD7\uFF0Cstop_background_task(task_id="${taskId}") \u7EC8\u6B62\u3002`;
|
|
2820
|
-
await
|
|
2821
|
-
let finished = false;
|
|
2822
|
-
const finish = (apply) => {
|
|
2823
|
-
if (finished) return;
|
|
2824
|
-
finished = true;
|
|
2825
|
-
apply();
|
|
2826
|
-
setTimeout(() => registry.delete(taskId), 6e4);
|
|
2827
|
-
ctx?.abortSignal?.removeEventListener("abort", onAbort);
|
|
2828
|
-
try {
|
|
2829
|
-
proc?.stdout?.removeAllListeners?.();
|
|
2830
|
-
} catch {
|
|
2831
|
-
}
|
|
2832
|
-
try {
|
|
2833
|
-
proc?.stderr?.removeAllListeners?.();
|
|
2834
|
-
} catch {
|
|
2835
|
-
}
|
|
2836
|
-
try {
|
|
2837
|
-
proc?.removeAllListeners?.();
|
|
2838
|
-
} catch {
|
|
2839
|
-
}
|
|
2840
|
-
resolve();
|
|
2841
|
-
};
|
|
2842
|
-
const onAbort = () => {
|
|
2843
|
-
killTree(proc).finally(() => {
|
|
2844
|
-
finish(() => {
|
|
2845
|
-
if (task.status === "running") task.status = "killed";
|
|
2846
|
-
task.exitCode = task.exitCode ?? -1;
|
|
2847
|
-
appendOutput(task, `
|
|
2848
|
-
[\u7528\u6237\u4E2D\u6B62\uFF0C\u8FDB\u7A0B\u6811\u5DF2\u7EC8\u6B62]`);
|
|
2849
|
-
});
|
|
2850
|
-
});
|
|
2851
|
-
};
|
|
2852
|
-
ctx?.abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
2853
|
-
proc.on("close", (code) => {
|
|
2854
|
-
finish(() => {
|
|
2855
|
-
task.status = task.status === "killed" ? "killed" : "exited";
|
|
2856
|
-
task.exitCode ??= code ?? 0;
|
|
2857
|
-
appendOutput(task, `
|
|
2858
|
-
[\u8FDB\u7A0B\u7ED3\u675F exit=${code}]`);
|
|
2859
|
-
});
|
|
2860
|
-
});
|
|
2861
|
-
proc.on("error", (e) => {
|
|
2862
|
-
finish(() => {
|
|
2863
|
-
if (task.status === "running") task.status = "exited";
|
|
2864
|
-
task.exitCode = task.exitCode ?? -1;
|
|
2865
|
-
appendOutput(task, `
|
|
2866
|
-
[spawn error: ${e.message}]`);
|
|
2867
|
-
});
|
|
2868
|
-
});
|
|
2869
|
-
});
|
|
3019
|
+
await attachTaskLifecycle(task, proc, { signal: ctx?.abortSignal, codec });
|
|
2870
3020
|
}
|
|
2871
3021
|
}
|
|
2872
3022
|
},
|
|
@@ -2878,7 +3028,7 @@ task_id: ${taskId}
|
|
|
2878
3028
|
parameters: {
|
|
2879
3029
|
type: "object",
|
|
2880
3030
|
properties: {
|
|
2881
|
-
task_id: { type: "string", description: "
|
|
3031
|
+
task_id: { type: "string", description: "\u540E\u53F0\u4EFB\u52A1\u7684 task_id\uFF08run_in_background \u8FD4\u56DE\uFF0C\u6216 run_command \u8D85\u65F6\u81EA\u52A8\u8F6C\u540E\u53F0\u8FD4\u56DE\uFF09" },
|
|
2882
3032
|
tail_lines: { type: "number", description: "\u53EA\u8FD4\u56DE\u6700\u540E N \u884C\u65E5\u5FD7\uFF08\u9ED8\u8BA4 50\uFF0C\u907F\u514D\u4E00\u6B21\u704C\u5165\u8FC7\u591A\uFF09" },
|
|
2883
3033
|
wait_seconds: { type: "number", description: "\u963B\u585E\u7B49\u5F85\u4EFB\u52A1\u9000\u51FA\uFF08\u6216\u5230\u8FBE\u6B64\u65F6\u957F\uFF09\u540E\u518D\u8FD4\u56DE\uFF0C\u4E0A\u9650 120 \u79D2\uFF1B\u4EFB\u52A1\u5DF2\u5728\u8DD1\u4E14\u9700\u8981\u7B49\u7ED3\u679C\u65F6\u4F7F\u7528\uFF0C\u4E0D\u9700\u8981\u7B49\u5C31\u7701\u7565" }
|
|
2884
3034
|
},
|
|
@@ -2919,7 +3069,7 @@ task_id: ${taskId}
|
|
|
2919
3069
|
parameters: {
|
|
2920
3070
|
type: "object",
|
|
2921
3071
|
properties: {
|
|
2922
|
-
task_id: { type: "string", description: "
|
|
3072
|
+
task_id: { type: "string", description: "\u540E\u53F0\u4EFB\u52A1\u7684 task_id\uFF08run_in_background \u8FD4\u56DE\uFF0C\u6216 run_command \u8D85\u65F6\u81EA\u52A8\u8F6C\u540E\u53F0\u8FD4\u56DE\uFF09" }
|
|
2923
3073
|
},
|
|
2924
3074
|
required: ["task_id"]
|
|
2925
3075
|
},
|
|
@@ -5970,6 +6120,7 @@ var init_command = __esm({
|
|
|
5970
6120
|
init_type();
|
|
5971
6121
|
init_guard();
|
|
5972
6122
|
init_background();
|
|
6123
|
+
init_config();
|
|
5973
6124
|
EXIT_SENTINEL = (code) => `
|
|
5974
6125
|
\u27E6DSC_EXIT:${code}\u27E7`;
|
|
5975
6126
|
EXIT_SENTINEL_RE = /⟦DSC_EXIT:(-?\d+)⟧/g;
|
|
@@ -5979,7 +6130,7 @@ var init_command = __esm({
|
|
|
5979
6130
|
type: "function",
|
|
5980
6131
|
function: {
|
|
5981
6132
|
name: "run_command",
|
|
5982
|
-
description: "\u5728\u5DE5\u4F5C\u533A\u6267\u884C shell \u547D\u4EE4\uFF08\
|
|
6133
|
+
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",
|
|
5983
6134
|
parameters: {
|
|
5984
6135
|
type: "object",
|
|
5985
6136
|
properties: {
|
|
@@ -6024,6 +6175,10 @@ ${tail}`,
|
|
|
6024
6175
|
const cwd = args.cwd ? resolveSafePath(args.cwd) : getActiveWorkspaceRoot();
|
|
6025
6176
|
const maxChars = RUN_COMMAND_MAX_CHARS;
|
|
6026
6177
|
let totalYieldedChars = 0;
|
|
6178
|
+
let fullOutput = "";
|
|
6179
|
+
let degraded = false;
|
|
6180
|
+
let degradeDue = false;
|
|
6181
|
+
let degradeReason = null;
|
|
6027
6182
|
const isWin = process.platform === "win32";
|
|
6028
6183
|
if (ctx?.abortSignal?.aborted) {
|
|
6029
6184
|
yield `\u274C [\u5DF2\u4E2D\u6B62]\uFF1A\u547D\u4EE4 [${args.command}] \u672A\u6267\u884C\uFF08\u7528\u6237\u5DF2\u4E2D\u65AD\uFF09\u3002`;
|
|
@@ -6078,6 +6233,15 @@ ${tail}`,
|
|
|
6078
6233
|
}
|
|
6079
6234
|
return (decoder ?? pendingUtf8).decode(buf, { stream: true });
|
|
6080
6235
|
};
|
|
6236
|
+
const codec = {
|
|
6237
|
+
decode: decodeChunk,
|
|
6238
|
+
flush: () => {
|
|
6239
|
+
let s = "";
|
|
6240
|
+
if (decoder) s += decoder.decode();
|
|
6241
|
+
s += pendingUtf8.decode();
|
|
6242
|
+
return s;
|
|
6243
|
+
}
|
|
6244
|
+
};
|
|
6081
6245
|
proc.stdout?.on("data", (d) => {
|
|
6082
6246
|
queue.push(decodeChunk(d));
|
|
6083
6247
|
notifyNewData();
|
|
@@ -6104,11 +6268,22 @@ ${tail}`,
|
|
|
6104
6268
|
void killTree(proc);
|
|
6105
6269
|
};
|
|
6106
6270
|
ctx?.abortSignal?.addEventListener("abort", onAbort);
|
|
6271
|
+
const IDLE_TIMEOUT_MS = Number(process.env.RUN_COMMAND_IDLE_TIMEOUT_MS) || 6e4;
|
|
6272
|
+
const autoBgMs = Math.max(1, appConfig.runCommandAutoBgMs);
|
|
6273
|
+
const runtimeTimer = setTimeout(() => {
|
|
6274
|
+
degradeDue = true;
|
|
6275
|
+
notifyNewData();
|
|
6276
|
+
}, autoBgMs);
|
|
6277
|
+
runtimeTimer.unref?.();
|
|
6107
6278
|
let overLimit = false;
|
|
6108
6279
|
try {
|
|
6109
|
-
while ((!settled || queue.length > 0) && !overLimit) {
|
|
6280
|
+
while ((!settled || queue.length > 0) && !overLimit && !degraded) {
|
|
6281
|
+
if (degradeDue && !settled) {
|
|
6282
|
+
degraded = true;
|
|
6283
|
+
degradeReason = "runtime";
|
|
6284
|
+
break;
|
|
6285
|
+
}
|
|
6110
6286
|
if (queue.length === 0) {
|
|
6111
|
-
const IDLE_TIMEOUT_MS = 6e4;
|
|
6112
6287
|
let timedOut = false;
|
|
6113
6288
|
await new Promise((r) => {
|
|
6114
6289
|
resolveWaiter = r;
|
|
@@ -6117,20 +6292,26 @@ ${tail}`,
|
|
|
6117
6292
|
r();
|
|
6118
6293
|
}, IDLE_TIMEOUT_MS);
|
|
6119
6294
|
});
|
|
6295
|
+
if (degradeDue && !settled) {
|
|
6296
|
+
degraded = true;
|
|
6297
|
+
degradeReason = "runtime";
|
|
6298
|
+
break;
|
|
6299
|
+
}
|
|
6120
6300
|
if (timedOut && !settled && queue.length === 0) {
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
\u23F1\uFE0F [\u770B\u95E8\u72D7]\uFF1A\u547D\u4EE4\u8FDE\u7EED ${IDLE_TIMEOUT_MS / 1e3}s \u65E0\u8F93\u51FA\u4E14\u672A\u9000\u51FA\uFF0C\u5224\u5B9A\u4E3A\u5E38\u9A7B\u8FDB\u7A0B\uFF08\u5982 dev server / tail -f\uFF09\u3002\u5DF2\u4E3B\u52A8\u7EC8\u6B62\u4EE5\u91CA\u653E\u4E3B\u5FAA\u73AF\u2014\u2014\u5E38\u9A7B\u547D\u4EE4\u8BF7\u6539\u7528 run_in_background\u3002
|
|
6124
|
-
`;
|
|
6125
|
-
onAbort();
|
|
6126
|
-
settled = true;
|
|
6127
|
-
overLimit = true;
|
|
6301
|
+
degraded = true;
|
|
6302
|
+
degradeReason = "idle";
|
|
6128
6303
|
break;
|
|
6129
6304
|
}
|
|
6130
6305
|
}
|
|
6131
6306
|
while (queue.length > 0) {
|
|
6307
|
+
if (degradeDue && !settled) {
|
|
6308
|
+
degraded = true;
|
|
6309
|
+
degradeReason = "runtime";
|
|
6310
|
+
break;
|
|
6311
|
+
}
|
|
6132
6312
|
const chunk = queue.shift();
|
|
6133
6313
|
totalYieldedChars += chunk.length;
|
|
6314
|
+
fullOutput += chunk;
|
|
6134
6315
|
if (totalYieldedChars > maxChars) {
|
|
6135
6316
|
yield `
|
|
6136
6317
|
|
|
@@ -6144,14 +6325,30 @@ ${tail}`,
|
|
|
6144
6325
|
yield chunk;
|
|
6145
6326
|
}
|
|
6146
6327
|
}
|
|
6147
|
-
if (
|
|
6328
|
+
if (degraded) {
|
|
6329
|
+
const taskId = adoptRunningProcess(
|
|
6330
|
+
proc,
|
|
6331
|
+
{ command: args.command, cwd, sessionId: ctx?.sessionId, signal: ctx?.abortSignal },
|
|
6332
|
+
fullOutput + queue.join(""),
|
|
6333
|
+
codec
|
|
6334
|
+
);
|
|
6335
|
+
const why = degradeReason === "idle" ? `\u8FDE\u7EED ${Math.round(IDLE_TIMEOUT_MS / 1e3)}s \u65E0\u8F93\u51FA\u4E14\u672A\u9000\u51FA` : `\u5DF2\u6301\u7EED\u8FD0\u884C\u8D85\u8FC7 ${Math.round(autoBgMs / 1e3)}s`;
|
|
6336
|
+
yield `
|
|
6337
|
+
|
|
6338
|
+
\u23F3 [\u81EA\u52A8\u8F6C\u540E\u53F0]\uFF1A\u547D\u4EE4 [${args.command}] ${why}\uFF0C\u5DF2\u81EA\u52A8\u8F6C\u4E3A\u540E\u53F0\u4EFB\u52A1\uFF08\u524D\u53F0\u6D41\u5F0F\u7ED3\u675F\uFF0C\u672A\u6D88\u8D39\u7684\u5269\u4F59\u8F93\u51FA\u5DF2\u5E76\u5165\u540E\u53F0\u7F13\u51B2\uFF09\u3002
|
|
6339
|
+
task_id: ${taskId}
|
|
6340
|
+
\u26A0\uFE0F \u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF0C\u9000\u51FA\u7801\u672A\u77E5\uFF08\u4E0D\u5224\u5B9A\u6210\u529F/\u5931\u8D25\uFF09\u2014\u2014\u7528 get_background_output(task_id="${taskId}", wait_seconds=\u2026) \u7B49\u5F85/\u67E5\u770B\u7ED3\u679C\uFF1B\u82E5\u786E\u8BA4\u65E0\u9700\u7EE7\u7EED\uFF0C\u7528 stop_background_task(task_id="${taskId}") \u7EC8\u6B62\u3002
|
|
6341
|
+
`;
|
|
6342
|
+
} else if (overLimit) {
|
|
6148
6343
|
yield EXIT_SENTINEL(-1);
|
|
6149
6344
|
} else if (exitCode !== null) {
|
|
6150
6345
|
yield EXIT_SENTINEL(exitCode);
|
|
6151
6346
|
}
|
|
6152
6347
|
} finally {
|
|
6153
6348
|
if (idleTimer) clearTimeout(idleTimer);
|
|
6349
|
+
clearTimeout(runtimeTimer);
|
|
6154
6350
|
ctx?.abortSignal?.removeEventListener("abort", onAbort);
|
|
6351
|
+
if (!settled && !degraded) void killTree(proc);
|
|
6155
6352
|
}
|
|
6156
6353
|
}
|
|
6157
6354
|
}
|
|
@@ -10033,6 +10230,7 @@ var init_streamInference = __esm({
|
|
|
10033
10230
|
init_truncate();
|
|
10034
10231
|
init_transcript();
|
|
10035
10232
|
init_contextCore();
|
|
10233
|
+
init_contentParts();
|
|
10036
10234
|
streamInference = async function* (ctx) {
|
|
10037
10235
|
const {
|
|
10038
10236
|
message,
|
|
@@ -10060,7 +10258,8 @@ var init_streamInference = __esm({
|
|
|
10060
10258
|
eventType: "llm.request",
|
|
10061
10259
|
metadata: { depth, decisionSource: userDecisionSource, ok: true, durationMs: performance.now() - startTime, round },
|
|
10062
10260
|
usage: { prompt_tokens: estimateTokens(inferenceMessages) },
|
|
10063
|
-
payload: { input: message[message.length - 1].content }
|
|
10261
|
+
payload: { input: msgText(message[message.length - 1].content) }
|
|
10262
|
+
// ★ 多模态:trace 只记文本视图
|
|
10064
10263
|
});
|
|
10065
10264
|
console.log(`\u{1F504} \u4EE3\u7406\u63A8\u7406\u7B2C ${round} \u8F6E\uFF08\u6D41\u5F0F\uFF09...`);
|
|
10066
10265
|
let contentBuf = "";
|
|
@@ -10192,7 +10391,8 @@ var init_streamInference = __esm({
|
|
|
10192
10391
|
prompt_cache_hit_tokens: lastUsage?.cached_tokens,
|
|
10193
10392
|
prompt_cache_miss_tokens: (lastUsage?.prompt_tokens || 0) - (lastUsage?.cached_tokens || 0)
|
|
10194
10393
|
},
|
|
10195
|
-
payload: { input: message[message.length - 1].content }
|
|
10394
|
+
payload: { input: msgText(message[message.length - 1].content) }
|
|
10395
|
+
// ★ 多模态:trace 只记文本视图
|
|
10196
10396
|
});
|
|
10197
10397
|
console.log(`[DSC-DIAG] streamInference round ${round} \u5B8C\u6210: content=${contentBuf.length}chars reasoning=${reasoningBuf.length}chars toolCalls=${toolCallsBuf.size}`);
|
|
10198
10398
|
return { kind: "completed", assistantMessage, usage: lastUsage };
|
|
@@ -10205,7 +10405,8 @@ var init_streamInference = __esm({
|
|
|
10205
10405
|
sessionId,
|
|
10206
10406
|
eventType: "llm.error",
|
|
10207
10407
|
metadata: { depth, decisionSource: llmDecisionSource, ok: false, durationMs: performance.now() - startTime, attempt: round },
|
|
10208
|
-
payload: { input: message[message.length - 1].content, output: err.message }
|
|
10408
|
+
payload: { input: msgText(message[message.length - 1].content), output: err.message }
|
|
10409
|
+
// ★ 多模态:文本视图
|
|
10209
10410
|
});
|
|
10210
10411
|
console.log(`[DSC-DIAG] streamInference round ${round} \u2550\u2550\u2550 ERROR: ${err.message}`);
|
|
10211
10412
|
return { kind: "error", error: err };
|
|
@@ -10420,7 +10621,7 @@ async function* runAgent(message, options) {
|
|
|
10420
10621
|
const firstPrompt = (() => {
|
|
10421
10622
|
if (depth !== 0) return "";
|
|
10422
10623
|
const m = message.find((x) => x?.role === "user");
|
|
10423
|
-
return
|
|
10624
|
+
return msgText(m?.content);
|
|
10424
10625
|
})();
|
|
10425
10626
|
const nudges = createNudgeScheduler({ firstPrompt, planMode: !!options.planMode, noEarlyFinal: !!options.noEarlyFinal });
|
|
10426
10627
|
const userDecisionSource = depth > 0 ? "spawn_agent" : "user";
|
|
@@ -10548,7 +10749,7 @@ async function* runAgent(message, options) {
|
|
|
10548
10749
|
const assistantMessage = infResult.assistantMessage;
|
|
10549
10750
|
message.push(assistantMessage);
|
|
10550
10751
|
await appendMessage({ ...assistantMessage, sessionId });
|
|
10551
|
-
if (assistantMessage.content) {
|
|
10752
|
+
if (typeof assistantMessage.content === "string" && assistantMessage.content) {
|
|
10552
10753
|
lastContent = assistantMessage.content;
|
|
10553
10754
|
}
|
|
10554
10755
|
if (!assistantMessage.tool_calls || assistantMessage.tool_calls.length === 0) {
|
|
@@ -10641,6 +10842,7 @@ var init_runAgent = __esm({
|
|
|
10641
10842
|
init_inbox();
|
|
10642
10843
|
init_common();
|
|
10643
10844
|
init_contextCore();
|
|
10845
|
+
init_contentParts();
|
|
10644
10846
|
init_store();
|
|
10645
10847
|
init_truncate();
|
|
10646
10848
|
init_hooks();
|
|
@@ -10733,11 +10935,12 @@ var init_recovery = __esm({
|
|
|
10733
10935
|
});
|
|
10734
10936
|
|
|
10735
10937
|
// ../core/src/session/content.ts
|
|
10736
|
-
var decayOldToolResults, buildContextMessages;
|
|
10938
|
+
var decayOldToolResults, NO_VISION_IMAGE_NOTE, enforceVisionGate, buildContextMessages;
|
|
10737
10939
|
var init_content = __esm({
|
|
10738
10940
|
"../core/src/session/content.ts"() {
|
|
10739
10941
|
"use strict";
|
|
10740
10942
|
init_contextCore();
|
|
10943
|
+
init_contentParts();
|
|
10741
10944
|
init_transcript();
|
|
10742
10945
|
init_store();
|
|
10743
10946
|
init_config();
|
|
@@ -10747,15 +10950,20 @@ var init_content = __esm({
|
|
|
10747
10950
|
const cutoffUnitIdx = Math.max(0, units.length - appConfig.KEEP_RECENT_UNITS);
|
|
10748
10951
|
if (cutoffUnitIdx === 0) return msgs;
|
|
10749
10952
|
const decayIds = /* @__PURE__ */ new Set();
|
|
10953
|
+
let hasOldImage = false;
|
|
10750
10954
|
for (let u = 0; u < cutoffUnitIdx; u++) {
|
|
10751
10955
|
for (const m of units[u]) {
|
|
10752
10956
|
const mm = m;
|
|
10753
10957
|
if (mm.role === "tool" && typeof mm.tool_call_id === "string") decayIds.add(mm.tool_call_id);
|
|
10958
|
+
if (hasImagePart(m.content)) hasOldImage = true;
|
|
10754
10959
|
}
|
|
10755
10960
|
}
|
|
10756
|
-
if (decayIds.size === 0) return msgs;
|
|
10961
|
+
if (decayIds.size === 0 && !hasOldImage) return msgs;
|
|
10757
10962
|
const keep = appConfig.BOUNDARY_TOOL_KEEP_CHARS;
|
|
10963
|
+
const oldRefs = /* @__PURE__ */ new Set();
|
|
10964
|
+
for (let u = 0; u < cutoffUnitIdx; u++) for (const m of units[u]) oldRefs.add(m);
|
|
10758
10965
|
return msgs.map((m) => {
|
|
10966
|
+
if (!oldRefs.has(m)) return m;
|
|
10759
10967
|
const mm = m;
|
|
10760
10968
|
if (mm.role === "tool" && decayIds.has(mm.tool_call_id) && typeof mm.content === "string" && mm.content.length > keep) {
|
|
10761
10969
|
const head = mm.content.slice(0, keep);
|
|
@@ -10763,9 +10971,11 @@ var init_content = __esm({
|
|
|
10763
10971
|
|
|
10764
10972
|
[\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]` };
|
|
10765
10973
|
}
|
|
10766
|
-
return
|
|
10974
|
+
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]");
|
|
10767
10975
|
});
|
|
10768
10976
|
};
|
|
10977
|
+
NO_VISION_IMAGE_NOTE = "[\u56FE\u7247\u672A\u9001\u8FBE\uFF1A\u5F53\u524D\u672A\u5F00\u542F\u89C6\u89C9\u80FD\u529B\uFF08DEEP_SEEK_VISION\uFF09\uFF0C\u6A21\u578B\u770B\u4E0D\u5230\u8BE5\u56FE\uFF1B\u539F\u56FE\u4FDD\u7559\u5728\u4F1A\u8BDD\u5F52\u6863\u4E2D\uFF0C\u5982\u9700\u5206\u6790\u8BF7\u8BA9\u7528\u6237\u91CD\u65B0\u63D0\u4F9B]";
|
|
10978
|
+
enforceVisionGate = (msgs) => isVisionEnabled() ? msgs : msgs.map((m) => collapseToText(m, NO_VISION_IMAGE_NOTE));
|
|
10769
10979
|
buildContextMessages = async (sessionId, currentUserMsg, systemPrompt) => {
|
|
10770
10980
|
const lines = await readTranscriptLines(sessionId);
|
|
10771
10981
|
const store = await getRollingState(sessionId);
|
|
@@ -10785,12 +10995,12 @@ var init_content = __esm({
|
|
|
10785
10995
|
const messageAll = all.slice(archivedMessageCount);
|
|
10786
10996
|
if (messageAll.length === 0) {
|
|
10787
10997
|
result.push(currentUserMsg);
|
|
10788
|
-
return result;
|
|
10998
|
+
return enforceVisionGate(result);
|
|
10789
10999
|
}
|
|
10790
11000
|
const repair = repairOrphanToolCalls(messageAll, recovery.interruption.kind === "crashed");
|
|
10791
11001
|
result.push(...decayOldToolResults(repair.msgs));
|
|
10792
11002
|
result.push(currentUserMsg);
|
|
10793
|
-
return result;
|
|
11003
|
+
return enforceVisionGate(result);
|
|
10794
11004
|
};
|
|
10795
11005
|
}
|
|
10796
11006
|
});
|
|
@@ -12254,6 +12464,7 @@ var init_chatProcessing = __esm({
|
|
|
12254
12464
|
init_store();
|
|
12255
12465
|
init_transcript();
|
|
12256
12466
|
init_content();
|
|
12467
|
+
init_contentParts();
|
|
12257
12468
|
init_trace();
|
|
12258
12469
|
init_webHost();
|
|
12259
12470
|
init_registry();
|
|
@@ -12309,10 +12520,16 @@ ${lines.join("\n")}
|
|
|
12309
12520
|
\u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${path41.basename(activeReal) || activeReal} \u751F\u6548\u3002`;
|
|
12310
12521
|
}
|
|
12311
12522
|
let replyText = "";
|
|
12523
|
+
let userContent = inbound.content;
|
|
12524
|
+
if (Array.isArray(inbound.attachments) && inbound.attachments.length > 0) {
|
|
12525
|
+
userContent = isVisionEnabled() ? toWireUserContent(inbound.content, inbound.attachments) : `${inbound.content}
|
|
12526
|
+
|
|
12527
|
+
\u{1F5BC} \u6536\u5230\u56FE\u7247\u9644\u4EF6\uFF08${inbound.attachments.map((a) => a?.name || "image").join("\u3001")}\uFF09\uFF1A\u5F53\u524D\u6A21\u578B\u672A\u5F00\u542F\u89C6\u89C9\u80FD\u529B\uFF08DEEP_SEEK_VISION\uFF09\uFF0C\u5DF2\u5FFD\u7565\u56FE\u7247\u5185\u5BB9\u3002`;
|
|
12528
|
+
}
|
|
12312
12529
|
try {
|
|
12313
12530
|
const fullMessages = await buildContextMessages(
|
|
12314
12531
|
sessionId,
|
|
12315
|
-
{ role: "user", content:
|
|
12532
|
+
{ role: "user", content: userContent },
|
|
12316
12533
|
sysPrompt
|
|
12317
12534
|
);
|
|
12318
12535
|
await emitTrace({
|
|
@@ -12325,7 +12542,7 @@ ${lines.join("\n")}
|
|
|
12325
12542
|
});
|
|
12326
12543
|
void sweepStaleAtomicTmp().catch(() => {
|
|
12327
12544
|
});
|
|
12328
|
-
await appendMessage({ sessionId, role: "user", content:
|
|
12545
|
+
await appendMessage({ sessionId, role: "user", content: userContent });
|
|
12329
12546
|
let streamedAnyText = false;
|
|
12330
12547
|
const onUIEvent = opts?.onUIEvent ?? ((evt) => sseWrite?.(evt));
|
|
12331
12548
|
const requestApproval2 = opts?.requestApproval ?? createWebRequestApproval((evt) => sseWrite?.(evt), abortSignal);
|
|
@@ -12399,6 +12616,7 @@ var init_fork = __esm({
|
|
|
12399
12616
|
"../core/src/session/fork.ts"() {
|
|
12400
12617
|
"use strict";
|
|
12401
12618
|
init_common();
|
|
12619
|
+
init_contentParts();
|
|
12402
12620
|
init_transcript();
|
|
12403
12621
|
init_store();
|
|
12404
12622
|
listForkAnchors = (lines) => {
|
|
@@ -12408,7 +12626,7 @@ var init_fork = __esm({
|
|
|
12408
12626
|
if (isEventLine(l)) continue;
|
|
12409
12627
|
const row = l;
|
|
12410
12628
|
if (row?.role === "user") {
|
|
12411
|
-
lastUser =
|
|
12629
|
+
lastUser = msgText(row.content) || (hasImagePart(row.content) ? "\u{1F5BC} [\u56FE\u7247\u6D88\u606F]" : "");
|
|
12412
12630
|
} else if (row?.role === "assistant") {
|
|
12413
12631
|
const content = typeof row.content === "string" ? row.content : "";
|
|
12414
12632
|
const names = Array.isArray(row.tool_calls) ? row.tool_calls.map((tc) => tc?.function?.name ?? "").filter(Boolean).join(", ") : "";
|