本文档说明 NeoCode 中 context compact 的配置、执行链路和摘要约定。
- runtime 已接入手动 compact、基于 token 阈值的自动 compact,以及 provider 上下文过长后的
reactivecompact 自动恢复。 internal/context/compact支持manual、auto与reactive三种 mode。- 用户通过
/compact对当前会话执行一次上下文压缩。 - compact 前会先写入完整 transcript,随后生成并校验新的 durable
TaskState与 display summary,再回写会话消息。
compact 相关配置位于:
context:
compact:
manual_strategy: keep_recent
manual_keep_recent_messages: 10
max_summary_chars: 1200
micro_compact_disabled: false
auto_compact:
enabled: false
input_token_threshold: 100000manual_strategy控制手动 compact 的策略,支持keep_recent和full_replace。manual_keep_recent_messages在keep_recent模式下保留最近消息数量,并按 tool call 与 tool result 的原子块整体保留。max_summary_chars控制 compact summary 的最大字符数。micro_compact_disabled控制是否关闭默认启用的读时 micro compact;设为true时会回退为仅 trim、不清理旧 tool result。auto_compact.enabled控制是否启用基于 token 阈值的自动压缩;默认关闭。auto_compact.input_token_threshold当会话累计输入 token 数达到此阈值时触发自动压缩;默认 100000。
当 auto_compact.enabled 为 true 时,runtime 在每次调用 context.Builder.Build() 时将当前 token 累计值传入 Metadata,context 模块通过比较累计值与阈值在 BuildResult.AutoCompactSuggested 中返回压缩建议。runtime 读取建议后调用现有 compact 管线执行压缩;token 计数的重置与持久化语义统一见 Session 持久化设计。
设计原则:
- context 拥有压缩决策权,runtime 只做编排执行。
- 每次
Run()调用最多触发一次自动压缩,避免无限循环。 - 压缩成功后 token 计数器重置为零,下一轮不会立即重复触发。
新增工具时,micro compact 策略不再由 context 层静态白名单维护,而是由 internal/tools 中的工具实现声明。
默认情况下,已注册工具都会参与 micro compact;只有显式声明保留历史结果的工具才会跳过旧结果清理。
但 micro compact 只有在当前会话已经建立非空 TaskState 时才会生效;没有 durable task state 时,context 仅做 trim,不清理旧 tool result。
- TUI 识别
/compact并调用runtime.Compact(...)。 - runtime 发出
compact_start事件。 - compact runner 将原始消息写入 transcript(JSONL)。
- compact runner 根据策略构造归档消息与保留消息,并过滤旧的
[compact_summary]展示摘要,避免“摘要的摘要”。 - runtime 选择用于生成 summary 的 provider 和 model:
优先复用会话记录的
provider/model,缺失时回退到当前配置。 - summary generator 调用模型生成完整
task_state与 display summary。 - runner 校验 display summary 结构与长度,必要时截断,并写入
task_state.last_updated_at。 - compact 成功时回写
session.TaskState与会话消息并发出compact_done;失败时发出compact_error。
其中 reactive mode 在 context 包内与 manual 复用同一条压缩管线:
- 先写 transcript。
- 默认按
keep_recent裁剪可归档历史。 - 生成并校验 display summary,同时更新 durable
TaskState。 - 返回压缩后的消息、
TaskState与 transcript 元信息。
当 provider 返回“上下文过长”错误时,runtime 会:
- 识别 provider 归一化后的 typed error,必要时回退到错误文本匹配。
- 触发一次
compact.Run(mode=reactive)。 - 继续复用
compact_start、compact_done、compact_error事件,并通过trigger_mode=reactive区分来源。 - 每次
Run()最多只执行一次 reactive 重试,避免无限循环。
compact generator 必须只返回一个 JSON 对象,顶层固定包含:
{
"task_state": {
"goal": "",
"progress": [],
"open_items": [],
"next_step": "",
"blockers": [],
"key_artifacts": [],
"decisions": [],
"user_constraints": []
},
"display_summary": "[compact_summary]\n..."
}task_state表示 compact 之后的完整 durable task state,而不是增量 patch。task_state只允许包含固定字段,不允许混入模型自定义键。display_summary仍然必须使用[compact_summary]协议,供人类阅读和后续轮次参考。
display_summary 必须以如下结构返回:
[compact_summary]
done:
- ...
in_progress:
- ...
decisions:
- ...
code_changes:
- ...
constraints:
- ...
- 必须包含固定起始标记
[compact_summary]。 - 必须包含
done、in_progress、decisions、code_changes、constraints五个 section。 - 每个 section 至少包含一条非空 bullet。
- durable truth 优先进入
TaskState,而不是散落在聊天消息里。 TaskState重点保留目标、已完成进展、未完成事项、下一步、阻塞点、关键工件、决策、用户约束。display_summary只保留继续工作最少需要的人类可读信息。- 默认忽略工具详细输出、重复背景、已解决错误的排查细节。
compact 相关 runtime 事件包括:
compact_startcompact_donecompact_error
compact_done payload 包含:
appliedbefore_charsafter_charssaved_ratiotrigger_modetranscript_idtranscript_path