use crate::messages::ToolDefinition;
use crate::tools::error::ToolError;
use crate::types::CorrelationId;
use acton_reactive::prelude::*;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::future::Future;
#[acton_message]
#[derive(Serialize, Deserialize)]
pub struct ExecuteToolDirect {
pub correlation_id: CorrelationId,
pub tool_call_id: String,
pub args: Value,
}
impl ExecuteToolDirect {
#[must_use]
pub fn new(
correlation_id: CorrelationId,
tool_call_id: impl Into<String>,
args: Value,
) -> Self {
Self {
correlation_id,
tool_call_id: tool_call_id.into(),
args,
}
}
}
#[acton_message]
#[derive(Serialize, Deserialize)]
pub struct ToolActorResponse {
pub correlation_id: CorrelationId,
pub tool_call_id: String,
pub result: Result<String, String>,
}
impl ToolActorResponse {
#[must_use]
pub fn success(
correlation_id: CorrelationId,
tool_call_id: impl Into<String>,
content: impl Into<String>,
) -> Self {
Self {
correlation_id,
tool_call_id: tool_call_id.into(),
result: Ok(content.into()),
}
}
#[must_use]
pub fn error(
correlation_id: CorrelationId,
tool_call_id: impl Into<String>,
error: impl Into<String>,
) -> Self {
Self {
correlation_id,
tool_call_id: tool_call_id.into(),
result: Err(error.into()),
}
}
}
pub trait ToolActor {
fn name() -> &'static str;
fn definition() -> ToolDefinition;
fn spawn(runtime: &mut ActorRuntime) -> impl Future<Output = ActorHandle> + Send;
}
pub trait ToolExecutor: Send + Sync {
fn execute(&self, args: Value) -> impl Future<Output = Result<Value, ToolError>> + Send;
fn validate_args(&self, args: &Value) -> Result<(), ToolError> {
let _ = args;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn execute_tool_direct_new() {
let corr_id = CorrelationId::new();
let msg = ExecuteToolDirect::new(corr_id.clone(), "tc_123", serde_json::json!({}));
assert_eq!(msg.correlation_id, corr_id);
assert_eq!(msg.tool_call_id, "tc_123");
}
#[test]
fn tool_actor_response_success() {
let corr_id = CorrelationId::new();
let resp = ToolActorResponse::success(corr_id.clone(), "tc_123", "result");
assert_eq!(resp.correlation_id, corr_id);
assert_eq!(resp.tool_call_id, "tc_123");
assert!(resp.result.is_ok());
assert_eq!(resp.result.unwrap(), "result");
}
#[test]
fn tool_actor_response_error() {
let corr_id = CorrelationId::new();
let resp = ToolActorResponse::error(corr_id.clone(), "tc_123", "failed");
assert_eq!(resp.correlation_id, corr_id);
assert_eq!(resp.tool_call_id, "tc_123");
assert!(resp.result.is_err());
assert_eq!(resp.result.unwrap_err(), "failed");
}
}