跳转到内容

对话压缩与会话恢复

对话压缩与会话恢复

学习目标

本章要解决的核心问题:当 AI 编程对话越来越长,超出模型上下文窗口时,如何压缩历史对话?会话如何在关闭后恢复?

你将学到:

  • Continue 的对话压缩(compactConversation)机制
  • 基于 SQLite 的本地会话持久化
  • Control Plane 远程会话同步
  • CLI 的 --resumecn ls 会话恢复

前置知识

本章涉及上下文压缩和记忆系统的通用原理,建议先阅读:


项目实践

对话压缩

当对话超出模型的上下文窗口时,Continue 使用 compactConversation 进行摘要压缩:

// 伪代码摘要
async function compactConversation({ sessionId, index, historyManager, currentModel }) {
// 1. 加载会话历史
const session = historyManager.load(sessionId);
// 2. 确定需要压缩的部分(最早的消息)
const messagesToCompact = session.history.slice(0, index);
// 3. 使用 LLM 生成摘要
const summary = await currentModel.generateSummary({
messages: messagesToCompact,
systemPrompt: "请总结这段编程对话的关键信息和上下文。"
});
// 4. 用摘要替换原始消息
session.compactSummary = summary;
session.compactIndex = index;
historyManager.save(session);
}

压缩策略:

  • 保留最近的对话消息(不压缩)
  • 将早期对话压缩为摘要
  • 摘要包含关键的代码片段、文件路径、决策记录
  • 使用当前对话中配置的 chat 模型执行压缩

本地会话存储

Continue 使用 SQLite 存储本地会话历史:

用户开始新对话
historyManager.create(session)
每条消息追加到 SQLite
用户关闭 IDE → 会话自动保存
用户重新打开 → 从 SQLite 加载

会话管理 API:

  • historyManager.list() — 列出所有会话(按时间排序)
  • historyManager.load(id) — 加载特定会话的完整历史
  • historyManager.save(session) — 保存或更新会话
  • historyManager.delete(id) — 删除会话
  • historyManager.clearAll() — 清除所有本地会话

远程会话同步

Continue 支持通过 Control Plane 同步会话到远程服务器:

// 本地 + 远程会话合并
on("history/list", async (msg) => {
const localSessions = historyManager.list(msg.data);
// 检查是否启用远程会话
const shouldFetchRemote = await configHandler.controlPlaneClient
.shouldEnableRemoteSessions();
// 获取远程会话
const remoteSessions = shouldFetchRemote
? await configHandler.controlPlaneClient.listRemoteSessions()
: [];
// 合并 + 按时间排序
return [...localSessions, ...remoteSessions]
.sort((a, b) => new Date(b.dateCreated) - new Date(a.dateCreated))
.slice(0, limit);
});

远程会话的加载:

on("history/loadRemote", async (msg) => {
return configHandler.controlPlaneClient.loadRemoteSession(msg.data.remoteId);
});

CLI 会话恢复

CLI 提供了独特的会话恢复体验:

Terminal window
# 恢复当前终端的最后一次会话
cn --resume
# 列出所有历史会话并选择
cn ls
# JSON 格式输出(适合脚本)
cn ls --json

CLI 的会话管理:

  • 每个终端会话有唯一的 session ID
  • 会话历史保存在本地 SQLite 中
  • cn ls 显示一个 TUI 选择器,按屏幕高度限制条目数
  • --resume 自动恢复最后一次的对话上下文

问题与规避

陷阱 1:压缩后的信息丢失

现象:对话压缩后,LLM 无法回答关于早期对话细节的问题。

原因:摘要压缩本质上是有损的——只保留关键信息。

规避

  • 压缩 prompt 指示保留代码片段、文件路径、决策等关键信息
  • 用户可以手动回顾压缩前的完整历史(如果有保存的话)
  • 重要的结论应该让用户确认并记录到规则文件中

陷阱 2:SQLite 数据库锁竞争

现象:多个进程同时写入会话历史时出现 SQLITE_BUSY 错误。

规避:索引系统明确处理这种情况——在 CodebaseIndexer 中对 SQLITE_BUSY 错误不做清除索引处理(区别于其他 SQLite 错误)。会话写入也采用类似的策略。

陷阱 3:远程会话同步延迟

现象:在 VS Code 中开始对话,切换到 CLI 时看不到最新的历史记录。

原因:远程会话同步是异步的,可能需要几秒才能传播。

规避:本地会话总是立即可用。远程会话作为补充,不保证实时一致。


设计取舍

对话压缩 vs 截断

方案优势代价
截断简单,零成本丢失历史信息
压缩(摘要)保留关键信息需要额外的 LLM 调用,有损压缩
滑动窗口保留最近 N 条消息早期信息完全丢失

Continue 选择压缩(摘要),因为编程对话的早期部分通常包含重要的上下文信息(项目结构、架构决策、已发现的文件路径),这些信息在后续对话中仍然相关。截断会丢失这些关键上下文。

本地优先 + 远程可选

Continue 的会话存储策略是本地优先

  • 所有会话首先在本地 SQLite 中存储
  • 远程同步是可选的(需要 Control Plane 登录)
  • 即使远程服务不可用,本地会话仍然可用

这与一些云端优先的方案(如 Cursor 的云端历史)不同,Continue 保证了即使没有网络连接,会话历史也不丢失


参考来源