use std::{any::Any, marker::PhantomData};
use schemars::JsonSchema;
use serde::{Serialize, de::DeserializeOwned};
use crate::traits::Elicitation;
pub trait AnyToolSlot: Any + Send + Sync + 'static {
fn prefix(&self) -> &str;
fn type_name(&self) -> &'static str;
fn schema(&self) -> schemars::Schema;
fn slot_type_id(&self) -> std::any::TypeId;
fn as_any(&self) -> &dyn Any;
}
pub struct TypedSlot<T>
where
T: Serialize + DeserializeOwned + JsonSchema + Elicitation + Send + Sync + 'static,
{
prefix: String,
_phantom: PhantomData<fn() -> T>,
}
impl<T> TypedSlot<T>
where
T: Serialize + DeserializeOwned + JsonSchema + Elicitation + Send + Sync + 'static,
{
pub fn new(prefix: impl Into<String>) -> Self {
Self {
prefix: prefix.into(),
_phantom: PhantomData,
}
}
pub fn downcast_ref(slot: &dyn AnyToolSlot) -> Option<&TypedSlot<T>> {
slot.as_any().downcast_ref::<TypedSlot<T>>()
}
}
impl<T> AnyToolSlot for TypedSlot<T>
where
T: Serialize + DeserializeOwned + JsonSchema + Elicitation + Send + Sync + 'static,
{
fn prefix(&self) -> &str {
&self.prefix
}
fn type_name(&self) -> &'static str {
std::any::type_name::<T>()
}
fn schema(&self) -> schemars::Schema {
schemars::schema_for!(T)
}
fn slot_type_id(&self) -> std::any::TypeId {
std::any::TypeId::of::<T>()
}
fn as_any(&self) -> &dyn Any {
self
}
}