Add shared /history parsing, read-only session access, message filtering, and bounded replies. Default to three messages, cap at five, and exclude saved history commands. Include channel integration tests, translations, command help, and the Issue #62 implementation plan.
14 KiB
Issue #62:九渠道会话历史预览方案
日期:2026-08-28。代码基线:v3.0.8 / bf0e157。状态:已实施。
需求来源:Issue #62。本方案仅描述实现,不代表功能已经上线。
1. 最终命令约定
新增一个共享命令:/history [数量]。
| 输入 | 行为 |
|---|---|
/history |
返回最近最多 3 条历史消息 |
/history 1 |
返回最近最多 1 条 |
/history 4 |
返回最近最多 4 条 |
/history 5 |
返回最近最多 5 条 |
/history 6、/history 100 |
均按 5 条处理,不报超限错误 |
/history 0、负数、小数、非数字、多个参数 |
返回用法,不访问模型 |
这里的默认值是 3 条,不是 3 天,不提供时间范围查询。
“一条历史消息”指一条用户消息,或一条助手最终回复;不是一轮对话,也不是一个工具事件。例如两次完整问答共有 4 条。数量不足时按实际数量返回,不补齐、不生成摘要。
先取最新 N 条,再按从旧到新的顺序展示。奇数条可能从助手回复开始,这是按消息计数的正常结果,不额外补入第 N+1 条。
2. 范围与体验
九渠道统一提供文字命令和文字预览,不新增卡片、按钮、设置项、数据库或历史缓存,不为 QQ、企业微信添加专门的发送逻辑。
本期沿用前一轮建议的私聊范围:微信、飞书、钉钉、企业微信、QQ、Slack、Telegram、Discord、WhatsApp 的私聊均支持;群聊、频道和群内线程只回复“请在与机器人的私聊中使用 /history”。它们不读取历史,也不自动转发到另一个私聊。渠道现有的入站路由行为保持不变。
只查看当前聊天已绑定的 Harness Session,不接受 Session ID 参数。切换成功后只增加一句“发送 /history 查看最近对话”,不自动发送历史。AI Office Connector 不属于本次九个聊天渠道。
预览示意:
会话历史|会话 abc123|最近 3 条
1. 助手
上一次已经完成登录接口,下一步是补充测试。
2. 用户
先补充登录失败场景的测试。
3. 助手
已补充三个失败场景,测试全部通过。
以上为历史记录,不是本次新回复。
这是历史文字摘录,不是让模型重新回答或概括。
3. 历史读取与筛选
3.1 读取流程
- 渠道先执行现有访问策略、去重和命令识别。
- 共享命令解析数量:省略为 3,正整数超过 5 时取 5。
- 确认是私聊、没有图片或文件,并读取当前聊天绑定的 Session ID;未绑定直接提示,不创建会话。
- 通过共享 HarnessClient 调用现有
session.history。本机沿用 v3.0.8 的进程内 API,显式配置远程 Host 时沿用 HTTP,不另建访问链路。 - 筛选可显示消息,选取最新 N 条,按原顺序排版。
- 读取结束后再次检查当前绑定和工作区作用域;读取期间切换了会话、工作区或机器人已失效,则丢弃结果并提示重试。
- 返回现有的
{ handled, message, messages }命令结果,由各桥接器现有发送函数投递到本次请求的原聊天。
发送一旦开始,整份回复始终使用同一份已读取快照和原回复目标,不在分段之间改读新会话。标题或短 ID 用于标明这份历史属于哪个会话。
3.2 什么可以显示
| 内容 | 处理 |
|---|---|
| 原始用户消息 | 只接受能确认是人类输入的消息来源,提取正文文字 |
用户历史中的 /history 命令记录 |
排除被 isHistoryCommand 识别的命令(含参数和首尾空白),不显示、不计数;普通正文或助手回复中提到 /history 的内容保留,不推断关联 Turn |
| 助手最终回复 | 每个成功结束的 Turn 只取最后一条定稿助手消息中的文字 |
| 当前运行中的用户输入 | 已进入历史时可以显示;未提交的排队输入不读取 |
| 正在生成的助手回复 | 不显示 token 分片或过程消息,可附“当前任务仍在进行中” |
| 图片、文件等非文字内容 | 不下载、不重发;有可靠结构化信息时显示类型占位说明 |
| 工具调用、工具结果、推理内容、系统指令、注入上下文、审批内容 | 不展示 |
| 压缩产生的替换副本 | 不当成新对话,不重复计数;保留原始人类对话的含义 |
| 无可显示文字的助手最终消息 | 显示“本条没有可预览的文字”,不拿更早的过程消息冒充最终回复 |
实现时不能简单地过滤 user/message、assistant/message 后取最后 N 个事件:
user/message也可能是内部注入内容,必须检查data.source.kind === 'user'。- 当前协议中,原始对话使用
surfaceOp: 'append';replace是模型侧替换内容,不重复展示。缺少关键字段时不猜测为普通对话。 - 助手消息需要结合
turn/end确认最终状态;忽略assistant/chunk、中断片段以及中间工具步骤的助手消息。 - 用户正文在
event.data.content,助手正文在event.data.message.content,两者不能用同一个未经区分的字段路径读取。
这些规则只限制显示哪些事件、哪些内容块,不承诺自动识别并清除用户正文里原本就包含的密码、路径等敏感文字。权限仍依赖机器人已有的可信访问范围,不新增一套管理员或 Session 所有者体系。
3.3 有限读取即可,不做历史浏览器
首次读取 maxMessages: 50;若筛选后不足 N 条且响应 hasMore 为真,使用 beforeSeq 向前补读,最多总共 3 次。整次读取设置 10 秒截止时间,不订阅实时事件。
maxMessages 是 Harness 的分页计数,不是本命令的返回条数。每页按 seq 校验、排序和去重,向前游标必须严格推进。固定首次尾页的快照边界,不在补读期间追赶新消息。
达到上限仍不足时,返回已确认的记录并说明不足;没有可用记录则给出对应提示。字段不合法、游标不推进或记录冲突时返回安全错误,不把原始响应作为文字发出去。
4. 防刷屏统一规则
防刷屏只在共享命令层处理,不按渠道另写策略。
- 最多选择 5 条历史消息。
- 每条正文最多展示 500 个字符,超出注明“已截断”;切分不得拆开 Unicode 代理对。
- 合并成一份带角色标签的文字回复,总长度控制在 3,000 个字符以内,标题、标签和截断提示都计入预算。
- 复用现有
splitWorkspaceCommandMessage()按 1,800 字符分段;最多发送 3 段,超出先缩短正文并标注截断。 - 逻辑历史消息数与 IM 分段数分开计算:
/history 5最多包含 5 条历史记录,不是固定发送 5 个气泡。 - 命令结果一次生成完再发送,不流式推送历史,不引导用户发送“继续”,不自动翻页。
上述 500 / 3,000 / 3 段是建议的统一显示预算,可在共享常量中调整;默认 3 条、上限 5 条则按本次需求固定。
5. 九渠道接入
| 渠道 | 接入位置 | 回复方式 |
|---|---|---|
| 微信 | src/channels/weixin/weixin-bridge.mjs |
现有命令回复流程 |
| 飞书 | src/channels/feishu/bridge.mjs |
现有命令文字回复流程,不新增卡片 |
| 钉钉 | src/channels/dingtalk/dingtalk-bridge.mjs |
现有命令回复流程 |
| 企业微信 | src/channels/wecom/wecom-bridge.mjs |
现有命令回复流程,不单独处理 |
src/channels/qq/qq-bridge.mjs |
现有命令回复流程,不单独处理 | |
| Slack | src/channels/shared/text-harness-bridge.mjs |
继承共享桥接器,复用现有发送函数 |
| Telegram | src/channels/shared/text-harness-bridge.mjs |
同上 |
| Discord | src/channels/shared/text-harness-bridge.mjs |
同上 |
src/channels/shared/text-harness-bridge.mjs |
同上 |
因此实际只需要接入六处桥接入口,不复制九份查询或格式化代码。各渠道现有回复目标、鉴权、入站去重、发送失败处理和机器人回声过滤都保留。
不修改 QQ Markdown 回复机制、企业微信即时回复机制、Discord Thread 路由、Telegram 富消息机制或任何平台 SDK。这里承诺的是复用现有行为,不额外承诺本次解决底层发送链路已有的重试或重复投递问题。
6. 状态和异常
| 情况 | 结果 |
|---|---|
| 没有绑定 Session | 提示先开始或绑定会话,不自动创建 |
| Session 为空 | “当前会话暂无可预览的历史消息” |
| 请求 N 条但只有更少 | 返回实际数量 |
| 最近记录包含失败或中断的 Turn | 用户输入仍可显示,不把未完成的助手片段当成最终回复 |
| 任务正在运行 | 可查历史,不停止、不等待任务结束 |
| 正在等待提问或审批 | 命令不被当作交互答案,不提交或取消原交互 |
| 批量输入正在收集 | 沿用现有规则,提示先 /send 或 /cancel;不收录、不查询 |
/history 带图片或文件 |
提示仅支持文字命令,不转给模型 |
| 数量格式错误 | 返回用法;大于 5 的合法正整数不是错误 |
| Session 不存在 | 提示重新绑定,不静默新建或切换 |
| 读取期间发生切换 | 丢弃旧结果,提示重新执行 |
| Harness 不支持、超时或返回异常 | 返回简短安全提示,不泄露原始异常和历史数据 |
| 平台发送失败 | 走该渠道现有错误路径,不新增历史专用重试 |
/history 应接到现有快速命令分支:在批量输入规则之后、待回答问题和审批识别之前处理。无效参数同样在本地消费,不能落入普通消息流程。新命令的识别不能因为携带附件而绕过校验、转发给模型。
7. 最小改动清单
- 新增
src/channels/shared/history-command.mjs:命令解析、数量上限、历史筛选、输出预算、提示文案;返回现有命令结果结构。 - 修改
src/channels/shared/harness-client.mjs:增加readSessionHistory(sessionId, options),复用已有 RPC 和错误类型。 - 修改
src/channels/shared/bot-workspace-store.mjs:在workspaceSession()句柄增加历史读取方法,复用工作区代际校验;命令另检查当前聊天绑定是否仍相同。 - 六处桥接器接入共享命令,并传递私聊类型及文字/附件信息。
- 更新九渠道帮助文案、共享
/session成功提示及飞书自己的绑定成功提示。只增加命令提示,不重放历史或新增按钮。 - 更新现有中英文文案、
README.md、README.en.md和CHANGELOG.md。 - 增加共享测试及九渠道接入测试。不新增持久化状态、依赖包或配置迁移。
读取链路不得调用 session.create、session.prompt、session.cancel、executeCommand 或会话恢复/接管方法;session.history 本身能够读取未激活会话,不需要先创建 Agent。
8. 验收与实施顺序
先完成共享命令和历史读取测试,再一次性接入六处入口覆盖九渠道,最后补帮助文案并执行现有 npm run check。
共享验收:
- 默认 3 条;参数 1、3、5 正确;6、100 和很大的正整数均按 5 条;0、负数、小数及多个参数返回用法。
- 最新 N 条、旧到新显示、数量不足及空会话正确;不能把“一轮”误当“一条”。
- 用户历史中的
/history命令记录在计数和截取前排除,数量不足时沿用有限分页补取;普通正文和助手回复中的提及不删。 - 多工具步骤、内部注入、推理内容、压缩替换、运行中回复、失败/中断及重复事件的筛选正确。
- 单条超长、中文、emoji、代码文字均遵守预算,最多 5 条记录和 3 段回复。
- 补读有上限且游标推进;API 不支持、超时、坏数据和读取期间切换均安全退出。
- 进程内 API 与显式 HTTP 模式都覆盖;查询全程不触发模型、会话创建、恢复或交互响应。
九渠道都执行同一组接入验收,不以“继承共享类”代替覆盖:
- 私聊发送
/history和/history 10,分别得到最多 3 条和 5 条,且回到原聊天。 - 未授权来源按原策略拒绝;已接收的群聊命令不读历史,提示去私聊。
- 正在运行、待回答/审批、批量输入三种状态都符合上表。
- 重复平台事件不重复处理;发送失败按原渠道处理;历史回声不触发新模型请求。
/help、绑定成功提示和英文提示包含正确用法。
发布前使用可用的真实机器人做九渠道私聊冒烟。未完成的实机项明确记录,不能将 mock 测试通过写成九渠道已经实测通过。发布回退可撤回命令入口和帮助提示,无需回滚会话数据。
9. 核对依据
- 本仓库
workspace-command.mjs的命令结果与 1,800 字符分段器,以及六处桥接器现有的result.messages发送循环。 - 本仓库
harness-client.mjs、bot-workspace-store.mjs和 v3.0.8 的harness-connection.mjs。 - Harness 历史 API 契约:
session.history、反向分页及只读行为。 - Harness 事件定义:用户来源、Turn 状态与定稿助手消息。
- Harness 原始对话与替换内容的区别:人类对话预览不能照搬压缩后的模型上下文。
上游仍在演进,实施时以实际支持的 Host 协议和测试样本为准,不额外假设新的 RPC 或字段。
10. 验收记录
2026-08-28:
- 用户确认:九个渠道实测均 OK,并要求停止进一步客户端测试。此项为用户确认,不代表我们独立完成了全部原生客户端实测。
- 自动验证:
npm run check的构建、1,554 条全量测试及包产物校验通过;随后新增的 Slack 前导空格联合回归通过,history-bridge测试文件 112/112 通过。 - 追加优化:在计数前排除
/history命令记录,普通正文中的命令引用不受影响;history-command34/34、重新构建及包产物校验通过。重启加载后,仅向飞书机器人“今天是牢梁”发送一次/history,返回 3 条正常历史消息,不包含查询命令;本轮未复测其他渠道。