deepseeker-code 1.0.59 → 1.0.60
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 +200 -151
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -12803,7 +12803,6 @@ var init_streamInference = __esm({
|
|
|
12803
12803
|
payload: { input: msgText(message[message.length - 1].content) }
|
|
12804
12804
|
// ★ 多模态:trace 只记文本视图
|
|
12805
12805
|
});
|
|
12806
|
-
console.log(`[DSC-DIAG] streamInference round ${round} \u5B8C\u6210: content=${contentBuf.length}chars reasoning=${reasoningBuf.length}chars toolCalls=${toolCallsBuf.size}`);
|
|
12807
12806
|
return { kind: "completed", assistantMessage, usage: lastUsage };
|
|
12808
12807
|
} catch (error) {
|
|
12809
12808
|
if (signal?.aborted) {
|
|
@@ -12817,7 +12816,7 @@ var init_streamInference = __esm({
|
|
|
12817
12816
|
payload: { input: msgText(message[message.length - 1].content), output: err.message }
|
|
12818
12817
|
// ★ 多模态:文本视图
|
|
12819
12818
|
});
|
|
12820
|
-
console.
|
|
12819
|
+
console.error(`\u274C \u63A8\u7406\u5931\u8D25\uFF08round ${round}\uFF09\uFF1A${err.message}`);
|
|
12821
12820
|
return { kind: "error", error: err };
|
|
12822
12821
|
}
|
|
12823
12822
|
};
|
|
@@ -13074,6 +13073,70 @@ ${PLAN_REJECT_TEXT(planRejectCount)}` };
|
|
|
13074
13073
|
}
|
|
13075
13074
|
});
|
|
13076
13075
|
|
|
13076
|
+
// ../core/src/config/prices.ts
|
|
13077
|
+
var MODEL_PRICES, PRICES_VERIFIED_AT, PRICES_STALE_DAYS, pricesAgeDays, isBeijingPeak, envPrice, ENV_OVERRIDE, priceFor, calcCostYuan;
|
|
13078
|
+
var init_prices = __esm({
|
|
13079
|
+
"../core/src/config/prices.ts"() {
|
|
13080
|
+
"use strict";
|
|
13081
|
+
MODEL_PRICES = {
|
|
13082
|
+
"deepseek-flash": {
|
|
13083
|
+
idle: { input: 1, output: 4, cacheHit: 0.02 },
|
|
13084
|
+
peak: { input: 2, output: 8, cacheHit: 0.04 }
|
|
13085
|
+
},
|
|
13086
|
+
// 官网脚注明示旧名按 Flash 价格计费(2026-10-19 核实),非猜测——与 flash 同价条目
|
|
13087
|
+
"deepseek-flash-vision-exp": {
|
|
13088
|
+
idle: { input: 1, output: 4, cacheHit: 0.02 },
|
|
13089
|
+
peak: { input: 2, output: 8, cacheHit: 0.04 }
|
|
13090
|
+
},
|
|
13091
|
+
"deepseek-v4-pro": {
|
|
13092
|
+
idle: { input: 4.5, output: 13.5, cacheHit: 0.15 },
|
|
13093
|
+
peak: { input: 9, output: 27, cacheHit: 0.3 }
|
|
13094
|
+
}
|
|
13095
|
+
};
|
|
13096
|
+
PRICES_VERIFIED_AT = "2026-10-19";
|
|
13097
|
+
PRICES_STALE_DAYS = 30;
|
|
13098
|
+
pricesAgeDays = () => Math.max(0, Math.floor((Date.now() - Date.parse(`${PRICES_VERIFIED_AT}T00:00:00Z`)) / 864e5));
|
|
13099
|
+
isBeijingPeak = (ts2 = /* @__PURE__ */ new Date()) => {
|
|
13100
|
+
const bj = new Date(ts2.getTime() + 8 * 36e5);
|
|
13101
|
+
const day = bj.getUTCDay();
|
|
13102
|
+
if (day === 0 || day === 6) return false;
|
|
13103
|
+
const h = bj.getUTCHours();
|
|
13104
|
+
return h >= 9 && h < 12 || h >= 14 && h < 18;
|
|
13105
|
+
};
|
|
13106
|
+
envPrice = (name) => {
|
|
13107
|
+
const raw = process.env[name];
|
|
13108
|
+
if (!raw) return void 0;
|
|
13109
|
+
const n = Number(raw);
|
|
13110
|
+
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
13111
|
+
};
|
|
13112
|
+
ENV_OVERRIDE = (() => {
|
|
13113
|
+
const input = envPrice("DEEP_SEEK_PRICE_INPUT");
|
|
13114
|
+
const output = envPrice("DEEP_SEEK_PRICE_OUTPUT");
|
|
13115
|
+
const cacheHit = envPrice("DEEP_SEEK_PRICE_CACHEHIT");
|
|
13116
|
+
if (input === void 0 && output === void 0 && cacheHit === void 0) return null;
|
|
13117
|
+
return { input, output, cacheHit };
|
|
13118
|
+
})();
|
|
13119
|
+
priceFor = (model, ts2) => {
|
|
13120
|
+
const tier = MODEL_PRICES[model];
|
|
13121
|
+
const base = tier ? isBeijingPeak(ts2 ?? /* @__PURE__ */ new Date()) ? tier.peak : tier.idle : void 0;
|
|
13122
|
+
if (!ENV_OVERRIDE) return base ?? null;
|
|
13123
|
+
const input = ENV_OVERRIDE.input ?? base?.input;
|
|
13124
|
+
const output = ENV_OVERRIDE.output ?? base?.output;
|
|
13125
|
+
const cacheHit = ENV_OVERRIDE.cacheHit ?? base?.cacheHit;
|
|
13126
|
+
if (input === void 0 || output === void 0 || cacheHit === void 0) return null;
|
|
13127
|
+
return { input, output, cacheHit };
|
|
13128
|
+
};
|
|
13129
|
+
calcCostYuan = (model, u, ts2) => {
|
|
13130
|
+
const p = priceFor(model, ts2);
|
|
13131
|
+
if (!p) return null;
|
|
13132
|
+
const cached2 = Math.max(0, u.cachedTokens ?? 0);
|
|
13133
|
+
const miss = Math.max(0, (u.promptTokens ?? 0) - cached2);
|
|
13134
|
+
const completion = Math.max(0, u.completionTokens ?? 0);
|
|
13135
|
+
return (miss * p.input + cached2 * p.cacheHit + completion * p.output) / 1e6;
|
|
13136
|
+
};
|
|
13137
|
+
}
|
|
13138
|
+
});
|
|
13139
|
+
|
|
13077
13140
|
// ../core/src/agent/costRelay.ts
|
|
13078
13141
|
var createCostRelay;
|
|
13079
13142
|
var init_costRelay = __esm({
|
|
@@ -13102,6 +13165,99 @@ var init_costRelay = __esm({
|
|
|
13102
13165
|
}
|
|
13103
13166
|
});
|
|
13104
13167
|
|
|
13168
|
+
// ../core/src/agent/runLedger.ts
|
|
13169
|
+
var BUDGET_HARD_LIMIT_RATIO, roundYuan6, createRunLedger;
|
|
13170
|
+
var init_runLedger = __esm({
|
|
13171
|
+
"../core/src/agent/runLedger.ts"() {
|
|
13172
|
+
"use strict";
|
|
13173
|
+
init_prices();
|
|
13174
|
+
init_costRelay();
|
|
13175
|
+
init_client();
|
|
13176
|
+
BUDGET_HARD_LIMIT_RATIO = 1.2;
|
|
13177
|
+
roundYuan6 = (y) => Math.round(y * 1e6) / 1e6;
|
|
13178
|
+
createRunLedger = (opts) => {
|
|
13179
|
+
let budgetSpentYuan = 0;
|
|
13180
|
+
let usageSum;
|
|
13181
|
+
let costYuanAcc = 0;
|
|
13182
|
+
let costKnown = true;
|
|
13183
|
+
let toolCostYuanAcc = 0;
|
|
13184
|
+
let auxCostYuanAcc = 0;
|
|
13185
|
+
let subCostYuanAcc = 0;
|
|
13186
|
+
const relay = createCostRelay(opts.costSink);
|
|
13187
|
+
const addUsage = (u) => {
|
|
13188
|
+
if (!u) return;
|
|
13189
|
+
usageSum = {
|
|
13190
|
+
prompt_tokens: (usageSum?.prompt_tokens ?? 0) + (u.prompt_tokens ?? 0),
|
|
13191
|
+
completion_tokens: (usageSum?.completion_tokens ?? 0) + (u.completion_tokens ?? 0),
|
|
13192
|
+
total_tokens: (usageSum?.total_tokens ?? 0) + (u.total_tokens ?? 0),
|
|
13193
|
+
cached_tokens: (usageSum?.cached_tokens ?? 0) + (u.cached_tokens ?? 0)
|
|
13194
|
+
};
|
|
13195
|
+
const cost = calcCostYuan(opts.model, { promptTokens: u.prompt_tokens, completionTokens: u.completion_tokens, cachedTokens: u.cached_tokens });
|
|
13196
|
+
if (cost == null) costKnown = false;
|
|
13197
|
+
else {
|
|
13198
|
+
costYuanAcc += cost;
|
|
13199
|
+
budgetSpentYuan += cost;
|
|
13200
|
+
}
|
|
13201
|
+
};
|
|
13202
|
+
const addToolCost = (yuan) => {
|
|
13203
|
+
if (!Number.isFinite(yuan) || yuan <= 0) return;
|
|
13204
|
+
toolCostYuanAcc += yuan;
|
|
13205
|
+
budgetSpentYuan += yuan;
|
|
13206
|
+
};
|
|
13207
|
+
const reportAuxUsage = (usage, kind) => {
|
|
13208
|
+
if (usage) {
|
|
13209
|
+
const cost = calcCostYuan(AUX_MODEL_NAME, { promptTokens: usage.prompt_tokens, completionTokens: usage.completion_tokens, cachedTokens: usage.cached_tokens });
|
|
13210
|
+
if (cost != null && Number.isFinite(cost) && cost > 0) {
|
|
13211
|
+
auxCostYuanAcc += cost;
|
|
13212
|
+
budgetSpentYuan += cost;
|
|
13213
|
+
}
|
|
13214
|
+
}
|
|
13215
|
+
try {
|
|
13216
|
+
opts.onAuxUsage?.(usage, kind);
|
|
13217
|
+
} catch {
|
|
13218
|
+
}
|
|
13219
|
+
};
|
|
13220
|
+
const reportSubCost = (yuan) => {
|
|
13221
|
+
if (Number.isFinite(yuan) && yuan > 0) {
|
|
13222
|
+
budgetSpentYuan += yuan;
|
|
13223
|
+
subCostYuanAcc += yuan;
|
|
13224
|
+
}
|
|
13225
|
+
};
|
|
13226
|
+
const snapshot = () => opts.budgetYuan != null ? { spent: budgetSpentYuan, budget: opts.budgetYuan } : null;
|
|
13227
|
+
return {
|
|
13228
|
+
addUsage,
|
|
13229
|
+
addToolCost,
|
|
13230
|
+
reportAuxUsage,
|
|
13231
|
+
reportSubCost,
|
|
13232
|
+
/** 预算 soft 判定读数(nudge 管线消费):未武装返回 null。O(1) 闭包读数。 */
|
|
13233
|
+
getBudgetStatus: snapshot,
|
|
13234
|
+
/** 预算硬线判定(E2):spent >= budget×1.2(>= 语义与收拢前逐字节等价,恰 1.2× 即触发)。
|
|
13235
|
+
* 自武装探测(inheritedBudgetCheck 兜底)与轮边界硬截断共用同一判定。 */
|
|
13236
|
+
overHardLimit: () => opts.budgetYuan != null && budgetSpentYuan >= opts.budgetYuan * BUDGET_HARD_LIMIT_RATIO,
|
|
13237
|
+
/** 子 run 成本中继 flush:基数=预算圈实时读数(子树完整口径,文件头★中继段)。主 run 无 sink 时 no-op。 */
|
|
13238
|
+
flushRelay: () => relay.flush(budgetSpentYuan),
|
|
13239
|
+
/** run.end 事件行与 receipt token 段共用的用量合计快照。 */
|
|
13240
|
+
usageSummary: () => usageSum,
|
|
13241
|
+
/** 预算读数快照:硬截断 final 文案金额源。未武装=null(调用方结构上只在已武装分支取,勿 ?? 0 兜底)。 */
|
|
13242
|
+
budgetSnapshot: snapshot,
|
|
13243
|
+
/** usageLog 落盘字段(recordUsageRun 入参金额段;costYuan 无价=undefined、各账 ≤0 省略——自动缺省容错)。 */
|
|
13244
|
+
usageLogFields: () => ({
|
|
13245
|
+
costYuan: costKnown ? roundYuan6(costYuanAcc) : void 0,
|
|
13246
|
+
toolCostYuan: toolCostYuanAcc > 0 ? roundYuan6(toolCostYuanAcc) : void 0,
|
|
13247
|
+
auxCostYuan: auxCostYuanAcc > 0 ? roundYuan6(auxCostYuanAcc) : void 0
|
|
13248
|
+
}),
|
|
13249
|
+
/** run.receipt 结算单金额段:costYuan 无价=null(显式「不知钱」,绝不编数);各账 ≤0 省略字段。 */
|
|
13250
|
+
receiptFields: () => ({
|
|
13251
|
+
costYuan: costKnown ? roundYuan6(costYuanAcc) : null,
|
|
13252
|
+
toolCostYuan: toolCostYuanAcc > 0 ? roundYuan6(toolCostYuanAcc) : void 0,
|
|
13253
|
+
auxCostYuan: auxCostYuanAcc > 0 ? roundYuan6(auxCostYuanAcc) : void 0,
|
|
13254
|
+
subCostYuan: subCostYuanAcc > 0 ? roundYuan6(subCostYuanAcc) : void 0
|
|
13255
|
+
})
|
|
13256
|
+
};
|
|
13257
|
+
};
|
|
13258
|
+
}
|
|
13259
|
+
});
|
|
13260
|
+
|
|
13105
13261
|
// ../core/src/observability/usageLog.ts
|
|
13106
13262
|
import fs34 from "fs/promises";
|
|
13107
13263
|
import path37 from "path";
|
|
@@ -13209,70 +13365,6 @@ var init_usageLog = __esm({
|
|
|
13209
13365
|
}
|
|
13210
13366
|
});
|
|
13211
13367
|
|
|
13212
|
-
// ../core/src/config/prices.ts
|
|
13213
|
-
var MODEL_PRICES, PRICES_VERIFIED_AT, PRICES_STALE_DAYS, pricesAgeDays, isBeijingPeak, envPrice, ENV_OVERRIDE, priceFor, calcCostYuan;
|
|
13214
|
-
var init_prices = __esm({
|
|
13215
|
-
"../core/src/config/prices.ts"() {
|
|
13216
|
-
"use strict";
|
|
13217
|
-
MODEL_PRICES = {
|
|
13218
|
-
"deepseek-flash": {
|
|
13219
|
-
idle: { input: 1, output: 4, cacheHit: 0.02 },
|
|
13220
|
-
peak: { input: 2, output: 8, cacheHit: 0.04 }
|
|
13221
|
-
},
|
|
13222
|
-
// 官网脚注明示旧名按 Flash 价格计费(2026-10-19 核实),非猜测——与 flash 同价条目
|
|
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
|
-
}
|
|
13231
|
-
};
|
|
13232
|
-
PRICES_VERIFIED_AT = "2026-10-19";
|
|
13233
|
-
PRICES_STALE_DAYS = 30;
|
|
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;
|
|
13241
|
-
};
|
|
13242
|
-
envPrice = (name) => {
|
|
13243
|
-
const raw = process.env[name];
|
|
13244
|
-
if (!raw) return void 0;
|
|
13245
|
-
const n = Number(raw);
|
|
13246
|
-
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
13247
|
-
};
|
|
13248
|
-
ENV_OVERRIDE = (() => {
|
|
13249
|
-
const input = envPrice("DEEP_SEEK_PRICE_INPUT");
|
|
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 };
|
|
13264
|
-
};
|
|
13265
|
-
calcCostYuan = (model, u, ts2) => {
|
|
13266
|
-
const p = priceFor(model, ts2);
|
|
13267
|
-
if (!p) return null;
|
|
13268
|
-
const cached2 = Math.max(0, u.cachedTokens ?? 0);
|
|
13269
|
-
const miss = Math.max(0, (u.promptTokens ?? 0) - cached2);
|
|
13270
|
-
const completion = Math.max(0, u.completionTokens ?? 0);
|
|
13271
|
-
return (miss * p.input + cached2 * p.cacheHit + completion * p.output) / 1e6;
|
|
13272
|
-
};
|
|
13273
|
-
}
|
|
13274
|
-
});
|
|
13275
|
-
|
|
13276
13368
|
// ../core/src/agent/runAgent.ts
|
|
13277
13369
|
async function* runAgent(message, options) {
|
|
13278
13370
|
const sessionId = options.sessionId;
|
|
@@ -13300,15 +13392,22 @@ async function* runAgent(message, options) {
|
|
|
13300
13392
|
let budgetTruncated = false;
|
|
13301
13393
|
const MAX_AGENT_ROUNDS = 500;
|
|
13302
13394
|
const firstPrompt = resolveFirstPrompt(message, options);
|
|
13303
|
-
|
|
13304
|
-
|
|
13395
|
+
const ledger = createRunLedger({
|
|
13396
|
+
model: effectiveModel,
|
|
13397
|
+
budgetYuan: depth === 0 && options.budgetYuan != null && options.budgetYuan > 0 ? options.budgetYuan : void 0,
|
|
13398
|
+
costSink: options.costSink,
|
|
13399
|
+
onAuxUsage: options.onAuxUsage
|
|
13400
|
+
});
|
|
13401
|
+
const reportAuxUsage = ledger.reportAuxUsage;
|
|
13402
|
+
const toolCostSink = process.env.DEEP_SEEK_TOOL_COST === "0" ? void 0 : ledger.addToolCost;
|
|
13305
13403
|
let runCompactCount = 0;
|
|
13306
13404
|
const nudges = createNudgeScheduler({
|
|
13307
13405
|
firstPrompt,
|
|
13308
13406
|
planMode: !!options.planMode,
|
|
13309
13407
|
noEarlyFinal: !!options.noEarlyFinal,
|
|
13310
13408
|
getContextUsage: () => ({ usedTokens: Math.round(estimateTokens(message) * calibRatio + toolsTokens), windowTokens: modelWindow }),
|
|
13311
|
-
getBudgetStatus:
|
|
13409
|
+
getBudgetStatus: ledger.getBudgetStatus
|
|
13410
|
+
// ★ E2 预算 soft 读数(闭包在账本内 O(1) 读数;未武装返回 null,管线自判)
|
|
13312
13411
|
});
|
|
13313
13412
|
const readTracker = /* @__PURE__ */ new Map();
|
|
13314
13413
|
const userDecisionSource = depth > 0 ? "spawn_agent" : "user";
|
|
@@ -13330,47 +13429,7 @@ async function* runAgent(message, options) {
|
|
|
13330
13429
|
let lastRealPromptTokens = persistedCalib.lastRealPromptTokens;
|
|
13331
13430
|
let lastCachedTokens = persistedCalib.lastCachedTokens;
|
|
13332
13431
|
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);
|
|
13432
|
+
const inheritedBudgetCheck = options.budgetCheck ?? (depth === 0 ? ledger.overHardLimit : void 0);
|
|
13374
13433
|
let planWriteRej = 0;
|
|
13375
13434
|
const toolCounts = {};
|
|
13376
13435
|
await appendEvent(sessionId, { dscEvent: "run.start", runId, depth });
|
|
@@ -13401,11 +13460,12 @@ async function* runAgent(message, options) {
|
|
|
13401
13460
|
yield { type: "final", text: lastContent || "\uFF08\u5DF2\u4E2D\u6B62\uFF09" };
|
|
13402
13461
|
return;
|
|
13403
13462
|
}
|
|
13404
|
-
if (depth === 0 &&
|
|
13463
|
+
if (depth === 0 && ledger.overHardLimit()) {
|
|
13464
|
+
const snap = ledger.budgetSnapshot();
|
|
13405
13465
|
stopReason = "limit";
|
|
13406
13466
|
budgetTruncated = true;
|
|
13407
13467
|
yield { type: "final", text: (lastContent || "") + `
|
|
13408
|
-
\uFF08\u{1F4B0} \u9884\u7B97\u622A\u65AD\uFF1A\u672C run \u5DF2\u82B1\u8D39 \xA5${
|
|
13468
|
+
\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
13469
|
return;
|
|
13410
13470
|
}
|
|
13411
13471
|
if (depth > 0 && options.budgetCheck?.()) {
|
|
@@ -13494,12 +13554,12 @@ async function* runAgent(message, options) {
|
|
|
13494
13554
|
const estAtInfer = estimateTokens(message) + toolsTokens;
|
|
13495
13555
|
if (estAtInfer > 1e3) {
|
|
13496
13556
|
const observed = infResult.usage.prompt_tokens / estAtInfer;
|
|
13497
|
-
calibRatio = calibRatio *
|
|
13557
|
+
calibRatio = calibRatio * CALIB_EMA_KEEP + observed * CALIB_EMA_NEW;
|
|
13498
13558
|
}
|
|
13499
13559
|
lastRealPromptTokens = infResult.usage.prompt_tokens;
|
|
13500
13560
|
lastCachedTokens = infResult.usage.cached_tokens;
|
|
13501
13561
|
}
|
|
13502
|
-
addUsage(infResult.usage);
|
|
13562
|
+
ledger.addUsage(infResult.usage);
|
|
13503
13563
|
const assistantMessage = infResult.assistantMessage;
|
|
13504
13564
|
message.push(assistantMessage);
|
|
13505
13565
|
await appendMessage({ ...assistantMessage, sessionId });
|
|
@@ -13509,7 +13569,7 @@ async function* runAgent(message, options) {
|
|
|
13509
13569
|
if (!assistantMessage.tool_calls || assistantMessage.tool_calls.length === 0) {
|
|
13510
13570
|
await appendEvent(sessionId, { dscEvent: "round.end", runId, round, usage: infResult.usage });
|
|
13511
13571
|
emitContextUsage();
|
|
13512
|
-
|
|
13572
|
+
ledger.flushRelay();
|
|
13513
13573
|
const finalText = (typeof assistantMessage.content === "string" ? assistantMessage.content : "") || "";
|
|
13514
13574
|
const intercepted = nudges.interceptFinal(finalText, round);
|
|
13515
13575
|
if (intercepted) continue;
|
|
@@ -13559,14 +13619,9 @@ async function* runAgent(message, options) {
|
|
|
13559
13619
|
contextTokensEst: Math.round(estimateTokens(message) * calibRatio + toolsTokens),
|
|
13560
13620
|
readTracker,
|
|
13561
13621
|
// ★ 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
|
-
},
|
|
13622
|
+
// ★ 子 run 成本回灌(成本信任链第二环 E1):runSubagent 经 toolCtx.reportCost 把子 run 花费
|
|
13623
|
+
// 记进账本预算圈 + 展示账——父预算自动继承约束(守卫与分账语义在 runLedger.reportSubCost)。
|
|
13624
|
+
reportCost: ledger.reportSubCost,
|
|
13570
13625
|
// ★ 按次计费工具成本上报(DeepSeek Search/Fetch):web 工具经 toolCtx.toolCostSink 拿到闭包,
|
|
13571
13626
|
// 成功调用后按次上报进本 run 累计器。
|
|
13572
13627
|
toolCostSink,
|
|
@@ -13591,7 +13646,7 @@ async function* runAgent(message, options) {
|
|
|
13591
13646
|
}
|
|
13592
13647
|
await appendEvent(sessionId, { dscEvent: "round.end", runId, round, usage: infResult.usage });
|
|
13593
13648
|
emitContextUsage();
|
|
13594
|
-
|
|
13649
|
+
ledger.flushRelay();
|
|
13595
13650
|
if (options.planMode && planWriteRej >= PLAN_REJECT_FORCE_AT) {
|
|
13596
13651
|
stopReason = "limit";
|
|
13597
13652
|
yield { type: "final", text: PLAN_REJECT_FORCE_FINAL_TEXT(planWriteRej) };
|
|
@@ -13615,10 +13670,11 @@ async function* runAgent(message, options) {
|
|
|
13615
13670
|
} catch {
|
|
13616
13671
|
}
|
|
13617
13672
|
try {
|
|
13618
|
-
await appendEvent(sessionId, { dscEvent: "run.end", runId, stopReason: signal?.aborted ? "aborted" : stopReason, rounds: round, usage:
|
|
13673
|
+
await appendEvent(sessionId, { dscEvent: "run.end", runId, stopReason: signal?.aborted ? "aborted" : stopReason, rounds: round, usage: ledger.usageSummary() });
|
|
13619
13674
|
} catch {
|
|
13620
13675
|
}
|
|
13621
13676
|
try {
|
|
13677
|
+
const us = ledger.usageSummary();
|
|
13622
13678
|
void recordUsageRun({
|
|
13623
13679
|
v: 1,
|
|
13624
13680
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -13629,40 +13685,33 @@ async function* runAgent(message, options) {
|
|
|
13629
13685
|
stopReason: signal?.aborted ? "aborted" : stopReason,
|
|
13630
13686
|
rounds: round,
|
|
13631
13687
|
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)
|
|
13688
|
+
promptTokens: us?.prompt_tokens,
|
|
13689
|
+
completionTokens: us?.completion_tokens,
|
|
13690
|
+
totalTokens: us?.total_tokens,
|
|
13691
|
+
cachedTokens: us?.cached_tokens,
|
|
13692
|
+
...ledger.usageLogFields(),
|
|
13693
|
+
// costYuan/toolCostYuan/auxCostYuan(口径与舍入在 runLedger)
|
|
13641
13694
|
tools: toolCounts
|
|
13642
13695
|
});
|
|
13643
13696
|
} catch {
|
|
13644
13697
|
}
|
|
13645
13698
|
try {
|
|
13646
|
-
|
|
13699
|
+
ledger.flushRelay();
|
|
13647
13700
|
} catch {
|
|
13648
13701
|
}
|
|
13649
13702
|
try {
|
|
13650
|
-
|
|
13651
|
-
|
|
13703
|
+
const us = ledger.usageSummary();
|
|
13704
|
+
if (depth === 0 && options.onUIEvent && us) {
|
|
13705
|
+
const prompt = us.prompt_tokens ?? 0;
|
|
13652
13706
|
options.onUIEvent({
|
|
13653
13707
|
type: "run.receipt",
|
|
13654
13708
|
rounds: round,
|
|
13655
13709
|
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 自动省略)
|
|
13710
|
+
completionTokens: us.completion_tokens ?? 0,
|
|
13711
|
+
cachedTokens: us.cached_tokens ?? 0,
|
|
13712
|
+
cacheHitRate: prompt > 0 ? (us.cached_tokens ?? 0) / prompt : 0,
|
|
13713
|
+
...ledger.receiptFields(),
|
|
13714
|
+
// costYuan(null=无价)/toolCostYuan/auxCostYuan/subCostYuan(口径与舍入在 runLedger)
|
|
13666
13715
|
durationMs: Math.round(performance.now() - startTime),
|
|
13667
13716
|
budgetTruncated: budgetTruncated || void 0
|
|
13668
13717
|
// 预算截断标注(E2;undefined 自动省略)
|
|
@@ -13683,7 +13732,7 @@ async function* runAgent(message, options) {
|
|
|
13683
13732
|
}
|
|
13684
13733
|
}
|
|
13685
13734
|
}
|
|
13686
|
-
var resolveFirstPrompt;
|
|
13735
|
+
var CALIB_EMA_KEEP, CALIB_EMA_NEW, resolveFirstPrompt;
|
|
13687
13736
|
var init_runAgent = __esm({
|
|
13688
13737
|
"../core/src/agent/runAgent.ts"() {
|
|
13689
13738
|
"use strict";
|
|
@@ -13700,11 +13749,11 @@ var init_runAgent = __esm({
|
|
|
13700
13749
|
init_toolScheduling();
|
|
13701
13750
|
init_streamInference();
|
|
13702
13751
|
init_agentNudges();
|
|
13703
|
-
|
|
13752
|
+
init_runLedger();
|
|
13704
13753
|
init_usageLog();
|
|
13705
|
-
init_prices();
|
|
13706
13754
|
init_createModel();
|
|
13707
|
-
|
|
13755
|
+
CALIB_EMA_KEEP = 0.6;
|
|
13756
|
+
CALIB_EMA_NEW = 0.4;
|
|
13708
13757
|
resolveFirstPrompt = (message, options) => {
|
|
13709
13758
|
if ((options.depth ?? 0) !== 0) return "";
|
|
13710
13759
|
const explicit = options.currentUserText?.trim();
|