feat: enhance Claude request header handling with append functionality

This commit is contained in:
CaIon
2026-03-09 23:47:33 +08:00
parent 80c09d7119
commit 2c9b22153f
11 changed files with 88 additions and 14 deletions

1
.gitignore vendored
View File

@@ -21,6 +21,7 @@ tiktoken_cache
.cache
web/bun.lock
plans
.claude
electron/node_modules
electron/dist

View File

@@ -2,6 +2,7 @@ package model_setting
import (
"net/http"
"strings"
"github.com/QuantumNous/new-api/setting/config"
)
@@ -50,23 +51,36 @@ func GetClaudeSettings() *ClaudeSettings {
func (c *ClaudeSettings) WriteHeaders(originModel string, httpHeader *http.Header) {
if headers, ok := c.HeadersSettings[originModel]; ok {
for headerKey, headerValues := range headers {
// get existing values for this header key
existingValues := httpHeader.Values(headerKey)
existingValuesMap := make(map[string]bool)
for _, v := range existingValues {
existingValuesMap[v] = true
}
// add only values that don't already exist
for _, headerValue := range headerValues {
if !existingValuesMap[headerValue] {
httpHeader.Add(headerKey, headerValue)
}
mergedValues := normalizeHeaderListValues(
append(append([]string(nil), httpHeader.Values(headerKey)...), headerValues...),
)
if len(mergedValues) == 0 {
continue
}
httpHeader.Set(headerKey, strings.Join(mergedValues, ","))
}
}
}
func normalizeHeaderListValues(values []string) []string {
normalizedValues := make([]string, 0, len(values))
seenValues := make(map[string]struct{}, len(values))
for _, value := range values {
for _, item := range strings.Split(value, ",") {
normalizedItem := strings.TrimSpace(item)
if normalizedItem == "" {
continue
}
if _, exists := seenValues[normalizedItem]; exists {
continue
}
seenValues[normalizedItem] = struct{}{}
normalizedValues = append(normalizedValues, normalizedItem)
}
}
return normalizedValues
}
func (c *ClaudeSettings) GetDefaultMaxTokens(model string) int {
if maxTokens, ok := c.DefaultMaxTokens[model]; ok {
return maxTokens

View File

@@ -369,6 +369,7 @@ const AWS_BEDROCK_ANTHROPIC_COMPAT_TEMPLATE = {
'tool-search-tool-2025-10-19': 'tool-search-tool-2025-10-19',
'web-fetch-2025-09-10': null,
'web-search-2025-03-05': null,
'oauth-2025-04-20': null
},
},
{

View File

@@ -85,6 +85,8 @@
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比": "Claude thinking adaptation BudgetTokens = MaxTokens * BudgetTokens percentage",
"Claude设置": "Claude settings",
"Claude请求头覆盖": "Claude request header override",
"Claude请求头追加": "Claude request header append",
"Claude会在原有请求头基础上追加这些值不会覆盖已有同名请求头重复值会自动忽略。": "Claude appends these values on top of existing request headers. Existing headers are not overwritten, and duplicate values are ignored automatically.",
"Client ID": "Client ID",
"Client Secret": "Client Secret",
"Codex 授权": "",
@@ -1781,6 +1783,9 @@
"格式化 JSON": "Format JSON",
"格式正确": "Format Correct",
"格式示例:": "Format example:",
"前:": "Before:",
"配置:": "Config:",
"后:": "After:",
"格式错误": "Format Error",
"检查更新": "Check for updates",
"检测到 FluentRead流畅阅读": "FluentRead (smooth reading) detected",

View File

@@ -86,6 +86,8 @@
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比": "Adaptation de la pensée Claude BudgetTokens = MaxTokens * BudgetTokens pourcentage",
"Claude设置": "Paramètres Claude",
"Claude请求头覆盖": "Remplacement de l'en-tête de la requête Claude",
"Claude请求头追加": "Ajout des en-tetes de requete Claude",
"Claude会在原有请求头基础上追加这些值不会覆盖已有同名请求头重复值会自动忽略。": "Claude ajoute ces valeurs aux en-tetes de requete existants. Les en-tetes existants ne sont pas remplaces et les valeurs en double sont ignorees automatiquement.",
"Client ID": "ID client",
"Client Secret": "Secret client",
"Codex 授权": "",
@@ -1765,6 +1767,9 @@
"格式化 JSON": "Formater le JSON",
"格式正确": "Format valide",
"格式示例:": "Exemple de format :",
"前:": "Avant :",
"配置:": "Configuration :",
"后:": "Apres :",
"格式错误": "Format invalide",
"检查更新": "Vérifier les mises à jour",
"检测到 FluentRead流畅阅读": "FluentRead détecté",

View File

@@ -82,6 +82,8 @@
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比": "Claude思考モードBudgetTokens = MaxTokens * BudgetTokensの割合",
"Claude设置": "Claude設定",
"Claude请求头覆盖": "Claudeリクエストヘッダーの上書き",
"Claude请求头追加": "Claudeリクエストヘッダーの追加",
"Claude会在原有请求头基础上追加这些值不会覆盖已有同名请求头重复值会自动忽略。": "Claude は既存のリクエストヘッダーにこれらの値を追加します。既存の同名ヘッダーは上書きされず、重複した値は自動的に無視されます。",
"Client ID": "Client ID",
"Client Secret": "Client Secret",
"Codex 授权": "",
@@ -1748,6 +1750,9 @@
"格式化 JSON": "JSON を整形",
"格式正确": "有効な形式",
"格式示例:": "フォーマット例:",
"前:": "前:",
"配置:": "設定:",
"后:": "後:",
"格式错误": "無効な形式",
"检查更新": "更新を確認",
"检测到 FluentRead流畅阅读": "FluentReadが検出されました",

View File

@@ -89,6 +89,8 @@
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比": "Адаптация мышления Claude BudgetTokens = MaxTokens * процент BudgetTokens",
"Claude设置": "Настройки Claude",
"Claude请求头覆盖": "Переопределение заголовков запроса Claude",
"Claude请求头追加": "Добавление заголовков запроса Claude",
"Claude会在原有请求头基础上追加这些值不会覆盖已有同名请求头重复值会自动忽略。": "Claude добавляет эти значения поверх существующих заголовков запроса. Уже существующие заголовки не перезаписываются, а дублирующиеся значения автоматически игнорируются.",
"Client ID": "ID клиента",
"Client Secret": "Секрет клиента",
"Codex 授权": "",
@@ -1777,6 +1779,9 @@
"格式化 JSON": "Форматировать JSON",
"格式正确": "Действительный формат",
"格式示例:": "Пример формата: ",
"前:": "До:",
"配置:": "Конфиг:",
"后:": "После:",
"格式错误": "Недействительный формат",
"检查更新": "Проверить обновления",
"检测到 FluentRead流畅阅读": "Обнаружен FluentRead (плавное чтение)",

View File

@@ -82,6 +82,8 @@
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比": "Thích ứng tư duy Claude BudgetTokens = MaxTokens * Tỷ lệ phần trăm BudgetTokens",
"Claude设置": "Cài đặt Claude",
"Claude请求头覆盖": "Ghi đè tiêu đề yêu cầu Claude",
"Claude请求头追加": "Thêm tiêu đề yêu cầu Claude",
"Claude会在原有请求头基础上追加这些值不会覆盖已有同名请求头重复值会自动忽略。": "Claude sẽ thêm các giá trị này vào các tiêu đề yêu cầu hiện có. Các tiêu đề cùng tên sẽ không bị ghi đè và các giá trị trùng lặp sẽ tự động bị bỏ qua.",
"Client ID": "Client ID",
"Client Secret": "Client Secret",
"Codex 授权": "",
@@ -1749,6 +1751,9 @@
"格式化 JSON": "Định dạng JSON",
"格式正确": "Định dạng hợp lệ",
"格式示例:": "Ví dụ định dạng:",
"前:": "Trước:",
"配置:": "Cấu hình:",
"后:": "Sau:",
"格式错误": "Định dạng không hợp lệ",
"检查更新": "Kiểm tra cập nhật",
"检测到 FluentRead流畅阅读": "Đã phát hiện FluentRead (đọc trôi chảy)",

View File

@@ -69,6 +69,8 @@
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比": "Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比",
"Claude设置": "Claude设置",
"Claude请求头覆盖": "Claude请求头覆盖",
"Claude请求头追加": "Claude请求头追加",
"Claude会在原有请求头基础上追加这些值不会覆盖已有同名请求头重复值会自动忽略。": "Claude会在原有请求头基础上追加这些值不会覆盖已有同名请求头重复值会自动忽略。",
"Client ID": "Client ID",
"Client Secret": "Client Secret",
"common.changeLanguage": "common.changeLanguage",
@@ -1415,6 +1417,7 @@
"格式化": "格式化",
"格式正确": "格式正确",
"格式示例:": "格式示例:",
"前:": "前:",
"格式错误": "格式错误",
"检查更新": "检查更新",
"检测到 FluentRead流畅阅读": "检测到 FluentRead流畅阅读",
@@ -2830,7 +2833,9 @@
"下面展示这个模型保存后会写入哪些后端字段,便于和原始 JSON 编辑框保持一致。": "下面展示这个模型保存后会写入哪些后端字段,便于和原始 JSON 编辑框保持一致。",
"补全价格已锁定": "补全价格已锁定",
"后端固定倍率:{{ratio}}。该字段仅展示换算后的价格。": "后端固定倍率:{{ratio}}。该字段仅展示换算后的价格。",
"后:": "后:",
"这些价格都是可选项,不填也可以。": "这些价格都是可选项,不填也可以。",
"配置:": "配置:",
"请先开启并填写音频输入价格。": "请先开启并填写音频输入价格。",
"输入模型名称,例如 gpt-4.1": "输入模型名称,例如 gpt-4.1",
"当前模型同时存在按次价格和倍率配置,保存时会按当前计费方式覆盖。": "当前模型同时存在按次价格和倍率配置,保存时会按当前计费方式覆盖。",

View File

@@ -69,6 +69,8 @@
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比": "Claude思考相容 BudgetTokens = MaxTokens * BudgetTokens 百分比",
"Claude设置": "Claude設定",
"Claude请求头覆盖": "Claude請求頭覆蓋",
"Claude请求头追加": "Claude請求頭追加",
"Claude会在原有请求头基础上追加这些值不会覆盖已有同名请求头重复值会自动忽略。": "Claude會在原有請求頭基礎上追加這些值不會覆蓋已有同名請求頭重複值會自動忽略。",
"Client ID": "Client ID",
"Client Secret": "Client Secret",
"common.changeLanguage": "common.changeLanguage",
@@ -1419,6 +1421,9 @@
"格式化": "格式化",
"格式正确": "格式正確",
"格式示例:": "格式示例:",
"前:": "前:",
"配置:": "配置:",
"后:": "後:",
"格式错误": "格式錯誤",
"检查更新": "檢查更新",
"检测到 FluentRead流畅阅读": "檢測到 FluentRead流暢閱讀",

View File

@@ -39,6 +39,16 @@ const CLAUDE_HEADER = {
},
};
const CLAUDE_HEADER_APPEND_CONFIG = {
'claude-3-7-sonnet-20250219-thinking': {
'anthropic-beta': ['token-efficient-tools-2025-02-19'],
},
};
const CLAUDE_HEADER_APPEND_BEFORE = `anthropic-beta: output-128k-2025-02-19`;
const CLAUDE_HEADER_APPEND_AFTER = `anthropic-beta: output-128k-2025-02-19,token-efficient-tools-2025-02-19`;
const CLAUDE_DEFAULT_MAX_TOKENS = {
default: 8192,
'claude-3-haiku-20240307': 4096,
@@ -114,7 +124,7 @@ export default function SettingClaudeModel(props) {
<Row>
<Col xs={24} sm={12} md={8} lg={8} xl={8}>
<Form.TextArea
label={t('Claude请求头覆盖')}
label={t('Claude请求头追加')}
field={'claude.model_headers_settings'}
placeholder={
t('为一个 JSON 文本,例如:') +
@@ -122,7 +132,20 @@ export default function SettingClaudeModel(props) {
JSON.stringify(CLAUDE_HEADER, null, 2)
}
extraText={
t('示例') + '\n' + JSON.stringify(CLAUDE_HEADER, null, 2)
<div>
<div>
{t(
'Claude会在原有请求头基础上追加这些值不会覆盖已有同名请求头重复值会自动忽略。',
)}
</div>
<div className='mt-2 whitespace-pre-wrap font-mono text-xs'>
{`${t('前:')}\n${CLAUDE_HEADER_APPEND_BEFORE}\n\n${t('配置:')}\n${JSON.stringify(
CLAUDE_HEADER_APPEND_CONFIG,
null,
2,
)}\n\n${t('后:')}\n${CLAUDE_HEADER_APPEND_AFTER}`}
</div>
</div>
}
autosize={{ minRows: 6, maxRows: 12 }}
trigger='blur'