feat(codex): pinned-accounts Codex model manifest for OpenAI groups

This commit is contained in:
Zero Clover
2026-09-05 00:10:24 +08:00
parent b1748c4ea9
commit 1e28ef5942
41 changed files with 2308 additions and 68 deletions
@@ -1,6 +1,7 @@
package handler
import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
@@ -50,6 +51,44 @@ func (h *OpenAIGatewayHandler) CodexModels(c *gin.Context) {
return
}
// 固定账号分支:开启后只用选定账号拉取 manifest,不经过调度器;
// 全部不可用/全部失败时按 FallbackToScheduler 决定回退调度器或返回错误。
if apiKey.Group.Platform == service.PlatformOpenAI &&
apiKey.Group.CodexModelsManifestConfig.Enabled &&
len(apiKey.Group.CodexModelsManifestConfig.AccountIDs) > 0 {
pinnedManifest, pinnedAccount, pinnedErr := h.gatewayService.FetchPinnedCodexModelsManifest(
c.Request.Context(),
apiKey.Group,
c.Query("client_version"),
)
if pinnedErr != nil {
if c.Request.Context().Err() != nil {
return
}
if !apiKey.Group.CodexModelsManifestConfig.FallbackToScheduler {
if errors.Is(pinnedErr, service.ErrNoPinnedCodexModelsAccounts) {
h.errorResponse(c, http.StatusServiceUnavailable, "upstream_error", "No available pinned OpenAI accounts")
return
}
h.errorResponse(c, infraerrors.Code(pinnedErr), "upstream_error", infraerrors.Message(pinnedErr))
return
}
// 回退开启:跌入下方调度器循环。
} else {
// 让 ops 错误日志携带实际拉取成功的首个固定账号。
setOpsSelectedAccount(c, pinnedAccount.ID, pinnedAccount.Platform)
if err := h.gatewayService.MergeGroupConfiguredCodexModels(c.Request.Context(), apiKey.Group, pinnedManifest, ifNoneMatch); err != nil {
h.errorResponse(c, http.StatusInternalServerError, "api_error", "Failed to build Codex models manifest")
return
}
if c.Request.Context().Err() != nil {
return
}
writeCodexModelsManifestResponse(c, pinnedManifest)
return
}
}
maxAccountSwitches := h.maxAccountSwitches
if maxAccountSwitches <= 0 {
maxAccountSwitches = 3