diff --git a/frontend/src/api/admin/settings.ts b/frontend/src/api/admin/settings.ts index 1e4a305309..3452c60995 100644 --- a/frontend/src/api/admin/settings.ts +++ b/frontend/src/api/admin/settings.ts @@ -428,6 +428,12 @@ export interface RectifierSettings { thinking_budget_enabled: boolean apikey_signature_enabled: boolean apikey_signature_patterns: string[] + /** + * 签名池容量。0 = 关闭池化,签名错误时走"剥除 thinking 重试"; + * \>0 = 从正常响应抓取签名入池,签名错误时从池中取签名替换重试, + * 池空直接透传错误(不回退剥除)。 + */ + signature_pool_size: number } /** diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index a9b0ea30c7..f59b92d5bf 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -4763,16 +4763,24 @@ export default { enabledHint: 'Master switch - disabling turns off all rectification features', thinkingSignature: 'Thinking Signature Rectifier', thinkingSignatureHint: 'Automatically strip signatures and retry when upstream returns thinking block signature validation errors', + thinkingSignatureHintPool: + 'Automatically replace bad signatures with pooled ones when upstream returns thinking block signature validation errors (pass through original error when pool is empty)', thinkingBudget: 'Thinking Budget Rectifier', thinkingBudgetHint: 'Automatically set budget to 32000 and retry when upstream returns budget_tokens constraint error (≥1024)', apikeySignature: 'API Key Signature Rectifier', apikeySignatureHint: 'Automatically strip signatures and retry when API Key accounts receive signature-related errors (built-in patterns always apply)', + apikeySignatureHintPool: + 'Automatically replace bad signatures with pooled ones when API Key accounts receive signature-related errors (pass through original error when pool is empty)', apikeyPatterns: 'Custom Match Patterns', apikeyPatternsHint: 'Additional keywords matched against the response body (case-insensitive). Built-in patterns always apply; use these for supplementary matching.', apikeyPatternPlaceholder: 'e.g., thinking_error', addPattern: 'Add Pattern', + poolSize: 'Signature Pool Size', + poolSizeHint: + '0 = pool disabled (legacy "strip and retry" behavior); >0 = harvest thinking signatures from successful responses into a Redis pool, then replace bad signatures with pooled ones on retry. OAuth/Setup accounts share one pool; each API Key account has its own. Signatures have a soft TTL of 1 hour; oldest entries are evicted when the pool is full.', + poolSizeUnit: 'entries', saved: 'Rectifier settings saved', saveFailed: 'Failed to save rectifier settings' }, diff --git a/frontend/src/i18n/locales/zh.ts b/frontend/src/i18n/locales/zh.ts index 7659ea80f4..a65189ca5e 100644 --- a/frontend/src/i18n/locales/zh.ts +++ b/frontend/src/i18n/locales/zh.ts @@ -4934,16 +4934,24 @@ export default { enabledHint: '总开关,关闭后所有整流功能均不生效', thinkingSignature: 'Thinking 签名整流', thinkingSignatureHint: '当上游返回 thinking block 签名校验错误时,自动去除签名并重试', + thinkingSignatureHintPool: + '当上游返回 thinking block 签名校验错误时,自动使用签名池中的签名(池空直接透传错误)', thinkingBudget: 'Thinking Budget 整流', thinkingBudgetHint: '当上游返回 budget_tokens 约束错误(≥1024)时,自动将 budget 设为 32000 并重试', apikeySignature: 'API Key 签名整流', apikeySignatureHint: '当 API Key 账号的上游返回签名相关错误时,自动去除签名并重试(内置规则始终生效)', + apikeySignatureHintPool: + '当 API Key 账号的上游返回签名相关错误时,自动使用签名池中的签名替换(池空直接透传错误)', apikeyPatterns: '自定义匹配关键词', apikeyPatternsHint: '额外的关键词,匹配响应体中的内容(不区分大小写)。内置规则始终生效,此处用于补充额外匹配。', apikeyPatternPlaceholder: '例如:thinking_error 或 签名无效', addPattern: '添加关键词', + poolSize: '签名池大小', + poolSizeHint: + '0 = 关闭池化(沿用"剥除 thinking 重试");>0 = 从成功响应抓取 thinking 签名到 Redis 池,签名错误时从池中取签名替换请求后重试。OAuth/Setup 账号共享一个池,每个 API Key 账号独立一个池。签名软 TTL 1 小时,池满后按时间淘汰最老的。', + poolSizeUnit: '条', saved: '整流器设置保存成功', saveFailed: '保存整流器设置失败' }, diff --git a/frontend/src/views/admin/SettingsView.vue b/frontend/src/views/admin/SettingsView.vue index ee6a4c6d41..dd6fec3376 100644 --- a/frontend/src/views/admin/SettingsView.vue +++ b/frontend/src/views/admin/SettingsView.vue @@ -429,6 +429,32 @@ v-if="rectifierForm.enabled" class="space-y-4 border-t border-gray-100 pt-4 dark:border-dark-700" > + +
+
+
+ +

+ {{ t('admin.settings.rectifier.poolSizeHint') }} +

+
+
+ + {{ + t('admin.settings.rectifier.poolSizeUnit') + }} +
+
+
+
@@ -436,7 +462,11 @@ t('admin.settings.rectifier.thinkingSignature') }}

- {{ t('admin.settings.rectifier.thinkingSignatureHint') }} + {{ + rectifierForm.signature_pool_size > 0 + ? t('admin.settings.rectifier.thinkingSignatureHintPool') + : t('admin.settings.rectifier.thinkingSignatureHint') + }}

@@ -462,7 +492,11 @@ t('admin.settings.rectifier.apikeySignature') }}

- {{ t('admin.settings.rectifier.apikeySignatureHint') }} + {{ + rectifierForm.signature_pool_size > 0 + ? t('admin.settings.rectifier.apikeySignatureHintPool') + : t('admin.settings.rectifier.apikeySignatureHint') + }}

@@ -2923,7 +2957,8 @@ const rectifierForm = reactive({ thinking_signature_enabled: true, thinking_budget_enabled: true, apikey_signature_enabled: false, - apikey_signature_patterns: [] as string[] + apikey_signature_patterns: [] as string[], + signature_pool_size: 0 }) // Beta Policy 状态 @@ -3893,7 +3928,8 @@ async function saveRectifierSettings() { apikey_signature_enabled: rectifierForm.apikey_signature_enabled, apikey_signature_patterns: rectifierForm.apikey_signature_patterns.filter( (p) => p.trim() !== '' - ) + ), + signature_pool_size: rectifierForm.signature_pool_size }) Object.assign(rectifierForm, updated) if (!Array.isArray(rectifierForm.apikey_signature_patterns)) {