Repository avatar
AI Tools
v0.4.9
active

dobocache

io.github.dobo123123/dobocache

MCP server for LLM prompt-cache observability: prefix diagnostics and per-call white-box report.

Documentation

简体中文 · English


DoboCache v0.4.9

命中缓存 + 白盒报告 —— 每一步都看得见、可复算。

DoboCache 是一个以 stdio 方式挂载的 MCP Server,作用是在你已有的编码 CLI / Agent 客户端和模型厂商 API 之间,把每一次请求的上下文整理成稳定、可复用、过长会自动补足的前缀,从而让厂商的**前缀缓存(prompt caching)**真正命中;命中与否、命中多少、哪一步做了调整,全部写进本地白盒日志并可随时查询。

先看硬数据:20 次连续请求对照(同一台机器、同一后端模型、同一套参数,只区分挂没挂)

请求端形态20 次请求 · 不挂载20 次请求 · 挂载 DoboCache
COD-X:Codex 系编码 CLI(后端模型 GLM,即「厂商 G」)0.00%(20/20 次全为 0)98.59%(区间 96.08% – 99.79%,20/20 次命中)
DSH:DeepSeek 官方 Harness headless(后端模型 DeepSeek,即「厂商 D」)66.00%(这 66% 全部来自它自带的约 2,560 tokens 系统前缀)96.85%
WBX:本工具自研白盒直连(不做任何前缀处理)0.00%(结构性零基线:这个请求端本来就没有前缀可命中)93.09%

读法只有一条:同一形态内部横着比「挂 vs 不挂」。跨形态的对照组不可互比——对照组的高低由请求端自己有没有前缀处理决定,与 DoboCache 无关。 逐次 usage、任务原文、复跑脚本全部随包提供,任何一行都能自己复算 → §四 实测数据


官方入口声明 DoboCache 的官方代码仓库只有 https://github.com/dobo123123/dobocache 一处,官方发布物只在它的 Releases 页面。 在其他渠道看到同名项目、同名服务或付费版本,均非官方出品。本项目免费,不通过任何第三方平台售卖。

第一次用?请先看 零基础三分钟上手 —— 从装 Node 到验证成功,六步走完,不用懂原理。 装的过程中报错,直接翻 FAQ 的「安装报错速查」,按报错原文查。

装不上、配不通、不知道怎么写配置?先看上面的 FAQ;还不行就到 Discussions 提问(安装类问题不用开 Issue)。

平台支持状态(装之前先看这一节)

DoboCache 是纯 JavaScript 的 stdio MCP Server,包内不含任何原生二进制(.node / .exe / .dll 数量均为 0),因此不存在 ABI 层面的平台锁定。但"能跑"和"验证过"是两件事,本版按实际验证程度如实标注:

平台状态验证到什么程度
Windows 10 / 11(x64)✅ 主打平台,已真机验证真机端到端跑通:本组实验 20 次连续请求对照(含真实 MCP 客户端挂载 + 厂商 usage 校验)、便携包解压即跑冒烟、全量 95 项测试通过、日志落盘实测 %LOCALAPPDATA%\DoboCache\logs
Linux(x86_64)🟡 容器环境已实测(非桌面真机)2026-11-04 在 Docker linux/amd64 + Node 官方 Linux 镜像内对发布包做真实运行:解压即跑、initialize/tools/list 返回合法、9 个工具全在、cf_judge 命中、cf_inject 返回 prefixReady=true、日志按 ~/.local/state/dobocache 落盘、XDG_STATE_HOME 生效、DOBOCACHE_LOG_DIR 优先级最高、只读目录降级不崩溃、Node 16 自检 exit 1。桌面 Linux 真机 + 图形客户端挂载、arm64 仍未验证(细节见 兼容性说明.md 附录 A)
macOS(Apple Silicon / Intel)🟡 CI 真机冒烟已通过(非长期使用验证)CI 的 macOS job 在真实 Mac 机器上跑通:npm ci → tsc → eslint → vitest → MCP stdio 握手(initialize + tools/list 恰好 9 个工具)+ 日志目录断言(必须落在 ~/Library/Logs/DoboCache 且 logDirSource=platform)。Apple Silicon(macos-latest)与 Intel(macos-13)两个架构都在矩阵内,最近一次全绿见 Actions。仍缺:真实桌面客户端(如各类编码 CLI)挂载后的长会话实测

我们把边界说清楚:

  1. Windows 是主打平台,也是唯一做过真机端到端验证(真实客户端挂载 + 厂商 usage 回读)的平台;
  2. Linux 已在 linux/amd64 容器环境做过真实运行验证(协议链路 + 日志 + 只读降级 + Node 版本自检),但桌面发行版的图形客户端挂载、arm64 仍未验证;macOS 侧 CI 已在 Apple Silicon 与 Intel 真机跑通冒烟链路,但没有做过桌面客户端的长时间会话实测。因此 macOS 只写"CI 冒烟已通过",Linux 只写"容器已实测",都不写"完整支持";成功率我们没有真实数据,不做任何百分比承诺;
  3. 欢迎反馈后修:在 Linux / macOS 上跑通或跑挂,都请反馈。我们不把这些平台当作"理论上没问题所以不用管"。

反馈渠道

渠道怎么用
GitHub Issues(推荐)标题带 [platform: macOS] 或 [platform: linux];正文附 node -v、uname -a(macOS 用 sw_vers)、cf_report 返回的 logDir / logDirSource、完整报错原文
私下联系(非公开)安全类问题请走 SECURITY.md 的私下上报渠道(GitHub Security Advisories),不要在公开 issue 中披露;一般问题走 Issues 即可。本项目当前不公开电子邮件地址,以避免维护者个人邮箱被骚扰、撞库或用于社工攻击
自查(反馈前先看)release/FAQ-使用须知.md §三(日志在哪)与 §七(prefixReady=false 怎么办),可解决大部分"看起来没生效"的问题

反馈时不要把提问原文粘进 issue:日志已脱敏(req-<hash> / sid-<hash>),贴日志片段足够定位问题。


一、它解决什么问题

现代厂商 API 都提供前缀缓存:请求开头部分如果与上一次完全一致,这部分 token 按缓存价计费,不再全价重算。但真实对话里前缀经常"差一点点":

  • 系统提示词顺序不稳定、拼接顺序每次不同;
  • 历史消息被裁剪后长度对不齐缓存块边界(常见是 128 token 对齐);
  • 前缀长度小于厂商的最小缓存门槛,压根不进入缓存;
  • 重复指令、重复文档块让前缀越来越长却越来越脏。

任何一处不一致,缓存就整个失效——你以为在用缓存,其实一直在全价重算。DoboCache 就是把这些"差一点点"逐条修掉,并且把每一步的调整原因写清楚,让你能自己核对而不是只看一个漂亮数字。

二、九个可调用的工具(8 个业务工具 + 1 个 ping 健康检查)

server 共暴露 8 个业务工具 + 1 个健康检查(ping),均为 stdio 本地调用,不联网、不上传:

工具作用是否写盘
cf_judge命中判定:关键词分层(实体锚词/意图修饰词)→ 三层匹配 → 时效衰减 → 负向过滤,输出可解释证据(hit / score / evidence / matched)记白盒日志
cf_tier价值分级准入:提纯去噪 → A/B/C 分级 → 按预算从高到低填充,输出准入列表与丢弃明细否
cf_inject记忆提纯注入:把上下文整理成稳定前缀(去重 → 128 token 对齐 → 过门槛补足),返回可直接发送的 prefix / tail记白盒日志、冻结会话前缀(内存)
cf_warmup预热:正式请求前显式调用一次,用冻结前缀构造最小占位请求,触发厂商前缀缓存建立(会产生少量计费,需自行发一次 LLM 请求)否
cf_report白盒累计统计:累计命中率、原始/优化 token、按会话聚合(per_session),并回传日志实际落点 logDir / logDirSource;加 source="disk" 时改为从本地日志重新聚合(跨进程、跨天累计,客户端重启不清零),days=<n> 限定只读最近 n 天否(读日志)
cf_meter请求计量快照(token 计数与计价相对值,不含任何请求正文)否
cf_prune工具输出确定性修剪:去重行、压缩空白、行数/字符数双上限,返回修剪前后体积比否
cf_normalize结构化结果归一:字段裁剪 + 稳定排序,返回不含原文的键值(nk-<16 位 hash>)否

典型参数:cf_inject(reset=true, sessionId=<你的会话标识>, minPrefixTokens=<目标厂商门槛>)。

参数在协议层做类型与范围校验(如 threshold ≥ 0、topK ≥ 1、maxChars ≥ 1、maxTokens > 0),越界会返回标准 -32602 校验错误并指明字段,不会静默生效。

三、版本说明(请先读这一节)

v0.4.9 = 发布通道切换版。npm 已公告自 2027-01 起限制「可绕过 2FA 的长寿命 token」直接发布,本版把发布通道整体切到 GitHub Actions OIDC Trusted Publishing:打 tag 时由 GitHub 签发短期令牌、npm 侧校验后直接收包,仓库与其设置里不再存放任何发布密钥,产物附带 provenance 签名、可追溯到具体 commit 与工作流运行。代码与缓存核心零改动,行为与 v0.4.8 逐字节一致。

项目说明
承接v0.4.7 的日志边界(单文件 10MB 轮转 + 默认保留 7 天)、cf_report 的 source="disk" 读盘聚合、cf_prune 口径澄清全部保留;更早的 v0.4.4 minPrefixTokens 修复与日志隐私脱敏(requestId → req-<8 位 hash>;sessionId → sid-<8 位 hash>;cf_normalize 键 → nk-<16 位 hash>)也仍在
本版改动① 对照图不再破图:两张对照图(命中率对照 / 三种请求端形态)改用 raw.githubusercontent.com 绝对地址,npm 包页面可直接显示出来;② 文档链接不再 404:根 README 里 9 处指向包内文档的相对链接(零基础上手 / FAQ / 兼容性说明 / SECURITY / LICENSE / 英文版 / 中文版)改为 GitHub 绝对地址,在 npm 页面上点击即可跳转;③ 便携包内文档保持原样:release/README.zh.md、README.en.md 继续用同目录相对路径——包内文档与图同目录,解压后离线也能看,两套路径各司其职
命中相关代码无代码改动。缓存核心(前缀冻结 / 对齐 / 分级准入 / 判定逻辑)与 v0.4.7 一致,dist 行为逐字节相同,仅 serverInfo.version 随版本号更新;默认档位下 cf_judge / cf_inject 返回只有一段 JSON、不含卡片
冒烟验证MCP stdio 冒烟通过(2026-11-07 本机 win32 实跑):serverInfo.version = 0.4.9、protocolVersion = 2024-11-05、9 工具齐全(ping/cf_judge/cf_tier/cf_inject/cf_meter/cf_warmup/cf_report/cf_prune/cf_normalize)、cf_judge 真实调用落盘成功(dobocache-2026-11-07.log.jsonl)、cf_report 返回 logDir / logDirSource(实测 calls=1、hitRate=80)
测试95 / 95 通过;tsc --noEmit 零报错;eslint src test 零告警
平台验证Windows 真机端到端已验证;Linux 已在 linux/amd64 容器内实测运行(协议链路 / 9 工具 / 日志分支 / 只读降级 / Node 版本自检,见「平台支持状态」与 release/兼容性说明.md);macOS 侧 CI 在 Apple Silicon 与 Intel 真机跑通冒烟链路(握手 / 9 工具 / 日志目录 / 构建与单测),桌面客户端长会话未实测
不宣称本版不是性能提升版,也不是功能版。命中率与 v0.4.7 / v0.4.4 完全相同,请勿把本文任何数字读成「新版本更高」

为什么会有 v0.4.3:v0.4.2 正式包里,injectIncremental 第 4 步 topUpPrefixToMin(...) 之后缺少 prefix = topUp.prefix;,导致补足结果没有接回、参数形同虚设。DeepSeek 系默认门槛低(295),正常前缀本就够长,所以一直没暴露;GLM 系真实门槛 1806+,必须靠补足才能过线,一补不上立刻露馅——这就是回归用 GLM 系做回归的原因。v0.4.3 补上了这一行。

四、实测数据(20 次连续请求对照)

本组实测:同一套 20 次递进式连续话题。请求端为 COD-X(Codex 系编码 CLI),后端模型接 GLM;白盒引擎以 stdio MCP 挂载 DoboCache;同一台机器、同一后端模型、同一套参数,只区分"挂载 / 不挂载"。这一形态一共跑了两轮完整 20 次(组 7 / 组 8),两轮挂的是不同版本——逐轮对比见本节末「两轮 20 次同口径复跑」。

代号一览(写成能认出来的样子,不做过度匿名)

代号是什么后端模型
WBX本工具自研的白盒直连请求端(不是任何官方客户端),故意不做任何前缀处理,专门用来测零基线—
DSHDeepSeek 官方 Harness 的 headless 模式DeepSeek
COD-XCodex 系编码 CLIGLM(智谱)

早期档案里把模型厂商记作「厂商 D」(DeepSeek)/「厂商 G」(GLM),本文起统一写成厂商名本身,读表时不必再猜。表中只报命中率与相对比例,不报任何金额;成本相关字段按 §六 的计价系数折算相对值。

对照组 vs 实验组 命中率对照

指标对照组(不挂载)实验组(挂载 DoboCache)
20 次请求命中率均值0.00%(20/20 次全为 0)98.59%
区间—96.08% – 99.79%
零命中请求数20 / 200 / 20
前缀就绪(prefixReady=true)—20 / 20
实际生效门槛 effectiveMinPrefixTokens—3450(= 3000 × 1.15,配置已生效)

为什么对照组读到 0 —— 因果链就三句话

  1. 每轮请求的头部都被注入了不同的随机噪音,所以两轮之间开头的第一段就不一样;
  2. 厂商前缀缓存只认"与上一次完全一致的开头",开头一变,已建立的那段缓存整段作废,本次请求从头到尾都按未命中算;
  3. 20 轮里每一轮都这样漂移,于是 20/20 次读数都是 0,均值自然 0.00%。

所以这 0 不是"厂商缓存不行",也不是"对照组被故意做坏",而是前缀不稳时前缀缓存的真实表现。本组的 0 与 WBX 的 0 成因不同:WBX 是结构性零基线(那个请求端干脆不做任何前缀处理,天生没有可命中的前缀);COD-X 组是噪音压力下的零(前缀本来可以有,被漂移打散了)。两者都不是 DoboCache 的作用结果,只有同一形态里"挂 vs 不挂"的差才是。

关键读法,请连同三条一起看:

  1. 对照组每次都注入了不同的随机噪音制造前缀漂移,所以 20 次全 0——这不是"对照组很差",而是"前缀一变,厂商前缀缓存就整段失效"的真实写照;
  2. 实验组 20 次全部命中,前缀 prefixTokens 稳定落在 3456–4480,每一次 prefixReady 均为 true;
  3. 命中率是单次请求输入内部的缓存命中占比,不是绝对 token 节省量。两组输入量本就不同(对照组输入随请求次数从 39 累积到 2738 tokens,实验组稳定在"前缀 + 尾部"),因此不可跨组直接换算成绝对 token 数,也不要在不同实验之间横向混比。

把视角拉高一层:不挂载并不总是 0%。 命中率不是只由"挂不挂"决定,请求端自己怎么构造请求,决定了对照组的起点。同一套挂载逻辑换到三种请求端形态各跑 20 次:

先把三个请求端分别是什么讲清楚——对照组起点之所以差这么多,全在这里:

形态请求端是谁请求端自身是否做前缀处理对照组为什么是这个数
A · WBX 白盒自研直连DoboCache 自研的白盒测试底座(为跑对照实验自己写的直连请求端,不是任何官方客户端)不做,一点都没做:不构造前缀、不预热缓存、不复用会话,每轮只发「任务原文 + 随机噪音」20 次累计命中 0 / 28,846 tokens。请求端手里没有任何可复用的前缀,基线因此恒为 0.00%,属结构性零基线,不是"缓存被打崩"
B · DSH DeepSeek 官方 Harness headlessDeepSeek 官方客户端(headless 模式),后端模型 DeepSeek做,且由客户端与厂商侧共同保证:每次新会话固定注入约 2,560 tokens 的厂商全局系统前缀20 次累计命中 51,200 / 77,576 tokens = 66.00%;51,200 正好等于 2,560 × 20,可自行验证这 66% 全部来自官方前缀,与 DoboCache 无关
C · COD-X Codex 系编码 CLICodex 系编码客户端,后端模型 GLM(智谱)不固定:无全局系统前缀,只有历史长前缀恰好稳定时才偶发命中组 8 全 20 次为 0;组 7 仅 R10 / R20 自然命中,逐次均值 9.87%

一句话讲明白:A 的 0% 是"这个请求端本来就没有前缀可命中"(我们自己搭的底座,故意什么都不做,用来测零基线);B 的 66% 是"官方客户端自带前缀垫在下面"。两者都不是 DoboCache 的作用结果。 这三个起点只说明一件事——对照组的高度由请求端自身的前缀处理能力决定。所以本表只能横着读同一形态内的「挂 vs 不挂」,不能竖着比"谁的对照组更高",更不能把跨形态百分比相减当作本方案的提升幅度。

三种请求端形态对照:不挂载 vs 挂载

请求端形态版本 · 实验来源对照组(不挂载)实验组(挂载)说明
A · WBX 白盒自研直连v0.4.0 · 实验 0310.00%93.09%自研白盒底座,未做任何前缀处理(结构性零基线)
A · WBX 白盒自研直连v0.4.2 · 实验 0320.00%91.89%同上
B · DSH DeepSeek 官方 Harnessv0.4.0 · 实验 03366.00%96.85%请求端自带约 2,560 tokens 全局系统前缀缓存;对照组随噪音累积由 84.27% 劣化到 54.54%
B · DSH DeepSeek 官方 Harnessv0.4.2 · 实验 03468.09%95.91%同批对照组基线同样来自厂商系统前缀缓存;实验组每轮未命中压至 135–426 tokens
C · COD-X Codex 系编码 CLI(后端 GLM)v0.4.2 候选修复构建 · 组 79.87%90.58%对照组 18/20 次为 0,R10/R20 因长历史前缀自然命中
C · COD-X Codex 系编码 CLI(后端 GLM)v0.4.3 · 组 80.00%98.59%即上表本组主数据

三条读法:

  1. 形态 B 的 66%–68% 不是 DoboCache 的功劳,也不是"提升幅度小"——那是请求端自己就挂了全局系统前缀缓存,对照组天生占便宜;而它随噪音累积一路劣化(84.27% → 54.54%),恰恰说明这种请求端的缓存同样脆弱;
  2. 三种形态的对照组起点从 0% 到 68%,差别全在请求端怎么构造请求,跨形态的对照值不可互比;唯一可比的是同一形态内部的"挂 vs 不挂";
  3. 挂载后三种形态都落在 90%–98%,说明"静态前缀复用"这件事与请求端形态无关,不是某一家请求端的特例。
  4. 口径提醒(比数字本身更要紧):形态 A / B 是「20 次请求累计口径」(累计命中 tokens ÷ 累计 prompt tokens),形态 C 是「20 次逐次请求命中率的均值」——两种统计算法不同,跨形态只能看量级,不能拿百分比互相加减;同一形态内部的「挂 vs 不挂」才是同口径对比。

两轮 20 次同口径复跑:后一版强在哪

COD-X 这一形态跑了完整两轮,每轮 20 次,两轮只差挂载的版本——这是本项目唯一一组「同形态、同任务、不同版本」的对照:

轮次挂载版本对照组(不挂载)实验组(挂载)20 次里出现异常读数的次数
组 7v0.4.2 候选修复构建9.87%90.58%3 次(53.08% / 85.53% / 0.00%)
组 8v0.4.30.00%98.59%(96.08% – 99.79%)0 次

两轮的对照组构造完全一样(每轮开头注入不同随机噪音,故意让前缀漂移),所以「组 7 = 9.87%、组 8 = 0.00%」不是"版本越高、不挂载越差",只是噪音本身的随机性:

  • 组 7 里 R10、R20 两次,历史已累积到 10 轮 / 19 轮,长历史前缀足够长,厂商侧缓存自己对上了,读到 99.27% / 98.10%;其余 18 次被打散读 0,20 次平均才 9.87%;
  • 组 8 那 20 次的噪音把前缀全部打散,次次为 0,均值 0.00%。

那么"后一版更强"强在哪——三件具体的事,都不是把均值往上抬:

  1. 抖动清零:组 7 的 20 次里有 3 次被厂商侧抖动打到 53.08% / 85.53% / 0.00%;组 8 的 20 次一次抖动都没有,prefixReady 20/20,区间收在 96.08% – 99.79%;
  2. 下限抬升:最差的一次读数从 0.00% 抬到 96.08%。缓存工具真正影响体验的是"偶尔一次完全没吃到",这一项从有到无;
  3. 真实缺陷被修掉:v0.4.3 补回了 injectIncremental 里 topUpPrefixToMin(...) 之后缺失的 prefix = topUp.prefix;——补足结果之前根本没接回下游,参数形同虚设。DeepSeek 系默认门槛低(295),正常前缀本就够长,所以一直没暴露;GLM 系真实门槛 1806+,必须靠补足才能过线,一补不上立刻露馅。这也是本套回归一律挂在 COD-X + GLM 上跑的原因:它是最严的那道门。

同时把话说全:剔除抖动轮次后,两版的稳定段是持平的——组 7 剩下 17 次均值 98.41%,组 8 同位置剔除后 98.57%,只差 0.16pp。所以请不要把「90.58% → 98.59%」读成"版本升级带来 8 个点提升";版本迭代真正在做的是把"稳"从偶发变成每次、把"会掉到 0"变成"掉不下去",稳定段的命中水平既没注水,也没夸大。逐次对照见 release/testdata/hitrate-regression-report-20261103.md 第六节。

这两个数还反过来说明一件对本工具"不算功劳"的事:厂商自带缓存本身很好用——只要前缀稳定,它能吃到接近 99%。 全程的卡点只有一件事:前缀稳不稳。DoboCache 做的是把前缀稳定下来、让"稳"发生在每一次请求上,不是凭空制造命中。所以「不挂载 0%–9.87%」是压力条件下的读数,既不是"厂商缓存很差",也不该被读成"挂上就从 0 涨到 98 个点"。

统一口径:不挂载约 0%–68%(随请求端形态浮动),挂载后 90%–98%。表中每一行都能落到实验档案的实测记录上(实验 031 / 032 / 033 / 034 与组 7 / 组 8),并与汇总 CSV 的 source_exp / recompute_file 字段一一对应:release/testdata/hitrate-multi-platform-summary-20261105.csv——形态 A / B 的分子分母以 token 列同表落盘,形态 C 为逐次均值、逐次数据在同目录,任一行都可自行复算。逐次曲线与重绘图脚本见 release/scripts/hitrate-comparison.py。本表不含任何估算值或取整凑数。

关于测试规模:一句实话

这套数据来自 8 组对照实验,正式组每组 20 次连续请求,另有两组 5 次、10 次的前期门槛探测。

但要先把边界讲清楚:这些测试的单次请求体量都很小——每轮输入是同一份 AI 资讯盘点话题,前缀几百到数千 tokens,任务原文与逐次 usage 都在 release/testdata/,谁都能自己算一遍。

我们没有测「特别长的长任务」:单轮上万 tokens 的长文档问答、整个代码库的分析、几十轮的超长会话,都不在样本里。缓存前缀复用在这种体量下是否一样成立,我们没测过,也不打算替它下结论。

如果你手上正好有这类长任务,欢迎自己挂上去跑一遍再回来说话——把逐次 usage 记下来,比我们的任何承诺都有用。这也正是我们把逐次数据、任务原文、复跑步骤全部放进包里的原因:让你能自己验证,而不是只能信我们。

五、白盒报告:每一步都看得见

每次 cf_judge / cf_inject 之后,白盒日志会记录这一步做了什么、为什么做、效果如何。下面是一条按当前口径(v0.4.9)输出的记录示例:

{
  "requestId": "req-1b0ff98f",
  "ts": 1793709231484,
  "reqIndex": 2,
  "promptChars": 36,
  "rawTokens": 201,
  "optimizedTokens": 4096,
  "hitRate": null,
  "savedTokens": 0,
  "savedPct": 0,
  "changes": [
    {"kind": "align128", "label": "前缀 128-token 对齐:减少尾部部分命中", "detail": "追加 98 个对齐块"},
    {"kind": "topup",    "label": "前缀过门槛补充:达到最小有效缓存长度", "detail": "补充 63 块(高价值片段/文档块)"},
    {"kind": "scenario", "label": "首条请求或缓存为空:轻量约束放行自由回答"}
  ],
  "note": "cf_inject:原始 201 tokens → 优化后 4096 tokens(前缀 4096 + tail);实际门槛 3450 tokens。",
  "sessionId": "sid-b6ca1662",
  "scenario": "first",
  "mode": "rebuild",
  "alignBlocks": 98,
  "prefixTokens": 4096
}

三类常用对照能力都在:第几次请求(reqIndex)、是否同一提问(req-... 相同即同一提问)、每一步动了什么(changes[] + note)。内容本身不落盘。

记录里 hitRate 为 null 表示本次请求未判定:cf_inject 处在注入阶段、请求尚未发出,且调用方没有把厂商返回的缓存 usage 回传给 DoboCache,本机就无法得知真实命中率——此时如实记 null(未判定),不再写 0。看到 null 不要读成"命中率 0%":要得到可判定的命中率,请在 cf_judge / cf_inject 里带上 hitTokens / missTokens(取自厂商 usage 的 prompt_cache_hit_tokens / prompt_cache_miss_tokens)。累计统计用 cf_report 查看。详见 FAQ-使用须知.md 第一节。

白盒报告默认关闭(v0.4.6)

白盒报告卡片是给你看的,但它写进对话上下文就要占 token(每张约 300+ tokens,每次工具调用都可能带一张)。因此从 v0.4.6 起:

  • 默认(quiet):报告只写本地日志,不随工具返回,不占对话 token;
  • 想看累计数据:随时调 cf_report,它读本机日志、不产生额外 token;
  • 想看每次的详情:设环境变量 DOBOCACHE_WHITEBOX:
    • once —— 下一次调用返回一次详情,之后自动回落 quiet(适合临时排查一次);
    • always —— 每次调用都带详情(适合正在做对照实验,代价就是每张卡的 token);
    • quiet —— 关闭(默认值,等价于不设);
  • 首次运行提示:本机第一次跑时会给一条一次性提示(告诉你白盒在哪、怎么开),之后永不再出。
档位是否随调用返回报告占用对话 token适用
quiet(默认)否,只写本地日志无日常使用
once只返回一次,随后自动回落 quiet一次性排查"到底有没有生效"
always每次都返回每次约 300+ tokens做对照实验、需要逐次读数时

一句话:平时不用管它;需要证据时用 cf_report(不花 token),需要看单次细节时再开 once / always。

六、安装与挂载(三种启动写法)

  1. 从 Releases 下载 dobocache-v0.4.9-portable.zip 并解压(内含 dist 与仅生产依赖的 node_modules,无需 npm install;包内不含任何原生 .node 二进制,换机器换平台不会因 ABI 不匹配崩掉);不想下载也可以用下文写法 B / C 从 npm 装;
  2. 在你所用客户端的 MCP 配置里加一个 stdio server(下面三种写法任选其一);
  3. 重启客户端,确认工具列表里出现 9 个(ping + cf_judge / cf_tier / cf_inject / cf_warmup / cf_report / cf_meter / cf_prune / cf_normalize)。少任何一个都说明 server 没起来,先看客户端日志里的 stderr。

前置条件:Node.js 18 或更高。进程启动时会自检,版本过低会直接打印一句中文提示然后退出(不会静默失效)。 通用建议:配置里的路径一律填绝对路径——客户端拉起 server 时不继承你 shell 的当前目录与 PATH,只写 node 或相对路径是最常见的翻车原因。

写法 A:绝对路径 node + 入口 js(推荐)

Windows:

{
  "mcpServers": {
    "dobocache": {
      "command": "C:\\Program Files\\nodejs\\node.exe",
      "args": ["D:\\<解压目录>\\dist\\index.js"]
    }
  }
}

macOS / Linux:

{
  "mcpServers": {
    "dobocache": {
      "command": "/usr/local/bin/node",
      "args": ["/Users/<你>/dobocache/dist/index.js"]
    }
  }
}
  • 适用:便携包解压即用、内网/离线机器、客户端以非登录用户或非常规工作目录拉起。
  • 怎么找 node 路径:Windows where node;macOS / Linux which node(Homebrew 常见 /opt/homebrew/bin/node、/usr/local/bin/node;用 nvm 的请填具体版本目录下的绝对路径)。
  • 该写法不需要 npm、不联网,跨机器最稳。

写法 B:npx -y 一次性运行

ℹ️ 渠道说明:写法 B / C 要求该版本已能从 npm registry 取到。若 npm view dobocache 返回 404(该版本尚未发布,或所用镜像尚未同步),请直接用写法 A(便携包)——功能、内容与日志行为完全一致,不需要改任何配置。

关于仓库内的 server.json:它是提交给 MCP Registry 的条目描述文件,其中 packages[].registryType 只有 npm / pypi / oci 等固定取值(schema 不存在"便携包"这个类型),因此 identifier / version 标注的是 npm 上的发布目标;若 npm 上暂时取不到该版本,一律以写法 A 为准。

{
  "mcpServers": {
    "dobocache": {
      "command": "npx",
      "args": ["-y", "dobocache@0.4.9"]
    }
  }
}
  • ⚠️ Windows 上必须写 npx.cmd("command": "npx.cmd")。npm 在 Windows 上只安装 npx.cmd,没有 npx.exe,客户端 spawn("npx") 会直接报 ENOENT——这是 MCP 客户端在 Windows 上最高频的报错。
  • macOS / Linux 保持 npx 即可;若客户端用非登录 shell 拉起且 PATH 里没有 node,可写死绝对路径(如 /usr/local/bin/npx)。
  • 适用:希望自动跟随版本、机器可联网、不想手工解压。
  • 前提:该版本能从 npm 取到(npm view dobocache@0.4.9 version 能返回版本号);取不到时改用写法 A。另外 npx 有本地缓存,升级后行为仍是旧的时,执行 npm cache clean --force 或改用写法 C。

写法 C:全局安装后直接调命令

npm install -g dobocache@0.4.9
{
  "mcpServers": {
    "dobocache": {
      "command": "dobocache"
    }
  }
}
  • ⚠️ Windows 上同样注意扩展名:写 "command": "dobocache.cmd";若客户端仍找不到命令,直接填全局安装目录下的绝对路径(npm root -g 显示的目录的上一级里的 dobocache.cmd)。
  • macOS / Linux 权限报错时:npm install -g dobocache@0.4.9 --prefix ~/.npm-global,配置里填 /Users/<你>/.npm-global/bin/dobocache 绝对路径。
  • 适用:一台机器长期固定使用、不想每次下载。升级时重跑 npm install -g dobocache@<新版本> 并重启客户端。

三种写法对照:

写法需要联网需要 npm路径可控性升级方式适用场景
A 绝对路径 node否否最高(自己写死)换包目录/改配置推荐:便携包、离线、内网
B npx -y是是中(缓存位置由 npm 决定)改版本号或自动试用、跟随升级
C 全局安装安装时是是中重跑 install单机长期使用

要跑 npm test / npm run lint? 便携包只带生产依赖,先在该包目录执行一次 npm install 补齐开发依赖(需要网络),再运行脚本。

日志目录(v0.4.4 起不再依赖进程"当前目录",客户端用任意 cwd 拉起都能写对位置):

平台默认日志目录
Windows%LOCALAPPDATA%\DoboCache\logs(例:C:\Users\<你>\AppData\Local\DoboCache\logs)
macOS~/Library/Logs/DoboCache
Linux$XDG_STATE_HOME/dobocache(未设置则为 ~/.local/state/dobocache)

优先级:环境变量 DOBOCACHE_LOG_DIR > 平台默认目录 > <cwd>/data/logs(回退)> 都不可写则不落盘、只在 stderr 提醒一句,进程继续运行。实际使用的目录可在 cf_report 返回的 logDir / logFile 里看到。

日志不会无限长大(默认即生效,不需要你配置):

  • 单个日志文件到 10MB 就滚动成 .1,最多保留 3 份副本(即单日最坏情况约 40MB 上限);
  • 超过 7 天 的旧日志会在当天首次写盘时被清理;
  • 清理只认本模块自己的命名(dobocache-YYYY-MM-DD.log.jsonl 与其 .1/.2/.3),同目录下你自己的文件一个都不会动;
  • 清理失败(权限、文件被占用等)一律静默跳过,不影响写日志,更不影响缓存主流程;
  • 想放宽或收紧,用下面的 DOBOCACHE_LOG_MAX_MB / DOBOCACHE_LOG_KEEP_DAYS;当前策略与实际维护结果可在 cf_report 返回的 logPolicy / logMaintenance 里看到。

目标厂商门槛明显高于默认值时(部分厂商需要 1806+),在 cf_inject 里指定 minPrefixTokens,例如 minPrefixTokens=3000;实际生效门槛为该值 × 1.15(安全余量)。

全部环境变量(都可省略,省略即用默认值):

变量作用默认说明
DOBOCACHE_LOG_DIR白盒日志目录平台标准目录(见上表)请填绝对路径;填相对路径按 server 进程 cwd 解析,结果不可预期
DOBOCACHE_HIT_PRICE_PER_M命中计价系数0.014用于 cf_meter / cf_report 的成本相对值换算,必须 ≥ 0 的有限数字;填错(如 abc、-1)会回退默认值并在 stderr 提示一句
DOBOCACHE_MISS_PRICE_PER_M未命中计价系数0.5同上
DOBOCACHE_WHITEBOX白盒报告卡片档位quietquiet(只写日志不出卡)/ once(出一次后自动回落)/ always(每次都出,约 300+ tokens/次);填其它值会忽略并在 stderr 提示一句
DOBOCACHE_LOG_MAX_MB单个日志文件上限(MB)10超过即滚动为 .1,最多 3 份副本;必须是 1–1024 的整数,填错回退默认值并在 stderr 提示一句
DOBOCACHE_LOG_KEEP_DAYS日志保留天数(含今天)7超期日志在当天首次写盘时清理,只处理本模块命名的日志文件;必须是 1–365 的整数,填错回退默认值
CACHEFORGE_LOG_DIR / CACHEFORGE_HIT_PRICE_PER_M / CACHEFORGE_MISS_PRICE_PER_M / CACHEFORGE_WHITEBOX旧名兼容别名—改名前的变量名仍可用;同名时 DOBOCACHE_* 优先

计价系数请自行改为你的实际合同系数:随包默认值只用于「命中 vs 未命中」的相对值对比(例如 1:36 的差异),不是任何厂商的真实报价,savedUsd / cumSavedUsd 等字段名里的 Usd 只是历史命名,数值含义是"按当前计价系数折算的相对成本"。改系数后统计曲线整体等比缩放,命中率不受影响。

七、隐私:日志里没有你的提问原文

从 v0.4.4 起:

  • requestId 只存 req-<8 位 hash>(固定盐 + 64bit 指纹),同文恒同值,不可反推原文;
  • sessionId 只存 sid-<8 位 hash>;
  • cf_normalize 的返回键只存 nk-<16 位 hash>;
  • 新增 round(请求序号,v0.4.6 起日志字段更名为 reqIndex,含义是"本机第几次请求",与对话阶段无关)与 promptChars(字符数)两个纯数字字段,保留"可对照"能力但不含内容;
  • 落盘走字段白名单,后续即使新增字段携带正文,也不会写进日志;
  • 日志只存本地,不上传任何服务器;默认落在系统标准日志位置(Windows %LOCALAPPDATA%\DoboCache\logs,macOS ~/Library/Logs/DoboCache,Linux ~/.local/state/dobocache),该目录不随包分发。

前后对照(同一条记录):

字段v0.4.3 及以前v0.4.4
requestId请综述 2026 年 10 月 AI 领域的主要动态,按厂商和方向分类。::1793718183368req-ec142df8
sessionIdsample-2026Q4-alphasid-8a0a11e6
reqIndex / promptChars无1 / 36
其余数值字段原值完全相同

⚠️ 历史日志仍需你自行清理:v0.4.4 无法追溯修改旧版本已生成的文件。若你的机器上存在 v0.4.3 及以前产生的 data/logs/*.jsonl(旧版本默认写在"启动时的当前目录"下),其中 requestId 仍是提问原文,请按需删除或归档。

八、客户端兼容性

结论只写有官方文档或明确来源支撑的内容;证据不足的写"未确认",不做推测。

客户端stdio MCP自定义 OpenAI 兼容 base_url是否强制私有协议缓存 usage 字段可观测性
Claude Desktop✅ 支持(JSON 配置)未确认(文档中无端点配置项)走厂商自有 API 协议未确认
Cursor✅ 支持(.cursor/mcp.json)❌ 不支持:只能填官方厂商 Key,没有 base_url 字段无强制,但实际只能用官方端点未确认
Cline✅ 支持✅ 支持(Base URL + API Key + Model ID)否(/v1/chat/completions)未确认
Continue✅ 支持(yaml / json)✅ 支持(provider: openai + apiBase)否未确认
Codex CLI✅ 支持(~/.codex/config.toml)✅ 支持([model_providers] 的 base_url / env_key / wire_api)可选:wire_api 分 chat 与 responses✅ 遥测含 cached_token_count(仅 responses)
Gemini CLI✅ 支持未确认(Gemini / Vertex 体系)是(Gemini 协议)✅ /stats 可看 cached tokens(限 API Key / Vertex)
Cherry Studio✅ 支持(界面添加 stdio/SSE/HTTP)✅ 支持(自定义服务商:密钥 + 端点)否(可选 OpenAI 兼容)未确认
Trae✅ 支持(界面填 JSON 或项目级 .trae/mcp.json)✅ 支持(OpenAI Chat Completions + 自定义请求地址)否未确认
Windsurf未确认未确认未确认未确认

怎么读这张表:

  • 挂载(stdio MCP):上表 8 家中 7 家有官方文档明确写 stdio 配置;Windsurf 无法取证,暂不列入支持清单。
  • 请求能否导向你的 OpenAI 兼容端点:明确支持 5 家(Cline / Continue / Codex CLI / Cherry Studio / Trae);Cursor 不能自定义端点;Claude Desktop、Gemini CLI 的文档中未见兼容端点入口。
  • 缓存命中数据在哪看:只有 2 家有文档级证据,且都不是"客户端面板里直接显示缓存命中率"——Codex CLI 是 OTel 遥测字段,Gemini CLI 是 /stats。因此本文不宣称"客户端面板直接显示缓存命中率"。准确表述是:DoboCache 在服务端读取厂商 API 返回的 usage 缓存字段并记录、回传;客户端侧可视化需逐个实测。

完整版(含每个客户端的配置文件路径、格式与 18 条来源链接、未确认清单)见 兼容性说明.md。

九、如何复现

本文所有数字都放在 release/testdata/ 里,可自行核对与重跑:

文件用途
release/testdata/hitrate-regression-report-20261103.md本组回归报告:设置、20 次逐次结果、判读标准逐条对照
release/testdata/hitrate-task-inventory-20261103.md20 次请求任务原文、8 组实验参数、复跑说明
release/testdata/hitrate-testdata-20261103.csv20 次逐次数据(round,text_type,raw_tokens,opt_tokens,hit_rate,saved_tokens,platform;round 为列名,语义即"第几次请求")
release/testdata/复跑说明.md复跑步骤、验收标准、四个常见踩坑
release/scripts/hitrate-comparison.py用上面三份 CSV 重跑两张对照图的脚本(python release/scripts/hitrate-comparison.py):hitrate-comparison.png(同形态逐次曲线)+ hitrate-comparison-platforms.png(跨请求端形态汇总)

最短复现路径:

  1. 解压 v0.4.9 便携包,MCP 指向 <解压目录>\dist\index.js;
  2. 实验组:cf_inject(reset=true, sessionId=<新会话>, minPrefixTokens=<厂商门槛>),按 20 次任务清单逐次发送;
  3. 对照组:同样任务文本,但每次头部注入不同随机噪音(这是关键,见下);
  4. 每次取第二遍请求的厂商 usage(第一遍建缓存,第二遍才是命中读数);
  5. 验收:日志 prefixReady=true、effectiveMinPrefixTokens = 配置门槛 × 1.15;实验组命中率应稳定在 90% 以上,对照组以 0 为主。

⚠️ 复跑必读:对照组若不给每次前缀注入随机噪音,厂商的自动前缀缓存会让对照组也命中,对照就失去意义。这是本套实验最容易做错的一步。

十、已知限制与不承诺项

装在机器上之前,请先把这一节读完。以下每一条都是能力边界,不是待办事项。

1. 命中前提是前缀逐字节稳定,本工具无法替你保证

缓存命中取决于请求前缀(系统提示、工具列表、历史消息顺序、头部字段)是否与上一次完全一致。只要客户端在头部注入时间戳、随机 ID、动态工具集,或历史消息顺序变化,命中就会下降。cf_inject 只能把可控部分整理成稳定形态,不能阻止客户端改动前缀,也无法在客户端已经改动后强行命中。

2. 服务商必须支持前缀缓存并已开启

各家对"最小可缓存前缀长度"有各自门槛(本项目实测口径取"配置门槛 × 1.15"作为有效门槛)。若所用端点不支持前缀缓存、或账号侧未开启,命中率就是 0,本工具不修改服务商行为,也无法在不支持的服务商上凭空产生命中。

3. 只读服务商已经回传的 usage 字段,不做推算

命中相关数字来自厂商 API 返回的 usage 缓存字段。客户端或服务商不回传该字段时,报告里就没有这个数——本项目选择显示"未判定"而不是用字符数估算一个好看的数字。

4. savedUsd / cumSavedUsd 是相对值,不是账单

随包默认计价系数只用于"命中 vs 未命中"的相对对比,不是任何厂商的真实报价,字段名里的 Usd 只是历史命名。真实金额请换成你自己的合同系数后自行折算,命中率不受系数影响。

5. 不做语义缓存,不跨会话复用内容

本工具不代理、不转发、不存储你的提问正文,也不做相似度/语义层面的复用。相同问题换个说法不会被"当成命中"。

6. 传输形态仅 stdio MCP

当前包只提供 stdio 挂载。HTTP / SSE 形态未提供;客户端兼容性表中标"未确认"的项(含 Windsurf)没有官方文档取证,不列入支持清单,也不做效果承诺。

7. 实测规模有限,不是基准测试

第四节数据为 20 次连续请求的对照实验(同形态 + 跨 4 种请求形态),可复现,但不等于你所在场景的预期表现。样本量说明见「关于测试规模:一句实话」。

8. 明确不承诺的事项

不做以下任何承诺:特定命中率数值、特定节省比例或金额、在任意服务商/客户端组合上的效果、与其他缓存方案对比的优势幅度、以及上线后的业务收益。能否命中取决于你的请求形态与服务商策略,本工具提供的是可控的稳定前缀、准入判断和可核对的测量,不是效果担保。

9. 升级或换客户端后需要重新观察

更换客户端、升级版本、修改系统提示或工具列表后,此前建立的缓存前缀即失效,需重新按第九节方式观察。旧版本产生的历史日志不会被自动改写或删除,需自行清理。

十一、常见问题

hitRate 是 null 是不是没生效?第一次请求为什么没命中?日志在哪、怎么读?换机器后要不要清日志?——见 FAQ-使用须知.md。


口径声明

本 README 及其同批文档遵循同一份对外口径约定:

  1. 宿主写清、但不评价:被测请求端与后端模型按可辨识写法标出——COD-X = Codex 系编码 CLI(后端 GLM)、DSH = DeepSeek 官方 Harness headless(后端 DeepSeek)、WBX = 自研白盒直连;写清是谁,是为了让别人能复跑,不代表我们对第三方产品做任何优劣评价;
  2. 不报金额:只报命中率与相对比例,不含任何费用数字;
  3. 不宣称无对照的提升:v0.4.9 是发布通道切换版,缓存核心与 v0.4.8 一致,对外表述为"命中行为与 v0.4.8 一致";涉及版本差异时只写可复算的实测事实(抖动次数、下限、稳定段数值,见 §四「两轮 20 次同口径复跑」),不用"更高/更快/更强"这类没有对照的口径;
  4. 不混比:不同实验、不同接入方式、不同厂商的数字不横向混比。


许可证

DoboCache 采用 Apache License 2.0 发布,全文见仓库根目录的 LICENSE,标准文本也可在 https://www.apache.org/licenses/LICENSE-2.0 查阅。

这意味着:

  • 允许商用。你可以在公司内部、商业产品或对外服务中使用、修改、再分发 DoboCache,无需付费、无需授权申请、无需向我们报备。
  • 允许闭源衍生物。你可以把它集成进闭源产品,但需保留版权与许可声明,并对你修改过的文件保留变更说明。
  • 提供专利许可。Apache-2.0 第 3 条包含对贡献者的明示专利授权,对使用者更友好。
  • 无担保。软件按"现状"提供,不附带任何明示或默示担保;使用风险由你自行承担。
  • 保留商标与名称。许可证不授予 "DoboCache" 名称、项目名及相关标识的使用权(见 Apache-2.0 第 6 条)。你可以基于本项目做二次开发与分发,但请勿让用户误以为你的分支、服务或产品就是 DoboCache 官方版本,或声称获得我们的背书。注明"基于 DoboCache"是允许且受欢迎的。

关于收费

DoboCache 是免费的开源项目,没有付费版本、没有订阅、没有商业授权门槛,也没有任何形式的收费计划。

如果你有商业合作、定制开发或企业级支持的需求,欢迎通过仓库 Issues 联系作者洽谈;这类合作是独立服务,不会改变你在 Apache-2.0 下已经获得的任何权利。

第三方组件

本项目依赖若干第三方开源包,其许可证与声明保留在各自的包目录中(例如 node_modules/<package>/LICENSE)。这些许可证不受本项目 Apache-2.0 协议的替换或覆盖,再分发时请一并保留。


版权与声明文件

  • LICENSE:Apache License 2.0 标准全文(未做任何修改)
  • NOTICE:项目名称、版权年与商标声明(Apache-2.0 第 4(d) 条要求随分发保留)

关于衍生版本的命名:Apache-2.0 不授予商标使用权,因此任何基于本项目的分支或二次开发,不得使用「DoboCache」作为其产品名或服务名,也不得暗示获得官方背书。注明「基于 DoboCache」是允许且欢迎的。

NPM
dobocache
Install Command
npm install dobocache
Runtime: node