feat(provider): 在请求头中新增 User-Agent 预设配置#5460
feat(provider): 在请求头中新增 User-Agent 预设配置#5460piexian wants to merge 3 commits intoAstrBotDevs:masterfrom
Conversation
Summary of ChangesHello @piexian, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 此拉取请求旨在通过在 WebUI 中引入统一且直观的请求头配置,增强用户体验和系统兼容性。通过为所有提供商默认启用自定义请求头,并提供常用字段(如 User-Agent)的预设模板,它解决了现有配置不直观的问题,并有效降低了因缺少特定请求头而导致的潜在服务拦截风险。这些改进确保了无论新旧配置,都能无缝支持高级请求头定制。 Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Hey - 我发现了两个问题,并给出了一些整体性的反馈:
- 在
withDefaultCustomHeaders中,使用JSON.parse(JSON.stringify(entry || {}))进行克隆可能过于笨重,而且会在没有提示的情况下丢弃非 JSON 安全的值;可以考虑直接修改原对象,或者使用更安全的克隆机制,比如在可用的环境下使用structuredClone。 - 在后端模板和前端(创建 + 规范化)同时为
custom_headers设置默认值会引入一些冗余;如果可能,建议把默认逻辑集中放在一侧,从而降低两边随着时间推移出现不一致的风险。
面向 AI 代理的提示词
Please address the comments from this code review:
## Overall Comments
- In `withDefaultCustomHeaders`, using `JSON.parse(JSON.stringify(entry || {}))` for cloning may be unnecessarily heavy and can silently strip non-JSON-safe values; consider either mutating the original object directly or using a safer clone mechanism like `structuredClone` (where available).
- Defaulting `custom_headers` on both the backend templates and the frontend (creation + normalization) introduces some redundancy; if possible, centralize the defaulting logic on one side to reduce the risk of the two drifting out of sync over time.
## Individual Comments
### Comment 1
<location path="dashboard/src/composables/useProviderSources.ts" line_range="43-52" />
<code_context>
const confirmDialog = useConfirmDialog()
+ function withDefaultCustomHeaders<T extends Record<string, any>>(entry: T): T {
+ const normalized = JSON.parse(JSON.stringify(entry || {}))
+ if (
+ !Object.prototype.hasOwnProperty.call(normalized, 'custom_headers') ||
+ typeof normalized.custom_headers !== 'object' ||
+ normalized.custom_headers === null ||
+ Array.isArray(normalized.custom_headers)
+ ) {
+ normalized.custom_headers = {}
+ }
+ return normalized as T
+ }
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Avoid JSON.parse/JSON.stringify for cloning here to prevent data loss and unnecessary overhead.
`JSON.parse(JSON.stringify(entry || {}))` will drop non-JSON-safe values (e.g., `Date`, `undefined`, class instances) and adds unnecessary cost. Since we only need to normalize `custom_headers`, we can shallow-copy and fix that field only:
```ts
function withDefaultCustomHeaders<T extends Record<string, any>>(entry: T): T {
const normalized = { ...entry } as any
const headers = normalized.custom_headers
if (!headers || typeof headers !== 'object' || Array.isArray(headers)) {
normalized.custom_headers = {}
}
return normalized as T
}
```
This avoids data loss, keeps other fields intact, and is cheaper than deep cloning.
</issue_to_address>
### Comment 2
<location path="astrbot/core/config/default.py" line_range="1633-1639" />
<code_context>
"type": "dict",
"items": {},
"hint": "此处添加的键值对将被合并到 OpenAI SDK 的 default_headers 中,用于自定义 HTTP 请求头。值必须为字符串。",
+ "template_schema": {
+ "User-Agent": {
+ "name": "User-Agent",
+ "description": "User-Agent 请求头",
+ "hint": "用于覆盖默认客户端标识。",
+ "type": "string",
+ "default": "",
+ },
+ "Accept": {
+ "name": "Accept",
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Reconsider defaulting the `Accept` header value to avoid unintentionally overriding SDK or provider defaults.
The `template_schema` sets a default `Accept: application/json`, which can override SDK/provider defaults that may expect different or more flexible values (e.g., streaming, audio, or `*/*`). Consider leaving the default empty so provider defaults apply, and requiring users to set `Accept` only when they intentionally want to override it, reducing subtle content negotiation issues.
```suggestion
"Accept": {
"name": "Accept",
"description": "Accept 请求头",
"hint": "声明可接受的响应类型。默认留空以使用 SDK/服务端默认值,仅在需要时显式覆盖(例如指定 application/json)。",
"type": "string",
"default": "",
},
```
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的评审。
Original comment in English
Hey - I've found 2 issues, and left some high level feedback:
- In
withDefaultCustomHeaders, usingJSON.parse(JSON.stringify(entry || {}))for cloning may be unnecessarily heavy and can silently strip non-JSON-safe values; consider either mutating the original object directly or using a safer clone mechanism likestructuredClone(where available). - Defaulting
custom_headerson both the backend templates and the frontend (creation + normalization) introduces some redundancy; if possible, centralize the defaulting logic on one side to reduce the risk of the two drifting out of sync over time.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `withDefaultCustomHeaders`, using `JSON.parse(JSON.stringify(entry || {}))` for cloning may be unnecessarily heavy and can silently strip non-JSON-safe values; consider either mutating the original object directly or using a safer clone mechanism like `structuredClone` (where available).
- Defaulting `custom_headers` on both the backend templates and the frontend (creation + normalization) introduces some redundancy; if possible, centralize the defaulting logic on one side to reduce the risk of the two drifting out of sync over time.
## Individual Comments
### Comment 1
<location path="dashboard/src/composables/useProviderSources.ts" line_range="43-52" />
<code_context>
const confirmDialog = useConfirmDialog()
+ function withDefaultCustomHeaders<T extends Record<string, any>>(entry: T): T {
+ const normalized = JSON.parse(JSON.stringify(entry || {}))
+ if (
+ !Object.prototype.hasOwnProperty.call(normalized, 'custom_headers') ||
+ typeof normalized.custom_headers !== 'object' ||
+ normalized.custom_headers === null ||
+ Array.isArray(normalized.custom_headers)
+ ) {
+ normalized.custom_headers = {}
+ }
+ return normalized as T
+ }
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Avoid JSON.parse/JSON.stringify for cloning here to prevent data loss and unnecessary overhead.
`JSON.parse(JSON.stringify(entry || {}))` will drop non-JSON-safe values (e.g., `Date`, `undefined`, class instances) and adds unnecessary cost. Since we only need to normalize `custom_headers`, we can shallow-copy and fix that field only:
```ts
function withDefaultCustomHeaders<T extends Record<string, any>>(entry: T): T {
const normalized = { ...entry } as any
const headers = normalized.custom_headers
if (!headers || typeof headers !== 'object' || Array.isArray(headers)) {
normalized.custom_headers = {}
}
return normalized as T
}
```
This avoids data loss, keeps other fields intact, and is cheaper than deep cloning.
</issue_to_address>
### Comment 2
<location path="astrbot/core/config/default.py" line_range="1633-1639" />
<code_context>
"type": "dict",
"items": {},
"hint": "此处添加的键值对将被合并到 OpenAI SDK 的 default_headers 中,用于自定义 HTTP 请求头。值必须为字符串。",
+ "template_schema": {
+ "User-Agent": {
+ "name": "User-Agent",
+ "description": "User-Agent 请求头",
+ "hint": "用于覆盖默认客户端标识。",
+ "type": "string",
+ "default": "",
+ },
+ "Accept": {
+ "name": "Accept",
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Reconsider defaulting the `Accept` header value to avoid unintentionally overriding SDK or provider defaults.
The `template_schema` sets a default `Accept: application/json`, which can override SDK/provider defaults that may expect different or more flexible values (e.g., streaming, audio, or `*/*`). Consider leaving the default empty so provider defaults apply, and requiring users to set `Accept` only when they intentionally want to override it, reducing subtle content negotiation issues.
```suggestion
"Accept": {
"name": "Accept",
"description": "Accept 请求头",
"hint": "声明可接受的响应类型。默认留空以使用 SDK/服务端默认值,仅在需要时显式覆盖(例如指定 application/json)。",
"type": "string",
"default": "",
},
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
主要解决 WebUI 中请求头配置不直观、且并非所有供应商都默认显示 custom_headers 的问题。通过统一展示并提供 User-Agent 等预设字段,降低某些api网站开启 Cloudflare Bot 被误拦截风险。
Modifications / 改动点
修改
astrbot/core/config/default.py:custom_headers增加template_schema预设字段:User-Agent、Accept、Accept-Language。config_template(chat_completion / agent_runner / speech_to_text / text_to_speech / embedding / rerank)补齐默认custom_headers: {}。修改
dashboard/src/composables/useProviderSources.ts:provider_sources与providers时自动补齐缺失的custom_headers,保证旧配置在编辑时也能显示该项。custom_headers: {}。修改i18n文案:
dashboard/src/i18n/locales/zh-CN/features/config-metadata.jsondashboard/src/i18n/locales/en-US/features/config-metadata.jsoncustom_headers.template_schema的字段名称与提示信息。This is NOT a breaking change. / 这不是一个破坏性变更。
Screenshots or Test Results / 运行截图或测试结果
Checklist / 检查清单
requirements.txt和pyproject.toml文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations inrequirements.txtandpyproject.toml.Summary by Sourcery
为所有 provider 配置添加可配置的 HTTP 自定义请求头预设,并确保它们在 Web 界面中可见且有默认值。
新功能:
User-Agent、Accept和Accept-Language。custom_headers默认设置为空对象。增强:
custom_headers对象,以在控制台中保持向后兼容性。文档:
custom_headers预设字段。Original summary in English
Summary by Sourcery
Add configurable HTTP custom headers with presets to all provider configurations and ensure they are visible and defaulted in the Web UI.
New Features:
Enhancements:
Documentation: