Commit Graph
7377 Commits
Author SHA1 Message Date
YahooYuan666 27f4a1780f test(grok): cover empty response.completed failover for PlatformGrok
Adds two regression cases mirroring the #5009 OpenAI ones for Grok
platform accounts (issue #7774):

- TestOpenAIResponsesEmptyCompletedFailsOverGrok: an empty
  response.completed on the forwardGrokResponses streaming path must
  produce UpstreamFailoverError with an empty client body. Verified to
  FAIL on main without the guard extension and PASS with it.
- TestOpenAIResponsesEmptyCompletedWithOutputSucceedsGrok: normal Grok
  streams with semantic output and usage are untouched.

Fixes #7774
2026-10-01 03:01:43 +08:00
YahooYuan666 3613174cf6 fix(grok): fail over silent-refusal empty response.completed on Grok Responses streams
Issue #5009 added a failover guard for OpenAI Responses streams that
terminate with an empty response.completed (no output, no usage, no
error), but the guard is gated on PlatformOpenAI. Grok platform
accounts reach the same handler (forwardGrokResponses ->
handleStreamingResponseWithReasoning) and exhibit the same upstream
silent-refusal shape, so their empty completions are relayed to the
client as successful empty turns: Responses SDK clients map the empty
completed to finishReason stop and accept the turn with no retry.

Extend the guard to PlatformGrok, matching the unconditional guard on
the passthrough path (openai_gateway_passthrough.go).

Fixes #7774
2026-10-01 02:16:22 +08:00
github-actions[bot] 42bc7f6cff chore: sync VERSION to 0.2.11 [skip ci] 2026-09-30 07:07:11 +00:00
Wesley Liddick 96f4c115c9 Merge pull request #7726 from william-drakemond/feat/claude-reset-redeem
feat(claude): 手动兑换 Claude 重置次数 / Manually redeem Claude limit resets
v0.2.11
2026-09-30 14:33:23 +08:00
Wesley Liddick 327c322184 Merge pull request #7730 from lyy0709/codex/gpt61-sol-codex-plans
feat(openai): support GPT-6.1 Sol, Codex plans and Astra Ultrafast
2026-09-30 14:32:59 +08:00
Wesley Liddick 48b7109588 Merge pull request #7736 from lyy0709/codex/remote-codex-model-catalog
feat(codex): 支持 model_catalog_url 远程模型目录配置
2026-09-30 14:32:34 +08:00
Wesley Liddick 4f0c079e27 Merge pull request #7681 from william-drakemond/fix/balance-inflight-reservation
fix(billing): Redis 在途预留,防止余额模式并发透支
2026-09-30 14:31:04 +08:00
Wesley Liddick b0cfff9826 Merge pull request #7752 from Wei-Shaw/fix/api-key-create-limits
feat(api-key): 增加 API Key 创建数量与频率限制
2026-09-30 14:20:00 +08:00
shaw 017bbcb901 chore(api-key): 创建频率默认值调整为每小时 60 次 2026-09-30 13:55:37 +08:00
shaw 9ecb340822 feat(api-key): 增加 API Key 创建数量与频率限制
- 新增 api_key_create.max_active_per_user(默认 200)与
  api_key_create.max_per_user_per_hour(默认 20),0 表示不限制
- 创建频率按固定一小时窗口统计,自定义与自动生成的 Key 统一计入
- 创建计数独立于 Key 生命周期,删除或修改 Key 不再重置计数
- 移除不再使用的 DeleteCreateAttemptCount 缓存方法
2026-09-30 13:44:02 +08:00
Wesley Liddick a0f41f95a0 Merge pull request #7579 from feeeei/fix/claude-code-only-fallback-openai-compat
fix(gateway): Claude Code 限制分组的 OpenAI 兼容入口改走降级分组,不再直接 403
2026-09-30 10:47:08 +08:00
lyy0709 b5efbe3f4c feat(codex): support remote model catalogs in client config 2026-09-29 13:26:44 -07:00
lyy0709 e6d191a83f fix(openai): support Astra Ultrafast capabilities and pricing 2026-09-29 11:50:08 -07:00
lyy0709 c91bb6124a feat(codex): recognize current subscription plans 2026-09-29 11:50:08 -07:00
lyy0709 9688571a83 feat(models): support GPT-6.1 Sol 2026-09-29 11:49:26 -07:00
William DrakeandClaude Opus 5.5 514ad0aa8e fix(accounts): readable window labels in Claude reset confirm (review R1-4)
- Map five_hour/seven_day/seven_day_overage_included to 5h/7d/7d overage
  (raw key fallback) in the confirm message, credit tooltip and success message.
- Align zh/en confirm copy with the Codex dialog; {count} is the count
  remaining after this use.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 14:24:19 -04:00
William DrakeandClaude Opus 5.5 dc2efc6b9a fix(claude): tighten reset redeem outcome handling (review R1)
- R1-1: an explicit upstream "unavailable" answer now fences the organization
  for 15 minutes (CLAUDE_RESET_UPSTREAM_UNAVAILABLE) instead of 24h; ambiguous
  outcomes keep the 24h fence. Frontend tells the operator to retry later.
- R1-2: rotate the idempotency key after definite pre-claim refusals (busy,
  not available, unresolved, upstream unavailable); map IDEMPOTENCY_IN_PROGRESS
  and IDEMPOTENCY_RETRY_BACKOFF to clear zh/en messages.
- R1-3: redeem reason and cleared windows pass only through explicit
  allowlists, so upstream values can never echo a grant ID to clients.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 14:21:10 -04:00
1872d44b58 feat(accounts): add confirmed Claude reset button next to reset count
Orange 「重置」 button mirrors the Codex cell: enabled only after a query
shows a redeemable credit, danger confirm, one idempotency key per
confirmation reused on retry, outcome-specific messages, then refreshes
credits and the usage row. Ported from upstream PR #7591.

Co-authored-by: korkin25 <eugeny.kuzakov@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 11:41:33 -04:00
196b47757a feat(claude): redeem native limit resets with server-selected grant
POST /admin/accounts/:id/claude/reset-credits/redeem (Idempotency-Key
required, same middleware chain as the Codex reset-quota route). The server
re-queries eligibility and claims only the upstream next_grant_id when it is
redeemable; grant/org IDs never reach the client. Claims are serialized by
account and organization Redis leases, and a durable per-organization fence
in the idempotency table blocks further redemption after an unconfirmed
outcome (settles after 24h). Ported from upstream PR #7591.

Co-authored-by: korkin25 <eugeny.kuzakov@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 11:41:33 -04:00
github-actions[bot] a60a29549f chore: sync VERSION to 0.2.10 [skip ci] 2026-09-29 08:28:45 +00:00
Wesley Liddick 2f3fed2fdb Merge pull request #7678 from PMExtra/feat/claude-code-only-client-tabs
feat: Claude Code 专用分组仅展示受支持的客户端入口
v0.2.10
2026-09-29 15:53:58 +08:00
Wesley Liddick fe9dadfc7d Merge pull request #7679 from PMExtra/feat/risk-control-allowlist
feat: 新增可信用户风控白名单,保留审计并免除本地自动处罚
2026-09-29 15:53:18 +08:00
Wesley Liddick 41dcfec489 Merge pull request #7680 from PMExtra/fix/openai-model-catalog
fix: 移除 OpenAI 分组 Codex 配置中的模型目录依赖
2026-09-29 15:52:51 +08:00
Wesley Liddick 052e08e764 Merge pull request #7684 from william-drakemond/feat/claude-reset-credits-ui
feat(claude): 查询 Claude 重置次数(只读),UI 复用 Codex 次数按钮 / Read-only Claude reset credit count, reusing Codex count UI
2026-09-29 15:50:53 +08:00
Wesley Liddick 1f955af353 Merge pull request #7380 from wucm667/fix/issue-7377-forward-stream-usage
fix(gateway): forward received chat stream usage
2026-09-29 15:44:10 +08:00
Wesley Liddick ccb027b515 Merge pull request #7378 from wucm667/fix/issue-7368-composite-ws-routing
fix(gateway): resolve composite routes for websocket aliases
2026-09-29 15:43:52 +08:00
Wesley Liddick f50b99b66c Merge pull request #7542 from wucm667/fix/model-whitelist-mapping-conflict
fix(accounts): warn when whitelist model conflicts with mapping
2026-09-29 15:43:33 +08:00
Wesley Liddick 883a53fea0 Merge pull request #7643 from wucm667/fix/issue-7637-antigravity-compat-keepalive
fix(antigravity): keep compat streams alive before first content
2026-09-29 15:43:19 +08:00
Wesley Liddick b35a611538 Merge pull request #7646 from wucm667/feat/issue-7642-dashboard-spending-trend
feat(dashboard): toggle recent usage between tokens and spending
2026-09-29 15:43:07 +08:00
Wesley Liddick 1dca86f287 Merge pull request #7701 from wucm667/fix/issue-7699-tool-rewrite
fix(anthropic): rewrite tool names in one body pass
2026-09-29 15:42:45 +08:00
Wesley Liddick dd6cb410e6 Merge pull request #7683 from StarryKira/codex/sonnet-5-5-upstream
feat: support Claude Sonnet 5.5
2026-09-29 15:42:21 +08:00
wucm667 27a9421e6a fix(anthropic): rewrite tool names in one body pass 2026-09-29 15:00:16 +08:00
William DrakeandClaude Opus 5.5 860782e6fb fix(claude): harden reset credit projection and cell state (review R2)
- Drop selection_token (unsalted hash of a short grant ID, reversible) and
  claudeGrantSelection from the read-only DTO; assert it never serializes.
- query() returns only the projected result; no raw upstream block escapes.
- Clear a cooldown_until that is already past, using the same `now` as the
  redeemable check; the cell also shows the cooldown only when in the future.
- Invalidate in-flight queries when account id, platform or type changes.
- Sort the earliest-expiry fallback by parsed timestamp, invalid/missing last.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:59:39 -04:00
William DrakeandClaude Opus 5.5 35232c3949 fix(accounts): address review of Claude reset credit count
- Show resets held (sum of resets_left) on the count button, matching the
  Codex count; flag "not usable now" when none is redeemable yet, instead
  of showing 0 while a grant exists.
- Pick the redeemable (next) grant for the expiry chip, falling back to
  the earliest expiry, rather than assuming credits[0] is next.
- Render a single ClaudeResetCreditsCell across usage states so a query
  started while usage loads is not lost on remount.
- Drop an unrelated google/subcommands go.sum entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 19:03:47 -04:00
William DrakeandClaude Opus 5.5 421da3f0d4 feat(accounts): align Claude reset credit query with Codex reset count button
The Claude reset credit query rendered as a bare "Claude 重置额度" link,
which reads like a redeem action, and dumped raw ISO timestamps and
window keys. Render it like OpenAIQuotaResetCell instead: a read-only
"次数 N" button sharing one row with the local query button via a
#pre-actions slot, plus an expiry chip whose tooltip carries the grant
label, cleared windows and limit requirement.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 18:06:23 -04:00
korkin25 48970f61b4 fix(claude): explicitly close status HTTP response 2026-09-28 18:04:14 -04:00
korkin25 f8984b8a93 feat(accounts): show Claude reset credit status on demand 2026-09-28 18:04:13 -04:00
korkin25 6a8f921650 feat(claude): expose sanitized native reset credit status 2026-09-28 18:04:13 -04:00
haruka 2cc459e24f style: satisfy Sonnet 5.5 lint checks 2026-09-29 05:20:04 +08:00
William DrakeandClaude Opus 5.5 475c0839c6 style: gofmt
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:08:27 -04:00
William DrakeandClaude Opus 5.5 b886fb8edb fix(billing): read account-level mappings from scheduler snapshot only when unpriced
- only consult account mappings after primary/channel candidates fail to price (or composite)
- source mappings from the scheduler snapshot (same pool as account selection), no direct DB query and no per-model cache
- ungrouped API keys use the scheduler's ungrouped pool
- no negative caching: new mappings take effect on the next request

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:08:13 -04:00
haruka 8490a81867 feat: support Claude Sonnet 5.5 2026-09-29 04:55:07 +08:00
William DrakeandClaude Opus 5.5 652a7d74f9 fix(billing): estimate unpriced aliases via billing fallback models; don't renew expired reservations
- Inflight estimate now mirrors billableModelWithFallback: when the primary
  billing model has no price, fall back to the channel-mapped model (also for
  billing_model_source=requested) and to account-level mapped models (max over
  schedulable accounts in the group, cached 30s).
- Composite groups also consider concrete account-mapped models (max) so the
  alias' family fuzzy price cannot underestimate.
- Renew Lua refuses (and purges) members whose score <= now.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:49:29 -04:00
William DrakeandClaude Opus 5.5 52c123e6f4 fix(billing): hold inflight reservation until billing lands; price estimate like billing; wire remaining endpoints
Address gaps found in adversarial verification of the in-flight balance
reservation:

- Early release: the reservation is now a ref-counted handle carried on the
  request context. Billing tasks submitted via submit*UsageRecordTask take a
  ref and return it only after RecordUsage has run; with reservation enabled
  the balance cache is deducted synchronously inside the billing task, so the
  reservation is released only after admission can see the deduction. Dropped
  tasks return their ref immediately. The reservation is renewed every ttl/3
  while the handler runs; after the handler returns it is no longer renewed,
  so the post-handler hold is bounded by one TTL.
- Estimate: use the same billing model (channel mapping + BillingModelSource,
  max over requested/mapped when ambiguous) and ModelPricingResolver (group
  ModelPricing incl. wildcards, channel per_request/image/video/token
  overrides), default/group/user rate + peak multiplier, plus image, video,
  audio and search surcharge kinds. Unpriced requests fail open with a
  throttled log; new billing.inflight_reservation.fail_closed_on_unpriced
  (default false) rejects them instead.
- Wire images, embeddings, web/x search, alpha search, grok media generation,
  grok realtime/voice, OpenAI-platform /v1/messages and ResponsesWebSocket
  (session-level reservation with renewal).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:14:43 -04:00
William DrakeandClaude Opus 5.5 43f88c99aa fix(billing): reserve in-flight balance to prevent concurrent overdraft
Balance-mode admission only checked cached balance > threshold, so N
concurrent expensive requests could all pass and overdraw the user.
Add a Redis in-flight reservation: at admission estimate a conservative
per-request cost (input estimate + output price x max_tokens, times rate
multiplier) and atomically require cached_balance - inflight >= estimate
(first in-flight request always admitted). Reservations are released via
defer on every path and expire by TTL. Fails open on estimation / Redis
errors. Configurable via billing.inflight_reservation (enabled by default).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 14:20:49 -04:00
PMExtra 6073704fd7 fix: omit Codex model catalog for OpenAI groups 2026-09-29 01:50:43 +08:00
PMExtra 6a69dd051a feat: add risk control user allowlist 2026-09-29 01:50:21 +08:00
PMExtra 2840cdeced feat(frontend): hide unsupported clients for Claude Code-only groups 2026-09-29 01:48:23 +08:00
wucm667 aa3a3ea787 feat(dashboard): toggle recent usage between tokens and spending 2026-09-28 14:48:42 +08:00
wucm667 bd48b2b2d2 fix(antigravity): keep compat streams alive before first content 2026-09-28 12:15:27 +08:00