use serde::{Deserialize, Serialize};
use std::fmt::Display;
pub mod internal;
pub mod manager;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolParameter {
pub name: String,
pub description: String,
pub required: bool,
pub default_value: Option<String>,
pub parameter_type: ParameterType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ParameterType {
String,
Number,
Boolean,
Array,
Object,
}
pub trait TaskType: Send + Sync + Display {
fn name(&self) -> &str;
fn description(&self) -> &str;
}
#[async_trait::async_trait]
pub trait Tool: Send + Sync {
async fn execute(
&mut self,
input: ToolInput,
) -> Result<ToolOutput, crate::error::KowalskiError>;
fn name(&self) -> &str;
fn description(&self) -> &str;
fn parameters(&self) -> Vec<ToolParameter>;
fn validate_input(&self, input: &ToolInput) -> Result<(), crate::error::KowalskiError> {
let required_params = self
.parameters()
.iter()
.filter(|p| p.required)
.map(|p| p.name.clone())
.collect::<Vec<_>>();
if let Some(params) = input.parameters.as_object() {
for param in required_params {
if !params.contains_key(¶m) {
return Err(crate::error::KowalskiError::ToolInvalidInput(format!(
"Missing required parameter: {}",
param
)));
}
}
}
Ok(())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolCall {
pub name: String,
pub parameters: serde_json::Value,
pub reasoning: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolInput {
pub task_type: String,
pub content: String,
pub parameters: serde_json::Value,
}
impl ToolInput {
pub fn new(task_type: String, content: String, parameters: serde_json::Value) -> Self {
Self {
task_type,
content,
parameters,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolOutput {
pub result: serde_json::Value,
pub metadata: Option<serde_json::Value>,
}
impl ToolOutput {
pub fn new(result: serde_json::Value, metadata: Option<serde_json::Value>) -> Self {
Self { result, metadata }
}
}
#[async_trait::async_trait]
impl<T: Tool + ?Sized> Tool for Box<T> {
async fn execute(
&mut self,
input: ToolInput,
) -> Result<ToolOutput, crate::error::KowalskiError> {
(**self).execute(input).await
}
fn name(&self) -> &str {
(**self).name()
}
fn description(&self) -> &str {
(**self).description()
}
fn parameters(&self) -> Vec<ToolParameter> {
(**self).parameters()
}
}