use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use crate::agent::{AgentCheckpointer, InterruptConfig, Middleware, UnifiedAgent};
use crate::schemas::StructuredOutputStrategy;
use crate::tools::{FileBackend, ToolContext, ToolStore};
pub struct DeepAgentConfig {
pub enable_planning: bool,
pub enable_filesystem: bool,
pub enable_task_tool: bool,
pub workspace_root: Option<PathBuf>,
#[allow(clippy::type_complexity)]
pub subagents: Vec<SubagentSpec>,
pub store: Option<Arc<dyn ToolStore>>,
pub context: Option<Arc<dyn ToolContext>>,
pub middleware: Option<Vec<Arc<dyn Middleware>>>,
pub response_format: Option<Box<dyn StructuredOutputStrategy>>,
pub skill_paths: Vec<PathBuf>,
pub skill_contents: Vec<(String, String)>,
pub skill_dirs: Vec<PathBuf>,
pub memory_paths: Vec<PathBuf>,
pub memory_contents: Vec<(String, String)>,
pub interrupt_before_tools: Vec<String>,
pub interrupt_on: HashMap<String, InterruptConfig>,
pub evict_tool_result_over_tokens: Option<usize>,
pub default_subagent_model: Option<String>,
pub file_backend: Option<Arc<dyn FileBackend>>,
pub checkpointer: Option<Arc<dyn AgentCheckpointer>>,
pub planning_system_prompt: Option<String>,
pub filesystem_system_prompt: Option<String>,
pub custom_tool_descriptions: HashMap<String, String>,
pub long_term_memory_prefix: Option<String>,
}
impl std::fmt::Debug for DeepAgentConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DeepAgentConfig")
.field("enable_planning", &self.enable_planning)
.field("enable_filesystem", &self.enable_filesystem)
.field("enable_task_tool", &self.enable_task_tool)
.field("workspace_root", &self.workspace_root)
.field("subagents", &self.subagents.len())
.field("store", &self.store.as_ref().map(|_| "..."))
.field("context", &self.context.as_ref().map(|_| "..."))
.field("middleware", &self.middleware.as_ref().map(|m| m.len()))
.field(
"response_format",
&self.response_format.as_ref().map(|_| "..."),
)
.field("skill_paths", &self.skill_paths)
.field("skill_contents", &self.skill_contents.len())
.field("skill_dirs", &self.skill_dirs)
.field("memory_paths", &self.memory_paths)
.field("memory_contents", &self.memory_contents.len())
.field("interrupt_before_tools", &self.interrupt_before_tools)
.field("interrupt_on", &self.interrupt_on.len())
.field(
"evict_tool_result_over_tokens",
&self.evict_tool_result_over_tokens,
)
.field("default_subagent_model", &self.default_subagent_model)
.field("file_backend", &self.file_backend.as_ref().map(|_| "..."))
.field("checkpointer", &self.checkpointer.as_ref().map(|_| "..."))
.field(
"planning_system_prompt",
&self.planning_system_prompt.as_ref().map(|_| "..."),
)
.field(
"filesystem_system_prompt",
&self.filesystem_system_prompt.as_ref().map(|_| "..."),
)
.field(
"custom_tool_descriptions",
&self.custom_tool_descriptions.len(),
)
.field("long_term_memory_prefix", &self.long_term_memory_prefix)
.finish()
}
}
#[derive(Clone)]
pub struct SubagentSpec {
pub agent: Arc<UnifiedAgent>,
pub name: String,
pub description: String,
pub interrupt_on: Option<HashMap<String, InterruptConfig>>,
}
impl std::fmt::Debug for SubagentSpec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SubagentSpec")
.field("name", &self.name)
.field("description", &self.description)
.finish()
}
}
impl Default for DeepAgentConfig {
fn default() -> Self {
Self {
enable_planning: true,
enable_filesystem: true,
enable_task_tool: false,
workspace_root: None,
subagents: Vec::new(),
store: None,
context: None,
middleware: None,
response_format: None,
skill_paths: Vec::new(),
skill_contents: Vec::new(),
skill_dirs: Vec::new(),
memory_paths: Vec::new(),
memory_contents: Vec::new(),
interrupt_before_tools: Vec::new(),
interrupt_on: HashMap::new(),
evict_tool_result_over_tokens: None,
default_subagent_model: None,
file_backend: None,
checkpointer: None,
planning_system_prompt: None,
filesystem_system_prompt: None,
custom_tool_descriptions: HashMap::new(),
long_term_memory_prefix: None,
}
}
}
impl DeepAgentConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_planning(mut self, enable: bool) -> Self {
self.enable_planning = enable;
self
}
pub fn with_filesystem(mut self, enable: bool) -> Self {
self.enable_filesystem = enable;
self
}
pub fn with_task_tool(mut self, enable: bool) -> Self {
self.enable_task_tool = enable;
self
}
pub fn with_workspace_root(mut self, root: PathBuf) -> Self {
self.workspace_root = Some(root);
self
}
pub fn with_workspace_root_opt(mut self, root: Option<PathBuf>) -> Self {
self.workspace_root = root;
self
}
pub fn with_subagent(
mut self,
agent: Arc<UnifiedAgent>,
name: impl Into<String>,
description: impl Into<String>,
) -> Self {
self.subagents.push(SubagentSpec {
agent,
name: name.into(),
description: description.into(),
interrupt_on: None,
});
self.enable_task_tool = true;
self
}
pub fn with_subagent_and_interrupt_on(
mut self,
agent: Arc<UnifiedAgent>,
name: impl Into<String>,
description: impl Into<String>,
interrupt_on: Option<HashMap<String, InterruptConfig>>,
) -> Self {
self.subagents.push(SubagentSpec {
agent,
name: name.into(),
description: description.into(),
interrupt_on,
});
self.enable_task_tool = true;
self
}
pub fn with_store(mut self, store: Arc<dyn ToolStore>) -> Self {
self.store = Some(store);
self
}
pub fn with_context(mut self, context: Arc<dyn ToolContext>) -> Self {
self.context = Some(context);
self
}
pub fn with_middleware(mut self, middleware: Vec<Arc<dyn Middleware>>) -> Self {
self.middleware = Some(middleware);
self
}
pub fn with_response_format(
mut self,
response_format: Box<dyn StructuredOutputStrategy>,
) -> Self {
self.response_format = Some(response_format);
self
}
pub fn with_skill_path(mut self, path: PathBuf) -> Self {
self.skill_paths.push(path);
self
}
pub fn with_skill_paths(mut self, paths: Vec<PathBuf>) -> Self {
self.skill_paths.extend(paths);
self
}
pub fn with_skill_content(
mut self,
name: impl Into<String>,
content: impl Into<String>,
) -> Self {
self.skill_contents.push((name.into(), content.into()));
self
}
pub fn with_skill_dir(mut self, dir: PathBuf) -> Self {
self.skill_dirs.push(dir);
self
}
pub fn with_skill_dirs(mut self, dirs: Vec<PathBuf>) -> Self {
self.skill_dirs.extend(dirs);
self
}
pub fn with_memory_path(mut self, path: PathBuf) -> Self {
self.memory_paths.push(path);
self
}
pub fn with_memory_paths(mut self, paths: Vec<PathBuf>) -> Self {
self.memory_paths.extend(paths);
self
}
pub fn with_memory_content(
mut self,
name: impl Into<String>,
content: impl Into<String>,
) -> Self {
self.memory_contents.push((name.into(), content.into()));
self
}
pub fn with_interrupt_before_tools(mut self, tool_names: Vec<String>) -> Self {
self.interrupt_before_tools = tool_names;
self
}
pub fn with_interrupt_on(mut self, interrupt_on: HashMap<String, InterruptConfig>) -> Self {
self.interrupt_on = interrupt_on;
self
}
pub fn with_interrupt_on_tool(
mut self,
tool_name: impl Into<String>,
config: InterruptConfig,
) -> Self {
self.interrupt_on.insert(tool_name.into(), config);
self
}
pub fn with_evict_tool_result_over_tokens(mut self, limit: Option<usize>) -> Self {
self.evict_tool_result_over_tokens = limit;
self
}
pub fn with_default_subagent_model(mut self, model: Option<String>) -> Self {
self.default_subagent_model = model;
self
}
pub fn with_file_backend(mut self, backend: Option<Arc<dyn FileBackend>>) -> Self {
self.file_backend = backend;
self
}
pub fn with_checkpointer(mut self, checkpointer: Option<Arc<dyn AgentCheckpointer>>) -> Self {
self.checkpointer = checkpointer;
self
}
pub fn with_planning_system_prompt(mut self, prompt: Option<String>) -> Self {
self.planning_system_prompt = prompt;
self
}
pub fn with_filesystem_system_prompt(mut self, prompt: Option<String>) -> Self {
self.filesystem_system_prompt = prompt;
self
}
pub fn with_custom_tool_description(
mut self,
tool_name: impl Into<String>,
description: impl Into<String>,
) -> Self {
self.custom_tool_descriptions
.insert(tool_name.into(), description.into());
self
}
pub fn with_custom_tool_descriptions(mut self, descriptions: HashMap<String, String>) -> Self {
self.custom_tool_descriptions = descriptions;
self
}
pub fn with_long_term_memory(mut self, prefix: impl Into<String>) -> Self {
self.long_term_memory_prefix = Some(prefix.into());
self
}
}