use std::collections::BTreeMap;
use std::sync::Arc;
use serde_json::Value;
use crate::runtime::sub_agent_sessions::{
_unregister_sub_agent_session, register_sub_agent_session, SubAgentSession,
};
use crate::runtime::sub_task_manager::{SubTaskLineage, SubTaskSessionAttachment};
use crate::types::{AgentTask, SubTaskOutcome, SubTaskRequest};
use super::super::session::RuntimeSubAgentSession;
use super::super::types::{
ResolvedSubAgentClient, RuntimeSubAgentSessionParts, SubRunLifecycle, SubTaskRunContext,
};
pub(super) fn run_attached_sub_agent_session(
context: &SubTaskRunContext,
request: &SubTaskRequest,
lifecycle: &SubRunLifecycle,
sub_task: AgentTask,
resolved_client: ResolvedSubAgentClient,
) -> Result<SubTaskOutcome, String> {
let initial_prompt = sub_task.user_prompt.clone();
let mut tool_policy = context.tool_policy.clone().unwrap_or_default();
for exclusion in &sub_task.exclude_tools {
if !tool_policy
.disallowed_tools
.iter()
.any(|tool| tool == exclusion)
{
tool_policy.disallowed_tools.push(exclusion.clone());
}
}
let resolved_payload = resolved_client.payload.clone();
let model_id = resolved_client.model_id.clone();
let session = Arc::new(RuntimeSubAgentSession::new(RuntimeSubAgentSessionParts {
llm_client: resolved_client.llm_client,
tool_registry: context.tool_registry.clone(),
workspace_path: context.workspace_path.clone(),
workspace_backend: context.workspace_backend.clone(),
task_template: sub_task,
agent_name: request.agent_name.clone(),
session_id: lifecycle.session_id.clone(),
resolved: resolved_client.payload,
settings_file: context.settings_file.clone(),
default_backend: context.default_backend.clone(),
parent_cancellation_token: context.parent_cancellation_token.clone(),
stream_callback: context.stream_callback.clone(),
parent_log_handler: context.parent_log_handler.clone(),
parent_event_handler: context.parent_event_handler.clone(),
parent_execution_context: context.parent_execution_context.clone(),
model_provider: context.model_provider.clone(),
run_model_ref: resolved_client.run_model_ref,
tool_policy,
budget_limits: context.budget_limits.clone(),
initial_lifecycle: lifecycle.clone(),
}));
let sub_agent_session: Arc<dyn SubAgentSession> = session.clone();
context
.sub_task_manager
.attach_running_session_with_resolved_and_lineage(
SubTaskSessionAttachment {
task_id: lifecycle.task_id.clone(),
session_id: lifecycle.session_id.clone(),
agent_name: request.agent_name.clone(),
task_title: request.task_description.clone(),
workspace_backend: context.workspace_backend.clone(),
session: sub_agent_session.clone(),
resolved: resolved_payload,
},
SubTaskLineage {
parent_run_id: (!lifecycle.parent_run_id.is_empty())
.then(|| lifecycle.parent_run_id.clone()),
parent_tool_call_id: (!lifecycle.parent_tool_call_id.is_empty())
.then(|| lifecycle.parent_tool_call_id.clone()),
},
);
session.emit(
"session_created",
BTreeMap::from([
(
"agent_name".to_string(),
Value::String(request.agent_name.clone()),
),
("model".to_string(), Value::String(model_id)),
(
"workspace".to_string(),
Value::String(context.workspace_path.display().to_string()),
),
(
"max_cycles".to_string(),
Value::from(session.task_template.max_cycles as u64),
),
]),
);
let mut registration = SessionRegistration {
session_id: lifecycle.session_id.clone(),
session: sub_agent_session.clone(),
registered: false,
};
register_sub_agent_session(lifecycle.session_id.clone(), sub_agent_session);
registration.registered = true;
session.continue_run(&initial_prompt)
}
struct SessionRegistration {
session_id: String,
session: Arc<dyn SubAgentSession>,
registered: bool,
}
impl Drop for SessionRegistration {
fn drop(&mut self) {
if self.registered {
_unregister_sub_agent_session(&self.session_id, Some(self.session.clone()));
}
}
}