// Package models builds model catalogs for official Codex clients.package models import ( "encoding/json" "sort" "strconv" "strings" "sync" "github.com/router-for-me/CLIProxyAPI/v7/internal/registry") type codexClientModelsPayload struct { Models []map[string]any `json:"models"`} // ProvidersForModelFunc returns the providers registered for a model.type ProvidersForModelFunc func(string) []string // WebSearchCapabilityForModelFunc returns explicit conservative capability// metadata for an exact public model ID. nil means unknown.type WebSearchCapabilityForModelFunc func(string) *bool var ( codexClientModelTemplatesMu sync.Mutex codexClientModelTemplatesLoaded bool codexClientModelTemplatesRevision uint64 codexClientModelTemplates map[string]map[string]any codexClientDefaultTemplate map[string]any codexClientModelTemplatesErr error) var codexClientAllowedReasoningLevels = map[string]struct{}{ "none": {}, "minimal": {}, "low": {}, "medium": {}, "high": {}, "xhigh": {}, "max": {}, "ultra": {},} var codexClientLegacyAllowedReasoningLevels = map[string]struct{}{ "none": {}, "minimal": {}, "low": {}, "medium": {}, "high": {}, "xhigh": {},} // BuildResponse builds a Codex client model response from available models.func BuildResponse(availableModels []map[string]any, providersForModel ProvidersForModelFunc, optimizeMultiAgentV2 bool) map[string]any { return BuildResponseForClient(availableModels, providersForModel, optimizeMultiAgentV2, "")} // BuildResponseForClient builds a Codex client model response from available models// tailored for a specific client version.func BuildResponseForClient(availableModels []map[string]any, providersForModel ProvidersForModelFunc, optimizeMultiAgentV2 bool, clientVersion string) map[string]any { return BuildResponseForClientWithCPACapabilities(availableModels, providersForModel, registry.GetGlobalRegistry().GetResponsesWebSearchCapability, optimizeMultiAgentV2, clientVersion)} // BuildResponseForClientWithCPACapabilities builds a client response while// allowing Home to supply capability metadata independent of the local registry.func BuildResponseForClientWithCPACapabilities(availableModels []map[string]any, providersForModel ProvidersForModelFunc, webSearchCapabilityForModel WebSearchCapabilityForModelFunc, optimizeMultiAgentV2 bool, clientVersion string) map[string]any { return map[string]any{ "models": buildCodexClientModels(availableModels, providersForModel, webSearchCapabilityForModel, optimizeMultiAgentV2, clientVersion), }} func buildCodexClientModels(models []map[string]any, providersForModel ProvidersForModelFunc, webSearchCapabilityForModel WebSearchCapabilityForModelFunc, optimizeMultiAgentV2 bool, clientVersion string) []map[string]any { templates, defaultTemplate, err := loadCodexClientModelTemplates() if err != nil || defaultTemplate == nil { return nil } result := make([]map[string]any, 0, len(models)) for _, model := range models { id := strings.TrimSpace(stringModelValue(model, "id")) if id == "" { continue } metadataID := codexClientMetadataModelID(id) if template, ok := templates[metadataID]; ok { entry := cloneCodexClientModelMap(template) entry["slug"] = id info := registry.LookupModelInfo(id) applyCodexClientModelCapabilities(entry, id, metadataID, info, providersForModel, clientVersion) applyCodexClientDisplayName(entry, model) applyCodexClientDescription(entry, model) applyCodexClientBaseInstructions(entry, model) applyCodexClientMaxContextLengthOverride(entry, model) applyCodexClientMaxTokens(entry, model) if thinkingSupport := codexClientThinkingSupport(model); thinkingSupport != nil { applyCodexClientThinkingMetadata(entry, thinkingSupport, clientVersion) } applyCodexClientProviderCapabilities(entry, id, true, providersForModel) applyCPAWebSearchCapability(entry, id, webSearchCapabilityForModel, clientVersion) sanitizeCodexClientReasoningMetadata(entry, clientVersion) applyCodexClientVisibilityOverride(entry, id) if optimizeMultiAgentV2 { entry["multi_agent_version"] = "v2" } result = append(result, entry) continue } entry := cloneCodexClientModelMap(defaultTemplate) applyCodexClientModelMetadata(entry, id, model, optimizeMultiAgentV2, clientVersion) applyCodexClientMaxTokens(entry, model) applyCodexClientProviderCapabilities(entry, id, false, providersForModel) applyCPAWebSearchCapability(entry, id, webSearchCapabilityForModel, clientVersion) sanitizeCodexClientReasoningMetadata(entry, clientVersion) applyCodexClientVisibilityOverride(entry, id) result = append(result, entry) } applyCodexClientNonTemplatePriorities(result, templates) sort.SliceStable(result, func(i, j int) bool { return codexClientModelPriority(result[i]) < codexClientModelPriority(result[j]) }) return result} func maxCodexClientTemplatePriority(templates map[string]map[string]any) int { maxPriority := 0 for _, template := range templates { priority := codexClientModelPriority(template) if priority > maxPriority { maxPriority = priority } } return maxPriority} func applyCodexClientNonTemplatePriorities(result []map[string]any, templates map[string]map[string]any) { if len(result) == 0 { return } basePriority := maxCodexClientTemplatePriority(templates) type nonTemplateEntry struct { index int displayName string slug string } pending := make([]nonTemplateEntry, 0) for index, entry := range result { slug := stringModelValue(entry, "slug") if _, ok := templates[codexClientMetadataModelID(slug)]; ok { continue } displayName := stringModelValue(entry, "display_name") if displayName == "" { displayName = slug } pending = append(pending, nonTemplateEntry{ index: index, displayName: displayName, slug: slug, }) } sort.SliceStable(pending, func(i, j int) bool { left := strings.ToLower(pending[i].displayName) right := strings.ToLower(pending[j].displayName) if left == right { return pending[i].slug < pending[j].slug } return left < right }) for rank, entry := range pending { result[entry.index]["priority"] = basePriority + 100*(rank+1) }} func loadCodexClientModelTemplates() (map[string]map[string]any, map[string]any, error) { raw, revision := registry.GetCodexClientModelsSnapshot() return loadCodexClientModelTemplatesSnapshot(raw, revision)} func loadCodexClientModelTemplatesSnapshot(raw []byte, revision uint64) (map[string]map[string]any, map[string]any, error) { codexClientModelTemplatesMu.Lock() defer codexClientModelTemplatesMu.Unlock() if codexClientModelTemplatesLoaded && codexClientModelTemplatesRevision == revision { return codexClientModelTemplates, codexClientDefaultTemplate, codexClientModelTemplatesErr } var payload codexClientModelsPayload err := json.Unmarshal(raw, &payload) var templates map[string]map[string]any var defaultTemplate map[string]any if err == nil { templates = make(map[string]map[string]any, len(payload.Models)) for _, model := range payload.Models { slug := strings.TrimSpace(stringModelValue(model, "slug")) if slug == "" { continue } templates[slug] = cloneCodexClientModelMap(model) if slug == "gpt-5.5" { defaultTemplate = cloneCodexClientModelMap(model) } } } codexClientModelTemplatesLoaded = true codexClientModelTemplatesRevision = revision codexClientModelTemplates = templates codexClientDefaultTemplate = defaultTemplate codexClientModelTemplatesErr = err return codexClientModelTemplates, codexClientDefaultTemplate, codexClientModelTemplatesErr} func codexClientMetadataModelID(id string) string { id = strings.TrimSpace(id) if info := registry.LookupModelInfo(id); info != nil { if metadataID := strings.TrimSpace(info.MetadataModelID); metadataID != "" { return metadataID } } if idx := strings.Index(id, "/"); idx != -1 { base := strings.TrimSpace(id[idx+1:]) if info := registry.LookupModelInfo(base); info != nil && strings.TrimSpace(info.MetadataModelID) != "" { return strings.TrimSpace(info.MetadataModelID) } return base } return id} func applyCodexClientDisplayName(entry map[string]any, model map[string]any) { if displayName := stringModelValue(model, "display_name"); displayName != "" { entry["display_name"] = displayName }} func applyCodexClientDescription(entry map[string]any, model map[string]any) { if description := stringModelValue(model, "description"); description != "" { entry["description"] = description }} func applyCodexClientBaseInstructions(entry map[string]any, model map[string]any) { if baseInstructions := stringModelValue(model, "base_instructions"); baseInstructions != "" { entry["base_instructions"] = baseInstructions }} func applyCodexClientModelCapabilities(entry map[string]any, id, metadataID string, info *registry.ModelInfo, providersForModel ProvidersForModelFunc, clientVersion string) { if info != nil && info.Type == registry.OpenAIImageModelType { entry["visibility"] = "hide" delete(entry, "input_modalities") delete(entry, "supports_image_detail_original") return } var providers []string if providersForModel != nil { providers = providersForModel(id) if len(providers) == 0 && strings.Contains(id, "/") { idx := strings.Index(id, "/") base := strings.TrimSpace(id[idx+1:]) providers = providersForModel(base) } } isAlias := metadataID != "" && !strings.EqualFold(id, metadataID) var constrainedModalities []string hasModalitiesConstraint := false for _, p := range providers { pInfo := registry.LookupModelInfo(id, p) if pInfo == nil && strings.Contains(id, "/") { idx := strings.Index(id, "/") pInfo = registry.LookupModelInfo(strings.TrimSpace(id[idx+1:]), p) } if pInfo == nil { continue } isCodex := strings.EqualFold(strings.TrimSpace(p), "codex") if (!isCodex && isAlias) || pInfo.ExplicitInputModalities { mods := pInfo.SupportedInputModalities if mods == nil { mods = []string{} } if !hasModalitiesConstraint { constrainedModalities = append([]string(nil), mods...) hasModalitiesConstraint = true } else { constrainedModalities = intersectStringSlices(constrainedModalities, mods) } } } if !hasModalitiesConstraint && info != nil && info.ExplicitInputModalities { mods := info.SupportedInputModalities if mods == nil { mods = []string{} } constrainedModalities = append([]string(nil), mods...) hasModalitiesConstraint = true } if hasModalitiesConstraint { codexModalities := filterCodexInputModalities(constrainedModalities) entry["input_modalities"] = codexModalities if hasImageModality(codexModalities) { entry["supports_image_detail_original"] = true } else { delete(entry, "supports_image_detail_original") } } var constrainedThinking *registry.ThinkingSupport hasThinkingConstraint := false for _, p := range providers { pInfo := registry.LookupModelInfo(id, p) if pInfo == nil && strings.Contains(id, "/") { idx := strings.Index(id, "/") pInfo = registry.LookupModelInfo(strings.TrimSpace(id[idx+1:]), p) } if pInfo == nil { continue } isCodex := strings.EqualFold(strings.TrimSpace(p), "codex") if (!isCodex && isAlias) || pInfo.ExplicitThinking { hasThinkingConstraint = true pThinking := pInfo.Thinking if pThinking == nil { pThinking = ®istry.ThinkingSupport{Levels: []string{}} } if constrainedThinking == nil { constrainedThinking = pThinking } else { constrainedThinking = intersectThinkingSupport(constrainedThinking, pThinking) } } } if !hasThinkingConstraint && info != nil && info.ExplicitThinking { pThinking := info.Thinking if pThinking == nil { pThinking = ®istry.ThinkingSupport{Levels: []string{}} } constrainedThinking = pThinking hasThinkingConstraint = true } if hasThinkingConstraint && constrainedThinking != nil { applyCodexClientThinkingMetadata(entry, constrainedThinking, clientVersion) }} func intersectThinkingSupport(a, b *registry.ThinkingSupport) *registry.ThinkingSupport { if a == nil { return b } if b == nil { return a } levels := intersectStringSlices(a.Levels, b.Levels) min := a.Min if b.Min > min { min = b.Min } max := a.Max if b.Max > 0 && (max == 0 || b.Max < max) { max = b.Max } return ®istry.ThinkingSupport{ Min: min, Max: max, ZeroAllowed: a.ZeroAllowed && b.ZeroAllowed, DynamicAllowed: a.DynamicAllowed && b.DynamicAllowed, Levels: levels, }} func intersectStringSlices(a, b []string) []string { if len(a) == 0 || len(b) == 0 { return []string{} } bMap := make(map[string]struct{}, len(b)) for _, item := range b { bMap[strings.ToLower(strings.TrimSpace(item))] = struct{}{} } out := make([]string, 0, len(a)) seen := make(map[string]struct{}, len(a)) for _, item := range a { key := strings.ToLower(strings.TrimSpace(item)) if _, inB := bMap[key]; inB { if _, inSeen := seen[key]; !inSeen { seen[key] = struct{}{} out = append(out, item) } } } return out} func applyCodexClientMaxContextLengthOverride(entry map[string]any, model map[string]any) { if maxContextLength := intModelValue(model, "max_context_length"); maxContextLength > 0 { entry["context_window"] = maxContextLength entry["max_context_window"] = maxContextLength }} func applyCodexClientMaxTokens(entry map[string]any, model map[string]any) { if maxCompletionTokens := intModelValue(model, "max_completion_tokens"); maxCompletionTokens > 0 { entry["max_tokens"] = maxCompletionTokens }} func applyCPAWebSearchCapability(entry map[string]any, id string, capabilityForModel WebSearchCapabilityForModelFunc, clientVersion string) { // Templates must not supply runtime capability claims or leak CPA-only fields. delete(entry, "cpa_capabilities") if clientVersion != "cpa" || capabilityForModel == nil { return } if supported := capabilityForModel(strings.TrimSpace(id)); supported != nil { entry["cpa_capabilities"] = map[string]any{"web_search": *supported} }} func applyCodexClientProviderCapabilities(entry map[string]any, id string, isTemplate bool, providersForModel ProvidersForModelFunc) { if !isTemplate { applyCodexClientSearchToolSupport(entry, id, false, providersForModel) return } if providersForModel != nil && !isPureCodexProvider(id, providersForModel) { entry["supports_search_tool"] = false entry["prefer_websockets"] = false delete(entry, "apply_patch_tool_type") entry["service_tiers"] = []any{} delete(entry, "upgrade") delete(entry, "availability_nux") return } applyCodexClientSearchToolSupport(entry, id, isTemplate, providersForModel)} func isPureCodexProvider(id string, providersForModel ProvidersForModelFunc) bool { if providersForModel == nil { return true } providers := providersForModel(id) if len(providers) == 0 && strings.Contains(id, "/") { idx := strings.Index(id, "/") base := strings.TrimSpace(id[idx+1:]) providers = providersForModel(base) } if len(providers) == 0 { return false } for _, provider := range providers { if !strings.EqualFold(strings.TrimSpace(provider), "codex") { return false } } return true} func applyCodexClientSearchToolSupport(entry map[string]any, id string, templateModel bool, providersForModel ProvidersForModelFunc) { supportsSearch, _ := entry["supports_search_tool"].(bool) if !supportsSearch { return } if !templateModel { entry["supports_search_tool"] = false return } if providersForModel == nil { return } providers := providersForModel(id) if len(providers) == 0 && strings.Contains(id, "/") { idx := strings.Index(id, "/") base := strings.TrimSpace(id[idx+1:]) providers = providersForModel(base) } if len(providers) == 0 { entry["supports_search_tool"] = false return } for _, provider := range providers { if !strings.EqualFold(strings.TrimSpace(provider), "codex") { entry["supports_search_tool"] = false return } }} Lines 1–500 of 888. Load more
// Package models builds model catalogs for official Codex clients. package models import ( "encoding/json" "sort" "strconv" "strings" "sync" "github.com/router-for-me/CLIProxyAPI/v7/internal/registry" ) type codexClientModelsPayload struct { Models []map[string]any `json:"models"` } // ProvidersForModelFunc returns the providers registered for a model. type ProvidersForModelFunc func(string) []string // WebSearchCapabilityForModelFunc returns explicit conservative capability // metadata for an exact public model ID. nil means unknown. type WebSearchCapabilityForModelFunc func(string) *bool var ( codexClientModelTemplatesMu sync.Mutex codexClientModelTemplatesLoaded bool codexClientModelTemplatesRevision uint64 codexClientModelTemplates map[string]map[string]any codexClientDefaultTemplate map[string]any codexClientModelTemplatesErr error ) var codexClientAllowedReasoningLevels = map[string]struct{}{ "none": {}, "minimal": {}, "low": {}, "medium": {}, "high": {}, "xhigh": {}, "max": {}, "ultra": {}, } var codexClientLegacyAllowedReasoningLevels = map[string]struct{}{ "none": {}, "minimal": {}, "low": {}, "medium": {}, "high": {}, "xhigh": {}, } // BuildResponse builds a Codex client model response from available models. func BuildResponse(availableModels []map[string]any, providersForModel ProvidersForModelFunc, optimizeMultiAgentV2 bool) map[string]any { return BuildResponseForClient(availableModels, providersForModel, optimizeMultiAgentV2, "") } // BuildResponseForClient builds a Codex client model response from available models // tailored for a specific client version. func BuildResponseForClient(availableModels []map[string]any, providersForModel ProvidersForModelFunc, optimizeMultiAgentV2 bool, clientVersion string) map[string]any { return BuildResponseForClientWithCPACapabilities(availableModels, providersForModel, registry.GetGlobalRegistry().GetResponsesWebSearchCapability, optimizeMultiAgentV2, clientVersion) } // BuildResponseForClientWithCPACapabilities builds a client response while // allowing Home to supply capability metadata independent of the local registry. func BuildResponseForClientWithCPACapabilities(availableModels []map[string]any, providersForModel ProvidersForModelFunc, webSearchCapabilityForModel WebSearchCapabilityForModelFunc, optimizeMultiAgentV2 bool, clientVersion string) map[string]any { return map[string]any{ "models": buildCodexClientModels(availableModels, providersForModel, webSearchCapabilityForModel, optimizeMultiAgentV2, clientVersion), } } func buildCodexClientModels(models []map[string]any, providersForModel ProvidersForModelFunc, webSearchCapabilityForModel WebSearchCapabilityForModelFunc, optimizeMultiAgentV2 bool, clientVersion string) []map[string]any { templates, defaultTemplate, err := loadCodexClientModelTemplates() if err != nil || defaultTemplate == nil { return nil } result := make([]map[string]any, 0, len(models)) for _, model := range models { id := strings.TrimSpace(stringModelValue(model, "id")) if id == "" { continue } metadataID := codexClientMetadataModelID(id) if template, ok := templates[metadataID]; ok { entry := cloneCodexClientModelMap(template) entry["slug"] = id info := registry.LookupModelInfo(id) applyCodexClientModelCapabilities(entry, id, metadataID, info, providersForModel, clientVersion) applyCodexClientDisplayName(entry, model) applyCodexClientDescription(entry, model) applyCodexClientBaseInstructions(entry, model) applyCodexClientMaxContextLengthOverride(entry, model) applyCodexClientMaxTokens(entry, model) if thinkingSupport := codexClientThinkingSupport(model); thinkingSupport != nil { applyCodexClientThinkingMetadata(entry, thinkingSupport, clientVersion) } applyCodexClientProviderCapabilities(entry, id, true, providersForModel) applyCPAWebSearchCapability(entry, id, webSearchCapabilityForModel, clientVersion) sanitizeCodexClientReasoningMetadata(entry, clientVersion) applyCodexClientVisibilityOverride(entry, id) if optimizeMultiAgentV2 { entry["multi_agent_version"] = "v2" } result = append(result, entry) continue } entry := cloneCodexClientModelMap(defaultTemplate) applyCodexClientModelMetadata(entry, id, model, optimizeMultiAgentV2, clientVersion) applyCodexClientMaxTokens(entry, model) applyCodexClientProviderCapabilities(entry, id, false, providersForModel) applyCPAWebSearchCapability(entry, id, webSearchCapabilityForModel, clientVersion) sanitizeCodexClientReasoningMetadata(entry, clientVersion) applyCodexClientVisibilityOverride(entry, id) result = append(result, entry) } applyCodexClientNonTemplatePriorities(result, templates) sort.SliceStable(result, func(i, j int) bool { return codexClientModelPriority(result[i]) < codexClientModelPriority(result[j]) }) return result } func maxCodexClientTemplatePriority(templates map[string]map[string]any) int { maxPriority := 0 for _, template := range templates { priority := codexClientModelPriority(template) if priority > maxPriority { maxPriority = priority } } return maxPriority } func applyCodexClientNonTemplatePriorities(result []map[string]any, templates map[string]map[string]any) { if len(result) == 0 { return } basePriority := maxCodexClientTemplatePriority(templates) type nonTemplateEntry struct { index int displayName string slug string } pending := make([]nonTemplateEntry, 0) for index, entry := range result { slug := stringModelValue(entry, "slug") if _, ok := templates[codexClientMetadataModelID(slug)]; ok { continue } displayName := stringModelValue(entry, "display_name") if displayName == "" { displayName = slug } pending = append(pending, nonTemplateEntry{ index: index, displayName: displayName, slug: slug, }) } sort.SliceStable(pending, func(i, j int) bool { left := strings.ToLower(pending[i].displayName) right := strings.ToLower(pending[j].displayName) if left == right { return pending[i].slug < pending[j].slug } return left < right }) for rank, entry := range pending { result[entry.index]["priority"] = basePriority + 100*(rank+1) } } func loadCodexClientModelTemplates() (map[string]map[string]any, map[string]any, error) { raw, revision := registry.GetCodexClientModelsSnapshot() return loadCodexClientModelTemplatesSnapshot(raw, revision) } func loadCodexClientModelTemplatesSnapshot(raw []byte, revision uint64) (map[string]map[string]any, map[string]any, error) { codexClientModelTemplatesMu.Lock() defer codexClientModelTemplatesMu.Unlock() if codexClientModelTemplatesLoaded && codexClientModelTemplatesRevision == revision { return codexClientModelTemplates, codexClientDefaultTemplate, codexClientModelTemplatesErr } var payload codexClientModelsPayload err := json.Unmarshal(raw, &payload) var templates map[string]map[string]any var defaultTemplate map[string]any if err == nil { templates = make(map[string]map[string]any, len(payload.Models)) for _, model := range payload.Models { slug := strings.TrimSpace(stringModelValue(model, "slug")) if slug == "" { continue } templates[slug] = cloneCodexClientModelMap(model) if slug == "gpt-5.5" { defaultTemplate = cloneCodexClientModelMap(model) } } } codexClientModelTemplatesLoaded = true codexClientModelTemplatesRevision = revision codexClientModelTemplates = templates codexClientDefaultTemplate = defaultTemplate codexClientModelTemplatesErr = err return codexClientModelTemplates, codexClientDefaultTemplate, codexClientModelTemplatesErr } func codexClientMetadataModelID(id string) string { id = strings.TrimSpace(id) if info := registry.LookupModelInfo(id); info != nil { if metadataID := strings.TrimSpace(info.MetadataModelID); metadataID != "" { return metadataID } } if idx := strings.Index(id, "/"); idx != -1 { base := strings.TrimSpace(id[idx+1:]) if info := registry.LookupModelInfo(base); info != nil && strings.TrimSpace(info.MetadataModelID) != "" { return strings.TrimSpace(info.MetadataModelID) } return base } return id } func applyCodexClientDisplayName(entry map[string]any, model map[string]any) { if displayName := stringModelValue(model, "display_name"); displayName != "" { entry["display_name"] = displayName } } func applyCodexClientDescription(entry map[string]any, model map[string]any) { if description := stringModelValue(model, "description"); description != "" { entry["description"] = description } } func applyCodexClientBaseInstructions(entry map[string]any, model map[string]any) { if baseInstructions := stringModelValue(model, "base_instructions"); baseInstructions != "" { entry["base_instructions"] = baseInstructions } } func applyCodexClientModelCapabilities(entry map[string]any, id, metadataID string, info *registry.ModelInfo, providersForModel ProvidersForModelFunc, clientVersion string) { if info != nil && info.Type == registry.OpenAIImageModelType { entry["visibility"] = "hide" delete(entry, "input_modalities") delete(entry, "supports_image_detail_original") return } var providers []string if providersForModel != nil { providers = providersForModel(id) if len(providers) == 0 && strings.Contains(id, "/") { idx := strings.Index(id, "/") base := strings.TrimSpace(id[idx+1:]) providers = providersForModel(base) } } isAlias := metadataID != "" && !strings.EqualFold(id, metadataID) var constrainedModalities []string hasModalitiesConstraint := false for _, p := range providers { pInfo := registry.LookupModelInfo(id, p) if pInfo == nil && strings.Contains(id, "/") { idx := strings.Index(id, "/") pInfo = registry.LookupModelInfo(strings.TrimSpace(id[idx+1:]), p) } if pInfo == nil { continue } isCodex := strings.EqualFold(strings.TrimSpace(p), "codex") if (!isCodex && isAlias) || pInfo.ExplicitInputModalities { mods := pInfo.SupportedInputModalities if mods == nil { mods = []string{} } if !hasModalitiesConstraint { constrainedModalities = append([]string(nil), mods...) hasModalitiesConstraint = true } else { constrainedModalities = intersectStringSlices(constrainedModalities, mods) } } } if !hasModalitiesConstraint && info != nil && info.ExplicitInputModalities { mods := info.SupportedInputModalities if mods == nil { mods = []string{} } constrainedModalities = append([]string(nil), mods...) hasModalitiesConstraint = true } if hasModalitiesConstraint { codexModalities := filterCodexInputModalities(constrainedModalities) entry["input_modalities"] = codexModalities if hasImageModality(codexModalities) { entry["supports_image_detail_original"] = true } else { delete(entry, "supports_image_detail_original") } } var constrainedThinking *registry.ThinkingSupport hasThinkingConstraint := false for _, p := range providers { pInfo := registry.LookupModelInfo(id, p) if pInfo == nil && strings.Contains(id, "/") { idx := strings.Index(id, "/") pInfo = registry.LookupModelInfo(strings.TrimSpace(id[idx+1:]), p) } if pInfo == nil { continue } isCodex := strings.EqualFold(strings.TrimSpace(p), "codex") if (!isCodex && isAlias) || pInfo.ExplicitThinking { hasThinkingConstraint = true pThinking := pInfo.Thinking if pThinking == nil { pThinking = ®istry.ThinkingSupport{Levels: []string{}} } if constrainedThinking == nil { constrainedThinking = pThinking } else { constrainedThinking = intersectThinkingSupport(constrainedThinking, pThinking) } } } if !hasThinkingConstraint && info != nil && info.ExplicitThinking { pThinking := info.Thinking if pThinking == nil { pThinking = ®istry.ThinkingSupport{Levels: []string{}} } constrainedThinking = pThinking hasThinkingConstraint = true } if hasThinkingConstraint && constrainedThinking != nil { applyCodexClientThinkingMetadata(entry, constrainedThinking, clientVersion) } } func intersectThinkingSupport(a, b *registry.ThinkingSupport) *registry.ThinkingSupport { if a == nil { return b } if b == nil { return a } levels := intersectStringSlices(a.Levels, b.Levels) min := a.Min if b.Min > min { min = b.Min } max := a.Max if b.Max > 0 && (max == 0 || b.Max < max) { max = b.Max } return ®istry.ThinkingSupport{ Min: min, Max: max, ZeroAllowed: a.ZeroAllowed && b.ZeroAllowed, DynamicAllowed: a.DynamicAllowed && b.DynamicAllowed, Levels: levels, } } func intersectStringSlices(a, b []string) []string { if len(a) == 0 || len(b) == 0 { return []string{} } bMap := make(map[string]struct{}, len(b)) for _, item := range b { bMap[strings.ToLower(strings.TrimSpace(item))] = struct{}{} } out := make([]string, 0, len(a)) seen := make(map[string]struct{}, len(a)) for _, item := range a { key := strings.ToLower(strings.TrimSpace(item)) if _, inB := bMap[key]; inB { if _, inSeen := seen[key]; !inSeen { seen[key] = struct{}{} out = append(out, item) } } } return out } func applyCodexClientMaxContextLengthOverride(entry map[string]any, model map[string]any) { if maxContextLength := intModelValue(model, "max_context_length"); maxContextLength > 0 { entry["context_window"] = maxContextLength entry["max_context_window"] = maxContextLength } } func applyCodexClientMaxTokens(entry map[string]any, model map[string]any) { if maxCompletionTokens := intModelValue(model, "max_completion_tokens"); maxCompletionTokens > 0 { entry["max_tokens"] = maxCompletionTokens } } func applyCPAWebSearchCapability(entry map[string]any, id string, capabilityForModel WebSearchCapabilityForModelFunc, clientVersion string) { // Templates must not supply runtime capability claims or leak CPA-only fields. delete(entry, "cpa_capabilities") if clientVersion != "cpa" || capabilityForModel == nil { return } if supported := capabilityForModel(strings.TrimSpace(id)); supported != nil { entry["cpa_capabilities"] = map[string]any{"web_search": *supported} } } func applyCodexClientProviderCapabilities(entry map[string]any, id string, isTemplate bool, providersForModel ProvidersForModelFunc) { if !isTemplate { applyCodexClientSearchToolSupport(entry, id, false, providersForModel) return } if providersForModel != nil && !isPureCodexProvider(id, providersForModel) { entry["supports_search_tool"] = false entry["prefer_websockets"] = false delete(entry, "apply_patch_tool_type") entry["service_tiers"] = []any{} delete(entry, "upgrade") delete(entry, "availability_nux") return } applyCodexClientSearchToolSupport(entry, id, isTemplate, providersForModel) } func isPureCodexProvider(id string, providersForModel ProvidersForModelFunc) bool { if providersForModel == nil { return true } providers := providersForModel(id) if len(providers) == 0 && strings.Contains(id, "/") { idx := strings.Index(id, "/") base := strings.TrimSpace(id[idx+1:]) providers = providersForModel(base) } if len(providers) == 0 { return false } for _, provider := range providers { if !strings.EqualFold(strings.TrimSpace(provider), "codex") { return false } } return true } func applyCodexClientSearchToolSupport(entry map[string]any, id string, templateModel bool, providersForModel ProvidersForModelFunc) { supportsSearch, _ := entry["supports_search_tool"].(bool) if !supportsSearch { return } if !templateModel { entry["supports_search_tool"] = false return } if providersForModel == nil { return } providers := providersForModel(id) if len(providers) == 0 && strings.Contains(id, "/") { idx := strings.Index(id, "/") base := strings.TrimSpace(id[idx+1:]) providers = providersForModel(base) } if len(providers) == 0 { entry["supports_search_tool"] = false return } for _, provider := range providers { if !strings.EqualFold(strings.TrimSpace(provider), "codex") { entry["supports_search_tool"] = false return } } }