billion-context官方版:上下文压缩插件,兼顾小窗口(100k上下文足矣)省token(省5倍token)和超长会话(数月级别几十亿token单会话)。
安装
# npm 包(预构建)
dsh plugin --profile web add billion-context
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:ranxianglei/billion-context
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
**缓存健康速览:**健康会话的前缀缓存命中率在 95–97% 左右——压缩本身代价 ≤2%。持续低于这个数,用
/acp或/acp-cache查归因(见常见问题);常见原因依次:上游缓存 TTL 到期 · 切换模型 · bili 的 bug(欢迎提报)· 其他/未知。
社区
QQ群: 1056132097(已满) 1108730198(已满) 1129868472(未满)
📄 论文 / 预印本
- 模型驱动的分层增量压缩:面向长寿命编码 Agent 的免训练多代上下文管理(中文版,v0.2)
📝 论文本身与代码一同以 MIT 许可开源(位于
paper/目录),是代码库的一部分 —— 这是一份活文档,任何人都可以编辑,欢迎提 PR 改进。
生产规模纵向研究:四个半月、三宿主、174,327 次模型调用、187.6 亿累计输入 token(三宿主合计约 247 亿),204,800-token 窗口零违规,马拉松会话 8,584–12,049 次调用。
📊 第三方独立评测基准
- 1,500 题三大基准横评报告(
LongMemEval-S·ContextBench·MemoryAgentBench)(English)—— 基于DeepSeek V4.1 Flash、Qwen3-Embedding-8B、Qwen3-Reranker-4B与Pi Agent,对billion-context(v0.1.202)、full全量上下文及 3 条 RAG 管线(bm25、embedding、embedding-rerank)进行全成本归因盲测:ContextBench 端到端有效 F1 夺得全场第一(0.3097,比full省钱58.3%)、LongMemEval-S 领先最强 RAG 达 +16.6%(79.20%vs62.60%,比独立会话full省钱71.1%)、MemoryAgentBench 1.48M 超长会话实现 100% 存活与 30× 稳态压缩(full199 题全部爆窗崩溃)。
billion-context 架在任意编程助手与其模型 API 之间,用 acp-kernel 压缩重写 Anthropic/OpenAI 流。何时压缩、压缩什么 —— 由模型决定,而非硬截断。
为什么
长编程会话会把上下文撑爆。各家 provider 按 token 计费,一旦超过上下文窗口,会话质量下降甚至崩掉。billion-context 把已消耗的对话压缩成分层摘要,让你一个会话连跑数天 —— 海量 token 穿过同一个上下文窗口。
与宿主自带的摘要器不同,这里的压缩增量、可逆、对前缀缓存友好:摘要在小范围内写入,可按需解压,缓存前缀保持完整。
工作原理
编程助手 (Claude Code / Codex / Cursor / Aider ...)
│ 你把助手的 base URL 指向 proxy
▼
┌─────────────────┐
│ billion-context│ 1. 解析请求(Anthropic 或 OpenAI 格式)
│ proxy │ 2. 对对话运行 acp-kernel 压缩
│ │ 3. 注入 `compress` 工具 + 压缩哲学
│ │ 4. 转发到真实模型 API
│ │ 5. 重写流式响应
└─────────────────┘
│
▼
真实模型 API (Anthropic / OpenAI / 兼容厂商)
上下文管理工具
代理向对话注入四个上下文管理工具;模型在上下文增长时自行调用,代理在服务端执行 compress,折叠后的范围在历史中保持摘要形态、直到被恢复:
compress—— 把一段消息范围折叠成详细摘要。decompress—— 需要精确细节时恢复某个已压缩范围。search_context—— 在压缩摘要与可见消息中做关键词检索。acp_status—— 上下文用量概览 + 哪些区间仍可压缩。
模型会自主使用以上工具自主管控上下文,无需人工干预。
该选哪个?
按客户端选:
| 客户端 | 用这个 |
|---|---|
| pi | billion-context —— bili pi(启动器)或 bili plugin install pi(原生);独立 billion-context-pi 仍可用 —— 细节见 CLIENTS.zh-CN.md |
| opencode(1.x / 2.x) | billion-context —— bili opencode(启动器)或 bili plugin install opencode(原生);独立 opencode-acp 在 1.x 上仍可用 —— 完整指南:OpenCode |
| omp | billion-context,bili omp(内置插件)或 bili plugin install omp(自拉起原生插件,免启动器) |
| dsh | billion-context —— bili dsh(启动器,经 --patch 注入完整原生插件)或 bili plugin install dsh ≡ dsh plugin --profile <name> add billion-context(统一泳道)—— 细节见 CLIENTS.zh-CN.md |
| kimi | bili plugin install kimi(自拉起原生,需 Kimi Code ≥ 2.0.0)或 bili kimi(证书 MITM)或 /bili/ 前缀 —— 细节见 CLIENTS.zh-CN.md |
| hermes | bili plugin install hermes(自拉起原生,Python 插件 #958)或 bili hermes(证书 MITM) |
| zcode(Z.ai / bigmodel coding plan) | bili plugin install zcode(自拉起原生,#1145)或 GUI「设置 → 网络」证书 MITM 或 /bili/ 前缀 —— 细节见 CLIENTS.zh-CN.md |
| claude | bili claude(启动器)或 bili plugin install claude(原生姿态,#964 —— 受管 settings 块 + 会话自管代理;见下方"注意") |
| codex | bili codex(启动器 —— 全功能零配置姿势)或 bili plugin install codex(MCP shell 工具面配套:先起 bili 再玩 —— shell 不拉代理,也路由不了 codex 本体流量)—— 细节见 CLIENTS.zh-CN.md |
| jcode | billion-context,bili jcode(cert-MITM)或 /bili/ 前缀 —— 无原生模式(编译型 Rust 二进制、无插件接缝,#962) |
| gemini(Gemini CLI) | bili gemini(启动器,GOOGLE_GEMINI_BASE_URL /bili/ 改写)或 /bili/ 前缀 —— 仅启动器(无环内工具注入接缝,#1043) |
| iflow(iFlow CLI) | bili iflow(启动器,IFLOW_BASE_URL /bili/ 改写)或 /bili/ 前缀 |
| qwen(Qwen Code) | bili qwen(启动器,cert-MITM)或 /bili/ 前缀 |
| antigravity(Antigravity CLI / agy,Google) | bili antigravity(启动器,CLOUD_CODE_URL 对 daily-cloudcode-pa.googleapis.com 的 /bili/ 改写 —— Antigravity 真实默认上游,#3129)或 /bili/ 前缀 —— 无插件接缝(闭源 Go language_server;其用户插件面仅可追加、不能拦截模型流,#2115)—— 细节见 CLIENTS.zh-CN.md |
| mcode(MiniMax Code) | billion-context,bili mcode(cert-MITM)或 /bili/ 前缀 —— 无原生模式(纯声明式事件钩子,无模型请求接缝,#1050) |
| aider | billion-context,bili aider(cert-MITM)或 /bili/ 前缀 —— 无原生模式(仅 shell 命令钩子,无工具注入接缝,#1048) |
| copilot(GitHub Copilot CLI) | bili copilot(启动器,cert-MITM)—— 闭源 Go 二进制、无插件接缝(#1049) |
| amp(Amp CLI) | bili amp(启动器,cert-MITM)—— 闭源 Go 二进制、无插件接缝(#1049) |
| crush(Charm Crush) | bili crush(启动器,cert-MITM)—— 开源 Go 二进制、无插件接缝;内置 provider 域加白,crush.json 自定义 base_url 自动发现(#2340) |
| zed(Zed 编辑器) | bili zed(启动器,cert-MITM)—— 开源 Rust 编辑器、无插件接缝;reqwest 吃 HTTPS_PROXY,CA 走 SSL_CERT_FILE(Linux TLS env 探测);内置 provider 域加白,settings.json 自定义 api_url 自动发现;环回 provider(ollama/lmstudio)经 NO_PROXY 保持直连(#2340) |
| goose(Goose CLI) | bili goose(启动器)—— rustls 不信任任何 CA 文件,无法 cert-MITM:openai/anthropic 腿经 OPENAI_HOST/ANTHROPIC_HOST,自定义 provider 经重新生成的 GOOSE_PATH_ROOT overlay(#1049) |
| 其余所有(没有上下文 hook) | billion-context —— bili <client>(启动器,优先)或 /bili/ 前缀 |
原生模式 vs 独立扩展。 宿主原生插件(bili plugin install …)与独立进程内扩展(billion-context-pi、opencode-acp)互斥 —— 两者同时生效意味着双重压缩。安装器负责切换:替换旧条目(裸名、npm: 别名、带版本号、路径形式都认,数组/对象两种形态都处理),原配置快照到 .bili-bak;项目级安装不会被碰 —— 需手动移除。作为手动安装的运行期安全网,原生入口在加载时同步设置 BILLION_CONTEXT_NATIVE=<host>,让独立扩展在动作时自动退出。pi 一侧该标记需要 billion-context-pi 0.1.72+。
安装
Linux / macOS —— 指定用户级 prefix 安装(全程不需要 sudo,也不改你的 npm 配置,bili 自更新不会再遇到权限问题):
npm install -g billion-context --prefix=~/.local
bili 命令装在 ~/.local/bin——多数发行版默认已在 PATH 中;没有的话把 export PATH="$HOME/.local/bin:$PATH" 写进 ~/.bashrc 或 ~/.zshrc。用 nvm 或 Homebrew Node 的,默认 prefix 本来就属于当前用户,直接 npm install -g billion-context 即可;Windows 的默认 prefix(%APPDATA%\npm)同样用户可写,直接 npm install -g billion-context。
这会安装 bili 命令(bili-proxy 保留为别名)。旧装的是 root 属主的 prefix、现在报 EACCES?用 --prefix=~/.local 重装即可根治(以后用 npm 重装 bili 时记得同样带上该参数)——不要用 sudo。
想用容器?仓库根目录自带 Dockerfile——见下文在 Docker 中运行。
快速上手
3种方式 —— 任选其一:
- 原生插件(最原生):
bili plugin install <client>—— bili 成为客户端内的插件,照常启动客户端即可. - 启动器(免安装):
bili <client>一条命令拉起代理 + 客户端,不碰任何真实配置文件. - 改url(最通用): 在客户端 baseURL 前面加上代理地址 +
/bili/。
三种方式背后的机制细节(插件生命周期、runtime-info 协议、注入优先级)见 TECHNICAL-NOTES.zh-CN.md。
端口,一句话(#1660):bili start(手工)拥有 8787;lane 替你拉起的一切(原生 hook、启动器 lane)住在独立的自管端口区,从 18787 起 —— 碰撞 +1 跳口、每个 lane 记住自己的漂移,零配置安装永不抢端口,刻意常驻的 bili start 守护进程则默认被附着。Attach 按泳道感知(#2905):hook 先骑自己 lane 的实例,绝不骑其他已声明 lane —— 除非在 native.attachLanePriority 里显式列出 —— 8787 用户区守护永远是最后兜底。升级重启时若旧版本还在该 lane 端口上排水,会最多等 5 秒让它释放并复用同一端口,而不是漂移(#1723);只有真正被占用的端口才 +1 跳口 —— 且这种跳口现在会大声打 warn。
方式 1 —— 原生插件(native,bili plugin install pi / omp / opencode / dsh / kimi / hermes / zcode)
代理住进客户端:装一次,之后照常启动客户端 —— 不用启动器命令、不用环境变量、不用固定端口、不用改 URL。目前支持 pi、omp、opencode(1.x 与 2.x)、dsh、kimi、hermes 与 zcode:
bili plugin install pi # 在 pi 的 settings 里注册 billion-context 条目(bili 自身为 npm 安装时写 npm 条目)
bili plugin install omp # 在 omp 的 config.yml(~/.omp/agent/config.yml)注册 extensions 条目
bili plugin install opencode # 在 opencode 真实配置里注册插件 + 关闭原生自动压缩
bili plugin install dsh # 对每个已存在的 profile 执行 'dsh plugin --profile <name> add billion-context'
bili plugin install kimi # 写 $KIMI_CODE_HOME/plugins/managed/billion-context/kimi.plugin.json(+ installed.json 记录);每会话路由块在首次启动时落到 config.toml(需 Kimi Code >= 2.0.0)
bili plugin install hermes # 把 Python 插件拷进 ~/.hermes/plugins/billion-context/(+ 机器自管的 bili.json sidecar),并经 `hermes plugins enable billion-context` 启用
bili plugin install zcode # 写 hooks.enabled + SessionStart hook + mcp.servers.bili 到 ~/.zcode/cli/config.json;每会话路由块在首次启动时落到 bigmodel provider store
bili plugin remove <client> # 卸载(dsh 经同一通道移除;配置快照存 .bili-bak)
客户端有自己的插件通道时,也可以原生安装、完全不用 bili 命令:
- dsh:
dsh plugin --profile <name> add billion-context正是bili plugin install dsh按 profile 驱动的那条命令(仅 npm 形态;git checkout 没有已发布入口 —— 直接填 GitHub 地址装到的是没有dist/的源码,bundle 永远加载不出来)—— 两种走法终态一致(pnpm 装进 profile、patch 层由 dsh 自己挂载);经同一通道卸载。见下文 dsh 段。 - opencode: 把裸 npm 包名直接写进你真实配置的插件列表 ——
"plugin": ["billion-context"](仅 npm 形态;git checkout 没有已发布入口)。包通过exports["./server"]→dist/agent/opencode-native.js暴露插件入口,opencode 用自己的 Npm.add 机制加载,插件自拉起的行为与 bili 安装的形态完全一致。另外要做两件 bili 安装器会替你做的事:在同一份配置里设"compaction": { "auto": false }(否则 OpenCode 的原生自动压缩会双重压缩),并先手工备份该配置文件。 - claude: 本仓库同时是一个 Claude Code 插件市场 ——
/plugin marketplace add ranxianglei/billion-context,再/plugin install billion-context@billion-context,然后运行/billion-context:bili-setup(它会替你驱动bili plugin install claude并提示重启)。终态与 bili 安装器一致;插件自身不携带 hooks 或 MCP 条目,不会双重注册。
pi / omp / kimi / claude 没有客户端侧通道 —— 它们的配置条目由 bili plugin install <client> 代写(kimi 的声明式 kimi.plugin.json + 注册记录、claude 的受管 settings 块等)。
注意:
- 原生模式与独立进程内扩展(
billion-context-pi、opencode-acp)互斥 —— 安装器负责换条目并把原配置快照(.bili-bak)。 - pi: 原生安装默认自带子代理功能(
acp_delegate/acp_delegate_wait/acp_delegate_cancel)—— 如何关闭它们并保留上下文压缩:Pi 内置子代理。 - OpenCode 旧会话、V1/V2 插件形态与全部注意事项:OpenCode。
kimi仅在自举时上报 runtime-info(静态头无法承载逐请求窗口/模型值);子代理工具调用由代理的出站 tool_use 见证环路由(#1685)——模型看不到任何会话 id。hermes的原生插件是 Python:健康检查通过后用环境变量把 hermes 的 httpx 栈指向代理,并经llm_request中间件打逐请求头。claude有原生姿态(#964):受管 settings 块 +SessionStarthook + MCP shell;hook 骑自管端口区(#1660),每会话把受管 URL 重钉到存活 origin,端口漂移自愈。#1821 起 MCP shell 还在会话内守护代理(30s × 3 次失败),代理死亡时自行重生,lane 内模型请求 ~90s 内恢复而无需新开会话(与 zcode 车道同语义)。BILI_NATIVE_CLAUDE=0退出(passthrough)。机制:TECHNICAL-NOTES.zh-CN.md。已知限制(#2290): Claude Desktop 应用的 Code 标签页(CLAUDE_CODE_ENTRYPOINT=claude-desktop)会为其内嵌的 Claude Code 设置自己的ANTHROPIC_BASE_URL,覆盖受管值——桌面会话完全绕过代理,而受管块的DISABLE_AUTO_COMPACT=1仍然生效,因此既没有 bili 压缩、也没有原生自动压缩。hook 会在会话开始时大声警告并记录下来供bili doctor展示(检测到本机装有 Claude Desktop 时,该 lane 也会显示 ⚠️ 提示);终端会话不受影响。真机验证(2026-10-06,#2290): 把HTTPS_PROXY写进 settings 的env块后,在 Claude Desktop 2.19675.1 / 内嵌 CC 2.1.288(Windows 11)上对一台开启 MITM 的存活代理零 CONNECT 流量——该变量没有到达应用内任何网络栈,与该时期的 CLI 行为一致——注意新版构建(CC 2.1.301 起)在 CLI 上会遵守HTTPS_PROXY,这正是bili claude走/bili/base-URL 改写的原因——launcher 不再为该 lane 设置代理、也不再设置 CA,而自带代理的子进程会把 loopback 主机合并进NO_PROXY/no_proxy,确保无论子进程的代理行为如何,这一腿都保持直连(#3446)。截至该版本,桌面 Code 标签页不存在可用的路由缝隙;该 lane 继续在 #2290 跟踪,若上游行为变化再议。仅用桌面的用户可用bili plugin remove claude恢复原生自动压缩。#5095 起受管块还会安装一个SubagentStarthook(node <root>/dist/claude-subagent-hook.js),给每次子代理派发铸一个随机 lane token 注入其上下文:骑着父会话 id 且无 agent-id 头的子代理(VS Code 扩展构建,#4352)按<id>|sub:…:t:<token>键控各自的压缩车道,并行同型派发不再合流(首条消息被折叠后 token 消失,后续请求回落到指纹车道)。卸载时随受管块一并移除。zcode有原生姿态(#1145):受管~/.zcode/cli/config.json块 + 每会话 providerbaseURL改写。完整机制:CLIENTS.zh-CN.md。omp是自拉起原生插件;codex性质不同 —— 它是 MCP shell 工具面配套:codex 的模型流量只能经 env 路由(默认 ChatGPT-登录 provider 没有可改写的配置缝 —— managedmodel_providers块会强制 API-key 认证、废掉订阅登录),而 MCP 子进程无法向父进程注入 env,所以插件安装既不拉代理、也永远路由不了 codex 本体流量。bili plugin install codex在~/.codex/config.toml写入[mcp_servers.bili](command = node,args = dist/mcp.js)注册四个 ACP 工具,会话启动时解析代理:envBILI_MCP_PROXY> 活实例登记(任一 lane 的代理或bili start守护)> 8787 用户区默认(#1660 去掉了安装时烘焙 origin,#403)—— 全不可达则tools/list报 -32003。结论:先起 bili(bili start或任一客户端的 lane 代理),想要压缩再自行导出 HTTPS_PROXY;零配置全功能用bili codex。机制:CLIENTS.zh-CN.md。jcode、aider无原生模式(无插件/MCP/工具注入接缝:#962、#1048)—— 用bili jcode/bili aider。copilot、amp、crush、zed、goose仅启动器模式(#1049/#2340);goose 无法 cert-MITM(rustls 不信任任何 CA 文件),改走纯 HTTP base-URL 重定向。
方式 2 —— 启动器(bili pi / bili codex / bili claude / bili omp / bili opencode / bili hermes / bili dsh / bili codebuddy / bili qoder / bili trae / bili jcode / bili kimi / bili gemini / bili iflow / bili qwen / bili antigravity / bili mcode / bili aider / bili copilot / bili amp / bili crush / bili zed / bili goose)
启动器把客户端包进一条命令:在独立端口拉起一个代理(总是全新实例,绝不复用端口),再按客户端支持的机制把它指向代理 —— 能吃代理/CA 环境变量的走证书 MITM,不吃的走隔离的**/bili/ 配置重写**。真实配置文件从不被修改;客户端自己的配置只被读取,用来发现它实际连接的 HTTPS 上游主机,把这些主机加入 MITM 白名单 —— 代理只 TLS 终结它们,其余流量盲透传。
bili pi # 拉起 pi,走代理 —— file-free(#535):环境变量 + 扩展 registerProvider,真实 ~/.pi 不动
bili codex # 拉起 codex
bili claude # 拉起 claude
bili omp # pi 同款,file-free(#535):环境变量 + 扩展 registerProvider + 压缩取消,真实 ~/.omp 不动
bili opencode # OpenCode(1.x 与 2.x):完整指南见下文 [OpenCode](CLIENTS.zh-CN.md#opencode) 一节
bili hermes # file-free(#535):hermes 代理环境变量(HTTPS_PROXY + SSL_CERT_FILE 组合 CA bundle)—— https 走 CONNECT MITM,http 走绝对形式转发;真实 ~/.hermes 不动
bili dsh # deepseek-harness:经 --patch 注入完整原生插件(#941) —— 真实 dsh 工具、会话绑定 /acp(plugin 模式);非回环上游走代理 env,回环保留 overlay DSH_HOME 改写(#535);dsh 自动压缩处处关闭(宿主平面经 bundle patch,web profile 的 preset 经 #3354 加载期 overlay,#1772/#2474/#3354)
bili codebuddy # Tencent CodeBuddy Code CLI:CODEBUDDY_BASE_URL /bili/ 重写(OpenAI chat completions wire),预算对齐走 CODEBUDDY_AUTO_COMPACT_WINDOW;真实 ~/.codebuddy 不动
bili qoder # qoder:模型端点硬编码 https(无法 /bili/ 改写)—— 证书 MITM(HTTPS_PROXY + NODE_EXTRA_CA_CERTS),默认模型主机已加白名单(#653)
bili trae # Trae CLI(字节跳动,闭源 Go 二进制,无 base-URL 覆盖)—— 证书 MITM(HTTPS_PROXY + SSL_CERT_FILE),模型主机取 TRAE_CLI_API_HOST 或默认企业网关(#655)
bili jcode # jcode(Rust 终端编码 agent)—— 环境变量式证书 MITM 启动:HTTPS_PROXY + SSL_CERT_FILE,模型主机 api.z.ai 默认加白,本地回环 provider 走 NO_PROXY 直连
bili kimi # Kimi Code CLI(Moonshot):除无条件回环绕过外遵循标准代理环境变量 —— https 证书 MITM、http 绝对形式转发;回环端点编目并附手动 /bili/ 提示(#757)
bili gemini # Gemini CLI(Google):GOOGLE_GEMINI_BASE_URL /bili/ 改写到 generativelanguage.googleapis.com(Google 原生 wire),真实 ~/.gemini 零改动
bili iflow # iFlow CLI:IFLOW_BASE_URL /bili/ 改写到 apis.iflow.cn/v1(OpenAI chat-completions wire),真实 ~/.iflow 零改动
bili qwen # Qwen Code(多协议 gemini-cli fork,无 base-URL 钩子):HTTPS_PROXY + NODE_EXTRA_CA_CERTS 证书 MITM,默认 DashScope/Qwen 模型主机加白,自建中转用 --mitm-domain 追加
bili antigravity # Google Antigravity CLI(agy,Gemini CLI 继任者):CLOUD_CODE_URL 对 daily-cloudcode-pa.googleapis.com 的 /bili/ 改写 —— 真实默认上游(裸 cloudcode-pa 在 /v1internal:* 上 400,#3129),无需证书 MITM(#2115)
bili mcode # MiniMax Code CLI:与 kimi 同构(代理环境变量、无条件回环绕过、证书 MITM/绝对形式);会话经 X-Mavis-Session-Id 绑定(#1050)
bili aider # Aider(Python pair programmer):HTTPS_PROXY + SSL_CERT_FILE/REQUESTS_CA_BUNDLE 证书 MITM;端点取自 OPENAI_API_BASE / ANTHROPIC_BASE_URL / --openai-api-base / .aider.conf.yml(#1048)
bili copilot # Copilot CLI(GitHub,闭源 Go 二进制)—— 证书 MITM(HTTPS_PROXY + SSL_CERT_FILE),api.githubcopilot.com + 各套餐子域加白(#1049)
bili amp # Amp CLI(Sourcegraph,闭源 Go 二进制)—— 证书 MITM(HTTPS_PROXY + SSL_CERT_FILE),ampcode.com 加白(#1049)
bili crush # Crush(Charm,开源 Go 二进制)—— 证书 MITM(HTTPS_PROXY + SSL_CERT_FILE),api.anthropic.com/api.openai.com/openrouter.ai + crush.json 自定义 base_url 加白(#2340)
bili zed # Zed 编辑器(开源 Rust)—— 证书 MITM(HTTPS_PROXY + SSL_CERT_FILE,Linux TLS env 探测),内置 provider 域 + settings.json 自定义 api_url 加白,环回 provider 保持直连(#2340)
bili goose # Goose(Block,Rust/reqwest):rustls 发布构建不信任任何 CA 文件 —— openai/anthropic 腿经 OPENAI_HOST/ANTHROPIC_HOST,自定义 provider 经重新生成的 GOOSE_PATH_ROOT overlay(/bili/ 改写,真实配置不动)(#1049)
bili pi --mitm-domain api.foo.com # 向 MITM 白名单追加域名
方式 3 —— 改url(/bili/ 前缀)
启动代理:
bili
然后把客户端现有的 baseURL 前面加上 http://localhost:8787/bili/ 就行。完整上游 URL 嵌在路径里,proxy 无需任何配置就知道转发到哪:
客户端 baseURL 之前: https://api.openai.com/v1
客户端 baseURL 之后: http://localhost:8787/bili/https://api.openai.com/v1
更多客户端配置参考网页引导: http://localhost:8787 .
验证。 代理跑着、配置保存了之后,确认它能应答,并且第一个真实请求在日志里显示压缩活动:
# 健康检查(代理是否在跑 + 转发到哪)
curl -s http://localhost:8787/__bili/health
# → {"ok":true,"upstream":"https://api.anthropic.com"}
# 实时会话统计(发过真实请求后)
curl -s http://localhost:8787/__bili/stats
然后从助手发一条消息,观察日志(~/.local/state/billion-context/bili.log,同时也打到 stderr)。每个请求应该看到一行 processTurn,等对话变长后会出现 [acp-usage] round N input=X cached=Y (cache hit Z%) + compress 事件。
客户端深入
一行带不过来的细节 —— 各模式(启动器 / /bili/ URL 前缀 / 原生插件)如何把流量接进代理、往哪儿写了什么、已知局限有哪些 —— 都在 CLIENTS.zh-CN.md:dsh · Kimi Code · Hermes · ZCode · Gemini 系(Gemini CLI / iFlow CLI / Qwen Code / Antigravity)· CONNECT 盲隧道接入但从不压缩的客户端(#897)· 未识别端点直连(#1290)· OpenCode(启动器 / 原生 / 纯代理、/acp 状态与规则、旧 opencode-acp 会话 #920)。
从源码安装(开发)
风险:
master是开发分支,随时可能处于不可用状态——未发布的改动、跑不过的构建、未验证的修复都可能出现。除非你要改代码、或验证一个还没发布的修复,否则请用上面的 npm 方式装发布版。
git clone https://github.com/ranxianglei/billion-context.git
cd billion-context
npm ci
npm run build
npm link
bili --version
npm link 之后,在任何目录都能直接用 bili。
常见问题
怎么查缓存命中率? 不用翻日志——/acp-cache 直接在客户端里打一份文字总结报告,顶部带一个可点击的 Web UI 链接,点进去是网页版会话页(折线图 + 逐断点归因):
报告四块,一眼定位:GRAND LEDGER(总账:总输入/总命中/hit%,直接给出 HEALTHY 或异常判定;miss 拆解为 new content 新增内容 / compress re-pay 压缩重付 / upstream-ttl-or-client-rewrite 上游 TTL 或客户端重写)· FOLD ECONOMICS(每次折叠的经济账:净省多少、是否回本)· LINE ITEMS(只列异常行:hit<85% 或 miss≥5000)。经验值:压缩本身只吃掉 ≤2%,健康会话稳在 95–97%;低于这个值时,归因按概率排序:①上游缓存 TTL 到期(报告里表现为 stable-prefix miss,top spikes 会点出闲置时长)②切换了模型 ③bili 的 bug(带报告页提 issue)④其他/未知。/acp-cache [full] 列每一折每一行;HTTP 同款:GET /__bili/cache-report;每个请求的 [acp-usage] 行仍会落日志,供深挖。
/acp 显示什么? 带原生插件的客户端(opencode、dsh)里,/acp 直接从代理取当前会话的 ACP 状态面板(会话、块、可压缩区间、用量);首个模型请求到来前显示空闲提示。/acp-cache [full] 打印上面的缓存报告。
能用网页查会话和配置吗? 能 —— 打开 http://localhost:8787:总览仪表盘、会话列表(含逐会话详情)、实时日志、配置编辑器、上游连通性测试。「博客」页还在面板内直接渲染发布笔记与长文——随装内置,在线时后台自动从 GitHub master 拉取新文章(约 1 小时节流,离线时回退到内置旧内容),完整文库也在 GitHub Pages。其余功能同样以纯 JSON 提供(/__bili/stats、/__bili/sessions、/__bili/config、…),方便脚本化。
压缩什么时候发生? 由模型驱动:注入的上下文工具由模型在上下文增长时自行调用,温和的增长 nudge(按设计固定约 50K token 步长,可用 compress.nudgeGrowthTokens 调整)沿途提醒它,仅输入就超窗时预检作为硬兜底触发(#470)。用 /acp 或网页界面实时观察。
为什么第一次压缩要到 ~200k 才触发? 压缩触发不是按绝对窗口位置、而是按增长区间:默认在开机内容之上增长 50k token 才触发第一次软压缩(compress.nudgeGrowthTokens 恒定步长、与窗口无关)。开机 100k 左右、或把 compress.nudgeGrowthTokens 设到 100k 左右时,可能都要到 ~200k 才发生第一次压缩。想更早压缩省 token:1.删减系统提示词、关闭不需要的工具、精简 skill;2.把 nudge 调小到 50k 左右;3.开启 lean 功能。完整算例见 CONFIGURATION.zh-CN.md。
bili 是透明的吗?怎么关掉? 未识别端点原样转发(CLIENTS.zh-CN.md),且每种模式都能干净退出:原生安装用 bili plugin remove <client>,另两种模式停掉启动器命令 / 环境变量 / /bili/ 前缀即可 —— 流量立刻恢复直连。
能配合模型路由网关(如 magpie)用吗? 能 —— 客户端指向 bili、bili 经 /bili/ 前缀指向网关(前缀内嵌网关的绝对 URL):http://localhost:8787/bili/http://127.0.0.1:3425…。例:Claude Code → ANTHROPIC_BASE_URL=http://localhost:8787/bili/http://127.0.0.1:3425 + ANTHROPIC_API_KEY=magpie;OpenAI 系客户端 → OPENAI_BASE_URL=http://localhost:8787/bili/http://127.0.0.1:3425/v1(+ OPENAI_API_KEY=magpie)。压缩发生在路由之前——到达网关节点里任何账号的请求都已是压缩后的。凭据留在网关内:客户端的假 key 原样穿过,真实 key 不接触 bili。注意:① 会话中途切换账号会使 provider 前缀缓存失效——多账号路由的固有代价,与 bili 无关(见 /acp-cache 的 KEY SWITCHES 段);② 路由后的模型名对 bili 的窗口查询不透明——需在 providers 键 http://127.0.0.1:3425 下用 models.<name>.context 声明其上下文窗口,否则按兜底窗口运行(route-miss 警告,#2317);③ 中继若拒绝 bili Anthropic 车道的 cache_control 标记,设 compat.noCacheControl;④ 回环网关开箱即用;网关在非回环私网地址时可能还需 network.allowPrivateHttpProviders(#2984)。三条线(OpenAI Chat / Responses / Anthropic Messages,含跨协议转换)已端到端实测,#4433。
日志和会话数据存在哪? 日志:~/.local/state/billion-context/bili.log(同时镜像到 stderr);会话状态:~/.local/share/billion-context/(XDG 可覆盖;Windows 杀软排除 #362、可选清理 #1082)—— 完整路径见 CONFIGURATION.zh-CN.md。
运行代理
在 Docker 中运行
仓库根目录自带 Dockerfile——构建期从 npm 装已发布的包(被测试过的产物;镜像里不编译任何东西),把代理作为服务跑起来:
docker build -t billion-context .
docker run -d --name bili -p 8787:8787 \
-v bili-config:/root/.config/billion-context \
-v bili-data:/root/.local/share/billion-context \
-v bili-cache:/root/.cache/billion-context \
-v bili-state:/root/.local/state/billion-context \
billion-context
然后把客户端 baseURL 指到 http://<host>:8787/bili/…,和上面方式 3 完全一样。
- 基础镜像:
node:24-slim—— 直接用内置node:sqlite存储引擎(不发生 native addon 下载)。不要换成 Node 20 基础镜像:自举下载的 SQLite 引擎要求 Node ≥ 22,在 20 上会崩(#3341)。 - 更新: 容器内自更新默认关闭(
ACP_AUTO_UPDATE=0)——容器化副本的合法升级通道是重建/pull 新镜像;原地自更新会在下次重建时被静默回退到镜像版本。想开回来用-e ACP_AUTO_UPDATE=1;构建期钉版本用--build-arg BILI_VERSION=0.1.197(默认latest)。 - 数据: 四个挂载目录分别存放配置、会话状态、更新节流/锁 + 缓存的 SQLite 引擎、日志。挂 volume 或 bind mount 让它们跨容器替换存活;镜像也把这四个目录声明为
VOLUME,裸docker run也不会把它们落进容器层。 - 安全: 容器监听
0.0.0.0:8787以便外部客户端接入——没有认证,端口只应暴露给可信网络(与下面--host 0.0.0.0的注意事项相同)。Web UI 和/__bili/*JSON 端点经映射端口照常可用。 - 健康检查: 镜像自带
HEALTHCHECK,用 node 内置 fetch 探 8787 上的/__bili/health(slim 基础无需 curl);若覆盖监听端口,注意探针仍钉在 8787。
命令行参数
bili --port 9000 # 改监听端口
bili --host 0.0.0.0 # 监听所有网卡(见下面的 host 说明)
bili --debug # 详细日志(也可在配置里设 "debug": true)
bili --passthrough # 不压缩直接转发(冒烟测试模式)
bili --config ~/my-bili.json # 用别的配置文件
bili update # 立即检查并安装新版本(跳过节流)
bili doctor --fix # 把漂移的 dsh profile 三本账(manifest 声明 / lockfile 记录 / 盘上副本)收敛到盘上版本(#3496)
bili --no-auto-update # 本次启动禁用自动更新
参数优先级高于环境变量和配置文件。bili --help 列出全部。
远程 agent(--host)
默认绑定 127.0.0.1,只接受本机连接。要给其他机器上的 agent 用:bili --host 0.0.0.0(或局域网 IP);远程 agent 把模型 baseURL 指向 http://<本机>:<端口>/bili/…。
- MITM 模式的
CONNECT也会接受远程客户端 —— 但仅限白名单内的模型域名;到任意主机的盲隧道仍仅限本机,代理不会沦为开放中继。 /bili/<绝对URL>目的地准入(#409):代理自身与 link-local/metadata 地址一律拒绝;loopback/私网目的地对本地客户端放行(自托管上游)、对远程客户端拒绝,除非列入BILI_TUNNEL_ALLOWED_HOSTS(host或host:port,逗号分隔)。一个例外(#1073):本地客户端经loopback IP 字面量目的地转发管理路径(/__bili/*、/__acp/*)时不带标记放行;远程 peer 与主机名目的地无条件保留内部隧道标记,管理路径即使经 NAT hairpin 也无法穿过隧道。指向本实例自身管理端点的绝对形式请求会在本地直接应答、而不是经隧道转发(正向代理式健康探测能拿到真实响应)。- 没有任何鉴权:只应在可信局域网或防火墙内使用。
/__bili/管理端点仍仅限本机访问。启动时的[security]警告会提醒上述事项。
调试
bili --debug(或环境变量 ACP_DEBUG=1,或配置里 "debug": true —— 优先级:参数 > 环境变量 > 配置)会打印每次 processTurn(标签计数、token 用量)、nudge 决策(growth/usage/pendingT1/shouldInject)、客户端 headers 和 SSE 重写。
日志文件
所有日志默认同时写入文件:~/.local/state/billion-context/bili.log(XDG state 目录),同时仍打印到 stderr。覆盖用配置的 "logFile" 或 ACP_LOG_FILE(off 关闭文件)。超过 10 MB 自动轮转(bili.log.old)。每个请求的缓存命中统计以 [acp-usage] round N input=X cached=Y (cache hit Z%) 打印,可直接从日志衡量前缀缓存健康度。
连接生命周期调优(#1982)
客户端侧连接在最终响应结束后优雅关闭:代理主动发起关闭(Connection: close)时,最多等待 BILI_POST_RESPONSE_LINGER_MS(默认 5000)毫秒的对端关闭信号才释放套接字,池化客户端因此看到的是干净的 EOF,而非字节竞态可能产生的 RST。相关旋钮:BILI_KEEP_ALIVE_TIMEOUT_MS(空闲回收预算,默认 5000)与 BILI_CLIENT_ERROR_BACKSTOP_MS(错误排空路径终局兜底,默认 30000)——完整语义见 CONFIGURATION.zh-CN.md。
自动更新
代理启动时和每 3 分钟检查 npm 是否有新版本。发现新版本就原位安装并打印通知 —— 重启 bili 才能生效,除非启用可选自重启(--auto-restart-on-update 参数 / ACP_AUTO_RESTART_ON_UPDATE=1 环境变量 / 配置 "autoRestartOnUpdate": true,默认关闭):零在途请求时校验新安装、停止接收连接、排空、在同一端口拉起替代进程并在其开始接受连接后退出(客户端自动重连;会话状态在磁盘上保留)。安全门:排空窗口全程零在途、re-exec 前安装完整性检查、10 分钟冷却标记防止版本抖动循环重启;任何失败恢复原监听器并回落到普通提醒。运行进程落后于磁盘安装("stale")时,Web UI 显示横幅,GET /__bili/status 返回 {version, diskVersion, stale, autoRestartOnUpdate, advisory, updatePolicy, inFlight} 供脚本使用(advisory 为生效中的严重缺陷公告或 null,见下节;updatePolicy 上报 #3619 撒点状态——策略来源、hold/pinned/blocked、以及待执行的撒点升级及其到点时刻)。永久禁用:配置("autoUpdate": false)或环境变量(ACP_AUTO_UPDATE=0)。
升级撒点(#3619): 发现新版本后,自动更新不再立即应用。每台实例在延迟窗口内随机抽取一个时刻(内置默认 15 分钟 – 48 小时),到点再升;抽中的时刻落盘持久化,重启不重摇。全量升级因此摊开在整个窗口内,而不是发版后十几分钟内全体升完,给坏发版留出中途拦截的响应窗(#3401/#3600/#3394)。窗口与紧急控制放在一个公开的策略文件里(本仓库的 auto-update-policy.json,匿名 GET + ETag 缓存):hold 全局冻结自动升级、blocked 跳过指定版本、pinned 设置升级天花板。按设计 fail-open——文件不可达或格式非法时直接回退本地默认;而且它只能调节奏/跳过/钉住,永远控制不了装什么。本机退出方式:手动 bili update 绕过 hold/撒点(但仍遵守 blocked/pinned)、"staggerMinDelayMs": 0 + "staggerMaxDelayMs": 0(或 BILI_UPDATE_STAGGER_MIN_MS/BILI_UPDATE_STAGGER_MAX_MS)恢复旧版立即升级、ACP_AUTO_UPDATE=0 完全停用自动更新。完整格式与语义见 CONFIGURATION.zh-CN.md → update。
插件模式(bili opencode / bili pi / bili dsh —— 代理内嵌在长驻宿主里运行时),"重启 bili"指的是重启宿主:内嵌进程无法自行退出,所以一直开着的宿主会持续运行它启动时的那份代码,默默地错过自动更新报告为"已安装"的每一处修复(#1603)。启用 --auto-restart-on-update 可让它在安全点自重启;或运行 /acp(当前仅 OpenCode 宿主,pi/dsh 覆盖见 #2084)—— 当磁盘安装领先于运行进程时,状态面板会追加一行过期警告(运行版本 vs 已安装版本)。若注入代码在运行期损坏(如 agent scope 被销毁),模型流量会静默直连(不压缩),直到宿主重启;自 #3581 起该状态可见:无会话运行时插件上报归属闸门降级,Web UI 显示「接管已失效」横幅,GET /__bili/status / /__bili/overview 暴露每代理的 attribution 状态。按设计无归属的后台车道(如 dsh 标题生成 sidecar)本身不携带 initiator,其小体量一次性请求按定义直连——按 #3651 契约这类正常拦截永不报告,因此永远不会触发横幅。横幅只在归属查询本身抛错(宿主内部错误,如 agent scope 被销毁)时出现,并给出可诊断信息:抛出的错误文本、脱敏后的端点、起始时间、已直连的请求数、解决方法(重启宿主进程),以及复制/提交诊断按钮(预填 GitHub issue)。
**自 v0.1.183 起,更新提示默认静默(#1977):**routine/recommended 版本不再在 /acp 面板脚注或 acp_status 中渲染更新行 —— 只有 critical 级别的版本会在那里显示(CRITICAL UPDATE READY/AVAILABLE)。检查"已安装未重启"版本的常设途径即上文所列的过期线索:Web UI 横幅、/acp 单行警告、以及 GET /__bili/status。刻意不设常驻提醒;严重缺陷公告通道(#1481)仍是唯一自动可见的严重路径。
当安装反复失败(目录不可写或受宿主托管、网络错误等)时,自动更新不再每个 3 分钟周期都重复下载并重试。连续失败三次后,它按指数退避(5 分钟 → 10 → 20 …,上限 6 小时),打印一次性的可操作提示(修复权限 / npm prefix、以用户级重装,或用 "autoUpdate": false / ACP_AUTO_UPDATE=0 禁用),并在冷却期间不再为这次失败输出日志(不下载、不打重试行);一旦故障消除或目标版本变化即恢复(#1603)。
同样的有界重试现在也覆盖全局自更新代为驱动的 owner 托管通道 —— dsh desktop 原位副本、dsh profile bundle 与 pi 的 npm 副本(#2192)。每条通道按「通道 + 目标版本」维护独立的失败计数,desktop 布局持续损坏时不再每周期重新下载整个 tarball(修复前每台受影响机器每天最多约 480 次下载);连续失败三次进入同样的指数冷却,一次性提示会指明出错的通道与手动修复方式(dsh plugin --profile <name> add …、pi update --extension …,或重建 desktop profile)。宿主托管实例另走更慢的独立检查节奏 —— 30 分钟加最多 15 分钟抖动,记在独立的节流标记里 —— 不再占用全局 3 分钟预算。失败计数通过缓存目录下的一个小状态文件(.install-backoff.json)在机器上所有 bili 进程间共享,多个运行中的实例不会各自烧掉独立的重试预算;bili plugin update 成功一次会立即解除 dsh profile 通道的冷却。该文件以原子方式写入(tmp+rename),且每次写入都与磁盘上已有内容合并,并发实例互相协作而不是覆盖彼此的计数;长驻进程会在文件变化时重新读取,任一副本执行的手动解除会在其它副本的下次检查时可见。它的一切失败模式都偏向重试 —— 损坏的文件或时钟跳跃会被丢弃,绝不允许长期沉默某条更新通道。bili plugin update 清除 dsh profile 通道的键;修复好的 desktop 通道则在下次成功的原位刷新时清除自己的键。
网络/VPN 切换后本地 DNS 陈旧(#5224)
长驻的独立代理在 WSL/VPN/TUN 拓扑变化后可能一直持有陈旧的 OS 解析器状态 —— 进程会缓存其系统解析器,而 libuv 的 getaddrinfo 不会自行重读 /etc/resolv.conf。症状:经 /bili/ 隧道发出的每个模型请求都返回 HTTP 502 tunnel_destination_denied(detail unresolvable),尽管同一时刻新起的 bili 能正常解析同一主机、新 shell 里的 curl 也正常。两种解决办法任选其一即可清除:
- 重启代理进程 —— 新进程会重读系统解析器。在 launcher 车道和 dsh web-profile 车道里,代理是一个独立登记的进程(instance registry),所以只重启客户端/宿主会从 registry 重新收养同一个楔死的代理,不起作用 —— 必须停掉并重新启动代理本身。(内嵌插件模式下代理跑在宿主内部,重启宿主能清除。)
- 让出口走上游代理 ——
-F http://<host:port>或BILI_UPSTREAM_PROXY=… BILI_UPSTREAM_PROXY_MODE=auto:目标改由那个上游代理远端解析,bili 准入时不再查询自己(已陈旧的)解析器。
严重缺陷公告(强制更新)
独立于自动更新(#1481):即使关闭了 autoUpdate,代理也会按同样的 3 分钟节奏轮询一个小的伴生 npm 包(billion-context-advisories,由 CI 从本仓库的 advisories/ 目录发布)。每条公告指明受缺陷影响的版本范围(affected,semver)、应安装的确切版本(target,可以比当前版本更旧,即回滚),以及面向用户的缺陷说明(reason)。当本地版本落入 affected 范围时,bili 会走自更新的全套安全链路强制安装 target(跨进程锁、备份+校验+回滚;源码检出和宿主托管的安装会被拒绝并给出手动升级指引),并以警告方式呈现:
- 日志中每个进程、每条公告一次性的
[advisory] ⚠️ …; - Web UI 概览页横幅,显示原因与手动升级命令;
GET /__bili/status在advisory字段返回生效中的公告。
该检查默认 fail-open:公告源不可达或格式错误只产生警告,绝不阻断模型流量。禁用方式:配置("advisoryCheck": false)或环境变量(BILI_ADVISORY_CHECK=0);可用 "advisoryUrl" / BILI_ADVISORY_URL 指向自定义文档。
配置
完整的配置参考 —— 配置文件位置、顶层键、providers、压缩调参、环境变量 —— 见 CONFIGURATION.zh-CN.md。
配置文件
一份 JSON 文档:~/.config/billion-context/billion-context.json
($XDG_CONFIG_HOME/billion-context/;用 BILI_CONFIG_FILE 可改路径)。
同一开关有多个来源时的优先级:CLI 参数(如有)> 环境变量 > 配置文件 > 内置默认值 —— 每个环境变量都继续作为覆盖层可用。
里面有什么(细节见 CONFIGURATION.zh-CN.md):
providers—— 按 provider 的路由表:上游覆盖、模型上下文窗口、按 provider/模型的压缩调参、wire 协议声明、compaction opt-in。compress—— 三级压缩调参(全局 → provider → 模型):阈值、nudge 节奏、保留规则、prompts、tiers。- 服务端级配置块 —— 进程级行为,含 #2030 新增:
network(超时 / 重试 / keep-alive / preflight 节奏)、persist(会话持久化格式 + tail)、sessions(上限 + GC 策略)、update(registry 镜像 + 检查间隔)、diagnostics(dump、render-tag 模式、注入开关)、fakeCompletion,以及标量codexCompact/ccrRetrievalTtlMs/decompressTmpCap和扩展项mitm.handshakeTimeoutMs、compat.noCacheControl、compat.keepResponseId。
最小示例:
{
"network": { "upstreamTimeoutMs": 900000 },
"persist": { "zstd": true },
"sessions": { "gc": { "enabled": true, "maxAgeDays": 14 } }
}
最常找的开关:
- 上游代理(防火墙/GFW)—— 让代理自身出站流量走 v2rayA/clash:完整解析顺序、空字符串 = 显式直连、SOCKS5 拒绝、两条出站路径都覆盖,以及
mitm://vshttps://键 scheme 区分,都在 CONFIGURATION.zh-CN.md(服务端设置 →proxy;Providers → key schemes)。 - 线上兼容角色改写(
compat.roles)—— 上游拒绝developer角色?CONFIGURATION.zh-CN.md(服务端设置 →compat)已覆盖 —— 包括零配置即用的失败自学习修复。 - 签名上游(body 级签名)—— 请求携带 body 级签名的网关(CodeArts APIG 的
SDK-HMAC-SHA256,或x-ofm-signature一类网关自造头):内置方案在 dsh 上透明重签;其他被形状检测识别出的方案一律本地拒收 —— 签名请求要么重签+压缩、要么拒绝,绝不无签名放行 —— bili 在补上对应重签器前每次启动与 web UI 持续提醒(#1884/#2090)。检测规则、按方案覆盖、BILI_RESIGN/BILI_RESIGN_PASSTHROUGH/BILI_CODEARTS_REF见 CONFIGURATION.zh-CN.md(服务端设置 →resign)。
Pi 内置子代理
使用 bili pi 或 pi 原生插件(bili plugin install pi)时,会自带默认启用的子代理功能:acp_delegate、acp_delegate_wait 和 acp_delegate_cancel。这组额外工具仅在 pi 上提供。
建议只启用一套子代理实现。 如果使用内置功能,建议在用户级和项目级配置中移除或禁用其他 pi 子代理插件(例如 pi-subagents 或单独安装的 billion-context-pi-subagents),避免工具、提示词或行为重叠。如果更喜欢其他子代理插件,可以关闭内置功能。项目级 pi-subagents 安装默认会让内置 delegate 自动让位,但仅有用户级安装时不会,因此不能把这项保护当作所有安装方式都适用的保障。
要关闭内置子代理并保留上下文压缩,请将以下配置合并到 ~/.config/billion-context/billion-context.json(或 BILI_CONFIG_FILE 指定的文件),保留已有的其他设置:
{
"pi": {
"subagents": false
}
}
重启 pi 并开启新会话后生效。该配置关闭三个 delegate 工具、配套的系统提示词和子代理管理界面的快捷键,上下文压缩仍然启用;单独安装的其他子代理插件不受此开关控制。更多选项见子代理配置。
会话机制
代理以**客户端自己提供的会话值(原样照搬)**为键隔离压缩状态(src/session-id.ts)—— 不哈希、不含协议/上游/API key 维度(它们会在会话中途变化,拿它们做 key 恰好在用户继续对话时把状态弄丢,#280/#286)。该 id 只在代理内部使用(状态存储、持久化、UI 标签),绝不上送。
取值来源(按顺序取第一个命中的):插件的 x-bili-plugin-conversation(仅当同时带 x-bili-plugin 标记 header)、客户端专属 header(x-claude-code-session-id、x-grok-session-id/x-grok-conv-id、x-mavis-session-id、x-opencode-session-id)、通用 header(x-session-affinity、x-acp-session、x-session-id、x-opencode-session、session-id/session_id)、或 body 字段:Responses wire 的 session_id/metadata.session_id,以及 Responses/OpenAI/Anthropic wire 上提升替代内容指纹回退的 prompt_cache_key。
| 客户端 | 发会话 id 吗? | 来源 |
|---|---|---|
| Codex | ✅ 发 | body.session_id / turn-metadata thread id |
| OpenCode | ✅ 发 | x-opencode-session-id header(ses_…,请求自身会话 id;2.x 同时在 x-session-affinity/X-Session-Id/x-opencode-session 里携带父级缓存路由亲和值,#2779 —— 1.x 在这些 header 里发送的是自身 id) |
| Claude Code | ✅ 发 | x-claude-code-session-id header |
| omp(经插件) | ✅ 发 | prompt_cache_key 提升为稳定身份(#268) |
| pi(裸跑) | ❌ 不发 | 无 → 见下方匿名前缀亲和 |
omp 注意(#2583/#3556): 较新的 OMP 构建中,默认 Anthropic(anthropic-messages)请求经 OMP 的 Cowork 传输以 node:https 直发 —— 到不了 bili 的 fetch 层,因此那条路径上 prompt_cache_key 打戳被主动放弃(打了戳反而会把字段泄漏进 Anthropic 严格 schema → HTTP 400)。自 #3556 起,bili omp launcher lane 默认不再留这个洞:除非你自己设置了 PI_PROXY / PI_PROXY_ANTHROPIC,launcher 会导出 PI_PROXY_ANTHROPIC=<proxy>,把 Cowork 推回 Bun 的 fetch、像其余 lane 一样经代理路由(可压缩、会话可见;打上的 key 由代理消费并剥离)。直连且匿名的行为只保留在 native omp 模式、以及你自己钉死代理姿态的 launcher lane;其余 omp 流量保持打戳身份。详见 TECHNICAL-NOTES.zh-CN.md。
无 header 客户端(pi 类):匿名前缀亲和。 当客户端完全不发任何会话信号时,代理从重放的历史本身解析会话(src/prefix-affinity.ts,#309):只有当请求历史从第 0 条开始逐字节复现某已存会话的消息链时,才重新挂回该会话;否则获得一个确定性的新 pfa-… 会话。后果(#1262):恢复(resume) 的对话重新挂回自己的会话(包括代理重启后,#499);开头相同的新任务不会继承另一个会话的 block —— 它拿到全新会话,历史一旦分叉就彻底独立;完全没有任何可用信号时,请求会被显式 400 拒绝,而不是静默与他人状态碰撞。
设计记录与威胁模型:SESSION-IDENTITY.md。消息粒度的对偶文档(为什么身份由内容派生、而非指派 id)是 MESSAGE-IDENTITY.zh-CN.md。
上游粘性路由方面,代理只转发客户端本来就提供的身份值(例如 body 里的 session_id 会以 x-session-id 上送),绝不自行合成一个。
建议: 发显式 id 的客户端可以安全并发。无 header 的多 agent 场景,优先装客户端插件(为每个会话盖稳定 id)或每会话传显式 x-acp-session header —— 两者都没有时,前缀亲和也能把不同任务分开(分叉的代价只是一次原始重发加压缩阶梯重启)。
派生(子)会话继承父会话的压缩上下文(#1333、#1362)
当 agent 派生子会话(subagent 或 fork,从空历史起步、不重发父会话内容)时,它会在出生时上报这条血缘:身份注册携带父会话 id(parentConversationId),代理在子会话上记录一条只读链接(derivedFrom)。此后 decompress / search_context 对子会话自己从未见过的内容沿父链回退(带环检测、深度上限 8);任何东西都不复制进子会话,父会话也绝不被修改;父会话未知时子会话就按全新起步。各 lane 的父信号(pi/omp parentSession header、OpenCode V1/V2 parentID):SESSION-IDENTITY.zh-CN.md。claude/codex/dsh 在这里不需要任何信号:它们的子 agent 共享同一个会话 id,或根本没有子会话概念。
Windows:把会话目录加入杀软排除项(#362)
代理把每个会话的压缩状态持久化到会话目录(默认 %USERPROFILE%\.local\share\billion-context\),长会话每一轮都会重写该文件。在 Windows 上,实时杀毒(Defender)、搜索索引器或同步工具(OneDrive)可能在写入中途锁住该目录,导致 rename 以 EPERM 失败。同一会话连续 N 次写失败(默认 5)时,代理打一条一次性可操作告警,指明要排除的目录。根上修复:把 %USERPROFILE%\.local\share\billion-context\ 加入杀软排除项,并确认没有同步工具在同步该路径 —— 完整步骤见 CONFIGURATION.zh-CN.md 的「Windows:把会话目录加入杀软排除项」章节。同一排除项也覆盖统一存储 index.db 打不开(unable to open database file,#3823)——存储降级告警会把它列为第一嫌疑。
单机多安装共存(#5046)
同一台机器上装了两份及以上 bili(例如两个 DSH profile——桌面端 + bot,或全局 npm 拷贝与宿主树拷贝并存)时,各自的代理默认都解析到同一个 XDG 会话目录(%USERPROFILE%\.local\share\billion-context\sessions\)和同一份配置文件。开了统一存储(storage.unified = shadow/full)后,两个进程会双写同一个 index.db:日志出现 [instances] another bili instance is running …,lane 重叠时还有 [storage] … two processes on one index.db corrupt it 级别的 error;SQLite 写锁争用(SQLITE_BUSY / database is locked)会让整轮模型请求直接失败,持续双写还有损坏风险。正确做法是**隔离**:给每份安装设独立的 BILI_SESSIONS_DIR(配置也要分开时再加 BILI_CONFIG_FILE),只加在该安装自己的启动器/profile 环境变量里,不动全局环境。隔离后两份可正常并存,[instances] 提示会自动降为 info 级(目录不同 ⇒ 无共享状态)。
会话文件清理(#1082)
短命会话会留下永远不会再被恢复的小状态文件。清理是可选开启(opt-in)的:设 BILI_SESSION_GC=1 才启用(默认关闭 —— 会话文件属于用户数据,不应有静默删除策略)。启用且持久化开启时,bili 在启动时和每小时扫描会话目录,只有两个条件同时满足才删除一个文件:年龄超过 BILI_SESSION_GC_MAX_AGE_DAYS(默认 7 天),并且该会话从未被压缩过(没有折叠块)、最近一次请求体 ≤ BILI_SESSION_GC_MAX_TOKENS token(默认 1M)—— 删除只丢字节不丢内容。CCR 内容存储遵循其会话文件的生命周期;被压缩过的会话永不删除;每次删除都写审计日志。详见 CONFIGURATION.zh-CN.md。
存储维护 CLI(#3928)
面板通过 HTTP(POST /__bili/storage/gc、POST /__bili/storage/restore)暴露的同一套存储维护操作,现在有一个薄的 CLI 层 —— 不需要代理进程,在持有会话目录的任何机器上都能直接跑:
bili sessions ls # id、label、解码后大小、最后更新时间、存储状态(active/archived)
bili sessions rm <id> # 完整删除(释放内容引用计数,含媒体);随后收缩 index.db(--no-vacuum 跳过)
bili sessions archive <id> # 导出到 archive/archive.jsonl + 清行;tombstone 保留 label 与身份
bili sessions restore <id> # 从日志行恢复已归档的会话
bili storage gc [--days N] [--vacuum full|incremental] [--dry-run]
# 先打印清扫计划(超期会话、零引用内容行、可回收页数估算),再执行与 HTTP 端点相同的 gc();--dry-run 只打印计划
archive/restore/gc 需要统一存储(BILI_STORAGE_UNIFIED=shadow|full 或配置文件里的 storage.unified)—— legacy-only 安装会拒绝并给出提示。--days 默认取 storage.archiveAfterDays(365)。没有调度器:全部按需运行。所有命令都支持 --json。
大库上 full vacuum 是离线操作(#4612)。 --vacuum full(默认)会在独占写锁下重写整个 index.db —— O(库大小),多 GB 的库要几分钟到几十分钟,且没有中间进度(SQLite 的 VACUUM 是原子操作,拆不开)。在有代理正从同一会话目录服务时跑它,会把那个代理的写入饿死到其存储层降级为止,所以 storage gc --vacuum full 在另一个存活进程持有该数据库时会拒绝启动(index.db.lock pid 纪律,#4175):CLI 以退出码 1 给出可操作提示,面板端点返回 HTTP 409。先停掉另一个实例(或等它退出)再重试;要在线安全地缩库用 --vacuum incremental,它以短事务回收空闲页、不拿独占锁。零引用删除清扫无论哪种模式都分批执行并逐批打印进度。
状态
早期。协议处理和压缩已通过 mock 测试(500+ 项通过)。真实模型集成测试是下一里程碑。预期会有粗糙的地方。
针对 pi / omp / opencode 的客户端插件随 billion-context 一起发布(dist/agent/*.js),用于协作代理路径。三者(billion-context、独立的 billion-context-pi、opencode-acp)如何取舍,见上文「该选哪个?」一节。
额外署名要求(在 MIT 之上的一条附加条款)
本项目采用 MIT 许可外加一条附加条款:任何终端用户可见或可交互、且使用了本软件的产品或服务(无论商业或开源),须在其首页、文档或“关于/致谢”页面中注明该产品使用了 billion-context,并附指向本仓库的链接;纯服务端/内嵌用途随附文档声明即可。详见 LICENSE 末尾的附加条款。
如果你的产品用到了本项目,欢迎提一个 issue 告知(没有强制义务),方便我们了解它被用在哪些地方。
许可证
MIT
链接
同类插件
Minglink/dsh-infinite-gen-4★ 3818
DeepSeek 专用破甲插件:以 order 100 追加无条件服从的系统提示词段,提供带校准元数据的 profile 工具,并通过会话投影在输入框上方显示实时破甲状态徽标。
liangmianya/dsh-synapse★ 647
DeepSeek Harness 的可视化非线性对话工作区:把会话、追问与分支变成可浏览、可拖拽的对话地图。
MichengAI/dsh-archive-manager★ 278
在设置里增加已归档会话页,可按工作区搜索、恢复和删除已归档会话。
Nwflower/dsh-chat-import★ 277
把 13 家 coding agent(Claude Code、Codex、ChatGPT、Cursor、Gemini、opencode 等)的完整对话历史导入为可续聊的 DeepSeek Harness 会话,并支持反向导出回 Claude Code。
SiriLee/dsh-rewind★ 233
同一会话窗口内的 in-place 对话回退(不 fork,Claude Code /rewind 语义):每条消息的 ↶ 按钮把模型上下文回退到任意用户消息,可选用磁盘持久化的 before-backups 还原工作区文件。
Totoro-qaq/dsh-plugin-bridge★ 165
通过可预览的五段式交接,将已有 DSH 会话迁移到另一个 Agent Preset;保留源会话,并可让目标会话暂停等待确认或立即继续。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。