diff --git a/rust/crates/api/src/client.rs b/rust/crates/api/src/client.rs index d7dacbe..6901de6 100644 --- a/rust/crates/api/src/client.rs +++ b/rust/crates/api/src/client.rs @@ -439,6 +439,19 @@ impl AnthropicClient { "beta_count".to_string(), Value::from(u64::try_from(self.request_profile.betas.len()).unwrap_or(u64::MAX)), ); + if !self.request_profile.betas.is_empty() { + attributes.insert( + "betas".to_string(), + Value::Array( + self.request_profile + .betas + .iter() + .cloned() + .map(Value::String) + .collect(), + ), + ); + } if !self.request_profile.extra_body.is_empty() { attributes.insert( "extra_body_keys".to_string(), diff --git a/rust/crates/api/tests/client_integration.rs b/rust/crates/api/tests/client_integration.rs index 569c2fa..4b78d0e 100644 --- a/rust/crates/api/tests/client_integration.rs +++ b/rust/crates/api/tests/client_integration.rs @@ -75,7 +75,7 @@ async fn send_message_posts_json_and_parses_response() { ); assert_eq!( request.headers.get("anthropic-beta").map(String::as_str), - Some("claude-code-20250219") + Some("claude-code-20250219,prompt-caching-scope-2026-01-05") ); let body: serde_json::Value = serde_json::from_str(&request.body).expect("request body should be json"); @@ -86,7 +86,10 @@ async fn send_message_posts_json_and_parses_response() { assert!(body.get("stream").is_none()); assert_eq!(body["tools"][0]["name"], json!("get_weather")); assert_eq!(body["tool_choice"]["type"], json!("auto")); - assert_eq!(body["betas"], json!(["claude-code-20250219"])); + assert_eq!( + body["betas"], + json!(["claude-code-20250219", "prompt-caching-scope-2026-01-05"]) + ); } #[tokio::test] @@ -133,7 +136,7 @@ async fn send_message_applies_request_profile_and_records_telemetry() { let request = captured.first().expect("server should capture request"); assert_eq!( request.headers.get("anthropic-beta").map(String::as_str), - Some("claude-code-20250219,tools-2026-04-01") + Some("claude-code-20250219,prompt-caching-scope-2026-01-05,tools-2026-04-01") ); assert_eq!( request.headers.get("user-agent").map(String::as_str), @@ -144,7 +147,11 @@ async fn send_message_applies_request_profile_and_records_telemetry() { assert_eq!(body["metadata"]["source"], json!("clawd-code")); assert_eq!( body["betas"], - json!(["claude-code-20250219", "tools-2026-04-01"]) + json!([ + "claude-code-20250219", + "prompt-caching-scope-2026-01-05", + "tools-2026-04-01" + ]) ); let events = sink.events(); diff --git a/rust/crates/telemetry/src/lib.rs b/rust/crates/telemetry/src/lib.rs index 4a471cc..6e369e1 100644 --- a/rust/crates/telemetry/src/lib.rs +++ b/rust/crates/telemetry/src/lib.rs @@ -13,6 +13,7 @@ pub const DEFAULT_ANTHROPIC_VERSION: &str = "2023-06-01"; pub const DEFAULT_APP_NAME: &str = "claude-code"; pub const DEFAULT_RUNTIME: &str = "rust"; pub const DEFAULT_AGENTIC_BETA: &str = "claude-code-20250219"; +pub const DEFAULT_PROMPT_CACHING_SCOPE_BETA: &str = "prompt-caching-scope-2026-01-05"; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ClientIdentity { @@ -65,7 +66,10 @@ impl AnthropicRequestProfile { Self { anthropic_version: DEFAULT_ANTHROPIC_VERSION.to_string(), client_identity, - betas: vec![DEFAULT_AGENTIC_BETA.to_string()], + betas: vec![ + DEFAULT_AGENTIC_BETA.to_string(), + DEFAULT_PROMPT_CACHING_SCOPE_BETA.to_string(), + ], extra_body: Map::new(), } } @@ -445,7 +449,8 @@ mod tests { ("user-agent".to_string(), "claude-code/1.2.3".to_string()), ( "anthropic-beta".to_string(), - "claude-code-20250219,tools-2026-04-01".to_string(), + "claude-code-20250219,prompt-caching-scope-2026-01-05,tools-2026-04-01" + .to_string(), ), ] ); @@ -459,7 +464,11 @@ mod tests { ); assert_eq!( body["betas"], - serde_json::json!(["claude-code-20250219", "tools-2026-04-01"]) + serde_json::json!([ + "claude-code-20250219", + "prompt-caching-scope-2026-01-05", + "tools-2026-04-01" + ]) ); }