mirror of
https://gh-proxy.org/https://github.com/klinsmaya/CLIProxyAPI.git
synced 2026-11-08 01:16:47 +08:00
fix(codex): gate tool search by model providers
This commit is contained in:
@@ -13,6 +13,8 @@ type codexClientModelsPayload struct {
|
||||
Models []map[string]any `json:"models"`
|
||||
}
|
||||
|
||||
type codexClientModelProvidersFunc func(string) []string
|
||||
|
||||
var (
|
||||
codexClientModelTemplatesMu sync.Mutex
|
||||
codexClientModelTemplatesLoaded bool
|
||||
@@ -33,16 +35,20 @@ var codexClientAllowedReasoningLevels = map[string]struct{}{
|
||||
}
|
||||
|
||||
func (h *OpenAIAPIHandler) codexClientModelsResponse() map[string]any {
|
||||
return CodexClientModelsResponse(h.Models())
|
||||
return codexClientModelsResponse(h.Models(), registry.GetGlobalRegistry().GetModelProviders)
|
||||
}
|
||||
|
||||
func CodexClientModelsResponse(models []map[string]any) map[string]any {
|
||||
return codexClientModelsResponse(models, nil)
|
||||
}
|
||||
|
||||
func codexClientModelsResponse(models []map[string]any, providersForModel codexClientModelProvidersFunc) map[string]any {
|
||||
return map[string]any{
|
||||
"models": buildCodexClientModels(models),
|
||||
"models": buildCodexClientModels(models, providersForModel),
|
||||
}
|
||||
}
|
||||
|
||||
func buildCodexClientModels(models []map[string]any) []map[string]any {
|
||||
func buildCodexClientModels(models []map[string]any, providersForModel codexClientModelProvidersFunc) []map[string]any {
|
||||
templates, defaultTemplate, err := loadCodexClientModelTemplates()
|
||||
if err != nil || defaultTemplate == nil {
|
||||
return nil
|
||||
@@ -58,6 +64,7 @@ func buildCodexClientModels(models []map[string]any) []map[string]any {
|
||||
if template, ok := templates[id]; ok {
|
||||
entry := cloneCodexClientModelMap(template)
|
||||
applyCodexClientDisplayName(entry, model)
|
||||
applyCodexClientSearchToolSupport(entry, id, true, providersForModel)
|
||||
sanitizeCodexClientReasoningMetadata(entry)
|
||||
applyCodexClientVisibilityOverride(entry, id)
|
||||
result = append(result, entry)
|
||||
@@ -66,6 +73,7 @@ func buildCodexClientModels(models []map[string]any) []map[string]any {
|
||||
|
||||
entry := cloneCodexClientModelMap(defaultTemplate)
|
||||
applyCodexClientModelMetadata(entry, id, model)
|
||||
applyCodexClientSearchToolSupport(entry, id, false, providersForModel)
|
||||
sanitizeCodexClientReasoningMetadata(entry)
|
||||
applyCodexClientVisibilityOverride(entry, id)
|
||||
result = append(result, entry)
|
||||
@@ -178,6 +186,32 @@ func applyCodexClientDisplayName(entry map[string]any, model map[string]any) {
|
||||
}
|
||||
}
|
||||
|
||||
func applyCodexClientSearchToolSupport(entry map[string]any, id string, templateModel bool, providersForModel codexClientModelProvidersFunc) {
|
||||
supportsSearch, _ := entry["supports_search_tool"].(bool)
|
||||
if !supportsSearch {
|
||||
return
|
||||
}
|
||||
|
||||
if providersForModel == nil {
|
||||
if !templateModel {
|
||||
entry["supports_search_tool"] = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
providers := providersForModel(id)
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applyCodexClientModelMetadata(entry map[string]any, id string, model map[string]any) {
|
||||
info := registry.LookupModelInfo(id)
|
||||
|
||||
|
||||
@@ -143,6 +143,75 @@ func TestCodexClientModelsResponse_AppliesDisplayNameToTemplateModel(t *testing.
|
||||
}
|
||||
}
|
||||
|
||||
func TestCodexClientModelsResponse_DisablesSearchToolForSynthesizedModels(t *testing.T) {
|
||||
resp := CodexClientModelsResponse([]map[string]any{
|
||||
{"id": "custom-openai-compatible-model"},
|
||||
{"id": "gpt-5.5"},
|
||||
})
|
||||
models, ok := resp["models"].([]map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("models type = %T, want []map[string]any", resp["models"])
|
||||
}
|
||||
|
||||
bySlug := make(map[string]map[string]any, len(models))
|
||||
for _, model := range models {
|
||||
bySlug[stringModelValue(model, "slug")] = model
|
||||
}
|
||||
|
||||
custom := bySlug["custom-openai-compatible-model"]
|
||||
if custom == nil {
|
||||
t.Fatal("expected synthesized custom model entry")
|
||||
}
|
||||
if got, ok := custom["supports_search_tool"].(bool); !ok || got {
|
||||
t.Fatalf("custom supports_search_tool = %#v, want false", custom["supports_search_tool"])
|
||||
}
|
||||
|
||||
official := bySlug["gpt-5.5"]
|
||||
if official == nil {
|
||||
t.Fatal("expected official template model entry")
|
||||
}
|
||||
if got, ok := official["supports_search_tool"].(bool); !ok || !got {
|
||||
t.Fatalf("official supports_search_tool = %#v, want true", official["supports_search_tool"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCodexClientModelsResponse_UsesProviderSearchToolSupport(t *testing.T) {
|
||||
providers := map[string][]string{
|
||||
"new-codex-model": {"codex"},
|
||||
"gpt-5.5": {"openai-compatible-deepseek"},
|
||||
"gpt-5.4": {"codex", "xai"},
|
||||
"gpt-5.6-sol": {"codex"},
|
||||
}
|
||||
resp := codexClientModelsResponse([]map[string]any{
|
||||
{"id": "new-codex-model"},
|
||||
{"id": "gpt-5.5"},
|
||||
{"id": "gpt-5.4"},
|
||||
{"id": "gpt-5.6-sol"},
|
||||
}, func(id string) []string {
|
||||
return providers[id]
|
||||
})
|
||||
models, ok := resp["models"].([]map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("models type = %T, want []map[string]any", resp["models"])
|
||||
}
|
||||
|
||||
bySlug := make(map[string]map[string]any, len(models))
|
||||
for _, model := range models {
|
||||
bySlug[stringModelValue(model, "slug")] = model
|
||||
}
|
||||
|
||||
for _, slug := range []string{"new-codex-model", "gpt-5.6-sol"} {
|
||||
if got, ok := bySlug[slug]["supports_search_tool"].(bool); !ok || !got {
|
||||
t.Errorf("%s supports_search_tool = %#v, want true", slug, bySlug[slug]["supports_search_tool"])
|
||||
}
|
||||
}
|
||||
for _, slug := range []string{"gpt-5.5", "gpt-5.4"} {
|
||||
if got, ok := bySlug[slug]["supports_search_tool"].(bool); !ok || got {
|
||||
t.Errorf("%s supports_search_tool = %#v, want false", slug, bySlug[slug]["supports_search_tool"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCodexClientModelsResponse_PreservesUltraReasoningEffort(t *testing.T) {
|
||||
resp := CodexClientModelsResponse([]map[string]any{{"id": "gpt-5.6-sol"}})
|
||||
models, ok := resp["models"].([]map[string]any)
|
||||
|
||||
Reference in New Issue
Block a user