fix(compaction): 摘要收缩改按路由价并补齐定价访问路径

ds-review-bot 首轮意见修复:

- 摘要收缩比较改用所选节点的路由价 shadowedRouteTokenCount,修复图片消息启发式价低于带框摘要时压缩被误拒;日志影子价仍为启发式
- DeepSeek 定价经序列化器同一套 access 解析构建句柄与占位文本,消除逐图数十 token 的低估;uncatalogued 分支 JSDoc 指明复现 projectImagesForTextModel 替换
- llm-replay 在加载时拒绝纯文本模型上的 imageRequestTokens 声明
- contextBreakdown 的 README 与 JSDoc 改为等于 heuristicTokens 之和,不再声称等于路由价 surfaceTokens
This commit is contained in:
creatixchu
2026-08-24 19:48:52 +08:00
parent 42164508c8
commit 5183bc2b65
24 changed files with 154 additions and 42 deletions
@@ -43,6 +43,8 @@ interface PreparedCompaction extends SurfaceSelection {
readonly measurement: TokenMeasurement
readonly selectedNodes: TokenMeasurement['nodes']
readonly shadowedTokenCount: number
/** Route-priced total of the selected span; the shrink comparison's unit. */
readonly shadowedRouteTokenCount: number
readonly input: SummarizationInput
}
@@ -353,8 +355,10 @@ function prepareCompaction(
selectedNodes,
// The shadow-price protocol prices replacements with the fixed heuristic
// so the O(1) projection fold stays in agreement with its own appends;
// retention and range selection read the route-priced `tokens` instead.
// retention, range selection, and the shrink comparison read the
// route-priced `tokens` instead.
shadowedTokenCount: selectedNodes.reduce((total, node) => total + node.heuristicTokens, 0),
shadowedRouteTokenCount: selectedNodes.reduce((total, node) => total + node.tokens, 0),
input: buildSummarizationInput(session, selection.shadowedSeqs),
}
}
@@ -373,10 +377,13 @@ async function summarizeCompaction(
content: frameSummary(summaryResult.summary),
source: compactCheckpointSource(compactionId, sourceCommandId),
})
// The checkpoint is text-only, so its fixed-heuristic price IS its route
// price; comparing it against the span's route price asks the real
// question — does the replacement lower the next request's pressure.
const framedSummaryTokenCount = dependencies.meter.estimateMessage(checkpointMessage)
if (framedSummaryTokenCount >= prepared.shadowedTokenCount) {
if (framedSummaryTokenCount >= prepared.shadowedRouteTokenCount) {
throw new Error(
`summary is not smaller than the shadowed content (${framedSummaryTokenCount} estimated framed tokens >= ${prepared.shadowedTokenCount})`,
`summary is not smaller than the shadowed content (${framedSummaryTokenCount} estimated framed tokens >= ${prepared.shadowedRouteTokenCount})`,
)
}
return {