use std::sync::Arc;
use foundation_db::traits::DocumentStore;
use foundation_nativeapis::shared::vfs::AsyncVfsFileSystem;
use crate::agentic::memory::MemoryHierarchy;
use crate::agentic::memory_store::MemoryStore;
use crate::agentic::tool_impl::{ToolCallManager, ToolImpl};
use crate::agentic::toolshed::{tool_fn, ToolConstructor, ToolShedError};
use crate::agentic::UserId;
use crate::types::routable_provider::ProviderRouter;
use crate::types::{ModelId, SessionId};
#[derive(Default)]
pub struct ToolPreset {
constructors: Vec<Box<dyn ToolConstructor>>,
}
impl ToolPreset {
#[must_use]
pub fn empty() -> Self {
Self::default()
}
#[must_use]
pub fn from_tools(tools: Vec<Arc<dyn ToolImpl>>) -> Self {
Self {
constructors: tools.into_iter().map(Into::into).collect(),
}
}
#[must_use]
pub fn from_constructors(constructors: Vec<Box<dyn ToolConstructor>>) -> Self {
Self { constructors }
}
#[must_use]
pub fn names(&self) -> Vec<&str> {
self.constructors.iter().map(|c| c.name()).collect()
}
fn prebuilt_tools(&self) -> Result<Vec<Arc<dyn ToolImpl>>, ToolShedError> {
self.constructors
.iter()
.map(|c| {
c.prebuilt()
.ok_or_else(|| ToolShedError::NeedsSession(c.name().to_string()))
})
.collect()
}
pub fn register_all(&self, manager: &ToolCallManager) -> Result<(), ToolShedError> {
for tool in self.prebuilt_tools()? {
manager.register(tool);
}
Ok(())
}
pub fn into_manager(self, session_id: SessionId) -> Result<ToolCallManager, ToolShedError> {
let mgr = ToolCallManager::new(session_id);
self.register_all(&mgr)?;
Ok(mgr)
}
pub fn as_child_tools(&self) -> Result<Vec<Arc<dyn ToolImpl>>, ToolShedError> {
self.prebuilt_tools()
}
#[must_use]
pub fn len(&self) -> usize {
self.constructors.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.constructors.is_empty()
}
#[must_use]
pub fn merge(mut self, other: Self) -> Self {
self.constructors.extend(other.constructors);
self
}
#[must_use]
pub fn files<F: AsyncVfsFileSystem + 'static>(fs: Arc<F>) -> Self {
use crate::agentic::tools::files::{EditTool, ReadTool, WriteTool};
Self::from_tools(vec![
Arc::new(ReadTool::new(Arc::clone(&fs) as Arc<_>)),
Arc::new(WriteTool::new(Arc::clone(&fs) as Arc<_>)),
Arc::new(EditTool::new(fs)),
])
}
#[must_use]
pub fn shell() -> Self {
use crate::agentic::tools::files::BashTool;
Self::from_tools(vec![Arc::new(BashTool::new())])
}
#[must_use]
pub fn memory<M, D>(hierarchy: Arc<MemoryHierarchy<M, D>>) -> Self
where
M: MemoryStore + 'static,
D: DocumentStore + 'static,
{
use crate::agentic::tools::memory::MemoryTool;
Self::from_tools(vec![Arc::new(MemoryTool::new(hierarchy))])
}
#[must_use]
pub fn agent<D, M>(
router: ProviderRouter,
depth: u32,
max_depth: u32,
default_model: ModelId,
output_base: &str,
user: UserId,
child_tools: Vec<Arc<dyn ToolImpl>>,
) -> Self
where
D: DocumentStore + Default + 'static,
M: MemoryStore + Default + 'static,
{
use crate::agentic::tools::agent::AgentTool;
Self::from_tools(vec![Arc::new(AgentTool::<D, M>::new(
router,
depth,
max_depth,
default_model,
output_base.to_string(),
user,
child_tools,
))])
}
#[must_use]
pub fn search_context() -> Self {
use crate::agentic::tools::search::SearchContextTool;
Self::from_constructors(vec![tool_fn("search_context", |s| {
Arc::new(SearchContextTool::new(Arc::clone(&s.context))) as Arc<dyn ToolImpl>
})])
}
#[must_use]
pub fn session_memory() -> Self {
use crate::agentic::tools::memory::MemoryTool;
Self::from_constructors(vec![tool_fn("memory", |s| {
Arc::new(MemoryTool::from_shared(Arc::clone(&s.memory))) as Arc<dyn ToolImpl>
})])
}
#[must_use]
pub fn minimal_sub_agent<F: AsyncVfsFileSystem + 'static>(fs: Arc<F>) -> Self {
Self::files(fs).merge(Self::shell())
}
#[must_use]
pub fn standard<F: AsyncVfsFileSystem + 'static>(fs: Arc<F>) -> Self {
Self::files(fs)
.merge(Self::shell())
.merge(Self::session_memory())
}
}
impl std::ops::Add for ToolPreset {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
self.merge(rhs)
}
}
impl IntoIterator for ToolPreset {
type Item = Box<dyn ToolConstructor>;
type IntoIter = std::vec::IntoIter<Box<dyn ToolConstructor>>;
fn into_iter(self) -> Self::IntoIter {
self.constructors.into_iter()
}
}