use oxi_ai::{ContentBlock, TextContent, ToolCall, ToolResultMessage};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
pub fn extract_tool_calls(message: &oxi_ai::AssistantMessage) -> Vec<ToolCall> {
let mut tool_calls = Vec::new();
for block in &message.content {
if let ContentBlock::ToolCall(tc) = block {
tool_calls.push(tc.clone());
}
}
tool_calls
}
pub fn create_tool_result_message(finalized: &FinalizedToolCall) -> ToolResultMessage {
let content_blocks = if let Some(ref blocks) = finalized.result.content_blocks {
blocks.clone()
} else {
vec![ContentBlock::Text(TextContent::new(
finalized.result.output.clone(),
))]
};
ToolResultMessage::new(
finalized.tool_call.id.clone(),
&finalized.tool_call.name,
content_blocks,
)
}
pub fn should_terminate_batch(finalized_calls: &[FinalizedToolCall]) -> bool {
if finalized_calls.is_empty() {
return false;
}
finalized_calls.iter().all(|f| f.result.terminate)
}
pub fn should_stop_after_turn(external_stop: &Arc<AtomicBool>) -> bool {
external_stop.load(Ordering::SeqCst)
}
use crate::AgentToolResult;
pub struct FinalizedToolCall {
pub tool_call: oxi_ai::ToolCall,
pub result: AgentToolResult,
pub is_error: bool,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_should_stop_returns_false_when_no_external_stop() {
let external_stop = Arc::new(AtomicBool::new(false));
assert!(!should_stop_after_turn(&external_stop));
}
#[test]
fn test_should_stop_returns_true_on_external_stop() {
let external_stop = Arc::new(AtomicBool::new(true));
assert!(should_stop_after_turn(&external_stop));
}
}