use std::collections::HashMap;
use laminate::provider::anthropic::parse_anthropic_response;
use laminate::provider::openai::parse_openai_response;
use laminate::{FlexValue, Laminate};
#[derive(Debug, Laminate)]
#[allow(dead_code)] struct WeatherArgs {
city: String,
#[laminate(coerce)]
days: u8, #[laminate(default)]
units: String, #[laminate(overflow)]
extra: HashMap<String, serde_json::Value>, }
fn main() -> Result<(), Box<dyn std::error::Error>> {
let openai_body = FlexValue::from_json(
r#"{
"id": "chatcmpl-x",
"model": "some-openai-compatible-model",
"x_provider_note": "openai-compatible gateway",
"choices": [{
"message": {
"tool_calls": [{
"id": "call_1", "type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"London\",\"days\":\"3\",\"region\":\"EU\"}"
}
}]
},
"finish_reason": "eos_token"
}]
}"#,
)?;
let anthropic_body = FlexValue::from_json(
r#"{
"id": "msg_1",
"model": "claude-sonnet-4-6",
"content": [{
"type": "tool_use",
"id": "tu_1",
"name": "get_weather",
"input": {"city": "London", "days": "3", "region": "EU"}
}],
"stop_reason": "tool_use"
}"#,
)?;
let responses = [
("openai", parse_openai_response(&openai_body)?),
("anthropic", parse_anthropic_response(&anthropic_body)?),
];
for (label, resp) in &responses {
println!("== {label} (stop_reason = {}) ==", resp.stop_reason);
for block in &resp.content {
if let Some((_id, name, input)) = block.as_tool_use() {
let (args, diags) = WeatherArgs::from_flex_value(input.raw())?;
println!(" tool: {name}");
println!(" args: {args:?}");
for d in &diags {
println!(" {d}");
}
}
}
println!();
}
Ok(())
}