devel/crush: OpenBSD patches
This commit is contained in:
17
devel/crush/patches/patch-internal_agent_coordinator_go
Normal file
17
devel/crush/patches/patch-internal_agent_coordinator_go
Normal file
@@ -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
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
--- internal/cmd/login.go
|
Index: internal/cmd/login.go
|
||||||
|
--- internal/cmd/login.go.orig
|
||||||
+++ internal/cmd/login.go
|
+++ internal/cmd/login.go
|
||||||
@@ -6,12 +6,14 @@
|
@@ -6,12 +6,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@@ -15,7 +16,7 @@
|
|||||||
"github.com/charmbracelet/crush/internal/oauth/copilot"
|
"github.com/charmbracelet/crush/internal/oauth/copilot"
|
||||||
"github.com/charmbracelet/crush/internal/oauth/hyper"
|
"github.com/charmbracelet/crush/internal/oauth/hyper"
|
||||||
"github.com/charmbracelet/x/ansi"
|
"github.com/charmbracelet/x/ansi"
|
||||||
@@ -25,11 +27,14 @@
|
@@ -25,11 +27,14 @@ var loginCmd = &cobra.Command{
|
||||||
Short: "Login Crush to a platform",
|
Short: "Login Crush to a platform",
|
||||||
Long: `Login Crush to a specified platform.
|
Long: `Login Crush to a specified platform.
|
||||||
The platform should be provided as an argument.
|
The platform should be provided as an argument.
|
||||||
@@ -31,7 +32,7 @@
|
|||||||
# Authenticate with GitHub Copilot
|
# Authenticate with GitHub Copilot
|
||||||
crush login copilot
|
crush login copilot
|
||||||
|
|
||||||
@@ -38,6 +43,8 @@
|
@@ -38,6 +43,8 @@ crush login -f copilot
|
||||||
`,
|
`,
|
||||||
ValidArgs: []cobra.Completion{
|
ValidArgs: []cobra.Completion{
|
||||||
"hyper",
|
"hyper",
|
||||||
@@ -40,7 +41,7 @@
|
|||||||
"copilot",
|
"copilot",
|
||||||
"github",
|
"github",
|
||||||
"github-copilot",
|
"github-copilot",
|
||||||
@@ -64,6 +71,8 @@
|
@@ -64,6 +71,8 @@ crush login -f copilot
|
||||||
switch provider {
|
switch provider {
|
||||||
case "hyper":
|
case "hyper":
|
||||||
return loginHyper(c, ws.ID, force)
|
return loginHyper(c, ws.ID, force)
|
||||||
@@ -49,7 +50,7 @@
|
|||||||
case "copilot", "github", "github-copilot":
|
case "copilot", "github", "github-copilot":
|
||||||
return loginCopilot(c, ws.ID, force)
|
return loginCopilot(c, ws.ID, force)
|
||||||
default:
|
default:
|
||||||
@@ -140,6 +149,68 @@
|
@@ -140,6 +149,68 @@ func loginHyper(c *client.Client, wsID string, force b
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("You're now authenticated with Hyper!")
|
fmt.Println("You're now authenticated with Hyper!")
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
--- internal/config/config.go
|
Index: internal/config/config.go
|
||||||
|
--- internal/config/config.go.orig
|
||||||
+++ internal/config/config.go
|
+++ 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())
|
maps.Copy(c.ExtraHeaders, copilot.Headers())
|
||||||
}
|
}
|
||||||
|
|
||||||
+func (c *ProviderConfig) SetupClaudeCode() {
|
+func (c *ProviderConfig) SetupClaudeCode() {
|
||||||
+ c.FlatRate = true
|
+ c.FlatRate = true
|
||||||
+ c.SystemPromptPrefix = "You are Claude Code, Anthropic's official CLI for Claude."
|
+ c.SystemPromptPrefix = "You are Claude Code, Anthropic's official CLI for Claude."
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
+ c.ExtraHeaders = make(map[string]string)
|
+ c.ExtraHeaders = make(map[string]string)
|
||||||
+ }
|
+ }
|
||||||
+ c.ExtraHeaders["anthropic-version"] = "2023-06-01"
|
+ c.ExtraHeaders["anthropic-version"] = "2023-06-01"
|
||||||
|
+ c.ExtraHeaders["User-Agent"] = "claude-code/2.1.112"
|
||||||
+ const want = "oauth-2025-04-20"
|
+ const want = "oauth-2025-04-20"
|
||||||
+ if v := c.ExtraHeaders["anthropic-beta"]; !strings.Contains(v, want) {
|
+ if v := c.ExtraHeaders["anthropic-beta"]; !strings.Contains(v, want) {
|
||||||
+ if v != "" {
|
+ if v != "" {
|
||||||
@@ -18,6 +20,11 @@
|
|||||||
+ }
|
+ }
|
||||||
+ c.ExtraHeaders["anthropic-beta"] = v + want
|
+ c.ExtraHeaders["anthropic-beta"] = v + want
|
||||||
+ }
|
+ }
|
||||||
|
+ if c.APIKey != "" && !strings.HasPrefix(c.APIKey, "Bearer ") {
|
||||||
|
+ c.APIKey = "Bearer " + c.APIKey
|
||||||
|
+ }
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
type MCPType string
|
type MCPType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
--- internal/config/load.go
|
Index: internal/config/load.go
|
||||||
|
--- internal/config/load.go.orig
|
||||||
+++ internal/config/load.go
|
+++ internal/config/load.go
|
||||||
@@ -287,14 +287,7 @@
|
@@ -287,14 +287,7 @@ func (c *Config) configureProviders(ctx context.Contex
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case p.ID == catwalk.InferenceProviderAnthropic && config.OAuthToken != nil:
|
case p.ID == catwalk.InferenceProviderAnthropic && config.OAuthToken != nil:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
--- internal/config/store.go
|
Index: internal/config/store.go
|
||||||
|
--- internal/config/store.go.orig
|
||||||
+++ internal/config/store.go
|
+++ internal/config/store.go
|
||||||
@@ -16,6 +16,7 @@
|
@@ -16,6 +16,7 @@ import (
|
||||||
"github.com/charmbracelet/crush/internal/env"
|
"github.com/charmbracelet/crush/internal/env"
|
||||||
"github.com/charmbracelet/crush/internal/lock"
|
"github.com/charmbracelet/crush/internal/lock"
|
||||||
"github.com/charmbracelet/crush/internal/oauth"
|
"github.com/charmbracelet/crush/internal/oauth"
|
||||||
@@ -8,7 +9,7 @@
|
|||||||
"github.com/charmbracelet/crush/internal/oauth/copilot"
|
"github.com/charmbracelet/crush/internal/oauth/copilot"
|
||||||
"github.com/charmbracelet/crush/internal/oauth/hyper"
|
"github.com/charmbracelet/crush/internal/oauth/hyper"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
@@ -470,6 +471,8 @@
|
@@ -470,6 +471,8 @@ func (s *ConfigStore) SetProviderAPIKey(scope Scope, p
|
||||||
providerConfig.APIKey = v.AccessToken
|
providerConfig.APIKey = v.AccessToken
|
||||||
providerConfig.OAuthToken = v
|
providerConfig.OAuthToken = v
|
||||||
switch providerID {
|
switch providerID {
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
case string(catwalk.InferenceProviderCopilot):
|
case string(catwalk.InferenceProviderCopilot):
|
||||||
providerConfig.SetupGitHubCopilot()
|
providerConfig.SetupGitHubCopilot()
|
||||||
}
|
}
|
||||||
@@ -596,7 +599,10 @@
|
@@ -596,7 +599,10 @@ func (s *ConfigStore) refreshOAuthTokenLocked(ctx cont
|
||||||
slog.Info("Successfully refreshed OAuth token", "provider", providerID)
|
slog.Info("Successfully refreshed OAuth token", "provider", providerID)
|
||||||
providerConfig.OAuthToken = refreshedToken
|
providerConfig.OAuthToken = refreshedToken
|
||||||
providerConfig.APIKey = refreshedToken.AccessToken
|
providerConfig.APIKey = refreshedToken.AccessToken
|
||||||
@@ -29,7 +30,7 @@
|
|||||||
providerConfig.SetupGitHubCopilot()
|
providerConfig.SetupGitHubCopilot()
|
||||||
}
|
}
|
||||||
cfg.Providers.Set(providerID, providerConfig)
|
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)
|
return s.exchangeToken(ctx, providerID, refreshToken)
|
||||||
}
|
}
|
||||||
switch providerID {
|
switch providerID {
|
||||||
@@ -38,7 +39,7 @@
|
|||||||
case string(catwalk.InferenceProviderCopilot):
|
case string(catwalk.InferenceProviderCopilot):
|
||||||
return copilot.RefreshToken(ctx, refreshToken)
|
return copilot.RefreshToken(ctx, refreshToken)
|
||||||
case hyperp.Name:
|
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 {
|
func (s *ConfigStore) applyToken(providerConfig ProviderConfig, token *oauth.Token, providerID string) error {
|
||||||
providerConfig.OAuthToken = token
|
providerConfig.OAuthToken = token
|
||||||
providerConfig.APIKey = token.AccessToken
|
providerConfig.APIKey = token.AccessToken
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
--- /dev/null
|
Index: internal/oauth/claude/challenge.go
|
||||||
|
--- internal/oauth/claude/challenge.go.orig
|
||||||
+++ internal/oauth/claude/challenge.go
|
+++ internal/oauth/claude/challenge.go
|
||||||
@@ -0,0 +1,28 @@
|
@@ -0,0 +1,28 @@
|
||||||
+package claude
|
+package claude
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
--- /dev/null
|
Index: internal/oauth/claude/oauth.go
|
||||||
|
--- internal/oauth/claude/oauth.go.orig
|
||||||
+++ internal/oauth/claude/oauth.go
|
+++ internal/oauth/claude/oauth.go
|
||||||
@@ -0,0 +1,126 @@
|
@@ -0,0 +1,131 @@
|
||||||
+package claude
|
+package claude
|
||||||
+
|
+
|
||||||
+import (
|
+import (
|
||||||
@@ -17,19 +18,24 @@
|
|||||||
+ "github.com/charmbracelet/crush/internal/oauth"
|
+ "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.
|
+// AuthorizeURL returns the Claude Code Max OAuth2 authorization URL.
|
||||||
+func AuthorizeURL(verifier, challenge string) (string, error) {
|
+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 {
|
+ if err != nil {
|
||||||
+ return "", err
|
+ return "", err
|
||||||
+ }
|
+ }
|
||||||
+ q := u.Query()
|
+ q := u.Query()
|
||||||
+ q.Set("response_type", "code")
|
+ q.Set("code", "true")
|
||||||
+ q.Set("client_id", clientId)
|
+ q.Set("client_id", clientId)
|
||||||
+ q.Set("redirect_uri", "https://console.anthropic.com/oauth/code/callback")
|
+ q.Set("response_type", "code")
|
||||||
+ q.Set("scope", "org:create_api_key user:profile user:inference")
|
+ 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", challenge)
|
||||||
+ q.Set("code_challenge_method", "S256")
|
+ q.Set("code_challenge_method", "S256")
|
||||||
+ q.Set("state", verifier)
|
+ q.Set("state", verifier)
|
||||||
@@ -52,11 +58,11 @@
|
|||||||
+ "state": state,
|
+ "state": state,
|
||||||
+ "grant_type": "authorization_code",
|
+ "grant_type": "authorization_code",
|
||||||
+ "client_id": clientId,
|
+ "client_id": clientId,
|
||||||
+ "redirect_uri": "https://console.anthropic.com/oauth/code/callback",
|
+ "redirect_uri": redirectURI,
|
||||||
+ "code_verifier": verifier,
|
+ "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 {
|
+ if err != nil {
|
||||||
+ return nil, err
|
+ return nil, err
|
||||||
+ }
|
+ }
|
||||||
@@ -87,7 +93,7 @@
|
|||||||
+ "client_id": clientId,
|
+ "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 {
|
+ if err != nil {
|
||||||
+ return nil, err
|
+ return nil, err
|
||||||
+ }
|
+ }
|
||||||
@@ -122,7 +128,7 @@
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ req.Header.Set("Content-Type", "application/json")
|
+ 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}
|
+ client := &http.Client{Timeout: 30 * time.Second}
|
||||||
+ return client.Do(req)
|
+ return client.Do(req)
|
||||||
|
|||||||
@@ -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
|
+++ internal/ui/dialog/oauth_claude.go
|
||||||
@@ -0,0 +1,241 @@
|
@@ -0,0 +1,241 @@
|
||||||
+package dialog
|
+package dialog
|
||||||
|
|||||||
@@ -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
|
+++ 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 {
|
switch provider.ID {
|
||||||
case "hyper":
|
case "hyper":
|
||||||
dlg, cmd = dialog.NewOAuthHyper(m.com, isOnboarding, provider, model, modelType)
|
dlg, cmd = dialog.NewOAuthHyper(m.com, isOnboarding, provider, model, modelType)
|
||||||
|
|||||||
Reference in New Issue
Block a user