feat(context): /clear 指令截断上下文并按会话过期归档

用户发送 /clear 时主动截断上下文:加载历史 → LLM 生成摘要归档
→ 丢弃在途会话 → 回复确认(带摘要预览)。

- context/types: SummaryReason 新增 Clear 变体
- context/builder: 抽出 archive_session 共享逻辑,
  新增 trigger_clear_summary(返回摘要文本)
- db/models: 新增 latest_session_boundary;list_recent_chat_records
  _for_context 按会话边界过滤(clear/timeout),并排除 source=clear
- daemon: SessionMap 记录 user_id;拦截 /clear 走 handle_clear_command;
  新增 build_clear_reply 纯函数
- migration: session_summaries (user_id, created_at DESC) 索引

会话边界机制统一 clear 与 12h 空闲超时;摘要不注入下一对话,
只存档供 read_summaries 查询。新增 4 个单元测试。
This commit is contained in:
2026-06-23 11:57:07 +08:00
parent 0299329fb2
commit 132089c8eb
6 changed files with 325 additions and 17 deletions
+27
View File
@@ -333,6 +333,33 @@ flowchart TB
I --> J["发送给 LLM"]
```
### 5.3.1 `/clear` 清空上下文流程
用户发送 `/clear` 指令时,主动截断上下文并把本次会话归档为摘要(按会话过期处理):
```mermaid
flowchart TB
U(["📱 用户发送 /clear"]) --> K{"is_clear_command() 匹配?"}
K -->|"否"| N(["走正常 LLM 对话流程"])
K -->|"是"| L["加载历史(过滤掉 /clear 本身)"]
L --> M{"历史非空?"}
M -->|"否"| R2["回复: 上下文已是空的"]
M -->|"是"| S["一次性 Conversation + summarizer"]
S --> T["trigger_clear_summary() → LLM 生成摘要"]
T --> DB[("session_summaries\nreason=clear")]
DB --> D["丢弃该用户在途会话 (sessions.retain)"]
D --> R1["回复确认 + 摘要预览"]
R2 --> END(["📱 用户收到回复"])
R1 --> END
```
- **会话边界**:摘要的 `created_at` 作为边界,之后加载历史时通过
`latest_session_boundary()` 过滤掉此前的消息(`/clear` 与 12h 空闲超时
共用同一套边界机制)
- **注入与否**`/clear` 摘要**不会**注入下一次对话的 system prompt
只存档供 `read_summaries` 工具查询(与空闲超时摘要一致)
- **在途会话**`/clear` 会丢弃该用户尚未完成的工具往返,避免用旧上下文继续
---
## 6. 文件依赖矩阵