use super::super::conversion::transform_unified_messages;
use super::super::types::{AnthropicContent, AnthropicContentBlock};
use crate::config::AnthropicConfig;
use crate::internals::retry::RetryPolicy;
use crate::messages::{
CacheType, MessageAttributes, MessageCategory, MessageContent, MessageRole, UnifiedMessage,
};
use chrono::Utc;
use std::collections::HashMap;
fn create_test_config() -> AnthropicConfig {
AnthropicConfig {
api_key: Some("test-key".to_string()),
base_url: "https://api.anthropic.com".to_string(),
default_model: "claude-3-5-sonnet-20241022".to_string(),
max_context_tokens: 200_000,
retry_policy: RetryPolicy::default(),
enable_prompt_caching: true,
cache_ttl: "1h".to_string(),
}
}
fn create_message(role: MessageRole, content: &str, cacheable: bool) -> UnifiedMessage {
UnifiedMessage {
role,
content: MessageContent::Text(content.to_string()),
attributes: MessageAttributes {
priority: 0,
cacheable,
cache_type: None,
cache_key: None,
category: MessageCategory::Current,
metadata: HashMap::new(),
},
timestamp: Utc::now(),
}
}
fn create_message_with_cache_type(
role: MessageRole,
content: &str,
cache_type: CacheType,
) -> UnifiedMessage {
UnifiedMessage {
role,
content: MessageContent::Text(content.to_string()),
attributes: MessageAttributes {
priority: 0,
cacheable: true,
cache_type: Some(cache_type),
cache_key: None,
category: MessageCategory::Current,
metadata: HashMap::new(),
},
timestamp: Utc::now(),
}
}
fn create_tool_call_message(id: &str, name: &str) -> UnifiedMessage {
UnifiedMessage {
role: MessageRole::Assistant,
content: MessageContent::ToolCall {
id: id.to_string(),
name: name.to_string(),
arguments: serde_json::json!({"arg": "value"}),
},
attributes: MessageAttributes {
priority: 0,
cacheable: false,
cache_type: None,
cache_key: None,
category: MessageCategory::Current,
metadata: HashMap::new(),
},
timestamp: Utc::now(),
}
}
fn create_tool_result_message(tool_call_id: &str, content: &str, is_error: bool) -> UnifiedMessage {
UnifiedMessage {
role: MessageRole::Tool,
content: MessageContent::ToolResult {
tool_call_id: tool_call_id.to_string(),
content: content.to_string(),
is_error,
},
attributes: MessageAttributes {
priority: 0,
cacheable: false,
cache_type: None,
cache_key: None,
category: MessageCategory::Current,
metadata: HashMap::new(),
},
timestamp: Utc::now(),
}
}
#[test]
fn test_empty_messages() {
let config = create_test_config();
let messages: Vec<&UnifiedMessage> = vec![];
let (system, conversation) = transform_unified_messages(&messages, &config, true);
assert!(
system.is_empty(),
"Empty input should produce no system messages"
);
assert!(
conversation.is_empty(),
"Empty input should produce no conversation messages"
);
}
#[test]
fn test_system_messages_separated() {
let config = create_test_config();
let system1 = create_message(MessageRole::System, "You are helpful.", false);
let system2 = create_message(MessageRole::System, "Be concise.", false);
let user = create_message(MessageRole::User, "Hello", false);
let messages = vec![&system1, &system2, &user];
let (system, conversation) = transform_unified_messages(&messages, &config, false);
assert_eq!(system.len(), 2, "Should have 2 system messages");
assert_eq!(system[0].text, "You are helpful.");
assert_eq!(system[1].text, "Be concise.");
assert_eq!(conversation.len(), 1, "Should have 1 conversation message");
}
#[test]
fn test_only_system_messages() {
let config = create_test_config();
let system = create_message(MessageRole::System, "System prompt", false);
let messages = vec![&system];
let (sys_msgs, conv_msgs) = transform_unified_messages(&messages, &config, false);
assert_eq!(sys_msgs.len(), 1);
assert!(conv_msgs.is_empty(), "Should have no conversation messages");
}
#[test]
fn test_only_conversation_messages() {
let config = create_test_config();
let user = create_message(MessageRole::User, "Question", false);
let assistant = create_message(MessageRole::Assistant, "Answer", false);
let messages = vec![&user, &assistant];
let (sys_msgs, conv_msgs) = transform_unified_messages(&messages, &config, false);
assert!(sys_msgs.is_empty(), "Should have no system messages");
assert_eq!(conv_msgs.len(), 2);
}
#[test]
fn test_cache_strategy_single_message() {
let config = create_test_config();
let msg = create_message(MessageRole::User, "Hello", true);
let messages = vec![&msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
assert_eq!(conversation.len(), 1);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert!(
blocks[0].has_cache_control(),
"Single message should be cached"
);
}
_ => panic!("Expected Blocks content"),
}
}
#[test]
fn test_cache_strategy_two_messages() {
let config = create_test_config();
let msg1 = create_message(MessageRole::User, "First", true);
let msg2 = create_message(MessageRole::Assistant, "Second", true);
let messages = vec![&msg1, &msg2];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
assert_eq!(conversation.len(), 2);
if let AnthropicContent::Blocks(blocks) = &conversation[0].content {
assert!(
blocks[0].has_cache_control(),
"First message should be cached"
);
}
}
#[test]
fn test_cache_strategy_three_to_five_messages() {
let config = create_test_config();
let messages_data: Vec<UnifiedMessage> = vec![
create_message(MessageRole::User, "Message 0", true),
create_message(MessageRole::Assistant, "Message 1", true),
create_message(MessageRole::User, "Message 2", true),
create_message(MessageRole::Assistant, "Message 3", true),
];
let message_refs: Vec<&UnifiedMessage> = messages_data.iter().collect();
let (_, conversation) = transform_unified_messages(&message_refs, &config, true);
assert_eq!(
conversation.len(),
4,
"Should have 4 messages with alternating roles"
);
if let AnthropicContent::Blocks(blocks) = &conversation[0].content {
assert!(blocks[0].has_cache_control(), "Message 0 should be cached");
}
if let AnthropicContent::Blocks(blocks) = &conversation[2].content {
assert!(blocks[0].has_cache_control(), "Message 2 should be cached");
}
}
#[test]
fn test_cache_strategy_six_plus_messages() {
let config = create_test_config();
let messages_data: Vec<UnifiedMessage> = vec![
create_message(MessageRole::User, "Message 0", true),
create_message(MessageRole::Assistant, "Message 1", true),
create_message(MessageRole::User, "Message 2", true),
create_message(MessageRole::Assistant, "Message 3", true),
create_message(MessageRole::User, "Message 4", true),
create_message(MessageRole::Assistant, "Message 5", true),
create_message(MessageRole::User, "Message 6", true),
create_message(MessageRole::Assistant, "Message 7", true),
];
let message_refs: Vec<&UnifiedMessage> = messages_data.iter().collect();
let (_, conversation) = transform_unified_messages(&message_refs, &config, true);
assert_eq!(
conversation.len(),
8,
"Should have 8 messages with alternating roles"
);
if let AnthropicContent::Blocks(blocks) = &conversation[6].content {
assert!(
blocks[0].has_cache_control(),
"Second-to-last message should be cached"
);
}
if let AnthropicContent::Blocks(blocks) = &conversation[7].content {
assert!(
blocks[0].has_cache_control(),
"Last message should be cached"
);
}
}
#[test]
fn test_caching_disabled_no_cache_control() {
let config = create_test_config();
let msg = create_message(MessageRole::User, "Test", true);
let messages = vec![&msg];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
match &conversation[0].content {
AnthropicContent::Text(_) => {
}
AnthropicContent::Blocks(_) => {
panic!("Should not have blocks when caching disabled");
}
}
}
#[test]
fn test_non_cacheable_messages_not_cached() {
let config = create_test_config();
let msg = create_message(MessageRole::User, "Test", false);
let messages = vec![&msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
match &conversation[0].content {
AnthropicContent::Text(_) => {
}
AnthropicContent::Blocks(_) => {
panic!("Non-cacheable message should not have cache control");
}
}
}
#[test]
fn test_consecutive_same_role_messages_combined() {
let config = create_test_config();
let user1 = create_message(MessageRole::User, "First question", false);
let user2 = create_message(MessageRole::User, "Second question", false);
let messages = vec![&user1, &user2];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
assert_eq!(
conversation.len(),
1,
"Consecutive same-role messages should combine"
);
assert_eq!(conversation[0].role, "user");
match &conversation[0].content {
AnthropicContent::Text(text) => {
assert!(text.contains("First question"));
assert!(text.contains("Second question"));
}
_ => panic!("Expected Text content"),
}
}
#[test]
fn test_alternating_roles_not_combined() {
let config = create_test_config();
let user = create_message(MessageRole::User, "Question", false);
let assistant = create_message(MessageRole::Assistant, "Answer", false);
let messages = vec![&user, &assistant];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
assert_eq!(
conversation.len(),
2,
"Alternating roles should stay separate"
);
assert_eq!(conversation[0].role, "user");
assert_eq!(conversation[1].role, "assistant");
}
#[test]
fn test_empty_text_no_cache_control() {
let config = create_test_config();
let empty_msg = create_message(MessageRole::User, "", true);
let messages = vec![&empty_msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
match &conversation[0].content {
AnthropicContent::Text(text) => {
assert_eq!(text, "", "Empty text should remain empty");
}
AnthropicContent::Blocks(_) => {
panic!("Empty text should not create content blocks");
}
}
}
#[test]
fn test_tool_role_converted_to_user() {
let config = create_test_config();
let tool_result = create_tool_result_message("tool_123", "Result", false);
let messages = vec![&tool_result];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
assert_eq!(conversation.len(), 1);
assert_eq!(
conversation[0].role, "user",
"Tool role should convert to user"
);
}
#[test]
fn test_tool_call_conversion() {
let config = create_test_config();
let tool_call = create_tool_call_message("call_123", "search");
let messages = vec![&tool_call];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert_eq!(blocks.len(), 1);
match &blocks[0] {
AnthropicContentBlock::ToolUse { id, name, .. } => {
assert_eq!(id, "call_123");
assert_eq!(name, "search");
}
_ => panic!("Expected ToolUse block"),
}
}
_ => panic!("Expected Blocks content"),
}
}
#[test]
fn test_tool_result_conversion() {
let config = create_test_config();
let tool_result = create_tool_result_message("call_456", "Found 3 results", false);
let messages = vec![&tool_result];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
assert_eq!(conversation[0].role, "user");
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => match &blocks[0] {
AnthropicContentBlock::ToolResult {
tool_use_id,
content,
..
} => {
assert_eq!(tool_use_id, "call_456");
assert_eq!(content, "Found 3 results");
}
_ => panic!("Expected ToolResult block"),
},
_ => panic!("Expected Blocks content"),
}
}
#[test]
fn test_tool_result_with_error() {
let config = create_test_config();
let error_result = create_tool_result_message("call_789", "Connection failed", true);
let messages = vec![&error_result];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => match &blocks[0] {
AnthropicContentBlock::ToolResult { content, .. } => {
assert!(
content.starts_with("Error:"),
"Error results should be prefixed"
);
assert!(content.contains("Connection failed"));
}
_ => panic!("Expected ToolResult block"),
},
_ => panic!("Expected Blocks content"),
}
}
#[test]
fn test_system_message_cache_control() {
let config = create_test_config();
let sys1 = create_message(MessageRole::System, "First", true);
let sys2 = create_message(MessageRole::System, "Second", true);
let user = create_message(MessageRole::User, "Hello", false);
let messages = vec![&sys1, &sys2, &user];
let (system, _) = transform_unified_messages(&messages, &config, true);
assert_eq!(system.len(), 2);
assert!(
system[0].cache_control.is_none(),
"First system msg should not be cached"
);
assert!(
system[1].cache_control.is_some(),
"Last system msg should be cached"
);
assert_eq!(
system[1].cache_control.as_ref().unwrap().cache_type,
"ephemeral"
);
}
#[test]
fn test_non_cacheable_system_messages_not_cached() {
let config = create_test_config();
let sys = create_message(MessageRole::System, "System", false);
let messages = vec![&sys];
let (system, _) = transform_unified_messages(&messages, &config, true);
assert_eq!(system.len(), 1);
assert!(
system[0].cache_control.is_none(),
"Non-cacheable system msg should not be cached"
);
}
trait HasCacheControl {
fn has_cache_control(&self) -> bool;
fn get_cache_ttl(&self) -> Option<String>;
}
impl HasCacheControl for AnthropicContentBlock {
fn has_cache_control(&self) -> bool {
match self {
AnthropicContentBlock::Text { cache_control, .. } => cache_control.is_some(),
_ => false,
}
}
fn get_cache_ttl(&self) -> Option<String> {
match self {
AnthropicContentBlock::Text { cache_control, .. } => {
cache_control.as_ref().and_then(|cc| cc.ttl.clone())
}
_ => None,
}
}
}
#[test]
fn test_merge_content_blocks_text_plus_blocks() {
let config = create_test_config();
let msg1 = create_message(MessageRole::Assistant, "First text", false);
let msg2 = create_tool_call_with_role(MessageRole::Assistant);
let messages = vec![&msg1, &msg2];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
assert_eq!(conversation.len(), 1);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert_eq!(blocks.len(), 2, "Should have text block + tool use block");
assert!(matches!(&blocks[0], AnthropicContentBlock::Text { .. }));
assert!(matches!(&blocks[1], AnthropicContentBlock::ToolUse { .. }));
}
_ => panic!("Expected Blocks content"),
}
}
#[test]
fn test_merge_content_blocks_blocks_plus_text() {
let config = create_test_config();
let msg1 = create_tool_call_with_role(MessageRole::Assistant);
let msg2 = create_message(MessageRole::Assistant, "Following text", false);
let messages = vec![&msg1, &msg2];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
assert_eq!(conversation.len(), 1);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert_eq!(blocks.len(), 2, "Should have tool use block + text block");
assert!(matches!(&blocks[0], AnthropicContentBlock::ToolUse { .. }));
assert!(matches!(&blocks[1], AnthropicContentBlock::Text { .. }));
}
_ => panic!("Expected Blocks content"),
}
}
#[test]
fn test_merge_content_blocks_text_plus_text() {
let config = create_test_config();
let msg1 = create_message(MessageRole::User, "First", false);
let msg2 = create_message(MessageRole::User, "Second", false);
let messages = vec![&msg1, &msg2];
let (_, conversation) = transform_unified_messages(&messages, &config, false);
assert_eq!(conversation.len(), 1);
match &conversation[0].content {
AnthropicContent::Text(text) => {
assert!(text.contains("First"), "Should contain first text");
assert!(text.contains("Second"), "Should contain second text");
assert!(text.contains('\n'), "Should have newline separator");
}
_ => panic!("Expected Text content"),
}
}
#[test]
fn test_extract_text_content_from_tool_call() {
let config = create_test_config();
let msg = create_tool_call_with_role(MessageRole::System);
let messages = vec![&msg];
let (system, _) = transform_unified_messages(&messages, &config, false);
assert_eq!(system.len(), 1);
assert!(
system[0].text.contains("Tool call:"),
"Should format as 'Tool call:'"
);
assert!(
system[0].text.contains("test_function"),
"Should include function name"
);
}
#[test]
fn test_extract_text_content_from_tool_result_success() {
let config = create_test_config();
let msg = UnifiedMessage {
role: MessageRole::System,
content: MessageContent::ToolResult {
tool_call_id: "call_123".to_string(),
content: "Success result".to_string(),
is_error: false,
},
attributes: MessageAttributes {
priority: 0,
cacheable: false,
cache_type: None,
cache_key: None,
category: MessageCategory::Current,
metadata: HashMap::new(),
},
timestamp: Utc::now(),
};
let messages = vec![&msg];
let (system, _) = transform_unified_messages(&messages, &config, false);
assert_eq!(system.len(), 1);
assert_eq!(
system[0].text, "Success result",
"Should not prefix with 'Error:'"
);
}
#[test]
fn test_extract_text_content_from_tool_result_error() {
let config = create_test_config();
let msg = UnifiedMessage {
role: MessageRole::System,
content: MessageContent::ToolResult {
tool_call_id: "call_123".to_string(),
content: "Something failed".to_string(),
is_error: true,
},
attributes: MessageAttributes {
priority: 0,
cacheable: false,
cache_type: None,
cache_key: None,
category: MessageCategory::Current,
metadata: HashMap::new(),
},
timestamp: Utc::now(),
};
let messages = vec![&msg];
let (system, _) = transform_unified_messages(&messages, &config, false);
assert_eq!(system.len(), 1);
assert_eq!(
system[0].text, "Error: Something failed",
"Should prefix with 'Error:'"
);
}
#[test]
fn test_cache_decision_logging_non_cacheable() {
let config = create_test_config();
let msg = create_message(MessageRole::User, "Test", false);
let messages = vec![&msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
assert_eq!(conversation.len(), 1);
match &conversation[0].content {
AnthropicContent::Text(_) => {} AnthropicContent::Blocks(blocks) => {
for block in blocks {
assert!(
!block.has_cache_control(),
"Non-cacheable message should not be cached"
);
}
}
}
}
#[test]
fn test_json_content_with_caching() {
let config = create_test_config();
let json_msg = UnifiedMessage {
role: MessageRole::User,
content: MessageContent::Json(serde_json::json!({"key": "value"})),
attributes: MessageAttributes {
priority: 0,
cacheable: true,
cache_type: None,
cache_key: None,
category: MessageCategory::Current,
metadata: HashMap::new(),
},
timestamp: Utc::now(),
};
let messages = vec![&json_msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
assert_eq!(conversation.len(), 1);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert!(
blocks[0].has_cache_control(),
"JSON content should have cache control when cacheable"
);
}
_ => panic!("Expected Blocks with cache control for cached JSON"),
}
}
#[test]
fn test_extended_cache_type_conversation_message() {
let config = create_test_config();
let msg = create_message_with_cache_type(MessageRole::User, "Context", CacheType::Extended);
let messages = vec![&msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
assert_eq!(conversation.len(), 1);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert!(
blocks[0].has_cache_control(),
"Extended cache message should have cache control"
);
assert_eq!(
blocks[0].get_cache_ttl(),
Some("1h".to_string()),
"Extended cache should use 1h TTL"
);
}
_ => panic!("Expected Blocks content with cache control"),
}
}
#[test]
fn test_ephemeral_cache_type_conversation_message() {
let config = create_test_config();
let msg = create_message_with_cache_type(MessageRole::User, "Query", CacheType::Ephemeral);
let messages = vec![&msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
assert_eq!(conversation.len(), 1);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert!(
blocks[0].has_cache_control(),
"Ephemeral cache message should have cache control"
);
assert_eq!(
blocks[0].get_cache_ttl(),
Some("5m".to_string()),
"Ephemeral cache should use 5m TTL"
);
}
_ => panic!("Expected Blocks content with cache control"),
}
}
#[test]
fn test_extended_cache_type_system_message() {
let config = create_test_config();
let sys =
create_message_with_cache_type(MessageRole::System, "Long context", CacheType::Extended);
let messages = vec![&sys];
let (system, _) = transform_unified_messages(&messages, &config, true);
assert_eq!(system.len(), 1);
assert!(
system[0].cache_control.is_some(),
"Extended cache system message should have cache control"
);
let cache_control = system[0].cache_control.as_ref().unwrap();
assert_eq!(cache_control.cache_type, "ephemeral");
assert_eq!(
cache_control.ttl,
Some("1h".to_string()),
"Extended cache system message should use 1h TTL"
);
}
#[test]
fn test_ephemeral_cache_type_system_message() {
let config = create_test_config();
let sys =
create_message_with_cache_type(MessageRole::System, "Short context", CacheType::Ephemeral);
let messages = vec![&sys];
let (system, _) = transform_unified_messages(&messages, &config, true);
assert_eq!(system.len(), 1);
assert!(
system[0].cache_control.is_some(),
"Ephemeral cache system message should have cache control"
);
let cache_control = system[0].cache_control.as_ref().unwrap();
assert_eq!(cache_control.cache_type, "ephemeral");
assert_eq!(
cache_control.ttl,
Some("5m".to_string()),
"Ephemeral cache system message should use 5m TTL"
);
}
#[test]
fn test_mixed_cache_types_in_conversation() {
let config = create_test_config();
let msg1 = create_message_with_cache_type(MessageRole::User, "Extended", CacheType::Extended);
let msg2 =
create_message_with_cache_type(MessageRole::Assistant, "Middle", CacheType::Ephemeral);
let msg3 = create_message_with_cache_type(MessageRole::User, "Ephemeral", CacheType::Ephemeral);
let messages = vec![&msg1, &msg2, &msg3];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
assert_eq!(conversation.len(), 3);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert_eq!(
blocks[0].get_cache_ttl(),
Some("1h".to_string()),
"First message should use Extended cache"
);
}
_ => panic!("Expected Blocks content"),
}
match &conversation[1].content {
AnthropicContent::Text(_) => {
}
AnthropicContent::Blocks(blocks) => {
assert!(
!blocks[0].has_cache_control(),
"Middle message should not be cached (not a breakpoint)"
);
}
}
match &conversation[2].content {
AnthropicContent::Blocks(blocks) => {
assert_eq!(
blocks[0].get_cache_ttl(),
Some("5m".to_string()),
"Third message should use Ephemeral cache"
);
}
_ => panic!("Expected Blocks content"),
}
}
#[test]
fn test_cache_type_overrides_config_ttl() {
let mut config = create_test_config();
config.cache_ttl = "1h".to_string();
let msg = create_message_with_cache_type(MessageRole::User, "Query", CacheType::Ephemeral);
let messages = vec![&msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert_eq!(
blocks[0].get_cache_ttl(),
Some("5m".to_string()),
"Message cache_type should override config.cache_ttl"
);
}
_ => panic!("Expected Blocks content"),
}
}
#[test]
fn test_no_cache_type_uses_config_ttl() {
let mut config = create_test_config();
config.cache_ttl = "30m".to_string();
let msg = create_message(MessageRole::User, "Query", true);
let messages = vec![&msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert_eq!(
blocks[0].get_cache_ttl(),
Some("30m".to_string()),
"Should use config.cache_ttl when message has no cache_type"
);
}
_ => panic!("Expected Blocks content"),
}
}
#[test]
fn test_extended_cache_with_json_content() {
let config = create_test_config();
let json_msg = UnifiedMessage {
role: MessageRole::User,
content: MessageContent::Json(serde_json::json!({"data": "value"})),
attributes: MessageAttributes {
priority: 0,
cacheable: true,
cache_type: Some(CacheType::Extended),
cache_key: None,
category: MessageCategory::Current,
metadata: HashMap::new(),
},
timestamp: Utc::now(),
};
let messages = vec![&json_msg];
let (_, conversation) = transform_unified_messages(&messages, &config, true);
match &conversation[0].content {
AnthropicContent::Blocks(blocks) => {
assert_eq!(
blocks[0].get_cache_ttl(),
Some("1h".to_string()),
"JSON content should respect Extended cache type"
);
}
_ => panic!("Expected Blocks content"),
}
}
fn create_tool_call_with_role(role: MessageRole) -> UnifiedMessage {
UnifiedMessage {
role,
content: MessageContent::ToolCall {
id: "call_123".to_string(),
name: "test_function".to_string(),
arguments: serde_json::json!({"param": "value"}),
},
attributes: MessageAttributes {
priority: 0,
cacheable: false,
cache_type: None,
cache_key: None,
category: MessageCategory::Current,
metadata: HashMap::new(),
},
timestamp: Utc::now(),
}
}