37 KiB
WhatsApp 群聊记录与按日总结方案
状态:方案草案,尚未实施。
日期:2026-08-28。
硬约束:只修改 dsh-im;不修改、打补丁或重新构建 Harness 核心;优先复用 Harness 的会话存储,不新增聊天内容数据库。
1. 方案结论
机器人账号加入指定 WhatsApp 群后,dsh-im 持续记录实际收到的群消息。记录过程不调用模型;授权成员发送 @机器人 总结今天 时,插件从已保存的记录中取出当天内容,生成总结并发回原群。已经启用的普通问答规则独立生效,不因记录功能被改写。
建议采用下面的存储分工:
| 对象 | 保存内容 | 是否运行 AI |
|---|---|---|
| 群记录会话 | 群成员的原始消息、收到的修订事件、记录状态 | 否 |
| 摘要会话 | 一次总结所选的消息、摘要提示词和 AI 回复 | 是,仅收到明确指令后 |
| 现有普通对话会话 | 原有机器人问答 | 保持现状 |
三者都可以使用 Harness 已有的会话设施,但不能混用其写入方式。群记录会话由 dsh-im 独占,通过宿主公开的 sessionPersistence 服务读写;摘要会话通过现有 session.create、session.prompt 等接口运行。普通对话的绑定、访问模式和命令保持原有行为。
“保存到会话记录”在本方案中指保存到 Harness 的会话持久化后端,不意味着每条群消息自动变成现有聊天窗口中的用户气泡。 第一版由 dsh-im 提供群记录查看入口。要求原有聊天窗口原样显示全部群消息,属于另一个展示需求,不能在不改核心的前提下直接承诺。
该路径有源码和已有后端测试支持,但尚未完成目标安装版本的插件集成验证。必须先通过第 15 节的兼容性验证,再进入功能开发;不能把“能调用一个方法”当作整条链路已经可用。
2. 目标、范围与明确不做的事情
2.1 第一版目标
- 只记录用户在设置页明确启用的群,默认关闭。
- 未 @ 机器人的文字消息也能入库;记录操作本身不触发 AI、已读提示、输入状态或群内回复。
- 支持按群时区总结今天、昨天、指定日期及日期内的明确时间段。
- 记录保存发言人、原始消息时间、收到时间和消息 ID,能够去重、排序和说明来源。
- 重启后能够读取已持久化记录;中断、缺失、未解析媒体等情况在总结中说明。
- 全部实现位于 dsh-im,使用 Harness 的公开插件服务和现有 RPC。
2.2 第一版不承诺
- 不修改 Harness 源码、事件白名单、RPC 协议、内置聊天 UI 或存储表结构。
- 不直接编辑 Harness 的 JSONL、压缩日志或 SQLite 文件。
- 不保证获取入群前、启用前、设备离线期间的完整历史。
- 不启用全量历史同步,不把手机上可见的全部旧聊天等同于程序已保存的数据。
- 不转写语音,不识别图片,不读取文件正文,不下载媒体。
- 不记录阅后即焚内容;第一版不支持启用了消息自动消失的群。
- 不自动每天发送总结,不增加定时任务。
- 不把普通群聊内容作为需要执行的命令、审批或工具指令。
- 不承诺自动物理删除过期记录,原因见第 12 节。
- 不在这一版本扩展其他八个 IM 渠道。
3. 当前代码与核验发现
3.1 dsh-im 已有能力
| 位置 | 已有行为 | 对本需求的影响 |
|---|---|---|
src/channels/whatsapp/whatsapp-web-session.mjs |
监听 messages.upsert;关闭历史同步;对旧 append 消息设置时间过滤 |
能收到实时消息,但不能直接宣称完整历史已接入 |
src/channels/whatsapp/whatsapp-runtime.mjs |
区分群聊、私聊、自己发出的消息、提及和回复 | 可复用账号接入和归一化基础;需要补原始时间、来源及记录策略 |
src/channels/shared/text-harness-bridge.mjs |
未被寻址的群消息不会进入 AI 处理 | 记录必须在回复过滤之前拥有独立的授权和写入流程 |
src/channels/shared/harness-client.mjs |
创建会话、读取历史、提交提示词 | 可复用摘要执行链路;没有现成的静默群记录方法 |
plugin-src/host/harness-connection.mjs |
默认同 Host 进程内接入,显式远程地址使用 HTTP | 第一版限定同 Host 的插件模式 |
src/channels/shared/conversation-state-store.mjs |
保存会话绑定和最近消息 ID,不保存群聊正文 | 不能把当前 state.json 当作群聊天记录 |
当前 addressed 还包含 fromMe,不能简单把它等同于“发生了真正的 @”。新增逻辑必须分别保留实际提及、回复、本人发送和机器人出站回声的信息。
3.2 对前期讨论的一项修正
前期讨论提出过直接使用 session.append() 写自定义群消息事件。进一步检查发现,这条路径不能直接作为可上线方案:
- 当前 Harness 的已知事件集合是构建时生成的;仓库外插件新增的事件类型不在其中。
- 未携带顶层
ignorable: true的未知事件,会在持久化读取时被拒绝。写入成功并不证明重启后能恢复。 - 所检查版本的
Session.append()不提供设置该顶层标记的参数,返回的事件又是冻结对象。 - 把聊天正文伪装成标题、待办或其他已有事件,或者修改内部白名单,均不采用。
因此,主方案调整为:使用公开的 sessionPersistence.create / append / inspect / load / readFrom 管理插件独占的群记录会话,并为纯信息记录设置 ignorable: true。不向正在运行的普通 Agent 会话旁路写入事件。
这里的标记表示:Harness 不认识这些事件时,可以不把它们解释为 Agent 执行状态。原始事件仍会被保存和读回,由 dsh-im 校验并解释;不能用这个标记掩盖会改变正常模型历史或执行状态的事件。
3.3 其他已确认限制
| 限制 | 设计处理 |
|---|---|
| 普通 HTTP RPC 没有静默追加接口 | 远程模式不开放本功能,不增加自定义 Harness RPC |
| 仅包含日志事件、没有执行轮次的会话可能被原生会话列表视为未开始 | dsh-im 管理自己的记录目录和预览入口,不伪造执行轮次使其显示 |
| 现有全文检索不为未知插件事件生成正文索引 | 按插件目录和时间分段读取原始事件,不依赖现有全文搜索 |
JSONL 的 readFrom 仍可能解析整个日志文件 |
记录按日期和大小分段,避免无限增长的单个会话 |
| 统一持久化服务没有删除接口 | 不提供会让人误以为已物理删除的保留期限或清空按钮 |
4. 总体结构
flowchart TD
A[WhatsApp 群消息] --> B[来源识别与归一化]
B --> C{是否有该群的记录授权}
C -->|有| D[串行去重与记录队列]
D --> E[Harness SessionPersistence]
E --> F[插件独占的群记录会话]
B --> G{是否为本功能接管的总结指令}
G -->|是| L{群与请求者是否获准}
L -->|是| H[固定群和日期范围并读取快照]
L -->|否| M[拒绝总结且不转入普通问答]
F --> H
H --> I[受限的摘要会话]
I --> J[生成总结并回复原群]
G -->|否| K[继续原有普通对话策略]
记录和总结分别授权。未通过记录授权的消息不落入记录队列;被接管但未通过总结授权的指令不读取历史、不调用模型,也不转入普通问答。功能关闭时的原有行为保持不变,普通对话策略不能因为启用了记录而被整体放开。
4.1 会话路由与归属
记录归属由 channel + botId + groupId + workspaceScope + recordingEpoch 确定,不使用群名或昵称作为身份。
- 每个群独立记录,不跨机器人或跨群合并数据。
- 归档会话 ID 使用插件生成的随机标识,不把电话号码或群 JID 放进文件名。
- 一组归档会话只属于一个记录归属,不接受用户从聊天正文指定任意 Session ID。
- 原有
/new和/session只影响普通对话,不清除、改绑或接管群记录。 - 摘要会话单独创建,不复用可能已经绑定其他群或私聊的普通会话。
- 工作区切换时暂停记录,要求用户确认新的作用域后开始新记录阶段;旧记录不自动复制到新作用域。
5. 设置、权限与用户体验
5.1 设置入口
在 WhatsApp 机器人卡片下新增“群记录与总结”区域,保存以下配置:
| 设置 | 第一版规则 |
|---|---|
| 启用群记录 | 默认关闭,老配置缺少此项也按关闭处理 |
| 允许记录的群 | 必须明确选择;空列表不记录任何群 |
| 群时区 | 启用时明确确认 IANA 时区,例如 Asia/Taipei,保存后不跟随机器时区漂移 |
| 可发起总结的成员 | 默认仅绑定账号本人;其他成员需要在此功能的白名单中明确添加 |
| 摘要 Agent Preset | 选择经验证的受限组合;不能直接假定普通编程 Agent 适合处理不可信群记录 |
| 运行与容量限制 | 使用插件配置字段;达到限制时暂停或拒绝,不静默丢弃后宣称完整 |
选择群时,可以由当前 WhatsApp 连接查询账号已加入的群,只返回群名、脱敏标识和插件内部选择标识,不返回成员名单、聊天内容或关联设备凭据。也可提供管理员手工输入群标识的高级入口,但必须验证该账号确实已加入。
启用前明确说明:会复制群消息到宿主会话存储;生成总结时所选内容会交给配置的模型;关闭功能不删除已保存记录。需由使用者确认有权记录并已告知群成员。不能仅因“账号已经在群里”就默认允许归档。
5.2 与现有访问模式的关系
“普通对话访问”和“群记录与总结”是两个显式授权项。界面文案必须体现这一点,不能继续让用户把“仅自己模式”理解为整个插件完全不会处理群消息。
| 情形 | 记录 | 总结 | 普通问答和命令 |
|---|---|---|---|
| 功能关闭或群未授权 | 不记录 | 不处理 | 完全沿用现状 |
| 群已授权,成员未 @ | 保存允许的消息类型 | 不触发 | 沿用现状 |
| 群已授权,白名单成员 @ 并发总结指令 | 保存该请求的记录 | 处理 | 本条不再重复进入普通问答 |
| 群已授权,非白名单成员请求总结 | 可按群记录授权保存普通文字 | 不读取历史、不调用 AI | 不能把被拒绝的总结请求转交普通 Agent |
| 群已授权,成员发其他 @ 消息 | 保存允许的消息类型 | 不处理 | 仍受原有访问模式控制 |
无需把账号切换到“开放响应模式”才能使用指定群的总结功能;新增授权只开放该群的记录和规定的总结指令,不顺带开放所有私聊、系统命令或工作区操作。
成员校验使用平台事件中的发送者身份。电话号码与 LID 只使用 Baileys 已确认的对应关系;映射缺失时拒绝,不能用昵称、消息中的号码或字符串后缀猜测身份。
5.3 查看入口
每个启用的群展示记录状态、开始时间、最近成功保存时间、今日文字条数、已知中断和错误。点击“查看群记录”后,才调用独立的授权 RPC 分页读取正文;普通机器人状态轮询不返回聊天内容。
预览展示日期、发言人、内容及修订状态。摘要运行时,管理员可以在此取消本次摘要;不改写原有 /stop 对普通对话的控制语义。摘要会话可以提供普通会话链接;原始记录是否出现在 Harness 原生列表中不作为本功能的依赖,也不伪造标题或轮次改变该行为。
6. 保存位置与事件格式
6.1 保存在哪里
原始聊天内容交给当前 Host 已挂载的 sessionPersistence 服务:
- 使用 JSONL 后端时,由 Harness 保存为它已有的会话文件,可能是压缩格式。
- 使用 SQLite 后端时,使用 Harness 当前的数据库,不新增 dsh-im 聊天数据库。
- 具体位置由该后端配置决定,不硬编码到代码仓库或某个固定
.dsh子目录。 - 如果后端支持
locate(meta),管理员界面可以展示定位结果;不支持独立文件定位时,说明由当前会话后端管理。
dsh-im 自己只保存群授权、记录阶段、归档会话 ID、摘要任务状态等管理元数据,不再保存第二份原始聊天正文。摘要提示词仍会把所选内容复制进普通摘要会话,这是 Harness 正常保存模型输入的结果,不能承诺整个后端只有一份聊天内容。
6.2 分段策略
按机器人、群、作用域及消息的 UTC 日期建立记录分段。群时区只用于用户查询,不用于修改原始 UTC 时间。一个本地自然日可能需要读取两个 UTC 日期分段。
单段达到配置的事件数或字节上限后继续写下一段;同一天可有多个段。迟到消息写入其原始日期对应的段,不假装在收到时才发出。超出允许的接收范围或时间无法解析时,记录缺失状态,不擅自用当前时间冒充发送时间。
分段只限制单次读取和恢复成本,不等于删除旧记录。日期、字节数、最早与最晚消息时间等可重建索引写入插件管理元数据,正文仍以 Harness 保存的事件为准。
6.3 事件示例
下面是拟新增的插件事件,不是当前已经存在的 Harness 事件类型:
{
"type": "dsh-im/whatsapp-group-message",
"seq": 12,
"time": 1787878801000,
"ignorable": true,
"data": {
"schemaVersion": 1,
"routeId": "opaque-group-route",
"recordingEpoch": "opaque-epoch",
"messageId": "provider-message-id",
"sentAt": 1787878800000,
"receivedAt": 1787878801000,
"senderId": "provider-participant-id",
"senderName": "群成员甲",
"kind": "text",
"text": "周五前完成接口联调。"
}
}
约束如下:
seq是该归档会话内连续序号,由唯一写入队列分配;不使用 WhatsApp 消息 ID 代替。time表示记录事件发生时间;日期查询使用data.sentAt,不能混淆。- 昵称可缺省;原始身份保存在本地记录中,默认不把电话号码作为摘要展示名称。
- 消息事件不带
surfaceOp,不伪装成普通user/message,不产生模型输入。 - 接口边界做 JSON、类型、长度与时间校验;不保存整个 Baileys 原始对象、认证信息、下载密钥或媒体载荷。
- 启用、暂停、断连、修订、出站消息预留和摘要任务状态也使用明确的插件信息事件;所有事件携带插件 schema 版本。
- 会话 Header 使用目标版本公开导出的格式版本与合法字段,不硬编码当前版本号,不添加未经支持的 Header 字段。
7. 持久化写入与恢复
7.1 专用归档会话的写入规则
- 获取当前 Host 的公开
sessionPersistence服务,校验后端能力与配置。 - 生成并保存待创建分段的 ID 和归属,再调用
create(meta);首批事件包含归属声明。 - 通过
append(id, events)提交连续批次,等待持久化成功后再更新已保存计数和游标。 - 插件重启时使用公开的
load或读取接口恢复专用分段、校验归属并重建去重索引;不通过session.prompt激活它。 - 归档会话不创建 Agent,不进入普通会话绑定,也不允许经 dsh-im 的
/session被选作可执行会话。
这是公开持久化服务的消费方式,不是修改数据库文件或绕过宿主的序号校验。Session.append + sessions.flush 仍适用于正常 live Session;本方案不把两条写入路径混在同一个会话里。
归档 Session ID 必须由插件独占。如果发现同 ID 已成为 live Session、归属不符或已有外部写入,立即暂停该分段并报告冲突,不向活跃 Agent 的持久化日志旁路追加。第一版只支持一个 Host 写入同一套记录;不声称支持多进程共享写入。
7.2 去重与异常写入
- 主身份使用机器人、群和平台消息 ID。相同消息重放不重复计数;不同正文的同 ID 不能直接当成新消息。
- 去重信息可从对应日期的归档事件重建,不能只依赖当前有限长度的
seenMessageIds或进程内缓存。 - 同群、同段写入串行;批量写入有时间、条数和内存上限。其他群不被一个群的失败无限阻塞。
- 写入返回不确定结果时,先读取并核对已持久化事件,确认成功前缀,再补剩余部分;不能盲目重试整个批次。
- 创建和管理元数据之间中断时,依据预留 ID、Header 及首条归属事件恢复;无法证明归属的日志不自动接管。
- 队列溢出、磁盘错误和无法恢复的记录失败应暂停或标注缺口;不得显示为正常完整记录。
- 每群总归档容量也设上限;达到上限时暂停新正文采集并告警,不通过删除旧 Harness 记录腾出空间。
程序或机器在批次真正持久化前崩溃,仍可能丢失已收到但尚未保存的消息。该方案不作端到端零丢失承诺,也不依赖 WhatsApp 必然重发。
8. 消息接收、修订与媒体
8.1 接入位置
在 WhatsApp 事件接入层增加仅供已授权群使用的记录回调,先进行记录授权和归一化,再进入记录队列。原有普通问答回调和访问控制继续保留。
记录入口需要看见 notify 和允许处理的 append 事件。现有对旧 append 的过滤不能原样套用到归档,否则重连后的消息会在到达存储前丢失;新增记录分支仅接收启用阶段内、时间范围合法且未保存过的消息。它不触发这些补到消息的旧命令或旧总结请求。
启用记录的生效时刻、连接代际和作用域代际必须明确保存。尚未准备好归档服务时不报告“正在记录”;启动过渡期使用有界队列或明确报告缺口。
8.2 内容处理
| 类型 | 第一版处理 |
|---|---|
| 普通文字、富文本中的文字 | 保存正文与必要元数据 |
| 图片或文件说明文字 | 可保存可见说明,标注未解析媒体 |
| 无说明的图片、语音、视频、文件 | 仅保存类型占位和统计信息,不下载正文 |
| 引用消息 | 保存引用 ID;不重复复制引用正文,不借引用导入其他聊天 |
| 表情反应、状态广播、频道消息 | 不作为群聊正文收集 |
| 阅后即焚、自动消失消息 | 不保存内容;启用自动消失的群不允许开启记录 |
| 机器人自己发送的总结或其他回复 | 根据出站消息身份排除,避免回声和重复总结 |
不能把 fromMe 全部排除,因为用户可能直接使用绑定账号在群中发言。机器人出站 ID 要在发送前预留并持久化,重启后仍能区分自动回复和人的发言。
隐私类型判断必须在拆解消息包装和提取说明文字之前完成,不能只排除图片载荷却保存阅后即焚图片的说明。启用时检查群的自动消失设置,并监听设置与成员变化;机器人被移出群或群开启自动消失后暂停采集与发送。无法可靠确认这些状态时不报告可以安全记录。
8.3 编辑与撤回
记录收到的编辑、撤回事件,使用修订事件关联原消息。查询时按快照内的最后有效版本生成摘要,已撤回的内容不再参与新摘要。离线期间未收到的修订无法凭空恢复,需要说明记录基于实际观察。
Harness 日志是追加式存储,修订事件不会物理擦除旧正文,已经生成的摘要也不会自动撤回。若使用场景要求撤回即彻底删除,本方案不满足这一要求,不能通过隐藏 UI 或加一条删除标记来宣称已删除。
9. 总结指令、日期与快照
9.1 支持的入口
@机器人 总结今天
@机器人 总结昨天
@机器人 总结 2026-08-28
@机器人 /summary 2026-08-28 09:00-12:00
第一版使用明确的命令解析和中文别名,不先调用模型判断任意自然语言是否要总结。其他成员必须通过真实提及或回复已确认的机器人消息触发;绑定账号本人可使用相同的明确命令,不要求能 @ 自己。
未来日期、非法日期、跨日时间段和存在歧义的本地时间返回清晰用法说明。夏令时地区按 IANA 时区计算,不把自然日固定当成 24 小时;重复或不存在的小时不能静默猜测。
9.2 固定查询范围
- 从真实入站事件固定机器人、群、请求者、请求 ID 和收到时间。
- 校验该群记录授权及请求者总结权限。
- 在同群队列设置屏障,等待请求之前已接收的消息得到保存或明确失败结果。
- 固定分段列表及各段已保存序号,形成不会随新消息增长的快照。
- 将群时区的日期范围转换为 UTC,按原始消息时间筛选,再折叠快照内收到的修订。
- 排除本条总结命令、已知机器人回声和未支持的正文类型;按发送时间和稳定次序排列。
今天的上限是本次请求时刻,指定过去日期使用该日结束边界。查询既受时间范围限制,也受快照序号限制;请求后才补到的旧消息留给下一次总结,不让本次结果不断变化。
没有记录、当天中途启用、已知离线区间或保存失败,都由程序生成说明。全日持续显示连接正常也不能证明绝无漏收,结果统一表述为“基于已收录消息”。
10. 摘要执行、费用与输出
10.1 调用方式
每次摘要任务创建新的、属于本群作用域的摘要会话,通过现有 Harness 客户端提交固定说明和该次快照。这样不会无意带入其他群、其他日期或普通问答的上下文。
读取和筛选由 dsh-im 完成,模型不需要获得“查询任意会话”的工具。群消息作为不可信资料提供,明确禁止把其中的要求当作当前任务指令。作者、时间和引用标签由程序装配,外部昵称不能破坏数据边界。
10.2 工具执行限制
优先使用经过验证的无工具摘要 Preset,并通过现有 ctx.tools.guard() 对本功能的摘要会话设置拒绝工具执行的规则。是否属于摘要会话根据插件创建记录及真实执行上下文判定,不根据模型参数或提示词中的标记判定。
保护必须在首次 prompt 前生效,不能只要求模型“不要调用工具”。Shell、文件读写、跨会话查询、浏览、发消息和创建自动任务等均不需要由摘要模型执行。正常机器人会话不受这个规则影响。
插件卸载、热重载或关闭功能时,先取消并等待摘要任务退出,再释放保护。原有摘要会话重新打开或恢复时的权限也必须在兼容性验证中覆盖;若目标 Host 无法可靠保证这一点,就不能以有工具的普通 Agent 作为默认实现。
10.3 长群聊
小记录集一次总结;超出可靠上下文预算时,按时间顺序分块提取,再汇总。每条已纳入的文字消息必须覆盖到某个分块,不能悄悄只取最近若干条。
每个分块使用独立受限会话,最终汇总使用本次摘要会话。归档原文不因分块而改变。若无法获得准确 token 计数,使用保守输入预算并处理模型的上下文超限错误,不伪称精确计数。
分块数、总输入预算、最大输出、运行超时和并发必须设上限。超出上限时提示缩短时间范围或由管理员调整预算;不能把部分结果标成全天完整总结。普通记录不消耗模型 token,总结时按实际输入、分块及输出消耗。
10.4 输出格式
群聊总结|2026-08-28 00:00–18:30|Asia/Taipei
基于已收录的 186 条文字消息;另有 7 条媒体消息未解析。
记录说明:今天 09:15 开始记录,无法覆盖此前讨论。
一、主要讨论
二、已经达成的结论
三、待办事项:事项 / 明确提到的负责人 / 明确提到的截止时间
四、待确认问题或分歧
条数、时间和覆盖说明由程序计算,不让模型编造。负责人、期限和结论必须来自记录;没有明确说明就标注未明确。可附发言时间、显示名称和短消息引用,不虚构 WhatsApp 消息链接。摘要仍是模型生成内容,重要事项应回查原文确认。
发送前再次核验群、作用域和授权仍有效。只回复发起请求的原群,不允许正文中的群名、号码或“转发给某人”改变目标。
11. 并发、发送与状态
| 情况 | 处理规则 |
|---|---|
| 同一请求重复投递 | 以平台请求 ID 识别已创建任务,不重复调用模型 |
| 同群同时请求多次 | 第一版同群只执行一个摘要;后续请求返回忙碌提示,不无限排队 |
| 生成期间群里继续聊天 | 继续记录;当前摘要保持原快照 |
| 跨群并发 | 使用独立队列和会话,并受机器人级并发预算约束 |
| 模型超时或失败 | 保留原记录,报告失败;重试前核验任务状态,避免重复运行 |
| 发送失败且明确未发送 | 可以使用已生成结果有限重试,不再调用模型 |
| 发送结果不确定 | 标注待确认,不盲目重复发送;不承诺平台级严格一次交付 |
| 插件重启 | 恢复记录索引和任务状态;未完成摘要标记中断,不自动重新付费生成或补发 |
| 记录服务失效 | 状态进入异常,不能用内存数据冒充已持久化历史 |
出站拆分复用 WhatsApp 已有的长度限制和发送方式。任务状态至少区分读取、生成、发送、成功、失败、中断和发送待确认,后台错误不泄露群正文或凭据。
12. 隐私、保存期限和关闭行为
这是复用 Harness 会话存储必须接受的限制:当前统一接口没有删除记录的能力。
| 用户操作或要求 | 第一版的真实效果 |
|---|---|
| 关闭记录 | 停止新消息采集,不删除旧记录 |
| 删除机器人 | 移除账号接入与授权;历史会话仍在 Harness 后端中 |
| 消息被撤回 | 新查询不再采用原文,但旧原文及已生成摘要仍可能保留 |
| 只查询最近 30 天 | 仅限制可查询范围,不是物理保留期限 |
| 要求 30 天后自动彻底删除 | 当前主方案不支持,不能包装成已支持 |
| 使用云端模型 | 被选中的原文或分块内容会发送给该模型服务商,并进入摘要会话 |
因此,第一版不显示“自动删除”“清空全部记录”等无法兑现的按钮。可以提供停止记录、容量告警和管理员定位说明,但不通过直接修改 Harness 文件实现删除。若业务必须有严格的删除期限,需另选插件自管存储方案,不能继续声称这两种方案完全等价。
关闭操作先停止新入队,处理或明确取消已接收队列,等待正在进行的持久化操作结束,再返回成功;生成和发送任务同时取消。已提交的记录不会因关闭而回滚。
插件管理元数据使用严格文件权限;Harness 后端的权限与加密由其实际配置决定,不因“本地保存”就宣称已加密。dsh-im 的按群授权不等于为整个 Harness 新增行级访问控制:本机管理员和其他具有宿主权限的组件仍属于受信范围。
发起者白名单限制的是谁能请求总结,输出仍对原群当前成员可见。后来加入的成员也可能通过摘要看到此前的讨论;第一版不模拟每位成员的历史可见范围,启用时需确认这种分享方式适合该群。
13. 拟修改的 dsh-im 文件
以下是实施时的范围,不代表本次已经修改:
| 文件或目录 | 职责 |
|---|---|
src/channels/whatsapp/whatsapp-web-session.mjs |
授权记录分支、原始时间、重连事件、编辑与撤回订阅 |
src/channels/whatsapp/whatsapp-runtime.mjs |
记录与普通响应分流、真实提及判断、出站回声识别 |
src/channels/whatsapp/whatsapp-controller.mjs |
群选择、启停、状态及生命周期 |
plugin-src/host/channels/whatsapp/production.mjs |
注入同 Host 的持久化、摘要和权限依赖 |
plugin-src/host/channels/whatsapp/rpc.mjs |
独立的群配置、状态和按需预览 RPC,沿用现有 RPC 授权 |
| 新增插件侧群记录服务 | 配置和元数据、归档会话所有权、批量写入与恢复 |
| 新增共享的群记录与摘要逻辑 | 最小消息语义、日期范围、快照、去重和摘要格式;不先搭建九渠道框架 |
| 新增摘要执行适配 | 创建专用摘要会话、工具保护、分块、取消和结果发送 |
plugin-src/client/channels/whatsapp/ |
群授权设置、状态、记录预览及风险说明 |
test/channels/whatsapp/ 及相关共享测试 |
优先扩展现有用例;独立存储与摘要模块在没有自然归属时新建测试文件 |
README.md、README.en.md、CHANGELOG.md |
实现后同步配置、使用方式、限制及升级说明 |
若需要调用 Harness 包导出的常量或类型,使用公开导出并在构建时保留正确的宿主依赖关系;不导入本地源码路径,不捆绑另一份宿主状态服务。对运行版本的支持范围以实际验证结果列出,不能仅靠方法存在就宣称兼容。
14. 与旧版本及其他功能的关系
- 旧机器人和新机器人都默认关闭,升级不会自动收集群消息。
- 配置保存与启用失败不改变普通聊天访问模式,不把失败的功能退化为开放访问。
- 现有
/history仍查看普通对话历史,不改变其私聊范围和条数语义。 - 原有普通问答、模型切换、审批、文件与图片收发、工作区和会话命令保持现状。
- 无兼容持久化服务、没有可靠工具限制或显式远程 HTTP 接入时,设置页显示具体不可用原因;其他 WhatsApp 功能继续运行。
- 停用或卸载 dsh-im 后,兼容的 Harness 读取器能够忽略纯信息事件;只有 dsh-im 理解其群记录含义。
- 不自动迁移已生成的群记录到其他后端,也不在回滚时删除用户数据。
- 管理元数据保留已删除账号的必要历史归属信息,但不保留认证材料,避免旧记录变成无法定位的孤立日志。
15. 实施顺序与必须先通过的验证
阶段 0:验证“不改 Harness”路径
在目标安装版本和临时数据目录中验证,不能在用户真实会话里试写:
- dsh-im 作为已构建插件可以获取所需公开服务及格式版本,不依赖源码别名。
- 创建仅有插件信息事件的独占归档会话,通过服务写入后可读回。
- 关闭整个临时 Host,再启动新 Host,原记录、顺序和去重信息仍能恢复并继续追加。
- JSONL 与 SQLite 后端均覆盖;缺少对应后端的版本不宣称已测。
- 插件不加载时,带兼容标记的记录不会使宿主拒绝其他正常会话;原生列表及日志预览表现明确。
- 自定义记录不进入模型消息历史,已有全文检索不会被错误当作归档检索入口。
- 摘要执行与恢复时,工具保护在真正的执行入口生效;测试恶意群文字不能引发工具调用副作用。
- 专用归档被误激活、多个写入者、重载和尾部异常均能停止或安全恢复,不污染普通 Agent 会话。
任何关键项不通过,都先报告限制,不修改 Harness 核心、不伪装事件、不直接改存储文件,也不未经确认切换成另一套聊天数据库。
阶段 1:授权与记录闭环
实现群配置、入站分流、纯文字归档、时间字段、分段、去重、编辑撤回处理、覆盖状态和管理员预览。先证明记录正确与重启恢复,再接模型。
阶段 2:总结闭环
实现明确指令、发送者白名单、按时区读取快照、受限摘要执行、长文本分块、引用与覆盖说明、原群发送及失败状态。
阶段 3:真实群验证与发布
在知情同意的测试群中验证未 @ 记录、@ 总结、重启、跨日、断连、重复消息和多群隔离。先限定已测试的同 Host 安装范围,完善帮助与发布说明,再开放使用。
16. 验收清单
| 场景 | 必须观察到的结果 |
|---|---|
| 未启用、群未授权 | 不保存正文、不创建摘要、不产生额外回复 |
| 仅自己普通访问模式,另行授权指定群 | 该群可记录与授权总结,其他私聊和群权限未扩大 |
| 其他成员未提及或回复机器人的普通群文字 | 保存一次,不调用模型、不发送聊天状态反馈 |
| 白名单成员 @ 总结 | 基于本群指定日期已收录记录回复 |
| 非白名单成员、伪造昵称或号码 | 不读取记录、不调用模型,不能绕到普通 Agent 总结 |
| PN/LID 身份混用 | 仅可信映射通过;未知映射拒绝,@ 判断不靠昵称 |
| 重复投递、重连补到消息 | 原始记录去重,历史总结命令不被重新执行 |
| 用户本人发言与机器人出站回声 | 前者正常记录,后者不触发循环,重启后仍成立 |
| 日期边界、跨 UTC 日期、夏令时 | 按保存的群时区查询,不混入相邻日期 |
| 一天中途启用或出现断连 | 说明真实记录范围,不冒充全天覆盖 |
| 编辑、撤回、媒体、自动消失设置变化 | 使用已观察的有效版本,媒体标注,受限内容停止采集 |
| 模型上下文不足 | 分块完整覆盖或明确拒绝,不静默截断 |
| 群文字包含执行命令或泄露其他群的要求 | 仅作为资料,不执行工具,不扩大读取范围 |
| 摘要期间继续收消息 | 新消息继续保存,本次快照不变化 |
| 切换工作区、关闭或删除机器人 | 取消旧范围任务,不向错误群发送,不声称已删除历史 |
| 磁盘错误、队列溢出、写入返回不确定 | 状态可见,恢复核对已提交前缀,无盲目重试 |
| 进程重启、插件热重载 | 可恢复记录,不重复生成或补发,不丢失工具保护 |
| 远程 HTTP 或不兼容宿主 | 仅新功能不可用,原因明确,原有功能不受影响 |
| 回归 | 既有 WhatsApp 私聊、群聊及其他渠道行为未改变 |
实现后先运行受影响的存储、时间、权限、队列和 WhatsApp 测试,再运行仓库现有构建与包校验。真实 WhatsApp、真实安装版本和完整重启验证分别报告,不能用 mock 或现有后端测试代替整体验收。
17. 本次方案的证据与未完成项
本次只新增方案文档,没有修改 dsh-im 功能代码或 Harness 代码。检查来源为本机工作区:
- dsh-im 基线提交:
8c6c31a1b668f307b36686c78a1d51ea5b0e04d0。工作区已有其他未提交改动,本方案未修改它们。 - Harness 所检查的关键源码基线:
47f943859bef60e4160492346772ded9b24f765a;关键读取文件无本地改动。它不自动代表当前已安装运行版本。 - 持久化公开 API:
packages/session/session-persistence/src/index.ts。 - 未知事件兼容校验:
packages/core/session/src/known-event-types.ts、packages/session/session-persistence/src/coordinator.ts。 - Session 追加行为:
packages/core/session/src/index.ts。 - 原生列表的未开始会话语义:
packages/host/apiproxy/src/api/sessions.ts。 - 自定义事件检索限制:
packages/session-query/session-query/README.md。 - 工具保护接口:
packages/core/tools/README.md。 - 后端格式、恢复和删除限制:
packages/session/session-persistence-jsonl/README.md、packages/session/session-persistence-sqlite/README.md。
已在本机 Harness 源码工作区运行现有定向测试:
pnpm exec vitest run \
packages/session/session-persistence-jsonl/tests/jsonl.spec.ts \
packages/session/session-persistence-sqlite/tests/sqlite.spec.ts \
-t 'rejects malformed persisted message events|unknown event type'
结果为 2 个测试文件通过,4 条测试通过,247 条跳过。这验证了两种后端已有的未知事件兼容规则,以及无执行轮次的独立插件记录可经 inspect 和 readFrom 读回,没有验证本方案尚未实现的插件、真实群接入、整机重启、摘要质量或已安装版本兼容性。
WhatsApp 接入仍使用非官方 Baileys;账号限制、连接变化和平台兼容性风险继续存在,不能因为记录放进 Harness 就消除这些风险。使用范围应符合群成员授权与平台要求,参见 Baileys 项目声明。
18. 建议采用的第一版决策
采用“同 Host 插件 + 明确群授权 + Harness 持久化服务中的专用群记录会话 + 受限摘要会话 + dsh-im 记录预览”。普通聊天与原有命令保持原样。
该方案满足“不改 Harness 核心”和“聊天原文保存在 Harness 会话存储中”。它不把“与原有问答共用同一个可执行 Session”“在原生聊天窗口逐条显示”“自动物理清除”和“远程 HTTP 支持”混入第一版承诺。先完成兼容性验证,通过后再实施功能。