From b5756bf72907e8d18744cac8710cabc05608cc0e Mon Sep 17 00:00:00 2001 From: ultraplan-bit <248279703+ultraplan-bit@users.noreply.github.com> Date: Tue, 17 Feb 2026 21:17:18 +0800 Subject: [PATCH 1/6] Fix Copilot 0x model incorrectly consuming premium requests Change Openai-Intent header from "conversation-edits" to "conversation-panel" to avoid triggering GitHub's premium execution path, which caused included models (0x multiplier) to be billed as premium requests. Co-Authored-By: Claude Opus 4.6 --- internal/runtime/executor/github_copilot_executor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/runtime/executor/github_copilot_executor.go b/internal/runtime/executor/github_copilot_executor.go index 173c4752..95f8ef17 100644 --- a/internal/runtime/executor/github_copilot_executor.go +++ b/internal/runtime/executor/github_copilot_executor.go @@ -39,7 +39,7 @@ const ( copilotEditorVersion = "vscode/1.107.0" copilotPluginVersion = "copilot-chat/0.35.0" copilotIntegrationID = "vscode-chat" - copilotOpenAIIntent = "conversation-edits" + copilotOpenAIIntent = "conversation-panel" ) // GitHubCopilotExecutor handles requests to the GitHub Copilot API. From 5726a99c801be1b5331e0e6c467c960daf54bb10 Mon Sep 17 00:00:00 2001 From: ultraplan-bit <248279703+ultraplan-bit@users.noreply.github.com> Date: Tue, 17 Feb 2026 22:11:17 +0800 Subject: [PATCH 2/6] Improve Copilot provider based on ericc-ch/copilot-api comparison - Fix X-Initiator detection: check for any assistant/tool role in messages instead of only the last message role, matching the correct agent detection for multi-turn tool conversations - Add x-github-api-version: 2025-04-01 header for API compatibility - Support Business/Enterprise accounts by using Endpoints.API from the Copilot token response instead of hardcoded base URL - Fix Responses API vision detection: detect vision content before input normalization removes the messages array - Add 8 test cases covering the above fixes Co-Authored-By: Claude Opus 4.6 --- .../executor/github_copilot_executor.go | 68 +++++++++------ .../executor/github_copilot_executor_test.go | 84 +++++++++++++++++++ 2 files changed, 126 insertions(+), 26 deletions(-) diff --git a/internal/runtime/executor/github_copilot_executor.go b/internal/runtime/executor/github_copilot_executor.go index 95f8ef17..0189ffc8 100644 --- a/internal/runtime/executor/github_copilot_executor.go +++ b/internal/runtime/executor/github_copilot_executor.go @@ -35,11 +35,12 @@ const ( maxScannerBufferSize = 20_971_520 // Copilot API header values. - copilotUserAgent = "GitHubCopilotChat/0.35.0" - copilotEditorVersion = "vscode/1.107.0" - copilotPluginVersion = "copilot-chat/0.35.0" - copilotIntegrationID = "vscode-chat" - copilotOpenAIIntent = "conversation-panel" + copilotUserAgent = "GitHubCopilotChat/0.35.0" + copilotEditorVersion = "vscode/1.107.0" + copilotPluginVersion = "copilot-chat/0.35.0" + copilotIntegrationID = "vscode-chat" + copilotOpenAIIntent = "conversation-panel" + copilotGitHubAPIVer = "2025-04-01" ) // GitHubCopilotExecutor handles requests to the GitHub Copilot API. @@ -51,8 +52,9 @@ type GitHubCopilotExecutor struct { // cachedAPIToken stores a cached Copilot API token with its expiry. type cachedAPIToken struct { - token string - expiresAt time.Time + token string + apiEndpoint string + expiresAt time.Time } // NewGitHubCopilotExecutor constructs a new executor instance. @@ -75,7 +77,7 @@ func (e *GitHubCopilotExecutor) PrepareRequest(req *http.Request, auth *cliproxy if ctx == nil { ctx = context.Background() } - apiToken, errToken := e.ensureAPIToken(ctx, auth) + apiToken, _, errToken := e.ensureAPIToken(ctx, auth) if errToken != nil { return errToken } @@ -101,7 +103,7 @@ func (e *GitHubCopilotExecutor) HttpRequest(ctx context.Context, auth *cliproxya // Execute handles non-streaming requests to GitHub Copilot. func (e *GitHubCopilotExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, req cliproxyexecutor.Request, opts cliproxyexecutor.Options) (resp cliproxyexecutor.Response, err error) { - apiToken, errToken := e.ensureAPIToken(ctx, auth) + apiToken, baseURL, errToken := e.ensureAPIToken(ctx, auth) if errToken != nil { return resp, errToken } @@ -124,6 +126,9 @@ func (e *GitHubCopilotExecutor) Execute(ctx context.Context, auth *cliproxyauth. body = e.normalizeModel(req.Model, body) body = flattenAssistantContent(body) + // Detect vision content before input normalization removes messages + hasVision := detectVisionContent(body) + thinkingProvider := "openai" if useResponses { thinkingProvider = "codex" @@ -147,7 +152,7 @@ func (e *GitHubCopilotExecutor) Execute(ctx context.Context, auth *cliproxyauth. if useResponses { path = githubCopilotResponsesPath } - url := githubCopilotBaseURL + path + url := baseURL + path httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body)) if err != nil { return resp, err @@ -155,7 +160,7 @@ func (e *GitHubCopilotExecutor) Execute(ctx context.Context, auth *cliproxyauth. e.applyHeaders(httpReq, apiToken, body) // Add Copilot-Vision-Request header if the request contains vision content - if detectVisionContent(body) { + if hasVision { httpReq.Header.Set("Copilot-Vision-Request", "true") } @@ -228,7 +233,7 @@ func (e *GitHubCopilotExecutor) Execute(ctx context.Context, auth *cliproxyauth. // ExecuteStream handles streaming requests to GitHub Copilot. func (e *GitHubCopilotExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Auth, req cliproxyexecutor.Request, opts cliproxyexecutor.Options) (stream <-chan cliproxyexecutor.StreamChunk, err error) { - apiToken, errToken := e.ensureAPIToken(ctx, auth) + apiToken, baseURL, errToken := e.ensureAPIToken(ctx, auth) if errToken != nil { return nil, errToken } @@ -251,6 +256,9 @@ func (e *GitHubCopilotExecutor) ExecuteStream(ctx context.Context, auth *cliprox body = e.normalizeModel(req.Model, body) body = flattenAssistantContent(body) + // Detect vision content before input normalization removes messages + hasVision := detectVisionContent(body) + thinkingProvider := "openai" if useResponses { thinkingProvider = "codex" @@ -278,7 +286,7 @@ func (e *GitHubCopilotExecutor) ExecuteStream(ctx context.Context, auth *cliprox if useResponses { path = githubCopilotResponsesPath } - url := githubCopilotBaseURL + path + url := baseURL + path httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body)) if err != nil { return nil, err @@ -286,7 +294,7 @@ func (e *GitHubCopilotExecutor) ExecuteStream(ctx context.Context, auth *cliprox e.applyHeaders(httpReq, apiToken, body) // Add Copilot-Vision-Request header if the request contains vision content - if detectVisionContent(body) { + if hasVision { httpReq.Header.Set("Copilot-Vision-Request", "true") } @@ -418,22 +426,22 @@ func (e *GitHubCopilotExecutor) Refresh(ctx context.Context, auth *cliproxyauth. } // ensureAPIToken gets or refreshes the Copilot API token. -func (e *GitHubCopilotExecutor) ensureAPIToken(ctx context.Context, auth *cliproxyauth.Auth) (string, error) { +func (e *GitHubCopilotExecutor) ensureAPIToken(ctx context.Context, auth *cliproxyauth.Auth) (string, string, error) { if auth == nil { - return "", statusErr{code: http.StatusUnauthorized, msg: "missing auth"} + return "", "", statusErr{code: http.StatusUnauthorized, msg: "missing auth"} } // Get the GitHub access token accessToken := metaStringValue(auth.Metadata, "access_token") if accessToken == "" { - return "", statusErr{code: http.StatusUnauthorized, msg: "missing github access token"} + return "", "", statusErr{code: http.StatusUnauthorized, msg: "missing github access token"} } // Check for cached API token using thread-safe access e.mu.RLock() if cached, ok := e.cache[accessToken]; ok && cached.expiresAt.After(time.Now().Add(tokenExpiryBuffer)) { e.mu.RUnlock() - return cached.token, nil + return cached.token, cached.apiEndpoint, nil } e.mu.RUnlock() @@ -441,7 +449,13 @@ func (e *GitHubCopilotExecutor) ensureAPIToken(ctx context.Context, auth *clipro copilotAuth := copilotauth.NewCopilotAuth(e.cfg) apiToken, err := copilotAuth.GetCopilotAPIToken(ctx, accessToken) if err != nil { - return "", statusErr{code: http.StatusUnauthorized, msg: fmt.Sprintf("failed to get copilot api token: %v", err)} + return "", "", statusErr{code: http.StatusUnauthorized, msg: fmt.Sprintf("failed to get copilot api token: %v", err)} + } + + // Use endpoint from token response, fall back to default + apiEndpoint := githubCopilotBaseURL + if apiToken.Endpoints.API != "" { + apiEndpoint = strings.TrimRight(apiToken.Endpoints.API, "/") } // Cache the token with thread-safe access @@ -451,12 +465,13 @@ func (e *GitHubCopilotExecutor) ensureAPIToken(ctx context.Context, auth *clipro } e.mu.Lock() e.cache[accessToken] = &cachedAPIToken{ - token: apiToken.Token, - expiresAt: expiresAt, + token: apiToken.Token, + apiEndpoint: apiEndpoint, + expiresAt: expiresAt, } e.mu.Unlock() - return apiToken.Token, nil + return apiToken.Token, apiEndpoint, nil } // applyHeaders sets the required headers for GitHub Copilot API requests. @@ -469,16 +484,17 @@ func (e *GitHubCopilotExecutor) applyHeaders(r *http.Request, apiToken string, b r.Header.Set("Editor-Plugin-Version", copilotPluginVersion) r.Header.Set("Openai-Intent", copilotOpenAIIntent) r.Header.Set("Copilot-Integration-Id", copilotIntegrationID) + r.Header.Set("X-Github-Api-Version", copilotGitHubAPIVer) r.Header.Set("X-Request-Id", uuid.NewString()) initiator := "user" if len(body) > 0 { if messages := gjson.GetBytes(body, "messages"); messages.Exists() && messages.IsArray() { - arr := messages.Array() - if len(arr) > 0 { - lastRole := arr[len(arr)-1].Get("role").String() - if lastRole != "" && lastRole != "user" { + for _, msg := range messages.Array() { + role := msg.Get("role").String() + if role == "assistant" || role == "tool" { initiator = "agent" + break } } } diff --git a/internal/runtime/executor/github_copilot_executor_test.go b/internal/runtime/executor/github_copilot_executor_test.go index 41877414..39868ef7 100644 --- a/internal/runtime/executor/github_copilot_executor_test.go +++ b/internal/runtime/executor/github_copilot_executor_test.go @@ -1,6 +1,7 @@ package executor import ( + "net/http" "strings" "testing" @@ -247,3 +248,86 @@ func TestTranslateGitHubCopilotResponsesStreamToClaude_TextLifecycle(t *testing. t.Fatalf("completed events = %#v, want message_delta + message_stop", completed) } } + +// --- Tests for X-Initiator detection logic (Problem L) --- + +func TestApplyHeaders_XInitiator_UserOnly(t *testing.T) { + t.Parallel() + e := &GitHubCopilotExecutor{} + req, _ := http.NewRequest(http.MethodPost, "https://example.com", nil) + body := []byte(`{"messages":[{"role":"system","content":"sys"},{"role":"user","content":"hello"}]}`) + e.applyHeaders(req, "token", body) + if got := req.Header.Get("X-Initiator"); got != "user" { + t.Fatalf("X-Initiator = %q, want user", got) + } +} + +func TestApplyHeaders_XInitiator_AgentWithAssistantAndUserToolResult(t *testing.T) { + t.Parallel() + e := &GitHubCopilotExecutor{} + req, _ := http.NewRequest(http.MethodPost, "https://example.com", nil) + // Claude Code typical flow: last message is user (tool result), but has assistant in history + body := []byte(`{"messages":[{"role":"user","content":"hello"},{"role":"assistant","content":"I will read the file"},{"role":"user","content":"tool result here"}]}`) + e.applyHeaders(req, "token", body) + if got := req.Header.Get("X-Initiator"); got != "agent" { + t.Fatalf("X-Initiator = %q, want agent (assistant exists in messages)", got) + } +} + +func TestApplyHeaders_XInitiator_AgentWithToolRole(t *testing.T) { + t.Parallel() + e := &GitHubCopilotExecutor{} + req, _ := http.NewRequest(http.MethodPost, "https://example.com", nil) + body := []byte(`{"messages":[{"role":"user","content":"hello"},{"role":"tool","content":"result"}]}`) + e.applyHeaders(req, "token", body) + if got := req.Header.Get("X-Initiator"); got != "agent" { + t.Fatalf("X-Initiator = %q, want agent (tool role exists)", got) + } +} + +// --- Tests for x-github-api-version header (Problem M) --- + +func TestApplyHeaders_GitHubAPIVersion(t *testing.T) { + t.Parallel() + e := &GitHubCopilotExecutor{} + req, _ := http.NewRequest(http.MethodPost, "https://example.com", nil) + e.applyHeaders(req, "token", nil) + if got := req.Header.Get("X-Github-Api-Version"); got != "2025-04-01" { + t.Fatalf("X-Github-Api-Version = %q, want 2025-04-01", got) + } +} + +// --- Tests for vision detection (Problem P) --- + +func TestDetectVisionContent_WithImageURL(t *testing.T) { + t.Parallel() + body := []byte(`{"messages":[{"role":"user","content":[{"type":"text","text":"describe"},{"type":"image_url","image_url":{"url":"data:image/png;base64,abc"}}]}]}`) + if !detectVisionContent(body) { + t.Fatal("expected vision content to be detected") + } +} + +func TestDetectVisionContent_WithImageType(t *testing.T) { + t.Parallel() + body := []byte(`{"messages":[{"role":"user","content":[{"type":"image","source":{"data":"abc","media_type":"image/png"}}]}]}`) + if !detectVisionContent(body) { + t.Fatal("expected image type to be detected") + } +} + +func TestDetectVisionContent_NoVision(t *testing.T) { + t.Parallel() + body := []byte(`{"messages":[{"role":"user","content":[{"type":"text","text":"hello"}]}]}`) + if detectVisionContent(body) { + t.Fatal("expected no vision content") + } +} + +func TestDetectVisionContent_NoMessages(t *testing.T) { + t.Parallel() + // After Responses API normalization, messages is removed — detection should return false + body := []byte(`{"input":[{"type":"message","role":"user","content":[{"type":"input_text","text":"hello"}]}]}`) + if detectVisionContent(body) { + t.Fatal("expected no vision content when messages field is absent") + } +} From c55275342c05379b07dc02307cb7d388bc1c2cf1 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 18 Feb 2026 03:04:27 +0800 Subject: [PATCH 3/6] feat(registry): add GPT-5.3 Codex to GitHub Copilot provider --- internal/registry/model_definitions.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/internal/registry/model_definitions.go b/internal/registry/model_definitions.go index abd943bc..19f53e5c 100644 --- a/internal/registry/model_definitions.go +++ b/internal/registry/model_definitions.go @@ -258,6 +258,19 @@ func GetGitHubCopilotModels() []*ModelInfo { SupportedEndpoints: []string{"/responses"}, Thinking: &ThinkingSupport{Levels: []string{"none", "low", "medium", "high", "xhigh"}}, }, + { + ID: "gpt-5.3-codex", + Object: "model", + Created: now, + OwnedBy: "github-copilot", + Type: "github-copilot", + DisplayName: "GPT-5.3 Codex", + Description: "OpenAI GPT-5.3 Codex via GitHub Copilot", + ContextLength: 200000, + MaxCompletionTokens: 32768, + SupportedEndpoints: []string{"/responses"}, + Thinking: &ThinkingSupport{Levels: []string{"none", "low", "medium", "high", "xhigh"}}, + }, { ID: "claude-haiku-4.5", Object: "model", From 922d4141c08f668490b12dc4d2b100d96e1d2cc0 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 18 Feb 2026 05:17:23 +0800 Subject: [PATCH 4/6] feat(registry): add Sonnet 4.6 to GitHub Copilot provider --- internal/registry/model_definitions.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/internal/registry/model_definitions.go b/internal/registry/model_definitions.go index abd943bc..67348971 100644 --- a/internal/registry/model_definitions.go +++ b/internal/registry/model_definitions.go @@ -330,6 +330,18 @@ func GetGitHubCopilotModels() []*ModelInfo { MaxCompletionTokens: 64000, SupportedEndpoints: []string{"/chat/completions"}, }, + { + ID: "claude-sonnet-4.6", + Object: "model", + Created: now, + OwnedBy: "github-copilot", + Type: "github-copilot", + DisplayName: "Claude Sonnet 4.6", + Description: "Anthropic Claude Sonnet 4.6 via GitHub Copilot", + ContextLength: 200000, + MaxCompletionTokens: 64000, + SupportedEndpoints: []string{"/chat/completions"}, + }, { ID: "gemini-2.5-pro", Object: "model", From e42ef9a95d27e3b3ed10f11871c0e9ec4a9c2760 Mon Sep 17 00:00:00 2001 From: gl11tchy <211956100+gl11tchy@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:43:22 +0000 Subject: [PATCH 5/6] feat(registry): add Claude Sonnet 4.6 model definitions Add claude-sonnet-4-6 to: - Claude OAuth provider (model_definitions_static_data.go) - Antigravity model config (thinking + non-thinking entries) - GitHub Copilot provider (model_definitions.go) Ref: https://docs.anthropic.com/en/docs/about-claude/models --- internal/registry/model_definitions.go | 12 ++++++++++++ internal/registry/model_definitions_static_data.go | 14 ++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/internal/registry/model_definitions.go b/internal/registry/model_definitions.go index abd943bc..118aa7a2 100644 --- a/internal/registry/model_definitions.go +++ b/internal/registry/model_definitions.go @@ -306,6 +306,18 @@ func GetGitHubCopilotModels() []*ModelInfo { MaxCompletionTokens: 64000, SupportedEndpoints: []string{"/chat/completions"}, }, + { + ID: "claude-sonnet-4.6", + Object: "model", + Created: now, + OwnedBy: "github-copilot", + Type: "github-copilot", + DisplayName: "Claude Sonnet 4.6", + Description: "Anthropic Claude Sonnet 4.6 via GitHub Copilot", + ContextLength: 200000, + MaxCompletionTokens: 64000, + SupportedEndpoints: []string{"/chat/completions"}, + }, { ID: "claude-sonnet-4", Object: "model", diff --git a/internal/registry/model_definitions_static_data.go b/internal/registry/model_definitions_static_data.go index 26716804..f366308d 100644 --- a/internal/registry/model_definitions_static_data.go +++ b/internal/registry/model_definitions_static_data.go @@ -40,6 +40,18 @@ func GetClaudeModels() []*ModelInfo { MaxCompletionTokens: 128000, Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: false}, }, + { + ID: "claude-sonnet-4-6", + Object: "model", + Created: 1771286400, // 2026-02-17 + OwnedBy: "anthropic", + Type: "claude", + DisplayName: "Claude 4.6 Sonnet", + Description: "Best combination of speed and intelligence", + ContextLength: 200000, + MaxCompletionTokens: 64000, + Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: false}, + }, { ID: "claude-opus-4-5-20251101", Object: "model", @@ -896,7 +908,9 @@ func GetAntigravityModelConfig() map[string]*AntigravityModelConfig { "claude-sonnet-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, "claude-opus-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, "claude-opus-4-6-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, + "claude-sonnet-4-6-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, "claude-sonnet-4-5": {MaxCompletionTokens: 64000}, + "claude-sonnet-4-6": {MaxCompletionTokens: 64000}, "gpt-oss-120b-medium": {}, "tab_flash_lite_preview": {}, } From f9a09b7f23c524f597a808cd5a146589e99e98da Mon Sep 17 00:00:00 2001 From: gl11tchy <211956100+gl11tchy@users.noreply.github.com> Date: Wed, 18 Feb 2026 15:06:28 +0000 Subject: [PATCH 6/6] style: sort model entries per review feedback --- internal/registry/model_definitions.go | 24 +++++++++---------- .../registry/model_definitions_static_data.go | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/internal/registry/model_definitions.go b/internal/registry/model_definitions.go index 118aa7a2..67348971 100644 --- a/internal/registry/model_definitions.go +++ b/internal/registry/model_definitions.go @@ -306,18 +306,6 @@ func GetGitHubCopilotModels() []*ModelInfo { MaxCompletionTokens: 64000, SupportedEndpoints: []string{"/chat/completions"}, }, - { - ID: "claude-sonnet-4.6", - Object: "model", - Created: now, - OwnedBy: "github-copilot", - Type: "github-copilot", - DisplayName: "Claude Sonnet 4.6", - Description: "Anthropic Claude Sonnet 4.6 via GitHub Copilot", - ContextLength: 200000, - MaxCompletionTokens: 64000, - SupportedEndpoints: []string{"/chat/completions"}, - }, { ID: "claude-sonnet-4", Object: "model", @@ -342,6 +330,18 @@ func GetGitHubCopilotModels() []*ModelInfo { MaxCompletionTokens: 64000, SupportedEndpoints: []string{"/chat/completions"}, }, + { + ID: "claude-sonnet-4.6", + Object: "model", + Created: now, + OwnedBy: "github-copilot", + Type: "github-copilot", + DisplayName: "Claude Sonnet 4.6", + Description: "Anthropic Claude Sonnet 4.6 via GitHub Copilot", + ContextLength: 200000, + MaxCompletionTokens: 64000, + SupportedEndpoints: []string{"/chat/completions"}, + }, { ID: "gemini-2.5-pro", Object: "model", diff --git a/internal/registry/model_definitions_static_data.go b/internal/registry/model_definitions_static_data.go index f366308d..6acd49dc 100644 --- a/internal/registry/model_definitions_static_data.go +++ b/internal/registry/model_definitions_static_data.go @@ -905,12 +905,12 @@ func GetAntigravityModelConfig() map[string]*AntigravityModelConfig { "gemini-3-pro-high": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"low", "high"}}}, "gemini-3-pro-image": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"low", "high"}}}, "gemini-3-flash": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"minimal", "low", "medium", "high"}}}, - "claude-sonnet-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, "claude-opus-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, "claude-opus-4-6-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, - "claude-sonnet-4-6-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, "claude-sonnet-4-5": {MaxCompletionTokens: 64000}, + "claude-sonnet-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, "claude-sonnet-4-6": {MaxCompletionTokens: 64000}, + "claude-sonnet-4-6-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, "gpt-oss-120b-medium": {}, "tab_flash_lite_preview": {}, }