matrixcode_core/command/handlers/
context.rs1use std::future::Future;
6use std::pin::Pin;
7
8use crate::command::{BackendContext, Command};
9use crate::AgentEvent;
10
11pub struct Context;
12
13impl Command for Context {
14 fn name(&self) -> &'static str {
15 "context"
16 }
17
18 fn aliases(&self) -> &[&'static str] {
19 &["ctx"]
20 }
21
22 fn help(&self) -> Option<&'static str> {
23 Some("显示当前上下文信息(消息、记忆、焦点等)")
24 }
25
26 fn execute<'a>(
27 &'a self,
28 ctx: &'a mut BackendContext<'_>,
29 ) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
30 Box::pin(async move {
31 let msg = ctx.message.trim();
32
33 if msg == "/context" || msg == "/context status" || msg == "/ctx" {
34 self.show_status(ctx).await
35 } else if msg == "/context full" || msg == "/ctx full" {
36 self.show_full_preview(ctx).await
37 } else if msg == "/context messages" || msg == "/ctx messages" {
38 self.show_messages(ctx).await
39 } else if msg == "/context memory" || msg == "/ctx memory" {
40 self.show_memory(ctx).await
41 } else if msg == "/context focus" || msg == "/ctx focus" {
42 self.show_focus(ctx).await
43 } else {
44 let _ = ctx
45 .event_tx
46 .send(AgentEvent::progress(
47 "用法:/context [status|full|messages|memory|focus]\n\
48 别名:/ctx\n\
49 - status: 显示上下文状态概览\n\
50 - full: 显示完整上下文预览\n\
51 - messages: 显示消息列表\n\
52 - memory: 显示记忆信息\n\
53 - focus: 显示焦点信息".to_string(),
54 None,
55 ))
56 .await;
57 false
58 }
59 })
60 }
61}
62
63impl Context {
64 async fn show_status(&self, ctx: &mut BackendContext<'_>) -> bool {
66 let info = ctx.agent.get_context_info();
67
68 let mut output = String::new();
69 output.push_str("📊 **上下文状态**\n\n");
70
71 output.push_str(&format!("**模型**: {}\n", info.model_name));
73 output.push_str(&format!("**消息数量**: {}\n", info.message_count));
74 output.push_str(&format!("**估算输入 tokens**: ~{}\n", info.estimated_input_tokens));
75 output.push_str(&format!("**累计输入 tokens**: {}\n", info.total_input_tokens));
76 output.push_str(&format!("**累计输出 tokens**: {}\n", info.total_output_tokens));
77 output.push_str(&format!("**最大 tokens 设置**: {}\n\n", info.max_tokens));
78
79 output.push_str("**系统提示预览**:\n");
81 output.push_str(&format!("> {}...\n\n",
82 truncate_string(&info.system_prompt_preview, 200)));
83
84 if let Some(memory) = &info.memory_summary {
86 output.push_str("**记忆摘要**: ✅ 已加载\n");
87 output.push_str(&format!("> {}...\n\n", truncate_string(memory, 100)));
88 } else {
89 output.push_str("**记忆摘要**: ❌ 未加载\n\n");
90 }
91
92 if let Some(overview) = &info.project_overview_preview {
94 output.push_str("**项目概述**: ✅ 已加载\n");
95 output.push_str(&format!("> {}...\n\n", truncate_string(overview, 100)));
96 } else {
97 output.push_str("**项目概述**: ❌ 未加载\n\n");
98 }
99
100 output.push_str("**最近 5 条消息**:\n");
102 for msg_preview in &info.recent_messages_preview {
103 output.push_str(&format!(" {}\n", msg_preview));
104 }
105
106 if let Some(_storage) = &ctx.memory_storage {
108 output.push_str("\n**记忆存储**: ✅ 已初始化\n");
109 } else {
110 output.push_str("\n**记忆存储**: ❌ 未初始化\n");
111 }
112
113 if let Some(session_mgr) = &ctx.session_mgr {
115 if session_mgr.has_current() {
116 if let Some(current) = session_mgr.current_id() {
117 output.push_str(&format!("\n**当前会话**: {}\n",
118 truncate_string(current, 20)));
119 }
120 } else {
121 output.push_str("\n**当前会话**: 新会话\n");
122 }
123 }
124
125 let _ = ctx
126 .event_tx
127 .send(AgentEvent::progress(output, None))
128 .await;
129
130 false
131 }
132
133 async fn show_full_preview(&self, ctx: &mut BackendContext<'_>) -> bool {
135 let preview = ctx.agent.get_full_context_preview();
136
137 let total_chars = preview.chars().count();
139 let estimated_tokens = total_chars / 3; let output = format!(
142 "📄 **完整上下文预览** ({} 字符, ~{} tokens)\n\n```text\n{}\n```",
143 total_chars,
144 estimated_tokens,
145 preview
146 );
147
148 let _ = ctx
149 .event_tx
150 .send(AgentEvent::progress(output, None))
151 .await;
152
153 false
154 }
155
156 async fn show_messages(&self, ctx: &mut BackendContext<'_>) -> bool {
158 let info = ctx.agent.get_context_info();
159
160 let mut output = String::new();
161 output.push_str(&format!("📨 **消息列表** (共 {} 条)\n\n", info.message_count));
162
163 for msg_preview in &info.recent_messages_preview {
164 output.push_str(&format!("{}\n", msg_preview));
165 }
166
167 if info.message_count > 5 {
168 output.push_str(&format!("\n... 还有 {} 条较早消息", info.message_count - 5));
169 }
170
171 let _ = ctx
172 .event_tx
173 .send(AgentEvent::progress(output, None))
174 .await;
175
176 false
177 }
178
179 async fn show_memory(&self, ctx: &mut BackendContext<'_>) -> bool {
181 let info = ctx.agent.get_context_info();
182
183 let mut output = String::new();
184 output.push_str("🧠 **记忆信息**\n\n");
185
186 if let Some(memory) = &info.memory_summary {
187 output.push_str("**已加载记忆摘要**:\n");
188 output.push_str(&format!("{}\n", memory));
189 } else {
190 output.push_str("**未加载记忆摘要**\n");
191 }
192
193 if let Some(_storage) = &ctx.memory_storage {
195 output.push_str("\n**记忆存储状态**:\n");
196 output.push_str(" ✅ 已初始化\n");
197 } else {
199 output.push_str("\n**记忆存储状态**: ❌ 未初始化\n");
200 }
201
202 let _ = ctx
203 .event_tx
204 .send(AgentEvent::progress(output, None))
205 .await;
206
207 false
208 }
209
210 async fn show_focus(&self, ctx: &mut BackendContext<'_>) -> bool {
212 let mut output = String::new();
213 output.push_str("🎯 **焦点信息**\n\n");
214
215 let info = ctx.agent.get_context_info();
218
219 if let Some(memory) = &info.memory_summary {
220 if memory.contains("焦点") || memory.contains("focus") {
222 output.push_str("**焦点状态**: ✅ 已跟踪\n");
223 output.push_str(&format!("{}\n", memory));
224 } else {
225 output.push_str("**焦点状态**: 信息在记忆摘要中\n");
226 output.push_str(&format!("{}\n", memory));
227 }
228 } else {
229 output.push_str("**焦点状态**: ❌ 无焦点信息\n");
230 }
231
232 output.push_str("\n**提示**: 焦点信息会随记忆一起发送给大模型\n");
236 output.push_str("使用 `/context full` 可查看完整上下文\n");
237
238 let _ = ctx
239 .event_tx
240 .send(AgentEvent::progress(output, None))
241 .await;
242
243 false
244 }
245}
246
247fn truncate_string(s: &str, max: usize) -> String {
249 if s.chars().count() <= max {
250 s.to_string()
251 } else {
252 let truncated: String = s.chars().take(max).collect();
253 format!("{}...", truncated)
254 }
255}