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

@ -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

View file

@ -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":

View file

@ -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...),
}
}

View file

@ -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 {