fix(conversation): 离屏不丢回复、列表预热 WS 与非阻塞进入聊天

- 后端:文本/转写后 AI 生成改为独立任务,避免断连取消整轮;按需 TTS 等与 WS 改动
- 前端:RealtimeSession 重绑 UI 时恢复流式 buffer;列表 onPressIn/挂载预热、已有会话立即 push
- 同步会话相关类型、i18n、测试与 env/资源等累计改动

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Kevin
2026-05-08 17:28:31 +08:00
parent 5dac3efd52
commit d0c26242db
44 changed files with 1209 additions and 212 deletions

View File

@@ -1,25 +1,35 @@
# WebSocket 消息协议
## 连接
- URL: /ws/conversation/{conversation_id}?token={jwt_access_token}
- 鉴权: query 参数 tokenJWT access_token
- URL: `/ws/conversation/{conversation_id}?token={jwt_access_token}`
- 鉴权: query 参数 `token`JWT `access_token`
## 消息类型 (client → server)
- TEXT: 文本消息
- AUDIO_SEGMENT: 语音分段
- AUDIO_MESSAGE: 完整语音消息
- TRANSCRIBE_ONLY: 仅转写不回复
- END_CONVERSATION: 结束对话
- `TEXT`:文本消息。`data.text` 必填。可选 `data.tts_this_turn`(布尔):为 `true` 且服务端 `ENABLE_TTS` 开启且本轮回避 `skip_tts` 时,对该轮助手回复分段合成 TTS默认为 `false`/缺省即不合成。**当开启本轮 TTS 时,每个助手分段服务端先推送 `tts_audio` 再推送该段 `agent_response`**,便于客户端先收音频再展示同段文字。
- `AUDIO_SEGMENT`:语音分段。`data``audio_base64``segment_index``voice_session_id` / `client_segment_id``is_last``duration`。可选同上 `tts_this_turn`
- `AUDIO_MESSAGE`:整段音频(单次 ASR + 对话)。同上可选 `tts_this_turn`
- `TRANSCRIBE_ONLY`:仅转写不回复
- `TTS_CANCEL`:取消当前轮未完成的分段合成与下发
- `TTS_REQUEST`:用户点击某一助手气泡「朗读」且该段尚无 TTS 时下发。`data``assistant_message_id`(落库 `conversation_messages.id`)、`segment_index`(与该条助手正文按 `[SPLIT]` 分段后的从 0 下标)、可选 `segment_text`(须与该分段正文一致,用于校验)。服务端若该段已有 URL 则只做预签名后推送 `tts_audio``data.manual=true`**不重复合成**。
- `END_CONVERSATION`:结束对话
- `PING` / `PONG`:心跳(客户端也可用 JSON `{"type":"ping"}`
## 消息类型 (server → client)
- TRANSCRIPT: ASR 转写结果
- AGENT_RESPONSE: AI 回复文本
- TTS_AUDIO: 语音合成音频 (base64)
- MEMOIR_UPDATE: 回忆录更新通知
- ERROR: 错误信息
- `TRANSCRIPT`: ASR 转写结果
- `AGENT_RESPONSE`: AI 回复文本分段
- `TTS_AUDIO`: 语音合成结果(可与 `COS` 签名 URL、`base64` 并存)。按需朗读成功时 `data.manual` 可为 `true`,提示客户端应播放(即使用户未开「本轮 Speak」
- `MEMOIR_UPDATE`: 回忆录更新通知
- `ERROR`: 错误信息
## 状态流转
CONNECT → (TEXT|AUDIO_*) ↔ (TRANSCRIPT|AGENT_RESPONSE|TTS_AUDIO) → END_CONVERSATION
`CONNECT → (TEXT|AUDIO_*) ↔ (TRANSCRIPT|AGENT_RESPONSE|[TTS_AUDIO]) → END_CONVERSATION`
同一连接内消息顺序稳定;首轮朗读模式下每一助手分段为 `tts_audio` 先于对应 `agent_response`
## 重连
客户端断连后可用相同 conversation_id 重连,历史消息从 Redis 恢复。
客户端断连后可用相同 `conversation_id` 重连,历史消息从 Redis / HTTP 缓存恢复。