主题
上下文压缩系统
本文引用的源码文件
本文引用的文件
- src/background/context-compactor.js
- src/side_panel/context-indicator.js
- src/side_panel/auto-compaction.js
- src/shared/compaction-prompt.js
- src/background/compaction-memory.js
- src/shared/context-usage.js
- src/shared/context-usage.js
- src/shared/token-counter.js
- src/background/constants.js
- src/background/config.js
- test/unit/compaction-error-surface.unit.test.js
更新摘要
变更内容
- 新增详细的错误处理机制,区分超时错误、空摘要、HTTP失败和解析异常
- 实现
compactErrorDetail函数提供可操作的反馈信息 - 增强 toast 通知系统,显示具体错误原因而非通用提示
- 改进 SSE 流式处理的空闲超时检测
- 完善单元测试覆盖各种错误场景
目录
引言
本文件面向"上下文压缩系统"的完整技术文档,覆盖自动触发条件、压缩策略算法、质量评估、用户控制、压缩后重建、性能优化与效果调优。该系统在扩展端(Manifest V3)与本地 Agent 端之间协作:扩展端负责 UI 交互、阈值决策、素材组装与注入;Agent 端提供长期记忆存储等能力。
更新 新增了详细的错误处理机制,能够区分不同类型的压缩失败并提供具体的用户反馈。
项目结构
上下文压缩相关代码分布在以下模块:
- 侧边栏交互与自动触发:
src/side_panel/context-indicator.js、src/side_panel/auto-compaction.js - 背景进程摘要生成与沉淀:
src/background/context-compactor.js、src/background/compaction-memory.js - 共享提示词与上下文预算:
src/shared/compaction-prompt.js、src/shared/context-usage.js、src/shared/token-counter.js - ReAct 循环中的增量批量压缩:
src/background/context-summarizer.js - 配置与默认值:
src/background/constants.js、src/background/config.js
graph TB subgraph "侧边栏" CI["context-indicator.js<br/>手动压缩/撤销/预览"] AC["auto-compaction.js<br/>半自动触发决策"] end subgraph "背景进程" CC["context-compactor.js<br/>结构化摘要生成"] CM["compaction-memory.js<br/>摘要沉淀到长期记忆"] CS["context-summarizer.js<br/>增量批量压缩"] end subgraph "共享层" CP["compaction-prompt.js<br/>提示词模板与限量"] CU["context-usage.js<br/>发送历史选择/注入"] TC["token-counter.js<br/>Token估算/窗口/预算"] end subgraph "配置" Cst["constants.js<br/>默认对话配置"] Cfg["config.js<br/>读取 chatConfig"] end CI --> AC CI --> CC CC --> CM CS --> CC CI --> CU AC --> CU CU --> TC CC --> CP CM --> Cfg Cst --> Cfg
图表来源
- src/side_panel/context-indicator.js#L296-L396
- src/side_panel/auto-compaction.js#L35-L122
- src/background/context-compactor.js#L32-L80
- src/background/compaction-memory.js#L37-L81
- src/background/context-summarizer.js#L181-L245
- src/shared/compaction-prompt.js#L63-L83
- src/shared/context-usage.js#L39-L145
- src/shared/token-counter.js#L397-L448
- src/background/constants.js#L78-L85
- src/background/config.js#L66-L89
章节来源
- src/side_panel/context-indicator.js#L296-L396
- src/side_panel/auto-compaction.js#L35-L122
- src/background/context-compactor.js#L32-L80
- src/background/compaction-memory.js#L37-L81
- src/background/context-summarizer.js#L181-L245
- src/shared/compaction-prompt.js#L63-L83
- src/shared/context-usage.js#L39-L145
- src/shared/token-counter.js#L397-L448
- src/background/constants.js#L78-L85
- src/background/config.js#L66-L89
核心组件
- 手动压缩入口与状态管理:
context-indicator.js - 半自动触发策略:
auto-compaction.js - 结构化摘要生成:
context-compactor.js - 摘要沉淀为长期记忆:
compaction-memory.js - 增量批量压缩(ReAct 超阈值):
context-summarizer.js - 提示词模板与素材限量:
compaction-prompt.js - 发送历史选择与摘要注入:
context-usage.js - Token 估算、上下文窗口与预算:
token-counter.js - 默认对话配置与读取:
constants.js、config.js
章节来源
- src/side_panel/context-indicator.js#L296-L396
- src/side_panel/auto-compaction.js#L35-L122
- src/background/context-compactor.js#L32-L80
- src/background/compaction-memory.js#L37-L81
- src/background/context-summarizer.js#L181-L245
- src/shared/compaction-prompt.js#L63-L83
- src/shared/context-usage.js#L39-L145
- src/shared/token-counter.js#L397-L448
- src/background/constants.js#L78-L85
- src/background/config.js#L66-L89
架构总览
上下文压缩系统由三层组成:
- 触发层:基于 Token 阈值检测、上下文窗口限制和性能监控指标决定是否压缩。
- 处理层:执行摘要生成、历史消息合并、工具调用精简和无关内容过滤。
- 重建层:将压缩结果注入 system prompt,并保证消息重组、工具链恢复与状态一致性。
sequenceDiagram participant UI as "侧边栏界面" participant Auto as "自动压缩决策" participant Indicator as "手动压缩内核" participant BG as "背景摘要生成" participant Memory as "长期记忆沉淀" participant Usage as "发送历史选择/注入" participant Model as "模型 API" UI->>Auto : 发送前检查是否自动压缩 Auto->>Indicator : silent=true 触发压缩 Indicator->>BG : 提交素材(material, model, sessionId) BG->>Model : 请求结构化摘要 Model-->>BG : 返回摘要文本或错误 BG->>Memory : 可选沉淀摘要(带 memoryId 去重) Memory-->>BG : 返回 memoryId BG-->>Indicator : 返回 summary + memoryId 或错误详情 Indicator->>Usage : 更新 activeCompaction Usage-->>UI : 注入 system prompt 并显示分隔条
图表来源
- src/side_panel/auto-compaction.js#L76-L122
- src/side_panel/context-indicator.js#L296-L396
- src/background/context-compactor.js#L32-L80
- src/background/compaction-memory.js#L37-L81
- src/shared/context-usage.js#L120-L145
详细组件分析
自动触发条件
- Token 阈值检测:通过
computeContextUsage计算当前占用比 ratio,并与autoCompactionThreshold比较。 - 上下文窗口限制:使用
getContextWindow获取模型上下文窗口,结合 system、工具定义、输出预留和安全余量计算 historyBudget。 - 性能监控指标:连续失败退避计数、生成中保护、记忆开关保护。
flowchart TD
Start(["进入发送前置"]) --> CheckEnabled{"自动压缩已启用?"}
CheckEnabled --> |否| Skip["跳过自动压缩"]
CheckEnabled --> |是| GetRatio["计算 ratio"]
GetRatio --> RatioOK{"ratio >= 阈值?"}
RatioOK --> |否| Skip
RatioOK --> |是| PendingCheck{"压缩点后新消息数 >= minPending?"}
PendingCheck --> |否| Skip
PendingCheck --> |是| Compact["silent=true 触发压缩"]
Compact --> Result{"压缩成功?"}
Result --> |是| ResetBackoff["重置连续失败计数"]
Result --> |否| IncFail["连续失败+1"]
ResetBackoff --> End(["继续发送"])
IncFail --> End
Skip --> End
图表来源
- src/side_panel/auto-compaction.js#L35-L49
- src/side_panel/auto-compaction.js#L76-L122
- src/shared/context-usage.js#L152-L212
- src/shared/token-counter.js#L397-L448
章节来源
- src/side_panel/auto-compaction.js#L35-L49
- src/side_panel/auto-compaction.js#L76-L122
- src/shared/context-usage.js#L152-L212
- src/shared/token-counter.js#L397-L448
压缩策略算法
- 摘要生成:
buildCompactionPrompt构建结构化四小节提示词,按语言选择指令块,并对素材进行单条与总量截断。 - 历史消息合并:
assembleCompactionMaterial将已有摘要与窗口内消息合并为素材,避免被裁剪头部永久丢失。 - 工具调用精简:
context-summarizer.js提取 tool_calls 的关键参数与结果片段,构造紧凑 transcript。 - 无关内容过滤:
sanitizeMaterialContent清洗非字符串内容,去除图片数据,保留关键标识符。
classDiagram
class CompactionPrompt {
+buildCompactionPrompt(material, lang) string
+sanitizeMaterialContent(content) string
+COMPACTION_SECTION_HEADINGS
}
class ContextUsage {
+selectHistoryForSend(history, options) object
+assembleCompactionMaterial(history, options) object
+appendCompactionToSystemPrompt(systemContent, compaction) string
+applyCompactionInjection(messages, selection, compaction, logger) Array
+computeContextUsage(params) object
}
class TokenCounter {
+estimateTokens(text) number
+estimateMessagesTokens(messages) number
+truncateByTokens(content, maxTokens) string
+getContextWindow(modelName, userConfiguredWindow, customModelMap) number
+assessContextPressure(usedTokens, budget) object
}
CompactionPrompt <.. ContextUsage : "用于构建提示词"
TokenCounter <.. ContextUsage : "用于预算与窗口"
图表来源
- src/shared/compaction-prompt.js#L14-L83
- src/shared/context-usage.js#L39-L145
- src/shared/context-usage.js#L220-L239
- src/shared/token-counter.js#L146-L217
- src/shared/token-counter.js#L397-L448
章节来源
- src/shared/compaction-prompt.js#L14-L83
- src/shared/context-usage.js#L39-L145
- src/shared/context-usage.js#L220-L239
- src/shared/token-counter.js#L146-L217
- src/shared/token-counter.js#L397-L448
压缩质量评估
- 语义保留度:结构化四小节模板强调任务目标、已完成事项、关键标识符与未决问题,避免丢弃既有摘要有效信息。
- 关键信息提取:工具调用关键参数与结果片段保留,路径、符号、URL 等标识符原样保留。
- 用户反馈机制:手动确认框、进行中模态、完成 toast、撤销与再次压缩按钮,以及详情弹窗预览/源码双模式。
章节来源
- src/shared/compaction-prompt.js#L27-L55
- src/background/context-summarizer.js#L55-L107
- src/side_panel/context-indicator.js#L240-L396
- src/side_panel/context-indicator.js#L582-L624
用户控制
- 手动触发:
triggerCompaction弹出确认框与进行中模态,成功后显示节约 tokens 提示。 - 压缩级别选择:通过
chatConfig.autoCompactionThreshold调整触发阈值;maxMemoryMessages控制携带历史范围。 - 预览确认:详情弹窗支持查看摘要全文(Markdown 预览或源码),并可撤销压缩。
章节来源
- src/side_panel/context-indicator.js#L296-L396
- src/side_panel/context-indicator.js#L582-L624
- src/background/constants.js#L78-L85
- src/background/config.js#L66-L89
压缩后的上下文重建
- 消息重组:
selectHistoryForSend根据压缩点过滤历史,仅保留压缩点之后的消息参与发送。 - 工具链恢复:
filterApiMessages修复 assistant(tool_calls) 与 tool 配对,确保工具调用完整性。 - 状态一致性:
activeCompaction包含 upToMessageId、compressedCount、summaryTokens、memoryId 等字段,保证跨会话一致性与去重。
sequenceDiagram participant Usage as "context-usage.js" participant TC as "token-counter.js" participant UI as "context-indicator.js" UI->>Usage : assembleCompactionMaterial(history, options) Usage->>TC : estimateMessagesTokens(material) TC-->>Usage : materialTokens Usage-->>UI : material + includedCount UI->>Usage : selectHistoryForSend(history, options) Usage->>TC : estimateMessagesTokens(keptHistory) TC-->>Usage : historyTokens Usage-->>UI : messages + compactionApplied
图表来源
- src/shared/context-usage.js#L220-L239
- src/shared/context-usage.js#L39-L114
- src/shared/token-counter.js#L160-L192
章节来源
- src/shared/context-usage.js#L39-L114
- src/shared/token-counter.js#L580-L675
- src/side_panel/context-indicator.js#L357-L371
错误处理与用户反馈
新增 系统现在提供详细的错误处理机制,能够区分不同类型的压缩失败并通过 toast 通知向用户提供具体反馈。
错误类型分类
- 超时错误:SSE 流空闲超时(headers 后卡流),显示"请求超时"
- 空摘要错误:模型返回空摘要,显示"模型未返回摘要"
- HTTP 失败:API 错误状态码及详细信息,显示"API 错误 HTTP {status}"
- 解析异常:JSON 解析失败或其他异常情况
错误详情映射机制
compactErrorDetail 函数将后端返回的错误码转换为可读的用户反馈:
flowchart TD
Error["后端错误"] --> TypeCheck{"错误类型判断"}
TypeCheck --> |empty_summary| Empty["空摘要错误"]
TypeCheck --> |CHAT_STREAM_IDLE_TIMEOUT| Timeout["超时错误"]
TypeCheck --> |http_*| Http["HTTP 错误"]
TypeCheck --> |其他| Generic["通用错误"]
Http --> ParseBody["解析响应正文"]
ParseBody --> ExtractMsg["提取 error.message"]
ExtractMsg --> Display["显示详细错误信息"]
Empty --> ShowEmpty["显示'模型未返回摘要'"]
Timeout --> ShowTimeout["显示'请求超时'"]
Generic --> ShowGeneric["显示原始错误信息"]
图表来源
用户反馈流程
- 配置缺失:直接显示"无法压缩:缺少 API 配置"
- 网络错误:显示 HTTP 状态码和具体错误原因
- 流式超时:显示"请求超时"而非原始错误码
- 空摘要:显示"模型未返回摘要"
- 其他异常:显示原始错误信息
章节来源
- src/side_panel/context-indicator.js#L294-L323
- src/side_panel/context-indicator.js#L386-L395
- src/background/context-compactor.js#L63-L83
- test/unit/compaction-error-surface.unit.test.js#L49-L110
依赖关系分析
- 侧边栏依赖共享层进行上下文计算与注入。
- 背景进程依赖共享层构建提示词与记录 token 使用。
- 配置层提供默认值与读取逻辑,影响自动压缩行为。
graph LR AC["auto-compaction.js"] --> CU["context-usage.js"] CI["context-indicator.js"] --> CU CC["context-compactor.js"] --> CP["compaction-prompt.js"] CC --> TC["token-counter.js"] CM["compaction-memory.js"] --> Cfg["config.js"] Cst["constants.js"] --> Cfg
图表来源
- src/side_panel/auto-compaction.js#L35-L122
- src/side_panel/context-indicator.js#L296-L396
- src/background/context-compactor.js#L32-L80
- src/background/compaction-memory.js#L37-L81
- src/background/constants.js#L78-L85
- src/background/config.js#L66-L89
章节来源
- src/side_panel/auto-compaction.js#L35-L122
- src/side_panel/context-indicator.js#L296-L396
- src/background/context-compactor.js#L32-L80
- src/background/compaction-memory.js#L37-L81
- src/background/constants.js#L78-L85
- src/background/config.js#L66-L89
性能与优化
- 异步处理:所有 LLM 调用均使用异步接口,失败不阻塞主流程。
- 增量压缩:
context-summarizer.js支持批量压缩多轮旧对话,减少重复调用。 - 缓存策略:system prompt 与 MCP 工具数缓存,避免高频重算。
- Token 校准:EWMA 校准因子平滑估算偏差,提升预算准确性。
章节来源
- src/background/context-summarizer.js#L181-L245
- src/side_panel/context-indicator.js#L110-L148
- src/shared/token-counter.js#L82-L127
质量评估与调优
- 准确率测试:通过单元测试验证提示词构建、注入逻辑与自动触发决策。
- 用户满意度调查:观察 toast 提示、撤销成功率与详情弹窗使用情况。
- 参数优化:调整
autoCompactionThreshold、minPending、maxMemoryMessages以平衡压缩频率与效果。
章节来源
- src/side_panel/auto-compaction.js#L35-L49
- src/side_panel/context-indicator.js#L240-L396
- src/background/constants.js#L78-L85
故障排查指南
- 配置缺失:若 API 配置缺失,压缩将返回错误码
config_missing。 - 生成中保护:正在生成回复时禁止压缩,避免打断用户。
- 记忆关闭:记忆功能关闭时无可压缩内容,直接返回
memory_off。 - 连续失败退避:自动压缩连续失败达到上限后进入退避,不再尝试。
- 新增 错误类型识别:系统现在能够区分超时、空摘要、HTTP 错误和解析异常,并提供具体的用户反馈。
章节来源
- src/background/context-compactor.js#L36-L39
- src/side_panel/context-indicator.js#L296-L304
- src/side_panel/auto-compaction.js#L81-L91
结论
上下文压缩系统通过结构化摘要、阈值驱动触发与多阶段重建,实现了高效且可控的上下文管理。系统在用户体验、性能与稳定性之间取得平衡,并提供丰富的用户控制选项与故障恢复机制。
更新 最新的错误处理改进显著提升了系统的可诊断性和用户体验,通过详细的错误分类和具体的用户反馈,帮助用户更好地理解压缩失败的原因并采取相应措施。未来可进一步优化摘要质量评估与自动化调参策略。