1061 Commits
Author SHA1 Message Date
alfadb ddd63a8402 test: cover endpoint wildcard edge cases 2026-07-07 10:20:23 +08:00
alfadb 75e3089496 fix: normalize inbound endpoints from raw request path 2026-07-07 10:20:23 +08:00
alfadb 2fb212b7d6 fix(openai): 区分 responses compact 入站端点
/v1/responses/compact 及其别名路径(/responses/compact、/openai/v1/responses/compact、
/backend-api/codex/responses/compact 等,含嵌套子路径)是独立的客户端端点,
新增 EndpointResponsesCompact 常量并单独归一化,不再与根 /v1/responses 混同。
根 Responses 别名(/responses、/backend-api/codex/responses 等)仍归一到
EndpointResponses。NormalizeInboundEndpoint 优先匹配 compact 分支,避免根路径
前缀提前命中。DeriveUpstreamEndpoint 在 inbound 已为 compact 但原始路径无法
派生后缀时,回退到 compact 而非根 upstream。
2026-07-07 10:20:23 +08:00
Wesley Liddick d1d3400b69 Merge pull request #3645 from bestony/worktree/lucky-harbor-dbe4
feat(keys): add api key concurrency stats
2026-07-06 16:45:15 +08:00
shaw d56e94b875 feat(payment): 订阅 CNY 换算改为独立汇率配置的显式 opt-in
- 新增 SUBSCRIPTION_USD_TO_CNY_RATE 配置(1 USD = X CNY,默认 0=关闭),
  替代复用 balance_recharge_multiplier 的隐式换算,促销倍率与订阅定价解耦
- 未配置汇率时订阅保持 price 直付的存量行为,存量部署升级零影响
- 前端确认页/原价/手续费/方式限额与后端换算条件严格镜像(rate>0 且币种为 CNY)
- 管理后台新增汇率配置输入(zh/en 文案),checkout-info 透出 subscription_usd_to_cny_rate
- 单测锁定:汇率未配置时不换算、换算使用汇率而非余额倍率、余额订单不受影响、返利仍按 USD price
2026-07-06 14:34:17 +08:00
shaw 0fd2e9216d fix(scheduler): 修复 OpenAI 高级调度器审计发现的正确性与性能问题
针对 #3692 合并后审计发现的问题集中修复:

- previous_response_id 剥离条件改为按 call_id 全覆盖校验,
  部分可重建的工具续链不再被误剥离(不受开关门控的行为回归)
- 粘性加权回退路径补分组归属校验并清理失效绑定,杜绝跨分组账号泄漏
- 账号列表页:无 OpenAI 账号时跳过分数计算、过滤池限定 openai 平台、
  负载批查合并为账号并集一次查询,消除全表扫描与 Redis N+1
- 订阅优先模式下常规池不可用时回退订阅池等待计划,
  busy-but-waitable 的订阅账号不再导致请求硬失败
- TopK/权重 DB 覆盖显式受总开关门控,与兄弟子开关语义一致
- 前端未分组 OpenAI 账号回退展示基础分,不再显示 "-"
- ListAllWithFilters 等能力正式进入 AccountRepository/AdminService 接口,
  移除匿名接口断言与静默降级;负载批查失败补 warn 日志
- SelectAccountWithSchedulerForCapability 增加显式 previousResponseCanMove
  参数,移除 "previous_response_can_move" 魔法字符串哨兵
- 设置写入路径补"基础权重不得全为零"聚合校验;
  运行时设置批量读取失败的降级路径覆盖全部键并留痕
2026-07-06 11:43:16 +08:00
Wesley Liddick 759332aa92 Merge pull request #3692 from linshuboy/codex/openai-advanced-scheduler-controls-squashed
[codex] add OpenAI advanced scheduler controls
2026-07-06 10:59:23 +08:00
linshuboy f26ca5661e feat: add OpenAI advanced scheduler controls
Related: #1089, #408, #123
2026-07-05 17:24:38 +08:00
wucm667 41cdd438d7 fix(gateway): honor Anthropic custom models list 2026-07-05 08:35:34 +08:00
Wesley Liddick 707b87a96f Merge pull request #3676 from wucm667/fix/codex-import-refresh-token-missing-collision
fix(admin): Codex Session 导入 refresh_token 缺失时不再合并同 workspace 不同账号
2026-07-04 10:29:47 +08:00
wucm667 6bd248fd1f fix(admin): avoid merging Codex access-only imports 2026-07-04 09:53:01 +08:00
Wesley Liddick 8e07ec55db Merge pull request #3685 from jianjianai/fix/optimize-slot-cleanup
fix: 优化并发槽位定时清理性能
2026-07-04 09:19:34 +08:00
DaydreamCoding ebbdc70311 feat(usage): 错误请求对齐用量明细(UI/排序/筛选/列设置)
错误请求列表(/admin/usage 错误 tab、Ops 弹窗、用户端 /usage 错误 tab)
对齐用量明细的交互与信息密度。Squash of:

- feat(usage): 错误请求全面对齐用量明细(UI/列序/排序/筛选/列设置/新列)
- refactor(usage): 错误表提取共享徽章工具与 IP 批量工具条,后端排序解析归并 SetSort
- feat(usage): /admin/usage 错误请求新增分类过滤
- fix(ops): 错误列表 phase=upstream 过滤生效,守卫豁免改为显式 opt-in
- fix(ops): 错误列表用户列回退显示已删除 KEY 所有者
- fix(usage): 错误请求状态码排序对齐展示/过滤,筛选项改固定常用码
2026-07-03 23:02:27 +08:00
jjaw f3a3a0869d 优化并发槽位清理 2026-07-03 21:02:31 +08:00
Wesley Liddick 87dfc66132 Merge pull request #3659 from jianjianai/fix/ops-realtime-stats-performance
fix: 优化运维实时账号统计接口性能
2026-07-03 10:45:24 +08:00
shaw a5638a4e54 fix: match Codex session imports by chatgpt_user_id before shared account id
Members of the same ChatGPT team share chatgpt_account_id, so matching
imports by the account key first could overwrite another member's
account credentials. Identity keys are now ordered by strength
(user > email > access > account), and an account-key hit is rejected
when both sides carry different chatgpt_user_id values.

- Keep the account-key fallback when either side lacks a user id, so
  legacy accounts without chatgpt_user_id are updated and backfilled
  instead of duplicated
- Index all candidate accounts per shared key so a teammate's row can
  no longer shadow a legacy account depending on row order
- Apply the same conflict check to in-batch dedup and emit a warning
  when a legacy account is claimed via the shared account key
- Scope a 120s timeout to the Codex session import request instead of
  raising the global client timeout
2026-07-03 10:13:51 +08:00
jianjian 3f2ef60468 fix: optimize ops realtime account stats 2026-07-02 20:04:47 +00:00
Wesley Liddick 3020652fa1 Merge pull request #3565 from zy6p/zy6p/pr-openai-ws-http-bridge
feat(openai-ws): 支持 http_bridge ingress 模式
2026-07-02 17:40:32 +08:00
Wesley Liddick 821399ade1 Merge pull request #3622 from deqiying/feat/subscription-revoke-restore
支持恢复已撤销订阅
2026-07-02 17:34:20 +08:00
shaw 11a3da65c0 fix(group): harden peak-rate config handling and label peak windows with server timezone
Follow-up fixes to #3569 based on code audit:

- Expose server_timezone / server_utc_offset in public settings (and the
  __APP_CONFIG__ injection payload) and label every peak-window display
  with the server UTC offset, so users don't misread the billing window
  as browser-local time
- Unify CreateGroup/UpdateGroup peak-config sanitization via a single
  NormalizePeakRateConfig chokepoint: non-subscription groups always get
  peak fields cleared; unparseable window strings and negative
  multipliers are scrubbed when peak is disabled
- Replace hot-path time.Parse in PeakMultiplierAt with a manual HH:MM
  parser (accept set verified byte-for-byte identical to
  time.Parse("15:04") by exhaustive fuzzing) and reuse it in validation
- Revert the zero-behavior CalculateCost indirection churn in
  billing_service/gateway_service introduced by #3569
- Remove dead GetGroupPlatformMap and the duplicate deref helper in the
  admin handler package
- Share frontend peak formatting via utils/peak-rate.ts, unify the ×N
  label format, and move hardcoded Chinese tooltips to i18n keys
2026-07-02 16:11:07 +08:00
Bestony@Homelab 089a7b7fae feat(keys): add api key concurrency stats 2026-07-02 15:58:29 +08:00
Wesley Liddick a632cb0050 Merge pull request #3569 from xueshiji/main
feat(group): 订阅分组新增可选的高峰时段倍率,以支持智谱等coding plan的高峰时段
2026-07-02 14:55:34 +08:00
deqiying b26dcc3da2 feat(subscription): 支持恢复已撤销订阅 2026-07-01 22:19:21 +08:00
Wesley Liddick 5eb9da9c93 Merge pull request #3593 from heathermhuang/codex/grok-media-routing
fix: route Grok media endpoints
2026-07-01 17:49:27 +08:00
xueshiji 5e99561d6e Merge branch 'Wei-Shaw:main' into main 2026-07-01 17:48:42 +08:00
xueshiji 1034f576d7 fix: 高峰倍率全链路透传、计费术语修正与边界处理
- 高峰倍率信息透传至可用渠道、支付计划、结算信息等 API,前端
  GroupBadge / GroupOptionItem / SubscriptionPlanCard / PaymentView /
  SubscriptionsView 统一展示高峰时段与倍率标签
- 修正计费术语:"文本倍率" → "token 倍率",明确高峰倍率同时作用于
  token 计费的图片 token,图片按次计费不受高峰影响
- 允许高峰倍率 multiplier=0,支持高峰时段免费策略
- 切换分组类型为 standard 时自动清除高峰倍率配置
- 长上下文计费与标准计费路径改用内部实现,移除冗余中间调用
- 前端高峰倍率相关控件文案改为 i18n
- 新增多组高峰倍率相关单元测试
2026-07-01 17:46:12 +08:00
Wesley Liddick 0a9146c3d1 Merge pull request #3586 from deqiying/codex/fix-subscription-revoke-soft-delete
修复订阅撤销操作实际上是软删除的bug
2026-07-01 15:38:45 +08:00
Heatherm Huang 42e471f59a fix: harden grok media routing 2026-07-01 15:36:08 +08:00
Wesley Liddick 3812e627a8 Merge pull request #3546 from nslogx/fix/platform-quota-five-platforms
fix: allow five platform quota updates
2026-07-01 14:07:08 +08:00
xueshiji 8b46994dc2 Merge branch 'Wei-Shaw:main' into main 2026-07-01 14:01:03 +08:00
xueshiji 5e9529bb88 Merge branch 'Wei-Shaw:main' into main 2026-07-01 14:00:51 +08:00
DaydreamCodingandClaude Sonnet 5 bdf7ead157 feat(spark-shadow): OpenAI Spark 链接型影子账号
背景:gpt-5.3-codex-spark 使用独立于 codex 全局(5h/7d)的配额窗口(数据源是
/wham/usage 响应体的 codex_bengalfox,而非 codex 全局用的 x-codex-* 响应头),且
只能挂在已完成 OAuth 授权的 OpenAI 账号下复用其登录态,不能作为独立账号单独接入。
为此新增“链接型影子账号”(spark shadow account):影子账号本身不持有任何凭据,
通过 parent_account_id 指向母账号,凭据/token/代理透传自母账号并共享母账号的刷新
周期,仅在配额维度(quota_dimension=spark)和用量窗口上与母账号完全独立调度、互不
连坐。

实现:
- 数据模型:migration 154(+154a)给 accounts 表加 parent_account_id /
  quota_dimension 列 + 4 条约束(维度合法 / parent⟺非 global 维度一致 / 禁自指 /
  FK)+ 2 个 CONCURRENTLY 索引(母账号索引 + 每母账号至多一个影子的唯一索引)。
- 创建:POST /api/v1/admin/accounts/:id/shadow(CreateShadow)—— 一母一影(唯一
  索引兜底并发竞态),继承母账号 proxy/分组/并发/优先级(显式传参可覆盖),默认
  model_mapping 恒等映射到 spark(拒绝非 spark 模型),母账号必须是真实的 OpenAI
  OAuth 账号(非影子)。
- 凭据透传:resolveCredentialAccount 把影子解析回母账号,GetAccessToken / 请求头
  / WS 三条路径统一走此函数;影子自身 Credentials 恒为空(仅允许写 model_mapping),
  凭据写入的汇聚点 persistAccountCredentials 对影子早返 no-op,防止误写。
- 调度:parentHealthyForShadow 只看母账号是否仍是 OpenAI OAuth + 凭据/传输是否
  可用(active、token 未过期、未处于 401/刷新失败/传输故障导致的临时不可调度冷却),
  刻意不看母账号的 global 限流窗口——两条 429 道互不连坐。
- 用量:影子的 codex_5h/7d 走 OpenAIQuotaService.QueryUsage(/wham/usage 的
  codex_bengalfox),与母账号走的 WSv2 探测(/responses 头)完全独立的数据源、
  刷新节流与 staleness 判定。
- 备份:ExportData 显式排除影子账号(影子不持凭据,通用凭据型导入强制
  credentials 非空、无法表达父子链接),按 skipped_shadows 计数提示前端。
- 前端:账号操作菜单新增“创建 Spark 影子”入口,影子行展示回填的母账号信息
  (邮箱 / plan / 隐私模式 / 订阅到期 / chatgpt_account_id),批量操作自动跳过
  影子账号。

说明:migrations 目录用完整文件名(而非纯数字前缀)标识迁移,故本次新增的
154_account_spark_shadow.sql / 154a_..._notx.sql 与已有的
154_add_ops_system_logs_api_key_id.sql 按序号共存,与目录里 145/151 已有的
先例一致。

测试:新增约 20 个测试文件,覆盖 handler(CreateShadow 校验 / 母账号信息回填)、
repository(影子 round-trip / 一母一影唯一索引 / 迁移 schema)、service(凭据
透传三路径 / 调度母健康门 / 用量窗口来源与刷新节流 / CRS 母账号不变量 / 各类
早返与 fail-closed 场景)及前端组件(账号列表 / 操作菜单 / 用量重置)。

验证(镜像 CI;golangci-lint 首次全量分析耗时过长被跳过,其余全部实测):
- gofmt -l:干净
- go build ./... / go vet ./...:通过
- go test ./... -count=1:全绿(全部包 ok,含 internal/service、
  internal/repository、migrations)
- go test -tags integration ./internal/repository/... ./internal/service/...
  (真实 Postgres,testcontainers):全绿,含迁移幂等性
  (TestMigrationsRunner_IsIdempotent_AndSchemaIsUpToDate)与影子相关全部用例
- pnpm lint:check / pnpm typecheck / pnpm build(真实 vite 构建)/
  pnpm vitest run:全绿(124 文件 760 用例)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 12:21:45 +08:00
Heatherm Huang 2fe756e4be fix: recognize grok media models 2026-07-01 11:43:35 +08:00
Heatherm Huang 3b5d812f7a fix: route grok media endpoints 2026-07-01 11:43:35 +08:00
shaw 59e9356c51 feat: 抹除 Anthropic OAuth 请求中客户端 dateline 隐写指纹
对 /v1/messages 转发到 Anthropic OAuth/setup-token 账号的请求做 dateline
归一化,将 system prompt 与 <system-reminder> 块中 "Today's date is …"
语句里的 4 种撇号变体与 "/" 日期分隔符还原为 ASCII 撇号 + "-",抹除某些
客户端在检测到非官方 base URL 时注入的 3 bit 隐写指纹。API Key 账号不受
影响。新增系统设置开关 enable_client_dateline_normalization,默认开启。
2026-07-01 10:54:18 +08:00
deqiying 03727ac363 fix(subscription): 修复订阅撤销软删除失效
总: 增加明确的订阅撤销接口,修复撤销后的缓存失效和管理端 revoked 展示。

分: 同步失效订阅 L1 与 billing cache,补跨实例失效通知、soft-delete-aware 列表查询、revoked_at DTO 字段和回归测试。
2026-07-01 00:37:51 +08:00
PMExtra cafc95c3e2 feat: align user usage analytics with admin 2026-06-30 15:31:28 +08:00
xueshiji 915c60b150 feat(group): 订阅分组新增可选的高峰时段倍率,以支持智谱等coding plan的高峰时段 2026-06-30 14:17:05 +08:00
Wesley Liddick 76e0d90736 Merge pull request #3509 from wucm667/fix/refund-pending-not-success
fix(payment): 退款 pending 不再当成最终成功,避免站内账务与网关状态不一致
2026-06-30 13:38:04 +08:00
Wesley Liddick efb8b45876 Merge pull request #3560 from StarryKira/feat/issue-3557-oauth-email
feat: fix OAuth email completion flow
2026-06-30 10:55:00 +08:00
zy6p 0476b5c97a fix(openai-ws): allow http_bridge accounts in ws ingress selection
(cherry picked from commit f0d215ec522e05043f5012a5f1e7aba2bfb57fcc)
(cherry picked from commit 7b14846a65e16570cb7b472b0ed06c6dcb190e0d)
2026-06-30 10:41:41 +08:00
wucm667 93a3bf3077 Fix refund pending finalization gaps 2026-06-30 10:19:50 +08:00
wucm667 7316d83027 fix(payment): 区分退款 pending 并收敛匿名查单 2026-06-30 10:00:48 +08:00
haruka 260fda19b3 feat: fix OAuth email completion flow 2026-06-30 01:11:51 +08:00
Heatherm Huang 10e623f674 fix: allow grok messages compatibility 2026-06-29 18:33:37 +08:00
Heatherm Huang 4a7148e203 fix: support grok cli compatibility routes 2026-06-29 17:53:19 +08:00
Wesley Liddick d3acd8e96e Merge pull request #3497 from JRBaggins/fix/openai-count-tokens-bridge
Bridge OpenAI count_tokens to responses input_tokens
2026-06-29 15:23:11 +08:00
nslogx d86e83259e fix: allow five platform quota updates 2026-06-29 09:40:04 +08:00
Wesley Liddick c99112a9e9 Merge pull request #3515 from bestony/feat/ops-system-log-key-id
feat(ops): add key id filter to system logs
2026-06-29 09:24:40 +08:00
mxyhi 82553c4dca fix(openai): preserve quota platform in usage billing 2026-06-28 11:13:09 +08:00