#[ allow( unused_imports ) ]
use super::*;
#[ test ]
fn test_tool_choice_auto()
{
let choice = the_module::ToolChoice::Auto;
assert!( choice.is_auto() );
assert!( !choice.is_none() );
assert!( !choice.is_specific() );
}
#[ test ]
fn test_tool_choice_none()
{
let choice = the_module::ToolChoice::None;
assert!( choice.is_none() );
assert!( !choice.is_auto() );
assert!( !choice.is_specific() );
}
#[ test ]
fn test_tool_choice_any()
{
let choice = the_module::ToolChoice::Any;
assert!( choice.is_any() );
assert!( !choice.is_auto() );
assert!( !choice.is_none() );
assert!( !choice.is_specific() );
}
#[ test ]
fn test_tool_choice_specific()
{
let choice = the_module::ToolChoice::specific( "calculator" );
assert!( choice.is_specific() );
assert!( !choice.is_auto() );
assert!( !choice.is_none() );
assert!( !choice.is_any() );
assert_eq!( choice.tool_name(), Some( "calculator" ) );
}
#[ test ]
fn test_tool_choice_serialization()
{
let auto = the_module::ToolChoice::Auto;
let none = the_module::ToolChoice::None;
let any = the_module::ToolChoice::Any;
let specific = the_module::ToolChoice::specific( "get_weather" );
let auto_json = serde_json::to_value( &auto ).unwrap();
let none_json = serde_json::to_value( &none ).unwrap();
let any_json = serde_json::to_value( &any ).unwrap();
let specific_json = serde_json::to_value( &specific ).unwrap();
assert_eq!( auto_json[ "type" ], "auto" );
assert_eq!( none_json[ "type" ], "none" );
assert_eq!( any_json[ "type" ], "any" );
assert_eq!( specific_json[ "type" ], "tool" );
assert_eq!( specific_json[ "name" ], "get_weather" );
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
#[ ignore = "Requires workspace secrets file" ]
async fn integration_tool_choice_auto_mode()
{
let client = the_module::Client::from_workspace()
.expect( "INTEGRATION: Must have valid API key" );
let tool = the_module::ToolDefinition
{
name : "calculator".to_string(),
description : "Perform basic arithmetic operations".to_string(),
input_schema : serde_json::json!({
"type": "object",
"properties": {
"operation": { "type": "string", "enum": ["add", "subtract", "multiply", "divide"] },
"a": { "type": "number" },
"b": { "type": "number" }
},
"required": ["operation", "a", "b"]
}),
};
let request = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 100,
messages : vec![ the_module::Message::user( "What is 25 + 17?".to_string() ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
tools : Some( vec![ tool ] ),
tool_choice : Some( the_module::ToolChoice::Auto ),
};
let response = match client.create_message( request ).await
{
Ok( response ) => response,
Err( the_module::AnthropicError::Api( ref api_err ) ) if api_err.message.contains( "credit balance is too low" ) =>
{
println!( "INTEGRATION TEST SKIPPED: Credit balance exhausted" );
return;
},
Err( err ) => panic!( "INTEGRATION: AUTO mode must work : {err}" ),
};
assert!( !response.id.is_empty() );
println!( "✅ Tool choice AUTO mode test passed!" );
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
#[ ignore = "Requires workspace secrets file" ]
async fn integration_tool_choice_any_mode()
{
let client = the_module::Client::from_workspace()
.expect( "INTEGRATION: Must have valid API key" );
let tool = the_module::ToolDefinition
{
name : "get_info".to_string(),
description : "Get information about a topic".to_string(),
input_schema : serde_json::json!({
"type": "object",
"properties": {
"topic": { "type": "string" }
},
"required": ["topic"]
}),
};
let request = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 100,
messages : vec![ the_module::Message::user( "Tell me about Rust".to_string() ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
tools : Some( vec![ tool ] ),
tool_choice : Some( the_module::ToolChoice::Any ),
};
let response = match client.create_message( request ).await
{
Ok( response ) => response,
Err( the_module::AnthropicError::Api( ref api_err ) ) if api_err.message.contains( "credit balance is too low" ) =>
{
println!( "INTEGRATION TEST SKIPPED: Credit balance exhausted" );
return;
},
Err( err ) => panic!( "INTEGRATION: ANY mode must work : {err}" ),
};
assert!( !response.id.is_empty() );
let has_tool_use = response.content.iter().any( |c| c.r#type == "tool_use" );
assert!( has_tool_use, "INTEGRATION: ANY mode must force tool use" );
println!( "✅ Tool choice ANY mode test passed!" );
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
#[ ignore = "Requires workspace secrets file" ]
async fn integration_tool_choice_none_mode()
{
let client = the_module::Client::from_workspace()
.expect( "INTEGRATION: Must have valid API key" );
let tool = the_module::ToolDefinition
{
name : "calculator".to_string(),
description : "Perform calculations".to_string(),
input_schema : serde_json::json!({
"type": "object",
"properties": {
"expression": { "type": "string" }
},
"required": ["expression"]
}),
};
let request = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 100,
messages : vec![ the_module::Message::user( "Calculate 10 + 5".to_string() ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
tools : Some( vec![ tool ] ),
tool_choice : Some( the_module::ToolChoice::None ),
};
let response = match client.create_message( request ).await
{
Ok( response ) => response,
Err( the_module::AnthropicError::Api( ref api_err ) ) if api_err.message.contains( "credit balance is too low" ) =>
{
println!( "INTEGRATION TEST SKIPPED: Credit balance exhausted" );
return;
},
Err( err ) => panic!( "INTEGRATION: NONE mode must work : {err}" ),
};
assert!( !response.id.is_empty() );
let has_tool_use = response.content.iter().any( |c| c.r#type == "tool_use" );
assert!( !has_tool_use, "INTEGRATION: NONE mode must prevent tool use" );
println!( "✅ Tool choice NONE mode test passed!" );
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
#[ ignore = "Requires workspace secrets file" ]
async fn integration_tool_choice_mode_transitions()
{
let client = the_module::Client::from_workspace()
.expect( "INTEGRATION: Must have valid API key" );
let tool = the_module::ToolDefinition::simple( "test_tool", "A test tool" );
let request1 = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 50,
messages : vec![ the_module::Message::user( "Hello".to_string() ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
tools : Some( vec![ tool.clone() ] ),
tool_choice : Some( the_module::ToolChoice::Auto ),
};
let response1 = match client.create_message( request1 ).await
{
Ok( r ) => r,
Err( the_module::AnthropicError::Api( ref api_err ) ) if api_err.message.contains( "credit balance is too low" ) =>
{
println!( "INTEGRATION TEST SKIPPED: Credit balance exhausted" );
return;
},
Err( err ) => panic!( "INTEGRATION: First request must work : {err}" ),
};
assert!( !response1.id.is_empty() );
let request2 = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 50,
messages : vec![ the_module::Message::user( "Hi again".to_string() ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
tools : Some( vec![ tool ] ),
tool_choice : Some( the_module::ToolChoice::None ),
};
let response2 = match client.create_message( request2 ).await
{
Ok( r ) => r,
Err( the_module::AnthropicError::Api( ref api_err ) ) if api_err.message.contains( "credit balance is too low" ) =>
{
println!( "INTEGRATION TEST SKIPPED: Credit balance exhausted on second request" );
return;
},
Err( err ) => panic!( "INTEGRATION: Second request must work : {err}" ),
};
assert!( !response2.id.is_empty() );
assert_ne!( response1.id, response2.id, "Responses should have different IDs" );
println!( "✅ Tool choice mode transitions test passed!" );
}