Files
maka/docs/archive/deepseek-reasonix-cost-runtime-design.md
agent-radar 7be535059e
Dependency audit / audit (push) Canceled after 0s
CI / plan (push) Canceled after 0s
Gitoxide helper admission / macos-latest (push) Canceled after 0s
Gitoxide helper admission / ubuntu-latest (push) Canceled after 0s
Gitoxide helper admission / windows-latest (push) Canceled after 0s
Runtime Host peer admission / quality (push) Canceled after 0s
Windows recovery / windows_recovery (push) Canceled after 0s
CI / heavy (push) Canceled after 0s
CI / test (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 19:05:14 +08:00

59 KiB
Raw Permalink Blame History

title, document, version, status, date, audience, derived_from
title document version status date audience derived_from
Maka DeepSeek-Reasonix 成本运行线 System Design DEEPSEEK_REASONIX_COST_RUNTIME_SYSTEM_DESIGN_V2 2.0 design draft with rationale 2026-06-24 准备实现或评审 Maka cost-runtime 方向的新工程师
Maka Runtime 主线教学手册 v2
Maka DeepSeek-Reasonix 成本运行线初学者教纲 v3

Archived on 2026-07-13. This is an implementation-slice and open-question chronicle, not current runtime authority. Current cost, request-shape, replay, and compaction mechanisms live in the backend architecture chapters and source.

Maka DeepSeek-Reasonix 成本运行线 System Design v2

这份文档不是教学手册的压缩版,而是从两份教学材料反推出来的一版系统设计文档。

v2 在 v1 的基础上补上最重要的一层:为什么要这样设计。每个关键设计不只描述“怎么切”,还要回答:

  1. 它面对的真实问题是什么?
  2. 它为什么放在这个边界,而不是放在别处?
  3. 它带来什么好处?
  4. 如果不这样设计,系统会怎样退化?

教学手册回答的是:“新人应该怎样一步一步理解这条线?”

系统设计文档要回答的是:“如果我们要把这条线作为 Maka 的长期 runtime 设计,哪些边界、状态、数据结构、fallback 和取舍必须被固定下来?”

本文的中心设计判断是:

DeepSeek-Reasonix 成本运行线不应该新建一条 agent flow。它应该沿着 Maka 已有的 SessionManager -> RuntimeKernel -> AgentRun -> RuntimeRunner -> AiSdkFlow -> AiSdkBackend -> ModelAdapter/ToolRuntime 主线,把 provider-visible request 的成本纪律安装到现有边界上。

换句话说,这不是一个 CostRuntime 设计,而是一个 cost-aware runtime discipline 设计。

0. 设计问题从哪里开始

最朴素的问题是:

一个 agent 会话为什么会越来越贵?

最常见的错误答案是:

因为历史越来越长,prompt token 越来越多。

这个答案只对了一半。DeepSeek 这类 provider 的成本不能只看 total input。Maka 已经观察过反直觉案例:history budget 让 total input 下降,但 cache miss 和估算成本反而上升。

所以本设计不以“压缩 prompt”为第一目标。它的第一目标是让系统能稳定回答四个问题:

  1. Provider 到底看到了什么 request?
  2. Provider 把哪些 token 当成 cache hit、cache miss、cache write、output、reasoning?
  3. 如果成本变了,是 durable prefix 变了,还是 history projection 变了,还是 tool schema 变了?
  4. 为了省成本而改变 replay 时,原始事实、来源和恢复路径是否还在?

这四个问题决定了整个设计。

还有第五个隐含问题:

新人为什么会觉得这些设计“绕”?

因为很多设计不是为了本轮能跑,而是为了长期能解释、能回退、能迁移、能做 checkpoint、能比较 paid matrix。一个只追求“这轮少传点 token”的实现,短期看更直接;但 Maka 要做的是 agent runtime,不是一次性 prompt 工具。它必须在成本、正确性、证据、可恢复、工具权限、UI 投影之间同时站住。

所以本文采用一种固定写法:每一层先讲设计压力,再讲边界选择,再讲收益和失败模式。读者不需要先相信结论,而是能从问题推导到结论。

1. 设计目标

1.1 可观察

每次 model request 都应该留下足够的 usage、cost、request-shape diagnostics,让后续能解释成本变化。

可观察不是只记录一个总 token 数。它至少要区分:

  • input tokens
  • cache hit input tokens
  • cache miss input tokens
  • cache write input tokens
  • output tokens
  • reasoning tokens
  • miss counter 是 provider 明确给出的,还是 Maka 推导出来的
  • durable prefix 是否变化
  • full request shape 是否变化

1.2 可解释

当 cache miss 上升时,系统不能只说“本轮更贵”。它要能进一步说明:

  • model/provider 是否变化
  • system prompt 是否变化
  • provider options 是否变化
  • active tool schema 是否变化
  • history projection 是否变化
  • current turn tail 是否变化

这些解释不等价于 provider 内部 cache key。Maka 不知道 DeepSeek 的真实 cache key。Maka 做的是本地 request-shape 诊断。

1.3 可回退

历史裁剪、工具结果归档、summary 替换、archive hydration 都只能改变本轮 provider request 的 replay projection,不能改写原始 runtime facts。

如果 archive 失败,保留原文。

如果 synthesis cache 不可信,跳过 summary。

如果 provider-native replay 不支持,显式降级。

系统可以少省一点 token,但不能为了省 token 丢掉证据。

1.4 可维护

成本线不能复制模型/工具循环。

Maka 已有主线已经承担:

  • session facade
  • run lifecycle
  • invocation terminal semantics
  • legacy event 到 runtime event 的迁移适配
  • provider request assembly
  • model stream
  • tool call/result
  • permission
  • abort
  • usage
  • telemetry

如果新建 CostAwareAiSdkFlow,它要么复制这些语义,要么绕回旧 backend。两种都不划算。

所以本设计选择把成本能力放到既有路径的关键边界,而不是开新路。

2. 非目标

本设计明确不解决以下问题:

  1. 不定义 DeepSeek provider 内部 cache key。
  2. 不把 prefixHash 当成真实 provider cache key。
  3. 不引入新的 model/tool stepping engine。
  4. 不重写 AiSdkBackend 的完整循环。
  5. 不把 local memory 产品完整纳入成本系统,只处理和 prompt placement 有关的部分。
  6. 不把 Harbor verifier、benchmark reward、task attempt retry 合并进 runtime terminal 语义。
  7. 不承诺 history budget、summary、archive hydration 在所有 workload 上都必然省钱。

这些非目标很重要。成本设计最容易失败的方式,就是把“诊断工具”误当 provider 真相,或者把“一个 paid matrix 里的结论”误当全局定律。

2.5 从问题压力推导设计

在进入组件前,先把设计动机讲清楚。DeepSeek-Reasonix 成本线不是从某个抽象类开始的,而是从几组冲突压力推出来的。

压力一:token 少了,账单不一定少

普通 prompt 优化会把问题表述为:“上下文太长,所以要压短。”

但 DeepSeek 的 cache-sensitive billing 让这个说法不够用。一个 request 的 total input 下降,可能同时让 cache miss 上升。对成本更敏感的不是“总共有多少输入”,而是 provider 把哪些输入当成 fresh token、哪些当成 cache read、哪些写入 cache。

这带来第一个设计结论:

先建立可信的 usage/cost 账本,再谈压缩。

如果跳过这一步,所有 history budget、summary、tool economy 的评估都会变成错觉。系统可能庆祝 prompt 变短,却把真正付费的 cache miss 推高。

收益是:成本优化从感觉变成可测量事实。

失败模式是:团队只看 total token,反复上线“看起来更短、实际更贵”的策略。

压力二:成本变化必须能归因

知道本轮更贵,还不够。系统还要解释为什么更贵。

成本变化可能来自很多地方:

  • system prompt 变了
  • provider options 变了
  • active tool schema 变了
  • history projection 变了
  • current turn tail 变了
  • model/provider 变了

这些变化对 provider cache locality 的影响不同。把它们混成一个总 hash,评审者仍然不知道问题在哪里。

这带来第二个设计结论:

provider-visible request 要拆成 durable prefix 和 full request shape 两层诊断。

收益是:当 cache miss 变多时,系统能说“稳定前缀没动,只是历史 projection 变了”,或者“工具 schema 进入 active set,prefix 发生了真实变化”。

失败模式是:成本 trace 只有一串 token 数,没有解释能力,团队只能靠猜。

压力三:当前事实有用,但会污染稳定前缀

cwd、git status、日期、刚批准的 memory update 都对当前回复有用。但它们每轮都变。如果把这些内容塞进 durable system prompt,prefix hash 会持续抖动。

这带来第三个设计结论:

稳定规则进入 durable system prompt,当前事实进入 turn tail。

收益是:模型仍然看到当前事实,但 prefix diagnostics 不会被无意义扰动。

失败模式是:团队以为 system prompt 没变,实际每轮都被日期、cwd、memory update 改写;cache miss 上升却找不到原因。

压力四:历史要变轻,但事实不能消失

长会话里最贵的往往不是用户文本,而是旧工具结果、网页内容、JSON、搜索结果、文件片段。直接删掉它们当然能省 token,但会丢证据。

这带来第四个设计结论:

RuntimeEvent ledger 是事实,replay projection 才是本轮可优化视图。

收益是:本轮 provider request 可以变轻,系统仍然保留原始事实、来源和恢复路径。

失败模式是:优化策略把历史真的删了,后续 raw evidence、audit、checkpoint、debug 都失去依据。

压力五:summary 不能成为无来源记忆

summary 看起来是历史压缩的自然手段,但没有来源的 summary 会变成一种危险的新事实。它可能覆盖了哪些 turns、漏了哪些限制、从哪些 tool result 来,后面都说不清。

这带来第五个设计结论:

synthesis cache 和 history compact 都必须是 source-bearing replay artifacts。

收益是:summary 可以作为 projection 优化,但仍然带 coverage、limitations、sources 和 fallback。

失败模式是:模型开始依赖一段没人能追溯的“总结”,错误会被长期 replay。

压力六:工具 schema 不是免费的

工具在本地执行,但工具 schema 会被 provider 看见。只要 schema 进入 request,它就是 provider-visible 成本和 prefix shape 的一部分。

这带来第六个设计结论:

full dispatch registry 和 provider-visible active tools 必须分开。

收益是:本地仍保留完整能力,provider 初始只看到必要 schema;需要重工具时通过显式 load_tools 加载,并进入 ledger。

失败模式是:每轮都把全部工具 schema 发给 provider,初始 prompt 重、prefix 大、诊断不清;或者过度动态路由导致工具不可用和 prefix 抖动。

压力七:不能为了成本复制 runtime

DeepSeek 成本线涉及 provider request、history replay、tools、usage、telemetry,看起来像可以新建一个 CostRuntime。但 Maka 已经有完整模型/工具循环和 runtime ledger 迁移路径。

这带来第七个设计结论:

成本线应安装到现有 runtime path 上,而不是新建 flow。

收益是:权限、abort、tool result、usage、terminal semantics 仍然只有一套权威。

失败模式是:新 flow 复制旧 backend,形成两套不一致的 agent loop;未来 bug 修复、checkpoint、tool policy、telemetry 都要维护两遍。

这七个压力就是后面设计层的来源。后面的每一层都不是孤立技巧,而是在回答这些压力中的一部分。

3. 基础运行脊柱

成本线必须建立在 Maka runtime 主线上:

SessionManager
  -> RuntimeKernel
    -> AgentRun
      -> RuntimeRunner
        -> AiSdkFlow
          -> AiSdkBackend
            -> ModelAdapter
            -> ToolRuntime
            -> ToolAvailabilityRuntime

这条主线不是为了让调用链变长,而是为了让事实归属清楚。

为什么成本线要先讲 runtime spine?

因为成本问题看起来在 provider request 上,实际会牵动整个 agent runtime:

  • request 由谁组装
  • prior history 从哪里来
  • tool result 写到哪里
  • usage 算在哪个 run 上
  • UI 看到什么 projection
  • replay 以后用哪套事实
  • retry/checkpoint 以后从哪里恢复

如果没有这条 spine,成本策略很容易变成一堆散落的 prompt hack。今天在 desktop path 生效,明天 headless 不生效;今天 usage 写进 session,明天 replay 找不到;今天 tool result 被压缩,后天 checkpoint 没有原始证据。

所以设计的第一步不是“怎么省”,而是“省的动作发生在哪个权威边界上”。

这条 spine 带来的核心好处是:

  • 外部入口稳定:调用者不需要理解 provider replay 细节。
  • run 生命周期稳定:成本 telemetry 有归属。
  • invocation 语义稳定:错误、abort、missing terminal 不被成本策略打散。
  • backend request 权威稳定:不会出现多处拼 provider messages。
  • legacy -> runtime-event 迁移稳定:成本优化不会绕开未来 ledger。

如果绕过这条 spine,成本优化短期可能更快,但长期会变成 runtime 分叉。

3.1 SessionManager

SessionManager 是外部 facade。桌面 UI、headless runner、测试入口不应该直接理解 run ledger、runtime-event store、provider replay plan。

成本线不应该把 policy 塞到 SessionManager。这里最多负责把外部请求送入 runtime。

设计约束:

  • 不在这里计算 provider request shape。
  • 不在这里做 context budget。
  • 不在这里决定 tool schema economy。
  • 不在这里直接归一化 provider usage。

为什么这样设计:

SessionManager 的价值是让产品入口慢变。成本策略属于 provider-visible request assembly,如果把它放到 facade,外部 API 就会被迫理解内部优化细节。

好处是:UI/headless/test 仍然只发起 session turn,不需要随着 request-shape、context-budget、tool economy 的演进反复改接口。

不这样做的后果是:每个入口都可能自己加一份成本逻辑,最后桌面和 headless 的成本行为不一致。

3.2 RuntimeKernel

RuntimeKernel 组织一轮 turn。它知道 active backend、active run、stop、permission response、child run、session status。

成本线仍然不应该在这里展开 provider request。它可以把当前 turn 的运行组织好,但 provider-visible request 的具体形状属于更内层。

设计约束:

  • 保持 turn orchestration 边界。
  • 不复制 AiSdkBackend request assembly。
  • 不把 cost policy 做成 kernel 级分支 flow。

为什么这样设计:

RuntimeKernel 解决的是“一轮 turn 如何被组织”,不是“这一轮 provider request 具体长什么样”。它应该知道 active run 和 permission/stop 路由,但不应该决定 history projection 或 tool schema。

好处是:kernel 可以继续服务所有 runtime path,而 cost policy 可以在 backend/request 边界独立演进。

不这样做的后果是:kernel 会变成第二个 backend,开始同时管理 turn lifecycle 和 provider request assembly,边界会迅速失控。

3.3 AgentRun

AgentRun 是 durable run envelope。它让一次执行有 run id、session id、turn id、状态、lineage、terminal outcome。

成本线要依赖它提供的 run identity 和 runtime context,但不能让成本 projection 改写 run fact。

设计约束:

  • usage/cost 可以成为 run 的 telemetry fact。
  • runtime-event ledger 是 replay 的事实来源。
  • context budget 只能派生 projection,不能改变 run ledger。

为什么这样设计:

一次成本数据必须属于某个 run,否则 later trace 无法回答“这笔钱是哪次执行产生的”。但 run ledger 本身不是压缩对象。它记录的是执行事实,不是为了下一次 request 省 token 的临时视图。

好处是:usage/cost、request shape、terminal state 可以一起归属到同一个 durable run;未来 checkpoint 或 replay 时可以追溯。

不这样做的后果是:成本数据散落在 session text 或 backend logs 里,后续无法把一次 cache miss spike 和具体 run、history projection、tool schema 变化连起来。

3.4 RuntimeRunner

RuntimeRunner 定义 invocation 语义:开始、遍历 flow、收集 event、判断 terminal、归类 abort/error/missing terminal。

成本线不应该绕开它。否则同一次 provider request 的 terminal 语义会散落到 backend 或新 flow。

设计约束:

  • cost-aware replay 仍然发生在一次 invocation 里面。
  • invocation terminal 仍然由 RuntimeRunner 统一归类。
  • future checkpoint/warm retry 需要这个边界。

为什么这样设计:

成本策略可能影响 provider request,但不应该重定义一次 invocation 怎样开始、怎样结束、怎样失败。terminal 语义一旦分叉,runtime read model、task retry、checkpoint high-water mark 都会受影响。

好处是:不管是否启用 history budget、tool schema economy、synthesis cache,一次 invocation 的结束语义仍然一致。

不这样做的后果是:某些成本路径可能把 provider error 当 completed,或者把 missing terminal 隐藏掉,最终让 UI、task runner、Harbor 对同一次运行得出不同结论。

3.5 AiSdkFlow

AiSdkFlow 是迁移 adapter。它调用旧 AiSdkBackend,把 legacy SessionEvent 转成 canonical RuntimeEvent。

成本线不应该把 AiSdkFlow 升级成新的 cost engine。它仍然是 adapter。

设计约束:

  • 不在这里复制 tool loop。
  • 不在这里独立拼 provider messages。
  • 不在这里定义新的 usage model。

为什么这样设计:

AiSdkFlow 是迁移桥,不是新 engine。它存在的原因是 Maka 正在从 legacy SessionEvent 迁向 canonical RuntimeEvent。如果把成本 engine 放在这里,它就会同时承担迁移 adapter 和 provider runtime 两种责任。

好处是:旧 UI 事件和新 runtime facts 可以继续双轨迁移,而成本逻辑仍然在真正组装 request 的 backend 层。

不这样做的后果是:flow 层开始知道太多 provider/tool 细节,迁移桥会变成不可替换的 runtime brain。

3.6 AiSdkBackend

AiSdkBackend 是成本线的主安装点。

它已经负责:

  • provider/model resolution
  • system prompt 和 current user message 组装
  • turn tail 拼接
  • prior message replay
  • context budget
  • active tools
  • AI SDK stream
  • tool call/result
  • permission
  • usage/cost/telemetry

这意味着 DeepSeek-Reasonix 成本能力主要应该安装在这里和它调用的 helper 边界上。

设计约束:

  • 保持 provider request assembly 的单一权威。
  • 在 request 发出前计算 request-shape diagnostics。
  • 在 stream 完成后归一化 usage 并计算 cost。
  • 让 history economy 和 tool schema economy 都进入 diagnostics。

为什么这样设计:

AiSdkBackend 是唯一同时看见 system prompt、turn tail、prior messages、active tools、provider options、stream usage 和 tool execution 的位置。成本线需要解释 provider-visible request,因此必须靠近这个边界。

好处是:所有改变 request shape 的动作都能在同一个地方被诊断,usage/cost 也能和 request shape 对齐。

不这样做的后果是:prompt placement 在桌面,history budget 在 context helper,tool schema 在 tool runtime,usage 在 adapter,各自写 telemetry,却没有一处能解释“这次 provider 到底看到了什么”。

4. 三套账本的权威边界

成本线依赖三套存储,但不能混用它们的权威性。

SessionStore        -> UI/session projection
AgentRunStore       -> run lifecycle ledger
RuntimeEventStore   -> semantic replay ledger

4.1 SessionStore

SessionStore 仍然服务 UI 和兼容投影。它保存用户看得懂的 session transcript。

成本线不能只从 SessionStore 拼历史,因为展示文本会压扁 runtime semantics。

4.2 AgentRunStore

AgentRunStore 记录一次 run 的生命周期。它回答 run 是否 created、started、completed、failed、cancelled、stale。

成本线可以把 usage/cost 作为 run telemetry,但不要把 replay projection 当成 run state。

4.3 RuntimeEventStore

RuntimeEventStore 是 replay 的语义事实来源。它记录 user event、model text/thinking、function call、function response、permission、usage、terminal facts。

成本线对历史做的所有优化,都应该从 RuntimeEvent 派生 projection,而不是改写 ledger。

5. 设计层一:先把钱算对

第一层设计只处理 usage normalization 和 cost computation。

本层解决的问题:

团队不能用错误的成本指标来评估成本优化。

为什么必须先做这一层?因为后续所有策略都要靠它验收。history budget、archive pruning、synthesis cache、tool schema economy 看起来都在减少输入,但真正要比较的是 cache miss、cache write、cache read、output、reasoning 的组合成本。

好处:

  • 能解释“input 少了但更贵”的情况。
  • 能避免用 total token 指挥 DeepSeek 策略。
  • 能把 provider 明确给出的 miss 和 Maka 推导出的 miss 区分开。
  • 能为 paid matrix 提供可信数据。

不这样做的后果:

  • 优化方向会被 total input 误导。
  • derived counter 会被误当 provider fact。
  • cost regression 可能被误报成 improvement。
  • 后续 request-shape diagnostics 没有可信 usage 可绑定。

5.1 输入

Provider 或 AI SDK 返回的 usage 字段可能不统一:

  • 有的 provider 明确给 cache hit/miss。
  • 有的 provider 只给 cached token details。
  • 有的 provider 给 reasoning token details。
  • 有的字段需要 Maka 推导。

5.2 输出

Maka 需要统一成内部 usage 结构,至少包含:

inputTokens
cacheHitInputTokens
cacheMissInputTokens
cacheWriteInputTokens
cacheMissInputSource
outputTokens
reasoningTokens

其中 cacheMissInputSource 很关键:

  • explicit 表示 provider 明确给了 miss counter。
  • derived 表示 Maka 用 input/cache-hit/cache-write 推导。
  • 缺失时不得假装精确。

5.3 组件归属

ModelAdapter 负责 provider/AI SDK usage normalization。

telemetry/cost.ts 负责把 normalized usage 转成估算成本。

设计约束:

  • 不用 total input 直接估算 DeepSeek 成本。
  • cache hit/cache miss/cache write/output 分开计价。
  • usage 缺失时仍记录诊断,不伪造 provider counter。

6. 设计层二:把钱绑定到 request shape

只知道本轮花了多少钱还不够。系统还要知道这笔钱对应什么 request。

本层解决的问题:

成本数字本身没有解释力,必须和 provider-visible request 的形状绑定。

为什么要拆 request shape?因为 cache miss 上升不是单一原因。可能是稳定前缀变了,也可能只是历史自然增长。没有结构化拆分,所有变化都混在一起。

好处:

  • 能把 durable prefix 变化和 history projection 变化分开。
  • 能把 tool schema 变化显式暴露出来。
  • 能让 paid matrix 的每一组结果都有 request 形状上下文。
  • 能帮助评审判断某个策略是在优化历史,还是无意中扰动了前缀。

不这样做的后果:

  • 每次 cache miss spike 都只能靠人工猜。
  • 系统 prompt、工具 schema、history rewrite 的影响会混在一起。
  • 优化策略之间不可比较。
  • prefix locality 问题会被误判为“历史太长”。

6.1 Request shape 分解

一次 provider-visible request 可以拆成:

provider-visible request
  durable prefix
    model/provider
    system prompt
    provider options
    active tool schema
  history projection
  current user content
  turn tail

注意:这里的分解是 Maka 的诊断模型,不是 DeepSeek 的内部实现。

6.2 两个 hash

prefixHash:

  • model/provider
  • system prompt
  • provider options
  • active tool schema

requestShapeHash:

  • model/provider
  • system prompt
  • provider options
  • active tool schema
  • history projection
  • current user content / turn tail 所形成的完整 request shape

6.3 设计意义

这让系统能区分:

  • durable prefix 没变,只是 history projection 自然变了。
  • tool schema 变了,可能影响 prefix locality。
  • system prompt 被 volatile facts 污染了。
  • provider options 或 model 变了。

6.4 组件归属

request-shape.ts 负责:

  • RequestShapeDiagnostic
  • component hash
  • prefixHash
  • requestShapeHash
  • durable prefix change classification
  • full request shape change classification

设计约束:

  • prefixHash 只能作为 Maka 本地诊断。
  • diagnostics 必须和 normalized usage 一起看。
  • active tool schema 必须只看本轮 provider-visible tools,不看 full local registry。

7. 设计层三:稳定前缀和 turn tail 分离

如果每一轮都把当前 cwd、git 状态、日期、刚批准的 memory update 塞进 system prompt,durable prefix 会无意义抖动。

所以本设计把 prompt placement 作为成本线的一部分。

本层解决的问题:

有些信息必须让模型知道,但不应该进入稳定前缀。

这是成本线里很容易被低估的一层。prompt placement 看起来像产品提示词组织问题,实际上直接影响 prefix diagnostics。如果 volatile facts 混入 system prompt,系统会错误地认为 durable prefix 每轮都变。

好处:

  • 当前事实仍然可见。
  • 稳定 prompt 更容易保持 locality。
  • request-shape diagnostics 更干净。
  • memory update 的生命周期更清楚:本轮 tail,下轮 durable state。

不这样做的后果:

  • 日期、cwd、git status 会造成 prefix hash 抖动。
  • local memory 刚批准的更新可能被重复拼进 stable prompt。
  • cache miss 变多时无法区分是策略变化还是临时事实变化。

7.1 Durable system prompt

适合放进 system prompt 的内容:

  • 稳定行为规则
  • 用户长期偏好
  • workspace instructions
  • skills instructions
  • opt-in 且状态 OK 的 active local memory

这些内容变化较慢,适合进入 durable prefix。

7.2 Turn tail

适合放进 turn tail 的内容:

  • 当前 cwd
  • 当前 git 状态
  • 当前日期
  • 当前平台
  • 本轮刚发生的 memory update
  • 本轮临时环境事实

这些内容对当前回复有用,但不应该污染 durable system prompt。

7.3 组件归属

apps/desktop/src/main/main.ts 负责:

  • buildSystemPrompt()
  • buildTurnTailPrompt()
  • buildLocalMemoryPromptFragment()
  • buildLocalMemoryUpdateTailFragment()

AiSdkBackend 在组装当前 user content 时追加 turn tail。

设计约束:

  • 当前事实仍然让模型可见。
  • volatile facts 不进入 durable prefix。
  • fresh memory update 当前轮进 tail,下轮从 durable state 重新读取。

8. 设计层四:不新建 CostRuntime flow

到了这里,已经能看出成本线需要的能力:

  • usage normalization
  • cost computation
  • request-shape diagnostics
  • prompt placement
  • history projection
  • tool schema economy

这些都在现有 AiSdkBackend path 周围,不需要新的 stepping engine。

本层解决的问题:

成本策略很容易被误设计成一个新 runtime,但真正需要的是现有 runtime 的边界纪律。

为什么不新建 flow?因为 flow 不只是拼 prompt。它要承接 stream、tool calls、permission、abort、usage、terminal semantics、legacy event mapping。成本线如果复制这些,就会创造一条平行 agent loop。

好处:

  • 工具循环只有一套。
  • 权限和 abort 语义不分叉。
  • usage/cost telemetry 仍然贴在真实 provider request 上。
  • runtime-event migration 不被绕开。
  • 后续 checkpoint/read-model 仍然能站在同一条主线上。

不这样做的后果:

  • CostAwareAiSdkFlow 很快会复制 AiSdkBackend。
  • 两套 flow 对同一个 tool result、permission denial、finish reason 可能得出不同语义。
  • bug fix 需要双写。
  • 新人会以为成本优化是另一个 agent 产品,而不是 runtime discipline。

8.1 被拒绝的设计

不建议引入:

RuntimeRunner
  -> CostAwareAiSdkFlow
    -> CostRuntime
      -> AiSdkBackend 或新 backend

问题是:

  • 如果复制 tool loop,就会出现两套权限、abort、usage、telemetry 语义。
  • 如果绕回 AiSdkBackend,新 flow 就只是换壳。
  • 如果只为了 DeepSeek 建新 engine,会让 provider-specific cost policy 污染 runtime abstraction。

8.2 被接受的设计

接受的设计是:

RuntimeRunner
  -> AiSdkFlow
    -> AiSdkBackend
      -> request-shape diagnostics
      -> context-budget replay projection
      -> tool availability economy
      -> ModelAdapter usage normalization
      -> cost telemetry

设计约束:

  • 新能力以 helper/component 形式进入现有 path。
  • 不改变 invocation terminal 语义。
  • 不复制 tool loop。
  • 不改变 provider request assembly 的单一权威。

9. 设计层五:历史不是删除,而是 projection

长会话成本优化的核心,不是改写历史,而是从 ledger 派生本轮 request projection。

RuntimeEvent ledger     -> immutable semantic facts
Replay projection       -> current provider-visible history view
Provider messages       -> materialized request messages

本层解决的问题:

历史太重需要变轻,但历史事实不能被成本策略破坏。

为什么要引入 projection 这个概念?因为“删历史”把两个动作混在了一起:一个是原始事实保存,另一个是本轮 provider request 视图。Maka 需要优化第二个,保留第一个。

好处:

  • 可以针对本轮 request 压缩 replay。
  • 原始 RuntimeEvent 仍然保留。
  • 未来 raw evidence、audit、checkpoint、read model 都有事实基础。
  • 不同 projection 策略可以在同一个 ledger 上比较。

不这样做的后果:

  • history budget 会变成 destructive deletion。
  • summary 或 placeholder 会逐渐替代原始事实。
  • 调试时无法回到“模型当时基于什么工具结果回答”。
  • checkpoint 只能保存压缩后的 prompt,不能恢复语义状态。

9.1 Replay 构造顺序

AiSdkBackend.buildPriorMessages() 的设计顺序应该保持清晰:

  1. 从 prior RuntimeEvent 出发。
  2. 准备 context budget policy。
  3. 调用 applyRuntimeEventContextBudget()。
  4. 运行 history search。
  5. 选择 synthesis cache。
  6. 需要时做 archive hydration。
  7. materialize 成 provider messages。

这个顺序体现了设计原则:

  • 先确定事实来源。
  • 再决定本轮视图。
  • 再选择 summary/archive/raw evidence。
  • 最后才拼 provider messages。

9.2 Context budget 内部顺序

applyRuntimeEventContextBudget() 至少要保持:

  1. stale tool result prune
  2. history compact
  3. token/turn budget selection
  4. diagnostics

设计约束:

  • projection 变化必须可诊断。
  • budget 不得改写 ledger。
  • partial or unsupported replay 必须显式降级。

10. 设计层六:旧大工具结果先 archive,再 placeholder

长会话里最重的内容往往是旧工具结果。直接删除不安全,因为工具结果可能是后续回答的证据来源。

本层解决的问题:

大工具结果是最高杠杆的成本来源,但也是最重要的证据来源。

为什么必须先 archive 再 placeholder?因为 placeholder 本身没有证据价值。它只有在能指回一个可信 artifact 时,才是安全的 replay rewrite。

好处:

  • 旧大结果不再每轮完整 replay。
  • 原始工具结果仍然可恢复。
  • placeholder 能携带 hash、size、source event、tool identity。
  • archive failure 不会破坏 correctness。

不这样做的后果:

  • 直接删:后续无法追溯证据。
  • 直接 placeholder:看似保留引用,实际没有可恢复原文。
  • archive 失败仍替换:系统产生一个无法兑现的证据承诺。
  • 只做 summary:raw evidence request 无法满足。

10.1 Archive-backed pruning

设计动作分三步:

  1. 找候选:旧的、过大的、超出保护窗口的 tool result。
  2. 先归档:host 写 artifact,记录 hash、bytes、estimated tokens、tool identity、tool call id。
  3. 再占位:只有 archive ref 匹配时,projection 里才把原始 tool result 换成 placeholder。

10.2 Fail open

如果 archive 失败:

archive failed -> keep original tool result in replay projection

这会牺牲本轮节省,但保住证据。

10.3 Placeholder 必须携带的信息

placeholder 至少需要:

  • artifact id
  • body hash
  • original bytes
  • estimated tokens
  • tool name
  • tool call id
  • rewrite reason
  • source runtime event ref

设计约束:

  • 不允许“无来源的省略”。
  • 不允许 archive 失败后仍替换成 placeholder。
  • placeholder 是 replay artifact,不是 ledger fact 的替代品。

11. 设计层七:Archive hydration 按需恢复

归档以后,模型什么时候应该看到原文?

本设计提供三种策略位置:

prune-only
eager hydration
history-search-gated hydration

本层解决的问题:

省略旧工具结果以后,系统需要知道什么时候把原文拿回来。

archive-backed pruning 只解决“怎么安全拿掉”。hydration 解决“什么时候恢复”。这两者必须成对出现,否则 archive 只是延迟删除。

好处:

  • prune-only 可以用于不需要原文的场景。
  • eager hydration 可以保护 raw evidence correctness。
  • history-search-gated hydration 可以在相关性和成本之间做折中。
  • 每次恢复都有 hash/session/source/bounds 校验。

不这样做的后果:

  • 模型永远只看到 placeholder,无法回答需要原文的问题。
  • 或者每次都恢复所有 archive,成本节省被抵消。
  • 或者恢复未校验 artifact,引入跨 session、hash mismatch、过大内容等风险。

11.1 Prune-only

最省,但可能错。适合模型不需要旧原文的场景。

11.2 Eager hydration

看到 placeholder 就按 bounds 尝试恢复。正确性更强,但可能读回太多 archive。

11.3 History-search-gated hydration

先用 lightweight history search 找相关 turns,再只恢复相关 archive。

这不是全局最优保证。它只是一个在相关性、正确性和成本之间更保守的选择。

11.4 Hydration 校验

恢复 archive 时必须校验:

  • artifact exists
  • source kind
  • session id
  • source event ref
  • hash
  • max bytes
  • total retrieved tokens bounds

设计约束:

  • raw evidence request 应该跳过 summary,倾向恢复原文。
  • hydration 失败不能伪造原文。
  • retrieval diagnostics 必须写入 telemetry。

12. 设计层八:Summary 也必须 source-bearing

不是每次 follow-up 都需要恢复完整旧工具结果。很多场景用 summary 更合理。

但普通 summary 有风险:它可能成为无来源记忆。

本设计只接受 source-bearing replay artifacts。

本层解决的问题:

summary 是必要的历史经济手段,但无来源 summary 会污染长期记忆。

为什么 summary 必须 source-bearing?因为 summary 本身不是事实,它是从事实派生出来的 projection artifact。它要告诉系统覆盖了哪些事实、有哪些限制、什么时候失效、用户要原文时怎么回去。

好处:

  • 普通 follow-up 不必恢复完整旧历史。
  • summary 可以参与 replay,但不伪装成原始事实。
  • source mismatch、raw evidence request、updated tool result 都能让 summary 失效。
  • 新人能区分“事实 ledger”和“帮助模型理解的压缩视图”。

不这样做的后果:

  • summary 一旦错误,会被长期 replay。
  • 后续无法判断它覆盖或遗漏了什么。
  • 用户要原始证据时,系统只能给一段摘要。
  • compact 历史会变成黑箱。

12.1 Synthesis cache block

一个 synthesis cache block 应包含:

  • summary
  • coverage
  • limitations
  • source refs
  • source hash
  • invalidation constraints
  • token estimate

使用前要检查:

  • 是否属于当前 session
  • 是否覆盖当前 query
  • source hash 是否匹配
  • token 是否超限
  • 是否被更新的相关 tool result invalidated
  • 用户是否在请求 raw evidence

12.2 History compact block

history compact block 是把更旧 turns 折叠成一个有来源的 compact view。

它也必须包含:

  • folded coverage
  • retained recent tail boundary
  • limitations
  • sources
  • archive refs if any

12.3 组件归属

context-budget.ts 负责:

  • selectSynthesisCacheForReplay()
  • renderSynthesisCacheBlock()
  • renderHistoryCompactBlock()

Host 侧 artifact 服务负责:

  • synthesis-cache-artifacts.ts
  • history-compact-artifacts.ts

设计约束:

  • summary 是 projection artifact,不是新的事实来源。
  • source refs 不可信时跳过 summary。
  • 用户要 raw evidence 时不要拿 summary 冒充原文。

13. 设计层九:工具 schema 也是成本面

工具 schema 只要被广告给 provider,就属于 provider-visible request 的一部分。

因此工具不是纯本地能力。工具 schema economy 是成本线的一部分。

本层解决的问题:

工具能力在本地执行,但工具 schema 在 provider request 里付成本。

为什么要把 full registry 和 active tools 分开?因为 Maka 需要本地保留完整执行能力,同时不想每轮都把全部 schema 广告给 provider。schema visibility 是 request shape;dispatch capability 是本地执行能力。二者不是同一件事。

好处:

  • 初始 request 更轻。
  • active tool schema hash 更有解释力。
  • group load 是显式行为,可以进入 ledger。
  • 权限系统仍然独立,不被 schema visibility 混淆。

不这样做的后果:

  • 全量 schema 每轮进入 durable prefix,成本和 cache locality 都受影响。
  • 过度动态隐藏工具会造成模型需要工具时看不到。
  • 没有 execute boundary guard 时,模型可能在 schema 未 active 的 step 调用工具。
  • 加载工具和授权工具混为一谈,安全边界被误读。

13.1 两个集合

Full dispatch registry
  Maka 本地可执行的完整工具集合

Provider-visible active tools
  本轮或当前 AI SDK step 广告给模型的工具 schema

这两个集合必须分开。

13.2 Group activation

在 economy mode:

  • ungrouped tools 初始 visible。
  • grouped tools 初始 hidden。
  • 模型先看到轻量 load_tools({ group })。
  • 加载某组后,从下一 step 开始,该组 schema 进入 active tools。
  • 加载事件写入 RuntimeEvent ledger。
  • 下一 turn 通过 ledger reseed 保持 active set 稳定。

13.3 为什么不做过度动态路由

per-turn semantic routing 看起来更省,但会带来:

  • prefix 更容易抖动
  • 误隐藏工具导致任务失败
  • 诊断困难
  • 权限和可见性容易混淆

Maka 选择 conservative group activation,是为了在减少 initial schema 成本和保持行为稳定之间取平衡。

13.4 Execute boundary guard

如果模型在同一个 step 里先 load_tools(browser),又立刻调用 browser_click,browser_click 还没有在 step-start active set 里。

ToolRuntime 必须在执行边界拒绝。

设计约束:

  • tool availability 控制 schema visibility。
  • PermissionEngine 控制安全授权。
  • load group 不等于获得权限。
  • active tool schema hash 只看 provider-visible active tools。

14. 设计层十:Local memory 只进入 prompt placement 设计

Local memory 是完整产品能力,但在成本线里只处理 prompt placement。

本层解决的问题:

memory 对模型有长期价值,但 memory 产品本身不应该被成本线吞掉。

为什么这里只讲 prompt placement?因为本设计关注 provider-visible request。memory 的 approval、隐私、同步、UX 是另一套产品问题。成本线只需要决定稳定 active memory 是否进入 durable prompt,以及本轮 fresh updates 是否进入 turn tail。

好处:

  • memory 对当前回复和长期偏好都能生效。
  • incognito/settings gate 仍由 memory service 控制。
  • fresh update 不会立刻污染 durable prefix。
  • 成本设计不会扩张成 memory 产品设计。

不这样做的后果:

  • 刚发生的 memory update 进入 stable prompt,导致 prefix 抖动。
  • memory disabled/incognito 情况下可能泄漏内容。
  • 成本文档开始承担 memory 产品语义,边界失焦。

14.1 Active memory

满足以下条件的 active memory 可以进入 durable system prompt:

  • 用户 opt-in
  • 非 incognito
  • 状态 OK
  • 内容经过 secret redaction
  • 长度受控

14.2 Fresh memory update

本轮刚发生的 memory writes、approval、archive/restore 更新进入 current-turn tail。

下一轮再从 durable memory state 读取。

设计约束:

  • 不把 fresh update 直接并入 durable prefix。
  • incognito/settings gate 必须在 host/service 层生效。
  • memory 文本长度要可控。

15. End-to-end request sequence

下面是一轮 cost-aware request 的设计级顺序:

1. SessionManager.sendMessage()
   - 接收外部 turn 请求

2. RuntimeKernel.startTurn()
   - 创建/注册 active run
   - 连接 stop/permission/session 状态

3. AgentRun.begin()
   - 创建 durable run envelope
   - 准备 prior runtime context

4. RuntimeRunner.invoke()
   - 定义 invocation boundary
   - 遍历 flow events
   - 统一 terminal/error/abort semantics

5. AiSdkFlow.run()
   - 调用 AiSdkBackend
   - 映射 legacy SessionEvent -> RuntimeEvent

6. AiSdkBackend.send()
   - resolve model/provider
   - build stable system prompt
   - build current turn tail
   - prepare ToolAvailabilityRuntime
   - build prior messages from RuntimeEvents
   - apply context budget
   - select synthesis/cache/archive hydration
   - compute request shape diagnostics
   - start provider stream through ModelAdapter
   - execute tools through ToolRuntime
   - normalize usage
   - compute cost
   - emit telemetry/session/runtime events

7. AgentRun.finish()
   - persist terminal run state
   - update session projection
   - close active run

这个顺序里,真正改变 provider-visible request 的点只有几个:

  • system prompt / turn tail placement
  • prior history projection
  • synthesis/compact/archive hydration
  • active tool schema
  • provider options/model

这些点必须进入 request-shape diagnostics。

15.5 设计收益总表

新人读完整套设计后,应该能把每个设计点和它解决的问题对应起来。下面这张表是整篇文档的压缩版。

问题压力 设计选择 直接收益 不这样做会怎样
total input 下降不一定更便宜 先 normalize usage,再按 cache miss/read/write/output/reasoning 算 cost 评估成本策略时不被 token 总量误导 上线“更短但更贵”的策略
成本变化无法归因 request-shape diagnostics,拆 prefixHash 和 requestShapeHash cache miss 变化能关联到 prefix/history/tool/schema 每次 regression 都靠人工猜
当前事实每轮变化 stable system prompt + current turn tail 模型看到当前事实,durable prefix 不乱抖 日期/cwd/git/memory update 污染前缀
成本线容易变成新 flow 不新建 CostRuntime,沿现有 AiSdkBackend path 安装纪律 工具、权限、usage、terminal 只有一套语义 出现两套 agent loop
历史太重但不能丢 RuntimeEvent ledger + replay projection 本轮 request 可变轻,事实仍保留 历史优化变成 destructive deletion
旧大工具结果最贵 archive-backed pruning 省 replay token,同时保留 raw evidence placeholder 没有可恢复原文
省略后还要能恢复 bounded archive hydration 需要原文时可校验恢复 prune-only 便宜但可能错,eager 全恢复又贵
summary 可能污染事实 source-bearing synthesis/compact artifact summary 有 coverage、limitations、sources 无来源 summary 长期污染 replay
工具 schema 也是 request 成本 full registry 和 active tools 分离,load_tools group activation 初始 schema 轻,prefix 变化可解释 每轮发全量工具,或动态路由不可诊断
memory 既稳定又会更新 active memory 进 durable prompt,fresh update 进 tail 长期偏好稳定,本轮更新可见 memory update 造成 prefix 抖动或隐私边界混乱

这张表也说明了一个更深层的设计收益:

Maka 把成本优化从“压 prompt”升级成“管理 provider-visible request 的事实边界”。

这句话对新人很重要。压 prompt 是局部技巧;管理 request fact boundary 是 runtime 设计。前者只关心本轮少一点,后者还关心下轮能不能解释、出错能不能回退、证据能不能追溯、checkpoint 能不能站住。

15.6 新人理解这套设计的三层收益

第一层收益:成本可观测

新人最先应该看到的是:系统不再只说“贵了”或“便宜了”。它能说:

  • 哪些 token 是 cache miss。
  • 哪些 token 是 cache hit/read。
  • 哪些 token 写入 cache。
  • output/reasoning 花了多少。
  • 这组数字对应哪个 request shape。

这让成本问题从感受变成 trace。

第二层收益:优化可解释

下一层收益是解释力。系统可以把一次成本变化归因到:

  • durable prefix
  • history projection
  • tool schema
  • provider options
  • current turn tail
  • model/provider

这让工程评审可以讨论具体设计,而不是讨论“模型是不是抽风”。

第三层收益:正确性可保护

最深一层收益是 correctness。Maka 不因为省 token 就丢掉事实:

  • ledger 保留原始 runtime facts。
  • archive 保留旧大工具结果。
  • placeholder 有 hash/source/artifact。
  • summary 有 sources/limitations。
  • hydration 有 bounds 和校验。
  • tool availability 不绕过 permission。

这让成本优化不会破坏 future replay、audit、checkpoint、raw evidence request。

一个新人如果只看到第一层,会以为这是成本 telemetry。看到第二层,会理解 request-shape diagnostics。看到第三层,才会理解为什么这是一条 runtime design line,而不是一组 prompt-compression patches。

16. 数据结构草案

以下不是最终 TypeScript API,而是设计所需的字段集合。

16.1 NormalizedUsage

type CacheMissInputSource = "explicit" | "derived" | "unavailable";

interface NormalizedUsage {
  inputTokens?: number;
  cacheHitInputTokens?: number;
  cacheMissInputTokens?: number;
  cacheWriteInputTokens?: number;
  cacheMissInputSource?: CacheMissInputSource;
  outputTokens?: number;
  reasoningTokens?: number;
}

16.2 CostBreakdown

interface CostBreakdown {
  inputCacheMissCost?: number;
  inputCacheHitCost?: number;
  inputCacheWriteCost?: number;
  outputCost?: number;
  reasoningCost?: number;
  estimatedTotalCost?: number;
  pricingSource?: string;
}

16.3 RequestShapeDiagnostic

interface RequestShapeDiagnostic {
  modelProviderHash: string;
  systemPromptHash: string;
  providerOptionsHash: string;
  activeToolSchemaHash: string;
  historyProjectionHash: string;
  prefixHash: string;
  requestShapeHash: string;
  durablePrefixChange?: string;
  requestShapeChange?: string;
}

16.4 ToolResultArchivePlaceholder

interface ToolResultArchivePlaceholder {
  kind: "archived_tool_result";
  artifactId: string;
  bodyHash: string;
  originalBytes: number;
  estimatedTokens?: number;
  toolName: string;
  toolCallId: string;
  sourceRuntimeEventId: string;
  rewriteReason: string;
}

16.5 SourceBearingReplayArtifact

interface SourceBearingReplayArtifact {
  kind: "synthesis_cache" | "history_compact";
  summary: string;
  coverage: string;
  limitations: string[];
  sourceRefs: string[];
  sourceHash: string;
  tokenEstimate?: number;
}

16.6 ToolAvailabilityState

interface ToolAvailabilityState {
  mode: "full" | "economy";
  fullRegistryVersion: string;
  activeToolNames: string[];
  loadedGroups: string[];
  stepStartActiveToolNames: string[];
}

17. Decision records

DR-1: 不新建 CostRuntime flow

结论:不新建。

原因:

  • 成本线需要的是 provider-visible request discipline,不是新 engine。
  • 复制 tool loop 会引入语义分叉。
  • 现有 AiSdkBackend 已经是 request assembly 的权威。

DR-2: prefixHash 是诊断,不是 provider cache key

结论:只作为 Maka 本地诊断。

原因:

  • DeepSeek 内部 cache key 不可见。
  • hash 只能说明 Maka 自己送出的 durable prefix 是否变化。
  • 成本判断仍以 provider usage counter 为准。

DR-3: context budget 改 projection,不改 ledger

结论:只改变本轮 replay projection。

原因:

  • RuntimeEvent ledger 是语义事实来源。
  • 删除或改写 ledger 会破坏 replay、audit、future checkpoint。
  • projection 可以针对 provider request 优化。

DR-4: archive pruning 必须 fail open

结论:archive 失败时保留原始 tool result。

原因:

  • 成本节省不能优先于证据保留。
  • placeholder 没有可信 artifact ref 时没有恢复路径。

DR-5: 工具 schema 采用 conservative group activation

结论:不做过度动态的 semantic routing。

原因:

  • active schema 是 durable prefix 的一部分。
  • 频繁动态路由可能增加 prefix 抖动。
  • 显式 load_tools 更容易进入 ledger 和 diagnostics。

DR-6: Local memory 在本设计里只处理 prompt placement

结论:不把 memory 产品语义扩进成本系统。

原因:

  • memory 的 UX、approval、隐私和同步是独立问题。
  • 成本线只关心 stable memory 是否进入 durable prefix、fresh updates 是否进入 turn tail。

18. Fallback and failure semantics

18.1 Provider usage 缺失

行为:

  • 记录可获得字段。
  • 标记 unavailable 或 derived。
  • 不伪造 explicit cache miss。

18.2 Request-shape diagnostic 失败

行为:

  • provider request 仍可继续。
  • telemetry 标记 diagnostic failure。
  • 不让诊断失败变成用户请求失败,除非它暴露了真正无法构造 request 的错误。

18.3 Archive 写入失败

行为:

  • 不替换成 placeholder。
  • 保留原 tool result。
  • 记录 archive failure diagnostic。

18.4 Archive hydration 失败

行为:

  • 保留 placeholder 或选择其他 fallback projection。
  • 不伪造 raw evidence。
  • 如果用户明确请求 raw evidence,应暴露无法恢复的诊断。

18.5 Synthesis cache invalid

行为:

  • 跳过 synthesis block。
  • 回到 archive hydration 或 raw runtime-event replay。

18.6 Tool group 未加载却被调用

行为:

  • ToolRuntime 在执行边界拒绝。
  • 不进入真实工具实现。
  • 不绕过 PermissionEngine。

18.7 Incognito 或 memory disabled

行为:

  • active memory 不进入 durable system prompt。
  • memory update tail 不应暴露禁用状态下的私有信息。

19. Telemetry contract

一次 request 的 telemetry 至少应该能把以下事实关联起来:

run id
session id
turn id
model/provider
normalized usage
cost breakdown
prefixHash
requestShapeHash
component hashes
context budget diagnostics
archive prune/hydration diagnostics
synthesis/compact diagnostics
active tool schema diagnostics
tool availability mode

这些字段的关系比任何单个字段都重要。

例如,cache miss 上升时,评审者应该能同屏看到:

  • cache miss 数字
  • cache miss source
  • prefixHash 是否变化
  • active tool schema hash 是否变化
  • history projection hash 是否变化
  • 本轮是否发生 archive hydration 或 synthesis 替换

20. 测试策略

20.1 Usage normalization tests

覆盖:

  • explicit DeepSeek cache miss
  • derived cache miss
  • missing cache fields
  • reasoning token extraction
  • cost split computation

20.2 Request shape tests

覆盖:

  • system prompt 改变 -> prefixHash 改变
  • history projection 改变 -> requestShapeHash 改变,prefixHash 不变
  • active tool schema 改变 -> prefixHash 改变
  • current turn tail 改变不应被误归类为 stable system prompt change

20.3 Context budget tests

覆盖:

  • ledger 不被 budget 改写
  • stale tool result archive 成功后 placeholder
  • archive 失败后保留原文
  • synthesis cache source mismatch 后跳过
  • raw evidence request 跳过 synthesis
  • history compact block 带 coverage/limitations/sources

20.4 Tool availability tests

覆盖:

  • economy mode 初始只暴露 ungrouped tools 和 load_tools
  • group load 后下一 step 可见
  • same step 未加载工具调用被拒绝
  • loaded group 从 ledger reseed
  • PermissionEngine 仍然独立执行

20.5 End-to-end paid or trace tests

覆盖:

  • total input 下降但 cache miss 上升的反例能被解释
  • archive hydration gated/eager/prune-only matrix 能比较 correctness/cost
  • tool schema economy 对 request shape diagnostics 可见
  • prompt placement 能减少无意义 durable prefix 抖动

21. 实施切片

这条线应该按可验证边界落地,而不是一次性大改。

Slice 1: Usage and cost are trustworthy

目标:

  • normalized usage 字段稳定。
  • cost breakdown 不再只看 total input。
  • telemetry 能区分 explicit/derived/unavailable。

验收:

  • focused tests 覆盖 DeepSeek/OpenAI-compatible usage shapes。
  • 真实 trace 能看到 cache hit/miss/write/output 拆分。

Slice 2: Request shape is explainable

目标:

  • prefixHash / requestShapeHash 稳定输出。
  • component hash 能解释变化来源。

验收:

  • 改 system prompt、history、tool schema 的 fixture 能分别命中不同 diagnostic。

Slice 3: Prompt placement is disciplined

目标:

  • volatile facts 进入 turn tail。
  • stable rules/memory 进入 durable system prompt。

验收:

  • cwd/git/date 变化不造成 system prompt hash 抖动。
  • fresh memory update 只在当前 turn tail 出现。

Slice 4: Replay projection is budgeted but recoverable

目标:

  • context budget 只改 projection。
  • stale tool result archive-backed prune。
  • hydration 有校验和 bounds。

验收:

  • archive 成功才 placeholder。
  • archive 失败保留原文。
  • raw evidence 可以恢复或明确失败。

Slice 5: Summary artifacts are source-bearing

目标:

  • synthesis/compact block 都带 coverage、limitations、sources。
  • source mismatch 或 raw evidence request 时跳过。

验收:

  • summary 无来源不能进入 replay projection。
  • invalidation 规则有测试。

Slice 6: Tool schema economy is active-set based

目标:

  • full registry 和 active provider-visible tools 分离。
  • load_tools group activation 进入 ledger。
  • active-only schema hash 进入 request-shape diagnostics。

验收:

  • same-step unavailable tool execution 被拒绝。
  • loaded groups 在下一 turn 可 reseed。

22. 开放问题

22.1 Request shape diagnostics 的持久位置

现在需要决定 diagnostics 最终应该写在哪里:

  • run telemetry
  • runtime event action
  • session projection metadata
  • 独立 request trace table

建议优先写到 run/request telemetry,再视 UI/read model 需要投影。

22.2 Context budget policy 的配置边界

DeepSeek 默认是否启用某些 budget 策略,不能只凭 total input。需要基于 paid matrix 和 workload 分类。

建议默认保守,先 expose diagnostics,再逐步启用策略。

22.3 Child run replay 和 subagent summary

当前 top-level replay 默认不混入 child runs。未来如果子代理成果需要进入主历史,应该通过 explicit source-bearing summary,而不是直接混入 child runtime events。

22.4 Checkpoint / warm retry

成本线为 checkpoint 提供了更清楚的事实边界:

  • run status
  • invocation terminal
  • runtime-event high-water mark
  • workspace snapshot
  • context budget projection
  • provider request diagnostics

但本设计不直接实现 checkpoint。它只是避免成本 projection 破坏 future checkpoint 的事实基础。

23. 评审清单

评审这条线时,可以按以下问题检查:

  1. 这个改动有没有复制模型/工具循环?
  2. 这个改动有没有改变 provider-visible request shape?如果有,diagnostics 能解释吗?
  3. 这个改动有没有把 volatile facts 放进 durable system prompt?
  4. 这个改动有没有把 projection 改写成 ledger fact?
  5. 这个改动有没有无来源地删除 tool result?
  6. 这个改动有没有把 summary 当事实来源?
  7. 这个改动有没有混淆 tool schema visibility 和 permission authorization?
  8. 这个改动有没有把 prefixHash 当 provider cache key?
  9. 这个改动的 fallback 是 fail safe 还是 fail closed/hidden?
  10. 这个改动能否通过 trace 解释 cache miss 变化?

24. 最终设计结论

Maka DeepSeek-Reasonix 成本运行线的系统设计,不是“把 prompt 压短”,也不是“为 DeepSeek 新建一个 flow”。

它是一套沿着现有 runtime 主线建立的 provider-visible request discipline:

算清 usage
  -> 绑定 request shape
    -> 稳住 durable prefix
      -> 把 volatile facts 放进 turn tail
        -> 从 RuntimeEvent ledger 派生 replay projection
          -> 对旧大工具结果先 archive 再 placeholder
            -> 按相关性和 bounds 恢复 archive
              -> 用 source-bearing summary/compact 替代无来源压缩
                -> 按需暴露 provider-visible tool schema
                  -> 把所有变化写进可解释 telemetry

这条线的价值不在于某一个优化技巧,而在于把成本问题变成可以观察、可以解释、可以回退、可以维护的 runtime 设计。

如果未来要继续演进,最重要的不是先增加更多 budget 策略,而是守住本文的几个边界:

  • 现有 runtime path 是主路。
  • Provider-visible request shape 必须可诊断。
  • RuntimeEvent ledger 是事实,不是压缩对象。
  • Replay projection 可以优化,但必须有来源和 fallback。
  • Tool schema visibility 是成本面,但不是权限面。
  • Local memory 只在 prompt placement 维度参与成本线。

守住这些边界,Maka 才能在不牺牲 correctness 和可恢复性的前提下,继续把 DeepSeek 这类 cache-sensitive provider 的成本问题做深。

25. Source index

教学和设计材料:

  • docs/architecture/runtime-core-architecture-draft.zh-CN.md
  • docs/architecture/durable-task-loop-headless-draft.zh-CN.md
  • DeepSeek-Reasonix cost-runtime Rive reading artifacts from workflow maka.deepseek-reasonix-cost-mainline
  • DeepSeek-Reasonix beginner teaching guide and fine outline from workflow maka.deepseek-reasonix-deep-read

主要源码入口:

  • packages/runtime/src/model-adapter.ts
  • packages/runtime/src/telemetry/cost.ts
  • packages/runtime/src/request-shape.ts
  • packages/runtime/src/ai-sdk-backend.ts
  • packages/runtime/src/context-budget.ts
  • packages/runtime/src/tool-availability.ts
  • packages/runtime/src/tool-runtime.ts
  • apps/desktop/src/main/main.ts
  • apps/desktop/src/main/synthesis-cache-artifacts.ts
  • packages/runtime/src/history-compact-artifacts.ts
  • packages/core/src/local-memory.ts
  • apps/desktop/src/main/local-memory-service.ts