diff --git a/internal/registry/model_definitions.go b/internal/registry/model_definitions.go index 06921a02..2c16d5bc 100644 --- a/internal/registry/model_definitions.go +++ b/internal/registry/model_definitions.go @@ -376,7 +376,7 @@ func GetGitHubCopilotModels() []*ModelInfo { ContextLength: 200000, MaxCompletionTokens: 32768, SupportedEndpoints: []string{"/responses"}, - Thinking: &ThinkingSupport{Levels: []string{"low", "medium", "high", "xhigh"}}, + Thinking: &ThinkingSupport{Levels: []string{"none", "low", "medium", "high", "xhigh"}}, }, { ID: "claude-haiku-4.5", diff --git a/internal/runtime/executor/github_copilot_executor.go b/internal/runtime/executor/github_copilot_executor.go index abdb3006..a5770e07 100644 --- a/internal/runtime/executor/github_copilot_executor.go +++ b/internal/runtime/executor/github_copilot_executor.go @@ -577,23 +577,24 @@ func useGitHubCopilotResponsesEndpoint(sourceFormat sdktranslator.Format, model return true } baseModel := strings.ToLower(thinking.ParseSuffix(model).ModelName) - if info := registry.GetGlobalRegistry().GetModelInfo(baseModel, ""); info != nil { - if len(info.SupportedEndpoints) > 0 && !containsEndpoint(info.SupportedEndpoints, githubCopilotChatPath) && containsEndpoint(info.SupportedEndpoints, githubCopilotResponsesPath) { - return true - } + if info := registry.GetGlobalRegistry().GetModelInfo(baseModel, githubCopilotAuthType); info != nil { + return len(info.SupportedEndpoints) > 0 && !containsEndpoint(info.SupportedEndpoints, githubCopilotChatPath) && containsEndpoint(info.SupportedEndpoints, githubCopilotResponsesPath) } - for _, info := range registry.GetGitHubCopilotModels() { - if info == nil || !strings.EqualFold(info.ID, baseModel) { - continue - } - if len(info.SupportedEndpoints) > 0 && !containsEndpoint(info.SupportedEndpoints, githubCopilotChatPath) && containsEndpoint(info.SupportedEndpoints, githubCopilotResponsesPath) { - return true - } - break + if info := lookupGitHubCopilotStaticModelInfo(baseModel); info != nil { + return len(info.SupportedEndpoints) > 0 && !containsEndpoint(info.SupportedEndpoints, githubCopilotChatPath) && containsEndpoint(info.SupportedEndpoints, githubCopilotResponsesPath) } return strings.Contains(baseModel, "codex") } +func lookupGitHubCopilotStaticModelInfo(model string) *registry.ModelInfo { + for _, info := range registry.GetStaticModelDefinitionsByChannel(githubCopilotAuthType) { + if info != nil && strings.EqualFold(info.ID, model) { + return info + } + } + return nil +} + func containsEndpoint(endpoints []string, endpoint string) bool { for _, item := range endpoints { if item == endpoint { diff --git a/internal/runtime/executor/github_copilot_executor_test.go b/internal/runtime/executor/github_copilot_executor_test.go index d3ce194a..dfc332f2 100644 --- a/internal/runtime/executor/github_copilot_executor_test.go +++ b/internal/runtime/executor/github_copilot_executor_test.go @@ -5,6 +5,7 @@ import ( "strings" "testing" + "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" sdktranslator "github.com/router-for-me/CLIProxyAPI/v6/sdk/translator" "github.com/tidwall/gjson" ) @@ -77,6 +78,22 @@ func TestUseGitHubCopilotResponsesEndpoint_RegistryResponsesOnlyModel(t *testing } } +func TestUseGitHubCopilotResponsesEndpoint_DynamicRegistryWinsOverStatic(t *testing.T) { + t.Parallel() + + reg := registry.GetGlobalRegistry() + clientID := "github-copilot-test-client" + reg.RegisterClient(clientID, "github-copilot", []*registry.ModelInfo{{ + ID: "gpt-5.4", + SupportedEndpoints: []string{"/chat/completions", "/responses"}, + }}) + defer reg.UnregisterClient(clientID) + + if useGitHubCopilotResponsesEndpoint(sdktranslator.FromString("openai"), "gpt-5.4") { + t.Fatal("expected dynamic registry definition to take precedence over static fallback") + } +} + func TestUseGitHubCopilotResponsesEndpoint_DefaultChat(t *testing.T) { t.Parallel() if useGitHubCopilotResponsesEndpoint(sdktranslator.FromString("openai"), "claude-3-5-sonnet") {