use crate::command::context::CommandContext; use crate::command::handler::{CommandHandler, CommandMetadata}; use crate::command::response::{CommandError, CommandResponse, MessageKind}; use crate::command::Command; use crate::storage::SessionStore; use async_trait::async_trait; use serde::{Deserialize, Serialize}; use std::sync::Arc; /// Topic 摘要信息 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TopicSummary { pub topic_id: String, pub session_id: String, pub title: String, pub description: Option, pub message_count: i64, pub created_at: i64, pub last_active_at: i64, } /// 列出 Session 的 Topics 命令处理器 pub struct ListTopicsCommandHandler { store: Arc, } impl ListTopicsCommandHandler { pub fn new(store: Arc) -> Self { Self { store } } } #[async_trait] impl CommandHandler for ListTopicsCommandHandler { fn can_handle(&self, cmd: &Command) -> bool { matches!(cmd, Command::ListTopics { .. }) } fn metadata(&self) -> Option { Some(CommandMetadata { name: "topics", description: "列出 Session 的所有 Topics", usage: "/topics ", }) } async fn handle( &self, cmd: Command, ctx: CommandContext, ) -> Result { match cmd { Command::ListTopics { session_id } => { handle_list_topics(self, session_id, ctx).await } _ => unreachable!(), } } } async fn handle_list_topics( handler: &ListTopicsCommandHandler, session_id: String, ctx: CommandContext, ) -> Result { let topics = handler .store .list_topics(&session_id) .map_err(|e| CommandError::new("LIST_TOPICS_ERROR", e.to_string()))?; let summaries: Vec = topics .into_iter() .map(|t| TopicSummary { topic_id: t.id, session_id: t.session_id, title: t.title, description: t.description.filter(|d| !d.is_empty()), message_count: t.message_count, created_at: t.created_at, last_active_at: t.last_active_at, }) .collect(); let topics_json = serde_json::to_string(&summaries) .map_err(|e| CommandError::new("SERIALIZE_ERROR", e.to_string()))?; let message = format!( "Found {} topic(s) in session '{}'", summaries.len(), session_id ); Ok(CommandResponse::success(ctx.request_id) .with_message(MessageKind::Notification, &message) .with_metadata("topics", &topics_json) .with_metadata("session_id", &session_id) .with_metadata("count", &summaries.len().to_string())) }