diff --git a/src-tauri/src/proxy/cache_injector.rs b/src-tauri/src/proxy/cache_injector.rs index e2b0464ad..a6bf8c9c9 100644 --- a/src-tauri/src/proxy/cache_injector.rs +++ b/src-tauri/src/proxy/cache_injector.rs @@ -13,6 +13,15 @@ pub fn inject(body: &mut Value, config: &OptimizerConfig) { let existing = count_existing(body); + if existing > 4 { + // Existing markers are caller-owned. Do not silently delete or reorder + // them; surface the invalid/unsupported total and leave validation to + // the upstream provider. + log::warn!( + "[OPT] cache: existing breakpoint count {existing} exceeds the supported total of 4; preserving caller input" + ); + } + // 升级已有断点的 TTL upgrade_existing_ttl(body, &config.cache_ttl); @@ -288,6 +297,32 @@ mod tests { .is_some()); } + #[test] + fn test_more_than_four_existing_breakpoints_are_preserved() { + let mut body = json!({ + "model": "test", + "tools": [ + {"name": "t1", "cache_control": {"type": "ephemeral"}}, + {"name": "t2", "cache_control": {"type": "ephemeral"}} + ], + "system": [ + {"type": "text", "text": "s1", "cache_control": {"type": "ephemeral"}}, + {"type": "text", "text": "s2", "cache_control": {"type": "ephemeral"}} + ], + "messages": [{"role": "user", "content": [ + {"type": "text", "text": "m1", "cache_control": {"type": "ephemeral"}}, + {"type": "text", "text": "m2"} + ]}] + }); + + inject(&mut body, &default_config()); + + assert_eq!(count_existing(&body), 5); + assert!(body["messages"][0]["content"][1] + .get("cache_control") + .is_none()); + } + #[test] fn test_system_string_converted_to_array() { let mut body = json!({ diff --git a/src-tauri/src/proxy/forwarder.rs b/src-tauri/src/proxy/forwarder.rs index ab6ab134e..5d62fed39 100644 --- a/src-tauri/src/proxy/forwarder.rs +++ b/src-tauri/src/proxy/forwarder.rs @@ -1450,7 +1450,7 @@ impl RequestForwarder { // configured TTL rather than silently forcing 5m on this conversion path. // otherwise system/tools/history are re-sent at full price every round, // inflating cost and first-token latency. The injector handles the - // string→array `system` conversion and the 4-breakpoint cap. + // string→array `system` conversion and the new-breakpoint budget. super::cache_injector::inject( &mut anthropic_body, &super::types::OptimizerConfig {