Files
trade-message-center/.trellis/tasks/archive/2026-09/09-17-onetalk-quote-reply-protocol/implement.md
T
YBF 784bbec2a0 feat: 支持 OneTalk 文本引用回复协议 (#66)
* 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
2026-09-17 11:56:35 +08:00

5.2 KiB
Raw Blame History

OneTalk 文本引用回复实施计划

Preconditions

  • 实施前在两个实际部署的 checkout 确认 Mind 和 Center 当前正在使用的 WebSocket protocol version。仓库快照显示常量不同,不能假定只改一侧即可兼容。
  • 只改 OneTalk 文本发送;媒体/富卡引用不进入本计划。
  • 在写任何 SDK raw 索引前,确认其生命周期仅限 MAIN world,且不会被现有 createOneTalkObservedPublisher、page bridge、日志或 IndexedDB 传播。

Workstream A — Shared contract and Center

  1. packages/onetalk-contract/src/sending.ts 为发送 payload 定义可选 replyToMessageId;保留普通发送精确 shape,新增文本引用 shape,拒绝空字符串、非文本 content 和未知额外字段。
  2. 同步 isValidOneTalkSendingPayload、frame type exports、协议版本和 packages/onetalk-contract/test/contract.test.ts。旧版本或只有一端携带新字段必须得到现有 protocol/invalid-message 失败,不作静默兼容。
  3. 验证 apps/server/src/websocket/pending-send-coordinator.ts 仍仅按账号、scope、conversation 和 sendRequestId 授权/关联;它可透传验证过的 replyToMessageId,但不解析引用源或存储 raw 数据。
  4. 更新 apps/server/test/websocket.test.tsMind send.request 到 plugin send.command 透传文本引用 ID;普通文本不带该字段;空/媒体/额外字段拒绝;失败/超时仍保持三态 payload。

Workstream B — Plugin MAIN-world resolution

  1. apps/chrome-extension/src/onetalk/main-page/message-observer/ 新增私有文本引用源索引。它以 channelAccountId + conversationId + normalizeOneTalkMessageId(messageId) 为键,存储最小的 SDK quote 输入来源,写入仅来自已验证的 raw history/live OneTalk 文本消息。
  2. 历史和实时解析在发布白名单观察前,向该索引登记 messageIdForSdksubType: 1senderAliId、方向对应名称、originalData、文本和 sendTime。若必要字段不完整,不登记;不得从已发布的 OneTalkMessage 反构 originalData
  3. 账号切换、页面重载、会话不一致时使索引不可用。lookup 要求 command 的 conversation、当前登录 channelAccountId 和 canonical message ID 三者一致。
  4. replyToMessageId 以可选顶层字段从 send.command 路由至 page command;扩展 handleOneTalkSendCommandSendObservationCorrelator.execute 的输入,使最终 SDK 输入为 { cid, conversationCode: cid, content, referMessage }
  5. 只有 lookup 成功才调用 sendUIMessages。引用源缺失、跨账号/会话、非文本或 SDK 不可用时返回 canonical rejected_before_send/invalid_requestsend_not_supported;绝不降级为普通发送、DOM 点击或私有 EventBus。
  6. 保持 SendObservationCorrelator 单一确认机制:SDK result 只补充候选 ID,最终确认仍由完整 direction: sent 旁路消息决定。
  7. 扩展 apps/chrome-extension/test/onetalk-send-page.test.jsonetalk-send-observation.test.jsonetalk-websocket-tap.test.js 及新增 focused quote-index test,覆盖输入 shape、MAIN 隔离、.PNM 恢复、预发送拒绝、SDK input 和非引用回归。

Workstream C — Mind text reply UX and WS client

  1. trade-mind/apps/web/src/features/communication/communication-onetalk-bright-types.tscommunication-onetalk-bright-realtime-rules.tsOneTalkBrightSendMessageRequest、frame builder 和 reader 增加可选 replyToMessageId,并采用已协商的 protocol version。
  2. alibaba-message-timeline.tsx 添加只针对普通文本消息的回复按钮;该组件只将 { id, from, text } 回调给 workspace,不暴露原始协议数据。
  3. communication-workspace.tsx 持有当前 OneTalk 文本引用目标,将它传入 oneTalkBrightRealtime.sendMessage,并在取消、会话切换、成功与拒绝后清理。为 Alibaba composer 添加引用预览,不增加历史引用卡。
  4. 补 Mind focused testsframe writer/parser 的可选字段与拒绝条件、文本行显示回复操作、非文本/系统/optimistic 行不显示、composer 取消和发送 payload、会话切换清理。

Verification gates

  1. Shared contract package tests和 server WebSocket tests(每个后端测试命令必须限制在 60 秒内)。
  2. Chrome extension focused testssend handler、raw quote source index、WebSocket/history observer、page bridge flow;再运行对应 type/lint/build 检查。
  3. Mind focused unit/render tests和 TypeScript check;在 Mind checkout 验证 WS builder 与当前 Center protocol version 匹配。
  4. 真实 Chromium:在当前会话对一条已加载的入站文本发出引用;确认 SDK input 的 referMessage、OneTalk 引用 UI、WebSocket complete sent fact 和 Mind confirmed_sent。再在未选中的目标会话测试 cid 路由。
  5. 回归普通文本、图片和文件发送,确认无 replyToMessageId 时 payload 与确认语义不变。

Rollback

  • 协议或 raw lookup 任一步不满足时,发布前不启用 Mind 回复入口;已有普通发送保持不带 replyToMessageId 的精确 payload。
  • 若上线后需回退,统一回退 Mind 与 Center/插件的协议版本;禁止仅回退一端后让新字段被静默吞掉。