deepseeker-code 1.0.59 → 1.0.61
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 +695 -480
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -4228,7 +4228,7 @@ async function killBackgroundTasksUnder(dirPath) {
|
|
|
4228
4228
|
}
|
|
4229
4229
|
return killed;
|
|
4230
4230
|
}
|
|
4231
|
-
var _winShellCache, resolveWinShell, MAX_BUFFER_CHARS, registry, createBgTask, attachTaskLifecycle, makeTaskExitNotifier, adoptRunningProcess, backgroundTools, killAllBackgroundTasks;
|
|
4231
|
+
var _winShellCache, resolveWinShell, MAX_BUFFER_CHARS, registry, createBgTask, attachTaskLifecycle, makeTaskExitNotifier, adoptRunningProcess, BG_WAIT_SECONDS_CAP, clampWaitSeconds, backgroundTools, killAllBackgroundTasks;
|
|
4232
4232
|
var init_background = __esm({
|
|
4233
4233
|
"../core/src/tool/registry/background.ts"() {
|
|
4234
4234
|
"use strict";
|
|
@@ -4393,6 +4393,8 @@ var init_background = __esm({
|
|
|
4393
4393
|
void attachTaskLifecycle(task, proc, { signal: meta.signal, codec, onExit: meta.onExit });
|
|
4394
4394
|
return task.taskId;
|
|
4395
4395
|
};
|
|
4396
|
+
BG_WAIT_SECONDS_CAP = 90;
|
|
4397
|
+
clampWaitSeconds = (v) => Math.min(Math.max(0, Math.floor(v ?? 0)), BG_WAIT_SECONDS_CAP);
|
|
4396
4398
|
backgroundTools = [
|
|
4397
4399
|
{
|
|
4398
4400
|
type: "function",
|
|
@@ -4481,13 +4483,13 @@ task_id: ${taskId}
|
|
|
4481
4483
|
type: "function",
|
|
4482
4484
|
function: {
|
|
4483
4485
|
name: "get_background_output",
|
|
4484
|
-
description: "\u67E5\u770B\u6307\u5B9A\u540E\u53F0\u4EFB\u52A1\u7684\u6700\u8FD1\u8F93\u51FA\u65E5\u5FD7\u4E0E\u8FD0\u884C\u72B6\u6001\uFF08running/exited/killed + \u9000\u51FA\u7801\uFF09\u3002\u7EAF\u8BFB\uFF0C\u514D\u5BA1\u6279\u3002\u7528\u4E8E\u786E\u8BA4 dev server \u662F\u5426\u542F\u52A8\u6210\u529F\u3001\u67E5\u770B\u62A5\u9519\u7B49\u3002\u7B49\u957F\u4EFB\u52A1\uFF08\u6784\u5EFA/\u6D4B\u8BD5\uFF09\u8DD1\u5B8C\uFF1A\u5E26 wait_seconds \u963B\u585E\u7B49\u5F85\u4EFB\u52A1\u9000\u51FA\u540E\u518D\u8FD4\u56DE\uFF08\u4ECD\u5728\u8DD1\u5219\u7B49\
|
|
4486
|
+
description: "\u67E5\u770B\u6307\u5B9A\u540E\u53F0\u4EFB\u52A1\u7684\u6700\u8FD1\u8F93\u51FA\u65E5\u5FD7\u4E0E\u8FD0\u884C\u72B6\u6001\uFF08running/exited/killed + \u9000\u51FA\u7801\uFF09\u3002\u7EAF\u8BFB\uFF0C\u514D\u5BA1\u6279\u3002\u7528\u4E8E\u786E\u8BA4 dev server \u662F\u5426\u542F\u52A8\u6210\u529F\u3001\u67E5\u770B\u62A5\u9519\u7B49\u3002\u7B49\u957F\u4EFB\u52A1\uFF08\u6784\u5EFA/\u6D4B\u8BD5\uFF09\u8DD1\u5B8C\uFF1A\u5E26 wait_seconds \u963B\u585E\u7B49\u5F85\u4EFB\u52A1\u9000\u51FA\u540E\u518D\u8FD4\u56DE\uFF08\u4ECD\u5728\u8DD1\u5219\u7B49\u6EE1 wait_seconds \u8FD4\u56DE\u5F53\u524D\u5FEB\u7167\uFF09\u2014\u2014\u7528\u5B83\u7B49\uFF0C\u4E0D\u8981\u4E0D\u5E26 wait \u53CD\u590D\u8F6E\u8BE2\u67E5\u8BE2\u3002",
|
|
4485
4487
|
parameters: {
|
|
4486
4488
|
type: "object",
|
|
4487
4489
|
properties: {
|
|
4488
4490
|
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" },
|
|
4489
4491
|
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" },
|
|
4490
|
-
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
|
|
4492
|
+
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 90 \u79D2\u2014\u2014\u987B\u4F4E\u4E8E\u8C03\u5EA6\u5C42 120s \u5DE5\u5177\u7194\u65AD\u7EBF\uFF0C\u66F4\u957F\u7684 wait \u4F1A\u88AB\u7194\u65AD\u3001\u771F\u5B9E\u7ED3\u679C\u88AB\u4E22\u5F03\u6362\u6210\u8D85\u65F6\u6587\u6848\u3002\u9884\u8BA1\u66F4\u4E45\u5C31\u4F20 90\uFF0C\u8FD4\u56DE\u4ECD running \u5C31\u518D\u8C03\u4E00\u6B21\u63A5\u7740\u7B49\uFF1B\u53EA\u770B\u5F53\u524D\u65E5\u5FD7\u5C31\u7701\u7565\u6B64\u53C2\u6570" }
|
|
4491
4493
|
},
|
|
4492
4494
|
required: ["task_id"]
|
|
4493
4495
|
},
|
|
@@ -4498,7 +4500,7 @@ task_id: ${taskId}
|
|
|
4498
4500
|
if (!task || task.sessionId !== ctx?.sessionId) {
|
|
4499
4501
|
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`);
|
|
4500
4502
|
}
|
|
4501
|
-
const waitMs =
|
|
4503
|
+
const waitMs = clampWaitSeconds(args.wait_seconds) * 1e3;
|
|
4502
4504
|
if (waitMs > 0 && task.status === "running") {
|
|
4503
4505
|
const deadline = Date.now() + waitMs;
|
|
4504
4506
|
while (task.status === "running" && Date.now() < deadline && !ctx?.abortSignal?.aborted) {
|
|
@@ -6027,13 +6029,17 @@ var init_toolResultCollect = __esm({
|
|
|
6027
6029
|
const idleMs = Number(process.env.DEEP_SEEK_STREAM_IDLE_TIMEOUT_MS) || 12e4;
|
|
6028
6030
|
while (true) {
|
|
6029
6031
|
let timer2;
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6032
|
+
let outcome;
|
|
6033
|
+
try {
|
|
6034
|
+
outcome = await Promise.race([
|
|
6035
|
+
ret.next().then((step) => ({ timedOut: false, step })),
|
|
6036
|
+
new Promise((resolve) => {
|
|
6037
|
+
timer2 = setTimeout(() => resolve({ timedOut: true }), idleMs);
|
|
6038
|
+
})
|
|
6039
|
+
]);
|
|
6040
|
+
} finally {
|
|
6041
|
+
if (timer2) clearTimeout(timer2);
|
|
6042
|
+
}
|
|
6037
6043
|
if (outcome.timedOut) {
|
|
6038
6044
|
full += `
|
|
6039
6045
|
|
|
@@ -6054,18 +6060,22 @@ var init_toolResultCollect = __esm({
|
|
|
6054
6060
|
const timeoutMs2 = Number(process.env.DEEP_SEEK_STREAM_IDLE_TIMEOUT_MS) || 12e4;
|
|
6055
6061
|
let timer;
|
|
6056
6062
|
let onAbort;
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
signal
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6063
|
+
let raced;
|
|
6064
|
+
try {
|
|
6065
|
+
raced = await Promise.race([
|
|
6066
|
+
Promise.resolve(ret).then((v2) => ({ kind: "ok", value: v2 })),
|
|
6067
|
+
new Promise((resolve) => {
|
|
6068
|
+
timer = setTimeout(() => resolve({ kind: "timeout" }), timeoutMs2);
|
|
6069
|
+
}),
|
|
6070
|
+
...signal ? [new Promise((resolve) => {
|
|
6071
|
+
onAbort = () => resolve({ kind: "abort" });
|
|
6072
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
6073
|
+
})] : []
|
|
6074
|
+
]);
|
|
6075
|
+
} finally {
|
|
6076
|
+
if (timer) clearTimeout(timer);
|
|
6077
|
+
if (onAbort && signal) signal.removeEventListener("abort", onAbort);
|
|
6078
|
+
}
|
|
6069
6079
|
if (raced.kind === "timeout") {
|
|
6070
6080
|
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" };
|
|
6071
6081
|
}
|
|
@@ -7801,9 +7811,15 @@ ${tail}`,
|
|
|
7801
7811
|
cwd,
|
|
7802
7812
|
detached: !isWin,
|
|
7803
7813
|
// 非 Win 下支持整个进程组独立
|
|
7804
|
-
env: scrubCommandEnv()
|
|
7814
|
+
env: scrubCommandEnv()
|
|
7805
7815
|
// ★ 剔除 agent 自身凭证(LLM key / 服务端 token / 搜索 key),防 LLM 经 env/printenv 读取外泄
|
|
7806
|
-
|
|
7816
|
+
// ★ 中止唯一出口 = 下方 onAbort→killTree(2026-10-27 修「■ 终止无效」):
|
|
7817
|
+
// 勿把 signal 交给 spawn——Node 内部 abort 监听先于 onAbort 触发,TerminateProcess
|
|
7818
|
+
// 只杀最外层进程;随后 killTree 的 taskkill /T 对已死根「找不到进程」直接失败,
|
|
7819
|
+
// 孙进程(tsx 的 esbuild、node --test 的每文件子进程)存活并持有继承的 stdout 管道,
|
|
7820
|
+
// close 永不触发 → 工具永不结束(多层进程树命令下点终止永远转圈)。
|
|
7821
|
+
// 根存活时 taskkill /T 才能整树剿灭;进入工具时已 aborted 由上方前置检查拦截,
|
|
7822
|
+
// pre-check 与 addEventListener 之间全同步无 await,无竞态窗口。
|
|
7807
7823
|
});
|
|
7808
7824
|
} catch (e) {
|
|
7809
7825
|
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;
|
|
@@ -7813,6 +7829,7 @@ ${tail}`,
|
|
|
7813
7829
|
const queue = [];
|
|
7814
7830
|
let settled = false;
|
|
7815
7831
|
let exitCode = null;
|
|
7832
|
+
let abortedByUser = false;
|
|
7816
7833
|
let resolveWaiter = null;
|
|
7817
7834
|
let idleTimer = null;
|
|
7818
7835
|
const notifyNewData = () => {
|
|
@@ -7866,13 +7883,14 @@ ${tail}`,
|
|
|
7866
7883
|
notifyNewData();
|
|
7867
7884
|
});
|
|
7868
7885
|
proc.on("close", (code) => {
|
|
7869
|
-
exitCode ??= code == null ? -1 : code;
|
|
7886
|
+
exitCode ??= abortedByUser ? -1 : code == null ? -1 : code;
|
|
7870
7887
|
if (decoder) queue.push(decoder.decode());
|
|
7871
7888
|
queue.push(pendingUtf8.decode());
|
|
7872
7889
|
settled = true;
|
|
7873
7890
|
notifyNewData();
|
|
7874
7891
|
});
|
|
7875
7892
|
const onAbort = () => {
|
|
7893
|
+
abortedByUser = true;
|
|
7876
7894
|
void killTree(proc);
|
|
7877
7895
|
};
|
|
7878
7896
|
ctx?.abortSignal?.addEventListener("abort", onAbort);
|
|
@@ -12033,7 +12051,7 @@ var init_autoPermission = __esm({
|
|
|
12033
12051
|
|
|
12034
12052
|
// ../core/src/agent/toolExecution.ts
|
|
12035
12053
|
import path36 from "path";
|
|
12036
|
-
var applyPrivacyMasking, scaleTruncBudget, failResult, emitValidationFailed, resolveEarlyOutcome, runSecurityGates, executeTool, finalizeOutcome, processToolCall;
|
|
12054
|
+
var applyPrivacyMasking, scaleTruncBudget, failResult, emitValidationFailed, resolveEarlyOutcome, runSecurityGates, executeTool, finalizeOutcome, previewArgs, processToolCall, processToolCallInner;
|
|
12037
12055
|
var init_toolExecution = __esm({
|
|
12038
12056
|
"../core/src/agent/toolExecution.ts"() {
|
|
12039
12057
|
"use strict";
|
|
@@ -12305,7 +12323,9 @@ ${state.result}`;
|
|
|
12305
12323
|
const { calledName, calledArgs, matchedTool } = state;
|
|
12306
12324
|
state.result = applyPrivacyMasking(matchedTool?.function?.privacyMaskingRules, calledArgs, state.result);
|
|
12307
12325
|
const fill = contextTokensEst !== void 0 && modelWindow > 0 ? contextTokensEst / modelWindow : void 0;
|
|
12308
|
-
const
|
|
12326
|
+
const baseBudget = matchedTool?.function?.maxOutputCharacters ?? appConfig.MAX_TOOL_RESULT_CHARS;
|
|
12327
|
+
const capped = ctx.batchBudgetChars !== void 0 ? Math.min(baseBudget, ctx.batchBudgetChars) : baseBudget;
|
|
12328
|
+
const truncBudget = scaleTruncBudget(capped, fill);
|
|
12309
12329
|
const sidecarNote = state.result.length > truncBudget ? await writeSidecarArchive(sessionId, String(toolCall.id), state.result) : void 0;
|
|
12310
12330
|
state.result = truncateToolResult(state.result, truncBudget, sidecarNote);
|
|
12311
12331
|
const resultStatus = state.resultStatus;
|
|
@@ -12322,7 +12342,7 @@ ${state.result}`;
|
|
|
12322
12342
|
}
|
|
12323
12343
|
if (state.postHookOverride !== void 0) {
|
|
12324
12344
|
console.log(`\u270F\uFE0F [Post-hook] [${calledName}] \u6A21\u578B\u89C6\u56FE\u7ED3\u679C\u5DF2\u88AB hook \u6539\u5199`);
|
|
12325
|
-
const overrideBudget = scaleTruncBudget(
|
|
12345
|
+
const overrideBudget = scaleTruncBudget(capped, fill);
|
|
12326
12346
|
const overrideNote = state.postHookOverride.length > overrideBudget ? await writeSidecarArchive(sessionId, String(toolCall.id), state.postHookOverride) : void 0;
|
|
12327
12347
|
resultForModel = truncateToolResult(state.postHookOverride, overrideBudget, overrideNote);
|
|
12328
12348
|
}
|
|
@@ -12332,7 +12352,36 @@ ${state.result}`;
|
|
|
12332
12352
|
}
|
|
12333
12353
|
return { toolCallId: toolCall.id, calledName, calledArgs, resultForModel, resultForUser, ok, imageAttachments: state.imageAttachments };
|
|
12334
12354
|
};
|
|
12355
|
+
previewArgs = (raw, max) => raw === void 0 ? void 0 : raw.length > max ? raw.slice(0, max) + `\u2026\uFF08\u5171 ${raw.length} \u5B57\u7B26\uFF09` : raw;
|
|
12335
12356
|
processToolCall = async (toolCall, ctx) => {
|
|
12357
|
+
try {
|
|
12358
|
+
return await processToolCallInner(toolCall, ctx);
|
|
12359
|
+
} catch (e) {
|
|
12360
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
12361
|
+
console.error(`\u274C \u5DE5\u5177\u8C03\u7528\u5904\u7406\u5F02\u5E38\uFF08\u5DF2\u9694\u79BB\uFF0C\u4E0D\u5F71\u54CD\u540C\u6279\u5176\u4ED6\u5DE5\u5177\uFF09: ${msg}`);
|
|
12362
|
+
try {
|
|
12363
|
+
ctx.events({
|
|
12364
|
+
sessionId: ctx.sessionId,
|
|
12365
|
+
eventType: "tool.failed",
|
|
12366
|
+
metadata: { depth: ctx.depth, decisionSource: ctx.llmDecisionSource, durationMs: performance.now() - ctx.startTime, round: ctx.round, tools_id: toolCall?.id ?? "", toolName: toolCall?.function?.name ?? "unknown", toolSource: "builtin", ok: false, attempt: ctx.round, errorCategory: "runtime" },
|
|
12367
|
+
payload: { output: `\u5DE5\u5177\u6267\u884C\u5F02\u5E38\uFF1A${msg}` }
|
|
12368
|
+
});
|
|
12369
|
+
} catch {
|
|
12370
|
+
}
|
|
12371
|
+
return {
|
|
12372
|
+
toolCallId: toolCall?.id ?? "",
|
|
12373
|
+
calledName: toolCall?.function?.name ?? "unknown",
|
|
12374
|
+
calledArgs: { _preview: previewArgs(toolCall?.function?.arguments, 300) },
|
|
12375
|
+
// ★ 保留参数上下文(截断预览):否则 tool.failed 排查时看不到模型当时传了什么
|
|
12376
|
+
resultForModel: `\u5DE5\u5177\u6267\u884C\u5F02\u5E38\uFF1A${msg}\uFF08\u672C\u8C03\u7528\u5DF2\u9694\u79BB\uFF0C\u5176\u4ED6\u5DE5\u5177\u7ED3\u679C\u4E0D\u53D7\u5F71\u54CD\uFF09`,
|
|
12377
|
+
resultForUser: `\u274C \u5DE5\u5177\u6267\u884C\u5F02\u5E38\uFF1A${msg}`,
|
|
12378
|
+
ok: false,
|
|
12379
|
+
aborted: ctx.signal?.aborted ? true : void 0
|
|
12380
|
+
// ★ 不吞 abort
|
|
12381
|
+
};
|
|
12382
|
+
}
|
|
12383
|
+
};
|
|
12384
|
+
processToolCallInner = async (toolCall, ctx) => {
|
|
12336
12385
|
const state = {
|
|
12337
12386
|
calledName: "",
|
|
12338
12387
|
calledArgs: {},
|
|
@@ -12354,7 +12403,9 @@ ${state.result}`;
|
|
|
12354
12403
|
} catch {
|
|
12355
12404
|
state.parseFailed = true;
|
|
12356
12405
|
}
|
|
12357
|
-
|
|
12406
|
+
const argsLog = JSON.stringify(state.calledArgs) ?? "";
|
|
12407
|
+
const argsPreview = process.env.DSC_DEBUG_TOOL_ARGS === "1" ? argsLog : argsLog.length > 200 ? argsLog.slice(0, 200) + `\u2026\uFF08\u5171 ${argsLog.length} \u5B57\u7B26\uFF09` : argsLog;
|
|
12408
|
+
console.log(`\u{1F916} \u6A21\u578B\u8BF7\u6C42\u8C03\u7528\u5DE5\u5177: ${state.calledName}\uFF0C\u53C2\u6570: ${argsPreview}`);
|
|
12358
12409
|
}
|
|
12359
12410
|
state.matchedTool = ctx.rawTools.find((t) => t.function.name === state.calledName);
|
|
12360
12411
|
const early = resolveEarlyOutcome(ctx, toolCall, state);
|
|
@@ -12396,13 +12447,14 @@ ${state.result}`;
|
|
|
12396
12447
|
});
|
|
12397
12448
|
|
|
12398
12449
|
// ../core/src/agent/toolScheduling.ts
|
|
12399
|
-
var dedupeSameRoundCalls, scheduleToolCalls;
|
|
12450
|
+
var dedupeSameRoundCalls, BATCH_MIN_CHARS, BATCH_WINDOW_SHARE, CHAR_PER_TOKEN, computeBatchBudget, scheduleToolCalls;
|
|
12400
12451
|
var init_toolScheduling = __esm({
|
|
12401
12452
|
"../core/src/agent/toolScheduling.ts"() {
|
|
12402
12453
|
"use strict";
|
|
12403
12454
|
init_toolExecution();
|
|
12404
12455
|
init_transcript();
|
|
12405
12456
|
init_contentParts();
|
|
12457
|
+
init_contextCore();
|
|
12406
12458
|
init_config();
|
|
12407
12459
|
init_tool();
|
|
12408
12460
|
init_permissions();
|
|
@@ -12422,6 +12474,14 @@ var init_toolScheduling = __esm({
|
|
|
12422
12474
|
}
|
|
12423
12475
|
return { batch, plan };
|
|
12424
12476
|
};
|
|
12477
|
+
BATCH_MIN_CHARS = 12e3;
|
|
12478
|
+
BATCH_WINDOW_SHARE = 0.5;
|
|
12479
|
+
CHAR_PER_TOKEN = 4;
|
|
12480
|
+
computeBatchBudget = (modelWindow, compactRatio, contextTokensEst, batchSize) => {
|
|
12481
|
+
const budgetTokensLeft = Math.max(0, modelWindow * compactRatio - (contextTokensEst ?? 0));
|
|
12482
|
+
const batchCapChars = Math.max(BATCH_MIN_CHARS, Math.floor(budgetTokensLeft * CHAR_PER_TOKEN * BATCH_WINDOW_SHARE));
|
|
12483
|
+
return { batchCapChars, perToolCapChars: Math.floor(batchCapChars / batchSize) };
|
|
12484
|
+
};
|
|
12425
12485
|
scheduleToolCalls = async function* (assistantMessage, message, ctx) {
|
|
12426
12486
|
const { sessionId, signal, rawTools } = ctx;
|
|
12427
12487
|
let abortedDuringTools = false;
|
|
@@ -12490,7 +12550,10 @@ var init_toolScheduling = __esm({
|
|
|
12490
12550
|
const bp = parseTc(p.tc);
|
|
12491
12551
|
yield { type: "tool.start", toolCallId: p.tc.id, toolName: bp.name, args: bp.args };
|
|
12492
12552
|
}
|
|
12493
|
-
const
|
|
12553
|
+
const budget = batch.length >= 2 ? computeBatchBudget(ctx.modelWindow, ctx.compactRatio, ctx.contextTokensEst, batch.length) : void 0;
|
|
12554
|
+
const tokensBefore = budget ? estimateTokens(message) : 0;
|
|
12555
|
+
const batchCtx = budget ? { ...ctx, batchBudgetChars: budget.perToolCapChars } : ctx;
|
|
12556
|
+
const outcomes = await Promise.all(batch.map((btc) => processToolCall(btc, batchCtx)));
|
|
12494
12557
|
const outcomeByTc = /* @__PURE__ */ new Map();
|
|
12495
12558
|
batch.forEach((btc, i) => outcomeByTc.set(btc, outcomes[i]));
|
|
12496
12559
|
const batchEntries = [];
|
|
@@ -12514,6 +12577,34 @@ var init_toolScheduling = __esm({
|
|
|
12514
12577
|
if (oc.aborted) abortedDuringTools = true;
|
|
12515
12578
|
}
|
|
12516
12579
|
await appendMessages(sessionId, batchEntries);
|
|
12580
|
+
if (budget) {
|
|
12581
|
+
try {
|
|
12582
|
+
const tokensAfter = estimateTokens(message);
|
|
12583
|
+
ctx.events({
|
|
12584
|
+
sessionId,
|
|
12585
|
+
eventType: "tool.batch.budget",
|
|
12586
|
+
metadata: {
|
|
12587
|
+
depth: ctx.depth,
|
|
12588
|
+
decisionSource: ctx.llmDecisionSource,
|
|
12589
|
+
ok: true,
|
|
12590
|
+
durationMs: performance.now() - ctx.startTime,
|
|
12591
|
+
round: ctx.round,
|
|
12592
|
+
batchSize: batch.length,
|
|
12593
|
+
batchCapChars: budget.batchCapChars,
|
|
12594
|
+
perToolCapChars: budget.perToolCapChars
|
|
12595
|
+
},
|
|
12596
|
+
payload: {
|
|
12597
|
+
output: JSON.stringify({
|
|
12598
|
+
injectedChars: batch.map((btc) => outcomeByTc.get(btc)?.resultForModel.length ?? 0),
|
|
12599
|
+
tokensBefore,
|
|
12600
|
+
tokensAfter,
|
|
12601
|
+
tokensDelta: tokensAfter - tokensBefore
|
|
12602
|
+
})
|
|
12603
|
+
}
|
|
12604
|
+
});
|
|
12605
|
+
} catch {
|
|
12606
|
+
}
|
|
12607
|
+
}
|
|
12517
12608
|
} else {
|
|
12518
12609
|
yield { type: "tool.start", toolCallId: tc.id, toolName: pname, args: pargs };
|
|
12519
12610
|
const oc = await processToolCall(tc, ctx);
|
|
@@ -12644,9 +12735,10 @@ var init_streamInference = __esm({
|
|
|
12644
12735
|
const MAX_STREAM_RETRIES = 2;
|
|
12645
12736
|
const MAX_API_RETRIES = 3;
|
|
12646
12737
|
let apiRetries = 0;
|
|
12738
|
+
let idleRetries = 0;
|
|
12647
12739
|
let compactedThisRound = false;
|
|
12648
12740
|
let visionDegradedThisRound = false;
|
|
12649
|
-
for (
|
|
12741
|
+
for (; ; ) {
|
|
12650
12742
|
try {
|
|
12651
12743
|
for await (const chunk of activeProvider.streamChat(inferenceMessages, cleanedToolSchemas, { signal, model, thinkingLevel })) {
|
|
12652
12744
|
if (signal?.aborted) break;
|
|
@@ -12692,10 +12784,11 @@ var init_streamInference = __esm({
|
|
|
12692
12784
|
}
|
|
12693
12785
|
);
|
|
12694
12786
|
const noOutputYet = !contentBuf && !reasoningBuf && toolCallsBuf.size === 0;
|
|
12695
|
-
if (isIdleTimeout &&
|
|
12787
|
+
if (isIdleTimeout && idleRetries < MAX_STREAM_RETRIES) {
|
|
12788
|
+
idleRetries++;
|
|
12696
12789
|
if (!noOutputYet) yield { type: "text.reset" };
|
|
12697
12790
|
const stallShape = noOutputYet ? "\uFF0C\u5C1A\u65E0\u8F93\u51FA" : hasCompleteToolCall ? "\uFF0C\u5DF2\u6709\u5B8C\u6574 tool_call\uFF08\u6D41\u5C3E\u90E8 stall\uFF09" : "\uFF0Ctool_call \u672A\u6D41\u5B8C";
|
|
12698
|
-
console.warn(`\u26A0\uFE0F \u6D41\u5F0F stall\uFF08idle \u8D85\u65F6${stallShape}\uFF09\uFF0C\u7B2C ${
|
|
12791
|
+
console.warn(`\u26A0\uFE0F \u6D41\u5F0F stall\uFF08idle \u8D85\u65F6${stallShape}\uFF09\uFF0C\u7B2C ${idleRetries}/${MAX_STREAM_RETRIES} \u6B21\u91CD\u8BD5...`);
|
|
12699
12792
|
contentBuf = "";
|
|
12700
12793
|
reasoningBuf = "";
|
|
12701
12794
|
toolCallsBuf.clear();
|
|
@@ -12803,7 +12896,6 @@ var init_streamInference = __esm({
|
|
|
12803
12896
|
payload: { input: msgText(message[message.length - 1].content) }
|
|
12804
12897
|
// ★ 多模态:trace 只记文本视图
|
|
12805
12898
|
});
|
|
12806
|
-
console.log(`[DSC-DIAG] streamInference round ${round} \u5B8C\u6210: content=${contentBuf.length}chars reasoning=${reasoningBuf.length}chars toolCalls=${toolCallsBuf.size}`);
|
|
12807
12899
|
return { kind: "completed", assistantMessage, usage: lastUsage };
|
|
12808
12900
|
} catch (error) {
|
|
12809
12901
|
if (signal?.aborted) {
|
|
@@ -12817,7 +12909,7 @@ var init_streamInference = __esm({
|
|
|
12817
12909
|
payload: { input: msgText(message[message.length - 1].content), output: err.message }
|
|
12818
12910
|
// ★ 多模态:文本视图
|
|
12819
12911
|
});
|
|
12820
|
-
console.
|
|
12912
|
+
console.error(`\u274C \u63A8\u7406\u5931\u8D25\uFF08round ${round}\uFF09\uFF1A${err.message}`);
|
|
12821
12913
|
return { kind: "error", error: err };
|
|
12822
12914
|
}
|
|
12823
12915
|
};
|
|
@@ -13074,6 +13166,70 @@ ${PLAN_REJECT_TEXT(planRejectCount)}` };
|
|
|
13074
13166
|
}
|
|
13075
13167
|
});
|
|
13076
13168
|
|
|
13169
|
+
// ../core/src/config/prices.ts
|
|
13170
|
+
var MODEL_PRICES, PRICES_VERIFIED_AT, PRICES_STALE_DAYS, pricesAgeDays, isBeijingPeak, envPrice, ENV_OVERRIDE, priceFor, calcCostYuan;
|
|
13171
|
+
var init_prices = __esm({
|
|
13172
|
+
"../core/src/config/prices.ts"() {
|
|
13173
|
+
"use strict";
|
|
13174
|
+
MODEL_PRICES = {
|
|
13175
|
+
"deepseek-flash": {
|
|
13176
|
+
idle: { input: 1, output: 4, cacheHit: 0.02 },
|
|
13177
|
+
peak: { input: 2, output: 8, cacheHit: 0.04 }
|
|
13178
|
+
},
|
|
13179
|
+
// 官网脚注明示旧名按 Flash 价格计费(2026-10-19 核实),非猜测——与 flash 同价条目
|
|
13180
|
+
"deepseek-flash-vision-exp": {
|
|
13181
|
+
idle: { input: 1, output: 4, cacheHit: 0.02 },
|
|
13182
|
+
peak: { input: 2, output: 8, cacheHit: 0.04 }
|
|
13183
|
+
},
|
|
13184
|
+
"deepseek-v4-pro": {
|
|
13185
|
+
idle: { input: 4.5, output: 13.5, cacheHit: 0.15 },
|
|
13186
|
+
peak: { input: 9, output: 27, cacheHit: 0.3 }
|
|
13187
|
+
}
|
|
13188
|
+
};
|
|
13189
|
+
PRICES_VERIFIED_AT = "2026-10-19";
|
|
13190
|
+
PRICES_STALE_DAYS = 30;
|
|
13191
|
+
pricesAgeDays = () => Math.max(0, Math.floor((Date.now() - Date.parse(`${PRICES_VERIFIED_AT}T00:00:00Z`)) / 864e5));
|
|
13192
|
+
isBeijingPeak = (ts2 = /* @__PURE__ */ new Date()) => {
|
|
13193
|
+
const bj = new Date(ts2.getTime() + 8 * 36e5);
|
|
13194
|
+
const day = bj.getUTCDay();
|
|
13195
|
+
if (day === 0 || day === 6) return false;
|
|
13196
|
+
const h = bj.getUTCHours();
|
|
13197
|
+
return h >= 9 && h < 12 || h >= 14 && h < 18;
|
|
13198
|
+
};
|
|
13199
|
+
envPrice = (name) => {
|
|
13200
|
+
const raw = process.env[name];
|
|
13201
|
+
if (!raw) return void 0;
|
|
13202
|
+
const n = Number(raw);
|
|
13203
|
+
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
13204
|
+
};
|
|
13205
|
+
ENV_OVERRIDE = (() => {
|
|
13206
|
+
const input = envPrice("DEEP_SEEK_PRICE_INPUT");
|
|
13207
|
+
const output = envPrice("DEEP_SEEK_PRICE_OUTPUT");
|
|
13208
|
+
const cacheHit = envPrice("DEEP_SEEK_PRICE_CACHEHIT");
|
|
13209
|
+
if (input === void 0 && output === void 0 && cacheHit === void 0) return null;
|
|
13210
|
+
return { input, output, cacheHit };
|
|
13211
|
+
})();
|
|
13212
|
+
priceFor = (model, ts2) => {
|
|
13213
|
+
const tier = MODEL_PRICES[model];
|
|
13214
|
+
const base = tier ? isBeijingPeak(ts2 ?? /* @__PURE__ */ new Date()) ? tier.peak : tier.idle : void 0;
|
|
13215
|
+
if (!ENV_OVERRIDE) return base ?? null;
|
|
13216
|
+
const input = ENV_OVERRIDE.input ?? base?.input;
|
|
13217
|
+
const output = ENV_OVERRIDE.output ?? base?.output;
|
|
13218
|
+
const cacheHit = ENV_OVERRIDE.cacheHit ?? base?.cacheHit;
|
|
13219
|
+
if (input === void 0 || output === void 0 || cacheHit === void 0) return null;
|
|
13220
|
+
return { input, output, cacheHit };
|
|
13221
|
+
};
|
|
13222
|
+
calcCostYuan = (model, u, ts2) => {
|
|
13223
|
+
const p = priceFor(model, ts2);
|
|
13224
|
+
if (!p) return null;
|
|
13225
|
+
const cached2 = Math.max(0, u.cachedTokens ?? 0);
|
|
13226
|
+
const miss = Math.max(0, (u.promptTokens ?? 0) - cached2);
|
|
13227
|
+
const completion = Math.max(0, u.completionTokens ?? 0);
|
|
13228
|
+
return (miss * p.input + cached2 * p.cacheHit + completion * p.output) / 1e6;
|
|
13229
|
+
};
|
|
13230
|
+
}
|
|
13231
|
+
});
|
|
13232
|
+
|
|
13077
13233
|
// ../core/src/agent/costRelay.ts
|
|
13078
13234
|
var createCostRelay;
|
|
13079
13235
|
var init_costRelay = __esm({
|
|
@@ -13102,6 +13258,99 @@ var init_costRelay = __esm({
|
|
|
13102
13258
|
}
|
|
13103
13259
|
});
|
|
13104
13260
|
|
|
13261
|
+
// ../core/src/agent/runLedger.ts
|
|
13262
|
+
var BUDGET_HARD_LIMIT_RATIO, roundYuan6, createRunLedger;
|
|
13263
|
+
var init_runLedger = __esm({
|
|
13264
|
+
"../core/src/agent/runLedger.ts"() {
|
|
13265
|
+
"use strict";
|
|
13266
|
+
init_prices();
|
|
13267
|
+
init_costRelay();
|
|
13268
|
+
init_client();
|
|
13269
|
+
BUDGET_HARD_LIMIT_RATIO = 1.2;
|
|
13270
|
+
roundYuan6 = (y) => Math.round(y * 1e6) / 1e6;
|
|
13271
|
+
createRunLedger = (opts) => {
|
|
13272
|
+
let budgetSpentYuan = 0;
|
|
13273
|
+
let usageSum;
|
|
13274
|
+
let costYuanAcc = 0;
|
|
13275
|
+
let costKnown = true;
|
|
13276
|
+
let toolCostYuanAcc = 0;
|
|
13277
|
+
let auxCostYuanAcc = 0;
|
|
13278
|
+
let subCostYuanAcc = 0;
|
|
13279
|
+
const relay = createCostRelay(opts.costSink);
|
|
13280
|
+
const addUsage = (u) => {
|
|
13281
|
+
if (!u) return;
|
|
13282
|
+
usageSum = {
|
|
13283
|
+
prompt_tokens: (usageSum?.prompt_tokens ?? 0) + (u.prompt_tokens ?? 0),
|
|
13284
|
+
completion_tokens: (usageSum?.completion_tokens ?? 0) + (u.completion_tokens ?? 0),
|
|
13285
|
+
total_tokens: (usageSum?.total_tokens ?? 0) + (u.total_tokens ?? 0),
|
|
13286
|
+
cached_tokens: (usageSum?.cached_tokens ?? 0) + (u.cached_tokens ?? 0)
|
|
13287
|
+
};
|
|
13288
|
+
const cost = calcCostYuan(opts.model, { promptTokens: u.prompt_tokens, completionTokens: u.completion_tokens, cachedTokens: u.cached_tokens });
|
|
13289
|
+
if (cost == null) costKnown = false;
|
|
13290
|
+
else {
|
|
13291
|
+
costYuanAcc += cost;
|
|
13292
|
+
budgetSpentYuan += cost;
|
|
13293
|
+
}
|
|
13294
|
+
};
|
|
13295
|
+
const addToolCost = (yuan) => {
|
|
13296
|
+
if (!Number.isFinite(yuan) || yuan <= 0) return;
|
|
13297
|
+
toolCostYuanAcc += yuan;
|
|
13298
|
+
budgetSpentYuan += yuan;
|
|
13299
|
+
};
|
|
13300
|
+
const reportAuxUsage = (usage, kind) => {
|
|
13301
|
+
if (usage) {
|
|
13302
|
+
const cost = calcCostYuan(AUX_MODEL_NAME, { promptTokens: usage.prompt_tokens, completionTokens: usage.completion_tokens, cachedTokens: usage.cached_tokens });
|
|
13303
|
+
if (cost != null && Number.isFinite(cost) && cost > 0) {
|
|
13304
|
+
auxCostYuanAcc += cost;
|
|
13305
|
+
budgetSpentYuan += cost;
|
|
13306
|
+
}
|
|
13307
|
+
}
|
|
13308
|
+
try {
|
|
13309
|
+
opts.onAuxUsage?.(usage, kind);
|
|
13310
|
+
} catch {
|
|
13311
|
+
}
|
|
13312
|
+
};
|
|
13313
|
+
const reportSubCost = (yuan) => {
|
|
13314
|
+
if (Number.isFinite(yuan) && yuan > 0) {
|
|
13315
|
+
budgetSpentYuan += yuan;
|
|
13316
|
+
subCostYuanAcc += yuan;
|
|
13317
|
+
}
|
|
13318
|
+
};
|
|
13319
|
+
const snapshot = () => opts.budgetYuan != null ? { spent: budgetSpentYuan, budget: opts.budgetYuan } : null;
|
|
13320
|
+
return {
|
|
13321
|
+
addUsage,
|
|
13322
|
+
addToolCost,
|
|
13323
|
+
reportAuxUsage,
|
|
13324
|
+
reportSubCost,
|
|
13325
|
+
/** 预算 soft 判定读数(nudge 管线消费):未武装返回 null。O(1) 闭包读数。 */
|
|
13326
|
+
getBudgetStatus: snapshot,
|
|
13327
|
+
/** 预算硬线判定(E2):spent >= budget×1.2(>= 语义与收拢前逐字节等价,恰 1.2× 即触发)。
|
|
13328
|
+
* 自武装探测(inheritedBudgetCheck 兜底)与轮边界硬截断共用同一判定。 */
|
|
13329
|
+
overHardLimit: () => opts.budgetYuan != null && budgetSpentYuan >= opts.budgetYuan * BUDGET_HARD_LIMIT_RATIO,
|
|
13330
|
+
/** 子 run 成本中继 flush:基数=预算圈实时读数(子树完整口径,文件头★中继段)。主 run 无 sink 时 no-op。 */
|
|
13331
|
+
flushRelay: () => relay.flush(budgetSpentYuan),
|
|
13332
|
+
/** run.end 事件行与 receipt token 段共用的用量合计快照。 */
|
|
13333
|
+
usageSummary: () => usageSum,
|
|
13334
|
+
/** 预算读数快照:硬截断 final 文案金额源。未武装=null(调用方结构上只在已武装分支取,勿 ?? 0 兜底)。 */
|
|
13335
|
+
budgetSnapshot: snapshot,
|
|
13336
|
+
/** usageLog 落盘字段(recordUsageRun 入参金额段;costYuan 无价=undefined、各账 ≤0 省略——自动缺省容错)。 */
|
|
13337
|
+
usageLogFields: () => ({
|
|
13338
|
+
costYuan: costKnown ? roundYuan6(costYuanAcc) : void 0,
|
|
13339
|
+
toolCostYuan: toolCostYuanAcc > 0 ? roundYuan6(toolCostYuanAcc) : void 0,
|
|
13340
|
+
auxCostYuan: auxCostYuanAcc > 0 ? roundYuan6(auxCostYuanAcc) : void 0
|
|
13341
|
+
}),
|
|
13342
|
+
/** run.receipt 结算单金额段:costYuan 无价=null(显式「不知钱」,绝不编数);各账 ≤0 省略字段。 */
|
|
13343
|
+
receiptFields: () => ({
|
|
13344
|
+
costYuan: costKnown ? roundYuan6(costYuanAcc) : null,
|
|
13345
|
+
toolCostYuan: toolCostYuanAcc > 0 ? roundYuan6(toolCostYuanAcc) : void 0,
|
|
13346
|
+
auxCostYuan: auxCostYuanAcc > 0 ? roundYuan6(auxCostYuanAcc) : void 0,
|
|
13347
|
+
subCostYuan: subCostYuanAcc > 0 ? roundYuan6(subCostYuanAcc) : void 0
|
|
13348
|
+
})
|
|
13349
|
+
};
|
|
13350
|
+
};
|
|
13351
|
+
}
|
|
13352
|
+
});
|
|
13353
|
+
|
|
13105
13354
|
// ../core/src/observability/usageLog.ts
|
|
13106
13355
|
import fs34 from "fs/promises";
|
|
13107
13356
|
import path37 from "path";
|
|
@@ -13209,106 +13458,323 @@ var init_usageLog = __esm({
|
|
|
13209
13458
|
}
|
|
13210
13459
|
});
|
|
13211
13460
|
|
|
13212
|
-
// ../core/src/
|
|
13213
|
-
|
|
13214
|
-
|
|
13215
|
-
|
|
13461
|
+
// ../core/src/observability/store.ts
|
|
13462
|
+
import path38 from "path";
|
|
13463
|
+
import fs35 from "fs/promises";
|
|
13464
|
+
var getTraceDirPath, getTracePath, tracePathCache, ensuredTraceDirs, ensureTraceDir, getGlobalClockPath, getTraceStorePath;
|
|
13465
|
+
var init_store3 = __esm({
|
|
13466
|
+
"../core/src/observability/store.ts"() {
|
|
13216
13467
|
"use strict";
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
|
|
13222
|
-
|
|
13223
|
-
"deepseek-flash-vision-exp": {
|
|
13224
|
-
idle: { input: 1, output: 4, cacheHit: 0.02 },
|
|
13225
|
-
peak: { input: 2, output: 8, cacheHit: 0.04 }
|
|
13226
|
-
},
|
|
13227
|
-
"deepseek-v4-pro": {
|
|
13228
|
-
idle: { input: 4.5, output: 13.5, cacheHit: 0.15 },
|
|
13229
|
-
peak: { input: 9, output: 27, cacheHit: 0.3 }
|
|
13230
|
-
}
|
|
13468
|
+
init_config();
|
|
13469
|
+
init_traceCalculate();
|
|
13470
|
+
init_common();
|
|
13471
|
+
getTraceDirPath = (mainTraceId) => {
|
|
13472
|
+
assertSafeSessionId(mainTraceId, "traceId");
|
|
13473
|
+
return path38.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
|
|
13231
13474
|
};
|
|
13232
|
-
|
|
13233
|
-
|
|
13234
|
-
pricesAgeDays = () => Math.max(0, Math.floor((Date.now() - Date.parse(`${PRICES_VERIFIED_AT}T00:00:00Z`)) / 864e5));
|
|
13235
|
-
isBeijingPeak = (ts2 = /* @__PURE__ */ new Date()) => {
|
|
13236
|
-
const bj = new Date(ts2.getTime() + 8 * 36e5);
|
|
13237
|
-
const day = bj.getUTCDay();
|
|
13238
|
-
if (day === 0 || day === 6) return false;
|
|
13239
|
-
const h = bj.getUTCHours();
|
|
13240
|
-
return h >= 9 && h < 12 || h >= 14 && h < 18;
|
|
13475
|
+
getTracePath = () => {
|
|
13476
|
+
return path38.join(appConfig.dataDir, "trace");
|
|
13241
13477
|
};
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
const
|
|
13246
|
-
|
|
13478
|
+
tracePathCache = /* @__PURE__ */ new Map();
|
|
13479
|
+
ensuredTraceDirs = /* @__PURE__ */ new Set();
|
|
13480
|
+
ensureTraceDir = async (mainTraceId) => {
|
|
13481
|
+
const dir = getTraceDirPath(mainTraceId);
|
|
13482
|
+
if (ensuredTraceDirs.has(dir)) return;
|
|
13483
|
+
await fs35.mkdir(dir, { recursive: true });
|
|
13484
|
+
ensuredTraceDirs.add(dir);
|
|
13247
13485
|
};
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
const output = envPrice("DEEP_SEEK_PRICE_OUTPUT");
|
|
13251
|
-
const cacheHit = envPrice("DEEP_SEEK_PRICE_CACHEHIT");
|
|
13252
|
-
if (input === void 0 && output === void 0 && cacheHit === void 0) return null;
|
|
13253
|
-
return { input, output, cacheHit };
|
|
13254
|
-
})();
|
|
13255
|
-
priceFor = (model, ts2) => {
|
|
13256
|
-
const tier = MODEL_PRICES[model];
|
|
13257
|
-
const base = tier ? isBeijingPeak(ts2 ?? /* @__PURE__ */ new Date()) ? tier.peak : tier.idle : void 0;
|
|
13258
|
-
if (!ENV_OVERRIDE) return base ?? null;
|
|
13259
|
-
const input = ENV_OVERRIDE.input ?? base?.input;
|
|
13260
|
-
const output = ENV_OVERRIDE.output ?? base?.output;
|
|
13261
|
-
const cacheHit = ENV_OVERRIDE.cacheHit ?? base?.cacheHit;
|
|
13262
|
-
if (input === void 0 || output === void 0 || cacheHit === void 0) return null;
|
|
13263
|
-
return { input, output, cacheHit };
|
|
13486
|
+
getGlobalClockPath = () => {
|
|
13487
|
+
return path38.join(getTracePath(), "trace-cleanup-clock.json");
|
|
13264
13488
|
};
|
|
13265
|
-
|
|
13266
|
-
|
|
13267
|
-
|
|
13268
|
-
const cached2 =
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13489
|
+
getTraceStorePath = async (mainTraceId) => {
|
|
13490
|
+
assertSafeSessionId(mainTraceId, "traceId");
|
|
13491
|
+
const rootId = getFileName(mainTraceId);
|
|
13492
|
+
const cached2 = tracePathCache.get(rootId);
|
|
13493
|
+
if (cached2) return cached2;
|
|
13494
|
+
await ensureTraceDir(rootId);
|
|
13495
|
+
const dir = getTraceDirPath(rootId);
|
|
13496
|
+
const files = await fs35.readdir(dir);
|
|
13497
|
+
const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
|
|
13498
|
+
let fileName = "";
|
|
13499
|
+
if (existedFile) {
|
|
13500
|
+
fileName = existedFile;
|
|
13501
|
+
} else {
|
|
13502
|
+
const todayStr = getTodayDateString();
|
|
13503
|
+
fileName = `trace-${todayStr}__${rootId}.jsonl`;
|
|
13504
|
+
}
|
|
13505
|
+
const resolved = path38.join(dir, fileName);
|
|
13506
|
+
tracePathCache.set(rootId, resolved);
|
|
13507
|
+
return resolved;
|
|
13272
13508
|
};
|
|
13273
13509
|
}
|
|
13274
13510
|
});
|
|
13275
13511
|
|
|
13276
|
-
// ../core/src/
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
const
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13512
|
+
// ../core/src/observability/trace.ts
|
|
13513
|
+
import fs36 from "fs/promises";
|
|
13514
|
+
import path39 from "path";
|
|
13515
|
+
async function emitTrace(base) {
|
|
13516
|
+
const event = {
|
|
13517
|
+
sessionId: base.sessionId,
|
|
13518
|
+
parentId: base.parentId,
|
|
13519
|
+
eventType: base.eventType,
|
|
13520
|
+
timestamp: base.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
13521
|
+
usage: base.usage,
|
|
13522
|
+
payload: base.payload,
|
|
13523
|
+
metadata: {
|
|
13524
|
+
...base.metadata || {}
|
|
13286
13525
|
}
|
|
13287
13526
|
};
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
|
|
13296
|
-
|
|
13297
|
-
|
|
13298
|
-
|
|
13299
|
-
|
|
13300
|
-
|
|
13301
|
-
|
|
13302
|
-
|
|
13303
|
-
|
|
13304
|
-
|
|
13305
|
-
|
|
13306
|
-
|
|
13307
|
-
|
|
13308
|
-
|
|
13527
|
+
if (event.payload) {
|
|
13528
|
+
if (typeof event.payload.input === "string") event.payload.input = truncateTracePayload(event.payload.input);
|
|
13529
|
+
if (typeof event.payload.output === "string") event.payload.output = truncateTracePayload(event.payload.output);
|
|
13530
|
+
}
|
|
13531
|
+
try {
|
|
13532
|
+
await appendTraceEvent(event);
|
|
13533
|
+
} catch (error) {
|
|
13534
|
+
console.warn("\u26A0\uFE0F [Trace] \u4E8B\u4EF6\u843D\u76D8\u5931\u8D25\uFF0C\u5DF2\u9632\u5FA1\u6027\u8DF3\u8FC7\uFF08\u4E0D\u5F71\u54CD\u4E3B\u4E1A\u52A1\uFF09:", error);
|
|
13535
|
+
}
|
|
13536
|
+
}
|
|
13537
|
+
async function appendTraceEvent(event) {
|
|
13538
|
+
const line = JSON.stringify(event) + "\n";
|
|
13539
|
+
const arr = traceBuf.get(event.sessionId);
|
|
13540
|
+
if (arr) arr.push(line);
|
|
13541
|
+
else traceBuf.set(event.sessionId, [line]);
|
|
13542
|
+
if (needImmediateFlush(event)) {
|
|
13543
|
+
await flushTraceBuffer(event.sessionId);
|
|
13544
|
+
return;
|
|
13545
|
+
}
|
|
13546
|
+
if ((traceBuf.get(event.sessionId)?.length ?? 0) >= TRACE_BATCH_LINES) {
|
|
13547
|
+
await flushTraceBuffer(event.sessionId);
|
|
13548
|
+
return;
|
|
13549
|
+
}
|
|
13550
|
+
scheduleTraceTimer(event.sessionId);
|
|
13551
|
+
}
|
|
13552
|
+
async function maybeCleanupAfterAppend(sessionId) {
|
|
13553
|
+
if (cleanupInProgress2) return;
|
|
13554
|
+
cleanupInProgress2 = true;
|
|
13555
|
+
try {
|
|
13556
|
+
await ensureClockLoaded2();
|
|
13557
|
+
const now = Date.now();
|
|
13558
|
+
const isTimeExpired = now - diskLastCleanupAt2 > CLEANUP_INTERVAL_MS2;
|
|
13559
|
+
const isSizeOverflow = workspaceTraceBytes > MAX_TRACE_FOLDER_BYTES;
|
|
13560
|
+
if (!isTimeExpired && !isSizeOverflow) return;
|
|
13561
|
+
if (isSizeOverflow && !isTimeExpired && now - lastSizeCleanupAt2 < SIZE_CLEANUP_COOLDOWN_MS2) {
|
|
13562
|
+
return;
|
|
13563
|
+
}
|
|
13564
|
+
const reason = isTimeExpired && isSizeOverflow ? "\u5BB9\u91CF+\u65F6\u95F4\u53CC\u95F8" : isSizeOverflow ? "\u5BB9\u91CF\u8D8A\u8FC750MB\u5927\u95F8" : "3\u5929\u51B7\u5374\u5468\u671F\u5DF2\u6EE1";
|
|
13565
|
+
console.log(`\u{1F9F9} [Trace\u8FD0\u7EF4] \u89E6\u53D1\u81EA\u9002\u5E94\u6E05\u7406\uFF08\u539F\u56E0: ${reason}\uFF09`);
|
|
13566
|
+
let deletedCount = 0;
|
|
13567
|
+
deletedCount += await cleanupOldTraceFiles();
|
|
13568
|
+
workspaceTraceBytes = await getDirBytes(getTracePath());
|
|
13569
|
+
if (workspaceTraceBytes > MAX_TRACE_FOLDER_BYTES) {
|
|
13570
|
+
const targetBytes = Math.floor(MAX_TRACE_FOLDER_BYTES * SIZE_RECLAIM_TARGET_RATIO2);
|
|
13571
|
+
deletedCount += await evictOldestForSize2(targetBytes);
|
|
13572
|
+
workspaceTraceBytes = await getDirBytes(getTracePath());
|
|
13573
|
+
}
|
|
13574
|
+
lastSizeCleanupAt2 = now;
|
|
13575
|
+
diskLastCleanupAt2 = now;
|
|
13576
|
+
const clockPath = getGlobalClockPath();
|
|
13577
|
+
await fs36.mkdir(path39.dirname(clockPath), { recursive: true });
|
|
13578
|
+
await fs36.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
|
|
13579
|
+
if (deletedCount > 0) {
|
|
13580
|
+
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`);
|
|
13581
|
+
}
|
|
13582
|
+
} catch (error) {
|
|
13583
|
+
console.warn("\u26A0\uFE0F [Trace\u8FD0\u7EF4] \u81EA\u52A8\u6E05\u7406\u53D1\u751F\u8F7B\u5FAE\u5F02\u5E38\uFF0C\u5DF2\u9632\u5FA1\u6027\u8DF3\u8FC7:", error);
|
|
13584
|
+
} finally {
|
|
13585
|
+
cleanupInProgress2 = false;
|
|
13586
|
+
}
|
|
13587
|
+
}
|
|
13588
|
+
async function cleanupOldTraceFiles() {
|
|
13589
|
+
const dir = getTracePath();
|
|
13590
|
+
const retentionDays = Math.max(1, appConfig.traceRetentionDays || 7);
|
|
13591
|
+
const cutoff = /* @__PURE__ */ new Date();
|
|
13592
|
+
cutoff.setHours(0, 0, 0, 0);
|
|
13593
|
+
cutoff.setDate(cutoff.getDate() - retentionDays);
|
|
13594
|
+
const now = Date.now();
|
|
13595
|
+
let deleted = 0;
|
|
13596
|
+
let relativePaths;
|
|
13597
|
+
try {
|
|
13598
|
+
relativePaths = await fs36.readdir(dir, { recursive: true });
|
|
13599
|
+
} catch {
|
|
13600
|
+
return 0;
|
|
13601
|
+
}
|
|
13602
|
+
const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
13603
|
+
for (const relativePath of relativePaths) {
|
|
13604
|
+
const fileName = path39.basename(relativePath);
|
|
13605
|
+
const m = fileName.match(re);
|
|
13606
|
+
if (!m) continue;
|
|
13607
|
+
const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
|
|
13608
|
+
if (fileBornDay >= cutoff) continue;
|
|
13609
|
+
const fullPath = path39.join(dir, relativePath);
|
|
13610
|
+
try {
|
|
13611
|
+
const st = await fs36.stat(fullPath);
|
|
13612
|
+
if (now - st.mtimeMs < ACTIVE_GRACE_MS2) continue;
|
|
13613
|
+
await fs36.unlink(fullPath);
|
|
13614
|
+
deleted += 1;
|
|
13615
|
+
} catch {
|
|
13616
|
+
}
|
|
13617
|
+
}
|
|
13618
|
+
return deleted;
|
|
13619
|
+
}
|
|
13620
|
+
async function evictOldestForSize2(targetBytes) {
|
|
13621
|
+
const dir = getTracePath();
|
|
13622
|
+
let relativePaths;
|
|
13623
|
+
try {
|
|
13624
|
+
relativePaths = await fs36.readdir(dir, { recursive: true });
|
|
13625
|
+
} catch {
|
|
13626
|
+
return 0;
|
|
13627
|
+
}
|
|
13628
|
+
const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
13629
|
+
const candidates = [];
|
|
13630
|
+
for (const relativePath of relativePaths) {
|
|
13631
|
+
const fileName = path39.basename(relativePath);
|
|
13632
|
+
if (!re.test(fileName)) continue;
|
|
13633
|
+
try {
|
|
13634
|
+
const st = await fs36.stat(path39.join(dir, relativePath));
|
|
13635
|
+
candidates.push({ mtime: st.mtimeMs, fullPath: path39.join(dir, relativePath), size: st.size });
|
|
13636
|
+
} catch {
|
|
13637
|
+
}
|
|
13638
|
+
}
|
|
13639
|
+
candidates.sort((a, b) => a.mtime - b.mtime);
|
|
13640
|
+
let totalBytes = candidates.reduce((sum, c) => sum + c.size, 0);
|
|
13641
|
+
let deleted = 0;
|
|
13642
|
+
for (const c of candidates) {
|
|
13643
|
+
if (totalBytes <= targetBytes) break;
|
|
13644
|
+
try {
|
|
13645
|
+
await fs36.unlink(c.fullPath);
|
|
13646
|
+
totalBytes -= c.size;
|
|
13647
|
+
deleted += 1;
|
|
13648
|
+
} catch {
|
|
13649
|
+
}
|
|
13650
|
+
}
|
|
13651
|
+
if (deleted > 0) {
|
|
13652
|
+
console.warn(`\u26A0\uFE0F [Trace\u8FD0\u7EF4] \u5BB9\u91CF\u786C\u9A71\u9010\uFF1A\u8D8A\u8FC7\u6D3B\u8DC3\u4FDD\u62A4\u5F3A\u5220 ${deleted} \u4E2A\u6700\u65E7 trace \u6587\u4EF6\uFF08\u78C1\u76D8\u538B\u529B\u515C\u5E95\uFF09\u3002`);
|
|
13653
|
+
}
|
|
13654
|
+
return deleted;
|
|
13655
|
+
}
|
|
13656
|
+
var CLEANUP_INTERVAL_MS2, ACTIVE_GRACE_MS2, MAX_TRACE_FOLDER_BYTES, SIZE_RECLAIM_TARGET_RATIO2, SIZE_CLEANUP_COOLDOWN_MS2, workspaceTraceBytes, diskLastCleanupAt2, clockLoaded2, lastSizeCleanupAt2, cleanupInProgress2, TRACE_BATCH_LINES, TRACE_BATCH_MS, traceBuf, traceTimers, cleanupTriggerCount, needImmediateFlush, scheduleTraceTimer, flushTraceBuffer, ensureClockLoaded2, tracePayloadMaxChars, truncateTracePayload;
|
|
13657
|
+
var init_trace = __esm({
|
|
13658
|
+
"../core/src/observability/trace.ts"() {
|
|
13659
|
+
"use strict";
|
|
13660
|
+
init_config();
|
|
13661
|
+
init_store3();
|
|
13662
|
+
init_traceCalculate();
|
|
13663
|
+
CLEANUP_INTERVAL_MS2 = 3 * 24 * 60 * 60 * 1e3;
|
|
13664
|
+
ACTIVE_GRACE_MS2 = 24 * 60 * 60 * 1e3;
|
|
13665
|
+
MAX_TRACE_FOLDER_BYTES = 50 * 1024 * 1024;
|
|
13666
|
+
SIZE_RECLAIM_TARGET_RATIO2 = 0.8;
|
|
13667
|
+
SIZE_CLEANUP_COOLDOWN_MS2 = 60 * 1e3;
|
|
13668
|
+
workspaceTraceBytes = -1;
|
|
13669
|
+
diskLastCleanupAt2 = 0;
|
|
13670
|
+
clockLoaded2 = false;
|
|
13671
|
+
lastSizeCleanupAt2 = 0;
|
|
13672
|
+
cleanupInProgress2 = false;
|
|
13673
|
+
TRACE_BATCH_LINES = 50;
|
|
13674
|
+
TRACE_BATCH_MS = 200;
|
|
13675
|
+
traceBuf = /* @__PURE__ */ new Map();
|
|
13676
|
+
traceTimers = /* @__PURE__ */ new Map();
|
|
13677
|
+
cleanupTriggerCount = 0;
|
|
13678
|
+
needImmediateFlush = (ev) => ev.metadata?.ok === false || ev.eventType === "user.aborted" || ev.eventType === "tool.repeat_break" || ev.eventType === "session.end";
|
|
13679
|
+
scheduleTraceTimer = (sessionId) => {
|
|
13680
|
+
if (traceTimers.has(sessionId)) return;
|
|
13681
|
+
const t = setTimeout(() => {
|
|
13682
|
+
traceTimers.delete(sessionId);
|
|
13683
|
+
void flushTraceBuffer(sessionId);
|
|
13684
|
+
}, TRACE_BATCH_MS);
|
|
13685
|
+
t.unref?.();
|
|
13686
|
+
traceTimers.set(sessionId, t);
|
|
13687
|
+
};
|
|
13688
|
+
flushTraceBuffer = async (sessionId) => {
|
|
13689
|
+
const ids = sessionId !== void 0 ? [sessionId] : [...traceBuf.keys()];
|
|
13690
|
+
for (const id of ids) {
|
|
13691
|
+
const arr = traceBuf.get(id);
|
|
13692
|
+
if (!arr || arr.length === 0) {
|
|
13693
|
+
traceBuf.delete(id);
|
|
13694
|
+
continue;
|
|
13695
|
+
}
|
|
13696
|
+
traceBuf.set(id, []);
|
|
13697
|
+
const timer = traceTimers.get(id);
|
|
13698
|
+
if (timer) {
|
|
13699
|
+
clearTimeout(timer);
|
|
13700
|
+
traceTimers.delete(id);
|
|
13701
|
+
}
|
|
13702
|
+
try {
|
|
13703
|
+
const joined = arr.join("");
|
|
13704
|
+
const p = await getTraceStorePath(id);
|
|
13705
|
+
await fs36.appendFile(p, joined, "utf-8");
|
|
13706
|
+
if (workspaceTraceBytes < 0) {
|
|
13707
|
+
workspaceTraceBytes = await getDirBytes(getTracePath());
|
|
13708
|
+
}
|
|
13709
|
+
workspaceTraceBytes += Buffer.byteLength(joined, "utf-8");
|
|
13710
|
+
cleanupTriggerCount++;
|
|
13711
|
+
void maybeCleanupAfterAppend(id);
|
|
13712
|
+
} catch (error) {
|
|
13713
|
+
console.warn("\u26A0\uFE0F [Trace] \u6279\u91CF\u843D\u76D8\u5931\u8D25\uFF0C\u4E22\u5F03\u8BE5\u6279\uFF08\u4E0D\u5F71\u54CD\u4E3B\u4E1A\u52A1\uFF09:", error);
|
|
13714
|
+
}
|
|
13715
|
+
}
|
|
13716
|
+
};
|
|
13717
|
+
ensureClockLoaded2 = async () => {
|
|
13718
|
+
if (clockLoaded2) return;
|
|
13719
|
+
clockLoaded2 = true;
|
|
13720
|
+
try {
|
|
13721
|
+
const rawClock = await fs36.readFile(getGlobalClockPath(), "utf-8");
|
|
13722
|
+
diskLastCleanupAt2 = JSON.parse(rawClock).lastCleanupAt || 0;
|
|
13723
|
+
} catch {
|
|
13724
|
+
diskLastCleanupAt2 = 0;
|
|
13725
|
+
}
|
|
13726
|
+
};
|
|
13727
|
+
tracePayloadMaxChars = () => Number(process.env.TRACE_PAYLOAD_MAX_CHARS) || 2e3;
|
|
13728
|
+
truncateTracePayload = (s) => {
|
|
13729
|
+
const max = tracePayloadMaxChars();
|
|
13730
|
+
return s.length > max ? s.slice(0, max) + `\u2026[trace \u622A\u65AD ${s.length - max} \u5B57\u7B26\uFF08\u5171 ${s.length} \u5B57\u7B26\uFF09]` : s;
|
|
13731
|
+
};
|
|
13732
|
+
}
|
|
13733
|
+
});
|
|
13734
|
+
|
|
13735
|
+
// ../core/src/agent/runAgent.ts
|
|
13736
|
+
async function* runAgent(message, options) {
|
|
13737
|
+
const sessionId = options.sessionId;
|
|
13738
|
+
const runId = createUUID();
|
|
13739
|
+
const rawEvents = options.events;
|
|
13740
|
+
const events = async (base) => {
|
|
13741
|
+
try {
|
|
13742
|
+
await rawEvents({ ...base, metadata: { ...base.metadata, runId } });
|
|
13743
|
+
} catch (e) {
|
|
13744
|
+
console.warn("\u26A0\uFE0F \u57CB\u70B9\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u63A8\u7406\uFF09:", e instanceof Error ? e.message : e);
|
|
13745
|
+
}
|
|
13746
|
+
};
|
|
13747
|
+
const modelWindow = options.modelWindow;
|
|
13748
|
+
const signal = options.abortSignal;
|
|
13749
|
+
const depth = options.depth ?? 0;
|
|
13750
|
+
const cwd = options.cwd ?? process.cwd();
|
|
13751
|
+
const keepRecentUnits = options.keepRecentUnits;
|
|
13752
|
+
const compactRatio = options.compactRatio;
|
|
13753
|
+
const parentSystemPrompt = options.parentSystemPrompt;
|
|
13754
|
+
const effectiveModel = options.model?.trim() || MODEL_NAME;
|
|
13755
|
+
const { rawTools, cleanedToolSchemas, toolsTokens } = await prepareToolsAndInjections(message, options, events);
|
|
13756
|
+
let round = 0;
|
|
13757
|
+
let lastContent = "";
|
|
13758
|
+
let stopReason = "normal";
|
|
13759
|
+
let budgetTruncated = false;
|
|
13760
|
+
const MAX_AGENT_ROUNDS = 500;
|
|
13761
|
+
const firstPrompt = resolveFirstPrompt(message, options);
|
|
13762
|
+
const ledger = createRunLedger({
|
|
13763
|
+
model: effectiveModel,
|
|
13764
|
+
budgetYuan: depth === 0 && options.budgetYuan != null && options.budgetYuan > 0 ? options.budgetYuan : void 0,
|
|
13765
|
+
costSink: options.costSink,
|
|
13766
|
+
onAuxUsage: options.onAuxUsage
|
|
13767
|
+
});
|
|
13768
|
+
const reportAuxUsage = ledger.reportAuxUsage;
|
|
13769
|
+
const toolCostSink = process.env.DEEP_SEEK_TOOL_COST === "0" ? void 0 : ledger.addToolCost;
|
|
13770
|
+
let runCompactCount = 0;
|
|
13771
|
+
const nudges = createNudgeScheduler({
|
|
13772
|
+
firstPrompt,
|
|
13773
|
+
planMode: !!options.planMode,
|
|
13309
13774
|
noEarlyFinal: !!options.noEarlyFinal,
|
|
13310
13775
|
getContextUsage: () => ({ usedTokens: Math.round(estimateTokens(message) * calibRatio + toolsTokens), windowTokens: modelWindow }),
|
|
13311
|
-
getBudgetStatus:
|
|
13776
|
+
getBudgetStatus: ledger.getBudgetStatus
|
|
13777
|
+
// ★ E2 预算 soft 读数(闭包在账本内 O(1) 读数;未武装返回 null,管线自判)
|
|
13312
13778
|
});
|
|
13313
13779
|
const readTracker = /* @__PURE__ */ new Map();
|
|
13314
13780
|
const userDecisionSource = depth > 0 ? "spawn_agent" : "user";
|
|
@@ -13330,47 +13796,7 @@ async function* runAgent(message, options) {
|
|
|
13330
13796
|
let lastRealPromptTokens = persistedCalib.lastRealPromptTokens;
|
|
13331
13797
|
let lastCachedTokens = persistedCalib.lastCachedTokens;
|
|
13332
13798
|
const breaker = createRepeatBreaker({ sessionId, depth, llmDecisionSource, startTime, events });
|
|
13333
|
-
|
|
13334
|
-
let costYuanAcc = 0;
|
|
13335
|
-
let costKnown = true;
|
|
13336
|
-
const addUsage = (u) => {
|
|
13337
|
-
if (!u) return;
|
|
13338
|
-
usageSum = {
|
|
13339
|
-
prompt_tokens: (usageSum?.prompt_tokens ?? 0) + (u.prompt_tokens ?? 0),
|
|
13340
|
-
completion_tokens: (usageSum?.completion_tokens ?? 0) + (u.completion_tokens ?? 0),
|
|
13341
|
-
total_tokens: (usageSum?.total_tokens ?? 0) + (u.total_tokens ?? 0),
|
|
13342
|
-
cached_tokens: (usageSum?.cached_tokens ?? 0) + (u.cached_tokens ?? 0)
|
|
13343
|
-
};
|
|
13344
|
-
const cost = calcCostYuan(effectiveModel, { promptTokens: u.prompt_tokens, completionTokens: u.completion_tokens, cachedTokens: u.cached_tokens });
|
|
13345
|
-
if (cost == null) costKnown = false;
|
|
13346
|
-
else {
|
|
13347
|
-
costYuanAcc += cost;
|
|
13348
|
-
budgetSpentYuan += cost;
|
|
13349
|
-
}
|
|
13350
|
-
};
|
|
13351
|
-
let toolCostYuanAcc = 0;
|
|
13352
|
-
const addToolCost = (yuan) => {
|
|
13353
|
-
if (!Number.isFinite(yuan) || yuan <= 0) return;
|
|
13354
|
-
toolCostYuanAcc += yuan;
|
|
13355
|
-
budgetSpentYuan += yuan;
|
|
13356
|
-
};
|
|
13357
|
-
const toolCostSink = process.env.DEEP_SEEK_TOOL_COST === "0" ? void 0 : addToolCost;
|
|
13358
|
-
let auxCostYuanAcc = 0;
|
|
13359
|
-
const reportAuxUsage = (usage, kind) => {
|
|
13360
|
-
if (usage) {
|
|
13361
|
-
const cost = calcCostYuan(AUX_MODEL_NAME, { promptTokens: usage.prompt_tokens, completionTokens: usage.completion_tokens, cachedTokens: usage.cached_tokens });
|
|
13362
|
-
if (cost != null && Number.isFinite(cost) && cost > 0) {
|
|
13363
|
-
auxCostYuanAcc += cost;
|
|
13364
|
-
budgetSpentYuan += cost;
|
|
13365
|
-
}
|
|
13366
|
-
}
|
|
13367
|
-
try {
|
|
13368
|
-
options.onAuxUsage?.(usage, kind);
|
|
13369
|
-
} catch {
|
|
13370
|
-
}
|
|
13371
|
-
};
|
|
13372
|
-
const costRelay = createCostRelay(options.costSink);
|
|
13373
|
-
const inheritedBudgetCheck = options.budgetCheck ?? (depth === 0 && options.budgetYuan != null && options.budgetYuan > 0 ? () => budgetSpentYuan >= options.budgetYuan * 1.2 : void 0);
|
|
13799
|
+
const inheritedBudgetCheck = options.budgetCheck ?? (depth === 0 ? ledger.overHardLimit : void 0);
|
|
13374
13800
|
let planWriteRej = 0;
|
|
13375
13801
|
const toolCounts = {};
|
|
13376
13802
|
await appendEvent(sessionId, { dscEvent: "run.start", runId, depth });
|
|
@@ -13401,11 +13827,12 @@ async function* runAgent(message, options) {
|
|
|
13401
13827
|
yield { type: "final", text: lastContent || "\uFF08\u5DF2\u4E2D\u6B62\uFF09" };
|
|
13402
13828
|
return;
|
|
13403
13829
|
}
|
|
13404
|
-
if (depth === 0 &&
|
|
13830
|
+
if (depth === 0 && ledger.overHardLimit()) {
|
|
13831
|
+
const snap = ledger.budgetSnapshot();
|
|
13405
13832
|
stopReason = "limit";
|
|
13406
13833
|
budgetTruncated = true;
|
|
13407
13834
|
yield { type: "final", text: (lastContent || "") + `
|
|
13408
|
-
\uFF08\u{1F4B0} \u9884\u7B97\u622A\u65AD\uFF1A\u672C run \u5DF2\u82B1\u8D39 \xA5${
|
|
13835
|
+
\uFF08\u{1F4B0} \u9884\u7B97\u622A\u65AD\uFF1A\u672C run \u5DF2\u82B1\u8D39 \xA5${snap.spent.toFixed(3)} / \u9884\u7B97 \xA5${snap.budget.toFixed(3)}\u3002/budget \u8C03\u6574\u9884\u7B97\u540E\u56DE\u590D"\u7EE7\u7EED"\u5373\u53EF\u63A5\u7EED\u3002\uFF09` };
|
|
13409
13836
|
return;
|
|
13410
13837
|
}
|
|
13411
13838
|
if (depth > 0 && options.budgetCheck?.()) {
|
|
@@ -13494,12 +13921,12 @@ async function* runAgent(message, options) {
|
|
|
13494
13921
|
const estAtInfer = estimateTokens(message) + toolsTokens;
|
|
13495
13922
|
if (estAtInfer > 1e3) {
|
|
13496
13923
|
const observed = infResult.usage.prompt_tokens / estAtInfer;
|
|
13497
|
-
calibRatio = calibRatio *
|
|
13924
|
+
calibRatio = calibRatio * CALIB_EMA_KEEP + observed * CALIB_EMA_NEW;
|
|
13498
13925
|
}
|
|
13499
13926
|
lastRealPromptTokens = infResult.usage.prompt_tokens;
|
|
13500
13927
|
lastCachedTokens = infResult.usage.cached_tokens;
|
|
13501
13928
|
}
|
|
13502
|
-
addUsage(infResult.usage);
|
|
13929
|
+
ledger.addUsage(infResult.usage);
|
|
13503
13930
|
const assistantMessage = infResult.assistantMessage;
|
|
13504
13931
|
message.push(assistantMessage);
|
|
13505
13932
|
await appendMessage({ ...assistantMessage, sessionId });
|
|
@@ -13509,7 +13936,7 @@ async function* runAgent(message, options) {
|
|
|
13509
13936
|
if (!assistantMessage.tool_calls || assistantMessage.tool_calls.length === 0) {
|
|
13510
13937
|
await appendEvent(sessionId, { dscEvent: "round.end", runId, round, usage: infResult.usage });
|
|
13511
13938
|
emitContextUsage();
|
|
13512
|
-
|
|
13939
|
+
ledger.flushRelay();
|
|
13513
13940
|
const finalText = (typeof assistantMessage.content === "string" ? assistantMessage.content : "") || "";
|
|
13514
13941
|
const intercepted = nudges.interceptFinal(finalText, round);
|
|
13515
13942
|
if (intercepted) continue;
|
|
@@ -13559,14 +13986,9 @@ async function* runAgent(message, options) {
|
|
|
13559
13986
|
contextTokensEst: Math.round(estimateTokens(message) * calibRatio + toolsTokens),
|
|
13560
13987
|
readTracker,
|
|
13561
13988
|
// ★ P3-8:run 级读取追踪(同一引用透传,跨轮累计)
|
|
13562
|
-
// ★ 子 run 成本回灌(成本信任链第二环 E1):runSubagent 经 toolCtx.reportCost
|
|
13563
|
-
//
|
|
13564
|
-
reportCost:
|
|
13565
|
-
if (Number.isFinite(yuan) && yuan > 0) {
|
|
13566
|
-
budgetSpentYuan += yuan;
|
|
13567
|
-
subCostYuanAcc += yuan;
|
|
13568
|
-
}
|
|
13569
|
-
},
|
|
13989
|
+
// ★ 子 run 成本回灌(成本信任链第二环 E1):runSubagent 经 toolCtx.reportCost 把子 run 花费
|
|
13990
|
+
// 记进账本预算圈 + 展示账——父预算自动继承约束(守卫与分账语义在 runLedger.reportSubCost)。
|
|
13991
|
+
reportCost: ledger.reportSubCost,
|
|
13570
13992
|
// ★ 按次计费工具成本上报(DeepSeek Search/Fetch):web 工具经 toolCtx.toolCostSink 拿到闭包,
|
|
13571
13993
|
// 成功调用后按次上报进本 run 累计器。
|
|
13572
13994
|
toolCostSink,
|
|
@@ -13578,7 +14000,10 @@ async function* runAgent(message, options) {
|
|
|
13578
14000
|
nudges.notePlanWriteRejected(planWriteRej);
|
|
13579
14001
|
},
|
|
13580
14002
|
// ★ P1-5 子任务预算熔断:runSubagent 经 toolCtx.budgetCheck 拿到探测闭包,子 runAgent 每轮边界自检
|
|
13581
|
-
budgetCheck: inheritedBudgetCheck
|
|
14003
|
+
budgetCheck: inheritedBudgetCheck,
|
|
14004
|
+
// ★ A 批批级预算:主循环不设(undefined);仅并行批 ≥2 时由调度层浅拷贝下发(R4/R5:
|
|
14005
|
+
// required 字段,构造处显式对齐,漏写即 tsc 打红)
|
|
14006
|
+
batchBudgetChars: void 0
|
|
13582
14007
|
};
|
|
13583
14008
|
const scheduleResult = yield* scheduleToolCalls(assistantMessage, message, toolCallCtx);
|
|
13584
14009
|
if (scheduleResult.kind === "aborted") {
|
|
@@ -13591,7 +14016,7 @@ async function* runAgent(message, options) {
|
|
|
13591
14016
|
}
|
|
13592
14017
|
await appendEvent(sessionId, { dscEvent: "round.end", runId, round, usage: infResult.usage });
|
|
13593
14018
|
emitContextUsage();
|
|
13594
|
-
|
|
14019
|
+
ledger.flushRelay();
|
|
13595
14020
|
if (options.planMode && planWriteRej >= PLAN_REJECT_FORCE_AT) {
|
|
13596
14021
|
stopReason = "limit";
|
|
13597
14022
|
yield { type: "final", text: PLAN_REJECT_FORCE_FINAL_TEXT(planWriteRej) };
|
|
@@ -13615,10 +14040,15 @@ async function* runAgent(message, options) {
|
|
|
13615
14040
|
} catch {
|
|
13616
14041
|
}
|
|
13617
14042
|
try {
|
|
13618
|
-
await appendEvent(sessionId, { dscEvent: "run.end", runId, stopReason: signal?.aborted ? "aborted" : stopReason, rounds: round, usage:
|
|
14043
|
+
await appendEvent(sessionId, { dscEvent: "run.end", runId, stopReason: signal?.aborted ? "aborted" : stopReason, rounds: round, usage: ledger.usageSummary() });
|
|
13619
14044
|
} catch {
|
|
13620
14045
|
}
|
|
13621
14046
|
try {
|
|
14047
|
+
await flushTraceBuffer();
|
|
14048
|
+
} catch {
|
|
14049
|
+
}
|
|
14050
|
+
try {
|
|
14051
|
+
const us = ledger.usageSummary();
|
|
13622
14052
|
void recordUsageRun({
|
|
13623
14053
|
v: 1,
|
|
13624
14054
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -13629,40 +14059,33 @@ async function* runAgent(message, options) {
|
|
|
13629
14059
|
stopReason: signal?.aborted ? "aborted" : stopReason,
|
|
13630
14060
|
rounds: round,
|
|
13631
14061
|
durationMs: Math.round(performance.now() - startTime),
|
|
13632
|
-
promptTokens:
|
|
13633
|
-
completionTokens:
|
|
13634
|
-
totalTokens:
|
|
13635
|
-
cachedTokens:
|
|
13636
|
-
|
|
13637
|
-
|
|
13638
|
-
// 按次计费工具花费(Search/Fetch)
|
|
13639
|
-
auxCostYuan: auxCostYuanAcc > 0 ? Math.round(auxCostYuanAcc * 1e6) / 1e6 : void 0,
|
|
13640
|
-
// 辅助模型花费(压缩摘要+风险分类器,P0-2)
|
|
14062
|
+
promptTokens: us?.prompt_tokens,
|
|
14063
|
+
completionTokens: us?.completion_tokens,
|
|
14064
|
+
totalTokens: us?.total_tokens,
|
|
14065
|
+
cachedTokens: us?.cached_tokens,
|
|
14066
|
+
...ledger.usageLogFields(),
|
|
14067
|
+
// costYuan/toolCostYuan/auxCostYuan(口径与舍入在 runLedger)
|
|
13641
14068
|
tools: toolCounts
|
|
13642
14069
|
});
|
|
13643
14070
|
} catch {
|
|
13644
14071
|
}
|
|
13645
14072
|
try {
|
|
13646
|
-
|
|
14073
|
+
ledger.flushRelay();
|
|
13647
14074
|
} catch {
|
|
13648
14075
|
}
|
|
13649
14076
|
try {
|
|
13650
|
-
|
|
13651
|
-
|
|
14077
|
+
const us = ledger.usageSummary();
|
|
14078
|
+
if (depth === 0 && options.onUIEvent && us) {
|
|
14079
|
+
const prompt = us.prompt_tokens ?? 0;
|
|
13652
14080
|
options.onUIEvent({
|
|
13653
14081
|
type: "run.receipt",
|
|
13654
14082
|
rounds: round,
|
|
13655
14083
|
promptTokens: prompt,
|
|
13656
|
-
completionTokens:
|
|
13657
|
-
cachedTokens:
|
|
13658
|
-
cacheHitRate: prompt > 0 ? (
|
|
13659
|
-
|
|
13660
|
-
|
|
13661
|
-
// 按次计费工具花费(undefined 自动省略)
|
|
13662
|
-
auxCostYuan: auxCostYuanAcc > 0 ? Math.round(auxCostYuanAcc * 1e6) / 1e6 : void 0,
|
|
13663
|
-
// 辅助模型花费(压缩摘要+风险分类器;undefined 自动省略)
|
|
13664
|
-
subCostYuan: subCostYuanAcc > 0 ? Math.round(subCostYuanAcc * 1e6) / 1e6 : void 0,
|
|
13665
|
-
// ★ Q12:子 run 花费并列展示(展示层补偿;undefined 自动省略)
|
|
14084
|
+
completionTokens: us.completion_tokens ?? 0,
|
|
14085
|
+
cachedTokens: us.cached_tokens ?? 0,
|
|
14086
|
+
cacheHitRate: prompt > 0 ? (us.cached_tokens ?? 0) / prompt : 0,
|
|
14087
|
+
...ledger.receiptFields(),
|
|
14088
|
+
// costYuan(null=无价)/toolCostYuan/auxCostYuan/subCostYuan(口径与舍入在 runLedger)
|
|
13666
14089
|
durationMs: Math.round(performance.now() - startTime),
|
|
13667
14090
|
budgetTruncated: budgetTruncated || void 0
|
|
13668
14091
|
// 预算截断标注(E2;undefined 自动省略)
|
|
@@ -13683,7 +14106,7 @@ async function* runAgent(message, options) {
|
|
|
13683
14106
|
}
|
|
13684
14107
|
}
|
|
13685
14108
|
}
|
|
13686
|
-
var resolveFirstPrompt;
|
|
14109
|
+
var CALIB_EMA_KEEP, CALIB_EMA_NEW, resolveFirstPrompt;
|
|
13687
14110
|
var init_runAgent = __esm({
|
|
13688
14111
|
"../core/src/agent/runAgent.ts"() {
|
|
13689
14112
|
"use strict";
|
|
@@ -13700,11 +14123,12 @@ var init_runAgent = __esm({
|
|
|
13700
14123
|
init_toolScheduling();
|
|
13701
14124
|
init_streamInference();
|
|
13702
14125
|
init_agentNudges();
|
|
13703
|
-
|
|
14126
|
+
init_runLedger();
|
|
13704
14127
|
init_usageLog();
|
|
13705
|
-
|
|
14128
|
+
init_trace();
|
|
13706
14129
|
init_createModel();
|
|
13707
|
-
|
|
14130
|
+
CALIB_EMA_KEEP = 0.6;
|
|
14131
|
+
CALIB_EMA_NEW = 0.4;
|
|
13708
14132
|
resolveFirstPrompt = (message, options) => {
|
|
13709
14133
|
if ((options.depth ?? 0) !== 0) return "";
|
|
13710
14134
|
const explicit = options.currentUserText?.trim();
|
|
@@ -13721,7 +14145,7 @@ var init_runAgent = __esm({
|
|
|
13721
14145
|
});
|
|
13722
14146
|
|
|
13723
14147
|
// ../core/src/session/lineage.ts
|
|
13724
|
-
import
|
|
14148
|
+
import fs37 from "node:fs";
|
|
13725
14149
|
var parentOfSubsession, stringAncestorsOf, readForkedFromSync, lineageClosureOf, ownerCanApprove;
|
|
13726
14150
|
var init_lineage = __esm({
|
|
13727
14151
|
"../core/src/session/lineage.ts"() {
|
|
@@ -13744,7 +14168,7 @@ var init_lineage = __esm({
|
|
|
13744
14168
|
};
|
|
13745
14169
|
readForkedFromSync = (sessionId) => {
|
|
13746
14170
|
try {
|
|
13747
|
-
const raw =
|
|
14171
|
+
const raw = fs37.readFileSync(getStatePath(sessionId), "utf-8");
|
|
13748
14172
|
const v = JSON.parse(raw)?.forkedFrom;
|
|
13749
14173
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
13750
14174
|
} catch {
|
|
@@ -13873,6 +14297,7 @@ var init_subagent = __esm({
|
|
|
13873
14297
|
sessionId: ""
|
|
13874
14298
|
};
|
|
13875
14299
|
}
|
|
14300
|
+
const SUBAGENT_REPORT_REQ = `\u3010\u6C47\u62A5\u8981\u6C42\u3011\u6700\u7EC8\u6C47\u62A5\u63A7\u5236\u5728\u4E00\u5C4F\u5185\uFF1A\u5DF2\u5B8C\u6210/\u6539\u52A8\u70B9\uFF08\u6587\u4EF6\u8DEF\u5F84\uFF09/\u9A8C\u8BC1\u7ED3\u679C/\u672A\u5B8C\u6210\u9879\u3002\u4E0D\u8981\u590D\u8FF0\u8FC7\u7A0B\u4E0E\u5DE5\u5177\u8F93\u51FA\u2014\u2014\u7236\u7EA7\u53EF\u76F4\u63A5\u7ECF resume \u8FFD\u95EE\u7EC6\u8282\u3002`;
|
|
13876
14301
|
const subSystem = manifest ? [
|
|
13877
14302
|
`# \u5B50 Agent \u8EAB\u4EFD\uFF1A${manifest.name}`,
|
|
13878
14303
|
manifest.body,
|
|
@@ -13881,7 +14306,8 @@ var init_subagent = __esm({
|
|
|
13881
14306
|
`\u5F53\u524D\u6240\u5904\u7684\u4EFB\u52A1\u6267\u884C\u5D4C\u5957\u6DF1\u5EA6: Depth ${ctx.depth + 1} / ${MAX_AGENT_DEPTH}`,
|
|
13882
14307
|
`
|
|
13883
14308
|
# \u3010\u7EE7\u627F\u7684\u5168\u5C40\u4EE3\u7801\u89C4\u8303\u3011`,
|
|
13884
|
-
parentSystemPrompt
|
|
14309
|
+
parentSystemPrompt,
|
|
14310
|
+
SUBAGENT_REPORT_REQ
|
|
13885
14311
|
].filter(Boolean).join("\n") : [
|
|
13886
14312
|
`# \u4EFB\u52A1\u4E0A\u4E0B\u6587`,
|
|
13887
14313
|
`\u5F53\u524D\u6240\u5904\u7684\u4EFB\u52A1\u6267\u884C\u5D4C\u5957\u6DF1\u5EA6: Depth ${ctx.depth + 1} / ${MAX_AGENT_DEPTH}`,
|
|
@@ -13890,7 +14316,8 @@ var init_subagent = __esm({
|
|
|
13890
14316
|
`\u4F60\u76F4\u63A5\u5171\u4EAB\u5E76\u64CD\u4F5C\u672C\u5730\u6587\u4EF6\u7CFB\u7EDF\u3002\u5F53\u4F60\u5BF9\u6587\u4EF6\u5168\u91CF\u5199\u5165\u6216\u5C40\u90E8\u4FEE\u6539\u65F6\uFF0C\u5FC5\u987B\u786E\u4FDD\u64CD\u4F5C\u7684\u7EDD\u5BF9\u7CBE\u51C6\u3002\u5B8C\u6210\u6307\u5B9A\u5B50\u4EFB\u52A1\u540E\uFF0C\u8BF7\u4F7F\u7528\u6700\u7EC8\u7684\u6587\u672C\u603B\u7ED3\u5411\u7236\u7EA7 Agent \u4EA4\u4ED8\u7ED3\u679C\u3002`,
|
|
13891
14317
|
`
|
|
13892
14318
|
# \u3010\u7EE7\u627F\u7684\u5168\u5C40\u4EE3\u7801\u89C4\u8303\u3011`,
|
|
13893
|
-
parentSystemPrompt
|
|
14319
|
+
parentSystemPrompt,
|
|
14320
|
+
SUBAGENT_REPORT_REQ
|
|
13894
14321
|
].join("\n");
|
|
13895
14322
|
const subTaskPrompt = [
|
|
13896
14323
|
role ? manifest ? `# \u672C\u6B21\u89D2\u8272\u8865\u5145: ${role}` : `\u3010\u4F60\u7684\u4E13\u5C5E\u89D2\u8272\u3011: ${role}` : manifest ? "" : `\u3010\u4F60\u7684\u4E13\u5C5E\u89D2\u8272\u3011: \u4E13\u6CE8\u6267\u884C\u7279\u5B9A\u5C40\u90E8\u5B50\u4EFB\u52A1\u7684\u72EC\u7ACB\u667A\u80FD\u4F53\u52A9\u624B`,
|
|
@@ -13984,15 +14411,15 @@ var init_subagent = __esm({
|
|
|
13984
14411
|
});
|
|
13985
14412
|
|
|
13986
14413
|
// ../core/src/hooks/trust.ts
|
|
13987
|
-
import
|
|
13988
|
-
import
|
|
14414
|
+
import path40 from "path";
|
|
14415
|
+
import fs38 from "fs/promises";
|
|
13989
14416
|
var TRUSTED_HOOKS_FILE, approved, loaded, ensureLoaded, isHookCommandApproved, approveHookCommand;
|
|
13990
14417
|
var init_trust2 = __esm({
|
|
13991
14418
|
"../core/src/hooks/trust.ts"() {
|
|
13992
14419
|
"use strict";
|
|
13993
14420
|
init_config();
|
|
13994
14421
|
init_common();
|
|
13995
|
-
TRUSTED_HOOKS_FILE =
|
|
14422
|
+
TRUSTED_HOOKS_FILE = path40.join(appConfig.dataDir, "trusted_hooks.json");
|
|
13996
14423
|
approved = /* @__PURE__ */ new Set();
|
|
13997
14424
|
loaded = false;
|
|
13998
14425
|
ensureLoaded = async () => {
|
|
@@ -14012,7 +14439,7 @@ var init_trust2 = __esm({
|
|
|
14012
14439
|
if (approved.has(ident)) return;
|
|
14013
14440
|
approved.add(ident);
|
|
14014
14441
|
try {
|
|
14015
|
-
await
|
|
14442
|
+
await fs38.mkdir(appConfig.dataDir, { recursive: true });
|
|
14016
14443
|
await atomicWriteJSON(TRUSTED_HOOKS_FILE, [...approved]);
|
|
14017
14444
|
} catch (e) {
|
|
14018
14445
|
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}`);
|
|
@@ -14022,8 +14449,8 @@ var init_trust2 = __esm({
|
|
|
14022
14449
|
});
|
|
14023
14450
|
|
|
14024
14451
|
// ../core/src/hooks/loader.ts
|
|
14025
|
-
import
|
|
14026
|
-
import
|
|
14452
|
+
import fs39 from "fs/promises";
|
|
14453
|
+
import path41 from "path";
|
|
14027
14454
|
var slimHookContext, readHooksConfig, appendValidated, validateRule, parseStdoutDecision, parseAgentDecision, gateSeq, firstRunGate, compileRule2, loadHooks, initHooks;
|
|
14028
14455
|
var init_loader4 = __esm({
|
|
14029
14456
|
"../core/src/hooks/loader.ts"() {
|
|
@@ -14052,15 +14479,15 @@ var init_loader4 = __esm({
|
|
|
14052
14479
|
readHooksConfig = async (includeProject) => {
|
|
14053
14480
|
const merged = {};
|
|
14054
14481
|
const paths = [
|
|
14055
|
-
|
|
14482
|
+
path41.join(appConfig.dataDir, "settings.json"),
|
|
14056
14483
|
// 全局用户级
|
|
14057
|
-
...includeProject ? [
|
|
14484
|
+
...includeProject ? [path41.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
|
|
14058
14485
|
// 项目级(叠加);未信任时省略
|
|
14059
14486
|
];
|
|
14060
14487
|
for (const configPath of paths) {
|
|
14061
14488
|
let raw;
|
|
14062
14489
|
try {
|
|
14063
|
-
raw = await
|
|
14490
|
+
raw = await fs39.readFile(configPath, "utf-8");
|
|
14064
14491
|
} catch {
|
|
14065
14492
|
continue;
|
|
14066
14493
|
}
|
|
@@ -14433,8 +14860,8 @@ ${m.context}`;
|
|
|
14433
14860
|
});
|
|
14434
14861
|
|
|
14435
14862
|
// ../core/src/skills/loader.ts
|
|
14436
|
-
import
|
|
14437
|
-
import
|
|
14863
|
+
import fs40 from "fs/promises";
|
|
14864
|
+
import path42 from "path";
|
|
14438
14865
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
14439
14866
|
var BUILTIN_DIR, SOURCES2, MAX_SKILL_BODY_BYTES, splitList, parseSkillAt, loadSkills, initSkills;
|
|
14440
14867
|
var init_loader5 = __esm({
|
|
@@ -14445,18 +14872,18 @@ var init_loader5 = __esm({
|
|
|
14445
14872
|
init_registry3();
|
|
14446
14873
|
init_skill();
|
|
14447
14874
|
init_registry2();
|
|
14448
|
-
BUILTIN_DIR =
|
|
14875
|
+
BUILTIN_DIR = path42.join(path42.dirname(fileURLToPath2(import.meta.url)), "builtin");
|
|
14449
14876
|
SOURCES2 = [
|
|
14450
14877
|
{ dir: BUILTIN_DIR, source: "builtin" },
|
|
14451
|
-
{ dir:
|
|
14452
|
-
{ dir:
|
|
14878
|
+
{ dir: path42.join(appConfig.dataDir, "skills"), source: "global" },
|
|
14879
|
+
{ dir: path42.join(process.cwd(), ".deepseeker-code", "skills"), source: "project" }
|
|
14453
14880
|
];
|
|
14454
14881
|
MAX_SKILL_BODY_BYTES = 64 * 1024;
|
|
14455
14882
|
splitList = (raw) => (raw ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
14456
14883
|
parseSkillAt = async (skillFile, dir, source) => {
|
|
14457
14884
|
let raw;
|
|
14458
14885
|
try {
|
|
14459
|
-
raw = await
|
|
14886
|
+
raw = await fs40.readFile(skillFile, "utf-8");
|
|
14460
14887
|
} catch {
|
|
14461
14888
|
return null;
|
|
14462
14889
|
}
|
|
@@ -14495,7 +14922,7 @@ var init_loader5 = __esm({
|
|
|
14495
14922
|
loadSkills = async (includeProject) => {
|
|
14496
14923
|
const picked = await scanSources(
|
|
14497
14924
|
filterSources(SOURCES2, includeProject),
|
|
14498
|
-
(e, dir) => e.isDirectory() ?
|
|
14925
|
+
(e, dir) => e.isDirectory() ? path42.join(dir, e.name, "SKILL.md") : void 0,
|
|
14499
14926
|
parseSkillAt
|
|
14500
14927
|
);
|
|
14501
14928
|
for (const { item } of picked) registerSkill(item);
|
|
@@ -14526,8 +14953,8 @@ var init_loader5 = __esm({
|
|
|
14526
14953
|
});
|
|
14527
14954
|
|
|
14528
14955
|
// ../core/src/agents/loader.ts
|
|
14529
|
-
import
|
|
14530
|
-
import
|
|
14956
|
+
import fs41 from "fs/promises";
|
|
14957
|
+
import path43 from "path";
|
|
14531
14958
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
14532
14959
|
var BUILTIN_DIR2, SOURCES3, parseAgentAt, initAgents;
|
|
14533
14960
|
var init_loader6 = __esm({
|
|
@@ -14537,16 +14964,16 @@ var init_loader6 = __esm({
|
|
|
14537
14964
|
init_frontmatter();
|
|
14538
14965
|
init_registry4();
|
|
14539
14966
|
init_registry2();
|
|
14540
|
-
BUILTIN_DIR2 =
|
|
14967
|
+
BUILTIN_DIR2 = path43.join(path43.dirname(fileURLToPath3(import.meta.url)), "builtin");
|
|
14541
14968
|
SOURCES3 = [
|
|
14542
14969
|
{ dir: BUILTIN_DIR2, source: "builtin" },
|
|
14543
|
-
{ dir:
|
|
14544
|
-
{ dir:
|
|
14970
|
+
{ dir: path43.join(appConfig.dataDir, "agents"), source: "global" },
|
|
14971
|
+
{ dir: path43.join(process.cwd(), ".deepseeker-code", "agents"), source: "project" }
|
|
14545
14972
|
];
|
|
14546
14973
|
parseAgentAt = async (file, dir, source) => {
|
|
14547
14974
|
let raw;
|
|
14548
14975
|
try {
|
|
14549
|
-
raw = await
|
|
14976
|
+
raw = await fs41.readFile(file, "utf-8");
|
|
14550
14977
|
} catch {
|
|
14551
14978
|
return null;
|
|
14552
14979
|
}
|
|
@@ -14581,7 +15008,7 @@ var init_loader6 = __esm({
|
|
|
14581
15008
|
const known = new Set(into.map((t) => t.function.name));
|
|
14582
15009
|
const picked = await scanSources(
|
|
14583
15010
|
filterSources(SOURCES3, includeProject),
|
|
14584
|
-
(e, dir) => e.isFile() && e.name.endsWith(".agent.md") ?
|
|
15011
|
+
(e, dir) => e.isFile() && e.name.endsWith(".agent.md") ? path43.join(dir, e.name) : void 0,
|
|
14585
15012
|
parseAgentAt
|
|
14586
15013
|
);
|
|
14587
15014
|
for (const { item: m, file, source } of picked) {
|
|
@@ -14618,8 +15045,8 @@ var init_registry7 = __esm({
|
|
|
14618
15045
|
});
|
|
14619
15046
|
|
|
14620
15047
|
// ../core/src/commands/loader.ts
|
|
14621
|
-
import
|
|
14622
|
-
import
|
|
15048
|
+
import fs42 from "fs/promises";
|
|
15049
|
+
import path44 from "path";
|
|
14623
15050
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
14624
15051
|
var BUILTIN_DIR3, SOURCES4, MAX_COMMAND_BODY_BYTES, parseCommandAt, loadCommands, initCommands;
|
|
14625
15052
|
var init_loader7 = __esm({
|
|
@@ -14629,17 +15056,17 @@ var init_loader7 = __esm({
|
|
|
14629
15056
|
init_frontmatter();
|
|
14630
15057
|
init_registry7();
|
|
14631
15058
|
init_registry2();
|
|
14632
|
-
BUILTIN_DIR3 =
|
|
15059
|
+
BUILTIN_DIR3 = path44.join(path44.dirname(fileURLToPath4(import.meta.url)), "builtin");
|
|
14633
15060
|
SOURCES4 = [
|
|
14634
15061
|
{ dir: BUILTIN_DIR3, source: "builtin" },
|
|
14635
|
-
{ dir:
|
|
14636
|
-
{ dir:
|
|
15062
|
+
{ dir: path44.join(appConfig.dataDir, "commands"), source: "global" },
|
|
15063
|
+
{ dir: path44.join(process.cwd(), ".deepseeker-code", "commands"), source: "project" }
|
|
14637
15064
|
];
|
|
14638
15065
|
MAX_COMMAND_BODY_BYTES = 64 * 1024;
|
|
14639
15066
|
parseCommandAt = async (file, _dir, source) => {
|
|
14640
15067
|
let raw;
|
|
14641
15068
|
try {
|
|
14642
|
-
raw = await
|
|
15069
|
+
raw = await fs42.readFile(file, "utf-8");
|
|
14643
15070
|
} catch {
|
|
14644
15071
|
return null;
|
|
14645
15072
|
}
|
|
@@ -14650,7 +15077,7 @@ var init_loader7 = __esm({
|
|
|
14650
15077
|
}
|
|
14651
15078
|
const name = parsed.frontmatter.name;
|
|
14652
15079
|
const description = parsed.frontmatter.description;
|
|
14653
|
-
const fallbackName =
|
|
15080
|
+
const fallbackName = path44.basename(file, ".md");
|
|
14654
15081
|
const finalName = name || fallbackName;
|
|
14655
15082
|
if (!description) {
|
|
14656
15083
|
console.warn(`\u26A0\uFE0F [commands] \u7F3A\u5C11 description\uFF08${file}\uFF09\uFF0C\u5DF2\u8DF3\u8FC7`);
|
|
@@ -14676,7 +15103,7 @@ var init_loader7 = __esm({
|
|
|
14676
15103
|
loadCommands = async (includeProject) => {
|
|
14677
15104
|
const picked = await scanSources(
|
|
14678
15105
|
filterSources(SOURCES4, includeProject),
|
|
14679
|
-
(e, dir) => e.isFile() && e.name.endsWith(".md") ?
|
|
15106
|
+
(e, dir) => e.isFile() && e.name.endsWith(".md") ? path44.join(dir, e.name) : void 0,
|
|
14680
15107
|
parseCommandAt
|
|
14681
15108
|
);
|
|
14682
15109
|
for (const { item } of picked) registerCommand(item);
|
|
@@ -14694,8 +15121,8 @@ var init_loader7 = __esm({
|
|
|
14694
15121
|
});
|
|
14695
15122
|
|
|
14696
15123
|
// ../core/src/outputStyles/loader.ts
|
|
14697
|
-
import
|
|
14698
|
-
import
|
|
15124
|
+
import fs43 from "fs/promises";
|
|
15125
|
+
import path45 from "path";
|
|
14699
15126
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14700
15127
|
var BUILTIN_DIR4, MAX_STYLE_BODY_BYTES, SOURCES5, parseStyleAt, loadOutputStyles, initOutputStyles;
|
|
14701
15128
|
var init_loader8 = __esm({
|
|
@@ -14705,17 +15132,17 @@ var init_loader8 = __esm({
|
|
|
14705
15132
|
init_frontmatter();
|
|
14706
15133
|
init_registry5();
|
|
14707
15134
|
init_registry2();
|
|
14708
|
-
BUILTIN_DIR4 =
|
|
15135
|
+
BUILTIN_DIR4 = path45.join(path45.dirname(fileURLToPath5(import.meta.url)), "builtin");
|
|
14709
15136
|
MAX_STYLE_BODY_BYTES = 64 * 1024;
|
|
14710
15137
|
SOURCES5 = [
|
|
14711
15138
|
{ dir: BUILTIN_DIR4, source: "builtin" },
|
|
14712
|
-
{ dir:
|
|
14713
|
-
{ dir:
|
|
15139
|
+
{ dir: path45.join(appConfig.dataDir, "output-styles"), source: "global" },
|
|
15140
|
+
{ dir: path45.join(process.cwd(), ".deepseeker-code", "output-styles"), source: "project" }
|
|
14714
15141
|
];
|
|
14715
15142
|
parseStyleAt = async (file, _dir, source) => {
|
|
14716
15143
|
let raw;
|
|
14717
15144
|
try {
|
|
14718
|
-
raw = await
|
|
15145
|
+
raw = await fs43.readFile(file, "utf-8");
|
|
14719
15146
|
} catch {
|
|
14720
15147
|
return null;
|
|
14721
15148
|
}
|
|
@@ -14747,7 +15174,7 @@ var init_loader8 = __esm({
|
|
|
14747
15174
|
loadOutputStyles = async (includeProject) => {
|
|
14748
15175
|
const picked = await scanSources(
|
|
14749
15176
|
filterSources(SOURCES5, includeProject),
|
|
14750
|
-
(e, dir) => e.isFile() && e.name.endsWith(".md") ?
|
|
15177
|
+
(e, dir) => e.isFile() && e.name.endsWith(".md") ? path45.join(dir, e.name) : void 0,
|
|
14751
15178
|
parseStyleAt
|
|
14752
15179
|
);
|
|
14753
15180
|
for (const { item } of picked) registerOutputStyle(item);
|
|
@@ -14828,8 +15255,8 @@ var init_bootstrap = __esm({
|
|
|
14828
15255
|
});
|
|
14829
15256
|
|
|
14830
15257
|
// ../core/src/statusLine/config.ts
|
|
14831
|
-
import
|
|
14832
|
-
import
|
|
15258
|
+
import fs44 from "fs/promises";
|
|
15259
|
+
import path46 from "path";
|
|
14833
15260
|
var parseBlock, readStatusLineConfig;
|
|
14834
15261
|
var init_config2 = __esm({
|
|
14835
15262
|
"../core/src/statusLine/config.ts"() {
|
|
@@ -14845,16 +15272,16 @@ var init_config2 = __esm({
|
|
|
14845
15272
|
};
|
|
14846
15273
|
readStatusLineConfig = async (includeProject) => {
|
|
14847
15274
|
const paths = [
|
|
14848
|
-
|
|
15275
|
+
path46.join(appConfig.dataDir, "settings.json"),
|
|
14849
15276
|
// 全局用户级
|
|
14850
|
-
...includeProject ? [
|
|
15277
|
+
...includeProject ? [path46.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
|
|
14851
15278
|
// 项目级(覆盖);未信任时省略
|
|
14852
15279
|
];
|
|
14853
15280
|
let result = null;
|
|
14854
15281
|
for (const configPath of paths) {
|
|
14855
15282
|
let raw;
|
|
14856
15283
|
try {
|
|
14857
|
-
raw = await
|
|
15284
|
+
raw = await fs44.readFile(configPath, "utf-8");
|
|
14858
15285
|
} catch {
|
|
14859
15286
|
continue;
|
|
14860
15287
|
}
|
|
@@ -14874,8 +15301,8 @@ var init_config2 = __esm({
|
|
|
14874
15301
|
|
|
14875
15302
|
// ../core/src/statusLine/runner.ts
|
|
14876
15303
|
import { spawn as spawn5 } from "child_process";
|
|
14877
|
-
import
|
|
14878
|
-
import
|
|
15304
|
+
import fs45 from "fs";
|
|
15305
|
+
import path47 from "path";
|
|
14879
15306
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
14880
15307
|
var STATUSLINE_TIMEOUT_MS, cachedVersion, runStatusLine;
|
|
14881
15308
|
var init_runner = __esm({
|
|
@@ -14884,16 +15311,16 @@ var init_runner = __esm({
|
|
|
14884
15311
|
init_guard();
|
|
14885
15312
|
STATUSLINE_TIMEOUT_MS = 3e3;
|
|
14886
15313
|
try {
|
|
14887
|
-
const here =
|
|
15314
|
+
const here = path47.dirname(fileURLToPath6(import.meta.url));
|
|
14888
15315
|
const candidates = [
|
|
14889
|
-
|
|
15316
|
+
path47.join(here, "../../../package.json"),
|
|
14890
15317
|
// src/core/package.json
|
|
14891
|
-
|
|
15318
|
+
path47.join(here, "../../../../package.json")
|
|
14892
15319
|
// 仓库根 package.json
|
|
14893
15320
|
];
|
|
14894
15321
|
for (const p of candidates) {
|
|
14895
15322
|
try {
|
|
14896
|
-
const pkg = JSON.parse(
|
|
15323
|
+
const pkg = JSON.parse(fs45.readFileSync(p, "utf-8"));
|
|
14897
15324
|
if (typeof pkg.version === "string" && pkg.version) {
|
|
14898
15325
|
cachedVersion = pkg.version;
|
|
14899
15326
|
break;
|
|
@@ -14943,222 +15370,6 @@ var init_runner = __esm({
|
|
|
14943
15370
|
}
|
|
14944
15371
|
});
|
|
14945
15372
|
|
|
14946
|
-
// ../core/src/observability/store.ts
|
|
14947
|
-
import path46 from "path";
|
|
14948
|
-
import fs44 from "fs/promises";
|
|
14949
|
-
var getTraceDirPath, getTracePath, tracePathCache, ensuredTraceDirs, ensureTraceDir, getGlobalClockPath, getTraceStorePath;
|
|
14950
|
-
var init_store3 = __esm({
|
|
14951
|
-
"../core/src/observability/store.ts"() {
|
|
14952
|
-
"use strict";
|
|
14953
|
-
init_config();
|
|
14954
|
-
init_traceCalculate();
|
|
14955
|
-
init_common();
|
|
14956
|
-
getTraceDirPath = (mainTraceId) => {
|
|
14957
|
-
assertSafeSessionId(mainTraceId, "traceId");
|
|
14958
|
-
return path46.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
|
|
14959
|
-
};
|
|
14960
|
-
getTracePath = () => {
|
|
14961
|
-
return path46.join(appConfig.dataDir, "trace");
|
|
14962
|
-
};
|
|
14963
|
-
tracePathCache = /* @__PURE__ */ new Map();
|
|
14964
|
-
ensuredTraceDirs = /* @__PURE__ */ new Set();
|
|
14965
|
-
ensureTraceDir = async (mainTraceId) => {
|
|
14966
|
-
const dir = getTraceDirPath(mainTraceId);
|
|
14967
|
-
if (ensuredTraceDirs.has(dir)) return;
|
|
14968
|
-
await fs44.mkdir(dir, { recursive: true });
|
|
14969
|
-
ensuredTraceDirs.add(dir);
|
|
14970
|
-
};
|
|
14971
|
-
getGlobalClockPath = () => {
|
|
14972
|
-
return path46.join(getTracePath(), "trace-cleanup-clock.json");
|
|
14973
|
-
};
|
|
14974
|
-
getTraceStorePath = async (mainTraceId) => {
|
|
14975
|
-
assertSafeSessionId(mainTraceId, "traceId");
|
|
14976
|
-
const rootId = getFileName(mainTraceId);
|
|
14977
|
-
const cached2 = tracePathCache.get(rootId);
|
|
14978
|
-
if (cached2) return cached2;
|
|
14979
|
-
await ensureTraceDir(rootId);
|
|
14980
|
-
const dir = getTraceDirPath(rootId);
|
|
14981
|
-
const files = await fs44.readdir(dir);
|
|
14982
|
-
const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
|
|
14983
|
-
let fileName = "";
|
|
14984
|
-
if (existedFile) {
|
|
14985
|
-
fileName = existedFile;
|
|
14986
|
-
} else {
|
|
14987
|
-
const todayStr = getTodayDateString();
|
|
14988
|
-
fileName = `trace-${todayStr}__${rootId}.jsonl`;
|
|
14989
|
-
}
|
|
14990
|
-
const resolved = path46.join(dir, fileName);
|
|
14991
|
-
tracePathCache.set(rootId, resolved);
|
|
14992
|
-
return resolved;
|
|
14993
|
-
};
|
|
14994
|
-
}
|
|
14995
|
-
});
|
|
14996
|
-
|
|
14997
|
-
// ../core/src/observability/trace.ts
|
|
14998
|
-
import fs45 from "fs/promises";
|
|
14999
|
-
import path47 from "path";
|
|
15000
|
-
async function emitTrace(base) {
|
|
15001
|
-
const event = {
|
|
15002
|
-
sessionId: base.sessionId,
|
|
15003
|
-
parentId: base.parentId,
|
|
15004
|
-
eventType: base.eventType,
|
|
15005
|
-
timestamp: base.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
15006
|
-
usage: base.usage,
|
|
15007
|
-
payload: base.payload,
|
|
15008
|
-
metadata: {
|
|
15009
|
-
...base.metadata || {}
|
|
15010
|
-
}
|
|
15011
|
-
};
|
|
15012
|
-
try {
|
|
15013
|
-
await appendTraceEvent(event);
|
|
15014
|
-
} catch (error) {
|
|
15015
|
-
console.warn("\u26A0\uFE0F [Trace] \u4E8B\u4EF6\u843D\u76D8\u5931\u8D25\uFF0C\u5DF2\u9632\u5FA1\u6027\u8DF3\u8FC7\uFF08\u4E0D\u5F71\u54CD\u4E3B\u4E1A\u52A1\uFF09:", error);
|
|
15016
|
-
}
|
|
15017
|
-
}
|
|
15018
|
-
async function appendTraceEvent(event) {
|
|
15019
|
-
const p = await getTraceStorePath(event.sessionId);
|
|
15020
|
-
const line = JSON.stringify(event) + "\n";
|
|
15021
|
-
await fs45.appendFile(p, line, "utf-8");
|
|
15022
|
-
if (workspaceTraceBytes < 0) {
|
|
15023
|
-
workspaceTraceBytes = await getDirBytes(getTracePath());
|
|
15024
|
-
}
|
|
15025
|
-
workspaceTraceBytes += Buffer.byteLength(line, "utf-8");
|
|
15026
|
-
void maybeCleanupAfterAppend(event.sessionId);
|
|
15027
|
-
}
|
|
15028
|
-
async function maybeCleanupAfterAppend(sessionId) {
|
|
15029
|
-
if (cleanupInProgress2) return;
|
|
15030
|
-
cleanupInProgress2 = true;
|
|
15031
|
-
try {
|
|
15032
|
-
await ensureClockLoaded2();
|
|
15033
|
-
const now = Date.now();
|
|
15034
|
-
const isTimeExpired = now - diskLastCleanupAt2 > CLEANUP_INTERVAL_MS2;
|
|
15035
|
-
const isSizeOverflow = workspaceTraceBytes > MAX_TRACE_FOLDER_BYTES;
|
|
15036
|
-
if (!isTimeExpired && !isSizeOverflow) return;
|
|
15037
|
-
if (isSizeOverflow && !isTimeExpired && now - lastSizeCleanupAt2 < SIZE_CLEANUP_COOLDOWN_MS2) {
|
|
15038
|
-
return;
|
|
15039
|
-
}
|
|
15040
|
-
const reason = isTimeExpired && isSizeOverflow ? "\u5BB9\u91CF+\u65F6\u95F4\u53CC\u95F8" : isSizeOverflow ? "\u5BB9\u91CF\u8D8A\u8FC750MB\u5927\u95F8" : "3\u5929\u51B7\u5374\u5468\u671F\u5DF2\u6EE1";
|
|
15041
|
-
console.log(`\u{1F9F9} [Trace\u8FD0\u7EF4] \u89E6\u53D1\u81EA\u9002\u5E94\u6E05\u7406\uFF08\u539F\u56E0: ${reason}\uFF09`);
|
|
15042
|
-
let deletedCount = 0;
|
|
15043
|
-
deletedCount += await cleanupOldTraceFiles();
|
|
15044
|
-
workspaceTraceBytes = await getDirBytes(getTracePath());
|
|
15045
|
-
if (workspaceTraceBytes > MAX_TRACE_FOLDER_BYTES) {
|
|
15046
|
-
const targetBytes = Math.floor(MAX_TRACE_FOLDER_BYTES * SIZE_RECLAIM_TARGET_RATIO2);
|
|
15047
|
-
deletedCount += await evictOldestForSize2(targetBytes);
|
|
15048
|
-
workspaceTraceBytes = await getDirBytes(getTracePath());
|
|
15049
|
-
}
|
|
15050
|
-
lastSizeCleanupAt2 = now;
|
|
15051
|
-
diskLastCleanupAt2 = now;
|
|
15052
|
-
const clockPath = getGlobalClockPath();
|
|
15053
|
-
await fs45.mkdir(path47.dirname(clockPath), { recursive: true });
|
|
15054
|
-
await fs45.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
|
|
15055
|
-
if (deletedCount > 0) {
|
|
15056
|
-
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`);
|
|
15057
|
-
}
|
|
15058
|
-
} catch (error) {
|
|
15059
|
-
console.warn("\u26A0\uFE0F [Trace\u8FD0\u7EF4] \u81EA\u52A8\u6E05\u7406\u53D1\u751F\u8F7B\u5FAE\u5F02\u5E38\uFF0C\u5DF2\u9632\u5FA1\u6027\u8DF3\u8FC7:", error);
|
|
15060
|
-
} finally {
|
|
15061
|
-
cleanupInProgress2 = false;
|
|
15062
|
-
}
|
|
15063
|
-
}
|
|
15064
|
-
async function cleanupOldTraceFiles() {
|
|
15065
|
-
const dir = getTracePath();
|
|
15066
|
-
const retentionDays = Math.max(1, appConfig.traceRetentionDays || 7);
|
|
15067
|
-
const cutoff = /* @__PURE__ */ new Date();
|
|
15068
|
-
cutoff.setHours(0, 0, 0, 0);
|
|
15069
|
-
cutoff.setDate(cutoff.getDate() - retentionDays);
|
|
15070
|
-
const now = Date.now();
|
|
15071
|
-
let deleted = 0;
|
|
15072
|
-
let relativePaths;
|
|
15073
|
-
try {
|
|
15074
|
-
relativePaths = await fs45.readdir(dir, { recursive: true });
|
|
15075
|
-
} catch {
|
|
15076
|
-
return 0;
|
|
15077
|
-
}
|
|
15078
|
-
const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
15079
|
-
for (const relativePath of relativePaths) {
|
|
15080
|
-
const fileName = path47.basename(relativePath);
|
|
15081
|
-
const m = fileName.match(re);
|
|
15082
|
-
if (!m) continue;
|
|
15083
|
-
const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
|
|
15084
|
-
if (fileBornDay >= cutoff) continue;
|
|
15085
|
-
const fullPath = path47.join(dir, relativePath);
|
|
15086
|
-
try {
|
|
15087
|
-
const st = await fs45.stat(fullPath);
|
|
15088
|
-
if (now - st.mtimeMs < ACTIVE_GRACE_MS2) continue;
|
|
15089
|
-
await fs45.unlink(fullPath);
|
|
15090
|
-
deleted += 1;
|
|
15091
|
-
} catch {
|
|
15092
|
-
}
|
|
15093
|
-
}
|
|
15094
|
-
return deleted;
|
|
15095
|
-
}
|
|
15096
|
-
async function evictOldestForSize2(targetBytes) {
|
|
15097
|
-
const dir = getTracePath();
|
|
15098
|
-
let relativePaths;
|
|
15099
|
-
try {
|
|
15100
|
-
relativePaths = await fs45.readdir(dir, { recursive: true });
|
|
15101
|
-
} catch {
|
|
15102
|
-
return 0;
|
|
15103
|
-
}
|
|
15104
|
-
const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
15105
|
-
const candidates = [];
|
|
15106
|
-
for (const relativePath of relativePaths) {
|
|
15107
|
-
const fileName = path47.basename(relativePath);
|
|
15108
|
-
if (!re.test(fileName)) continue;
|
|
15109
|
-
try {
|
|
15110
|
-
const st = await fs45.stat(path47.join(dir, relativePath));
|
|
15111
|
-
candidates.push({ mtime: st.mtimeMs, fullPath: path47.join(dir, relativePath), size: st.size });
|
|
15112
|
-
} catch {
|
|
15113
|
-
}
|
|
15114
|
-
}
|
|
15115
|
-
candidates.sort((a, b) => a.mtime - b.mtime);
|
|
15116
|
-
let totalBytes = candidates.reduce((sum, c) => sum + c.size, 0);
|
|
15117
|
-
let deleted = 0;
|
|
15118
|
-
for (const c of candidates) {
|
|
15119
|
-
if (totalBytes <= targetBytes) break;
|
|
15120
|
-
try {
|
|
15121
|
-
await fs45.unlink(c.fullPath);
|
|
15122
|
-
totalBytes -= c.size;
|
|
15123
|
-
deleted += 1;
|
|
15124
|
-
} catch {
|
|
15125
|
-
}
|
|
15126
|
-
}
|
|
15127
|
-
if (deleted > 0) {
|
|
15128
|
-
console.warn(`\u26A0\uFE0F [Trace\u8FD0\u7EF4] \u5BB9\u91CF\u786C\u9A71\u9010\uFF1A\u8D8A\u8FC7\u6D3B\u8DC3\u4FDD\u62A4\u5F3A\u5220 ${deleted} \u4E2A\u6700\u65E7 trace \u6587\u4EF6\uFF08\u78C1\u76D8\u538B\u529B\u515C\u5E95\uFF09\u3002`);
|
|
15129
|
-
}
|
|
15130
|
-
return deleted;
|
|
15131
|
-
}
|
|
15132
|
-
var CLEANUP_INTERVAL_MS2, ACTIVE_GRACE_MS2, MAX_TRACE_FOLDER_BYTES, SIZE_RECLAIM_TARGET_RATIO2, SIZE_CLEANUP_COOLDOWN_MS2, workspaceTraceBytes, diskLastCleanupAt2, clockLoaded2, lastSizeCleanupAt2, cleanupInProgress2, ensureClockLoaded2;
|
|
15133
|
-
var init_trace = __esm({
|
|
15134
|
-
"../core/src/observability/trace.ts"() {
|
|
15135
|
-
"use strict";
|
|
15136
|
-
init_config();
|
|
15137
|
-
init_store3();
|
|
15138
|
-
init_traceCalculate();
|
|
15139
|
-
CLEANUP_INTERVAL_MS2 = 3 * 24 * 60 * 60 * 1e3;
|
|
15140
|
-
ACTIVE_GRACE_MS2 = 24 * 60 * 60 * 1e3;
|
|
15141
|
-
MAX_TRACE_FOLDER_BYTES = 50 * 1024 * 1024;
|
|
15142
|
-
SIZE_RECLAIM_TARGET_RATIO2 = 0.8;
|
|
15143
|
-
SIZE_CLEANUP_COOLDOWN_MS2 = 60 * 1e3;
|
|
15144
|
-
workspaceTraceBytes = -1;
|
|
15145
|
-
diskLastCleanupAt2 = 0;
|
|
15146
|
-
clockLoaded2 = false;
|
|
15147
|
-
lastSizeCleanupAt2 = 0;
|
|
15148
|
-
cleanupInProgress2 = false;
|
|
15149
|
-
ensureClockLoaded2 = async () => {
|
|
15150
|
-
if (clockLoaded2) return;
|
|
15151
|
-
clockLoaded2 = true;
|
|
15152
|
-
try {
|
|
15153
|
-
const rawClock = await fs45.readFile(getGlobalClockPath(), "utf-8");
|
|
15154
|
-
diskLastCleanupAt2 = JSON.parse(rawClock).lastCleanupAt || 0;
|
|
15155
|
-
} catch {
|
|
15156
|
-
diskLastCleanupAt2 = 0;
|
|
15157
|
-
}
|
|
15158
|
-
};
|
|
15159
|
-
}
|
|
15160
|
-
});
|
|
15161
|
-
|
|
15162
15373
|
// ../core/src/tool/approvalGate.ts
|
|
15163
15374
|
var approvalGate_exports = {};
|
|
15164
15375
|
__export(approvalGate_exports, {
|
|
@@ -16874,7 +17085,7 @@ var init_StreamingCursor = __esm({
|
|
|
16874
17085
|
// src/components/MessageBlock.tsx
|
|
16875
17086
|
import { Box, Text as Text3 } from "ink";
|
|
16876
17087
|
import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
16877
|
-
var UsageFooter, listPrefix, AssistantLine,
|
|
17088
|
+
var UsageFooter, listPrefix, AssistantLine, fenceLen, isMdRow, isMdSep, mdCells, parseBlocks, fitCell, tableWidths, buildVLines, AssistantVLine, MessageBlock;
|
|
16878
17089
|
var init_MessageBlock = __esm({
|
|
16879
17090
|
"src/components/MessageBlock.tsx"() {
|
|
16880
17091
|
"use strict";
|
|
@@ -16913,7 +17124,10 @@ var init_MessageBlock = __esm({
|
|
|
16913
17124
|
}
|
|
16914
17125
|
return /* @__PURE__ */ jsx3(RichText, { text: line });
|
|
16915
17126
|
};
|
|
16916
|
-
|
|
17127
|
+
fenceLen = (l, bareOnly) => {
|
|
17128
|
+
const m = l.match(/^\s*(`{3,})([a-z0-9_-]*)\s*$/);
|
|
17129
|
+
return m && (!bareOnly || !m[2]) ? m[1].length : 0;
|
|
17130
|
+
};
|
|
16917
17131
|
isMdRow = (l) => l.includes("|");
|
|
16918
17132
|
isMdSep = (l) => /^[ \t|:-]+$/.test(l) && l.includes("-") && l.includes("|");
|
|
16919
17133
|
mdCells = (l) => l.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((c) => c.trim());
|
|
@@ -16922,10 +17136,11 @@ var init_MessageBlock = __esm({
|
|
|
16922
17136
|
const blocks = [];
|
|
16923
17137
|
let i = 0;
|
|
16924
17138
|
while (i < src.length) {
|
|
16925
|
-
|
|
17139
|
+
const openLen = fenceLen(src[i], false);
|
|
17140
|
+
if (openLen) {
|
|
16926
17141
|
const body = [];
|
|
16927
17142
|
i++;
|
|
16928
|
-
while (i < src.length &&
|
|
17143
|
+
while (i < src.length && fenceLen(src[i], true) < openLen) body.push(src[i++]);
|
|
16929
17144
|
if (i < src.length) i++;
|
|
16930
17145
|
blocks.push({ kind: "fence", lines: body });
|
|
16931
17146
|
continue;
|