feat(providers): support custom request headers in HTTP providers

This commit is contained in:
chanchann 2026-02-28 02:42:08 +00:00
parent 2f4f45080b
commit 41eaf48516
4 changed files with 36 additions and 13 deletions

View file

@ -464,6 +464,7 @@ type ModelConfig struct {
APIBase string `json:"api_base,omitempty"` // API endpoint URL APIBase string `json:"api_base,omitempty"` // API endpoint URL
APIKey string `json:"api_key"` // API authentication key APIKey string `json:"api_key"` // API authentication key
Proxy string `json:"proxy,omitempty"` // HTTP proxy URL Proxy string `json:"proxy,omitempty"` // HTTP proxy URL
Headers map[string]string `json:"headers,omitempty"` // Custom HTTP headers
// Special providers (CLI-based, OAuth, etc.) // Special providers (CLI-based, OAuth, etc.)
AuthMethod string `json:"auth_method,omitempty"` // Authentication method: oauth, token AuthMethod string `json:"auth_method,omitempty"` // Authentication method: oauth, token

View file

@ -84,12 +84,13 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err
if apiBase == "" { if apiBase == "" {
apiBase = getDefaultAPIBase(protocol) apiBase = getDefaultAPIBase(protocol)
} }
return NewHTTPProviderWithMaxTokensFieldAndRequestTimeout( return NewHTTPProviderWithOptions(
cfg.APIKey, cfg.APIKey,
apiBase, apiBase,
cfg.Proxy, cfg.Proxy,
cfg.MaxTokensField, cfg.MaxTokensField,
cfg.RequestTimeout, cfg.RequestTimeout,
cfg.Headers,
), modelID, nil ), modelID, nil
case "openrouter", "groq", "zhipu", "gemini", "nvidia", case "openrouter", "groq", "zhipu", "gemini", "nvidia",
@ -103,12 +104,13 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err
if apiBase == "" { if apiBase == "" {
apiBase = getDefaultAPIBase(protocol) apiBase = getDefaultAPIBase(protocol)
} }
return NewHTTPProviderWithMaxTokensFieldAndRequestTimeout( return NewHTTPProviderWithOptions(
cfg.APIKey, cfg.APIKey,
apiBase, apiBase,
cfg.Proxy, cfg.Proxy,
cfg.MaxTokensField, cfg.MaxTokensField,
cfg.RequestTimeout, cfg.RequestTimeout,
cfg.Headers,
), modelID, nil ), modelID, nil
case "anthropic": case "anthropic":
@ -128,12 +130,13 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err
if cfg.APIKey == "" { if cfg.APIKey == "" {
return nil, "", fmt.Errorf("api_key is required for anthropic protocol (model: %s)", cfg.Model) return nil, "", fmt.Errorf("api_key is required for anthropic protocol (model: %s)", cfg.Model)
} }
return NewHTTPProviderWithMaxTokensFieldAndRequestTimeout( return NewHTTPProviderWithOptions(
cfg.APIKey, cfg.APIKey,
apiBase, apiBase,
cfg.Proxy, cfg.Proxy,
cfg.MaxTokensField, cfg.MaxTokensField,
cfg.RequestTimeout, cfg.RequestTimeout,
cfg.Headers,
), modelID, nil ), modelID, nil
case "antigravity": case "antigravity":

View file

@ -31,14 +31,23 @@ func NewHTTPProviderWithMaxTokensFieldAndRequestTimeout(
apiKey, apiBase, proxy, maxTokensField string, apiKey, apiBase, proxy, maxTokensField string,
requestTimeoutSeconds int, requestTimeoutSeconds int,
) *HTTPProvider { ) *HTTPProvider {
return &HTTPProvider{ return NewHTTPProviderWithOptions(apiKey, apiBase, proxy, maxTokensField, requestTimeoutSeconds, nil)
delegate: openai_compat.NewProvider( }
apiKey,
apiBase, func NewHTTPProviderWithOptions(
proxy, apiKey, apiBase, proxy, maxTokensField string,
requestTimeoutSeconds int,
customHeaders map[string]string,
) *HTTPProvider {
opts := []openai_compat.Option{
openai_compat.WithMaxTokensField(maxTokensField), openai_compat.WithMaxTokensField(maxTokensField),
openai_compat.WithRequestTimeout(time.Duration(requestTimeoutSeconds) * time.Second), 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, opts...),
} }
} }

View file

@ -32,6 +32,7 @@ type Provider struct {
apiKey string apiKey string
apiBase string apiBase string
maxTokensField string // Field name for max tokens (e.g., "max_completion_tokens" for o1/glm models) maxTokensField string // Field name for max tokens (e.g., "max_completion_tokens" for o1/glm models)
customHeaders map[string]string
httpClient *http.Client 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 { func NewProvider(apiKey, apiBase, proxy string, opts ...Option) *Provider {
client := &http.Client{ client := &http.Client{
Timeout: defaultRequestTimeout, Timeout: defaultRequestTimeout,
@ -176,6 +183,9 @@ func (p *Provider) Chat(
if p.apiKey != "" { if p.apiKey != "" {
req.Header.Set("Authorization", "Bearer "+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) resp, err := p.httpClient.Do(req)
if err != nil { if err != nil {