mirror of
https://github.com/sinanyuntu/trade-message-center.git
synced 2026-09-17 13:22:11 +08:00
* 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
137 lines
5.6 KiB
Markdown
137 lines
5.6 KiB
Markdown
# 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`。
|
||
|
||
```ts
|
||
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 必须恰好为以下形状:
|
||
|
||
```json
|
||
{
|
||
"conversationId": "c123",
|
||
"content": {
|
||
"kind": "text",
|
||
"text": "这条消息是在回复前文"
|
||
},
|
||
"replyToMessageId": "123456"
|
||
}
|
||
```
|
||
|
||
完整帧示例(`scope`、`requestId` 与 `sendRequestId` 继续使用当前 Mind 的既有生成与关联逻辑):
|
||
|
||
```json
|
||
{
|
||
"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`:
|
||
|
||
```json
|
||
{
|
||
"conversationId": "c123",
|
||
"content": { "kind": "text", "text": "普通文本" }
|
||
}
|
||
```
|
||
|
||
不要把 `replyToMessageId` 放到 `content`、`ext` 或其他扩展对象中;协议采用严格字段校验,未知字段或错误层级会被拒绝。
|
||
|
||
## 4. Mind 侧校验
|
||
|
||
发起引用发送前,Mind 必须确认:
|
||
|
||
- `conversationId` 是当前会话的 OneTalk `conversationId`;
|
||
- `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. 联调验收
|
||
|
||
1. 加载 OneTalk 会话与文本消息,确认时间线行使用 Bright 返回的真实 `messageId`。
|
||
2. 选择一条文本消息,发送引用文本,检查发送帧只有顶层 `payload.replyToMessageId`。
|
||
3. 确认 `send.result` 与同一个 `sendRequestId` 关联,并仅在 `confirmed_sent` 时显示发送成功。
|
||
4. 验证切换会话、取消引用与 `rejected_before_send` 都会清除 composer 的引用状态。
|
||
5. 验证普通文本、图片和文件发送均不携带 `replyToMessageId`,原有行为不变。
|
||
|
||
## 8. 兼容性
|
||
|
||
Mind、Bright 与 Chrome 插件必须使用兼容的 OneTalk 协议版本部署。当前源码的协议版本为 9;上线前以实际运行中的共享 contract 为准,不要让旧客户端向新协议帧附加未知字段。
|