feat: add OAuth support for Claude Code tokens
Add support for Claude Code OAuth tokens (sk-ant-oat01-*) in the Anthropic provider. Claude Code generates OAuth tokens that require different authentication headers than standard Anthropic API keys: - Standard API keys use: x-api-key header - OAuth tokens require: Authorization: Bearer header + anthropic-beta: oauth-2025-04-20 header Changes: - Add isOAuthToken() to detect Claude Code OAuth tokens by sk-ant-oat01- prefix - Update NewProviderWithBaseURL() to use proper headers for OAuth tokens - Update Chat() method to handle OAuth tokens when using tokenSource This implementation matches the approach used in zeroclaw (Rust implementation). Fixes authentication errors when using Claude Code OAuth tokens: - Before: "OAuth authentication is currently not supported" - After: OAuth tokens work correctly with proper headers Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3584c0c7be
commit
ba2b4da723
1 changed files with 31 additions and 5 deletions
|
|
@ -25,6 +25,11 @@ type (
|
|||
|
||||
const defaultBaseURL = "https://api.anthropic.com"
|
||||
|
||||
// isOAuthToken detects Claude Code OAuth tokens by their prefix
|
||||
func isOAuthToken(token string) bool {
|
||||
return strings.HasPrefix(strings.TrimSpace(token), "sk-ant-oat01-")
|
||||
}
|
||||
|
||||
type Provider struct {
|
||||
client *anthropic.Client
|
||||
tokenSource func() (string, error)
|
||||
|
|
@ -37,10 +42,22 @@ func NewProvider(token string) *Provider {
|
|||
|
||||
func NewProviderWithBaseURL(token, apiBase string) *Provider {
|
||||
baseURL := normalizeBaseURL(apiBase)
|
||||
client := anthropic.NewClient(
|
||||
option.WithAuthToken(token),
|
||||
option.WithBaseURL(baseURL),
|
||||
|
||||
var opts []option.RequestOption
|
||||
|
||||
// OAuth tokens (Claude Code) require special handling
|
||||
if isOAuthToken(token) {
|
||||
opts = append(opts,
|
||||
option.WithHeader("Authorization", "Bearer "+token),
|
||||
option.WithHeader("anthropic-beta", "oauth-2025-04-20"),
|
||||
)
|
||||
} else {
|
||||
opts = append(opts, option.WithAuthToken(token))
|
||||
}
|
||||
|
||||
opts = append(opts, option.WithBaseURL(baseURL))
|
||||
|
||||
client := anthropic.NewClient(opts...)
|
||||
return &Provider{
|
||||
client: &client,
|
||||
baseURL: baseURL,
|
||||
|
|
@ -77,8 +94,17 @@ func (p *Provider) Chat(
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("refreshing token: %w", err)
|
||||
}
|
||||
|
||||
// OAuth tokens (Claude Code) require special handling
|
||||
if isOAuthToken(tok) {
|
||||
opts = append(opts,
|
||||
option.WithHeader("Authorization", "Bearer "+tok),
|
||||
option.WithHeader("anthropic-beta", "oauth-2025-04-20"),
|
||||
)
|
||||
} else {
|
||||
opts = append(opts, option.WithAuthToken(tok))
|
||||
}
|
||||
}
|
||||
|
||||
params, err := buildParams(messages, tools, model, options)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue