Commit Graph
7678 Commits
Author SHA1 Message Date
shaw f37b69b779 fix(payment): treat Alipay refund query errors as pending and delay not-found failure
- The SDK returns signed business-failure responses (for example
  ACQ.SYSTEM_ERROR) with a nil error and empty fields. QueryRefund now
  checks the response code and returns an error, so the order stays
  REFUND_PENDING instead of being read as "no refund record" and failed.
- A missing refund record is treated as failed only after a 10 minute
  grace period from when the refund became pending. Alipay notes that a
  query sent too soon can miss a refund that later succeeds. The pending
  time comes from the REFUND_PENDING audit entry.
2026-10-15 22:26:53 +08:00
shaw 83337a0c65 fix(payment): query Alipay refund status and close unsupported order types
- Alipay: record the generated out_request_no as the refund ID and
  implement QueryRefund (alipay.trade.fastpay.refund.query), so refunds
  that return fund_change=N can be finalized from the admin refund query.
  Refunds recorded before this change return REFUND_QUERY_UNSUPPORTED.
- Fulfillment: mark paid orders with an unsupported order type as FAILED
  with an audit entry instead of erroring, so payment callbacks are
  acknowledged; RetryFulfillment rejects them with INVALID_ORDER_TYPE.
2026-10-15 22:03:15 +08:00
shaw 44e35fbf84 fix(payment): finalize failed pending refunds atomically
- Claim REFUND_PENDING -> REFUND_FAILED, return the held deduction and
  write the audit in one transaction. If the deduction cannot be
  returned, the order is still marked failed together with a
  REFUND_ROLLBACK_FAILED audit so a retried refund skips the deduction.
- Return an error when the REFUND_PENDING audit cannot be loaded or
  parsed instead of falling back to the legacy finalization path.
2026-10-15 21:38:57 +08:00
harukaandClaude Opus 5.5 f996b0bfaa fix(payment): load Stripe client secret from the local order snapshot
The /payment/stripe route no longer carries client_secret in its query.
The page reads it from the recovery snapshot written when the order was
created and requires the snapshot order to match order_id, consistent
with AirwallexPaymentView.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:38:52 +08:00
harukaandClaude Opus 5.5 7c6f70680d fix(payment): validate order types and keep refund deductions while pending
- Validate order_type (balance/subscription) at order creation and in
  fulfillment; other values are rejected with INVALID_ORDER_TYPE.
- Keep the balance/subscription deduction while a gateway refund is
  pending. The deduction is recorded in the REFUND_PENDING audit (written
  in the same transaction as the status change), not applied again on
  successful finalization, and returned once if the gateway reports
  failure. Legacy pending audits keep the previous behaviour.
- REFUND_PENDING orders are finalized via refund query only;
  PrepareRefund/ExecuteRefund no longer accept them.
- Invalidate the billing balance cache after refund deductions/returns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:38:48 +08:00
Wesley Liddick 1b2243a4f5 Merge pull request #8120 from Wei-Shaw/revert/inline-account-filters
revert(accounts): restore inline account filters (#7853)
2026-10-15 21:01:40 +08:00
shaw c2cca510f2 revert(accounts): restore inline account filters (#7853)
Revert 679a7186f ("feat(accounts): compact account search and filters"),
which moved the type / privacy / group filters behind a collapsed
"More filters" panel on /admin/accounts.

Polish on top of the revert:
- Widen the privacy select (w-48) so "全部Privacy状态" / "All Privacy States"
  no longer truncates.
- Narrow the search input to w-52 so all six controls fit on one row at 1440px.
- Below sm, lay the filters out as a two-column grid that fills the width
  instead of fixed-width selects with a ragged edge.
2026-10-15 20:44:29 +08:00
Wesley Liddick 698d142468 Merge pull request #8088 from wucm667/fix/issue-8077-workspace-aware-import
fix(openai): isolate Codex imports by workspace
2026-10-15 16:40:38 +08:00
Wesley Liddick ddef05527e Merge pull request #8079 from wucm667/fix/issue-8074-anthropic-base-url
fix(gateway): honor Anthropic protocol base URLs.
2026-10-15 16:40:19 +08:00
Wesley Liddick 58b5e858c8 Merge pull request #8094 from wucm667/feat/issue-8092-configurable-min-output
feat(apicompat): configure minimum output token floor
2026-10-15 16:40:06 +08:00
Wesley Liddick 857a76d4a0 Merge pull request #8093 from baryon/contrib/gemini-4-argon-support
feat(antigravity): support Gemini 4 Argon and accurate upstream model catalogs
2026-10-15 16:13:07 +08:00
shaw 9d3cc4507f fix(antigravity): keep legacy default passthroughs and bill Claude 5.5 tier IDs at base rates
- Restore runtime default passthroughs and Gemini 3.1 Pro aliases for
  explicit Antigravity model_mapping. Mappings saved before the Gemini
  3.x Flash / 3.1 Pro releases still depend on them; dropping them would
  silently remove those models from existing accounts on upgrade.
- Capability sync now skips injected-only passthrough targets, so models
  the upstream catalog omits no longer mark the sync as partial.
- Price Antigravity claude-{opus,sonnet}-5-5-{high,medium,low} at the base
  Opus/Sonnet 5.5 card instead of substring-matching claude-opus-5 /
  claude-sonnet-4-5 (1.25x-3x overbilling).
2026-10-15 15:47:42 +08:00
shaw 8afd2abd97 Merge remote-tracking branch 'origin/main' into contrib/gemini-4-argon-support
Resolve Gemini 4 Argon pricing conflicts in favor of main (#8078), which
already provides the base and Cyber Permissive price cards, thinking-tier
pricing aliases, and the local pricing snapshot.
2026-10-15 15:37:14 +08:00
Wesley Liddick dcde68aa58 Merge pull request #8078 from feeeei/feat/gemini-4-argon-pricing
feat(gemini): 补齐 Gemini 4 Argon 计费
2026-10-15 15:27:15 +08:00
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
Wesley Liddick 3856a02856 Merge pull request #8106 from Wei-Shaw/fix/composite-oauth-ambiguous-misroute
fix(gateway): 拒绝含 OpenAI 网关 OAuth 的 composite 歧义路由,防止凭据误入 Anthropic 管线
2026-10-15 15:08:47 +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
shaw 92c9433d40 chore: update sponsors 2026-10-15 08:53:20 +08:00
Long Li feab6d80dc fix(antigravity): preserve tool_result images, native Gemini functionCall/thoughtSignature, and composite /v1beta routing 2026-10-15 06:55:32 +09:00
wucm667 2a8cb088af feat(apicompat): configure minimum output token floor 2026-10-15 01:56:00 +08:00
Long Li 373d43533a feat(antigravity): support Gemini 4 Argon and accurate upstream model catalogs 2026-10-15 02:06:23 +09:00
wucm667 16611a8ee0 fix(openai): isolate Codex imports by workspace 2026-10-14 18:34:52 +08:00
wucm667 867563ae76 fix(gateway): honor Anthropic protocol base URLs 2026-10-14 14:58:26 +08:00
feeeei c6c9935ae3 feat(gemini): 补齐 Gemini 4 Argon 计费
- 内置兜底价:gemini-4-argon 为 $2 输入 / $10 输出 / $0.10 缓存读取(每百万
  token,优惠价有效期至 2026-11-30,2026-12-01 起为 $4 / $20 / $0.20);
  Cyber 变体(gemini-4-argon-cyber-permissive)不参与优惠,为 $4 / $20 / $0.20,
  匹配时先于基础型号判断
- Antigravity 的 -low / -medium / -high 档位名归一到基础价
- 本地价格快照新增两个不带前缀的条目,含 Priority 档价格;所有提示词长度同价,
  不带长上下文阶梯;只支持隐式缓存,不带存储价
2026-10-14 14:22:17 +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
shaw 9c2cca9e62 chore: update sponsors 2026-10-14 11:30:36 +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
v0.2.16
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
Wesley Liddick 49dc6e2363 Merge pull request #7828 from feeeei/feat/temp-unsched-rule-scope
feat(account): 临时不可调度规则新增作用范围 scope 选项
2026-10-13 14:59:27 +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 b669dc6daf test(frontend): 将模型白名单回归用例纳入 CI 2026-10-13 14:42:29 +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