十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Caveman 本地代理与多提供商接入全解:127.0.0.1:8787 上的字节安全流量网关

Caveman 本地代理与多提供商接入全解:127.0.0.1:8787 上的字节安全流量网关 Caveman 本地代理与多提供商接入全解127.0.0.1:8787 上的字节安全流量网关【免费下载链接】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/cavemanCaveman 的本地代理local proxy是一个只绑定在回环地址上的开发者工具它在127.0.0.1:8787上暴露 Anthropic、OpenAI、Gemini、Bedrock 等提供商兼容的 HTTP 路由对符合条件的请求执行本地变换如上下文压缩再把请求转发到真实提供商端点并记录本地用量。读完本文你将掌握如何用caveman start启动代理、把 Agent 的 base URL 指过去、理解其请求路径与七种运行模式、配置各提供商挂载与凭据来源并理解其 loopback 强制与 SSRF 出站防护的实现细节。定位单操作者开发工具而非多用户网关本地代理的本质是base-URL-swap 反向代理把任意 Agent 的 provider base URL 指向http://127.0.0.1:8787其 LLM 流量就会经过 Caveman无需修改任何代码。启动方式是caveman start默认监听地址为127.0.0.1:8787。需要明确它的边界它是单操作者single-operator开发者工具不是多用户网络网关BYOK自带密钥零云依赖凭据来自请求本身或本地环境变量record 模式永远是字节透传任何变换环节出现问题原始字节原样转发每笔花费记录到本地~/.caveman/caveman.db且所有节省数字只标记为inferred推断值从不标记为verified。上述定位在 proxy/README.md 中有明确声明运行时代码也印证了这一点入口文件 proxy/cmd/caveman-proxy/main.go 的包注释说明该二进制loads caveman.yaml, opens the local~/.caveman/spend store, and serves the byte-safe lifecycle on 127.0.0.1:8787 with zero cloud dependencies. Every savings figure it records isinferred。请求路径从 Agent 到提供商的完整链路本地代理的请求处理遵循一条固定序列源自 docs/technical/proxy-and-providers.mdAgent SDK ──provider-compatible request──▶ 本地代理 本地代理 ──inspect / transform eligible context──▶ Engine Engine ──original or compact request data──▶ 本地代理 本地代理 ──forward request with provider credential──▶ Provider Provider ──response usage──▶ 本地代理 ──▶ Agent SDK从源码结构看proxy/internal/gateway/server.go 的包注释把这条生命周期概括为match → authenticate → inspect → byte-safe transform → upstream → meter匹配 → 认证 → 检查 → 字节安全变换 → 上游 → 计量。它与托管网关共用同一形态区别仅在于把多租户控制面替换为三个注入的缝seams注入缝接口职责Authenticatorserver.go接受请求并返回RuntimeMode与 optimizer 策略CredentialResolverserver.go解析上游 provider 密钥BYOK 环境变量或请求透传TelemetrySinkserver.go记录一条真实的每请求花费行本地 SQLite凭据处理原则与文档一致提供商凭据优先从入站请求中保留inbound auth header只有当集成方没有随请求发送凭据时才回退到本地环境变量的命名密钥。这一点在 proxy/internal/config/config.go 的Credential方法中可见——每个 provider 的凭据对象都带AuthFallbackEnv字段回退仅在入站缺失时生效。路由表各提供商挂载点全览代理在127.0.0.1:8787上按提供商划分挂载前缀。以下路由表完整继承自原文档使用哪个提供商就把对应前缀配进 Agent 的 base URL。Anthropic/anthropic/v1/messages /anthropic/v1/messages/count_tokens /v1/messagesOpenAI/openai/v1/chat/completions /openai/v1/responses /openai/v1/embeddings /v1/chat/completions /v1/responses /v1/embeddingsGoogle Gemini/gemini/v1beta/models/{model}:generateContent /gemini/v1beta/models/{model}:streamGenerateContent /gemini/v1beta/models/{model}:countTokens当 profile 配置使用裸路径时等价的 bare Gemini 路径也会被接受/v1beta/models/...形式源码中 proxy/internal/gateway/gemini_bare_route_test.go 专门覆盖该行为的测试。Amazon Bedrock/bedrock/model/{model}/invoke /bedrock/model/{model}/invoke-with-response-stream /bedrock/model/{model}/converse /bedrock/model/{model}/converse-stream可选的 Mantle 兼容路由Anthropic Messages 兼容形态/bedrock/anthropic/v1/messages从 proxy/README.md 可知Bedrock Runtime 在 standalone 模式是一等公民默认走 Bedrock Runtime lane/bedrock/anthropic的 Mantle 路由独立存在且默认关闭只有显式设置CAVE_BEDROCK_MANTLE_ENABLED才启用。Bedrock 凭据支持两条路径——低摩擦的 bearer 密钥或完整 IAM 密钥对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 凭据有效。凭据优先级为显式入站凭据 → Bedrock bearer token → 完整 IAM 对只有半套 IAM缺 access key 或 secret会失败关闭fail closed绝不会被当作可用凭据。这一点可以在 proxy/internal/config/config.go 的Credential方法中验证accessKey || secretKey 时返回空凭据A partial IAM pair is never useful and must not fall through as an apparently valid credential。区域解析优先级为providers.bedrock.regioncaveman.yaml→CAVE_BEDROCK_REGION→AWS_REGION→AWS_DEFAULT_REGION→ 默认us-east-1与 config.go 中BedrockRegion()的实现完全一致。Azure OpenAI 与 Vertex AIAzure 在其 base URL 配置后挂载在/azure/...下Vertex 挂载在/vertex/v1/projects/...下支持由适配器实现的公有 Google 与 Anthropic 发布者publisher路由形态。两者均为显式 opt-in因为端点和身份配置属于安装环境特有。Vertex 的适配器实现位于 proxy/providers/vertex/vertex.go 与 routing.go。OpenAI 兼容提供商命名兼容挂载使用如下形式/compat/{name}/...每个挂载在caveman.yaml的compat段声明base_url和存放凭据的环境变量名compat: myllm: base_url: https://llm.example.com/v1 api_key_env: MY_LLM_API_KEY从源码看config.go 的validateCompat在启动时强制校验名称合法、base_url必填且格式合法由openaicompat.ValidateName/ValidateBaseURL检查CompatCredential则说明空的api_key_env有意表示该命名上游不发 Authorization 头。要特别注意文档的限定兼容指 HTTP 形态HTTP shape兼容不保证支持某个提供商的所有扩展特性。运行模式七种模式与失败关闭语义原文档定义了七种模式行为语义如下模式请求行为record模型可见字节原样转发永远透传compress对符合条件的 Engine 变换施加带恢复CCR能力pixel允许配置过的 text-to-image 上下文传输recommend只产生本地推荐不激活任何变换shadow评估符合条件的变更但不实际提供canary对选定流量应用配置的实验性行为active应用已启用的 optimizer 行为关键规则未知模式一律退化为record。标准本地 CLI 工作流只暴露 record、compress、pixel 三种其余模式服务于受控评估路径。源码印证了这一fail closed设计。proxy/internal/config/config.go 中定义了已知模式白名单且未知值在加载时即被归一化为recordvar knownModes map[string]bool{record: true, recommend: true, shadow: true, canary: true, active: true, compress: true, pixel: true} // withDefaults 中 if !knownModes[c.Mode] { c.Mode record }注释明确说明原因anything else fails closed torecordso an unrecognized config can never silently enable transforms——未识别的配置永远不可能悄悄打开变换。此外 proxy/cmd/caveman-proxy/main.go 的initializeNativePersistence展示了运行期的第二道保险当本地恢复存储CCR不可用或会话关联密钥缺失时代理会显式降级为 record 透传并禁用 native runtime而不是带着不可恢复的压缩状态继续运行。流式处理变换前置、流式保持代理保留提供商的流式协议与状态码行为。时序上的关键约束是请求侧变换在上游分发之前完成流式响应保持流式streaming response stays streaming。从源码结构看RequestRecord 字段中的Stream、TTFBMStime-to-first-byte以及RequestHashComplete字段都围绕流式场景设计流式传输失败时可能只捕获到请求体前缀这类行会保留空哈希并标记RequestHashCompletefalse保证审计诚实性。凭据管理密钥不入库、不落地原文档的凭据章节给出两条硬规则源码逐条对应API 密钥永远不写进 YAML。caveman.yaml只承载模式、监听地址、optimizer 开关与各 provider base URLAPI key 在请求时从环境读取。config.go 顶部的包注释即声明此约定。各提供商的命名环境变量映射为Provider环境变量AnthropicANTHROPIC_API_KEYOpenAIOPENAI_API_KEYGeminiGEMINI_API_KEYAzure OpenAIAZURE_OPENAI_API_KEYOpenAI 兼容OPENAI_COMPAT_API_KEY或 compat 段自定义api_key_envBedrockAWS_BEARER_TOKEN_BEDROCK或AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 可选AWS_SESSION_TOKEN从不记录 Authorization 头。日志经过 redaction 层main.go 中 slog handler 使用redact.SlogReplaceAttr对日志属性做脱敏本地遥测只存用量与有界元数据如 RequestRecord 中的 token 数、哈希、状态码不存原始密钥。端点安全loopback 强制 SSRF 出站防护代理有两道安全边界均已在源码中确认入站拒绝非 loopback 监听地址config.go 的validateListen是启动期硬校验func validateListen(listen string) error { host, port, err : net.SplitHostPort(strings.TrimSpace(listen)) if err ! nil || port { return fmt.Errorf(listen address %q must be loopback host:port, listen) } if strings.EqualFold(host, localhost) { return nil } ip : net.ParseIP(host) if ip nil || !ip.IsLoopback() { return fmt.Errorf(listen address %q is not loopback; standalone proxy has no inbound authentication, listen) } return nil }原因是直白的这是一个无入站认证的 BYOK 代理绑定空地址、通配符或任何非回环地址都会把配置好的所有 provider 凭据暴露到网络上。出站SSRF 防护与白名单逃生门shared/platform/ssrf/ssrf.go 实现了双向 SSRF 防护预检 URL 校验 DialContext 拨号期校验后者用于防 DNS rebinding。其封禁策略分层永远封禁任何模式link-local含云元数据地址169.254.169.254、unique-local IPv6、组播、文档/测试段、CGNAT、Teredo/6to4以及::ffff:0:0/96这类 IPv4-mapped IPv6 绕过形态条件封禁loopback127.0.0.0/8、::1/128与 RFC1918 私网段10/8、172.16/12、192.168/16——self-hosted 模式下可通过显式白名单放回。对本地自托管模型Ollama、LM Studio、测试 stub 等的接入通过CAVE_SSRF_ALLOWLIST精确加入主机名或 IP 即可其中localhost作为白名单项会同时覆盖127.0.0.0/8与::1。proxy/internal/standalone/standalone.go 中的StandaloneHTTPClient用ssrf.SelfHostedConfig守护每一次上游拨号保证该逃生门真实生效standalone_test.go 用t.Setenv(CAVE_SSRF_ALLOWLIST, 127.0.0.1)验证了放行路径。在允许接入本地模型端点之前建议先阅读 Security and privacy。配置加载与运行环境要点caveman start背后的二进制 caveman-proxy 的启动流程值得开发者了解因为它决定了排查问题的切入点解析 home 目录默认~/.caveman可用CAVEMAN_HOME覆盖创建目录从CAVEMAN_CONFIG默认~/.caveman/caveman.yaml加载配置——文件缺失不是错误得到默认配置record 模式、127.0.0.1:8787即裸caveman start是一次合法的 record-only 会话config.go 的Load函数注释打开本地花费存储CAVEMAN_DB默认~/.caveman/caveman.db与 CCR 恢复存储默认~/.caveman/ccr.db按模式装配 Compressor仅当mode为compress或pixel且恢复存储可用时才接入真实引擎压缩器recordCAVEMAN_OBSERVE_ESTIMATE时接入只读估计器绑定监听器、写运行状态runstate供后续 wrap 校验复用的代理、启动 HTTP 服务ReadHeaderTimeout 5s、ReadTimeout 30s、MaxHeaderBytes 1MB。健康检查与指标端点同样值得在排障时使用server.go 的HandlerGET /health/live → {ok:true,service:caveman-proxy,billing:byok,adapters:N} GET /health/ready GET /metrics → cave_proxy_inflight_requests N此外日志会落盘到~/.caveman/proxy.log超过 16MB 轮转一次为proxy.log.1这对排查上游失败但客户端只有笼统报错的场景很有价值。定价与用量诚实的数字Provider catalog 提供带日期的公开 list price未知 provider 或模型的定价解析为零并打上unpriced标记而不是猜测成本——main.go 中stats路径的注释同样强调The summarys basis is alwaysinferred; the figures are never re-projectedprovider 报告的 token 数与 Engine 自己的估计值始终分开记录RequestRecord中TokenUsageBasis独立于Basis前者取值provider_complete/provider_partial/provider_malformed/unavailable后者是节省数字的来源依据standalone 恒为inferred展示的 provider 成本是list-price 小计不是 provider 账单。详细口径见 Accounting and evidence。故障排查清单原文档给出的排查条目结合源码可以定位得更精确404通常是 Agent 用错了 provider 挂载前缀或裸路由。对照本文路由表核对 base URL认证失败分别检查入站请求头与 provider 凭据来源环境变量检查过程中不要打印密钥值自定义 base URL 被拒通常需要精确的CAVE_SSRF_ALLOWLIST条目主机名或 IP上下文意外未变化这在 record 模式下是正常行为compress 模式下变换未过 parse、size、policy 或 recovery 任一闸门时同样会回退为原样字节转发——byte-safe 契约就是任何变换问题都向前兼容行为对比在 record 模式重放同一请求比较 provider 请求与响应的类别class而非带密钥的原始日志本地还提供CAVE_CAPTURE_DIR捕获目录用于受控的本地观测见 server.go 中capture字段注释它never affects what is sent, recorded, or claimed。小结Caveman 本地代理把给 Agent 省钱做成了一个可本地验证的字节安全网关caveman start一条命令起服务路由表覆盖主流提供商的兼容形态七种模式从纯记录到主动优化逐级放开且全部失败关闭凭据永远走环境变量或入站透传监听强制 loopback、出站强制 SSRF 防护所有节省数字只标注inferred。对需要理解实现细节的读者建议按 proxy/README.md → proxy/cmd/caveman-proxy/main.go启动装配→ proxy/internal/config/config.go配置与凭据解析→ proxy/internal/gateway/server.go请求生命周期→ proxy/providers/各提供商字节安全适配器的顺序阅读每一环都有对应的*_test.go可供验证。【免费下载链接】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),仅供参考
返回列表