* feat: add OneTalk quote reply support * chore(task): archive 09-17-onetalk-quote-reply-protocol * chore: record journal * docs: format OneTalk DOM card collection plan * chore: release 0.8.29 * chore: release 0.8.30
5.6 KiB
OneTalk 引用回复:Mind 对接说明
适用范围:Mind 已接入 Bright OneTalk WebSocket 的文本发送链路。本说明只增加引用目标字段,不改变连接、授权、普通发送或发送结果协议。
1. 能力与边界
Mind 在 OneTalk 时间线中选择一条文本消息后,可以发送一条引用该消息的新文本。Mind 只向 Bright 提交被引用消息的 OneTalk messageId;Bright 和插件负责在同一账号、同一会话内解析 OneTalk SDK 所需的原始引用对象。
Mind 不得发送、保存或展示下列数据:
- OneTalk SDK
referMessage/originalData; .PNM后缀的 SDK 传输别名;- 根据正文、时间、发送人或 UI 序号推导出的 ID;
- Mind 数据库 UUID(它不是 OneTalk
messageId)。
第一版只支持“引用文本后发送文本”。图片和文件仍走既有普通发送,不能附带引用字段。
2. 引用目标的来源
从 Bright 返回的 OneTalk 时间线消息中读取该条消息的 id / messageId,将其原样作为 replyToMessageId。
type ReplyTarget = {
messageId: string; // Bright OneTalk messageId,不是 Mind UUID
from: string;
text: string;
};
仅当时间线行满足以下条件时显示“回复”入口:
- 消息正文是非空文本;
messageId为非空字符串;- 消息属于当前 OneTalk 会话,且不是 system、optimistic 或本地临时消息。
messageId 不做 trim、拼接或格式转换;例如 123456.PNM 不是合法的 replyToMessageId。
3. 发送帧增量
沿用既有 send.request WebSocket 帧。在当前共享协议版本 9 中,引用发送的 payload 必须恰好为以下形状:
{
"conversationId": "c123",
"content": {
"kind": "text",
"text": "这条消息是在回复前文"
},
"replyToMessageId": "123456"
}
完整帧示例(scope、requestId 与 sendRequestId 继续使用当前 Mind 的既有生成与关联逻辑):
{
"protocolVersion": 9,
"connectionType": "mind_page",
"type": "send.request",
"requestId": "mind-frame-001",
"sendRequestId": "mind-send-001",
"scope": {
"workspaceId": "workspace-1",
"mindUserId": "mind-user-1",
"channelAccountId": "286995452"
},
"payload": {
"conversationId": "c123",
"content": {
"kind": "text",
"text": "这条消息是在回复前文"
},
"replyToMessageId": "123456"
}
}
普通发送保持原样,省略 replyToMessageId:
{
"conversationId": "c123",
"content": { "kind": "text", "text": "普通文本" }
}
不要把 replyToMessageId 放到 content、ext 或其他扩展对象中;协议采用严格字段校验,未知字段或错误层级会被拒绝。
4. Mind 侧校验
发起引用发送前,Mind 必须确认:
conversationId是当前会话的 OneTalkconversationId;replyToMessageId非空、没有首尾空白,且不是纯数字加.PNM;content.kind === "text"且content.text非空;- 当前 WebSocket scope 中的
channelAccountId与时间线消息所属账号一致。
不要在客户端把无效引用降级为普通文本发送。若本地无法确定目标 ID,应禁用发送并提示用户重新选择消息。
5. Composer 交互
点击“回复”后,Mind 只保留临时 UI 状态 { messageId, from, text }:composer 中显示发送者和截断文本摘要,并提供“取消引用”。
以下场景必须清除该临时状态:
- 切换 OneTalk 会话;
- 收到
confirmed_sent; - 收到
rejected_before_send。
收到 delivery_unknown 时,不能自动重试或伪造发送成功;应保留既有“结果未知”的可见状态,由用户决定后续操作。
第一版不要求 Mind 解析或重新绘制远端消息里的引用卡片。引用内容由 OneTalk 页面渲染,Mind 时间线仍按 Bright 已返回的规范化消息展示。
6. 结果处理
send.result 与普通发送使用同一关联键 sendRequestId,结果语义不变:
| status | Mind 行为 |
|---|---|
confirmed_sent |
将返回的已发送消息并入时间线,清除引用临时状态。 |
rejected_before_send |
显示 reason,清除引用临时状态;不得改发普通文本。 |
delivery_unknown |
显示结果未知;不得自动重试、不得假定消息已发送。 |
常见拒绝原因包括 invalid_request(引用 ID 不合法、引用目标不在当前会话或不支持的内容类型)、waiting_for_page、page_not_found、page_identity_mismatch 与 send_not_supported。Mind 应直接展示已有的发送错误状态,不自行转换错误码。
7. 联调验收
- 加载 OneTalk 会话与文本消息,确认时间线行使用 Bright 返回的真实
messageId。 - 选择一条文本消息,发送引用文本,检查发送帧只有顶层
payload.replyToMessageId。 - 确认
send.result与同一个sendRequestId关联,并仅在confirmed_sent时显示发送成功。 - 验证切换会话、取消引用与
rejected_before_send都会清除 composer 的引用状态。 - 验证普通文本、图片和文件发送均不携带
replyToMessageId,原有行为不变。
8. 兼容性
Mind、Bright 与 Chrome 插件必须使用兼容的 OneTalk 协议版本部署。当前源码的协议版本为 9;上线前以实际运行中的共享 contract 为准,不要让旧客户端向新协议帧附加未知字段。