返回 DeepSeek-Reasonix
SESSION_REFERENCE_ARCHITECTURE.md
根目录 / docs / SESSION_REFERENCE_ARCHITECTURE.md
1 # 会话引用功能架构文档
2
3 > GitHub Issue: https://github.com/esengine/DeepSeek-Reasonix/issues/3185
4
5 ## 1. 功能需求
6
7 在当前会话中使用 `@` 引用其他会话的聊天记录作为内容发送给 AI。
8
9 ### 1.1 用户场景
10
11 - 用户在当前会话中想引用之前会话的对话内容
12 - 用户想让 AI 参考之前的对话上下文
13 - 用户想合并多个会话的讨论结果
14
15 ### 1.2 预期行为(P0-MVP)
16
17 ```
18 输入 @
19 → 显示原有菜单(文件/目录列表)
20 → 菜单顶部新增 "past:chats" 选项
21 → 选择 past:chats
22 → 切换到历史会话列表
23 → 选择一个会话
24 → Composer 上方显示"已引用会话"
25 → 发送时把该会话历史内容附加到当前 prompt/context
26 ```
27
28 ---
29
30 ## 2. 现有代码结构分析
31
32 ### 2.1 核心文件
33
34 | 文件 | 作用 |
35 |------|------|
36 | `desktop/frontend/src/components/Composer.tsx` | 输入框组件,包含 @ 功能 |
37 | `desktop/frontend/src/components/FileMenu.tsx` | @ 文件菜单组件 |
38 | `desktop/frontend/src/components/HistoryPanel.tsx` | 历史会话面板 |
39 | `desktop/frontend/src/lib/bridge.ts` | 前后端通信接口 |
40 | `desktop/frontend/src/lib/types.ts` | 类型定义 |
41
42 ### 2.2 现有 @ 功能实现
43
44 **Composer.tsx 第 257-337 行** 实现了文件引用功能:
45
46 ```typescript
47 // --- @ file references ---
48 const atRaw = useMemo(() => {
49 const m = /(?:^|\s)@([^\s]*)$/.exec(text);
50 return m ? m[1] : null;
51 }, [text]);
52
53 // 文件匹配结果
54 const atMatches = useMemo(() => {
55 // 过滤本地目录和搜索结果
56 }, [atRaw, atFrag, entries, searchEntries]);
57
58 // 菜单模式判断
59 const menuMode: "slash" | "slasharg" | "at" | null = ...;
60
61 // 渲染文件菜单
62 {menuMode === "at" && <FileMenu items={atMatches} ... />}
63 ```
64
65 ### 2.3 已有的会话 API(可复用)
66
67 ```typescript
68 interface AppBindings {
69 // 会话列表
70 ListSessions(): Promise<SessionMeta[]>;
71
72 // 会话操作(可复用读取历史)
73 PreviewSession(path: string): Promise<HistoryMessage[]>;
74 }
75 ```
76
77 ---
78
79 ## 3. P0-MVP 实施方案
80
81 ### 3.1 设计思路
82
83 在现有的 `@` 菜单中添加 "past:chats" 选项,而不是创建新的 `@session:` 语法。
84
85 **菜单结构:**
86 ```
87 @
88 ├── 📁 past:chats ← 新增:选择后显示历史会话列表
89 ├── 📁 src/
90 ├── 📁 docs/
91 ├── 📄 README.md
92 └── ...
93 ```
94
95 ### 3.2 实施路线
96
97 ```
98 第一步:后端加搜索接口
99
100 第二步:前端 bridge.ts 暴露接口
101
102 第三步:在 @ 菜单中添加 "past:chats" 选项
103
104 第四步:选择 past:chats 后切换到会话列表
105
106 第五步:选择会话后添加到引用区域
107
108 第六步:发送时附加会话上下文
109 ```
110
111 ### 3.3 最小改动文件清单
112
113 ```
114 desktop/frontend/src/lib/types.ts — 添加 SessionReference 类型
115 desktop/frontend/src/lib/bridge.ts — 添加 SearchSessions API
116 desktop/frontend/src/components/Composer.tsx — 扩展 @ 菜单逻辑
117 desktop/frontend/src/components/FileMenu.tsx — 扩展菜单支持会话项
118 desktop/app.go — 添加 SearchSessions 方法
119 desktop/sessions.go — 实现会话搜索逻辑
120 ```
121
122 ### 3.4 类型定义
123
124 ```typescript
125 // types.ts
126 export interface SessionReference {
127 path: string;
128 title: string;
129 preview?: string;
130 turns?: number;
131 createdAt?: number;
132 lastActivityAt?: number;
133 messages?: HistoryMessage[]; // P0 先不存,发送时再拉取
134 }
135 ```
136
137 ### 3.5 API 设计
138
139 ```typescript
140 // bridge.ts
141 interface AppBindings {
142 // 新增:搜索会话
143 SearchSessions(query: string): Promise<SessionMeta[]>;
144
145 // 已有:读取会话历史(复用)
146 PreviewSession(path: string): Promise<HistoryMessage[]>;
147 }
148 ```
149
150 ### 3.6 前端逻辑修改
151
152 **Composer.tsx 修改:**
153
154 ```typescript
155 // 1. 添加状态
156 const [showPastChats, setShowPastChats] = useState(false);
157 const [pastChats, setPastChats] = useState<SessionMeta[]>([]);
158 const [sessionRefs, setSessionRefs] = useState<SessionReference[]>([]);
159
160 // 2. 修改 @ 菜单渲染
161 {menuMode === "at" && (
162 showPastChats ? (
163 // 显示会话列表
164 <SessionMenu
165 items={pastChats}
166 activeIndex={active}
167 onPick={pickSession}
168 onHover={setActive}
169 />
170 ) : (
171 // 显示文件列表(原有逻辑)
172 <>
173 <button
174 className="slashmenu__item slashmenu__item--special"
175 onMouseDown={() => {
176 setShowPastChats(true);
177 app.ListSessions().then(setPastChats);
178 }}
179 >
180 <MessageSquare size={13} />
181 <span className="slashmenu__name">past:chats</span>
182 <span className="slashmenu__desc">引用历史会话</span>
183 </button>
184 <FileMenu items={atMatches} ... />
185 </>
186 )
187 )}
188
189 // 3. 选择会话后的处理
190 const pickSession = (session: SessionMeta) => {
191 // 添加到引用区域
192 setSessionRefs(prev => [...prev, {
193 path: session.path,
194 title: session.title || session.preview || "Untitled",
195 preview: session.preview,
196 turns: session.turns,
197 createdAt: session.createdAt,
198 lastActivityAt: session.lastActivityAt,
199 }]);
200
201 // 重置状态
202 setShowPastChats(false);
203 setText(""); // 清空输入框
204 };
205
206 // 4. 发送时附加会话上下文
207 const handleSubmit = async () => {
208 let context = "";
209
210 if (sessionRefs.length > 0) {
211 context = "以下是用户引用的历史会话上下文:\n\n";
212 for (const ref of sessionRefs) {
213 const messages = await app.PreviewSession(ref.path);
214 const limited = limitMessages(messages, 30, 20000);
215 context += formatSessionContext(ref.title, limited);
216 }
217 context += "\n\n当前用户问题:\n";
218 }
219
220 onSubmit(context + text);
221 };
222 ```
223
224 ### 3.7 限制策略
225
226 ```
227 最多引用最近 30 条消息
228 或最多 20k 字符
229 超出部分截断,并提示"已截断"
230 ```
231
232 ### 3.8 发送时的消息格式
233
234 ```
235 以下是用户引用的历史会话上下文:
236
237 [会话:修复登录 bug]
238 用户:...
239 助手:...
240 用户:...
241
242 当前用户问题:
243 ...
244 ```
245
246 ---
247
248 ## 4. 架构图
249
250 ```
251 ┌─────────────────────────────────────────────────────────────┐
252 │ Composer.tsx │
253 │ ┌─────────────────────────────────────────────────────┐ │
254 │ │ @ 菜单逻辑 │ │
255 │ │ - 原有:文件/目录列表 │ │
256 │ │ - 新增:past:chats 选项(在菜单顶部) │ │
257 │ └─────────────────────────────────────────────────────┘ │
258 │ │ │
259 │ ▼ │
260 │ ┌─────────────────────────────────────────────────────┐ │
261 │ │ 菜单渲染 │ │
262 │ │ - showPastChats=false → FileMenu + past:chats 按钮 │ │
263 │ │ - showPastChats=true → SessionMenu (会话列表) │ │
264 │ └─────────────────────────────────────────────────────┘ │
265 └─────────────────────────────────────────────────────────────┘
266
267
268 ┌─────────────────────────────────────────────────────────────┐
269 │ bridge.ts │
270 │ ┌─────────────────────────────────────────────────────┐ │
271 │ │ 新增 API: │ │
272 │ │ - SearchSessions(query): Promise<SessionMeta[]> │ │
273 │ │ │ │
274 │ │ 复用 API: │ │
275 │ │ - ListSessions(): Promise<SessionMeta[]> │ │
276 │ │ - PreviewSession(path): Promise<HistoryMessage[]> │ │
277 │ └─────────────────────────────────────────────────────┘ │
278 └─────────────────────────────────────────────────────────────┘
279
280
281 ┌─────────────────────────────────────────────────────────────┐
282 │ desktop/app.go │
283 │ ┌─────────────────────────────────────────────────────┐ │
284 │ │ 新增方法: │ │
285 │ │ - SearchSessions(query string) []SessionMeta │ │
286 │ └─────────────────────────────────────────────────────┘ │
287 └─────────────────────────────────────────────────────────────┘
288 ```
289
290 ---
291
292 ## 5. UI 设计
293
294 ### 5.1 @ 菜单(showPastChats=false)
295
296 ```
297 ┌─────────────────────────────────────────────────────────────┐
298 │ @ ← 用户输入 │
299 │ ┌─────────────────────────────────────────────────────┐ │
300 │ │ 💬 past:chats 引用历史会话 │ │
301 │ ├─────────────────────────────────────────────────────┤ │
302 │ │ 📁 src/ │ │
303 │ │ 📁 docs/ │ │
304 │ │ 📄 README.md │ │
305 │ └─────────────────────────────────────────────────────┘ │
306 │ │
307 │ [输入消息...] [发送] │
308 └─────────────────────────────────────────────────────────────┘
309 ```
310
311 ### 5.2 会话列表(showPastChats=true)
312
313 ```
314 ┌─────────────────────────────────────────────────────────────┐
315 │ @past:chats ← 用户输入 │
316 │ ┌─────────────────────────────────────────────────────┐ │
317 │ │ 💬 项目架构设计讨论 - 2026-06-04 │ │
318 │ │ 💬 数据处理方案 - 2026-06-03 │ │
319 │ │ 💬 API 接口设计 - 2026-06-02 │ │
320 │ │ ← 返回文件列表 │ │
321 │ └─────────────────────────────────────────────────────┘ │
322 │ │
323 │ [输入消息...] [发送] │
324 └─────────────────────────────────────────────────────────────┘
325 ```
326
327 ### 5.3 引用区域
328
329 ```
330 ┌─────────────────────────────────────────────────────────────┐
331 │ 📎 引用的会话: │
332 │ ┌─────────────────────────────────────────────────────┐ │
333 │ │ 📄 项目架构设计讨论 (8 轮) [×] │ │
334 │ └─────────────────────────────────────────────────────┘ │
335 ├─────────────────────────────────────────────────────────────┤
336 │ │
337 │ [输入消息...] [发送] │
338 └─────────────────────────────────────────────────────────────┘
339 ```
340
341 ---
342
343 ## 6. P1 后续优化(暂不实施)
344
345 - 选择单条/多条消息
346 - hover 预览会话详情
347 - 截断/缓存优化
348 - 国际化翻译
349 - 搜索会话功能
350
351 ---
352
353 ## 7. 验收标准
354
355 ### P0 验收
356
357 - [ ] 输入 `@` 显示菜单,包含 "past:chats" 选项
358 - [ ] 选择 "past:chats" 显示历史会话列表
359 - [ ] 选择会话后显示在引用区域
360 - [ ] 可以删除引用的会话
361 - [ ] 发送时正确附加会话上下文
362 - [ ] 引用内容限制在 30 条消息或 20k 字符内
363 - [ ] 超出部分截断并提示
364
365 ### 测试用例
366
367 - [ ] 无历史会话时的行为
368 - [ ] 引用超大会话时的截断
369 - [ ] 与现有 @ 文件引用同时使用
370 - [ ] 在不同主题下的显示效果
371
371 lines MARKDOWN