Skip to main content

matrixcode_core/command/handlers/
sessions.rs

1//! /sessions 命令实现
2//!
3//! 列出和管理会话。
4
5use super::super::backend_context::BackendContext;
6use super::super::command_trait::Command;
7use crate::event::{AgentEvent, EventData, EventType, SessionListItem};
8
9/// Sessions 命令
10///
11/// 用法:
12/// - /sessions - 列出所有会话
13/// - /sessions cleanup - 清理旧会话
14/// - /sessions stats - 显示会话统计
15/// - /resume - 别名,列出会话
16pub struct Sessions;
17
18impl Command for Sessions {
19    fn name(&self) -> &'static str {
20        "sessions"
21    }
22
23    fn aliases(&self) -> &[&'static str] {
24        &["resume"]
25    }
26
27    fn help(&self) -> Option<&'static str> {
28        Some("列出和管理会话。用法: /sessions [cleanup|stats]")
29    }
30
31    fn execute<'a>(
32        &'a self,
33        ctx: &'a mut BackendContext<'_>,
34    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = bool> + Send + 'a>> {
35        Box::pin(async move {
36            const SESSION_CLEANUP_DAYS: u64 = 30;
37            const DISPLAY_SESSIONS_LIMIT: usize = 20;
38
39            let subcmd = if ctx.message.starts_with("/sessions ") {
40                ctx.message.strip_prefix("/sessions ").unwrap_or("")
41            } else {
42                ""
43            };
44
45            if let Some(mgr) = ctx.session_mgr {
46                if subcmd == "cleanup" {
47                    let removed = mgr.cleanup_old_sessions(SESSION_CLEANUP_DAYS).unwrap_or(0);
48                    let _ = ctx
49                        .event_tx
50                        .send(crate::AgentEvent::progress(
51                            format!("✓ Removed {} old sessions", removed),
52                            None,
53                        ))
54                        .await;
55                } else if subcmd == "stats" {
56                    let sessions = mgr.list_sessions();
57                    let _ = ctx
58                        .event_tx
59                        .send(crate::AgentEvent::progress(
60                            format!("📊 {} sessions total", sessions.len()),
61                            None,
62                        ))
63                        .await;
64                } else {
65                    let sessions = mgr.list_sessions();
66                    if sessions.is_empty() {
67                        let _ = ctx
68                            .event_tx
69                            .send(crate::AgentEvent::progress("No saved sessions", None))
70                            .await;
71                    } else {
72                        // Send SessionsList event for interactive selector
73                        let session_list: Vec<SessionListItem> = sessions
74                            .iter()
75                            .take(DISPLAY_SESSIONS_LIMIT)
76                            .map(|s| {
77                                let local: chrono::DateTime<chrono::Local> = s.created_at.with_timezone(&chrono::Local);
78                                let formatted_time = local.format("%Y-%m-%d %H:%M").to_string();
79                                SessionListItem {
80                                    short_id: s.short_id(),
81                                    title: s.display_name(),
82                                    message_count: s.message_count,
83                                    created_at: formatted_time,
84                                }
85                            })
86                            .collect();
87                        
88                        let _ = ctx
89                            .event_tx
90                            .send(AgentEvent::with_data(
91                                EventType::SessionsList,
92                                EventData::SessionsList { sessions: session_list },
93                            ))
94                            .await;
95                    }
96                }
97            } else {
98                let _ = ctx
99                    .event_tx
100                    .send(crate::AgentEvent::progress(
101                        "❌ Session manager not available",
102                        None,
103                    ))
104                    .await;
105            }
106
107            false // 不转发给 agent
108        })
109    }
110}