并行上下文管理

将单个对话拆分为 N 个并行上下文,每个上下文独立维护自己的消息历史。非活跃上下文从内存卸载(切换时懒加载),持久化到磁盘。


为什么需要多上下文?

单个对话线性增长——每次工具调用、每次响应都增加 token。上下文会变得嘈杂。多上下文提供:


上下文管理

创建上下文

/context new 前端设计
/context new 后端API
/context new bug调查

每个上下文拥有独立名称和消息历史。达到上限(max_contexts,默认 5)时自动淘汰最不活跃的上下文。

切换上下文

/context                    → 打开上下文切换弹框
/context 2                  → 切换到上下文 #2

TUI 模式下 /context 无参数打开可视化弹框面板。使用 ↑↓ 导航,Enter 切换,Del 淘汰。按 Esc 关闭。

重命名和删除

/context rename "UI重构"     → 重命名当前上下文
/context del 3              → 淘汰上下文 #3

LRU 淘汰

新建上下文且槽位已满时,niuma_code 按三级优先级选择淘汰候选:

  1. 空上下文 — 消息数为 0 的空壳最先淘汰(价值最低)
  2. 未命名上下文 — 仅有自动生成摘要、未被用户显式命名的上下文次之
  3. 最久未使用 — 剩余候选中 last_active_ts 最小者被淘汰

当前激活上下文受保护,永远不会被淘汰。

状态 说明
激活 在内存中,完整历史可用
非活跃 从内存卸载,元数据在清单中,消息在磁盘

淘汰是透明的——被淘汰上下文的消息文件({sid}.json)保留在磁盘上,切换回去时可按需恢复。


上下文摘要

切换上下文时,niuma_code 自动从最后一条用户消息(前 20 字)截取作为上下文的显示标签。这是纯内存截断——无 LLM 调用,零延迟。

从 "后端API" 切换到 "前端设计"
  → 摘要已捕获:"修复认证中间件..."
  → 已切换到 前端设计

如果通过 /context new <名称>/context rename <名称> 显式命名了上下文,名称会被固定(pinned),不会被自动摘要覆盖。


/messages 命令

/messages 打开可视化弹框,管理当前上下文的对话历史:

操作 快捷键
导航 ↑↓
多选 Space
删除选中 Deleted
移位 Alt+↑ / Alt+↓
合并选中 m(LLM 分别摘要 user/assistant 两侧)
清空 recall 注入 c(二次确认)
保存修改 Ctrl+S
关闭 Esc

消息按「对话单元」组织(每个单元从一条 user 消息开始,包含其后所有 assistant 响应直到下一条 user 消息)。编辑操作为预览模式,按 Ctrl+S 后才持久化。


配置

settings.jsonllm 节中配置:

{
    "llm": {
        "max_contexts": 5,
        "resume_latest_context": false
    }
}
设置 默认值 说明
max_contexts 5 活动上下文最大数量,超出后 LRU 淘汰
resume_latest_context false true:重启恢复上次 active 上下文;false:每次进入空上下文(旧对话保留,可 /context 切回)

持久化

上下文数据存储在 .session/ 目录:

启动时仅加载 active 上下文的消息到内存,其他上下文在切换时懒加载。


工作流示例

/context new API重构
# 进行 API 重构...

/context new 修复bug
# 调查并修复 bug...

/context 1
# 回到 API 重构——上下文完整保留

/context new 编写测试
# 写测试——独立上下文保持整洁

每个上下文维护: