会话树导航
/tree 命令提供基于树的会话历史导航。
概述
会话以树形结构存储,每个条目都有 id 和 parentId。"叶子"指针跟踪当前位置。/tree 允许你导航到任意节点,并可选择对离开的分支生成摘要。
与 /fork 的区别
树 UI
控制
显示
- 高度:终端高度的一半
- 当前叶子标记为
← active - 标签内联显示:
[label-name] - 默认过滤器隐藏
label和custom条目(Ctrl+O 模式下显示) - 子节点按时间戳排序(最早的优先)
选择行为
用户消息或自定义消息
- 叶子设置为所选节点的父节点(如果是根节点则为
null) - 消息文本放入编辑器供重新提交
- 用户编辑并提交,创建新分支
非用户消息(助手、压缩等)
- 叶子设置为所选节点
- 编辑器保持空白
- 用户从该点继续
选择根用户消息
如果用户选择了最初的第一条消息(没有父节点):
- 叶子重置为
null(空对话) - 消息文本放入编辑器
- 用户实际上从头开始
分支摘要
切换分支时,用户会看到三个选项:
- 不生成摘要 - 立即切换,不进行摘要
- 摘要 - 使用默认提示生成摘要
- 自定义提示摘要 - 打开编辑器输入额外的聚焦指令,追加到默认摘要提示中
摘要范围
从旧叶子回溯到与目标的公共祖先的路径:
被放弃的路径:D → E → F(生成摘要)
摘要在以下情况停止:
- 公共祖先(始终停止)
- 压缩节点(如果先遇到)
摘要存储
存储为 BranchSummaryEntry:
实现
AgentSession.navigateTree()
选项说明:
summarize:是否为被放弃的分支生成摘要customInstructions:摘要生成器的自定义指令replaceInstructions:如果为 true,customInstructions替换默认提示而非追加label:附加到分支摘要条目(或不摘要时附加到目标条目)的标签
流程:
- 验证目标,检查无操作(target === 当前叶子)
- 查找旧叶子和目标之间的公共祖先
- 收集要摘要的条目(如果请求)
- 触发
session_before_tree事件(钩子可取消或提供摘要) - 如果需要,运行默认摘要生成器
- 通过
branch()或branchWithSummary()切换叶子 - 更新智能体:
agent.replaceMessages(sessionManager.buildSessionContext().messages) - 触发
session_tree事件 - 通过会话事件通知自定义工具
- 返回结果,如果选择了用户消息则包含
editorText
SessionManager
getLeafUuid(): string | null- 当前叶子(空时为 null)resetLeaf(): void- 将叶子设为 null(用于根用户消息导航)getTree(): SessionTreeNode[]- 完整树,子节点按时间戳排序branch(id)- 更改叶子指针branchWithSummary(id, summary)- 更改叶子并创建摘要条目
InteractiveMode
/tree 命令显示 TreeSelectorComponent,然后:
- 提示是否摘要
- 调用
session.navigateTree() - 清除并重新渲染聊天
- 如果适用,设置编辑器文本
扩展钩子
session_before_tree
扩展可以通过从 session_before_tree 处理程序返回来覆盖 customInstructions、replaceInstructions 和 label。
session_tree
示例:自定义摘要生成器
错误处理
- 摘要生成失败:取消导航,显示错误
- 用户中止(Escape):取消导航
- 钩子返回
cancel: true:静默取消导航