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