ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Caveman Gateway 深度解析:caveman 项目中字节安全的独立代理(caveman-proxy)设计

Caveman Gateway 深度解析:caveman 项目中字节安全的独立代理(caveman-proxy)设计 Caveman Gateway 深度解析caveman 项目中字节安全的独立代理caveman-proxy设计【免费下载链接】caveman why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman项目地址: https://gitcode.com/GitHub_Trending/caveman1/caveman本文围绕 caveman 仓库 proxy/README.md 中描述的 Caveman Gatewaystandalone 独立代理展开它是一个只换 base URL的本地反向代理把 Coding Agent 的 LLM 流量引到127.0.0.1:8787在不改一行 Agent 代码的前提下完成上下文压缩与本地花费记账。读完本文你可以掌握它的构建与启动方式、caveman.yaml配置项与全部环境变量、BYOK 凭据解析链、Bedrock 一等支持、字节安全byte-safe不变量的源码依据以及~/.caveman/caveman.db花费存储与stats等子命令的实操用法。一、定位base-URL-swap 式反向代理Caveman Gateway 的核心思路非常朴素把你的 AgentClaude Code、Codex、Gemini CLI 等的 provider base URL 指向http://127.0.0.1:8787其后的 LLM 流量就会流经 Caveman 的本地代理。它的设计约束在 proxy/doc.go 中写得明确单操作者single-operator代理只监听回环地址服务本机上的一个操作者不做多租户鉴权BYOKBring Your Own Key上游 provider 凭据来自你自己的环境变量代理不托管任何密钥零云依赖zero cloud dependencies全部状态落在本地~/.caveman/目录无外部控制面记账诚实性每次请求记录真实的 token 用量到本地 SQLite但任何节省数字只标记为inferred推断永不标记为verified已验证。请求生命周期可概括为一条流水线match → authenticate → inspect → byte-safe transform → upstream → meter路由匹配 → 认证 → 检视 → 字节安全变换 → 转发上游 → 计量该循环实现于 proxy/internal/gateway/server.go 所在的internal/gateway包通过三个注入接缝Authenticator、CredentialResolver、TelemetrySink与控制面解耦。需要注意授权边界按 proxy/README.md 与根目录 LICENSING.md该运行时以 BSL 1.1 发布属于 source-available 而非 OSI 开源在 Change Date 之前自托管生产使用允许第三方托管/嵌入式使用需要商业授权。二、构建与启动README 给出的最小可运行序列如下go build ./proxy/... # 构建 ANTHROPIC_API_KEY… caveman-proxy # 在 127.0.0.1:8787 提供服务 caveman-proxy stats # 以 JSON 打印本地花费摘要启动入口是 proxy/cmd/caveman-proxy/main.go。runServeL157 起的装配顺序值得细看mustHome解析并创建~/.caveman目录可被CAVEMAN_HOME覆盖并把 JSON 日志同时写到 stdout 与~/.caveman/proxy.log超过 16MB 轮转为proxy.log.1——因为caveman wrap以忽略 stdio 的方式后台拉起本进程不落盘的日志意味着现场排障时毫无证据对应代码注释中提到的 #897config.Load读取caveman.yaml路径可用CAVEMAN_CONFIG覆盖store.Open打开花费库~/.caveman/caveman.db可用CAVEMAN_DB覆盖initializeNativePersistence打开 CCR内容恢复存储ccr.db若恢复存储损坏会把cfg.Mode强制降级为record直通模式并禁用 native runtime而不是带病运行压缩——这是字节安全优先的直接体现仅当mode为compress或pixel且 CCR 可用时才通过standalone.NewEngineCompressor接入压缩引擎并把同一个花费库复用为持久化替换缓存opts.PrefixCache保证一条被压缩过的消息在后续每一轮对话里重新序列化出逐字节相同的内容从而不破坏 provider 的 KV 前缀缓存绑定监听器、写运行态文件runstate进入srv.Serve。HTTP 服务器参数固定为ReadHeaderTimeout 5s、ReadTimeout 30s、IdleTimeout 2min、MaxHeaderBytes 1MiB。除默认的serve外二进制还带有一组内容无关content-blind的运维子命令见 main.go L51-L82stats、agent-evidence --session --build --plan、trial、usage、learn、status、version、native-why、native-hook。其中agent-evidence只返回精确的 provider 用量、请求哈希、声明的 context/plan 标识与实际变换 IDbasis恒为inferredverified_usd恒为 0。三、配置caveman.yaml 与环境变量配置加载器在 proxy/internal/config/config.go。有几个设计要点必须理解1. 密钥永不写入 YAML。文件里只有模式、监听地址、优化器开关和每 provider 的 base URLAPI key 一律在请求时从环境变量解析providerEnvKey映射config.go L259-L265ProviderBYOK 环境变量anthropicANTHROPIC_API_KEYopenaiOPENAI_API_KEYgeminiGEMINI_API_KEYazure_openaiAZURE_OPENAI_API_KEYopenai_compatibleOPENAI_COMPAT_API_KEYbedrockAWS_BEARER_TOKEN_BEDROCK或 IAM 三元组见下节2. 运行模式 fail-closed。合法模式集合为{record, recommend, shadow, canary, active, compress, pixel}config.go L92 的knownModes任何未知值都回落到record直通模式未识别的配置永远不会悄悄启用变换。各模式行为在 docs/technical/proxy-and-providers.md 中给出对照record原样转发模型可见字节compress应用带恢复能力的 Engine 变换pixel允许配置的 text-to-image 上下文传输recommend/shadow/canary用于受控评估路径active应用已启用的优化器。标准本地 CLI 工作流只暴露 record / compress / pixel 三种。3. 监听地址强制回环。validateListenconfig.go L123-L136拒绝空值、通配符或任何非回环 host——因为 standalone 代理没有入站鉴权绑定非回环地址等于把每个已配置的 provider 凭据裸暴露给网络。默认监听为127.0.0.1:8787DefaultListen与 proxy/doc.go 的DefaultListenAddr一致。4. 关键配置项与环境变量覆盖。withDefaultsconfig.go L138-L192显示每个 YAML 字段都有对应的环境变量覆盖YAML 字段环境变量语义labelCAVEMAN_LABEL给本地遥测行打标签默认local试用运行会写入trial:trial_...以隔离单个会话modeCAVEMAN_MODE运行模式未知值回落recordlistenCAVEMAN_LISTEN监听地址默认127.0.0.1:8787必须回环subscription_compressCAVEMAN_SUBSCRIPTION_COMPRESS订阅制会话的 live-zone 压缩开关空/live_zone允许off关闭未知值 fail-closed 到offtoolschema_stripCAVEMAN_TOOLSCHEMA_STRIP工具 schema 注解剥离默认关仅显式annotations开启breakpoint_planCAVEMAN_BREAKPOINT_PLAN缓存断点规划器默认关仅显式frontier开启—CAVEMAN_OBSERVE_ESTIMATErecord 模式下的仅观察估算在副本上测量压缩本可省下的 token但绝不改动转发字节、不写 CCR 原文此外providers.name.base_url覆盖各 provider 上游地址Anthropic/OpenAI/Gemini 有公共默认值因此裸caveman start就能工作Azure、Vertex、OpenAI 兼容端点无通用端点属 opt-incompat.name声明命名 OpenAI 兼容上游挂载在/compat/name/下base_url必填、api_key_env指定凭据环境变量空值表示该上游无鉴权头。billing_tier仅接受paid/free两种可信值未知值直接省略而非猜测BillingTiersconfig.go L204-L213。四、BYOK 凭据解析与 Bedrock 一等支持入站凭据优先于本地 BYOK。Creds.Resolveproxy/internal/standalone/standalone.go L50-L77的解析顺序是请求头x-api-key→Authorization: Bearer→ 命名 compat 上游的专属 key → 该 provider 的 BYOK 环境变量。其中有一个易被忽略但关键的细节从入站Authorization: Bearer取出的 key 会在providers.Credential上保留Scheme: bearer。原因是 Claude/Gemini 的 OAuth token 只能以 bearer 形式转发若被重映射成x-api-key请求头订阅制会话就直接坏掉。Bedrock 是 standalone 模式的一等 provider不需要手贴 raw endpointBedrockBaseURLconfig.go L235-L240由解析出的区域推导标准 Runtime 端点https://bedrock-runtime.region.amazonaws.com。凭据支持两种形态README 原文示例AWS_REGIONus-east-1 AWS_BEARER_TOKEN_BEDROCK… caveman-proxy # 或 AWS_REGIONus-east-1 AWS_ACCESS_KEY_ID… AWS_SECRET_ACCESS_KEY… caveman-proxyAWS_SESSION_TOKEN受支持用于临时 IAM 凭据拼进AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY[:AWS_SESSION_TOKEN]形式。凭据优先级为显式入站凭据 → Bedrock bearer token → 完整 IAM 对部分 IAM 对只给一半会 fail-closed——Credential(bedrock)config.go L271-L298在 access key 或 secret key 任一为空时返回空凭据确保任何未签名的上游请求都不可能被发出。区域解析优先级为caveman.yaml的providers.bedrock.region→CAVE_BEDROCK_REGION→AWS_REGION→AWS_DEFAULT_REGION→ 默认us-east-1BedrockRegionconfig.go L218-L230。另一个安全细节入站 Bedrock 流量的x-api-key与 bearer 凭据会在 auth-mode 分类之前被打上bedrock_api_key标签standalone.go L54-L63。其效果是一个走 Claude Code 用户代理的 Bedrock 调用无法把付费 Bedrock 流量重新标记成订阅制流量。Mantle 路由默认关闭。Mantle 提供的 Anthropic Messages 兼容路由/bedrock/anthropic独立于默认 Bedrock 通道仅在部署显式设置CAVE_BEDROCK_MANTLE_ENABLED时启用。通过 CLI 接入 Agent。代理由cavemanCLI 驱动caveman start拉起caveman-proxycaveman wrap agent把该 Agent 的 provider base URL 指过来。对 Bedrock 上的 Claude Codewrap 会保留本地的 AWS BYOK 环境面对托管网关时则通过 Claude Code 的 custom-header 接缝附加 Caveman 项目 key子进程没有 AWS 凭据时由网关解析项目存储的 Bedrock 凭据环境中存在 bearer key 或完整 IAM 元组时wrap 会把它以x-cave-upstream-key头临时转发bearer 优先IAM 编码为AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY[:AWS_SESSION_TOKEN]。含换行的 key 与不完整的 IAM 环境会在启动前直接失败。五、字节安全不变量从 README 承诺到源码证据byte-safe 是这套代理的核心契约README 的承诺在源码里能找到一一对应的实现1. record 模式永不变换变换出错回退原字节。gateway包文档server.go L1-L13写明record 模式恒为直通任何变换环节出问题都原样转发原始字节HTTP 200fail-open而不是回 400。引擎压缩器同样遵守engineCompressor.CompressSegmentstandalone.go L201-L207在eng.Compress出错时返回原始 segment 并声明零差额。2. SSRF 防护常开且不可被环境开关关闭。StandaloneHTTPClientstandalone.go L318-L332用ssrf.SelfHostedConfig()构造上游客户端在拨号层阻断回环/私有/链路本地/metadata 地址——这与托管网关仅 prod 开启防护不同standalone 永远开启。本地模型服务器如 Ollama可通过CAVE_SSRF_ALLOWLIST把特定 host 加回localhost这一条会覆盖127.0.0.0/8与::1metadata 与链路本地地址在所有模式下保持阻断。3. record 模式承诺精确的响应线上字节。同一函数里有一处不起眼但重要的细节Go 标准库在调用方未指定Accept-Encoding时会自动注入 gzip 并透明解压这会让 record 模式的响应字节与 provider 实际发出的不同因此 standalone 客户端显式设置transport.DisableCompression truestandalone.go L327-L329。4. 无虚假节省no-fake-savings。本地花费库的每行记录Basis: inferred从不写verified也从不把逐请求数字重投影成月度口径caveman-proxy stats的 Summary 同理见 main.go L362-L363 注释。5. 路由与模式双双 fail-closed。未知路由返回 404未知模式回落record。健康检查端点GET /health/readyserver.go L504-L521返回billing: byok标识本代理只是转发调用者自己选择的 provider 凭据SDK 侧的美元预算对缺失/未知 billing 来源会 fail-closed。服务端还暴露GET /health/live与极简的GET /metrics仅cave_proxy_inflight_requests一个计数以及 ChatGPT 登录版 Codex 专用的/chatgpt/前缀路由OAuth 保持转发 Responses 通道 live-zone 压缩 精确原文回退。6. 监听地址只允许回环见第三节防止无鉴权代理外泄。六、路由面把 provider 原生路径挂到回环上代理对外呈现的是 provider 兼容的 HTTP 路由完整列表见 docs/technical/proxy-and-providers.md# Anthropic /anthropic/v1/messages /anthropic/v1/messages/count_tokens /v1/messages # OpenAI /openai/v1/chat/completions /openai/v1/responses /openai/v1/embeddings /v1/chat/completions /v1/responses /v1/embeddings # Google Gemini /gemini/v1beta/models/{model}:generateContent /gemini/v1beta/models/{model}:streamGenerateContent /gemini/v1beta/models/{model}:countTokens # Amazon Bedrock /bedrock/model/{model}/invoke /bedrock/model/{model}/invoke-with-response-stream /bedrock/model/{model}/converse /bedrock/model/{model}/converse-stream # 可选 Mantle 兼容路由默认禁用 /bedrock/anthropic/v1/messages # Azure配置 base URL 后/azure/... # Vertex配置 base URL 后/vertex/v1/projects/... # OpenAI 兼容命名上游 /compat/{name}/...Anthropic 与 OpenAI 同时携带带前缀与裸路径bare route两种形态Gemini 的裸路径在 profile 配置使用时也接受。compat 的语义是 HTTP 形状兼容不保证支持某 provider 的全部扩展特性。流式方面代理保持 provider 的流式协议与状态码行为请求侧变换在上游派发前完成流式响应保持流式。七、花费存储与本地记账实操全部本地状态集中在~/.caveman/可用CAVEMAN_HOME整体迁移caveman.db—— SQLite 花费库modernc.org/sqlite无 cgo实现TelemetrySink记录每个请求的真实 provider 用量ccr.db—— CCR 内容恢复存储压缩/pixel 模式下被替换的原始内容存于此可经披露的句柄字节精确取回proxy.log/proxy.log.1—— 代理自身日志运行态文件 —— 记录监听地址、模式、ownerstart/wrap与版本供后续caveman wrap校验复用的代理是否匹配其请求的恢复契约。记账的实操入口是caveman-proxy stats不带参数打印完整花费摘要Summary--recent N打印最近 N 行请求--json --since RFC3339输出会话结束时本可节省所需的紧凑 observe-estimate 对象。摘要的 basis 恒为inferred。围绕这套本地数据trialstart/finish/analyze/report/export/promote、usageimport/link/refresh/unlink codex、claude 用量、learnscan/report/savings/apply/applied/simulate等子命令构成了一个纯本地、不依赖任何云端服务的分析闭环——它们的输出同样携带basis: inferred。八、共享适配器集一次修改两个代理受益README 最后一行点出了仓库层面的关键架构决策providers/下的字节安全 provider 适配器Adapter接口 Base嵌入 UsageScanner/ParseUsageBytes见 proxy/providers/adapter.go被托管网关从这里导入共享覆盖 anthropic、openai、gemini、azureopenai、bedrock、vertex、openaicompat 七个适配器默认装配四家在 standalone.gobuildAdaptersL275-L307。从源码结构看ResolveUpstreamURL只接收providers.RouteContext与控制面零耦合——这正是公共/私有边界的设计方式proxy/CLAUDE.md 明确要求公共代理代码永不反向导入托管云侧并由make check-boundaries强制。新 provider 或优化器工作的落点就是这个共享目录改一次standalone 与 managed 两个代理同时获得。小结Caveman Gateway 的设计可以用 README 的三句话概括换 base URL 即接入、record 模式恒直通且出错转发原字节、记账只标inferred不标verified。源码层面这些承诺分别由gateway的 fail-open 转发逻辑、standalone的 SSRF 常开客户端与DisableCompression、config的未知模式回落与回环监听校验、以及store的inferred-only 写入共同保证。对于想在本地评估 Caveman 压缩效果而不愿引入任何云依赖的开发者caveman start之后的caveman-proxy stats就是最诚实的入口它给出的每一个数字都能追溯到本地 SQLite 中的 provider 原始用量行。【免费下载链接】caveman why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman项目地址: https://gitcode.com/GitHub_Trending/caveman1/caveman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表