Headroom 0.34 压缩与检索契约:字段、模式与真实端点验证
工程笔记
发布 / DavidHLPL
集成 Headroom 0.34.0 时,先把 API 当成版本化契约,而不是根据 dashboard、类型名或 mock 猜字段。/v1/compress 需要 model 和 messages,压缩统计位于响应顶层;/v1/retrieve 返回 original_content。这三个细节足以让“测试全绿”的适配器在真实代理上失败。
契约速查
POST /v1/compress
{
"model": "<MODEL_NAME>",
"messages": [{ "role": "user", "content": "..." }],
"config": {}
}
非空消息走正常压缩路径时,成功响应包含以下顶层字段:
messages
tokens_before
tokens_after
tokens_saved
compression_ratio
transforms_applied
transforms_summary
ccr_hashes
边界如下:
- 缺少
model或messages返回 HTTP 400。 - 端点接受
messages;Codex Responses 的input数组必须先转换,不能原样发送。 tokens_saved在顶层,不在stats下。- 空消息列表在 config 校验前快速返回,且响应不含
transforms_summary;调用方仍应决定空列表是否符合业务语义。
POST /v1/retrieve
{ "hash": "<CCR_HASH>" }
成功响应包含:
hash
original_content
original_tokens
original_item_count
compressed_item_count
tool_name
retrieval_count
缺少 hash 返回 HTTP 400;hash 不存在或已过期返回 HTTP 404。适配器应读取 original_content,不要探测并不存在的 content 或 found。
压缩模式不是同义开关
config.mode |
Marker | Store write | 适用条件 |
|---|---|---|---|
| 省略 | 无 | 无 | 默认路径;调用方不需要 CCR 检索闭环 |
ccr |
条件产生 | 条件写入 | 调用方能注入检索工具并访问 loopback /v1/retrieve |
lossy_inline |
无 | 无 | 先 lossless fold,再对剩余内容执行 Kompress |
lossless_then_lossy |
无 | 无 | lossy_inline 的兼容别名 |
ccr_hashes 只报告实际插入的 marker。即使启用 ccr,普通文本或一般 function 消息也不保证产生 marker;structured tool output 发生 SmartCrusher row-drop 时才是已验证的产生路径。因此,测试不能把“启用了 ccr”等同于“响应一定有非空 ccr_hashes”。
固定 provider cache 前缀
非空消息进入正常压缩路径时,config.frozen_message_count 必须是非负整数。它固定前 N 条已经进入 provider prompt cache 的消息:这些消息仍参与跨消息分析,但返回时保持字节不变,避免每轮压缩重写已付费的 cache prefix。空消息会在这项校验前快速返回。
它与“保护最近 N 条消息”方向相反:
frozen_message_count固定开头的 provider cache 前缀;protect_recent保护靠近尾部的最近消息。
把两者混用会造成 cache miss,或让本应压缩的历史消息被长期保留。
为什么 mock 会给出假阳性
曾出现过三种自洽但错误的 mock 假设:
- 从
stats.tokens_saved读取统计; - 从检索响应读取
content或found; - 允许省略
model。
如果实现与 mock 共享这些错误,单元测试仍会通过。最小修复不是增加更多 mock,而是从固定版本源码提取真实 schema,再让 mock 和 loopback contract test 共同遵守它。
最小 contract test
至少覆盖四类断言:
/v1/compress缺model返回 400;- 合法压缩请求的
tokens_saved位于顶层; /v1/retrieve的正文键为original_content;- 只有实际产生 marker 的 fixture 才断言
ccr_hashes非空。
测试真实 loopback 端点时还要隔离传输环境。Bun 的 fetch 在某些环境会使用 HTTP_PROXY,却不按预期绕过 loopback;此时应在测试进程中清除代理变量,或改用明确不代理 loopback 的客户端。否则连接错误会被误诊为 API 契约失败。
适用范围、风险与回滚
本页只适用于 headroom-ai==0.34.0。升级后应重新读取固定标签源码并执行同一组 contract tests,尤其关注请求必填字段、响应层级、mode 别名和 CCR store 行为。
集成回滚不需要删除数据:将新请求恢复为默认 marker-free 模式。已经含有 CCR marker 的活跃会话应继续保留检索工具直到越过会话边界,或直接新开会话;之后再停用依赖 /v1/retrieve 的工具注入。若已经写入 CCR store,应按 Headroom 自身生命周期清理,不要手工修改 store 内部文件。
相关页面
来源与关联文档
研究记录
- 原始文档: src/content/note/zh-cn/headroom-compress-retrieve-contract.md
- 来源版本: f49953fb0d4bd52a39bf81167b0c4b7dd7d78a64
- 证据状态: 有效