Wesley Liddick
|
9392d1fc43
|
Merge pull request #3841 from fengshao1227/fix/html-escape-site-name-and-sanitize-doc-url
fix(security): HTML-escape site_name 并对 doc_url 统一应用 sanitizeUrl
|
2026-07-09 14:39:26 +08:00 |
|
Wesley Liddick
|
a57157b9fa
|
Merge pull request #3822 from wucm667/feat/api-key-last-used-ip
feat(api-key): 展示 API Key 最近使用 IP
|
2026-07-09 14:38:01 +08:00 |
|
Wesley Liddick
|
0118fa3ce2
|
Merge pull request #3721 from CHOS1N11111/codex/add-response-format-compat
Add response_format compatibility mapping
|
2026-07-09 14:37:46 +08:00 |
|
Wesley Liddick
|
105ac31c37
|
Merge pull request #3781 from fengshao1227/fix/openai-oauth-empty-mapping-model-guard
fix(scheduler): 空 model_mapping 的 OpenAI OAuth 账号不再吸收全部模型
|
2026-07-09 14:37:33 +08:00 |
|
Wesley Liddick
|
7302be4d13
|
Merge pull request #3833 from superman2003/fix/security-and-frontend-hardening
fix(gateway,frontend): 修复 Gemini 鉴权绕过与前端支付/会话缺陷
|
2026-07-09 14:37:19 +08:00 |
|
Wesley Liddick
|
636c452535
|
Merge pull request #3836 from ShuYeJang/main
fix(billing): 渠道定价覆盖写穿 fallbackPrices 共享指针导致全局计费污染
|
2026-07-09 14:37:05 +08:00 |
|
Heatherm Huang
|
cccba9a82e
|
Add official Grok 4.5 support
|
2026-07-09 14:26:10 +08:00 |
|
shaw
|
25a7169601
|
chore: Go 工具链升级 1.26.4 → 1.26.5——修复 stdlib 漏洞并补齐 CI 版本引用
- backend/go.mod 工具链 1.26.5:修复 stdlib crypto/tls 漏洞(GO-2026-5856)
- 同步全部构建/校验点的硬编码版本:根 Dockerfile、backend/Dockerfile、
deploy/Dockerfile 基础镜像;backend-ci / release / security-scan 三个
workflow 的 go version 校验
|
2026-07-09 14:06:57 +08:00 |
|
InCerry
|
53a5c45bd8
|
fix(gateway): cap lenient json normalization
Fixes #3540
|
2026-07-09 11:15:52 +08:00 |
|
li
|
bfb827b879
|
fix(security): HTML-escape site_name 并对 doc_url 统一应用 sanitizeUrl
Refs #3839 (第 8、12 点)
|
2026-07-09 10:03:49 +08:00 |
|
 superman2003andCursor
|
29a5fcd25e
|
fix(gateway,frontend): 修复鉴权绕过与前端支付/会话缺陷
后端:
- Gemini /v1beta 鉴权中间件补齐主中间件的授权校验: API Key 的 IP 白/黑名单、
专属分组授权、运行时过期/配额二次检查, 修复经 Gemini 端点绕过 IP ACL、
越权访问专属分组、以及状态未刷新时的配额/有效期绕过窗口。
- 粘性会话等待计划分支改走 newSelectionResult 以 hydrate 账号凭证, 修复调度
快照中账号凭证被剥离导致等待路径转发鉴权失败。
- SSE 流式转发客户端断开时不再 break 跳过当前事件 usage 合并, 修复少计费。
- Forward 对 nil gin.Context 的防御补齐; 上游错误体读取失败时记录日志避免静默。
前端:
- logout 将本地会话清理移入 finally, 服务端吊销失败也保证本地登出。
- Stripe 弹窗轮询改用正确的 auth_token 键并加防重入; 收到 INIT 后清除兜底
超时定时器, onUnmounted 清理 message 监听器。
- token 刷新请求补充 30s 超时, 避免挂起导致请求队列与 loading 永久卡死。
- 路由守卫在公共设置未加载时先 await fetchPublicSettings, 避免 payment/
risk_control 被误判为未启用而错误拦截。
- 支付状态轮询回调补充防重入与终态守卫。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-07-09 09:06:56 +08:00 |
|
Wesley Liddick
|
88581912ba
|
test: add regression tests for fallback pricing pollution
|
2026-07-08 19:23:38 +00:00 |
|
Wesley Liddick
|
4a30397623
|
fix: prevent channel pricing overrides from mutating shared fallback pricing
|
2026-07-08 18:37:33 +00:00 |
|
Bestony@Homelab
|
5debe1db33
|
feat(keys): sort by current concurrency
|
2026-07-08 15:51:22 +08:00 |
|
wucm667
|
7a11b39d6d
|
fix(api-key): check usage log rows close
|
2026-07-08 15:36:12 +08:00 |
|
wucm667
|
e0d149d511
|
feat(api-key): show last used IP
|
2026-07-08 15:26:54 +08:00 |
|
Heatherm Huang
|
3b206cc639
|
test: preserve grok video resolution forwarding
|
2026-07-08 13:50:49 +08:00 |
|
Heatherm Huang
|
889b657451
|
test: accept casted video billing constraint
|
2026-07-08 13:50:49 +08:00 |
|
Heatherm Huang
|
376e03ded1
|
fix: update Grok media default rate card
|
2026-07-08 13:50:49 +08:00 |
|
Heatherm Huang
|
4d702e3234
|
fix: split Grok image and video pricing
|
2026-07-08 13:50:49 +08:00 |
|
Eyre921
|
5aba53d542
|
fix(ops): 记录固化 200 SSE 流上的就地错误,修复流内限流不进错误看板
流式请求一旦 flush 了 keepalive ping,HTTP 状态码即固化为 200;此后
出现的错误(等待并发槽位超时后回退的限流、Wait 后二次计费校验失败、
流开始后才无可用账号等)只能就地以 SSE error 帧回传。而 ops_error_logger
以 status>=400 为采集触发条件,这类挂在 200 流上的失败此前会在错误看板里
完全隐形——客户端能收到 rate_limit_error,但网关侧没有任何错误记录可供排障。
- service: 新增 OpsStreamError 上下文 + MarkOpsStreamError/GetOpsStreamError,
采用「首个标记生效」保留根因错误,避免被后续通用兜底帧覆盖。
- handler: handleStreamingAwareError 在 streamStarted 分支标记流内错误。
- handler: OpsErrorLoggerMiddleware 在 status<400 且无上游错误上下文时,
据标记补记一条错误日志;分级用 IntendedStatus(如并发限流 429),
StatusCode 仍记 wire 的 200。上游透传错误已由 upstream-context 分支落库,
故此路径不重复记录。
- 补充单测覆盖补记、no-op、skip_monitoring 跳过与首个标记生效。
|
2026-07-08 02:51:51 +00:00 |
|
Wesley Liddick
|
6f43986c37
|
Merge pull request #3811 from jianjianai/hotfix/admin-scheduler-score-opt-in
fix(admin): 管理员账号列表默认关闭调度权值计算以降低负载
|
2026-07-08 10:22:10 +08:00 |
|
shaw
|
a56eb5b4dc
|
fix(compact): body-signal 提升上移到 handler 层并对齐 path-based 链路
合并 main 解决拆分冲突后,将原先 Forward 内的 body-signal 提升重构到
handler 的 compact 归一化入口之前,修复原方案的四个问题:
- reqStream 未重推导:body-signal 原始请求带 stream:true,Forward 级提升
后 compact 上游返回 JSON(Accept: application/json)却被流式 handler
解析,"stream ended before a terminal event" 会触发最多
max_account_switches 次换号 failover,且每次都白烧一次上游 compact 配额;
handler 级提升让白名单归一化先删除 stream,reqStream 自然为 false。
- requireCompact 调度过滤失效:原方案 path 改写发生在 requireCompact 判定
之后,调度器不会过滤不支持 compact 的账号;现在改写先于该判定。
- passthrough / Grok / chat-completions 桥接分支位于 Forward 检测点之前,
passthrough 账号完全无法命中;handler 级改写对所有分支生效。
- body 归一化口径不一致:body-signal 现在与 path-based 一样走白名单归一化
(prompt_cache_key 等一并删除),而非仅依赖 OAuth 黑名单转换。
检测函数导出为 HasCompactionTriggerInInput 供 handler 使用,保留原 PR 的
7 个单测;新增 6 个 handler 级回归测试(提升、codex 别名路由、尾斜杠、
子路径不误伤、path-based 无双重后缀、普通请求不受影响)。
Refs #3777
|
2026-07-08 10:04:14 +08:00 |
|
shaw
|
a855317624
|
Merge remote-tracking branch 'origin/main' into fix/compact-body-signal-routing
# Conflicts:
# backend/internal/service/openai_gateway_service.go
|
2026-07-08 09:57:31 +08:00 |
|
shaw
|
bb5d2e84a1
|
refactor(handler): 纯移动拆分 setting_handler.go(3957→468行)
|
2026-07-08 08:49:22 +08:00 |
|
shaw
|
f013bc1141
|
refactor(service): 纯移动拆分 admin_service.go(4409→642行)
|
2026-07-08 08:49:22 +08:00 |
|
shaw
|
2a4c28e8f5
|
refactor(service): 纯移动拆分 antigravity_gateway_service.go(4664→639行)
|
2026-07-08 08:49:22 +08:00 |
|
shaw
|
d0f669338b
|
refactor(service): 纯移动拆分 openai_ws_forwarder.go(4675→399行)
|
2026-07-08 08:49:21 +08:00 |
|
shaw
|
db3bd9971e
|
refactor(repository): 纯移动拆分 usage_log_repo.go(4701→212行)
|
2026-07-08 08:49:21 +08:00 |
|
shaw
|
4d23ad4bac
|
refactor(service): 纯移动拆分 openai_gateway_service.go(4872→1095行)
|
2026-07-08 08:49:21 +08:00 |
|
shaw
|
50043b1176
|
refactor(service): 纯移动拆分 setting_service.go(5471→263行)
|
2026-07-08 08:49:20 +08:00 |
|
shaw
|
084d26cbd2
|
refactor(service): 纯移动拆分 gateway_service.go(7294→1289行)
|
2026-07-08 08:49:20 +08:00 |
|
shaw
|
a4f942d8a9
|
fix(deps): 升级 AWS SDK 修复 govulncheck 报告的 GO-2026-5764
eventstream v1.7.5→v1.7.8、service/s3 v1.96.2→v1.97.3(含关联 internal 模块),
修复 EventStream 解码器 DoS 漏洞,恢复 backend-security CI。
|
2026-07-08 08:37:29 +08:00 |
|
jjaw
|
6ae5fc31b3
|
fix(admin): gate scheduler score calculation
|
2026-07-08 06:58:35 +08:00 |
|
 zhengshanandClaude Opus 4.8
|
3866da508f
|
fix(ratelimit): Anthropic 无 reset 头的 429 也进入兜底冷却
此前 Anthropic 429 若响应头无窗口重置时间(如 Extra usage required),
被视为"非真实限流"直接跳过标记。后果:账号永不冷却,调度器让每个
请求反复撞同一批持续 429 的账号——failover 预算烧尽后客户端稳定
收到 429(生产实测:一次请求 1.3s 内连换 4 账号全 429,而 DB 中
这些账号的限流状态毫无更新)。
改为与其他平台一致走 apply429FallbackRateLimit 秒级兜底回避:
- 默认 5s,管理端 RateLimit429CooldownSettings 可调 1~7200s
- 管理端关闭该设置即恢复旧行为(不标记)
- 日志 reason 标记为 anthropic_no_reset_time 便于运营区分
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-07 23:19:23 +08:00 |
|
shaw
|
d754be0d8e
|
refactor(gateway): 抽取 CC forwarder 公共管线并拆分两大 service 文件
PR #3802 遗留项:三个 CC forwarder(raw 直转 / responses 回退 / messages
回退)间约 85% 重复的 HTTP 管线与 SSE 循环骨架收敛到新文件
openai_gateway_cc_pipeline.go,messages / chat_completions 两条主路径中
逐字相同的错误处理块一并接入。各路径有意保留的行为差异(GLM effort
归一化、fast policy 适用范围、ClientDisconnect 语义、Grok 分支等)留在
调用方,未强行统一。
同时对两个最臃肿的网关文件做纯移动拆分(零语义变化,逐字节校验):
- openai_gateway_service.go 7821→4872 行:
调度 → openai_gateway_scheduling.go
passthrough → openai_gateway_passthrough.go
用量/计费/codex 快照 → openai_gateway_usage.go
- gateway_service.go 10912→7294 行:
调度 → gateway_scheduling.go
Anthropic APIKey 直通 → gateway_anthropic_passthrough.go
Bedrock → gateway_bedrock.go
回归保障:全部搬迁块与 HEAD 逐字节 diff 一致;留存文件经"HEAD 减去搬迁
范围"重构比对,差异仅为 goimports 移除的孤儿 import;定向单测
(fallback/raw/cyber/grok/transport/调度/用量/广域 Forward-Handle 扫描)
全绿;另经独立对抗审计确认零行为差异。
|
2026-07-07 22:14:46 +08:00 |
|
li
|
2dd2be9922
|
fix(compact): 识别 /v1/responses body 中的 compaction_trigger 信号
Codex remote compact v2 可以把 compact 触发器作为 input item
(type=compaction_trigger)嵌入普通 POST /v1/responses 请求体,
而非直接调用 /v1/responses/compact。此前 isCompactRequest 仅检查
URL path 后缀,导致 body-signal 形式的 compact 请求被当作普通
Responses 处理——上游路径、模型映射、body 归一化全部错误,Codex
收到非 compact 响应后报 "expected exactly one compaction output
item, got 0",长会话无法继续。
新增 hasCompactionTriggerInInput 检测 input 中的 compaction_trigger
item,命中后提升为 compact 请求并改写 URL path,使后续所有
isCompactRequest 分支(模型映射、body 归一化、上游 URL 构建)
自动生效。
Fixes #3777 (part 1: body-signal routing)
|
2026-07-07 21:23:02 +08:00 |
|
shaw
|
dad92488e5
|
fix(messages): 修复 /v1/messages CC 回退的错误处理旁路并补齐流式测试
针对 #3795 合并后审计发现的问题:
- 非 failover 上游错误分支改走共享 handleAnthropicErrorResponse:恢复
ops 上游错误记录、错误透传规则、cyber_policy 检测与按状态码映射的
错误 type(400→invalid_request_error 等);删除随之失效的
mapUpstreamStatusToAnthropicStatus
- 流式读错误对齐 forwardResponsesViaRawChatCompletions:scanner 出错时
不再 finalize(不再补发 message_stop 把截断伪装成正常完成),返回
stream usage incomplete 错误
- sawDone 由死变量改为与兄弟一致的无 [DONE] 哨兵 debug 日志
- 补充 fast policy 在本路径有意省略的说明注释
- 新增 8 个单测:流式收尾闭块、tool_call 分片聚合、length→max_tokens、
空流补帧、非 failover 400 走共享处理器、读错误不伪造收尾、
Responses 账号门控回归、非流式转换
|
2026-07-07 20:59:41 +08:00 |
|
Wesley Liddick
|
4bcb13f77f
|
Merge pull request #3786 from creamtea47/codex/openai-fast-force-priority
add force priority fast policy action
|
2026-07-07 20:45:45 +08:00 |
|
Wesley Liddick
|
9643382bd3
|
Merge pull request #3795 from fengshao1227/fix/messages-inbound-chat-completions-fallback
fix(messages): /v1/messages 入站支持不兼容 Responses API 的 OpenAI 上游
|
2026-07-07 20:45:14 +08:00 |
|
Wesley Liddick
|
af4b75a77c
|
Merge pull request #3794 from fengshao1227/fix/image-gen-namespace-permission-bypass
fix(image): 识别 Codex namespace image_gen 工具声明以拦截生图请求
|
2026-07-07 20:42:43 +08:00 |
|
Wesley Liddick
|
c7249a54ac
|
Merge pull request #3793 from heathermhuang/codex/grok-video-text-fallback
fix: route text-only Grok video 1.5 requests
|
2026-07-07 20:22:44 +08:00 |
|
shaw
|
b5604afd3d
|
test(batch-image): 集成测试适配 ReplaceBatchImageItemsForJob 的 indexing 状态守卫
守卫要求 job 处于 indexing 状态才允许重建 item 表;原测试在 created
状态下直接调用被 409 拒绝。改为先断言非 indexing 状态的冲突行为,
再经 created→submitted→indexing 合法链推进后执行原有断言。
|
2026-07-07 20:13:28 +08:00 |
|
CHOS1N
|
2fd3539527
|
Merge remote-tracking branch 'upstream/main' into codex/add-response-format-compat
|
2026-07-07 20:05:50 +08:00 |
|
 limingeandClaude Fable 5
|
13e773ef5e
|
feat: Codex 客户端模型清单(manifest)透传接口
背景:Codex CLI / Codex App 会从 provider 的 GET {base_url}/models?client_version=...
(自定义 provider 模式)或 GET /backend-api/codex/models(chatgpt_base_url 模式)
刷新模型选单,期望 ChatGPT Codex manifest 格式({"models":[{slug,...}]})。
sub2api 此前只提供 OpenAI 兼容格式的 /v1/models,Codex 客户端解析失败后静默
回落到本地缓存,导致指向 sub2api 的 Codex 客户端模型选单永久冻结在切换
provider 当天的状态,新模型(如 gpt-5.6 系列)永远不会出现。
方案:新增 manifest 透传——用组内可调度 OAuth 账号的凭据向
chatgpt.com/backend-api/codex/models 实时转发请求,响应体与 ETag 原样透传。
不在网关侧解析或维护模型清单:manifest schema 随 Codex 客户端版本演进,
透传保证网关无需跟进 schema 变化,且返回的始终是账号真实的模型权限
(区别于静态 DefaultModels 的"理论列表")。
路由:
- GET /backend-api/codex/models(新增)
- GET /v1/models 带 client_version 查询参数且组平台为 openai 时分发到
manifest 透传(client_version 是 Codex 客户端的天然指纹,普通 OpenAI
客户端不携带);其余请求保持原有 OpenAI 格式行为不变。
上游失败时按 fast-fail 返回错误,不伪造列表;Codex 客户端自身会回落缓存。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-07 19:49:40 +08:00 |
|
xlplbo
|
27e29f0562
|
feat(apicompat): 添加 tool_search 支持,增强工具调用处理逻辑
|
2026-07-07 19:19:35 +08:00 |
|
shaw
|
80a229bce5
|
fix(batch-image): 修复审计发现的计费死锁、状态机与队列原子性缺陷
修复 PR #3768 批量图像 MVP 合并后审计报告中的全部问题:
结算与计费(高危):
- 所有 SETTLEMENT_* 失败(超冻结/计数非法/manifest 冲突/定价缺失/扣费失败)
统一计入 retry_count 并在耗尽时释放冻结转 failed,消灭 settling 无限
requeue 导致的冻结余额永久锁死
- 耗尽出口的释放指纹统一为 RequestHash,与 processor/Cancel/recovery 一致;
release 遇同 request id 指纹冲突视为幂等成功,治愈历史毒消息
- 管理端校验 hold_multiplier >= discount_multiplier,定价快照对存量脏数据钳制
- 释放前校验 per-job hold claim(dedup+归档表),杜绝幻影释放
索引对账(高危):
- provider 输出与提交 custom_id 集对账:未知条目丢弃并记事件,
漏项补 PROVIDER_RESULT_MISSING 失败行,保证 success+fail == item_count
提交与恢复(高危):
- 提交前转 uploading 并在 provider.Submit 期间心跳刷新 updated_at;
恢复扫描改为原子复核(FailStaleUnsubmittedBatchImageJob),
消灭慢提交被误杀退款而上游任务照常计费的孤儿场景
- 上游任务创建成功但本地状态推进失败时,尽力取消上游并清理输入
- recovery 释放失败时入队交由 worker releaseTerminalHold 兜底重试
队列与并发(中危):
- Enqueue(SetNX+LPush)与 Reserve(BRPop+ZAdd)均改为 Lua 原子脚本,
消灭崩溃窗口导致 job 脱离队列、被 7 天 inflight 键锁死
- 锁冲突按 LockConflictDelay 重新入队(原直接丢弃需等 10 分钟 stale 恢复)
- 处理期间心跳:active zset 续期(ZAddXX 防幽灵成员)+ 锁 TTL 续期
- ReplaceBatchImageItemsForJob 增加 indexing 状态守卫,防掉队 worker 重写账目
存量回归(中危):
- image-only 定价条目(仅图片价无 token 价)恢复 token 计费 fail-closed,
不再按 $0 计费;图片计费路径不受影响
- 鉴权余额门槛恢复 balance <= 0 语义,MinimumBalanceReserve 不再作硬 403
加固:
- ZIP max_items 钳制到管理员上限;Submit 补齐 Platform==Gemini 校验;
gemini downloadUri 跟随前做 host 白名单校验
- 批量客户端改用共享 httpclient(拨号/TLS/响应头超时有界)
- 审计点名的忽略错误(MarkDownloaded/SettlementFailed/AppendEvent 等)改为记日志
|
2026-07-07 18:53:56 +08:00 |
|
li
|
69d02d2036
|
fix: 补齐 failover 路径的 appendOpsUpstreamError 日志
审查发现 error 路径缺少 appendOpsUpstreamError 和 upstreamDetail
记录,与 forwardResponsesViaRawChatCompletions 不对称。
|
2026-07-07 17:35:09 +08:00 |
|
li
|
5c0e580fbe
|
fix(messages): /v1/messages 入站支持不兼容 Responses API 的 OpenAI 上游
ForwardAsAnthropic 此前无条件把 Anthropic Messages 转为 Responses
格式发往 /v1/responses,导致只支持 /v1/chat/completions 的第三方
OpenAI 兼容上游(京东云、DeepSeek、Kimi、GLM 等)全部 400。
在入口增加与 ForwardAsChatCompletions 对称的 ShouldUseResponsesAPI
分流:APIKey 账号 + 上游不支持 Responses 时,改走新建的
forwardAnthropicViaRawChatCompletions,链式复用全部已有转换桥
(Anthropic→Responses→CC 请求,CC→Responses→Anthropic 响应),
不新建转换函数。
Fixes #3735
|
2026-07-07 17:23:18 +08:00 |
|
li
|
a02700c16f
|
fix(image): 识别 Codex namespace image_gen 工具声明以拦截生图请求
分组 allow_image_generation=false 时,Codex /image 技能通过
namespace 工具声明(type=namespace, name=image_gen)和 Responses
Lite 的 input additional_tools 绕过了现有生图意图检测——现有逻辑
只识别 tools[].type == "image_generation" 这一种形式。
在 gjson 版(openAIJSONToolsContainImageGeneration)和 map 版
(hasOpenAIImageGenerationTool)检测中增加 namespace image_gen
识别;同时扫描 input[].type == "additional_tools" 中嵌套的工具
声明,覆盖 Responses Lite 格式。
Fixes #3608
|
2026-07-07 16:58:48 +08:00 |
|