From 25736099ee44902462cb6fb30e958e969bcc07dc Mon Sep 17 00:00:00 2001 From: chuan Date: Sat, 22 Aug 2026 19:18:54 +0800 Subject: [PATCH] chore: upgrade CLIProxyAPI to v7.2.139 --- .externals/CLIProxyAPI | 2 +- .gitattributes | 1 + AGENTS.md | 4 ++-- README.md | 2 +- docs/operations.md | 14 +++++++------- patch/README.md | 12 ++++++------ patch/cli-proxy-api-usage-identity.patch | 24 ++++++++++++------------ 7 files changed, 30 insertions(+), 29 deletions(-) create mode 100644 .gitattributes diff --git a/.externals/CLIProxyAPI b/.externals/CLIProxyAPI index 85d2fad..0a14eb7 160000 --- a/.externals/CLIProxyAPI +++ b/.externals/CLIProxyAPI @@ -1 +1 @@ -Subproject commit 85d2faddd17e6f4f8675a84ee28b131f702e8eaa +Subproject commit 0a14eb70ce19fac1d114bcdb4a476d61adc819e2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7a9c93e --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +patch/*.patch whitespace=-space-before-tab diff --git a/AGENTS.md b/AGENTS.md index c7007e8..873ff4f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,8 +34,8 @@ - 本地 CPA 在 WSL 中运行,项目运行目录统一使用 `cpa-plugin/.runtime`;Windows 客户端经 `127.0.0.1` 访问 WSL 时,localhost 转发层可能不会立即向 CPA 传递客户端断开,取消链路测试优先在 WSL 内直连执行。 - 从 PowerShell 跨 WSL 或 SSH 执行包含 Bash 变量、命令替换或多层引号的逻辑时,优先在 `.runtime/tmp/` 创建临时脚本后传入目标环境执行,不拼接复杂的单行 shell;临时脚本不提交。 -- CLIProxyAPI 宿主补丁保存在 `patch/`,当前已验证基线为 `v7.2.137` / `85d2fadd`,必须按 `usage-context`、`usage-identity`、`request-lifecycle-cancel` 的顺序应用;升级 CPA 后按 `docs/operations.md` 核对补丁和已知上游测试例外。 -- 构建本项目 patched CPA 时必须按上游 release workflow 使用 `-ldflags` 注入 `main.Version`、`main.Commit` 和 `main.BuildDate`。`Version` 固定使用“当前上游最新 tag + `-dev`”格式(例如 `v7.2.137-dev`),用于明确区分官方 Release 与本项目补丁构建;不得发布只显示 `dev`、`none` 或 `unknown` 的产物。上传前先在本地执行二进制并核对完整版本输出。 +- CLIProxyAPI 宿主补丁保存在 `patch/`,当前已验证基线为 `v7.2.139` / `0a14eb70`,必须按 `usage-context`、`usage-identity`、`request-lifecycle-cancel` 的顺序应用;升级 CPA 后按 `docs/operations.md` 核对补丁和已知上游测试例外。 +- 构建本项目 patched CPA 时必须按上游 release workflow 使用 `-ldflags` 注入 `main.Version`、`main.Commit` 和 `main.BuildDate`。`Version` 固定使用“当前上游最新 tag + `-dev`”格式(例如 `v7.2.139-dev`),用于明确区分官方 Release 与本项目补丁构建;不得发布只显示 `dev`、`none` 或 `unknown` 的产物。上传前先在本地执行二进制并核对完整版本输出。 - CPA Linux 可执行文件解压后约 60 MiB,`gzip -9` 后约 20 MiB。上传远端时使用 gzip/tar.gz 或 `scp -C`,不要直接传输未压缩二进制;部署后的运行文件仍需解压为原始可执行文件。 - 实际服务器为 `root@akko.pchuan.top`,CPA 根目录为 `/root/cpa`。只维护本项目的 `billing` 和已要求启用的 `keeper`,不启用或部署其他参考插件。 - 远端替换 CPA 或 billing 前,先停止 `/root/cpa/cpa.sh` 管理的进程,并把旧二进制、插件和 `data/cpa-ext.db*` 备份到 `/root/cpa/backups//`;新版本启动失败时恢复旧二进制和插件。 diff --git a/README.md b/README.md index dc59e05..2233c67 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ CLIProxyAPI 负责 HTTP 接入、协议转换、上游凭证和实际请求执 ## 当前兼容目标 -- CLIProxyAPI 基线:`v7.2.137` / `85d2faddd17e6f4f8675a84ee28b131f702e8eaa`,由 `.externals/CLIProxyAPI` submodule 锁定,需依次应用 `patch/` 中三项宿主补丁 +- CLIProxyAPI 基线:`v7.2.139` / `0a14eb70ce19fac1d114bcdb4a476d61adc819e2`,由 `.externals/CLIProxyAPI` submodule 锁定,需依次应用 `patch/` 中三项宿主补丁 - 插件版本:`0.1.0` - Native ABI:`1` - RPC schema:最高 `4`,注册时按宿主版本向下协商;schema v4 提供 Usage 请求身份 diff --git a/docs/operations.md b/docs/operations.md index ca0ef0c..acd23a8 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -4,9 +4,9 @@ | 项目 | 当前值 | |---|---| -| CLIProxyAPI Tag | `v7.2.137` | -| submodule 提交 | `85d2faddd17e6f4f8675a84ee28b131f702e8eaa` | -| patched 构建版本 | `v7.2.137-dev` | +| CLIProxyAPI Tag | `v7.2.139` | +| submodule 提交 | `0a14eb70ce19fac1d114bcdb4a476d61adc819e2` | +| patched 构建版本 | `v7.2.139-dev` | | Native ABI | `1` | | RPC schema | `4` | | Go | `1.26.x` | @@ -29,7 +29,7 @@ DeepSeek 必须配置在 CPA 的 `codex-api-key` 通道,`base-url` 使用 `htt ## 已知上游测试失败 -CLIProxyAPI `85d2fadd` 在 Debian WSL 中运行 `go test ./... -count=1` 时有以下失败: +CLIProxyAPI `0a14eb70` 在 Debian WSL 中运行 `go test ./... -count=1` 时有以下失败: | 测试 | 实际值 | 期望值 | |---|---|---| @@ -39,11 +39,11 @@ CLIProxyAPI `85d2fadd` 在 Debian WSL 中运行 `go test ./... -count=1` 时有 | `TestInPlaceByteWritesAreReviewed` | `internal/home/client.go` 清单项已过期 | 文件已无原地字节写入 | | `TestInPlaceByteWritesAreReviewed` | `internal/pluginstore/auth.go` 清单项已过期 | 文件已无原地字节写入 | -2026-08-20 已在未应用任何 billing 补丁的纯上游 `85d2fadd` 临时 worktree 中复现以上 5 项。三项补丁不修改 `internal/runtime/executor`、`internal/util`、`internal/home` 或 `internal/pluginstore`,因此同一提交、同一 WSL 环境、同一失败内容再次出现时,直接记为已知上游失败,不修复、不再创建干净 worktree复测。 +2026-08-22 已在未应用任何 billing 补丁的纯上游 `0a14eb70` 临时 worktree 中复现以上 5 项。三项补丁不修改 `internal/runtime/executor`、`internal/util`、`internal/home` 或 `internal/pluginstore`,因此同一提交、同一 WSL 环境、同一失败内容再次出现时,直接记为已知上游失败,不修复、不再创建干净 worktree复测。 出现以下任一情况时重新验证: -- submodule 提交不再是 `85d2fadd`; +- submodule 提交不再是 `0a14eb70`; - 上游修改了 `internal/runtime/executor/claude_executor_test.go`、`claude_executor_request.go` 或 `helps/claude_device_profile.go`; - 失败测试、行号、实际值或期望值发生变化; - 三项补丁开始修改 `internal/runtime/executor`。 @@ -110,7 +110,7 @@ CPA 版本必须使用当前最新 Tag 加 `-dev`,提交取 submodule HEAD: ```bash cd .externals/CLIProxyAPI -version=v7.2.137-dev +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 \ diff --git a/patch/README.md b/patch/README.md index eff84ae..4b4b4fb 100644 --- a/patch/README.md +++ b/patch/README.md @@ -1,6 +1,6 @@ # CLIProxyAPI 宿主补丁 -这里保存 billing 最初为 CLIProxyAPI `v7.2.133` 制作、已在 `v7.2.137` 重新验证的三项宿主修复。三项补丁都不改变计费规则或数据库结构,必须按下列顺序应用: +这里保存 billing 最初为 CLIProxyAPI `v7.2.133` 制作、已在 `v7.2.139` 重新验证的三项宿主修复。三项补丁都不改变计费规则或数据库结构,必须按下列顺序应用: 1. [`cli-proxy-api-usage-context.patch`](cli-proxy-api-usage-context.patch) 2. [`cli-proxy-api-usage-identity.patch`](cli-proxy-api-usage-identity.patch) @@ -8,8 +8,8 @@ 适用基线: -- CLIProxyAPI:`v7.2.137` -- 提交:`85d2faddd17e6f4f8675a84ee28b131f702e8eaa` +- CLIProxyAPI:`v7.2.139` +- 提交:`0a14eb70ce19fac1d114bcdb4a476d61adc819e2` - Native ABI:`1` - 第二项补丁把 RPC schema 从 `3` 提升到 `4` @@ -84,8 +84,8 @@ git -C .externals/CLIProxyAPI apply ../../patch/cli-proxy-api-request-lifecycle- cd .externals/CLIProxyAPI gofmt -w internal/pluginhost sdk/api/handlers sdk/cliproxy/usage sdk/pluginabi sdk/pluginapi go test -race ./internal/pluginhost ./sdk/api/handlers ./sdk/cliproxy/usage -count=1 -version=v7.2.137-dev -commit=85d2fadd +version=v7.2.139-dev +commit=0a14eb70 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" \ @@ -129,7 +129,7 @@ billing 必须使用 RPC schema v4 重新构建;旧 billing 动态库会向下 - billing 全部测试、billing race 测试及 CLIProxyAPI 相关包 race 测试通过; - schema v3 对照插件仍能正常注册,新增字段不会发送给旧 schema。 -升级到 CLIProxyAPI `v7.2.137` / `85d2fadd` 后,三项补丁可从干净基线按顺序重放,补丁涉及的三个包及其 race 测试通过。宿主全仓测试中的 3 个 Claude 指纹失败和 2 个 `reviewedInPlaceByteWrites` 清单过期失败均已在未应用补丁的纯上游 `85d2fadd` 上原样复现,属于上游例外,详见 [`../docs/operations.md`](../docs/operations.md)。 +升级到 CLIProxyAPI `v7.2.139` / `0a14eb70` 后,三项补丁可从干净基线按顺序重放,补丁涉及的三个包及其 race 测试通过。`usage-identity` 已适配上游插件 executor 的独立 `execCtx`,保留嵌套执行防重复统计逻辑。宿主全仓测试中的 3 个 Claude 指纹失败和 2 个 `reviewedInPlaceByteWrites` 清单过期失败均已在未应用补丁的纯上游 `0a14eb70` 上原样复现,属于上游例外,详见 [`../docs/operations.md`](../docs/operations.md)。 ## 性能影响 diff --git a/patch/cli-proxy-api-usage-identity.patch b/patch/cli-proxy-api-usage-identity.patch index fb43897..b08d675 100644 --- a/patch/cli-proxy-api-usage-identity.patch +++ b/patch/cli-proxy-api-usage-identity.patch @@ -131,13 +131,13 @@ index 994bd33a..3cc7743e 100644 opts := coreexecutor.Options{ Stream: false, Alt: alt, -@@ -177,6 +179,7 @@ func (h *BaseAPIHandler) executeWithPluginExecutor(ctx context.Context, entryPro - } - req, opts := h.pluginExecutorRequest(ctx, entryProtocol, responseProtocol, modelName, originalRequestedModel, rawJSON, alt, false, execOptions) - lifecycle := h.newRequestLifecycleTracker(ctx, entryProtocol, modelName, originalRequestedModel, false, opts.Metadata, execOptions.SkipInterceptorPluginID) -+ ctx = lifecycle.executionContext() +@@ -179,6 +181,7 @@ func (h *BaseAPIHandler) executeWithPluginExecutor(ctx context.Context, entryPro + execCtx, nestedTracker := withNestedExecutionTracker(ctx) + req, opts := h.pluginExecutorRequest(execCtx, entryProtocol, responseProtocol, modelName, originalRequestedModel, rawJSON, alt, false, execOptions) + lifecycle := h.newRequestLifecycleTracker(execCtx, entryProtocol, modelName, originalRequestedModel, false, opts.Metadata, execOptions.SkipInterceptorPluginID) ++ execCtx = lifecycle.executionContext() var interceptErr *interfaces.ErrorMessage - req, opts, interceptErr = h.applyRequestInterceptorsBeforeAuth(ctx, entryProtocol, originalRequestedModel, lifecycle.requestID(), req, opts, execOptions.SkipInterceptorPluginID) + req, opts, interceptErr = h.applyRequestInterceptorsBeforeAuth(execCtx, entryProtocol, originalRequestedModel, lifecycle.requestID(), req, opts, execOptions.SkipInterceptorPluginID) if interceptErr != nil { @@ -211,6 +214,7 @@ func (h *BaseAPIHandler) countWithPluginExecutor(ctx context.Context, handlerTyp } @@ -209,13 +209,13 @@ diff --git a/sdk/api/handlers/handlers_stream.go b/sdk/api/handlers/handlers_str index 9cceec54..dcdc08df 100644 --- a/sdk/api/handlers/handlers_stream.go +++ b/sdk/api/handlers/handlers_stream.go -@@ -41,6 +41,7 @@ func (h *BaseAPIHandler) streamWithPluginExecutor(ctx context.Context, entryProt - } - req, opts := h.pluginExecutorRequest(ctx, entryProtocol, responseProtocol, modelName, originalRequestedModel, rawJSON, alt, true, execOptions) - lifecycle := h.newRequestLifecycleTracker(ctx, entryProtocol, modelName, originalRequestedModel, true, opts.Metadata, execOptions.SkipInterceptorPluginID) -+ ctx = lifecycle.executionContext() +@@ -43,6 +43,7 @@ func (h *BaseAPIHandler) streamWithPluginExecutor(ctx context.Context, entryProt + execCtx, nestedTracker := withNestedExecutionTracker(ctx) + req, opts := h.pluginExecutorRequest(execCtx, entryProtocol, responseProtocol, modelName, originalRequestedModel, rawJSON, alt, true, execOptions) + lifecycle := h.newRequestLifecycleTracker(execCtx, entryProtocol, modelName, originalRequestedModel, true, opts.Metadata, execOptions.SkipInterceptorPluginID) ++ execCtx = lifecycle.executionContext() var interceptErr *interfaces.ErrorMessage - req, opts, interceptErr = h.applyRequestInterceptorsBeforeAuth(ctx, entryProtocol, originalRequestedModel, lifecycle.requestID(), req, opts, execOptions.SkipInterceptorPluginID) + req, opts, interceptErr = h.applyRequestInterceptorsBeforeAuth(execCtx, entryProtocol, originalRequestedModel, lifecycle.requestID(), req, opts, execOptions.SkipInterceptorPluginID) if interceptErr != nil { @@ -305,6 +306,7 @@ func (h *BaseAPIHandler) executeStreamWithAuthManagerFormats(ctx context.Context }