HuntercodeT
3438580213
fix(gateway): stop a per-model cooldown from turning 404 model_not_found into 429
...
classifySelectionFailureError upgrades a selection failure to 429
rate_limit_error whenever the scheduler's compact reason string matches
model_rate_limited=(\d+) with a positive count. It does so unconditionally,
including when the fallback it was handed is the authoritative 404
model_not_found classification.
Selection failure reasons are additive, so both can appear at once, e.g.
"pool=9, filtered: model_not_supported=8 model_rate_limited=1": eight accounts
cannot serve the model at all and the ninth happens to sit in a per-model
cooldown. classifyNoAccountError only produces ModelNotFound through
DiagnoseModelAvailabilityForPlatform, a dedicated database query over
persistent eligibility (active + schedulable + model_mapping), so it has
already established that no account in the group can serve the model. One
transient cooldown does not make "All available accounts are currently
rate-limited" true.
The mislabel is not cosmetic:
- Retrying can never succeed, yet 429 explicitly invites a retry.
- Clients that treat 429 as a rate limit retry hard and swallow the body;
Codex surfaces only "exceeded retry limit, last status: 429", discarding the
one message that names the real problem. Operators then look for capacity
and rate limits instead of a model whitelist.
- Ops attribution becomes self-contradictory: classifyNoAccountErrorFromGin
has already marked the request business-limited for local model
configuration, while call sites gate markOpsRoutingCapacityLimitedIfNoAvailable
on ModelNotFound, which the override clears, so the same request is also
counted as routing capacity limited.
Return the fallback untouched when it is ModelNotFound. The 429 upgrade is
preserved for every other fallback, which is the case it was written for:
accounts that can serve the model exist but are all cooling down, where the
fallback is 503 and retrying is meaningful.
Claude-Session: https://claude.ai/code/session_01LwvyJVV2sdqiu41Z9JDNUq
2026-09-01 15:18:30 +08:00
Wesley Liddick
2ac784c51a
Merge pull request #6353 from feeeei/main
...
refactor(billing): 长上下文阶梯计价改为价格目录数据驱动
2026-09-01 09:32:06 +08:00
Wesley Liddick
6b39d0b453
Merge pull request #6379 from baryon/contrib/codex-priority-service-tier
...
fix(codex): advertise Fast service tier in generated catalogs
2026-09-01 09:02:24 +08:00
Wesley Liddick
f218c8d40a
Merge pull request #6394 from qiujun8023/fix/account-stats-deepseek-peak
...
fix(billing): apply model pricing policies to account stats cost
2026-09-01 08:58:49 +08:00
Wesley Liddick
1cce2b38ee
Merge pull request #6417 from fengshao1227/fix/ws-ingress-capacity-shed-client-code
...
fix(openai): ctx_pool WS ingress 下发前改写上游容量降载错误码(Codex 会话被硬终止)
2026-09-01 08:54:00 +08:00
Wesley Liddick
9d9ed1cc62
Merge pull request #6415 from icebreaker-forked/fix/retry-transient-db-startup
...
fix(repository): PostgreSQL 恢复期间退避重试,避免首次启动退出
2026-09-01 08:53:25 +08:00
Wesley Liddick
2d7767eaf2
Merge pull request #6407 from wucm667/fix/issue-6402-delegation-bootstrap
...
fix(openai): accept delegation bootstrap without call id
2026-09-01 08:51:46 +08:00
Wesley Liddick
064d9b74e8
Merge pull request #6432 from okbexx/fix/codex-disabled-account-capabilities
...
fix(codex): ignore persistently disabled catalog accounts
2026-09-01 08:46:42 +08:00
Wesley Liddick
e87c47c957
Merge pull request #6435 from wucm667/fix/issue-6420-apikey-responses-instructions
...
fix(openai): avoid synthesized instructions for API keys
2026-09-01 08:45:58 +08:00
Wesley Liddick
bdedd6c544
Merge pull request #6433 from swjturay/codex/upstream-stale-ws-recycle
...
fix(openai-ws): recycle stale idle pool connections without reader liveness
2026-09-01 08:45:30 +08:00
feeeei
e2cfaa46e7
fix(pricing): 目录 cache 侧字段契约哨兵与 Gemini pro 缓存写入价修正
...
阶梯计价数据驱动后,目录条目的字段缺失或版本拼接会直接变成计费偏差,
解析层补两道数据契约哨兵,并修正出厂快照中 Gemini pro 系的缓存写入价:
- orphanCacheTierFields / warnOrphanCacheTierFields:条目带 cache 侧
above 档(含 _priority/_flex 变体与 above_1hr 形态)却没有基础价时打
WARN——cache 侧 above 档不参与计费取值,按"基础价 × 输入倍率"计,基础价
缺失即该分项按 0 计;变体缺自身基础价时沿 变体→1h→标准 回落链任一存在
即不算孤儿,与计费回落一致
- isLopsidedLongContextLadder / warnLopsidedLongContextLadders:above 档
折算出只有一侧带附加费的阶梯时打 WARN(基础价与 above 档来自不同价格
版本的形态),显式 long_context_* 字段不告警
- deriveLongContextFromAboveTierFields 注释改为陈述契约:cache above 档
须恰为基础价 × 输入倍率
- 出厂快照 6 个 Gemini pro 条目补 cache_creation_input_token_cost(= 标准
输入价,Google 对缓存写入不另收费)、above_200k 改为输入 above 价、带
priority 输入价的 4 条补 priority 孪生,与 model-price-repo 数据修正同值
测试:
- 解析层:孤儿字段 WARN(含 priority/1h 孤儿正例、1h 回落 5m 反例)、单侧
阶梯 WARN、出厂快照契约(全条目无孤儿字段、无单侧阶梯、Gemini pro 缓存
写入价 = 输入价)
- 用量契约:extractGeminiUsage 与 Antigravity 非流式/流式转换均不产生
cache_creation token(Gemini usageMetadata 无该类别)
- 计费:gemini-2.5-pro 阶梯对 cache_read / cache_creation 分项生效,阈值
计入缓存写入 token;阶梯表场景与夹具同步为现行目录值
2026-09-01 01:26:55 +08:00
feeeei
593fc93659
feat(pricing): 新增 override_file 价格目录覆盖补丁
...
新增 pricing.override_file 配置(默认关闭):稀疏补丁文件按 JSON 字段
浅合并覆盖目录/回退数据,作为最高优先级数据源,用于本地自定义官方
目录条目(如显式 long_context_input_token_threshold=0 关闭某模型阶梯)
而无需自建价格镜像:
- applyPricingOverrides 挂在 parsePricingData 解析入口,只修补已存在
条目(补丁字段覆盖同名字段,值为 null 删除字段);目录、回退与灾备
路径都经该入口,覆盖语义三处一致
- mergeOverrideOnlyModels 在回退合并后把目录/回退都没有的模型作为
独立条目并入(复用主解析路径,须自带价格字段通过有效性过滤);
不在主解析时抢先建条目,避免纯补丁挡住回退完整条目、其余分项价
静默变 0
- 最终未生效的条目(模型名拼错、纯补丁落在不存在的模型上)打 WARN
哨兵;override 文件缺失/损坏仅跳过合并,不影响目录加载
- 生效时机为重启或下次目录下载,与 fallback_file 一致;fallback_file
只补缺失模型的语义不变
2026-09-01 01:26:55 +08:00
feeeei
530fb20f25
refactor(billing): 长上下文阶梯计价改为价格目录数据驱动
...
删除 GPT/Gemini 系列写死的阶梯规则,阶梯一律由目录数据驱动:
- 解析层折算 LiteLLM 的 *_above_XXXk_tokens 绝对价字段为阈值+倍率
(阈值取自字段名,倍率 = above/基础价,cache 侧跟随输入倍率,
xAI 按 provider 用达到即进高档语义);显式 long_context_* 字段
按"字段存在"优先,显式 threshold=0 或 multiplier=1 可关闭阶梯
- 删除 OpenAI 272K 常量与 applyModelSpecificPricingPolicy 的长上下文
强补分支、fallbackPrices/静态兜底条目的 LongContext 字段、Gemini 旧
边际规则全链路(CalculateCostWithLongContext / RecordUsageWithLongContext /
阶梯表 marginal 基准);保留 fastRatio 与 GPT-5.6 cache_write 1.25x
防御分支、grok 静态兜底阶梯
- 渠道配置定价区间时完全以渠道区间为准,不再叠加目录阶梯
- 长上下文倍率 ≤0 在应用点按 1 计,防止显式字段残缺把分项乘 0 免费
- 目录重载时对比新旧数据,原有阶梯丢失打 WARN 哨兵告警
行为变化:Gemini 由边际 2x(仅 /v1beta、全模型)改为整单换档(数据
驱动、仅带 above_200k 的 pro 系),渠道平价之上叠加目录阶梯;Claude
sonnet-4/4.5 随目录数据获得 200K 整单阶梯(与官方定价一致);模型广场
官方参考价列与实付列同源展示目录阶梯。
2026-09-01 01:26:55 +08:00
Brisbanehuang
e2624fb65c
fix(codex): preserve known image input capabilities
2026-08-31 09:42:58 -04:00
Ray
6d5f027848
fix(openai-ws): recycle stale idle pool connections
2026-08-31 21:04:29 +08:00
wucm667
e21b849a92
fix(openai): avoid synthesized instructions for API keys
2026-08-31 20:58:49 +08:00
Jarl
ba345f1052
fix(codex): ignore persistently disabled catalog accounts
2026-08-31 20:26:29 +08:00
ice breaker
b6a7b8b7df
fix(repository): allow eight transient database retries
2026-08-31 17:10:31 +08:00
li
1dc0a09009
fix(openai): ctx_pool WS ingress 下发前改写上游容量降载错误码
...
上游容量降载(server_is_overloaded / slow_down)被 ctx_pool 的 ingress 直写路径
原样转发给客户端。Codex CLI 按闭集判定,这两个码属致命集,客户端打印
"Selected model is at capacity" 并直接终止会话,不退避重试。
仓库已有 sanitizeOpenAICapacityShedErrorCodeForClient 处理这件事,且注释写明了
Codex 的闭集判定与"账号状态判定使用改写前原始 payload"的前提。它此前只在
HTTP/SSE(openai_gateway_response_handling.go)与 http_bridge
(openai_ws_http_bridge.go)两条路径被调用,ctx_pool ingress 直写路径是唯一漏掉
的一条——同一账号同一时刻切到 http_bridge 就能正常退避重试。
改写结果写入独立的 clientMessage,不动 upstreamMessage:写出点之后的
markOpenAIWSClientVisibleFailure 与 handleOpenAIWSTerminalTransientFailure
仍按原始 payload 判定账号状态,与 http_bridge 的写法一致。
新增用例覆盖改写生效与改写范围两侧(非容量类错误码必须原样下发)。
2026-08-31 16:53:57 +08:00
ice breaker
863667ce67
fix: retry transient database startup errors
2026-08-31 16:25:13 +08:00
li
8f5451587e
fix(apicompat): Anthropic→Responses 流式转换在 thinking 块前关闭 message item 并推进 content_index
...
thinking 块开始时不关闭已打开的 message item,直接覆盖 CurrentItemType/
CurrentItemID,累积的助手文本既不进 state.Outputs 也拿不到 output_item.done,
response.completed 只带 reasoning——客户端收到「成功但无输出」。同 switch 的
tool_use 分支本来就先调 closeCurrentResponsesItem,只有 thinking 漏了。
content_index 只在 item 打开时置 0,从不推进。同一 message item 里第二个 text
块会再发一次 content_part.added(content_index=0),与第一个 part 撞在同一下标,
SDK 累积式 helper 按 content[content_index] 写入时后者覆盖前者。反方向
responses_to_anthropic.go 有三处 ContentBlockIndex++,正方向一处都没有。
新增用例覆盖两条坏顺序,外加一条生命周期不变式用例(output_item.added 与
output_item.done 必须配平、terminal 事件按announce 顺序逐项携带)。
2026-08-31 16:15:08 +08:00
shaw
0fcec63b68
test(openai): isolate visible TTFT fixture
2026-08-31 15:15:44 +08:00
shaw
8553c91c1a
test(api): update settings contract fixture
2026-08-31 15:05:39 +08:00
shaw
c66e700f05
fix(openai): move TTFT metric mode to admin settings
2026-08-31 14:52:07 +08:00
Wesley Liddick
fdf9751c12
Merge pull request #6378 from Ritel-T/fix/codex-oauth-service-tier-billing
...
fix(openai): preserve Codex OAuth Fast billing tier
2026-08-31 13:56:00 +08:00
wucm667
1be69e56aa
fix(openai): accept delegation bootstrap without call id
2026-08-31 12:57:06 +08:00
qiujun and Claude Opus 5
e7c029875c
test(billing): 图片输出按 output 子集计价
...
上一条改用统一定价管线后,TestTryModelFilePricing_WithImageOutput 挂在 0.3 vs
0.28:原算式把 ImageOutputTokens 当 OutputTokens 之外的额外量叠加,等于按文本
output 价和图片价各收一次,测试固化了这个重复计费。
ImageOutputTokens 本就是 OutputTokens 的子集(Gemini 取自 candidatesTokensDetails
的 IMAGE 档,OpenAI 取自 output_tokens_details),统一管线先扣除再按图片单价计,
未配图片价时回退到 output 价、总额不变,正是这个语义。期望改为 0.28。
影响:涉及图片输出的模型,账号统计成本会降低"图片 token × 文本 output 单价"。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-08-31 12:33:06 +08:00
Wesley Liddick
0678b24d58
Merge pull request #6283 from okbexx/feat/usage-compaction-kind
...
feat(usage): track native compaction requests
2026-08-31 11:19:37 +08:00
Wesley Liddick
f34735f462
Merge pull request #6388 from alfadb/feature/ollama-usage-cn-platforms
...
feat(ollama): 用量窗口支持挂在国产三家平台下的 Ollama Cloud 账号
2026-08-31 11:16:25 +08:00
Wesley Liddick
a2d7d41185
Merge pull request #6325 from 251392463/fix/grok-responses-vision-tool-output
...
fix(grok): preserve Responses vision tool output images
2026-08-31 11:15:33 +08:00
Wesley Liddick
03ab687686
Merge pull request #5866 from wucm667/fix/issue-5863-scope-monitor-groups
...
fix: scope channel monitor groups by user access
2026-08-31 11:15:13 +08:00
Wesley Liddick
fbc69322af
Merge pull request #6254 from wucm667/fix/issue-6249-configurable-image-cooldown
...
feat(openai): configure image tool cooldown
2026-08-31 11:13:52 +08:00
Wesley Liddick
414489d152
Merge pull request #5469 from wucm667/fix/issue-5467-passthrough-http-bridge
...
fix(openai-ws): bridge oversized passthrough requests
2026-08-31 11:13:35 +08:00
Wesley Liddick
50a9dd7a64
Merge pull request #6386 from wucm667/fix/issue-6383-isolate-passthrough-ws
...
fix(openai): isolate passthrough websocket sessions
2026-08-31 11:13:16 +08:00
Wesley Liddick
a4156eea10
Merge pull request #6385 from wucm667/fix/issue-6381-preserve-quota-limits
...
fix(admin): preserve quota limits on partial group updates
2026-08-31 11:12:56 +08:00
wucm667
897faea333
fix(account): reset quota cooldown atomically
2026-08-31 09:12:09 +08:00
qiujun and Claude Opus 5
9eabd2a5b7
fix(billing): apply model pricing policies to account stats cost
...
resolveAccountStatsCost 的优先级 3 维护了第二份"单价 × token 数"实现,每加一个
定价特性都要手工镜像:service tier 与长上下文分别由 9261dd77、25e6688a 补齐,
而 b5827cfd 引入的 DeepSeek 官方峰谷一直没有生效,高峰时段账号成本最多低估一半。
改为复用 CalculateCostWithServiceTier。channelPricing 仍为 nil,优先级 3 的语义
不变:只取模型定价文件、不引入渠道自定义定价;低谷时段结果与原算式完全一致。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-08-30 22:57:53 +08:00
wucm667
d5a0124637
fix(openai): isolate passthrough websocket sessions
2026-08-30 16:49:01 +08:00
alfadb
30b29e51e8
feat(ollama): 用量窗口支持挂在国产三家平台下的 Ollama Cloud 账号
...
Ollama Cloud 用量窗口(浏览器会话、5h/7d 快照、自动刷新、同 key 组共享)此前
只认 platform ∈ {openai, anthropic} 的 apikey 账号。但网关对 kimi/zhipu/deepseek
的 apikey 账号同样按 credentials.base_url 转发,用户把 Ollama Cloud 的 key 挂在
这三个平台下跑 Ollama Cloud 托管的 glm/kimi/deepseek 模型时,请求转发正常,用量
窗口却完全不可用。
- 平台白名单放开到 {openai, anthropic, kimi, zhipu, deepseek};type='apikey'
与官方 ollama.com base_url 的限制不变
- Go 侧收敛为 isOllamaCloudUsagePlatform,SQL 侧收敛为
ollamaCloudUsagePlatformsSQL,6 处白名单只引用单一来源,并补两侧互为镜像的
漂移守卫测试
- CN 周期余额/额度探测跳过 ollama 用量账号:其探测端点由 base_url 衍生,对
ollama.com 会被出站 URL 白名单拒绝,每轮都白跑并产生噪声
- 前端账号列表 CN 分支在 eligible 时改渲染 Ollama 用量窗口,并跳过 CN 额度/
余额子单元格(同上,渲染出来只会是一行探测报错)
2026-08-30 16:38:11 +08:00
wucm667
9f1effd71c
fix(admin): preserve quota limits on partial group updates
2026-08-30 16:36:13 +08:00
Long Li
57c76584a6
fix(codex): advertise priority tier for fast models
2026-08-30 14:21:08 +09:00
Ritel-T
82105f260a
fix(billing): resolve shadow credential tier contract
2026-08-30 13:40:37 +09:00
Ritel-T
50ad6e2e50
fix(billing): narrow Codex OAuth default exception
2026-08-30 13:40:19 +09:00
Ritel-T
f323d84644
test(billing): cover Codex OAuth usage pricing
2026-08-30 13:07:33 +09:00
Ritel-T
3a9070359b
fix(billing): scope Codex OAuth tier trust
2026-08-30 13:07:21 +09:00
Ritel-T
d39fc491ec
test(openai): cover websocket tier separation
2026-08-30 13:07:07 +09:00
Ritel-T
2b8cb628b6
fix(openai): preserve tiers in messages chat fallback
2026-08-30 13:06:45 +09:00
Ritel-T
8b4b3f4a94
fix(openai): preserve tiers in responses chat fallback
2026-08-30 13:06:32 +09:00
Ritel-T
624e4eef64
fix(openai): separate outbound and observed tiers
2026-08-30 13:06:11 +09:00
wucm667
a3bbf33c05
fix(monitor): scope groups by user access
2026-08-30 09:28:40 +08:00