Skip to main content

tiny_loop/tool/executor/
sequential.rs

1use std::collections::HashMap;
2
3use crate::{
4    tool::{Tool, executor::ToolExecutor},
5    types::{Message, ToolCall},
6};
7use async_trait::async_trait;
8
9/// Executes tools sequentially one by one by using [`Tool::call`]
10pub struct SequentialExecutor {
11    tools: HashMap<String, Box<dyn Tool + Sync>>,
12}
13
14impl SequentialExecutor {
15    pub fn new() -> Self {
16        Self {
17            tools: HashMap::new(),
18        }
19    }
20}
21
22#[async_trait]
23impl ToolExecutor for SequentialExecutor {
24    fn add(&mut self, name: String, tool: Box<dyn Tool + Sync>) -> Option<Box<dyn Tool + Sync>> {
25        tracing::trace!("Registering tool: {}", name);
26        self.tools.insert(name, tool)
27    }
28
29    async fn execute(&self, calls: Vec<ToolCall>) -> Vec<Message> {
30        tracing::debug!("Executing {} tool calls sequentially", calls.len());
31        let mut results = Vec::new();
32        for call in calls {
33            tracing::debug!("Executing tool '{}'", call.function.name);
34            let message = if let Some(tool) = self.tools.get(&call.function.name) {
35                Message::Tool {
36                    tool_call_id: call.id.clone(),
37                    content: tool.call(call.function.arguments).await,
38                }
39            } else {
40                tracing::debug!("Tool '{}' not found", call.function.name);
41                Message::Tool {
42                    tool_call_id: call.id,
43                    content: format!("Tool '{}' not found", call.function.name),
44                }
45            };
46            results.push(message);
47        }
48        tracing::debug!("Sequential execution completed");
49        results
50    }
51}