# 历史对话

`pbot_history` 共同查询当前工作区的 Pi 与 dsh 问答归档。Pi 的人工入口为 `/pbot history [关键词]`；dsh 使用 `/pbot` 的历史页，或 `/pbot history {"action":"search",…}`。无需给会话命名。原生会话由所属宿主管理，不跨宿主接管或恢复。

## 查询

| 操作 | 参数与行为 |
| --- | --- |
| search | query 是不区分大小写的连续文本，搜索问答原文和已生成摘要；省略 query 列会话。host 可选 pi/dsh，sessionId、from、to 限定会话与相交时间范围，日期按 ISO 解析；offset/limit 分页，默认 20、最多 50 条 |
| read | id 是搜索或导航返回的节点 ID；host 指定来源。offset/limit 读取正文，默认 12000、最多 24000 个 UTF-16 单元；childrenOffset 分页子节点，每页 20 个 |

返回的 nextOffset、nextChildrenOffset 非空时可继续读取。parents/children 提供来源、节点 ID 与预览；共享前缀可能有多个父节点。source 给出 host、原始 sessionId 和消息 entryIds，摘要的消息 ID 是覆盖范围的首尾。来源不保存文件路径；原生会话不可用时，已保存的问答仍可直接读取。ready=false 表示摘要尚未生成；completed=false 表示内容包含未完成的问答。

查询只刷新当前宿主的原生索引，并读取另一来源的现成归档；不调用模型，不恢复会话或重放任务。跨来源 ID 发生歧义时必须指定 host。摘要命中是检索线索，重要结论仍要展开到问答原文核对。全文搜索依赖词语重合，忘记原词时可以换词查询。不同层级的命中分别返回。

## 原生收录

Pi 通过 SDK 读取当前会话目录、原生默认目录、当前会话，以及本工作区受管专家的原生引用，按 sessionId 关联已有归档。不在发现范围的会话可通过 Pi 打开并加载 pbot 重新关联。Pi 分配文件名后、首条消息落盘前，文件可以不存在；扫描静默跳过这种空会话。不会扫描旧版 pbot 私有会话布局。

dsh 通过公开 SessionQuery 冷读本工作区根会话与按父关系关联的专家；专家 cwd 不同仍按父归属收录，同目录但属于其他工作区父会话的专家不混入。普通 fork 可以收录。读取不创建 Agent、不恢复会话、不修改原生记录，也不从私有请求日志推断对话。

用户输入到有效最终答复组成问答，回答前的人工补充输入保留在同一问答。dsh 的协调者委派输入也保留来源；通知和团队背景不会被当作新的用户问题。工具调用、工具结果和推理不进入问答。中断、截断、缺少正常结束或尚未回答的记录保留为未完成。dsh 必须有持久化的正常 stop 才能确认完成；工具文本和 idle 状态不代替最终回答。

完整工具、错误和审批记录留在原生会话。dsh 管理页的专家记录支持冷读、事件分页、正文与原始 JSON；history 不替代它。Pi 的原生 JSONL 同样只读解析，不改写或迁移。

## 摘要与取消

每条分支独立分组，每四个连续节点形成一个摘要，再逐层合并。共同前缀复用节点，不跨分支汇总；会话根只做目录，不生成全局摘要。不足四个的尾部节点仍可查询。连续区间与渐进合并参考 [pi-optchat](https://github.com/jonaslsaa/pi-optchat)，实现与提示词由 pbot 维护。

正常主交互结束后，在空闲阶段使用当前宿主选择的模型与原生认证，串行补齐本来源已发现的摘要。Pi 使用自己的交互结束事件；dsh 在同一工作区的所有已绑定父 Agent 空闲、无待输入时安排原生 LLM 调用，不创建额外 Agent 或主聊天消息。查询和页面重连只收录原文，不触发摘要。

两种摘要调用都只接收 `resources/prompts/history-summary.md` 和本次待整理的问答或下层摘要，带来源时段及未完成标记。不加载主会话或专家角色、工作区资料、技能、环境与团队上下文，也不提供工具。提示要求把历史当作资料，保留决定与建议、尝试与完成的区别；摘要不会执行历史中的任务。

新人工输入、下一模型步骤、所属资源关闭或 Pi 会话切换会取消当前整理。失败保留待处理内容与警告，下次正常交互结束再试。超长输入分段概括再合并，完整原文保留；摘要失败不妨碍原文查询。来源扫描错误与摘要错误分别保留，刷新成功不会掩盖尚未修复的摘要失败。

摘要产生额外模型调用，不纳入主聊天的使用量承诺。原生上下文、压缩、模型路由和认证继续由宿主管理。真实摘要质量和实际请求取消仍需获准模型环境验收。

## 存储与并发

| 来源 | 工作区归档 | 写入者 |
| --- | --- | --- |
| Pi | `.pi/pbot/history/<id>.json` | Pi 收录与整理自己的原生会话 |
| dsh | `.dsh/pbot/history/<id>.json` | dsh 收录与整理自己的原生会话 |

归档保存问答文本、来源 ID、节点关系与摘要。Pi 既有节点 ID 保持不变；新 dsh 根节点带 `dsh-` 前缀。目录决定工作区与来源，不要求复制后的绝对路径相同。复制时包含两种归档即可查询现成内容；原生恢复仍需各宿主自己的会话数据，工具日志和附件二进制不在归档内。

Pi 保留既有旧索引处理：将当前 Pi agent dir 中旧 `pbot/history/` 下属于本工作区且尚未存在的记录复制到工作区，保留旧副本，不覆盖新归档；移除已有 Pi 归档中的旧 file 字段时保留正文、摘要和节点 ID。失败的旧目录读取可在后续刷新重试。dsh 不导入这些旧 Pi 记录，也不清理或回写 Pi 归档。

每个来源有独立的短写锁。原生扫描和模型调用在锁外进行，提交时重读最新归档；过时扫描不能覆盖后来保存的原文，过时摘要不能覆盖变更后的子节点或已提交摘要。一个来源损坏时，另一来源仍可查询并附带警告。不保证多个进程同时整理时只调用一次模型。

服务位于 `services/history`，负责分组、查询、摘要队列与提交规则；`integrations/pi/history` 和 `integrations/dsh/history` 负责各自原生投影，`storage/history-files` 负责校验、短锁与原子文件发布。命令和工具调用同一服务。首版仍使用全文扫描，不增加数据库或向量索引。

这些归档是用户历史资料。原生数据还在时可以重新提取；原生数据已不可用时，删除归档会失去这份历史。复制前停止原工作区的活动写入，不支持多机同时写同步目录。真实模型、长历史性能和平台验收边界见[验证](validation.md)。
