From 667998db759599555ffb6c6a3bb3a87ef71db40d Mon Sep 17 00:00:00 2001 From: Joshua Barrington Date: Fri, 10 Apr 2026 17:42:55 +0200 Subject: [PATCH 1/3] default the api_type as openai_response for appropriate github copilot models --- pkg/model/provider/provider.go | 33 +++++++++++++++++++ pkg/model/provider/provider_test.go | 49 +++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/pkg/model/provider/provider.go b/pkg/model/provider/provider.go index 749bb9536..5b14c6fde 100644 --- a/pkg/model/provider/provider.go +++ b/pkg/model/provider/provider.go @@ -422,6 +422,9 @@ func applyModelDefaults(cfg *latest.ModelConfig) { return } + // Set appropriate github copilot api_type. + applyGithubCopilotAPIType(cfg) + // No thinking_budget configured — only thinking-only models get a default. switch providerType { case "openai", "openai_chatcompletions", "openai_responses": @@ -467,6 +470,19 @@ func ensureInterleavedThinking(cfg *latest.ModelConfig, providerType string) { } } +// applyGithubCopilotAPIType ensures api_type is set to openai_responses for appropriate models. +func applyGithubCopilotAPIType(cfg *latest.ModelConfig) { + if isGithubCopilotProvider(cfg.Provider) && isCopilotResponsesModel(cfg.Model) { + if cfg.ProviderOpts == nil { + cfg.ProviderOpts = make(map[string]any) + } + // If it's not set, or was set to openai_chatcompletions by the generic fallback, override it. + if apiType, ok := cfg.ProviderOpts["api_type"].(string); !ok || apiType == "" || apiType == "openai_chatcompletions" { + cfg.ProviderOpts["api_type"] = "openai_responses" + } + } +} + // isOpenAIThinkingOnlyModel returns true for OpenAI models that require thinking // to function properly (o-series reasoning models). func isOpenAIThinkingOnlyModel(model string) bool { @@ -529,6 +545,23 @@ func resolveEffectiveProvider(cfg latest.ProviderConfig) string { return "openai" } +func isGithubCopilotProvider(providerType string) bool { + switch providerType { + case "github-copilot": + return true + default: + return false + } +} + +func isCopilotResponsesModel(model string) bool { + codex := map[string]bool{ + "gpt-5.3-codex": true, + "gpt-5.2-codex": true, + } + return codex[model] +} + // isOpenAICompatibleProvider returns true if the provider type uses the OpenAI API protocol. func isOpenAICompatibleProvider(providerType string) bool { switch providerType { diff --git a/pkg/model/provider/provider_test.go b/pkg/model/provider/provider_test.go index 2a678cb23..1e0ef51b7 100644 --- a/pkg/model/provider/provider_test.go +++ b/pkg/model/provider/provider_test.go @@ -4,6 +4,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "github.com/docker/docker-agent/pkg/config/latest" ) func TestCatalogProviders(t *testing.T) { @@ -88,3 +90,50 @@ func TestIsKnownProvider(t *testing.T) { assert.False(t, IsKnownProvider("unknown")) assert.False(t, IsKnownProvider("")) } + +func TestIsGithubCopilotProvider(t *testing.T) { + t.Parallel() + + assert.True(t, isGithubCopilotProvider("github-copilot")) + assert.False(t, isGithubCopilotProvider("openai")) + assert.False(t, isGithubCopilotProvider("")) +} + +func TestIsCopilotResponsesModel(t *testing.T) { + t.Parallel() + + assert.True(t, isCopilotResponsesModel("gpt-5.3-codex")) + assert.True(t, isCopilotResponsesModel("gpt-5.2-codex")) + assert.False(t, isCopilotResponsesModel("gpt-4o")) + assert.False(t, isCopilotResponsesModel("claude-sonnet-4-5")) + assert.False(t, isCopilotResponsesModel("")) +} + +func TestGithubCopilotApiType(t *testing.T) { + cfg := &latest.ModelConfig{ + Provider: "github-copilot", + Model: "gpt-5.3-codex", + } + + enhancedCfg := applyProviderDefaults(cfg, nil) + + apiType := resolveProviderType(enhancedCfg) + + if apiType != "openai_responses" { + t.Errorf("Expected api_type to be 'openai_responses', got '%s'", apiType) + } + + // test when it is a custom provider + customProviders := map[string]latest.ProviderConfig{ + "github-copilot": { + Provider: "github-copilot", + }, + } + + enhancedCfg2 := applyProviderDefaults(cfg, customProviders) + apiType2 := resolveProviderType(enhancedCfg2) + + if apiType2 != "openai_responses" { + t.Errorf("Expected api_type to be 'openai_responses', got '%s'", apiType2) + } +} From f3eb4d2a7ae208feb14483f5499891663bd55688 Mon Sep 17 00:00:00 2001 From: Joshua Barrington Date: Fri, 10 Apr 2026 18:57:02 +0200 Subject: [PATCH 2/3] apply copilot api type earlier in defaults setup --- pkg/model/provider/provider.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/model/provider/provider.go b/pkg/model/provider/provider.go index 5b14c6fde..afc2f69b3 100644 --- a/pkg/model/provider/provider.go +++ b/pkg/model/provider/provider.go @@ -406,6 +406,9 @@ func applyProviderDefaults(cfg *latest.ModelConfig, customProviders map[string]l // // NOTE: max_tokens is NOT set here; see teamloader and runtime/model_switcher. func applyModelDefaults(cfg *latest.ModelConfig) { + // Set appropriate github copilot api_type. + applyGithubCopilotAPIType(cfg) + // Explicitly disabled → normalise to nil so providers never see it. if cfg.ThinkingBudget.IsDisabled() { cfg.ThinkingBudget = nil @@ -422,9 +425,6 @@ func applyModelDefaults(cfg *latest.ModelConfig) { return } - // Set appropriate github copilot api_type. - applyGithubCopilotAPIType(cfg) - // No thinking_budget configured — only thinking-only models get a default. switch providerType { case "openai", "openai_chatcompletions", "openai_responses": From 1f80c3b864dc4837b255b269a1b0a512b45cc88c Mon Sep 17 00:00:00 2001 From: David Gageot Date: Mon, 13 Apr 2026 11:51:07 +0200 Subject: [PATCH 3/3] Update pkg/model/provider/provider.go --- pkg/model/provider/provider.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pkg/model/provider/provider.go b/pkg/model/provider/provider.go index afc2f69b3..21f4b38bb 100644 --- a/pkg/model/provider/provider.go +++ b/pkg/model/provider/provider.go @@ -546,12 +546,7 @@ func resolveEffectiveProvider(cfg latest.ProviderConfig) string { } func isGithubCopilotProvider(providerType string) bool { - switch providerType { - case "github-copilot": - return true - default: - return false - } + return providerType == "github-copilot" } func isCopilotResponsesModel(model string) bool {