# Cyrene v2 — WebSocket 协议 > **端点**: `ws://localhost:8080/ws/chat?token=` > **协议**: JSON 文本帧 --- ## 连接 ``` ws://localhost:8080/ws/chat?token=eyJhbGciOi... ``` Token 通过 query 参数传递,需先通过 `/api/v1/auth/login` 获取。 --- ## 客户端 → 服务端 ### 发送消息 ```json { "type": "message", "content": "你好呀", "session_id": "abc123", "timestamp": 1234567890 } ``` | 字段 | 类型 | 说明 | |------|------|------| | type | string | 固定 `"message"` | | content | string | 用户输入文本 | | session_id | string | 会话 ID(需先通过 REST 创建) | | timestamp | number | Unix 毫秒时间戳 | --- ## 服务端 → 客户端 ### `stream_chunk` — 流式输出 LLM 逐 token 推送。前端应累积拼接。 ```json { "type": "stream_chunk", "content": "你", "session_id": "abc123" } ``` ### `stream_end` — 流式结束 ```json { "type": "stream_end", "session_id": "abc123" } ``` ### `response` — 独立消息 审查后的 action/chat 分段或系统响应。 ```json { "type": "response", "content": "你好呀~ 有什么可以帮你的吗?", "session_id": "abc123" } ``` > **action 消息**:当 content 包含 `[Intent: xxxx]` 前缀时,前端应居中斜体渲染。 ### `device_update` — IoT 状态广播 ```json { "type": "device_update", "devices": [ {"id": "light-livingroom", "name": "客厅灯", "type": "light", "state": {"power": true}, "online": true} ] } ``` ### `notification` — 推送通知 ```json { "type": "notification", "title": "提醒", "body": "你设置的闹钟时间到了" } ``` ### `error` — 错误消息 ```json { "type": "error", "error": "AI 引擎未配置" } ``` --- ## 完整对话流程 ``` 1. 浏览器 → POST /api/v1/auth/login → 获得 JWT Token 2. 浏览器 → POST /api/v1/sessions → 获得 session_id 3. 浏览器 → WS /ws/chat?token= → WebSocket 连接建立 4. 浏览器 → 发送 {"type":"message","content":"打开客厅灯","session_id":"..."} 5. 服务端 → stream_chunk: "好" 6. 服务端 → stream_chunk: "的" 7. 服务端 → stream_chunk: "~" 8. 服务端 → response: "[Intent: iot_control]" 9. 服务端 → response: "客厅灯已经打开啦♪" 10. 服务端 → stream_end ``` --- ## 重连策略 前端应实现指数退避自动重连: | 重试次数 | 等待时间 | |---------|---------| | 1 | 1s | | 2 | 2s | | 3 | 4s | | 4 | 8s | | 5+ | 30s (上限) | 重连后需重新发送 `session_id` 绑定消息。 --- ## 注意事项 - 单连接单会话:一个 WebSocket 连接对应一个 `session_id` - Token 过期:服务端返回 `{"type":"error","error":"invalid token"}` 后关闭连接,前端应重新登录 - 心跳:暂时无 ping/pong 协议,TCP 层保活。