use async_trait::async_trait; use std::sync::Arc; use crate::command::Command; use crate::command::context::CommandContext; use crate::command::handler::{CommandHandler, CommandMetadata}; use crate::command::response::{CommandError, CommandResponse, MessageKind}; use crate::gateway::cancel_manager::CancelManager; use crate::gateway::session::SessionManager; use crate::tools::SubAgentRuntime; /// 处理 StopExecution 命令:按话题取消当前正在执行的 Agent。 /// /// 取消传播:同时取消该 topic 下所有正在运行的异步子代理(通过 CancellationToken)。 pub struct StopExecutionCommandHandler { cancel_manager: CancelManager, session_manager: SessionManager, subagent_executor: Option>, } impl StopExecutionCommandHandler { pub fn new( cancel_manager: CancelManager, session_manager: SessionManager, subagent_executor: Option>, ) -> Self { Self { cancel_manager, session_manager, subagent_executor, } } } #[async_trait] impl CommandHandler for StopExecutionCommandHandler { fn can_handle(&self, cmd: &Command) -> bool { matches!(cmd, Command::StopExecution) } fn metadata(&self) -> Option { Some(CommandMetadata { name: "stop", description: "停止当前话题正在执行的 Agent", usage: "/stop", }) } async fn handle( &self, _cmd: Command, ctx: CommandContext, ) -> Result { // 优先使用 ctx.topic_id,如果没有则从 session_manager 获取真实的 topic_id let topic_id = match ctx.topic_id.as_deref() { Some(id) => { tracing::info!( channel = %ctx.channel_name, chat_id = ?ctx.chat_id, topic_id = %id, source = "ctx", "Stop execution command received" ); id.to_string() } None => { // 从 SessionManager 获取真实的 current topic let chat_id = ctx.chat_id.as_deref().unwrap_or(""); match self .session_manager .get_current_topic(&ctx.channel_name, chat_id) .await { Ok(Some(id)) => { tracing::info!( channel = %ctx.channel_name, chat_id = %chat_id, topic_id = %id, source = "session_manager", "Stop execution command received (resolved from session)" ); id } Ok(None) => { return Ok(CommandResponse::success(ctx.request_id).with_message( MessageKind::Notification, "当前没有活跃的话题,无法停止", )); } Err(e) => { return Ok(CommandResponse::error( ctx.request_id, CommandError::new("QUERY_TOPIC_ERROR", e.to_string()), )); } } } }; let cancelled = self.cancel_manager.cancel_by_topic(&topic_id).await; // 取消传播:同时取消该 topic 下所有正在运行的异步子代理 let cancelled_subagents = if let Some(ref executor) = self.subagent_executor { executor.cancel_pending_for_topic(&topic_id).await } else { 0 }; if cancelled || cancelled_subagents > 0 { let msg = if cancelled && cancelled_subagents > 0 { format!( "正在停止当前任务及 {} 个后台子代理...", cancelled_subagents ) } else if cancelled { "正在停止当前任务...".to_string() } else { format!("正在停止 {} 个后台子代理...", cancelled_subagents) }; Ok(CommandResponse::success(ctx.request_id) .with_message(MessageKind::Notification, msg)) } else { Ok(CommandResponse::success(ctx.request_id) .with_message(MessageKind::Notification, "当前没有正在执行的任务")) } } }