use crate::core::platform::container::arsenal::{
Armament, ArmamentCall, ArmamentResult, ArsenalError,
};
use async_trait::async_trait;
use paladin_ports::output::arsenal_port::{ArsenalPort, ArsenalRegistry};
use serde_json::Value;
use std::sync::Arc;
pub struct ArsenalExecutionService {
registry: Arc<dyn ArsenalRegistry>,
}
impl ArsenalExecutionService {
pub fn new(registry: Arc<dyn ArsenalRegistry>) -> Self {
Self { registry }
}
fn validate_parameters(
&self,
armament: &Armament,
call: &ArmamentCall,
) -> Result<(), ArsenalError> {
for required_param in &armament.required_params {
if !call.arguments.contains_key(required_param) {
return Err(ArsenalError::InvalidArguments(format!(
"Missing required parameter: {}",
required_param
)));
}
}
Ok(())
}
}
#[async_trait]
impl ArsenalPort for ArsenalExecutionService {
async fn list_armaments(&self) -> Vec<Armament> {
Vec::new()
}
async fn invoke(&self, call: ArmamentCall) -> Result<ArmamentResult, ArsenalError> {
self.validate_call(&call)?;
let armament = self
.registry
.get(&call.tool_name)
.await
.ok_or_else(|| ArsenalError::ToolNotFound(call.tool_name.clone()))?;
self.validate_parameters(&armament, &call)?;
let start = tokio::time::Instant::now();
let output = Value::String(format!("Tool {} executed successfully", call.tool_name));
let execution_time = start.elapsed().as_millis() as u64;
Ok(ArmamentResult::success(
call.call_id,
output,
execution_time,
))
}
fn validate_call(&self, call: &ArmamentCall) -> Result<(), ArsenalError> {
if call.tool_name.is_empty() {
return Err(ArsenalError::InvalidArguments(
"Tool name cannot be empty".to_string(),
));
}
Ok(())
}
}