use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::{broadcast, RwLock};
use bamboo_agent_core::storage::Storage;
use bamboo_agent_core::tools::ToolExecutor;
use bamboo_agent_core::Session;
use bamboo_engine::McpServerManager;
use bamboo_engine::SkillManager;
use bamboo_infrastructure::Config;
use bamboo_infrastructure::SessionStoreV2;
use super::init::PermissionChecker;
use super::{AgentRunner, ScheduleManager, ScheduleStore, SpawnScheduler};
pub(super) fn build_base_tools(
config: Arc<RwLock<Config>>,
permission_checker: Arc<PermissionChecker>,
mcp_manager: Arc<McpServerManager>,
skill_manager: Arc<SkillManager>,
storage: Arc<dyn Storage>,
sessions: Arc<RwLock<HashMap<String, Session>>>,
app_data_dir: PathBuf,
) -> Arc<dyn ToolExecutor> {
let builtin_executor = Arc::new(
bamboo_tools::BuiltinToolExecutor::new_with_config_and_permissions(
config.clone(),
permission_checker,
),
);
let builtin_tools: Arc<dyn ToolExecutor> = builtin_executor;
let mcp_tools = Arc::new(bamboo_engine::McpToolExecutor::new(
mcp_manager.clone(),
mcp_manager.tool_index(),
));
let base: Arc<dyn ToolExecutor> = Arc::new(bamboo_engine::CompositeToolExecutor::new(
builtin_tools,
mcp_tools,
));
let memory_tool = Arc::new(crate::tools::MemoryTool::new(
sessions.clone(),
storage.clone(),
app_data_dir.clone(),
));
let with_memory: Arc<dyn ToolExecutor> =
Arc::new(crate::tools::OverlayToolExecutor::new(base, memory_tool));
let load_skill_tool = Arc::new(crate::tools::LoadSkillTool::new(
skill_manager.clone(),
config.clone(),
sessions.clone(),
storage.clone(),
));
let with_load_skill: Arc<dyn ToolExecutor> = Arc::new(crate::tools::OverlayToolExecutor::new(
with_memory,
load_skill_tool,
));
let read_skill_resource_tool = Arc::new(crate::tools::ReadSkillResourceTool::new(
skill_manager,
config,
sessions,
storage,
));
let with_skills: Arc<dyn ToolExecutor> = Arc::new(crate::tools::OverlayToolExecutor::new(
with_load_skill,
read_skill_resource_tool,
));
let compact_tool = Arc::new(crate::tools::CompactContextTool);
Arc::new(crate::tools::OverlayToolExecutor::new(
with_skills,
compact_tool,
))
}
#[allow(clippy::too_many_arguments)]
pub(super) fn build_root_tools(
base_tools: Arc<dyn ToolExecutor>,
schedule_store: Arc<ScheduleStore>,
schedule_manager: Arc<ScheduleManager>,
session_store: Arc<SessionStoreV2>,
storage: Arc<dyn Storage>,
spawn_scheduler: Arc<SpawnScheduler>,
sessions: Arc<RwLock<HashMap<String, Session>>>,
agent_runners: Arc<RwLock<HashMap<String, AgentRunner>>>,
session_event_senders: Arc<
RwLock<HashMap<String, broadcast::Sender<bamboo_agent_core::AgentEvent>>>,
>,
subagent_model_resolver: crate::tools::OptionalSubagentModelResolver,
config: Arc<RwLock<Config>>,
subagent_profiles: Arc<bamboo_domain::subagent::SubagentProfileRegistry>,
) -> Arc<dyn ToolExecutor> {
let profiles_for_tool = subagent_profiles.clone();
let adapter = Arc::new(crate::tools::ChildSessionAdapter {
session_store: session_store.clone(),
storage: storage.clone(),
scheduler: spawn_scheduler,
sessions_cache: sessions,
agent_runners: agent_runners.clone(),
session_event_senders,
subagent_model_resolver,
config,
subagent_profiles,
});
let sub_session_tool = Arc::new(crate::tools::SubSessionTool::new(
adapter,
profiles_for_tool,
));
let tools_with_sub_session: Arc<dyn ToolExecutor> = Arc::new(
crate::tools::OverlayToolExecutor::new(base_tools, sub_session_tool),
);
let schedule_tasks_tool = Arc::new(crate::tools::ScheduleTasksTool::new(
schedule_store,
schedule_manager,
session_store.clone(),
storage.clone(),
));
let tools_with_schedule: Arc<dyn ToolExecutor> = Arc::new(
crate::tools::OverlayToolExecutor::new(tools_with_sub_session, schedule_tasks_tool),
);
let session_inspector_tool = Arc::new(crate::tools::SessionInspectorTool::new(
session_store,
storage,
));
Arc::new(crate::tools::OverlayToolExecutor::new(
tools_with_schedule,
session_inspector_tool,
))
}