From 41eaf48516e9b71783b0137bd3fe88599a2ae232 Mon Sep 17 00:00:00 2001 From: chanchann Date: Sat, 28 Feb 2026 02:42:08 +0000 Subject: [PATCH] feat(providers): support custom request headers in HTTP providers --- pkg/config/config.go | 7 ++++--- pkg/providers/factory_provider.go | 9 ++++++--- pkg/providers/http_provider.go | 23 ++++++++++++++++------- pkg/providers/openai_compat/provider.go | 10 ++++++++++ 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index d84772d2b..9eadef797 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -461,9 +461,10 @@ type ModelConfig struct { Model string `json:"model"` // Protocol/model-identifier (e.g., "openai/gpt-4o", "anthropic/claude-sonnet-4.6") // HTTP-based providers - APIBase string `json:"api_base,omitempty"` // API endpoint URL - APIKey string `json:"api_key"` // API authentication key - Proxy string `json:"proxy,omitempty"` // HTTP proxy URL + APIBase string `json:"api_base,omitempty"` // API endpoint URL + APIKey string `json:"api_key"` // API authentication key + Proxy string `json:"proxy,omitempty"` // HTTP proxy URL + Headers map[string]string `json:"headers,omitempty"` // Custom HTTP headers // Special providers (CLI-based, OAuth, etc.) AuthMethod string `json:"auth_method,omitempty"` // Authentication method: oauth, token diff --git a/pkg/providers/factory_provider.go b/pkg/providers/factory_provider.go index 53f7a08a0..74d935ea2 100644 --- a/pkg/providers/factory_provider.go +++ b/pkg/providers/factory_provider.go @@ -84,12 +84,13 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err if apiBase == "" { apiBase = getDefaultAPIBase(protocol) } - return NewHTTPProviderWithMaxTokensFieldAndRequestTimeout( + return NewHTTPProviderWithOptions( cfg.APIKey, apiBase, cfg.Proxy, cfg.MaxTokensField, cfg.RequestTimeout, + cfg.Headers, ), modelID, nil case "openrouter", "groq", "zhipu", "gemini", "nvidia", @@ -103,12 +104,13 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err if apiBase == "" { apiBase = getDefaultAPIBase(protocol) } - return NewHTTPProviderWithMaxTokensFieldAndRequestTimeout( + return NewHTTPProviderWithOptions( cfg.APIKey, apiBase, cfg.Proxy, cfg.MaxTokensField, cfg.RequestTimeout, + cfg.Headers, ), modelID, nil case "anthropic": @@ -128,12 +130,13 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err if cfg.APIKey == "" { return nil, "", fmt.Errorf("api_key is required for anthropic protocol (model: %s)", cfg.Model) } - return NewHTTPProviderWithMaxTokensFieldAndRequestTimeout( + return NewHTTPProviderWithOptions( cfg.APIKey, apiBase, cfg.Proxy, cfg.MaxTokensField, cfg.RequestTimeout, + cfg.Headers, ), modelID, nil case "antigravity": diff --git a/pkg/providers/http_provider.go b/pkg/providers/http_provider.go index 5c328f418..aa35f1db5 100644 --- a/pkg/providers/http_provider.go +++ b/pkg/providers/http_provider.go @@ -31,14 +31,23 @@ func NewHTTPProviderWithMaxTokensFieldAndRequestTimeout( apiKey, apiBase, proxy, maxTokensField string, requestTimeoutSeconds int, ) *HTTPProvider { + return NewHTTPProviderWithOptions(apiKey, apiBase, proxy, maxTokensField, requestTimeoutSeconds, nil) +} + +func NewHTTPProviderWithOptions( + apiKey, apiBase, proxy, maxTokensField string, + requestTimeoutSeconds int, + customHeaders map[string]string, +) *HTTPProvider { + opts := []openai_compat.Option{ + openai_compat.WithMaxTokensField(maxTokensField), + openai_compat.WithRequestTimeout(time.Duration(requestTimeoutSeconds) * time.Second), + } + if customHeaders != nil { + opts = append(opts, openai_compat.WithCustomHeaders(customHeaders)) + } return &HTTPProvider{ - delegate: openai_compat.NewProvider( - apiKey, - apiBase, - proxy, - openai_compat.WithMaxTokensField(maxTokensField), - openai_compat.WithRequestTimeout(time.Duration(requestTimeoutSeconds)*time.Second), - ), + delegate: openai_compat.NewProvider(apiKey, apiBase, proxy, opts...), } } diff --git a/pkg/providers/openai_compat/provider.go b/pkg/providers/openai_compat/provider.go index 5dab9b03e..2fb351d23 100644 --- a/pkg/providers/openai_compat/provider.go +++ b/pkg/providers/openai_compat/provider.go @@ -32,6 +32,7 @@ type Provider struct { apiKey string apiBase string maxTokensField string // Field name for max tokens (e.g., "max_completion_tokens" for o1/glm models) + customHeaders map[string]string httpClient *http.Client } @@ -53,6 +54,12 @@ func WithRequestTimeout(timeout time.Duration) Option { } } +func WithCustomHeaders(headers map[string]string) Option { + return func(p *Provider) { + p.customHeaders = headers + } +} + func NewProvider(apiKey, apiBase, proxy string, opts ...Option) *Provider { client := &http.Client{ Timeout: defaultRequestTimeout, @@ -176,6 +183,9 @@ func (p *Provider) Chat( if p.apiKey != "" { req.Header.Set("Authorization", "Bearer "+p.apiKey) } + for key, value := range p.customHeaders { + req.Header.Set(key, value) + } resp, err := p.httpClient.Do(req) if err != nil {