# WebSocket 消息协议 ## 连接 - URL: `/ws/conversation/{conversation_id}?token={jwt_access_token}` - 鉴权: query 参数 `token`,JWT `access_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 缓存恢复。