use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_with::skip_serializing_none;
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Tool {
pub name: String,
pub description: Option<String>,
pub input_schema: ToolInputSchema,
pub annotations: Option<ToolAnnotations>,
}
impl Tool {
pub fn new(name: impl Into<String>, input_schema: ToolInputSchema) -> Self {
Self {
name: name.into(),
description: None,
input_schema,
annotations: None,
}
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self
}
pub fn with_annotations(mut self, annotations: ToolAnnotations) -> Self {
self.annotations = Some(annotations);
self
}
}
#[skip_serializing_none]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ToolInputSchema {
#[serde(rename = "type")]
pub schema_type: String,
pub properties: Option<Value>,
pub required: Option<Vec<String>>,
}
impl ToolInputSchema {
pub fn new() -> Self {
Self::default()
}
pub fn with_properties(mut self, properties: Value) -> Self {
self.properties = Some(properties);
self
}
pub fn append_required(mut self, required_prop: impl Into<String>) -> Self {
self.required.get_or_insert_with(Vec::new).push(required_prop.into());
self
}
}
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct ToolAnnotations {
pub title: Option<String>,
pub read_only_hint: Option<bool>,
pub destructive_hint: Option<bool>,
pub idempotent_hint: Option<bool>,
pub open_world_hint: Option<bool>,
}
impl ToolAnnotations {
pub fn new() -> Self {
Self::default()
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn with_read_only_hint(mut self, read_only: bool) -> Self {
self.read_only_hint = Some(read_only);
self
}
pub fn with_destructive_hint(mut self, destructive: bool) -> Self {
self.destructive_hint = Some(destructive);
self
}
pub fn with_idempotent_hint(mut self, idempotent: bool) -> Self {
self.idempotent_hint = Some(idempotent);
self
}
pub fn with_open_world_hint(mut self, open_world: bool) -> Self {
self.open_world_hint = Some(open_world);
self
}
}