feat(openapi): auto-generate OpenAPI spec via Fuego - #3073
Closed
0-don wants to merge 5406 commits into
Closed
Conversation
fix: /v1/chat/completions -> /v1/responses json_schema
将散落在多个文件中的预扣费/结算/退款逻辑抽象为统一的 BillingSession 生命周期管理: - 新增 BillingSettler 接口 (relay/common/billing.go) 避免循环引用 - 新增 FundingSource 接口 + WalletFunding / SubscriptionFunding 实现 (service/funding_source.go) - 新增 BillingSession 封装预扣/结算/退款原子操作 (service/billing_session.go) - 新增 SettleBilling 统一结算辅助函数,替换各 handler 中的 quotaDelta 模式 - 重写 PreConsumeBilling 为 BillingSession 工厂入口 - controller/relay.go 退款守卫改用 BillingSession.Refund() 修复的 Bug: - 令牌额度泄漏:PreConsumeTokenQuota 成功但 DecreaseUserQuota 失败时未回滚 - 订阅退款遗漏:FinalPreConsumedQuota=0 但 SubscriptionPreConsumed>0 时跳过退款 - 订阅多扣费:subConsume 强制为 1 但 FinalPreConsumedQuota 不同步 - 退款路径不统一:钱包/订阅退款逻辑现统一由 FundingSource.Refund 分派
- Settle 部分失败保护:新增 fundingSettled 标记,资金来源提交后 令牌调整失败不再导致 Refund 误退已结算的资金 - 订阅多扣费修复:trySubscription 传 subConsume 而非 preConsumedQuota 给 preConsume,保证三者(amount/preConsume/FinalPreConsumedQuota)一致 - 令牌回滚错误记录:preConsume 中 funding 失败时令牌回滚错误不再丢弃 - 移除钱包路径死代码:用户额度不足的 strings.Contains 匹配不可能命中 - WalletFunding.Refund 不重试:IncreaseUserQuota 非幂等,重试会多退
…e recharge card tabs - Defaulting to subscriptions when available and avoiding initial flash when no plans exist. - Adjust the wide-screen layout to place wallet and invite sections side by side, simplify the subscription header and controls, and add padding to prevent card borders from clipping. - Update related i18n strings by adding the new tab label and removing the obsolete subscription blurb.
…-when-no-plans ✨ refactor(wallet): Top-up layout to embed subscription plans into the recharge card tabs
refactor: 抽象统一计费会话 BillingSession
Add a lightweight active-subscription check to skip subscription pre-consume when none exist, reducing unnecessary transactions and locks. In the subscription UI, disable subscription-first options when no active plan is available, show the effective fallback to wallet with a clear notice, and distinguish “invalidated” from “expired” states. Update i18n strings across supported locales to reflect the new messages and status labels.
Aligns the error variable types in the subscription-first path so that quota fallback checks use the correct NewAPIError. This prevents build failures and preserves the intended wallet fallback when subscription pre-consume returns an insufficient quota error.
Routes quota alerts through a subscription-specific check when billing from subscriptions, preventing wallet-based thresholds from triggering false warnings. Updates the notification settings description and localization keys to clarify that both wallet and subscription balances are monitored.
🔔 feat: Add subscription-aware quota notifications and update UI copy
…-fallback ✨ chore: Improve subscription billing fallback and UI states
当上游为 AWS Bedrock 时,message_delta 的 usage 可能缺少 input_tokens、 cache_creation_input_tokens、cache_read_input_tokens 等字段,导致与原生 Anthropic 格式不一致。从 message_start 积累的 claudeInfo 中补全这些字段后 重新序列化,确保客户端收到一致的 usage 格式。
Modified the formatUserLogs function to include a startIdx parameter, allowing for more flexible log ID assignment. Updated calls to this function in GetLogByTokenId and GetUserLogs to pass the appropriate starting index.
feat: add Codex channel disclaimer (i18n, OpenAI terms)
feat: Force beta=true parameter for Anthropic channel
feat(oauth): implement custom OAuth provider
fix: Claude stream block index/type transitions
fix: add paragraph breaks between reasoning summary chunks
# Conflicts: # service/openaicompat/chat_to_responses.go
feat: channel test with stream=true
fix: 使用openai兼容接口调用部分渠道在最终端点为claude原生端点下还是走了openai扣减input_token的逻辑
fix: 补全 streaming message_delta 事件缺失的 input_tokens 和 cache 相关字段
feat: /v1/messages -> /v1/responses
…rable feat: make 5m cache-creation ratio configurable
…eader-append feat:support $keep_only_declared and deduped $append for header override
0-don
force-pushed
the
feat/openapi-fuego
branch
2 times, most recently
from
March 10, 2026 18:47
30eb261 to
f071a31
Compare
chore: update model lists for frequently used channels
0-don
force-pushed
the
feat/openapi-fuego
branch
from
March 12, 2026 23:17
f071a31 to
93cfaf5
Compare
…tion links and submission checks
0-don
force-pushed
the
feat/openapi-fuego
branch
from
March 14, 2026 15:59
93cfaf5 to
30bd781
Compare
Round remaining balance
enhance channel key viewing
…cff3f3572f535919 feat: add logs content tooltip
Replace static docs/openapi/*.json files with auto-generated OpenAPI spec using Fuego's fuegogin adapter. Gin remains the HTTP runtime; Fuego only generates the spec at startup. Key changes: - Add dto/router.go wrapper providing typed route registration helpers (Get, PostB, PutB, Delete, etc.) that register in both Gin and the OpenAPI spec simultaneously - Add dto/responses.go with Response[T], Ok/Fail helpers, PageData[T] for consistent typed API responses - Refactor all controllers from raw gin.Context to Fuego typed handlers with proper request/response types - Add 25+ DTO files (channel, token, user, subscription, deployment, performance, custom_oauth, etc.) - Move shared types to types/ package to break dto>model>relay import cycle (channel_settings, user_settings, openai_video, oauth_errors) - Add router/openapi.go for spec serving (/openapi.json) and Scalar UI (/swagger) - Gated by ENABLE_OPENAPI=true env var (off by default) - Bump Go to 1.25+, add go-fuego/fuego dependency Stats: 201 routes use native Fuego typed handlers, 92 remain as raw gin.HandlerFunc (relay streaming, OAuth sessions, webhooks) Related: #907, #2348, #2353, #1128, #2502
0-don
force-pushed
the
feat/openapi-fuego
branch
from
March 16, 2026 23:29
30bd781 to
24f3655
Compare
Contributor
Author
|
Addressed remaining CodeRabbit feedback:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replace static
docs/openapi/api.jsonanddocs/openapi/relay.jsonwith auto-generated OpenAPI spec via Fuego. Gin remains the HTTP runtime; Fuego only generates the spec at startup. Gated byENABLE_OPENAPI=trueenv var (off by default).Related: #907, #2348, #2353, #1128, #2502
This supersedes the static JSON approach from #2348/#2353. Specs are now generated from code, so they never go stale.
How it works
gin.HandlerFunc(relay streaming, OAuth sessions, webhooks, redirects that need raw*gin.Context)GinResp[T]()/GinBody[T]()annotations document raw Gin routes in the OpenAPI spec regardlessGET /openapi.json(spec),GET /swagger(Scalar UI)Changes
New
dto/package (25+ files)dto/router.go: wrapper providing typed route registration helpers (Get,PostB,PutB,Delete, etc.) that register in both Gin and the OpenAPI spec simultaneouslydto/responses.go:Response[T],Ok/Failhelpers,PageData[T]for consistent typed API responsesController refactoring (all controllers)
gin.Contextto Fuego typed handlers with proper request/response typeswithJSONBody()helper ensures all body-accepting routes useapplication/jsonin the specGinBody[T]()annotates remaining raw Gin handlers with typed request bodiesType reorganization
types/package to breakdto > model > relay/common > dtoimport cyclechannel_settings.go,user_settings.go,openai_video.gomoved fromdto/totypes/dto/type_aliases.gofor backwards compatibilityOther
router/openapi.go: spec serving and Scalar UI setupgo-fuego/fuegodependencymodel/user.go: addomitemptyto Password validate tag (Fuego runs validation before handler)Known limitations (all acceptable)
fuegogin.Params()is a stub: all 41 call sites usedto.ParseParams[P](c)insteadsanitizeSchemaNamesdoes raw string replacement: no type-name collisions exist todayOk[T]returns*Response[T]: workaround for Go 1.25.x ICE with large generic typesTest plan
go build ./...succeedsENABLE_OPENAPI=true:/openapi.jsonreturns valid spec,/swaggershows Scalar UIENABLE_OPENAPI=false(default): routes still work, no spec served