Files
cpa-plugin/docs/operations.md
T

10 KiB
Raw Blame History

CLIProxyAPI 升级、构建与部署记录

当前基线

项目 当前值
CLIProxyAPI Tag v7.2.139
submodule 提交 0a14eb70ce19fac1d114bcdb4a476d61adc819e2
patched 构建版本 v7.2.139-dev
Native ABI 1
RPC schema 4
Go 1.26.x
本地运行目录 .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/v1wire_api 使用 responses

当前本地测试状态保存在被 Git 忽略的 .runtime

  • CPA 配置:.runtime/config.yaml
  • billing 数据库:.runtime/data/billing.db
  • 管理 Key 和默认下游 Key000000
  • 测试模型:deepseek-v4-flash
  • 默认额度:$10,最大并发数:4
  • 当前价格是本地验收价格,不作为生产价格依据。

升级宿主或插件时保留配置和数据库,不重复初始化 Key、价格和额度。

已知上游测试失败

CLIProxyAPI 0a14eb70 在 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
TestInPlaceByteWritesAreReviewed internal/home/client.go 清单项已过期 文件已无原地字节写入
TestInPlaceByteWritesAreReviewed internal/pluginstore/auth.go 清单项已过期 文件已无原地字节写入

2026-08-22 已在未应用任何 billing 补丁的纯上游 0a14eb70 临时 worktree 中复现以上 5 项。三项补丁不修改 internal/runtime/executorinternal/utilinternal/homeinternal/pluginstore,因此同一提交、同一 WSL 环境、同一失败内容再次出现时,直接记为已知上游失败,不修复、不再创建干净 worktree复测。

出现以下任一情况时重新验证:

  • submodule 提交不再是 0a14eb70
  • 上游修改了 internal/runtime/executor/claude_executor_test.goclaude_executor_request.gohelps/claude_device_profile.go
  • 失败测试、行号、实际值或期望值发生变化;
  • 三项补丁开始修改 internal/runtime/executor

submodule 升级

当前 submodule 工作区包含三项已应用补丁。升级前必须按反方向撤销,再切换上游提交:

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

重新应用补丁:

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

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 不提交。

每次升级执行以下检查:

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/pluginhostsdk/api/handlerssdk/cliproxy/usage race 测试通过;
  • billing 全量测试和全量 race 测试通过;
  • CPA 全量测试除已记录的纯上游失败外通过;
  • CPA 和 billing 均可编译。

构建

CPA 版本必须使用当前最新 Tag 加 -dev,提交取 submodule HEAD

cd .externals/CLIProxyAPI
version=v7.2.139-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 参数,不要使用该参数核对版本。

构建插件:

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 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 的 registeredenabledeffective_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 脚本:

./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。

只执行本地构建、测试和打包,不上传或部署:

./scripts/push.ps1 -WhatIf

复用已有核心时使用 -SkipBuild -BinaryPath <path>;跳过补丁相关 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/<timestamp>/
  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/