# hermes-chat-protocol **Repository Path**: datahowler/hermes-chat-protocol ## Basic Information - **Project Name**: hermes-chat-protocol - **Description**: Hermes Chat WS 消息协议 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-06 - **Last Updated**: 2026-07-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Hermes Chat — WS 消息协议 v3 > 从零设计,遵循最小化、一致性、可扩展原则。 --- ## 消息结构 所有消息统一格式,无嵌套 type: ```json { "id": "uuid", "type": "...", "from": "user_id", "to": "user_id | hermes", "session": "uuid", "reply_to": "uuid | null", "ts": 1719123456, "data": { ... } } ``` | 字段 | 必填 | 说明 | |---|---|---| | `id` | ✅ | 消息唯一 ID,UUID | | `type` | ✅ | 消息类型 | | `from` | ✅ | 发送方 ID | | `to` | ✅ | 接收方 ID(`hermes` 或 user_id) | | `session` | ✅ | 会话 ID | | `reply_to` | ❌ | 回复某条消息的 `id` | | `ts` | ✅ | Unix 秒级时间戳 | | `data` | ❌ | 消息体 | > `ping` / `pong` 只带 `type`,不需要其他字段。 --- ## 连接 ``` App: wss://www.inonworks.com/ws/app?token= Agent: wss://www.inonworks.com/ws/agent?api_key= ``` Gateway 在 upgrade 前验证,通过后按 `user_id` 配对路由。 --- ## 类型总览 | type | 方向 | 说明 | |---|---|---| | `text` | 双向 | 文本消息 | | `image` | 双向 | 图片 | | `voice` | 双向 | 语音 | | `video` | 双向 | 视频 | | `file` | 双向 | 文件 | | `stream_start` | Agent → App | 流式回复开始 | | `stream` | Agent → App | 流式增量 | | `stream_end` | Agent → App | 流式回复结束 | | `error` | 双向 | 错误通知 | | `ping` | App ↔ Server | 心跳 | | `pong` | Server → App | 心跳响应 | --- ## text ### App 发送 ```json { "id": "msg_001", "type": "text", "from": "admin", "to": "hermes", "session": "abc-123-def", "ts": 1719123456, "data": { "text": "帮我写个快速排序" } } ``` ### Agent 回复(非流式,简单应答) ```json { "id": "msg_002", "type": "text", "from": "hermes", "to": "admin", "session": "abc-123-def", "reply_to": "msg_001", "ts": 1719123457, "data": { "text": "好的,马上处理" } } ``` --- ## image ```json { "id": "msg_003", "type": "image", "from": "admin", "to": "hermes", "session": "abc-123-def", "ts": 1719123456, "data": { "text": "看下这张图", "media": { "id": "med_a1b2c3", "name": "photo.jpg", "type": "image/jpeg", "size": 245760, "width": 1920, "height": 1080 } } } ``` ## voice ```json { "id": "msg_004", "type": "voice", "from": "admin", "to": "hermes", "session": "abc-123-def", "ts": 1719123456, "data": { "media": { "id": "med_d4e5f6", "type": "audio/aac", "size": 48000, "duration": 15 }, "text": "帮我查下今天的天气" } } ``` ## video ```json { "id": "msg_005", "type": "video", "from": "admin", "to": "hermes", "session": "abc-123-def", "ts": 1719123456, "data": { "text": "看下这个演示", "media": { "id": "med_g7h8i9", "name": "demo.mp4", "type": "video/mp4", "size": 5242880, "duration": 30, "width": 1920, "height": 1080 } } } ``` ## file ```json { "id": "msg_006", "type": "file", "from": "admin", "to": "hermes", "session": "abc-123-def", "ts": 1719123456, "data": { "text": "分析下这个数据", "media": { "id": "med_j0k1l2", "name": "sales.csv", "type": "text/csv", "size": 10240 } } } ``` ### media 字段 | 字段 | image | voice | video | file | |---|---|---|---|---| | `id` | ✅ | ✅ | ✅ | ✅ | | `name` | ✅ | — | ✅ | ✅ | | `type` | ✅ | ✅ | ✅ | ✅ | | `size` | ✅ | ✅ | ✅ | ✅ | | `width` | ✅ | — | ✅ | — | | `height` | ✅ | — | ✅ | — | | `duration` | — | ✅ | ✅ | — | --- ## 流式回复 Agent 回复较长内容时使用流式。时序: ``` stream_start → stream × N → stream_end ``` ### stream_start ```json { "id": "str_001", "type": "stream_start", "from": "hermes", "to": "admin", "session": "abc-123-def", "reply_to": "msg_001", "ts": 1719123457 } ``` App 收到后插入空白气泡 + 闪烁光标。 ### stream ```json { "type": "stream", "from": "hermes", "to": "admin", "session": "abc-123-def", "data": { "text": "快速排序的" } } ``` > `stream` 不带 `id` 和 `ts`——它是流的一部分,不是独立消息。 App 收到后追加文字到当前气泡。 ### stream_end ```json { "type": "stream_end", "from": "hermes", "to": "admin", "session": "abc-123-def" } ``` App 收到后光标消失,消息完成。 --- ## error ```json { "id": "err_001", "type": "error", "from": "hermes", "to": "admin", "session": "abc-123-def", "reply_to": "msg_001", "ts": 1719123457, "data": { "code": "timeout", "text": "处理超时,请稍后再试" } } ``` | code | 说明 | |---|---| | `timeout` | 处理超时 | | `offline` | 对方不在线 | | `rate_limited` | 频率限制 | | `file_too_large` | 文件超限 | | `unsupported` | 不支持的格式 | | `upload_failed` | 上传失败 | | `internal` | 内部错误 | --- ## ping / pong ```json {"type": "ping"} {"type": "pong"} ``` 30s 间隔,90s 无响应断开。 --- ## 媒体传输流程 ### App 发文件给 Agent ``` 1. App HTTP POST /api/media/upload → { media_id, name, type, size } 2. App WS 发 file 消息 3. Bridge 收到 file 消息 → GET /media/{media_id} → 下载 → 传给 Hermes ``` ### Agent 返回文件给 App ``` 1. Hermes 产出文件 → Bridge 检测到 2. Bridge HTTP POST /api/media/upload → { media_id, ... } 3. Bridge WS 先发 stream_end 关闭文本流 4. Bridge WS 再发 file 消息携带 media_id 5. App 收到 file 消息 → GET /media/{media_id} 下载 ``` --- ## 重连 退避 `1s → 2s → 4s → 8s → 30s`,成功后重置。 --- ## 与旧协议对比 | | v1/v2 | v3 | |---|---|---| | 信封 | 嵌套 `{type, payload: {type, ...}}` 或 扁平不统一 | 统一 `{id, type, from, to, session, reply_to, ts, data}` | | 流式 | `stream_start`/`stream_chunk`/`stream_end` 三 type | `stream_start`/`stream`/`stream_end`,chunk 改名 stream | | 心跳 | `ping`/`pong` | `ping`/`pong` ✅ 不变 | | 冗余字段 | `chunk_index`、`total_chunks`、`is_markdown`、`final_content_hash` | 全部砍掉 | | 媒体 | 拆分 image/file/voice/video 四种 type | image/voice/video/file ✅ 保留 | | 会话管理 | `session` type 的 CRUD | 砍掉,App 本地管理 | | 链接 | 独立 `link` type | 砍掉,text 消息里直接发 URL |