use bamboo_agent_core::AgentEvent;
use bamboo_domain::subagent::{disabled_tools_for_profile, SubagentProfile};
use tokio::sync::broadcast;
use crate::runtime::execution::session_events::get_or_create_event_sender;
use crate::runtime::execution::spawn::{SpawnContext, SpawnJob};
#[derive(Debug, Clone)]
pub struct RunProfileInput {
pub child_session_id: String,
pub parent_session_id: String,
pub model: String,
}
pub struct ProfileRunner {
ctx: SpawnContext,
}
pub fn profile_runner(ctx: SpawnContext) -> ProfileRunner {
ProfileRunner::new(ctx)
}
impl ProfileRunner {
pub fn new(ctx: SpawnContext) -> Self {
Self { ctx }
}
fn tool_names(&self) -> Vec<String> {
self.ctx
.tools
.list_tools()
.into_iter()
.map(|schema| schema.function.name)
.collect()
}
pub(crate) fn build_job(&self, profile: &SubagentProfile, input: &RunProfileInput) -> SpawnJob {
let tool_names = self.tool_names();
let disabled = disabled_tools_for_profile(&profile.tools, &tool_names);
let disabled_tools = if disabled.is_empty() {
None
} else {
Some(disabled)
};
SpawnJob {
parent_session_id: input.parent_session_id.clone(),
child_session_id: input.child_session_id.clone(),
model: input.model.clone(),
disabled_tools,
}
}
pub async fn run_profile(
&self,
profile: &SubagentProfile,
input: RunProfileInput,
) -> Result<(), String> {
let job = self.build_job(profile, &input);
crate::sdk::spawn::run_child_spawn(self.ctx.clone(), job).await
}
pub async fn run_profile_stream(
&self,
profile: &SubagentProfile,
input: RunProfileInput,
) -> Result<broadcast::Receiver<AgentEvent>, String> {
let child_tx =
get_or_create_event_sender(&self.ctx.session_event_senders, &input.child_session_id)
.await;
let rx = child_tx.subscribe();
let job = self.build_job(profile, &input);
crate::sdk::spawn::run_child_spawn(self.ctx.clone(), job).await?;
Ok(rx)
}
}