mirror of
https://mirror.skon.top/github.com/router-for-me/CLIProxyAPI
synced 2026-05-01 00:30:55 +08:00
feat(models): add hardcoded GPT-Image-2 model support in Codex
- Added `GPT-Image-2` as a built-in model to avoid dependency on remote updates for Codex. - Updated model tier functions (`CodexFree`, `CodexTeam`, etc.) to include built-in models via `WithCodexBuiltins`. - Introduced new handlers for image generation and edit operations under `OpenAIAPIHandler`. - Extended tests to validate 503 response for unsupported image model requests.
This commit is contained in:
@@ -344,6 +344,8 @@ func (s *Server) setupRoutes() {
|
||||
v1.GET("/models", s.unifiedModelsHandler(openaiHandlers, claudeCodeHandlers))
|
||||
v1.POST("/chat/completions", openaiHandlers.ChatCompletions)
|
||||
v1.POST("/completions", openaiHandlers.Completions)
|
||||
v1.POST("/images/generations", openaiHandlers.ImagesGenerations)
|
||||
v1.POST("/images/edits", openaiHandlers.ImagesEdits)
|
||||
v1.POST("/messages", claudeCodeHandlers.ClaudeMessages)
|
||||
v1.POST("/messages/count_tokens", claudeCodeHandlers.ClaudeCountTokens)
|
||||
v1.GET("/responses", openaiResponsesHandlers.ResponsesWebsocket)
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const codexBuiltinImageModelID = "gpt-image-2"
|
||||
|
||||
// staticModelsJSON mirrors the top-level structure of models.json.
|
||||
type staticModelsJSON struct {
|
||||
Claude []*ModelInfo `json:"claude"`
|
||||
@@ -48,22 +50,22 @@ func GetAIStudioModels() []*ModelInfo {
|
||||
|
||||
// GetCodexFreeModels returns model definitions for the Codex free plan tier.
|
||||
func GetCodexFreeModels() []*ModelInfo {
|
||||
return cloneModelInfos(getModels().CodexFree)
|
||||
return WithCodexBuiltins(cloneModelInfos(getModels().CodexFree))
|
||||
}
|
||||
|
||||
// GetCodexTeamModels returns model definitions for the Codex team plan tier.
|
||||
func GetCodexTeamModels() []*ModelInfo {
|
||||
return cloneModelInfos(getModels().CodexTeam)
|
||||
return WithCodexBuiltins(cloneModelInfos(getModels().CodexTeam))
|
||||
}
|
||||
|
||||
// GetCodexPlusModels returns model definitions for the Codex plus plan tier.
|
||||
func GetCodexPlusModels() []*ModelInfo {
|
||||
return cloneModelInfos(getModels().CodexPlus)
|
||||
return WithCodexBuiltins(cloneModelInfos(getModels().CodexPlus))
|
||||
}
|
||||
|
||||
// GetCodexProModels returns model definitions for the Codex pro plan tier.
|
||||
func GetCodexProModels() []*ModelInfo {
|
||||
return cloneModelInfos(getModels().CodexPro)
|
||||
return WithCodexBuiltins(cloneModelInfos(getModels().CodexPro))
|
||||
}
|
||||
|
||||
// GetKimiModels returns the standard Kimi (Moonshot AI) model definitions.
|
||||
@@ -76,6 +78,71 @@ func GetAntigravityModels() []*ModelInfo {
|
||||
return cloneModelInfos(getModels().Antigravity)
|
||||
}
|
||||
|
||||
// WithCodexBuiltins injects hard-coded Codex-only model definitions that should
|
||||
// not depend on remote models.json updates. Built-ins replace any matching IDs
|
||||
// already present in the provided slice.
|
||||
func WithCodexBuiltins(models []*ModelInfo) []*ModelInfo {
|
||||
return upsertModelInfos(models, codexBuiltinImageModelInfo())
|
||||
}
|
||||
|
||||
func codexBuiltinImageModelInfo() *ModelInfo {
|
||||
return &ModelInfo{
|
||||
ID: codexBuiltinImageModelID,
|
||||
Object: "model",
|
||||
Created: 1704067200, // 2024-01-01
|
||||
OwnedBy: "openai",
|
||||
Type: "openai",
|
||||
DisplayName: "GPT Image 2",
|
||||
Version: codexBuiltinImageModelID,
|
||||
}
|
||||
}
|
||||
|
||||
func upsertModelInfos(models []*ModelInfo, extras ...*ModelInfo) []*ModelInfo {
|
||||
if len(extras) == 0 {
|
||||
return models
|
||||
}
|
||||
|
||||
extraIDs := make(map[string]struct{}, len(extras))
|
||||
extraList := make([]*ModelInfo, 0, len(extras))
|
||||
for _, extra := range extras {
|
||||
if extra == nil {
|
||||
continue
|
||||
}
|
||||
id := strings.TrimSpace(extra.ID)
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
key := strings.ToLower(id)
|
||||
if _, exists := extraIDs[key]; exists {
|
||||
continue
|
||||
}
|
||||
extraIDs[key] = struct{}{}
|
||||
extraList = append(extraList, cloneModelInfo(extra))
|
||||
}
|
||||
|
||||
if len(extraList) == 0 {
|
||||
return models
|
||||
}
|
||||
|
||||
filtered := make([]*ModelInfo, 0, len(models)+len(extraList))
|
||||
for _, model := range models {
|
||||
if model == nil {
|
||||
continue
|
||||
}
|
||||
id := strings.TrimSpace(model.ID)
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
if _, exists := extraIDs[strings.ToLower(id)]; exists {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, model)
|
||||
}
|
||||
|
||||
filtered = append(filtered, extraList...)
|
||||
return filtered
|
||||
}
|
||||
|
||||
// cloneModelInfos returns a shallow copy of the slice with each element deep-cloned.
|
||||
func cloneModelInfos(models []*ModelInfo) []*ModelInfo {
|
||||
if len(models) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user