fix: 让消息 cache_control 改写默认关闭

This commit is contained in:
shaw
2026-05-11 21:26:41 +08:00
parent 297b54d066
commit 9377c96746
15 changed files with 226 additions and 30 deletions
+2
View File
@@ -477,6 +477,7 @@ export interface SystemSettings {
enable_metadata_passthrough: boolean;
enable_cch_signing: boolean;
enable_anthropic_cache_ttl_1h_injection: boolean;
rewrite_message_cache_control: boolean;
web_search_emulation_enabled?: boolean;
// Payment configuration
@@ -673,6 +674,7 @@ export interface UpdateSettingsRequest {
enable_metadata_passthrough?: boolean;
enable_cch_signing?: boolean;
enable_anthropic_cache_ttl_1h_injection?: boolean;
rewrite_message_cache_control?: boolean;
// Payment configuration
payment_enabled?: boolean;
risk_control_enabled?: boolean;
+2
View File
@@ -5335,6 +5335,8 @@ export default {
cchSigningHint: 'Sign the billing header in forwarded requests with CCH hash. When disabled, the placeholder is preserved.',
anthropicCacheTTL1hInjection: 'Anthropic Cache TTL Injection',
anthropicCacheTTL1hInjectionHint: 'When enabled, existing ephemeral cache_control blocks in Anthropic OAuth/Setup Token request bodies are forced to 1h; response usage is billed back as 5m by default, with account-level TTL billing override taking priority.',
rewriteMessageCacheControl: 'Rewrite Message Cache Breakpoints',
rewriteMessageCacheControlHint: 'Default off: preserve client cache_control on message content blocks. When enabled, client breakpoints are stripped and proxy breakpoints are injected for clients that do not manage caching themselves.',
},
webSearchEmulation: {
title: 'Web Search Emulation',
+2
View File
@@ -5494,6 +5494,8 @@ export default {
cchSigningHint: '对转发请求的 billing header 进行 CCH 哈希签名。关闭时保留原始占位符。',
anthropicCacheTTL1hInjection: 'Anthropic 缓存 TTL 注入',
anthropicCacheTTL1hInjectionHint: '开启后,对 Anthropic OAuth/Setup Token 请求体中已有的 ephemeral 缓存块强制写入 1h;响应 usage 默认按 5m 回写计费,账号级 TTL 计费设置优先。',
rewriteMessageCacheControl: '改写消息缓存断点',
rewriteMessageCacheControlHint: '默认关闭,保留客户端在 messages 内容块中的 cache_control。开启后会清除客户端断点并注入代理断点,适合不自行管理缓存策略的客户端。',
},
webSearchEmulation: {
title: 'Web Search 模拟',
+25
View File
@@ -3428,6 +3428,29 @@
v-model="form.enable_anthropic_cache_ttl_1h_injection"
/>
</div>
<!-- messages cache_control 改写 -->
<div class="flex items-center justify-between">
<div>
<label
class="text-sm font-medium text-gray-700 dark:text-gray-300"
>
{{
t(
"admin.settings.gatewayForwarding.rewriteMessageCacheControl",
)
}}
</label>
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">
{{
t(
"admin.settings.gatewayForwarding.rewriteMessageCacheControlHint",
)
}}
</p>
</div>
<Toggle v-model="form.rewrite_message_cache_control" />
</div>
</div>
</div>
<!-- Web Search Emulation -->
@@ -6547,6 +6570,7 @@ const form = reactive<SettingsForm>({
enable_metadata_passthrough: false,
enable_cch_signing: false,
enable_anthropic_cache_ttl_1h_injection: false,
rewrite_message_cache_control: false,
// Balance & quota notification
balance_low_notify_enabled: false,
balance_low_notify_threshold: 0,
@@ -7617,6 +7641,7 @@ async function saveSettings() {
enable_cch_signing: form.enable_cch_signing,
enable_anthropic_cache_ttl_1h_injection:
form.enable_anthropic_cache_ttl_1h_injection,
rewrite_message_cache_control: form.rewrite_message_cache_control,
// Payment configuration
payment_enabled: form.payment_enabled,
risk_control_enabled: form.risk_control_enabled,
@@ -369,6 +369,7 @@ const baseSettingsResponse = {
enable_metadata_passthrough: false,
enable_cch_signing: false,
enable_anthropic_cache_ttl_1h_injection: false,
rewrite_message_cache_control: false,
payment_enabled: true,
payment_min_amount: 1,
payment_max_amount: 10000,
@@ -601,6 +602,26 @@ describe("admin SettingsView payment visible method controls", () => {
);
});
it("submits message cache_control rewrite gateway setting", async () => {
getSettings.mockResolvedValueOnce({
...baseSettingsResponse,
rewrite_message_cache_control: true,
});
const wrapper = mountView();
await flushPromises();
await wrapper.find("form").trigger("submit.prevent");
await flushPromises();
expect(updateSettings).toHaveBeenCalledTimes(1);
expect(updateSettings).toHaveBeenCalledWith(
expect.objectContaining({
rewrite_message_cache_control: true,
}),
);
});
it("updates provider enablement immediately and reloads providers", async () => {
const provider = {
id: 7,