diff --git a/backend/internal/pkg/antigravity/request_transformer.go b/backend/internal/pkg/antigravity/request_transformer.go index f9499c1cca..f9b917fb17 100644 --- a/backend/internal/pkg/antigravity/request_transformer.go +++ b/backend/internal/pkg/antigravity/request_transformer.go @@ -298,11 +298,9 @@ func filterOpenCodePrompt(text string) string { // from Antigravity system text. This is prompt metadata, not an HTTP header; it // can trigger RESOURCE_EXHAUSTED on the Google upstream. Keep this scoped to the // Antigravity transformer: native Anthropic OAuth may require the attribution. -// claudeIdentityOpeners are the Claude Agent SDK identity sentences that some -// Anthropic clients put at the start of a system block. Stripping the -// x-anthropic-billing-header line alone is not enough: a request whose system -// text still opens with this sentence is still rejected by the Google upstream -// with 429 RESOURCE_EXHAUSTED (see docs/ANTIGRAVITY_ATTRIBUTION_429.md). +// claudeIdentityOpeners 是部分 Anthropic 客户端放在系统块开头的 Claude Agent SDK 身份语句。 +// 仅移除 x-anthropic-billing-header 行还不够:如果系统文本仍以这些语句开头, +// Google 上游仍会返回 429 RESOURCE_EXHAUSTED。 // // The patterns are anchored at the start of a system block on purpose, so user // instructions that merely mention Claude or Anthropic are left untouched. diff --git a/docs/ANTIGRAVITY_ATTRIBUTION_429.md b/docs/ANTIGRAVITY_ATTRIBUTION_429.md deleted file mode 100644 index e4b3cc1822..0000000000 --- a/docs/ANTIGRAVITY_ATTRIBUTION_429.md +++ /dev/null @@ -1,106 +0,0 @@ -# Antigravity:Claude Desktop attribution 元数据触发 429 的排查记录 - -本文记录一次实际问题的定位和修复,适用于 Claude Desktop / Claude Code 经 Anthropic Messages 协议转到 Antigravity 的场景。它不是所有 `429 RESOURCE_EXHAUSTED` 的通用解释:额度耗尽、请求频率、上游容量等仍应独立排查。 - -## 现象与环境 - -- 实测部署为 Sub2API 0.2.0,Claude Desktop 2.110.0,内嵌 Claude Code 2.1.271,CC Switch 3.20.3。 -- 请求链路:Claude Desktop → CC Switch 本地代理 → Sub2API Antigravity → Google 上游;映射模型为 `gemini-3.8-flash-high`。 -- 新对话中的简单问候也返回 `429 RESOURCE_EXHAUSTED`,上游信息为 `Resource has been exhausted (e.g. check quota).`。 -- 随后账号进入模型冷却,单账号组还可能出现 `503 No available accounts`。 -- 独立构造的极简请求成功,但真实客户端请求失败。客户端即使只发送一句问候,也会附带 system 提示词和工具定义。 - -## 定位方法与对照结果 - -保留一次失败请求,在相同账号、模型和上游端点下逐项删减内容。不要仅用手写的短请求判断完整客户端链路已经恢复,也不要在公开 issue / PR 上传原始请求或访问令牌。 - -| 对照项 | 本次观察 | -| --- | --- | -| 原始客户端请求(约 187 KB、106 个工具) | 429 | -| 移除工具定义,保留 system 内容 | 429 | -| 移除 messages 中的 system 角色消息 | 429 | -| 直接请求 Google,保留原始顶层 system 内容 | 429 | -| 同一 Google 请求改用简单 system 内容 | 200 | -| 分别测试 system 文本块 | attribution 元数据块返回 429,其余指令块返回 200 | -| 原始请求仅移除 attribution 元数据块,保留模型、工具及其他内容 | 200,收到完整回复 | - -触发问题的文本形如: - -```text -x-anthropic-billing-header: cc_version=2.1.271.4bf; cc_entrypoint=claude-desktop-3p; -``` - -这里的 “header” 是请求 JSON 的 `system` 文本中的一行,**不是 HTTP 请求头**。因此,不需要在 Claude Desktop 的 “Custom inference headers” 里增删同名字段;也不应通过修改正常工作的 Bearer 认证来处理这个问题。 - -这些对照支持“该元数据文本在本次 Google 请求中触发拒绝”的判断,但不能据此确定 Google 内部策略,也不能推断所有账号或模型都具有相同行为。 - -## 本次修复 - -在 Antigravity 的 Claude → Gemini 请求转换中,移除顶层 `system` 字符串或文本块**开头**的 `x-anthropic-billing-header:` 行: - -- 支持字符串和文本块数组,兼容 LF / CRLF / CR 换行及前导空白。 -- 如果同一文本块后面还有指令,原样保留后续内容;仅元数据的空块不再发送。 -- 不匹配缺少冒号的普通文本、其他字段名,以及正常指令中间引用的相同文本。 -- 不修改用户消息、工具定义、模型映射、认证和账号额度状态。 -- 处理限于 Antigravity 转换器,不修改原生 Anthropic 转发路径。 - -上线前的临时修复采用相同范围的反向代理 JSON 过滤,并通过原始完整请求和真实 Claude Desktop 会话验证成功。本文 PR 将处理放入转换器,避免用户必须自行维护代理脚本。原部署曾尝试降低账号并发,但未解决问题;定位后已恢复原配置。 - -如需在旧版本临时处理,应只对目标 Antigravity Messages 路径修改 JSON 的顶层 system 文本。不要用全局字符串替换,否则可能误改消息、工具参数或代码示例。代理实现还需保持空数组和空对象类型、更新请求体长度,并覆盖实际使用的 token-count 路径。面板重新生成代理配置时也可能覆盖自定义过滤规则。 - -## 不要全局禁用 attribution - -Claude Code 提供 [`CLAUDE_CODE_ATTRIBUTION_HEADER`](https://code.claude.com/docs/en/env-vars) 环境变量,但桌面端是否继承该配置需要实测。本次仅修改全局 Claude 设置并未消除 Desktop 请求中的元数据。 - -更重要的是,原生 Anthropic OAuth 线路有相反的报告:禁用 attribution 会造成 429,见 [issue #6344](https://github.com/Wei-Shaw/sub2api/issues/6344)。因此,不建议为这个 Antigravity 问题统一设置 `CLAUDE_CODE_ATTRIBUTION_HEADER=0` 或在所有上游请求中删除该文本。 - -## 验证与仍需排查的情况 - -回归测试覆盖两种 system 格式、换行与空白、保留后续指令、保留普通文本和用户 / 工具内容,以及不修改原请求。已有的无冒号 billing-header 文本保留测试继续适用。 - -修复后应使用真实客户端新建会话验证完整响应,并确认已有冷却已到期。如果仍返回 429,继续检查原始上游错误、实际额度、并发和模型映射;不要用无限重试或反复清空冷却替代定位。 - -## 补充:仅移除 attribution 行仍不足(2026-09-20) - -在另一套部署上(**Sub2API 0.2.7,已包含上一节的 `stripClaudeAttribution` 修复**, -Claude Code 2.1.278 / claude-vscode 入口,映射模型 `gemini-3.8-flash-high`), -同一类 429 再次出现在 Claude Code 的**会话标题生成**请求上。 -这类请求很小:约 4 KB、system 3201 字符、0 个工具、1 条消息。 - -也就是说,下面的“原始请求回放”本身就是在**已经移除 attribution 行**的代码上跑的。 - -对照实验在一个只绑定单个账号的隔离分组里进行,每次请求之前都等模型冷却到期, -避免上一次失败造成的冷却把后续结果污染成 503: - -| 对照项 | 结果 | -| --- | --- | -| 原始请求回放 | 429(8/8) | -| 仅把 system 换成普通提示词,其余不变 | 200(8/8) | -| 回放前先由客户端侧移除 attribution 块(与网关行为叠加,确认无额外影响) | **429(3/3)** | -| 在上一行基础上再中性化身份开场白 | **200(3/3)** | -| 仅把 system 里的 `Claude` 替换为中性词 | 200(2/2) | -| 仅把 system 里的 `Anthropic` 移除 | 200(2/2) | -| 去掉 `output_config` / 改小 `max_tokens` / 改非流式 | 429(各 1/1,无影响) | - -该请求的 system 是三个文本块: - -1. 仅 attribution 元数据(本文上一节的修复会整块丢弃); -2. `You are a Claude agent, built on Anthropic's Claude Agent SDK.`; -3. 其余任务说明,不含厂商名。 - -也就是说,触发拒绝的不只是 attribution 元数据,**第 2 块的身份声明同样会触发**。 -Claude Code 的主对话提示词以 `You are an interactive CLI tool` 开头,已被 -`filterOpenCodePrompt` 处理,所以只有 Agent SDK 这类提示词漏网。 - -### 本次修复 - -在 attribution 处理之后,追加一次**开头锚定**的身份句中性化: - -- 命中 `You are a Claude agent, built on Anthropic's Claude Agent SDK.` 与 - `You are Claude Code, Anthropic's official CLI for Claude.` 两种开场白,替换为 - `You are an AI agent.`,块内其余内容原样保留。 -- 只在 system 文本块**开头**匹配:正文中间提到 Claude/Anthropic 的用户指令不受影响, - `claude-sonnet-4-6` 这类模型名也不会被改写。 -- 不修改用户消息、工具定义、模型映射与认证;仅作用于 Antigravity 转换器。 - -同样地,这些对照只支持“这段文本在本次请求中触发拒绝”的判断,不能推断 Google 的内部策略。 diff --git a/docs/log-retention.md b/docs/log-retention.md deleted file mode 100644 index 64c90f68e8..0000000000 --- a/docs/log-retention.md +++ /dev/null @@ -1,21 +0,0 @@ -# 滚动日志保留设置 - -管理员在 **运维监控 → 系统日志 → 运行时日志配置** 中设置保留期,然后点击「保存并应用」。 - -| 日志 | 可选范围 | 执行时间 | -| --- | --- | --- | -| 运维系统日志 | 1–3650 天 | 运维设置中的数据清理计划,须开启「启用数据清理」 | -| 请求日志(请求使用明细) | 1–3650 天,或永久保留 | 每 6 小时清理一次,保存后在下一次清理生效 | - -下拉框提供 1、3、7、14、30、60、90、180、365 天,也可以选择「自定义天数」。按天清理只删除早于截止时间的记录;截止时间上的记录保留。请求日志按月分区时,也会清理截止日期所在分区中的过期记录。 - -## 配置兼容 - -- 设置保存在 `ops_runtime_log_config`:`retention_days` 控制运维系统日志,`request_retention_days` 控制请求日志,后者为 `0` 时表示永久保留。 -- 没有请求日志设置时,沿用 `dashboard_aggregation.retention.usage_logs_days`(默认 90 天);原来禁用仪表盘聚合的部署继续保留请求日志,不自动开启删除。 -- 显式保存请求日志保留天数后,即使仪表盘聚合关闭,滚动清理仍会运行。 -- 旧客户端没有传入 `request_retention_days` 时,保留已有值。「重置默认值」恢复部署配置。 -- 计费去重记录的保留期至少与请求日志一样长;请求日志永久保留时,也停止清理计费去重记录。 -- 读取请求日志保留设置失败或设置无效时,跳过清理,避免回退到更短的保留期。 - -运维错误日志和指标继续使用运维设置中的各自保留策略。本页的运维保留期针对数据库中的系统日志;磁盘日志文件仍使用部署配置中的轮转策略。 diff --git a/docs/screenshots/log-retention.png b/docs/screenshots/log-retention.png deleted file mode 100644 index fe45f97f2a..0000000000 Binary files a/docs/screenshots/log-retention.png and /dev/null differ