- 列表预热仅预取消息缓存,避免后台 WebSocket 覆盖服务端连接 - RealtimeSession UI 回调按 owner 独占,防止 offscreen 覆盖聊天页 - 列表页聚焦时再 prewarm,会话页 TTS 入队优先 base64 - 管线下发 TTS 同时带 audio_base64 与 audio_url;协议说明同步 - 移除 TTS 排查用前后端调试日志,保留错误/告警 - 补充 WS / RealtimeSession / entry-warmup / 播放器相关单测 Co-authored-by: Cursor <cursoragent@cursor.com>
2.4 KiB
2.4 KiB
WebSocket 消息协议
连接
- URL:
/ws/conversation/{conversation_id}?token={jwt_access_token} - 鉴权: query 参数
token,JWTaccess_token
消息类型 (client → server)
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: 语音合成结果。标准链路下发data.audio_base64作为本轮即时播放通道,并同时下发data.audio_url(COS 预签名可播放 URL)供客户端绑定气泡、退出重进后复播。按需朗读成功时data.manual可为true,提示客户端应播放(即使用户未开「本轮 Speak」)。MEMOIR_UPDATE: 回忆录更新通知ERROR: 错误信息
状态流转
CONNECT → (TEXT|AUDIO_*) ↔ (TRANSCRIPT|AGENT_RESPONSE|[TTS_AUDIO]) → END_CONVERSATION
同一连接内消息顺序稳定;首轮朗读模式下每一助手分段为 tts_audio 先于对应 agent_response。
重连
客户端断连后可用相同 conversation_id 重连,历史消息从 Redis / HTTP 缓存恢复。