shaw
b7cfe24626
chore: update README
2026-06-08 16:41:47 +08:00
shaw
acbcb50de1
chore: update README
2026-06-08 15:43:19 +08:00
Wesley Liddick
54b1c7fc31
Merge pull request #3113 from learnerLj/main
...
fix(openai): Chat Completions 转 Responses 时保留 prompt_cache_key
2026-06-08 15:20:28 +08:00
Jiahao Luo
d251487da8
fix(openai): propagate prompt cache key for chat completions
2026-06-08 11:13:18 +08:00
github-actions[bot]
0aad603013
chore: sync VERSION to 0.1.135 [skip ci]
2026-06-08 01:47:21 +00:00
Wesley Liddick
8c782bcc81
Merge pull request #3083 from xzz0081/fix/non-streaming-content-type
...
fix: force Content-Type to application/json on non-streaming responses
2026-06-08 09:20:17 +08:00
Wesley Liddick
870cefddf5
Merge pull request #3097 from NeckBozia/fix/5h-resets-at-stale
...
fix(usage): sync 5h ResetsAt to SessionWindowEnd and zero expired window
2026-06-08 09:08:23 +08:00
Wesley Liddick
a2bf6ad77a
Merge pull request #3107 from DaydreamCoding/feat/proxy-failover-resilience
...
feat: 代理生命周期与故障健壮性增强
2026-06-08 08:59:15 +08:00
Wesley Liddick
d7eef1e942
Merge pull request #3104 from CoolCoolTomato/fix/api-key-exclusive-group-auth
...
fix(bug): Fix the bug related to unauthorized use of groups
2026-06-08 08:58:44 +08:00
Wesley Liddick
7b394ed157
Merge pull request #3094 from okbexx/fix-openai-sticky-group-validation
...
fix: ignore stale OpenAI sticky sessions outside request group
2026-06-08 08:49:09 +08:00
DaydreamCoding
af19d44327
feat(proxies): 代理有效期与失败回退
...
- schema/迁移: 代理有效期、提醒天数、失败回退配置 + 账号 fallback 来源字段
- service/repo/DTO/handler: CRUD 透传新字段 + 校验
- fallback 目标解析纯函数(链式解析 + 环检测 + 兜底)
- SweepExpiredProxies 到期改投账号 + outbox 失效
- ProxyExpiryService 后台到期扫描任务 + wire 注册
- 账号侧手动回切原代理 + fallback 来源徽章/按钮
- 前端: 创建/编辑表单、列表到期徽章、类型/API/i18n
- ops 告警: proxy_expired_count / proxy_expiring_soon_count 指标
- 导入导出携带有效期/回退字段(备用按 name 映射)
- 补全测试 stub + 集成测试 + review 问题修复
2026-06-08 00:01:30 +08:00
DaydreamCoding and Claude Opus 4.8
f20e6bf769
feat(ops): 新增 account_temp_unscheduled_count 告警指标
...
临时摘除(temp-unschedulable)的账号被 account_error_count 指标显式排除
(acc.HasError && TempUnschedulableUntil == nil),且 SetTempUnschedulable 不
改账号 Status,导致代理/凭据故障触发的自动摘除无法被现有告警覆盖。
新增 account_temp_unscheduled_count 指标,统计当前处于临时不可调度窗口
(TempUnschedulableUntil 未过期) 的账号数,打通对自动摘除的定向告警:
- evaluator computeRuleMetric 新增分支 + handler 允许列表;
- 前端联合类型、告警规则下拉项与 en/zh 文案同步。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-07 22:31:45 +08:00
DaydreamCoding and Claude Opus 4.8
217f85999c
fix(openai): /responses 传输层错误转 failover + 持久故障临时摘除账号
...
代理/网络等传输层失败(Do/DoWithTLS 返回 error、无 HTTP 状态码,例如 SOCKS5
代理凭据过期返回 "username/password authentication failed")此前直接写
502 "Upstream request failed" 并返回普通 error:既不 failover 到健康账号,
也不摘除故障账号,导致同一坏账号被反复调度、大量用户持续收到 502。
- 新增 classifyOpenAITransportError:typed-error 优先
(ECONNREFUSED/EHOSTUNREACH/ENETUNREACH、*net.DNSError.IsNotFound)
+ 字符串兜底(SOCKS5 认证失败无 typed 形式)区分持久 vs 瞬时。
- 新增 handleOpenAIUpstreamTransportError:记录 ops 错误;对持久故障调用
SetTempUnschedulable(10min,DB) + 内存 BlockAccountScheduling 摘除账号并打
稳定 WARN 事件;统一返回 *UpstreamFailoverError 让 handler 切换到健康账号;
context.Canceled(客户端断开)不 failover、不摘除。
- /responses 主路径、passthrough、chat-completions 回退三处统一接入共享 helper。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-07 22:31:45 +08:00
Wesley Liddick
2a7c0fbb0f
Merge pull request #3093 from feitianbubu/fix/select-dropdown-max-height
...
fix(ui): 账号管理状态下拉菜单列表显示不全的问题
2026-06-07 22:22:32 +08:00
Wesley Liddick
c85174c717
Merge pull request #3095 from twodogegg/docs/update-sub2api-admin-skill
...
docs: update Sub2API admin skill
2026-06-07 22:22:04 +08:00
Wesley Liddick
d01e4fd84d
Merge pull request #3075 from bwliangc/feat/openai-cross-group-prev-response
...
fix(openai): 切组后剥离失配的 previous_response_id,修复跨组会话鉴权失败
2026-06-07 22:21:24 +08:00
CoolCoolTomato
1a86c6ce12
fix: enforce exclusive group access for api keys
2026-06-07 20:46:03 +08:00
bwlc and Claude Opus 4.8
9a0e439803
fix(openai): 跨组会话失配保护移到生效的 WSv2 路径并补测
...
87dd5f5d 把 previous_response_id 剥离保护加在了 HTTP Responses 路径,但该路径
在 previousResponseID != "" 时已无条件返回 400(0fcddce6 引入),剥离块恒不可达,
RemovePreviousResponseIDFromBody 也只被这段死分支调用、无覆盖。
- 删除 HTTP Responses 路径的死代码剥离块,留注释指明保护应在 WSv2 路径。
- 在 ResponsesWebSocket 首包(wsFirstMessage)处补回等价保护:previous_response_id
未命中当前分组粘连账号(StickyPreviousHit=false)时剥离,改用首包 input 重建;
带 function_call_output 的工具续链保持原样。这是 previous_response_id 真正生效、
会触发跨组会话链鉴权失败的路径。
- 为 RemovePreviousResponseIDFromBody 增加单元测试(现已有真实 caller)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-07 20:30:56 +08:00
NeckBozia
16bc876935
fix(usage): sync 5h ResetsAt to SessionWindowEnd and zero expired window
...
active poll 拿到新 5h ResetsAt 时只回写了 Extra.session_window_utilization,
没回写 SessionWindowEnd column;estimateSetupTokenUsage 读这个 column 作为 5h
窗口结束时间,导致被动采样模式下 dashboard 显示 utilization > 0 但 reset
时间渲染为「现在」。
- syncActiveToPassive 增加 UpdateSessionWindowEnd 回写
- estimateSetupTokenUsage 抄齐 Codex 分支的过期归零 guard,避免 active
poll 没回写时 UI 渲染矛盾
- UsageProgressBar 区分「待刷新」/「现在」语义;i18n key 中英补齐
2026-06-07 15:23:45 +08:00
twodogegg
606bfb421c
docs: update Sub2API admin skill
2026-06-07 14:29:51 +08:00
okbexx
a436296357
fix: validate OpenAI sticky session groups
2026-06-07 14:15:27 +08:00
feitianbubu
f5cecea5b4
fix(ui): 放开 Select 下拉选项区高度,避免选项被截断
...
将 .select-options 的 max-h-60(240px,约 6 项)放大到 max-h-80(320px,约 8 项),修复账号管理状态筛选 7 个选项时第 7 项「不可调度」被滚动隐藏、看似缺失的问题。overflow-y-auto 保留,超长列表仍可滚动。
2026-06-07 13:41:21 +08:00
Wesley Liddick
f868f7cb4b
Merge pull request #3078 from feitianbubu/feat/usage-cache-token-split
...
feat(usage): 用量统计拆分缓存创建与命中 token
2026-06-07 11:45:55 +08:00
Wesley Liddick
8ec448a8f6
Merge pull request #3077 from twodogegg/add-sub2api-admin-skill
...
docs: add Sub2API admin skill
2026-06-07 11:44:56 +08:00
xzz0081
154e0ed6c5
fix: force Content-Type to application/json on non-streaming responses
...
When the gateway forces streaming to the upstream, the upstream returns
Content-Type: text/event-stream. In the non-streaming branches, the body
is correctly aggregated into JSON, but WriteFilteredHeaders has already
passed the upstream's text/event-stream header through. Since Gin's
c.JSON/c.Data only set Content-Type via writeContentType when it is not
already present, the SSE header is never overwritten -- so the body is JSON
while the header says SSE.
Downstream middlewares that decide "is this streaming?" by Content-Type
(e.g. new-api) then mis-handle the response as SSE, breaking non-streaming
JSON clients.
Fix: explicitly Set Content-Type to application/json right after
WriteFilteredHeaders in the three non-streaming JSON write paths.
2026-06-07 02:56:26 +08:00
twodogegg
cb4f0015f7
docs: use Codex skill path in examples
2026-06-07 00:30:39 +08:00
feitianbubu
7386f38cf5
test(usage): API契约测试补充缓存创建/命中token字段
2026-06-06 22:43:06 +08:00
feitianbubu
0760cda921
feat(i18n): 添加缓存命中/创建/命中率文案
2026-06-06 22:32:37 +08:00
feitianbubu
029b6d61a2
feat(usage): 聚合统计拆分缓存创建与命中 token
2026-06-06 22:32:37 +08:00
twodogegg
9ecfc4e929
docs: add Sub2API admin skill
2026-06-06 21:13:08 +08:00
bwlc and Claude Opus 4.8
87dd5f5d72
fix(openai): 切组后剥离失配的 previous_response_id,修复跨组会话鉴权失败
...
用户从公开组切回订阅组后,客户端沿用旧 Responses 会话 ID,订阅组调度到
不拥有该会话链的账号,上游因会话链鉴权不匹配返回“鉴权失败,请检查 API Key”。
两处修复:
- openai_ws_state_store: 本地热缓存 responseToAccount 改为按 {groupID}:{responseID}
命名空间,与 Redis 层 sticky_session:{groupID}:... 一致,避免单实例下跨组命中
其他分组遗留的本地绑定,确保 StickyPreviousHit 信号可信。
- openai_gateway_handler: 转发前若 previous_response_id 未在当前分组命中粘连账号
(StickyPreviousHit=false),主动剥离并改用完整 input 重建上下文;带
function_call_output 的工具续链保持原样(与 WS 重连恢复逻辑一致)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 16:54:56 +08:00
github-actions[bot]
635ad81cdc
chore: sync VERSION to 0.1.134 [skip ci]
2026-06-06 07:52:15 +00:00
shaw
7f6fdcd639
fix(apicompat): remove duplicated stream lifecycle test declarations
...
PR #3016 's merge appended a verbatim second copy of four
TestStream_Reasoning* functions into
chatcompletions_responses_stream_lifecycle_test.go, causing
'redeclared in this block' build failures that broke both the
test and golangci-lint CI jobs.
Remove the duplicate block; each test now appears once.
2026-06-06 15:20:16 +08:00
Wesley Liddick
51fd9c6cf4
Merge pull request #3016 from Fool0ntheHill/codex/deepseek-cc-responses-bridge
...
fix(apicompat): surface reasoning-only chat streams
2026-06-06 15:08:58 +08:00
Wesley Liddick
651b24571c
Merge pull request #3000 from Pluviobyte/codex/sub2api-stream-field-validation
...
fix: validate stream field type across OpenAI-compatible handlers
2026-06-06 15:02:06 +08:00
Wesley Liddick
96b4bf624c
Merge pull request #2997 from bobobo2026/codex/openai-responses-sticky-account
...
Bind OpenAI HTTP response IDs to selected accounts
2026-06-06 14:52:55 +08:00
Wesley Liddick
56a6f53848
Merge pull request #2999 from Pluviobyte/codex/sub2api-scheduler-snapshot-sync
...
fix: sync scheduler snapshots after account state updates
2026-06-06 14:27:31 +08:00
Wesley Liddick
c06ad7520d
Merge pull request #2951 from EricLi404/00_lyy/add-codex-auto-review-model
...
Add codex-auto-review to OpenAI default models
2026-06-06 14:17:31 +08:00
Wesley Liddick
c65f9f19d2
Merge pull request #2955 from paraliine/main
...
Align OpenAI Codex usage stats with reset windows
2026-06-06 14:16:40 +08:00
Wesley Liddick
7b7eebc72d
Merge pull request #3069 from wsxfs/main
...
fix(auth): 修复 Linux DO 登录误进入邮箱验证
2026-06-06 14:10:35 +08:00
Wesley Liddick
5824359e97
Merge pull request #3062 from visa2/fix/multi-instance-bg-job-leader-lock
...
fix(service): gate periodic background jobs with a leader lock for multi-instance
2026-06-06 13:59:42 +08:00
Wesley Liddick
b76f9524ba
Merge pull request #3040 from bwliangc/feat/ops-ttft-sample-weighting
...
fix(ops): 运维监控首 token 延迟(TTFT)按流式样本数加权
2026-06-06 13:48:51 +08:00
wsxfs
aea2950b18
fix(auth): 修复 Linux DO 登录误进入邮箱验证
2026-06-06 13:05:07 +08:00
Wesley Liddick
6f18f74030
Merge pull request #2970 from ghostg00/compat/redis-replicate-commands
...
compat(redis): make TIME-using Lua scripts work on Redis 3.2-4.x
2026-06-06 11:23:54 +08:00
Wesley Liddick
1f423ae02a
Merge pull request #2961 from CheriWen/fix/cwe-204-info-disclosure-key-oracle
...
[Security] fix: return 404 instead of 403 to prevent key ID enumeration
2026-06-06 11:10:03 +08:00
Wesley Liddick
84cedd3d71
Merge pull request #2960 from CheriWen/fix/cwe-79-stored-xss-key-name
...
[Security] fix: sanitize API key name to prevent stored XSS
2026-06-06 11:09:08 +08:00
Wesley Liddick
ff3c976dbd
Merge pull request #3009 from liulinhuai/fix/images-upstream-error-passthrough
...
fix(images): surface real upstream error instead of generic 502
2026-06-06 11:07:53 +08:00
Wesley Liddick
1dda8626d5
Merge pull request #3018 from Zbl1007/openmeta/2989-0
...
Fix fixed weekly quota usage after switching from rolling reset
2026-06-06 10:59:18 +08:00
Wesley Liddick
1efd3e205d
Merge pull request #3056 from CoolCoolTomato/fix/postgres-dsn-dbname
...
fix(setup): bootstrap postgres connection with maintenance db
2026-06-06 10:42:42 +08:00
shaw
bba86f97d8
fix(repo): make userRepo.Delete reuse caller's transaction
...
userRepository.Delete used the r.client.Tx(ctx)+ErrTxStarted pattern,
which only reuses a transaction when r.client is itself a tx-bound
client. With the singleton base client (how Wire injects repos),
r.client.Tx() always starts a NEW independent transaction and ignores
any tx carried in the context.
As a result, AdminService.DeleteUser's transaction (added in #3047 )
only covered the API-key deletions; the user soft-delete escaped into a
separate, immediately-committed transaction. If the outer commit failed
after the user tx had committed, the user was deleted while its API keys
stayed active, reintroducing the unrecoverable state of #3021 .
Add a leading dbent.TxFromContext check (mirroring DeleteWithAudit) so
Delete joins an externally-provided transaction and lets the caller
commit/rollback. Extract the deletion body into deleteUser(ctx, exec,
id). All three original paths are preserved; callers passing a plain ctx
are unaffected.
Add user_repo_delete_atomicity_integration_test.go: builds repos with
the base client and a manual outer tx, asserting that delete-keys and
delete-user roll back together on abort and commit together on success.
2026-06-06 10:28:28 +08:00