fix(provider): align stream user-agent and header precedence docs

This commit is contained in:
lc6464 2026-04-07 15:41:01 +08:00
parent 7ffcd294c4
commit 92486c453f
No known key found for this signature in database
GPG key ID: 53C61B42FEC71D6D
4 changed files with 12 additions and 3 deletions

View file

@ -122,7 +122,7 @@ This design also enables **multi-agent support** with flexible provider selectio
| `max_tokens_field` | string | No | Override the max tokens field name in request body (e.g., `max_completion_tokens` for o1 models) |
| `thinking_level` | string | No | Extended thinking level: `off`, `low`, `medium`, `high`, `xhigh`, or `adaptive` |
| `extra_body` | object | No | Additional fields to inject into every request body |
| `custom_headers` | object | No | Additional HTTP headers to inject into every request (e.g., `{"X-Source":"coding-plan"}`) |
| `custom_headers` | object | No | Additional HTTP headers to inject into every request (e.g., `{"X-Source":"coding-plan"}`). If a key matches a built-in header, the custom value overrides the built-in one (e.g., `Authorization`, `User-Agent`, `Content-Type`, `Accept`). |
| `rpm` | int | No | Per-minute request rate limit |
| `fallbacks` | string[] | No | Fallback model names for automatic failover |
| `enabled` | bool | No | Whether this model entry is active (default: `true`) |

View file

@ -118,7 +118,7 @@
| `max_tokens_field` | string | 否 | 覆盖请求体中 max tokens 的字段名(如 o1 模型使用 `max_completion_tokens` |
| `thinking_level` | string | 否 | 扩展思考级别:`off``low``medium``high``xhigh``adaptive` |
| `extra_body` | object | 否 | 注入到每个请求体中的额外字段 |
| `custom_headers` | object | 否 | 注入到每个请求中的额外 HTTP 请求头(例如 `{"X-Source":"coding-plan"}` |
| `custom_headers` | object | 否 | 注入到每个请求中的额外 HTTP 请求头(例如 `{"X-Source":"coding-plan"}`。若键名与内置请求头同名,会覆盖内置值(如 `Authorization``User-Agent``Content-Type``Accept`)。 |
| `rpm` | int | 否 | 每分钟请求速率限制 |
| `fallbacks` | string[] | 否 | 自动故障转移的备用模型名称 |
| `enabled` | bool | 否 | 是否启用此模型条目(默认:`true` |

View file

@ -271,6 +271,9 @@ func (p *Provider) ChatStream(
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "text/event-stream")
if p.userAgent != "" {
req.Header.Set("User-Agent", p.userAgent)
}
if p.apiKey != "" {
req.Header.Set("Authorization", "Bearer "+p.apiKey)
}

View file

@ -765,11 +765,12 @@ func TestProviderChat_CustomHeadersInjected(t *testing.T) {
}
func TestProviderChatStream_CustomHeadersInjected(t *testing.T) {
var gotSource, gotAuth string
var gotSource, gotAuth, gotUserAgent string
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotSource = r.Header.Get("X-Source")
gotAuth = r.Header.Get("Authorization")
gotUserAgent = r.Header.Get("User-Agent")
w.Header().Set("Content-Type", "text/event-stream")
_, _ = w.Write([]byte("data: {\"choices\":[{\"delta\":{\"content\":\"ok\"},\"finish_reason\":\"stop\"}]}\n\n"))
@ -781,9 +782,11 @@ func TestProviderChatStream_CustomHeadersInjected(t *testing.T) {
"key",
server.URL,
"",
WithUserAgent("PicoClaw/Test"),
WithCustomHeaders(map[string]string{
"X-Source": "coding-plan",
"Authorization": "Token stream-auth",
"User-Agent": "Custom-UA/Stream",
}),
)
@ -807,6 +810,9 @@ func TestProviderChatStream_CustomHeadersInjected(t *testing.T) {
if gotAuth != "Token stream-auth" {
t.Fatalf("Authorization = %q, want %q", gotAuth, "Token stream-auth")
}
if gotUserAgent != "Custom-UA/Stream" {
t.Fatalf("User-Agent = %q, want %q", gotUserAgent, "Custom-UA/Stream")
}
}
type roundTripperFunc func(*http.Request) (*http.Response, error)