From 844067ee41634e50c3357d8ba710946723011a60 Mon Sep 17 00:00:00 2001 From: c0dev0id Date: Wed, 8 Jul 2026 11:31:31 +0200 Subject: [PATCH] devel/crush: OpenBSD patches --- .../patch-internal_agent_coordinator_go | 17 +++++++++++ .../crush/patches/patch-internal_cmd_login_go | 13 +++++---- .../patches/patch-internal_config_config_go | 13 +++++++-- .../patches/patch-internal_config_load_go | 5 ++-- .../patches/patch-internal_config_store_go | 13 +++++---- .../patch-internal_oauth_claude_challenge_go | 3 +- .../patch-internal_oauth_claude_oauth_go | 28 +++++++++++-------- .../patch-internal_ui_dialog_oauth_claude_go | 3 +- .../patches/patch-internal_ui_model_ui_go | 5 ++-- 9 files changed, 68 insertions(+), 32 deletions(-) create mode 100644 devel/crush/patches/patch-internal_agent_coordinator_go diff --git a/devel/crush/patches/patch-internal_agent_coordinator_go b/devel/crush/patches/patch-internal_agent_coordinator_go new file mode 100644 index 0000000..3831fe4 --- /dev/null +++ b/devel/crush/patches/patch-internal_agent_coordinator_go @@ -0,0 +1,17 @@ +Index: internal/agent/coordinator.go +--- internal/agent/coordinator.go.orig ++++ internal/agent/coordinator.go +@@ -823,11 +823,11 @@ func (c *coordinator) buildAnthropicProvider(baseURL, + switch { + case strings.HasPrefix(apiKey, "Bearer "): + // NOTE: Prevent the SDK from picking up the API key from env. +- os.Setenv("ANTHROPIC_API_KEY", "") ++ os.Unsetenv("ANTHROPIC_API_KEY") + headers["Authorization"] = apiKey + case providerID == string(catwalk.InferenceProviderMiniMax) || providerID == string(catwalk.InferenceProviderMiniMaxChina): + // NOTE: Prevent the SDK from picking up the API key from env. +- os.Setenv("ANTHROPIC_API_KEY", "") ++ os.Unsetenv("ANTHROPIC_API_KEY") + headers["Authorization"] = "Bearer " + apiKey + case apiKey != "": + // X-Api-Key header diff --git a/devel/crush/patches/patch-internal_cmd_login_go b/devel/crush/patches/patch-internal_cmd_login_go index 05ed9ed..bd65ae2 100644 --- a/devel/crush/patches/patch-internal_cmd_login_go +++ b/devel/crush/patches/patch-internal_cmd_login_go @@ -1,6 +1,7 @@ ---- internal/cmd/login.go +Index: internal/cmd/login.go +--- internal/cmd/login.go.orig +++ internal/cmd/login.go -@@ -6,12 +6,14 @@ +@@ -6,12 +6,14 @@ import ( "fmt" "os" "os/signal" @@ -15,7 +16,7 @@ "github.com/charmbracelet/crush/internal/oauth/copilot" "github.com/charmbracelet/crush/internal/oauth/hyper" "github.com/charmbracelet/x/ansi" -@@ -25,11 +27,14 @@ +@@ -25,11 +27,14 @@ var loginCmd = &cobra.Command{ Short: "Login Crush to a platform", Long: `Login Crush to a specified platform. The platform should be provided as an argument. @@ -31,7 +32,7 @@ # Authenticate with GitHub Copilot crush login copilot -@@ -38,6 +43,8 @@ +@@ -38,6 +43,8 @@ crush login -f copilot `, ValidArgs: []cobra.Completion{ "hyper", @@ -40,7 +41,7 @@ "copilot", "github", "github-copilot", -@@ -64,6 +71,8 @@ +@@ -64,6 +71,8 @@ crush login -f copilot switch provider { case "hyper": return loginHyper(c, ws.ID, force) @@ -49,7 +50,7 @@ case "copilot", "github", "github-copilot": return loginCopilot(c, ws.ID, force) default: -@@ -140,6 +149,68 @@ +@@ -140,6 +149,68 @@ func loginHyper(c *client.Client, wsID string, force b fmt.Println() fmt.Println("You're now authenticated with Hyper!") diff --git a/devel/crush/patches/patch-internal_config_config_go b/devel/crush/patches/patch-internal_config_config_go index 9508a94..8fc89b0 100644 --- a/devel/crush/patches/patch-internal_config_config_go +++ b/devel/crush/patches/patch-internal_config_config_go @@ -1,9 +1,10 @@ ---- internal/config/config.go +Index: internal/config/config.go +--- internal/config/config.go.orig +++ internal/config/config.go -@@ -177,6 +177,22 @@ func (c *ProviderConfig) SetupGitHubCopilot() { +@@ -178,6 +178,26 @@ func (c *ProviderConfig) SetupGitHubCopilot() { maps.Copy(c.ExtraHeaders, copilot.Headers()) } - + +func (c *ProviderConfig) SetupClaudeCode() { + c.FlatRate = true + c.SystemPromptPrefix = "You are Claude Code, Anthropic's official CLI for Claude." @@ -11,6 +12,7 @@ + c.ExtraHeaders = make(map[string]string) + } + c.ExtraHeaders["anthropic-version"] = "2023-06-01" ++ c.ExtraHeaders["User-Agent"] = "claude-code/2.1.112" + const want = "oauth-2025-04-20" + if v := c.ExtraHeaders["anthropic-beta"]; !strings.Contains(v, want) { + if v != "" { @@ -18,6 +20,11 @@ + } + c.ExtraHeaders["anthropic-beta"] = v + want + } ++ if c.APIKey != "" && !strings.HasPrefix(c.APIKey, "Bearer ") { ++ c.APIKey = "Bearer " + c.APIKey ++ } +} + type MCPType string + + const ( diff --git a/devel/crush/patches/patch-internal_config_load_go b/devel/crush/patches/patch-internal_config_load_go index 65ace97..69c2b31 100644 --- a/devel/crush/patches/patch-internal_config_load_go +++ b/devel/crush/patches/patch-internal_config_load_go @@ -1,6 +1,7 @@ ---- internal/config/load.go +Index: internal/config/load.go +--- internal/config/load.go.orig +++ internal/config/load.go -@@ -287,14 +287,7 @@ +@@ -287,14 +287,7 @@ func (c *Config) configureProviders(ctx context.Contex switch { case p.ID == catwalk.InferenceProviderAnthropic && config.OAuthToken != nil: diff --git a/devel/crush/patches/patch-internal_config_store_go b/devel/crush/patches/patch-internal_config_store_go index c0c2317..0f3f4c5 100644 --- a/devel/crush/patches/patch-internal_config_store_go +++ b/devel/crush/patches/patch-internal_config_store_go @@ -1,6 +1,7 @@ ---- internal/config/store.go +Index: internal/config/store.go +--- internal/config/store.go.orig +++ internal/config/store.go -@@ -16,6 +16,7 @@ +@@ -16,6 +16,7 @@ import ( "github.com/charmbracelet/crush/internal/env" "github.com/charmbracelet/crush/internal/lock" "github.com/charmbracelet/crush/internal/oauth" @@ -8,7 +9,7 @@ "github.com/charmbracelet/crush/internal/oauth/copilot" "github.com/charmbracelet/crush/internal/oauth/hyper" "github.com/tidwall/gjson" -@@ -470,6 +471,8 @@ +@@ -470,6 +471,8 @@ func (s *ConfigStore) SetProviderAPIKey(scope Scope, p providerConfig.APIKey = v.AccessToken providerConfig.OAuthToken = v switch providerID { @@ -17,7 +18,7 @@ case string(catwalk.InferenceProviderCopilot): providerConfig.SetupGitHubCopilot() } -@@ -596,7 +599,10 @@ +@@ -596,7 +599,10 @@ func (s *ConfigStore) refreshOAuthTokenLocked(ctx cont slog.Info("Successfully refreshed OAuth token", "provider", providerID) providerConfig.OAuthToken = refreshedToken providerConfig.APIKey = refreshedToken.AccessToken @@ -29,7 +30,7 @@ providerConfig.SetupGitHubCopilot() } cfg.Providers.Set(providerID, providerConfig) -@@ -638,6 +644,8 @@ +@@ -638,6 +644,8 @@ func (s *ConfigStore) exchange(ctx context.Context, pr return s.exchangeToken(ctx, providerID, refreshToken) } switch providerID { @@ -38,7 +39,7 @@ case string(catwalk.InferenceProviderCopilot): return copilot.RefreshToken(ctx, refreshToken) case hyperp.Name: -@@ -662,7 +670,10 @@ +@@ -662,7 +670,10 @@ func (s *ConfigStore) refreshLockPath(providerID strin func (s *ConfigStore) applyToken(providerConfig ProviderConfig, token *oauth.Token, providerID string) error { providerConfig.OAuthToken = token providerConfig.APIKey = token.AccessToken diff --git a/devel/crush/patches/patch-internal_oauth_claude_challenge_go b/devel/crush/patches/patch-internal_oauth_claude_challenge_go index cc86526..274922f 100644 --- a/devel/crush/patches/patch-internal_oauth_claude_challenge_go +++ b/devel/crush/patches/patch-internal_oauth_claude_challenge_go @@ -1,4 +1,5 @@ ---- /dev/null +Index: internal/oauth/claude/challenge.go +--- internal/oauth/claude/challenge.go.orig +++ internal/oauth/claude/challenge.go @@ -0,0 +1,28 @@ +package claude diff --git a/devel/crush/patches/patch-internal_oauth_claude_oauth_go b/devel/crush/patches/patch-internal_oauth_claude_oauth_go index 87c9575..c328ca0 100644 --- a/devel/crush/patches/patch-internal_oauth_claude_oauth_go +++ b/devel/crush/patches/patch-internal_oauth_claude_oauth_go @@ -1,6 +1,7 @@ ---- /dev/null +Index: internal/oauth/claude/oauth.go +--- internal/oauth/claude/oauth.go.orig +++ internal/oauth/claude/oauth.go -@@ -0,0 +1,126 @@ +@@ -0,0 +1,131 @@ +package claude + +import ( @@ -17,19 +18,24 @@ + "github.com/charmbracelet/crush/internal/oauth" +) + -+const clientId = "9d1c250a-e61b-44d9-88ed-5944d1962f5e" ++const ( ++ clientId = "9d1c250a-e61b-44d9-88ed-5944d1962f5e" ++ tokenURL = "https://platform.claude.com/v1/oauth/token" ++ redirectURI = "https://platform.claude.com/oauth/code/callback" ++) + +// AuthorizeURL returns the Claude Code Max OAuth2 authorization URL. +func AuthorizeURL(verifier, challenge string) (string, error) { -+ u, err := url.Parse("https://claude.ai/oauth/authorize") ++ u, err := url.Parse("https://platform.claude.com/oauth/authorize") + if err != nil { + return "", err + } + q := u.Query() -+ q.Set("response_type", "code") ++ q.Set("code", "true") + q.Set("client_id", clientId) -+ q.Set("redirect_uri", "https://console.anthropic.com/oauth/code/callback") -+ q.Set("scope", "org:create_api_key user:profile user:inference") ++ q.Set("response_type", "code") ++ q.Set("redirect_uri", redirectURI) ++ q.Set("scope", "org:create_api_key user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload") + q.Set("code_challenge", challenge) + q.Set("code_challenge_method", "S256") + q.Set("state", verifier) @@ -52,11 +58,11 @@ + "state": state, + "grant_type": "authorization_code", + "client_id": clientId, -+ "redirect_uri": "https://console.anthropic.com/oauth/code/callback", ++ "redirect_uri": redirectURI, + "code_verifier": verifier, + } + -+ resp, err := request(ctx, "POST", "https://console.anthropic.com/v1/oauth/token", reqBody) ++ resp, err := request(ctx, "POST", tokenURL, reqBody) + if err != nil { + return nil, err + } @@ -87,7 +93,7 @@ + "client_id": clientId, + } + -+ resp, err := request(ctx, "POST", "https://console.anthropic.com/v1/oauth/token", reqBody) ++ resp, err := request(ctx, "POST", tokenURL, reqBody) + if err != nil { + return nil, err + } @@ -122,7 +128,7 @@ + } + + req.Header.Set("Content-Type", "application/json") -+ req.Header.Set("User-Agent", "anthropic") ++ req.Header.Set("User-Agent", "claude-code/2.1.112") + + client := &http.Client{Timeout: 30 * time.Second} + return client.Do(req) diff --git a/devel/crush/patches/patch-internal_ui_dialog_oauth_claude_go b/devel/crush/patches/patch-internal_ui_dialog_oauth_claude_go index 542eda0..8e21a06 100644 --- a/devel/crush/patches/patch-internal_ui_dialog_oauth_claude_go +++ b/devel/crush/patches/patch-internal_ui_dialog_oauth_claude_go @@ -1,4 +1,5 @@ ---- /dev/null +Index: internal/ui/dialog/oauth_claude.go +--- internal/ui/dialog/oauth_claude.go.orig +++ internal/ui/dialog/oauth_claude.go @@ -0,0 +1,241 @@ +package dialog diff --git a/devel/crush/patches/patch-internal_ui_model_ui_go b/devel/crush/patches/patch-internal_ui_model_ui_go index 168ff09..870c642 100644 --- a/devel/crush/patches/patch-internal_ui_model_ui_go +++ b/devel/crush/patches/patch-internal_ui_model_ui_go @@ -1,6 +1,7 @@ ---- internal/ui/model/ui.go +Index: internal/ui/model/ui.go +--- internal/ui/model/ui.go.orig +++ internal/ui/model/ui.go -@@ -1952,6 +1952,8 @@ func (m *UI) openAuthenticationDialog(provider catwalk.Provider, model config.Se +@@ -1952,6 +1952,8 @@ func (m *UI) openAuthenticationDialog(provider catwalk switch provider.ID { case "hyper": dlg, cmd = dialog.NewOAuthHyper(m.com, isOnboarding, provider, model, modelType)