# CLIProxyAPI 升级、构建与部署记录 ## 当前基线 | 项目 | 当前值 | |---|---| | CLIProxyAPI Tag | `v7.2.135` | | submodule 提交 | `ee2c494788f8a089c58f7ae9aa6ebd1b422211cb` | | patched 构建版本 | `v7.2.135-dev` | | Native ABI | `1` | | RPC schema | `4` | | Go | `1.26.6` | | 本地运行目录 | `.runtime` | | 本地管理页面 | `http://127.0.0.1:8317/management.html` | | 远端目录 | `root@akko.pchuan.top:/root/cpa` | DeepSeek 必须配置在 CPA 的 `codex-api-key` 通道,`base-url` 使用 `https://api.deepseek.com`。不要把该凭证配置为 `openai-compatibility`。Windows Codex CLI 连接本地 CPA 时,provider 的 `base_url` 使用 `http://127.0.0.1:8317/v1`,`wire_api` 使用 `responses`。 当前本地测试状态保存在被 Git 忽略的 `.runtime`: - CPA 配置:`.runtime/config.yaml`; - billing 数据库:`.runtime/data/billing.db`; - 管理 Key 和默认下游 Key:`000000`; - 测试模型:`deepseek-v4-flash`; - 默认额度:`$10`,最大并发数:`4`; - 当前价格是本地验收价格,不作为生产价格依据。 升级宿主或插件时保留配置和数据库,不重复初始化 Key、价格和额度。 ## 已知上游测试失败 CLIProxyAPI `ee2c4947` 在 Debian WSL 中运行 `go test ./... -count=1` 时有以下失败: | 测试 | 实际值 | 期望值 | |---|---|---| | `TestApplyClaudeHeaders_DisableDeviceProfileStabilization` | `X-Stainless-Os=MacOS` | `Linux` | | `TestApplyClaudeHeaders_LegacyModePreservesConfiguredUserAgentOverrideForClaudeClients` | `X-Stainless-Os=MacOS` | `Linux` | | `TestClaudeExecutor_NonClaudeRequestUsesClaudeCode220CLIFingerprint` | `X-Stainless-Os=MacOS` | `Linux` | 2026-08-18 已在未应用任何 billing 补丁的纯上游 `ee2c4947` 临时 worktree 中复现相同结果。三项补丁没有修改 `internal/runtime/executor`,因此同一提交、同一 WSL 环境、同一失败内容再次出现时,直接记为已知上游失败,不再创建干净 worktree复测。 出现以下任一情况时重新验证: - submodule 提交不再是 `ee2c4947`; - 上游修改了 `internal/runtime/executor/claude_executor_test.go`、`claude_executor_request.go` 或 `helps/claude_device_profile.go`; - 失败测试、行号、实际值或期望值发生变化; - 三项补丁开始修改 `internal/runtime/executor`。 ## submodule 升级 当前 submodule 工作区包含三项已应用补丁。升级前必须按反方向撤销,再切换上游提交: ```bash git -C .externals/CLIProxyAPI apply --reverse ../../patch/cli-proxy-api-request-lifecycle-cancel.patch git -C .externals/CLIProxyAPI apply --reverse ../../patch/cli-proxy-api-usage-identity.patch git -C .externals/CLIProxyAPI apply --reverse ../../patch/cli-proxy-api-usage-context.patch git -C .externals/CLIProxyAPI fetch --tags --prune origin git -C .externals/CLIProxyAPI switch --detach origin/main ``` 重新应用补丁: ```bash git -C .externals/CLIProxyAPI apply ../../patch/cli-proxy-api-usage-context.patch git -C .externals/CLIProxyAPI apply ../../patch/cli-proxy-api-usage-identity.patch git -C .externals/CLIProxyAPI apply ../../patch/cli-proxy-api-request-lifecycle-cancel.patch git -C .externals/CLIProxyAPI diff --check ``` 应用后 submodule 显示 `dirty` 是预期结果。根仓库提交新的 gitlink 指针和必要的 `patch/` 更新,不在 submodule 中创建派生提交。 ## 测试顺序 WSL 使用以下环境。Go bootstrap 可能低于 `1.26.6`,有效 toolchain 由 Go 自动下载;`gofmt` 位于有效 `GOROOT/bin`,因此需要补充 `PATH`: ```bash export GOPROXY=https://goproxy.cn,direct export PATH="$(go env GOROOT)/bin:$PATH" go version gofmt -h >/dev/null ``` 从 PowerShell 调用包含 Bash 变量、命令替换或多层引号的命令时,把内容写入 `.runtime/tmp/*.sh` 后交给 WSL 执行。`.runtime/tmp` 不提交。 每次升级执行以下检查: ```bash cd .externals/CLIProxyAPI go test -race ./internal/pluginhost ./sdk/api/handlers ./sdk/cliproxy/usage -count=1 go test ./... -count=1 cd ../.. go test ./... -count=1 go test -race ./... -count=1 ``` 补丁正确性的最低标准如下: - 三项补丁按顺序应用成功,`git diff --check` 通过; - `internal/pluginhost`、`sdk/api/handlers`、`sdk/cliproxy/usage` race 测试通过; - billing 全量测试和全量 race 测试通过; - CPA 全量测试除已记录的纯上游失败外通过; - CPA 和 billing 均可编译。 ## 构建 CPA 版本必须使用当前最新 Tag 加 `-dev`,提交取 submodule HEAD: ```bash cd .externals/CLIProxyAPI version=v7.2.135-dev commit="$(git rev-parse --short=8 HEAD)" build_date="$(date -u +%Y-%m-%dT%H:%M:%SZ)" CGO_ENABLED=1 go build -buildvcs=false \ -ldflags="-s -w -X main.Version=$version -X main.Commit=$commit -X main.BuildDate=$build_date" \ -o ../../.runtime/bin/cli-proxy-api.new ./cmd/server/ ../../.runtime/bin/cli-proxy-api.new -h >/dev/null ``` `-h` 会在第一行输出完整版本。上游没有 `--version` 参数,不要使用该参数核对版本。 构建插件: ```bash cd ../.. bash scripts/build.sh cp bin/billing.so .runtime/plugins/billing.so.new sha256sum bin/billing.so .runtime/plugins/billing.so.new ``` 两个插件哈希必须一致。 ## 本地替换与验收 本地 CPA 只使用 `.runtime`。替换前停止进程并保存旧产物: ```bash bash scripts/stop-test-host.sh backup=".runtime/backups/$(date +%Y%m%d-%H%M%S)" mkdir -p "$backup" cp .runtime/bin/cli-proxy-api "$backup/" cp .runtime/plugins/billing.so "$backup/" mv .runtime/bin/cli-proxy-api.new .runtime/bin/cli-proxy-api mv .runtime/plugins/billing.so.new .runtime/plugins/billing.so bash scripts/run-test-host.sh ``` 启动后检查: 1. `/healthz` 返回 `status=ok`; 2. `/v0/management/plugins` 中 billing 的 `registered`、`enabled`、`effective_enabled` 都为 `true`; 3. 日志版本与构建参数一致,且没有插件错误或 panic; 4. 无下游 Key 的请求返回 401; 5. 有效 billing Key 的 `/v1/responses` 请求返回 200; 6. 请求只新增一条明细,包含唯一 Request ID 和 Token; 7. 额度只扣减一次,`active_requests` 回到 0。 本地 CPA 通过 WSL localhost 转发供 Windows 使用。取消链路测试需要在 WSL 内直连 `127.0.0.1:8317`,避免 Windows localhost 转发延迟传递断开。 ## 远端发布 核心升级使用 PowerShell 脚本: ```powershell ./scripts/push.ps1 ``` 脚本默认执行以下操作: - fetch `origin/main` 并要求 submodule HEAD 与其一致; - 要求 submodule 修改文件集合与 `patch/*.patch` 声明一致; - 运行三个补丁相关包的 race 测试; - 使用最新 Tag 加 `-dev` 和当前提交、构建时间编译核心; - 生成 gzip 最高压缩级别的核心包和 SHA-256; - 上传后在远端重新校验压缩包、版本和核心哈希; - 等待 billing `active_requests=0`,备份后只替换 CPA 核心; - 核对配置、所有插件动态库、插件注册状态和独立 keeper; - 失败时恢复旧核心并按部署前状态启动 CPA Manager Plus。 只执行本地构建、测试和打包,不上传或部署: ```powershell ./scripts/push.ps1 -WhatIf ``` 复用已有核心时使用 `-SkipBuild -BinaryPath `;跳过补丁相关 race 测试使用 `-SkipTests`;部署锁定但不是当前 `origin/main` 的提交时显式使用 `-SkipUpstreamCheck`。请求排空默认等待 120 秒,可通过 `-DrainTimeoutSeconds` 和 `-DrainPollSeconds` 调整。 远端只部署本项目的 billing 和已要求启用的 keeper。发布步骤如下: 1. 本地完成真实模型请求、协议、计费和取消链路验收; 2. 对 CPA 二进制和插件计算 SHA-256; 3. 使用 gzip、tar.gz 或 `scp -C` 上传; 4. 停止 `/root/cpa/cpa.sh` 管理的进程; 5. 把旧 CPA、billing、keeper 和 `data/cpa-ext.db*` 保存到 `/root/cpa/backups//`; 6. 替换二进制和插件,保留配置及 secret 文件; 7. 启动进程并检查健康状态、版本、插件注册状态和日志; 8. 启动失败时恢复同一备份目录中的文件并重启。 远端不发送 `/v1/responses`、`/v1/chat/completions` 或 compact 请求。管理密钥和下游 Key 在远端脚本内部从 secret 文件或管理 API 读取,不输出到终端和普通日志。 `cpa.sh start` 会先把管理 Key 同步到 `config.yaml`,CPA 启动后会重新保存该字段的哈希,因此每次启动后 `config.yaml` 的原始 SHA-256 可能变化。部署校验应把 `remote-management.secret-key` 的值归一化后比较其余配置内容,不得因为原始配置哈希变化回滚核心。 远端存在持续请求时,在远端部署脚本内部先完成压缩包和插件检查,再每 5 秒读取 billing `active_requests`。检测到 0 后立即停止 CPA,避免在本地轮询与远端执行之间出现新请求。 ## 2026-08-18 验证记录 `v7.2.135` / `ee2c4947` 已完成以下验证: - 三项补丁重新应用成功,共修改 11 个文件,增加 289 行,删除 10 行; - 补丁相关三个包的 race 测试通过; - billing 全量测试和全量 race 测试通过; - CPA 和 billing Linux amd64 产物编译成功; - CPA 运行版本为 `v7.2.135-dev / ee2c4947`; - billing `0.1.0` 加载并注册; - DeepSeek Codex `/v1/responses` 返回 200 和 `CODEX_READY`; - 该请求记录 129 Token,只产生一条计费记录,`active_requests=0`; - 本地替换前产物保存在 `.runtime/backups/20260818-154252-v7.2.135/`。 同日已完成远端核心升级: - 只替换 `/root/cpa/bin/cli-proxy-api`,插件、配置、数据库和独立 keeper 未替换; - 远端运行版本为 `v7.2.135-dev / ee2c4947`,核心 SHA-256 为 `d702d8d65a06911b5bec78476d84e228bcfb57e03c511b4c1d89df8f460c41fd`; - CPA PID 为 `278177`,独立 keeper PID 保持为 `230299`; - billing 和 keeper `0.1.0` 均已加载、注册和启用; - `/healthz` 正常,启动日志没有 panic 或插件错误; - 未向远端模型端点发送验收请求; - 升级前文件保存在 `/root/cpa/backups/20260818T081102Z-core-v7.2.135/`。