use crate::runtime::activity::ActivityManager;
use crate::runtime::behavior::AgentBehavior;
use crate::runtime::inference::ContextMessage;
use crate::runtime::run::RunIdentity;
use crate::runtime::tool_call::lifecycle::SuspendedCall;
use crate::runtime::tool_call::{CallerContext, Tool, ToolDescriptor, ToolResult};
use crate::thread::{Message, ToolCall};
use crate::RunPolicy;
use async_trait::async_trait;
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;
use thiserror::Error;
use tirea_state::TrackedPatch;
use tokio_util::sync::CancellationToken;
#[derive(Debug, Clone)]
pub struct ToolExecution {
pub call: ToolCall,
pub result: ToolResult,
pub patch: Option<TrackedPatch>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ToolCallOutcome {
Suspended,
Succeeded,
Failed,
}
impl ToolCallOutcome {
pub fn from_tool_result(result: &ToolResult) -> Self {
match result.status {
crate::runtime::tool_call::ToolStatus::Pending => Self::Suspended,
crate::runtime::tool_call::ToolStatus::Error => Self::Failed,
crate::runtime::tool_call::ToolStatus::Success
| crate::runtime::tool_call::ToolStatus::Warning => Self::Succeeded,
}
}
}
pub struct ToolExecutionRequest<'a> {
pub tools: &'a HashMap<String, Arc<dyn Tool>>,
pub calls: &'a [ToolCall],
pub state: &'a Value,
pub tool_descriptors: &'a [ToolDescriptor],
pub agent_behavior: Option<&'a dyn AgentBehavior>,
pub activity_manager: Arc<dyn ActivityManager>,
pub run_policy: &'a RunPolicy,
pub run_identity: RunIdentity,
pub caller_context: CallerContext,
pub thread_id: &'a str,
pub thread_messages: &'a [Arc<Message>],
pub state_version: u64,
pub cancellation_token: Option<&'a CancellationToken>,
}
#[derive(Debug, Clone)]
pub struct ToolExecutionResult {
pub execution: ToolExecution,
pub outcome: ToolCallOutcome,
pub suspended_call: Option<SuspendedCall>,
pub messages: Vec<ContextMessage>,
pub pending_patches: Vec<TrackedPatch>,
pub serialized_state_actions: Vec<crate::runtime::state::SerializedStateAction>,
}
#[derive(Debug, Clone, Error)]
pub enum ToolExecutorError {
#[error("tool execution cancelled")]
Cancelled { thread_id: String },
#[error("tool execution failed: {message}")]
Failed { message: String },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DecisionReplayPolicy {
Immediate,
BatchAllSuspended,
}
#[async_trait]
pub trait ToolExecutor: Send + Sync {
async fn execute(
&self,
request: ToolExecutionRequest<'_>,
) -> Result<Vec<ToolExecutionResult>, ToolExecutorError>;
fn name(&self) -> &'static str;
fn requires_parallel_patch_conflict_check(&self) -> bool {
false
}
fn decision_replay_policy(&self) -> DecisionReplayPolicy {
DecisionReplayPolicy::Immediate
}
}