Commit Graph
5636 Commits
Author SHA1 Message Date
Wesley Liddick abdc82725f Merge pull request #8076 from feeeei/fix/gemini-vertex-sa-and-error-policy
fix(gemini): Vertex SA 已删除时停用账号并换号,401 临时不可调度规则首次命中不再永久停用
2026-10-15 15:27:01 +08:00
Wesley Liddick 3b83e045ed Merge pull request #8060 from feeeei/fix/gemini-vertex-shared-capacity-429
fix(gemini): Vertex 共享容量不足的 429 不冷却账号,改为同号退避重试
2026-10-15 15:26:51 +08:00
Wesley Liddick fdc7f1fa01 Merge pull request #8087 from coder-zhw/fix/zhipu-credit-limit-window-classification
fix(zhipu): 修正 GLM Coding Plan 5h/weekly 用量窗口标反 / fix swapped GLM coding plan usage windows
2026-10-15 15:26:38 +08:00
shaw d19265ddb2 fix(gateway): 拒绝含 OpenAI 网关 OAuth 的 composite 歧义路由,防止凭据误入 Anthropic 管线
composite 分组中 openai OAuth 账号与 deepseek API Key 账号同时显式映射同一
gpt 模型时,模型归属判为歧义、路由层不解析平台,请求落到默认 Anthropic
GatewayHandler;handler 再按模型名前缀猜回 openai 并选中 OpenAI OAuth 账号,
ChatGPT token 被发往 api.anthropic.com,上游 401 "Invalid bearer token"
经 failover 逐号打成临时不可调度,单请求即可扫空号池。

- 归属记录声明方是否含 OpenAI 网关族 OAuth / setup-token;当模型名兜底也
  落在 OpenAI 网关族时判为配置错误,路由中间件与 WS 入口直接 400 拒绝并
  提示配置显式路由。纯 API Key 歧义及 Anthropic/Antigravity/Gemini OAuth
  歧义保持原行为。
- 模型归属改按配置计算(ListModelAvailabilityCandidates),不再随限流 /
  临时不可调度在「唯一归属」与「歧义」之间翻转。
- Anthropic 请求构建前校验凭据:非 Anthropic 网关族的 OAuth 凭据不出站,
  返回仅换号、不处罚账号的 failover;count_tokens 返回 404 不支持。
  API Key 不受限(上游可能兼容多种协议格式)。
2026-10-15 14:57:03 +08:00
coder-zhw 1774b79dcb fix(zhipu): 修正 GLM Coding Plan 5h/weekly 用量窗口标反
parseZhipuTokenTiers 只在 limitType == "TOKENS_LIMIT" 分支里按 unit 显式分类,
而智谱当前把 5h / weekly 两条窗口都标成 CREDIT_LIMIT(level=lite)。这些条目被放进
creditFallback,entry 结构体又不带 unit,信息在此永久丢失,降级路径退化为
「按 nextResetTime 升序填空位」。当周窗口先于 5h 重置时(每个周期临尾的几小时),
周窗口会被先填进 5h 槽,两档必然标反 —— 函数文档注释第 1 条已警告过该场景,
只是防线建在了错误的 type 分支上。

因为只在「CREDIT_LIMIT 且周窗口更早重置」这一种组合下出错,症状是间歇性的,
容易被误判为随机抽风。该函数自 v0.2.0 到 v0.2.16 逐字节未变,不属于版本回归。

改动:
- entry 增加 unit 字段;classify 改为直接接收 unit,不再依赖 item。
- 仅在降级路径(无任何 TOKENS_LIMIT 条目)上,对 creditFallback 中 unit 可识别的
  条目先按 unit 分类;unit 仍不可识别的才落入原有的 reset 时间启发式。
- TOKENS_LIMIT 优先占槽的既有语义保持不变:两种 type 同时返回时 CREDIT_LIMIT
  依旧不参与槽位竞争。
- 更新 cnZhipuWindow 与 parseZhipuTokenTiers 的文档注释。
- cn_providers_test.go 补充 3 个回归用例。

验证:
- 反向验证:仅回退源文件保留测试,CreditLimitUnitClassification 失败于
  14 vs 90(两档被对调);另两个钉住原语义的用例修复前后均通过。
- go build ./... 通过;gofmt -l 无输出;golangci-lint v2.14.0 0 issues。
- go test -tags=unit ./internal/service/ 全量通过。

影响范围:backend/internal/service 两个文件(service + unit test)。
2026-10-15 14:56:00 +08:00
feeeei 14cd587175 fix(gemini): 每个上游错误响应只检查一次错误策略
- 三条 Gemini 转发路径在重试循环内和循环外各对最终上游错误响应检查一次错误策略。
  配了账号级 401 临时不可调度规则的 API Key / Vertex 账号首次收到 401 时,第一次
  检查写入 401 暂停记录,第二次检查读回该记录判定为重复 401,同一请求内即升级为
  error 永久停用
- 循环内的检查结果带到循环外复用;循环内未检查的最终响应(Claude 兼容层的签名 400
  分支、原生路径的 cachedContent 透传分支)仍在循环外检查
2026-10-14 12:00:44 +08:00
feeeei 20c4bf5ae5 fix(gemini): Vertex SA 已不存在时账号置为 error 并换号
- 换取 SA access token 时 token 端点返回 400
  {"error":"invalid_grant","error_description":"Invalid grant: account not found"}
  表示服务账号已被删除,凭据再也换不到 token;此前三条 Gemini 转发路径把它当作
  本地构造请求失败直接回 502,不换号也不改账号状态,账号持续被调度
- 识别该错误后账号置为 error 并停止调度(Service account token rejected (400): …),
  记录凭据获取阶段(stage=account_auth)的 Ops 事件,请求交给 handler 换号
- 只匹配 400 + invalid_grant + account not found:invalid_grant 还涵盖时钟偏差、
  签名无效等情况,其他换 token 失败保持原行为
- token 端点地址改为包级变量,测试中替换为本地服务
2026-10-14 11:58:37 +08:00
feeeei 89ad4c2caa fix(gemini): Vertex 共享容量不足的 429 不冷却账号,改为同号退避重试
- Vertex 按量付费返回的 "Resource exhausted ... try again later"
  (RESOURCE_EXHAUSTED、无错误明细)表示共享资源池当时没有容量,与账号额度
  无关;此前一律冷却账号 1 分钟,冷却期间账号被调度快照剔除,绑定显式缓存
  的请求因无法换号直接 503
- 这类 429 只记日志、账号保持可调度,由请求内同号 1/2/4/8s 退避重试消化,
  重试用尽后未绑定缓存的请求照常换号
- 带 retryDelay、文案重试时长、配额/预留吞吐字样或其他形态的 429 仍按账号
  自身限速冷却;非 Vertex 账号行为不变
2026-10-13 23:51:43 +08:00
github-actions[bot] 4d9ac3e482 chore: sync VERSION to 0.2.16 [skip ci] 2026-10-13 07:20:40 +00:00
Wesley Liddick 01842576b3 Merge pull request #7810 from wucm667/fix/issue-6247-responses-chat-fallback
fix(gateway): retry rejected structured input through chat endpoint
2026-10-13 15:01:20 +08:00
Wesley Liddick 49b2122dc6 Merge pull request #7991 from wucm667/fix/issue-7988-international-quota
fix(quota): recognize international coding endpoints
2026-10-13 15:00:31 +08:00
Wesley Liddick 8d7d3185e9 Merge pull request #8038 from wucm667/fix/issue-8035-gemini-tool-result-images
Preserve images from tool results
2026-10-13 15:00:04 +08:00
Wesley Liddick bba85923b9 Merge pull request #8046 from wucm667/fix/issue-8040-antigravity-image-rate-limit
Isolate Antigravity image model rate limits
2026-10-13 14:59:39 +08:00
shaw 9d5e63a598 合并 main 并解决 PR #7828 的测试文件冲突
完整保留临时不可调度规则作用范围测试与 Gemini 显式缓存测试;保留双方生产代码改动。
2026-10-13 14:59:02 +08:00
Wesley Liddick 53c21fed25 Merge pull request #8006 from feeeei/feat/gemini-explicit-cache
feat(gemini): 支持显式上下文缓存,并完善 Vertex 与第三方 API Key 账号
2026-10-13 14:51:11 +08:00
Wesley Liddick 7c5afa4c36 Merge pull request #7957 from xcrong/feat/haiku-5-5-support-7919
feat(gateway): adapt Claude Haiku 5.5
2026-10-13 14:50:40 +08:00
shaw c4bdc48475 fix(haiku): 修正采样边界、默认模型配置与 lint 2026-10-13 14:38:16 +08:00
xcrong 26f70c6a87 fix(gateway): wire Claude Haiku 5.5 into Responses bridge
ResponsesToAnthropicRequest only recognized opus/sonnet 5.5, so Haiku
requests fell into the generic enabled+budget_tokens path (upstream 400)
and lost signed thinking history (preserveThinking=false). Mirror the
Messages-side rules: adaptive+medium default, none->disabled+low,
temp/top_p/combo guards, forced tool_choice allowed.

Also preserve Haiku55 thinking signatures in AnthropicToResponsesResponse
and streaming state, and name the model correctly in the between_tools
rejection.
2026-10-13 10:45:13 +08:00
wucm667 cfbbfd6b3b fix(antigravity): isolate image model rate limits 2026-10-13 09:24:38 +08:00
feeeei 43a3c197cb fix(gemini): 显式缓存恢复流程区分账号已删除与暂不支持缓存,上游必已过期后作废意图
后台回滚在持有账号返回 nil 时把修改意图当作已回滚清除:账号临时关闭显式缓存能力后
意图丢失,重新开启也无法补偿。

- boundAccount 区分两种情形:账号已删除返回 nil,账号存在但不支持显式缓存返回
  errGeminiCachedContentAccountUnsupported;BoundAccount 对外行为不变
- 账号暂不支持缓存时不改动上游、保留意图,租约过期后重试(期间同一缓存的修改返回 409);
  账号已删除时没有凭据可回滚上游,软删本地记录
- 修改前到期时间加上单次最长有效期与 1 小时容忍都已过去时上游缓存必已自行过期:
  账号不支持缓存或上游回滚持续失败的意图不再重试,直接作废本地记录
- 测试夹具 GetForOwner 过滤已软删记录
2026-10-13 00:54:27 +08:00
feeeei 2023c290e1 fix(account): 计数、Bedrock 与重试耗尽入口把上游模型交给错误处理
OpenAI 与 Anthropic 的 count_tokens / input_tokens 入口、Bedrock 故障转移入口
以及 OAuth 403 重试耗尽入口调 HandleUpstreamError 时没有传入实际发往上游的模型,
显式 scope=model 的 401 规则在这些入口看到空模型,仍落到 handleAuthError 整号置 error。

- 四处计数入口传入映射后的上游模型;Anthropic 透传计数函数新增 upstreamModel 参数
- handleRetryExhaustedSideEffects / handleRetryExhaustedError 增加模型变参,
  Forward、Anthropic 透传与 Bedrock 三处调用方传入实际模型
- Bedrock 入口传调度器的模型键(account.GetMappedModel),不是发往上游的
  Bedrock 模型 ID,模型级冷却才会被调度器读取
- 这些入口的 404 模型未找到与缺省 scope 的非 401 规则随之按主转发路径语义处理
  (模型已知走模型级)
2026-10-13 00:53:39 +08:00
Wesley Liddick ab80abc6d1 Merge pull request #7960 from feeeei/feat/group-i18n
feat(groups): 分组名称与描述支持多语言
2026-10-12 22:16:51 +08:00
wucm667 492c630599 fix(gemini): satisfy test lint 2026-10-12 19:13:17 +08:00
wucm667 ba2a717332 fix(gemini): preserve images from tool results 2026-10-12 18:52:00 +08:00
feeeei 8b74741efe fix(groups): 广场 Vary 保留 Origin,分组译文语言代码统一大小写
- 模型广场以追加方式写入 Vary: Accept-Language,保留 CORS 中间件为具体来源
  写入的 Vary: Origin
- 管理端写入分组译文时语言代码统一为 BCP 47 惯用大小写(en、zh-TW),
  统一后重复的语言代码(如 en 与 EN)返回 400 INVALID_GROUP_I18N
- 用户侧按语言取译文时规范写法的键优先,仅大小写不同的多个键按字节序取最小者,
  同一请求语言的结果固定
2026-10-12 18:09:03 +08:00
feeeei fc82e83102 fix(account): 显式模型级 401 规则在网关故障转移入口生效
OpenAI 转发 fastpath、HandleUpstreamError 及两处池模式分支对 401 一律跳过
临时不可调度规则,显式 scope=model 的 401 规则在 API Key 账号上仍落到
handleAuthError 整号置 error。

- 新增 tempUnschedRulesApply:401 仅在首条命中规则按模型级生效时交给规则,
  其余保持认证错误处理
- 凭据级 401(OAuth 账号与 Spark 影子、OpenAI token_invalidated/token_revoked、
  {"detail":"Unauthorized"})不受规则作用范围影响,各入口沿用原有处理
- 模型级命中不参与重复 401 升级;fastpath 不再因模型级命中封整号
2026-10-12 17:39:26 +08:00
Wesley Liddick 9591136d45 Merge pull request #8033 from Larry-Labs/fix/gpt61-sol-500k-context
fix(codex): raise GPT-6.1 Sol generated context default to 500k
2026-10-12 17:18:51 +08:00
feeeei 26b31a83e4 fix(gemini): 显式缓存修改串行化、失败回滚,确定金额费用按 Key / 订阅预留
同一缓存的并发 PATCH 可能以与上游提交不同的顺序写回本地到期时间;
确定金额的存储费只预留用户余额,并发续期可越过 API Key 总额度与订阅额度;
上游已修改而本地写回失败时没有可恢复的状态。

- 新增迁移 245:缓存记录增加修改意图(mutation_token / mutation_lease_until)。
  PATCH 在调用上游前登记意图并取得 2 分钟租约,条件为没有进行中的修改且到期时间
  未变;上游修改、本地写回与计费均由持有者完成,并发的修改返回 409 ABORTED
- 上游结果未知、本地写回失败或进程退出时修改意图保留且不计费;租约过期后由下一次
  修改或后台每分钟的恢复流程把上游有效期回滚到修改前的到期时间(已到期则删除上游
  缓存与本地记录)。上游明确拒绝或请求未发出时直接清除意图
- 修改 / 删除上游缓存的单次调用超时改为 30 秒;请求发出前的失败包装为
  ErrGeminiCachedContentRequestNotSent
- CheckChargeAffordable 与 ReserveInflightCharge 合并为 ReserveFixedCharge:在途预留
  新增订阅、API Key 两个维度(Redis billing:inflight_scope:*),先登记本笔预留再读取
  库中权威用量(Key quota_used 与限速窗口、订阅日 / 周 / 月用量)叠加同维度在途合计
  校验;预留随计费任务交接,落库后释放
- GetRateLimitData 一并读取 quota_used
2026-10-12 17:14:56 +08:00
shaw 43768680d3 fix(billing): 取消 GPT-6.1 Sol 订阅长上下文附加费 2026-10-12 16:47:22 +08:00
xugao 0718581265 fix(codex): raise GPT-6.1 Sol generated context default to 500k 2026-10-12 15:16:44 +08:00
Wesley Liddick 5dbb8f7085 Merge pull request #7649 from Yukinoshita-Yukino/fix/codex-image-bridge-openai-only
fix(openai): only inject the Codex image generation bridge for OpenAI accounts
2026-10-12 14:38:00 +08:00
Wesley Liddick 6d509c632d Merge pull request #7711 from wucm667/fix/issue-7709-risk-control-groups
fix(risk-control): remove deleted groups from moderation scope
2026-10-12 14:37:44 +08:00
feeeei daebb7a80c fix(gemini): 模型列表与模型详情接口支持 Agent Platform (Vertex) 账号
Gemini 分组对外提供 AI Studio 兼容协议,分组内账号不一定是 AI Studio。
分组只剩 Vertex 服务账号时,GET /v1beta/models 与 /v1beta/models/{model}
选中服务账号后报 502 unsupported account type: service_account。

- SelectAccountForAIStudioEndpoints 改名 SelectAccountForModelsEndpoints,
  Vertex 账号排在所有 AI Studio 兼容账号之后参与选号
- ForwardAIStudioGET 拆为 ForwardListModels / ForwardGetModel,按账号类型分流:
  AI Studio 兼容账号原样转发;Vertex 服务账号读取 Google 发布方模型列表并
  转换为 AI Studio 格式,模型详情在该模型所用区域的列表中查找;Vertex API Key
  账号返回内置列表
- Vertex 发布方模型分页读取抽成 listVertexGeminiPublisherModels,与后台
  同步上游模型共用
- 模型接口响应体上限改用 gateway.models_list_read_max_bytes,超出时报错
2026-10-11 22:03:36 +08:00
feeeei 4426593e9d fix(gemini): 3.6 Flash 兜底价改为官方优惠价
- 内置兜底价与本地价格表快照的 gemini-3.6-flash 改为 $0.75 输入 / $3.75 输出 /
  $0.075 缓存读取(Priority 档 $1.35 / $6.75 / $0.135),有效期至 2026-12-31,
  2027-01-01 起恢复 $1.50 / $7.50 / $0.15,与 3.7 / 3.8 Flash 及远程价格目录一致
2026-10-11 11:22:48 +08:00
feeeei f0ee427f0a feat(gemini): 显式缓存存储价内置官方价并按 Pro / Flash 系列兜底
- 新增 Gemini 显式缓存存储单价表(Standard 档,USD / token / 小时):
  Pro 全系 $4.50、Flash 与 Flash-Lite 全系 $1.00;3.6 / 3.7 / 3.8 Flash
  为优惠价 $0.50(有效期至 2026-12-31,2027-01-01 起恢复 $1.00),
  AI Studio 与 Vertex 统一按优惠价计
- 型号表未命中的 Gemini 模型按系列兜底:Pro 取 $4.50,Flash / Flash-Lite
  取标准价 $1.00;Flash-Lite 变体不落到同版本 Flash 的优惠价
- 取值优先级:价格表(override_file 等)配置值 > 内置型号价 > 内置系列价;
  两者都没有的模型仍拒绝创建缓存
2026-10-11 11:22:43 +08:00
feeeei 05d7946af8 fix(gemini): 显式缓存错误透传收窄到上游网关账号,延长沿用创建时计费口径
- 绑定缓存的请求与缓存管理接口收到 429 / 5xx 时,只有上游网关账号的响应原样回写
  (UpstreamFailoverError.BoundUpstreamPassthrough / GeminiCachedContentUpstreamError.UpstreamGateway),
  官方账号仍走错误透传规则与通用映射,不向客户端暴露配额明细
- 记录新增 channel_usage(迁移 244)保存创建时的渠道计费口径,PATCH 延长按同一口径预检、报价与记账
- 创建 / 延长费用行的 request_id 改为固定前缀 gcache:{create|patch}:{id},不被客户端或网关请求 id 覆盖,
  按缓存 ID 即可检索一个缓存的全部费用行
- 调度快照凭据投影补齐 base_url / auth_mode / 上游显式缓存声明,显式缓存候选过滤一次算全,
  不再逐个选号后剔除
2026-10-11 01:37:04 +08:00
feeeei 6f9b02f12c feat(gemini): Vertex 服务账号支持同步上游模型列表
- Gemini 平台 Service Account 账号改用 v1beta1 publishers/google/models
  分页拉取模型(pageSize 300,最多 20 页),按账号默认区域选端点;
  只保留 publishers/google/models/gemini-* 条目,排除区域端点里的
  Gemma、Veo、AutoML 等模型花园条目
- 凭据缺失或 location 非法返回配置错误(400),且不发起 token 交换;
  API Key 认证的 Vertex 账号返回不支持
- 翻页途中的 404/405 不再触发配置模型回退
- 模型列表的请求、读体与状态码检查抽成 readUpstreamModelsResponse
  供各平台共用
2026-10-10 23:37:48 +08:00
feeeei 1c68f9996d feat(gemini): 适配 AI Studio AQ. 格式 Key
- AI Studio 新建 Key 为 AQ.Ab 前缀的 auth key:logredact.RedactText 与
  渠道监控 sanitizeErrorMessage 增加 AQ.Ab 规则,长度按 40 位以上放宽以覆盖格式变体
- 创建 / 编辑账号的 Key 占位符改为 AQ.Ab...,提示文案说明新旧两种前缀
  与第三方上游 Key
2026-10-10 23:37:48 +08:00
feeeei 2588675ce7 fix(gemini): 第三方上游 API Key 与 Vertex 不再套用 AI Studio 等级和模拟配额
- 按 base_url 判定上游:非官方地址的 Gemini API Key 账号视为第三方上游
- 第三方上游与 Vertex 不返回本地模拟配额,隐藏等级与配额说明;
  账号列表中第三方上游按普通 Key 账号展示今日统计与额度进度条,
  Vertex 显示 vertex 徽章与今日统计
- 第三方上游的 429 只认显式重试时长,否则走全局 429 兜底冷却,
  不按每日配额冷却到 PST 午夜
- 创建账号:第三方 Base URL 不显示 AI Studio 等级选项,也不写入 tier_id;
  API 密钥卡片标题与说明不再限定 AI Studio,免费层说明只在官方 Base URL 下显示;
  OAuth 等级回退下拉只在 OAuth 表单显示
2026-10-10 23:37:48 +08:00
feeeei 81e6ec5346 feat(gemini): Vertex 账号支持 API Key 认证
- Gemini 平台的 Vertex 账号新增 API Key 认证(credentials.auth_mode=apikey),
  不填 Project ID 走全局端点,填写后走项目级端点,Key 通过 x-goog-api-key 传递;
  Anthropic 平台的 Vertex 账号仍只支持 Service Account JSON
- 转发(Claude 兼容 / 原生 / Chat Completions)与测试连接统一走
  buildVertexGeminiAccountURL / setVertexGeminiAuth
- API Key 账号不参与显式缓存(Vertex 缓存接口不接受 API Key)与批量生图
- 创建弹窗新增认证方式选择;编辑弹窗支持轮换 Key 与修改 Project ID,
  Key 留空表示保留
2026-10-10 23:37:48 +08:00
feeeei 3abd646582 fix(ops): Gemini 原生路由的网关本地错误按错误类型归类
Google 格式错误体没有 type 字段,ops 一律记为 api_error,客户端参数错误、
引用不存在的缓存等都被归为平台内部错误。

- googleError 写出时按状态码向 ops 登记错误类型:400/413 invalid_request_error、
  401 authentication_error、403 permission_error、404 not_found_error,
  429 与 5xx 不登记
- 计费、并发与风控拦截沿用 Claude / OpenAI 格式错误的类型与错误码,归类口径一致
- 存储价未配置、显式缓存未启用改用 googlePlatformError,仍按平台错误统计;
  错误透传规则改写的上游错误不登记本地类型
- 上游返回的缓存不存在标记为请求级失败:按客户端请求错误分类,
  上游原始错误保留为明细但不参与上游归因
2026-10-10 23:37:48 +08:00
feeeei d5a802f84a feat(gemini): 支持显式上下文缓存(AI Studio / Vertex / 自建网关上游)
新增 /v1beta/cachedContents 的创建、列表、查询、更新有效期与删除接口。
参与账号:官方地址的 AI Studio API Key 账号、Vertex service account 账号,
以及开启"上游支持显式缓存"的自定义地址 API Key 账号。

- 网关自发缓存 ID,绑定上游资源名、持有账号与创建它的 API Key
  (迁移 243 gemini_cached_contents);list/get 只读本地记录
- 引用缓存的 generateContent / streamGenerateContent / countTokens
  改写为上游资源名,只发往持有缓存的账号,不参与会话粘性、不换号;
  拒绝重复键与 snake_case 写法;在持有账号上重试耗尽后,
  上游 429 / 5xx 原样透传,401 / 403 映射为 502
- 计费:创建时一次性收取缓存 token 输入费与整个有效期的存储费;
  延长按库中实际推进的时长收费,纯存储费不算一次请求;缩短与删除不退费
- 存储单价随计费模型取价,来自定价覆盖文件字段
  cache_storage_cost_per_token_per_hour,未配置的模型拒绝创建;
  存储费同时计入账号统计成本,渠道按 token 重算成本时叠加且不重复计入
- 扣费前校验:创建在上游建成后按确定金额校验余额 / 订阅额度 /
  API Key 额度并登记不封顶的在途预留,不足时删除上游缓存、只收输入费;
  延长在调用上游前按增量时长校验
- 有效期上限 gateway.gemini_cached_content_max_ttl_seconds,默认 86400,
  有效期向上取整到秒;创建请求保留数字原文、兼容 snake_case 元数据字段
- 上游调用与落库同客户端连接脱钩;2xx 不可用响应不换号并删除已建缓存
- 缓存不存在:AI Studio 的 403、Vertex 生成请求的 400 与缓存资源接口的
  404 统一识别;原生转发(含流式)不重试、不换号、不改账号状态,
  向客户端返回标准 403,不暴露上游缓存资源 ID,上游原始错误登记到 ops;
  PATCH 遇上游 404 移除本地记录并返回 403,DELETE 视为成功
- 自建网关上游:账号开关 explicit_cache_upstream,缓存接口发往账号自身
  base_url;可选 explicit_cache_upstream_max_ttl_seconds 对齐上游 TTL 上限,
  显式 TTL 超限时创建跳过该账号(全部超限返回 400),未显式时按上限创建,
  PATCH 取本站与账号上限的较小值;绑定缓存的请求在网关账号上收到
  429 / 5xx 时不重试、不限流该账号;前端创建 / 编辑账号弹窗新增开关与上限输入框
- 用量与 ops 端点统计:带缓存 ID 的路径归一化为 /v1beta/cachedContents,
  缓存操作的上游端点记为 /v1beta/cachedContents
2026-10-10 23:37:47 +08:00
feeeei 3bfd40f5af fix(gemini): 引用缓存不存在的 403 不再停用账号并换号
上游对不存在、已过期、已删除或不属于当前项目的 cachedContent 一律返回
403 "CachedContent not found (or permission denied)"。原生转发路径在错误
策略之前识别该响应,原样返回客户端,不标记账号错误、不临时停调度、
不重试、不换号;其余 403 处理不变。
2026-10-10 23:36:17 +08:00
wucm667 ce6242fca1 fix(quota): recognize international coding endpoints 2026-10-10 14:47:11 +08:00
wucm667 29b2d721f4 test(web): use shipped SVG asset in embedded frontend tests 2026-10-10 08:39:49 +08:00
wucm667 b686842716 fix(gateway): sync main routing without widening responses retry 2026-10-09 13:36:36 +08:00
feeeei 9a51333101 feat(groups): 分组名称与描述支持多语言
- groups 新增 i18n JSONB 列(迁移 242):语言代码 -> {name, description},只存译文;
  name/description 原列语义不变,仍用于唯一性校验、搜索与各类日志
- 用户侧接口由后端按请求语言输出:取 Accept-Language 中权重最高的一项,先按完整
  语言代码、再按主语言匹配;该语言有译文的字段换成译文,否则保持原字段,且不再带出
  译文表。覆盖密钥、可用分组、订阅(含进度与汇总)、兑换、使用记录、可用渠道、
  模型广场、套餐列表
- 管理端接口一律返回原字段;分组管理接口额外带 i18n 供编辑
- 创建/编辑分组:名称、描述的标题行右侧新增语言下拉,同一个输入框在默认内容与各语言
  版本之间切换;语种跟随前端 availableLocales
- 管理端写入:创建/更新接受 i18n(更新时缺省不修改,传入则整体替换),校验语言代码
  形态与名称长度并丢弃空译文;简易模式同样放行;复制分组只带走描述译文
- 切换界面语言后整页刷新,让已加载的数据换成新语言;模型广场响应加
  Vary: Accept-Language
- 网关路径,以及只带 group_name 字符串的统计、错误记录出口不做本地化
2026-10-09 11:39:18 +08:00
github-actions[bot] 3a6fd1c9db chore: sync VERSION to 0.2.15 [skip ci] 2026-10-09 03:36:07 +00:00
shaw 85e3110953 fix(lint): check type assertions in web_search history helper and test 2026-10-09 11:10:11 +08:00
IrisRainbowNeko 64caa9af8b fix(openai): declare web_search via additional_tools for Responses Lite
Responses Lite rejects hosted tools at the top level ("responses Lite does
not support top-level tool type web_search"), so Lite requests now carry the
injected web_search tool in an input additional_tools item: extend the
caller's first additional_tools item, or insert one before a trailing
compaction_trigger so the v2 compaction wire keeps the trigger last.

The HTTP passthrough path also runs the shared compatibility normalizer on
/responses/compact; thread the compact flag through so that endpoint is
left untouched, and drop the now-redundant call from the passthrough OAuth
body normalizer.
2026-10-09 11:03:13 +08:00