# Cyrene Gateway API 文档 **版本:** v1 | **Base URL:** `http://:/api/v1` 所有需要认证的接口在 HTTP Header 中携带 JWT: ``` Authorization: Bearer ``` WebSocket 通过 query 参数传 token:`/ws/chat?token=` --- ## 目录 1. [认证](#1-认证) 2. [WebSocket 实时通信](#2-websocket-实时通信) 3. [会话管理](#3-会话管理) 4. [消息搜索](#4-消息搜索) 5. [语音 STT / TTS](#5-语音-stt--tts) 6. [文件管理](#6-文件管理) 7. [图片分析](#7-图片分析) 8. [知识库](#8-知识库) 9. [记忆管理](#9-记忆管理) 10. [自动化规则与场景](#10-自动化规则与场景) 11. [通知推送](#11-通知推送) 12. [提醒管理](#12-提醒管理) 13. [Webhook 第三方接入](#13-webhook-第三方接入) 14. [Admin 管理](#14-admin-管理) 15. [健康检查](#15-健康检查) --- ## 1. 认证 ### POST /auth/register — 注册 Auth: 无。IP 限流 ~5/min。仅 `REGISTRATION_ENABLED=true` 时可用(默认关闭)。 ```json // 请求 { "username": "string (3-32 chars, ^[a-zA-Z0-9_]+$)", "password": "string (6-64 chars)", "email": "string (需含 @)", "nickname": "string (1-32 chars)", "verify_code": "string (6 chars, 开发阶段固定 000000)" } // 响应 201 { "user_id": "user_", "token": "JWT", "refresh_token": "JWT (30天)", "expires": 1717000000, "nickname": "string" } ``` 错误: 400 `用户名格式无效`, 400 `邮箱格式无效`, 400 `验证码错误`, 403 `当前不开放公开注册`, 409 `用户名已被注册` --- ### POST /auth/login — 登录 Auth: 无。IP 限流 ~5/min。 管理员始终通过 `.env` 中的 `ADMIN_USERNAME` / `ADMIN_PASSWORD` 验证,不依赖数据库状态。普通用户通过数据库 bcrypt 密码哈希验证。 ```json // 请求 { "username": "string", "password": "string" } // 响应 200 { "user_id": "admin", // admin 用户固定为 "admin",普通用户为 "user_" "nickname": "string", "token": "JWT", "refresh_token": "JWT (30天)", "expires": 1717000000 } ``` 错误: 400 `用户名格式无效`, 401 `用户名或密码错误` --- ### POST /auth/refresh — 刷新 Token Auth: JWT(可接受已过期的 token,或在 body 中提供 refresh_token)。 ```json // 请求(可选) { "refresh_token": "string" } // 响应 200 { "token": "新 JWT", "refresh_token": "新 JWT (30天)", "expires": 1717000000 } ``` 错误: 401 `刷新令牌无效或已过期`, 401 `未提供认证令牌` --- ### GET /profile — 查询当前用户 Auth: JWT。根据 token 返回当前登录用户的信息。 ```json // 响应 200 (管理员) { "user_id": "admin", "username": "admin", "nickname": "管理员", "is_admin": true, "created_at": "2026-01-01T00:00:00Z" } // 响应 200 (普通用户) { "user_id": "user_alice", "username": "alice", "nickname": "Alice", "is_admin": false, "created_at": "2026-01-01T00:00:00Z" } ``` | 字段 | 类型 | 说明 | |------|------|------| | `user_id` | string | 用户 ID(admin 为 `"admin"`,普通用户为 `"user_"`) | | `username` | string | 用户名(管理员为 `.env` 中配置的 `ADMIN_USERNAME`) | | `nickname` | string | 显示昵称 | | `is_admin` | bool | 是否管理员 | | `created_at` | string | 注册时间 (RFC3339),数据库不可用时为 null | 错误: 401 `未提供认证令牌`, 404 `用户不存在` --- ## 2. WebSocket 实时通信 ### GET /ws/chat — 建立连接 ``` ws:///ws/chat?token=&session_id=&client_id=&device_name= ``` | Query 参数 | 必填 | 说明 | |-----------|------|------| | `token` | 是* | JWT(也可用 `Authorization: Bearer` header) | | `session_id` | 否 | 不传自动生成 `session_` + 12 随机字符 | | `client_id` | 否 | 多端标识 | | `device_name` | 否 | 设备名 | 注意:WebSocket 仅限 admin 用户;非 admin 收到 **403**。 --- ### 客户端 → 服务端 (ClientMessage) ```json { "type": "message|voice_input|ping|history", "session_id": "string (可选)", "mode": "text|voice_msg|voice_assistant", "content": "string (纯图片消息可留空,文字+图片时填写提问内容)", "audio_data": "string (voice_input 类型必填, base64)", "attachments": [ { "type": "image", "url": "string (base64 data URI, 旧格式, 向后兼容)", "file_id": "string (文件 UUID, 新格式推荐, 配合 POST /files/upload 使用)", "thumbnail_url": "string (缩略图 URL, 跨设备同步友好)", "filename": "string", "width": 0, "height": 0, "size": 0, "description": "string" } ], ``` > **图片附件两种格式**: > - **旧格式** (`url`): base64 data URI,直接内嵌于 WebSocket 消息中,简单但不适合跨设备同步。 > - **新格式(推荐)** (`file_id`): 先通过 [`POST /api/v1/files/upload`](#post-filesupload) 上传图片获取 `file_id` 和 `thumbnail_url`,消息中只携带轻量引用。Gateway 自动解析为本地文件 URL 传给 AI-Core。 ``` "timestamp": 1717000000000, "client_id": "string", "device_name": "string", "user_agent": "string" } ``` | type | 说明 | |------|------| | `message` | 文字聊天,触发 AI 回复 | | `voice_input` | 语音输入,先转录再作为 message 处理 | | `ping` | 心跳,自动回复 pong | | `history` | 请求历史消息 | --- ### 服务端 → 客户端 (ServerMessage) ```json { "type": "string (见下表)", "message_id": "string", "text": "string (完整文本)", "content": "string (增量文本/完整内容)", "role": "user|assistant|action|system", "msg_type": "chat|action|thinking|tool_progress|system_info|markdown|code (后端始终填充,前端无需自行解析)", "session_id": "string", "error": "string (仅错误时)", "timestamp": 1717000000000, "segments": [ { "index": 0, "text": "string", "audio_url": "string", "duration_ms": 0 } ], "messages": [ Message ], "thinking_status": "string", "thinking_content": "string", "tool_progress": { "tool_name": "string", "status": "started|running|completed|failed", "progress": 0.5, "message": "string" }, "system_info": { "level": "info|warning|error", "message": "string", "action": "string" }, "notification": { "id": "string", "type": "info|warning|success|thinking|reminder", "title": "string", "body": "string", "timestamp": "string", "data": {} }, "multi_message": { "messages": [ { "index": 0, "content": "string", "msg_type": "chat|action|system_info" } ] }, "review_messages": [ { "type": "action|chat|markdown|code|search_result", "content": "string", "delay_ms": 0, "metadata": { "language": "string (code 类型时)", "url": "string (search_result 类型时)" } } ], "client_info": { "client_id": "string", "device_name": "string", "user_agent": "string" }, "full_audio_url": "string", "response_mode": "string" } ``` ### ServerMessage type 列表 | type | 说明 | |------|------| | `response` | 完整文本回复 | | `stream_start` | AI 开始生成 | | `stream_chunk` | 增量文本块 | | `stream_end` | AI 生成结束(含完整 text) | | `stream_segments` | 流式断句(语音) | | `voice_transcript` | 语音转录结果 | | `error` | 错误 | | `history_response` | 历史消息返回 | | `notification` | 推送通知 | | `multi_message` | 多条消息合并投递 | | `review` | 审查后结构化消息 | | `thinking` | 后台思考更新 | | `tool_progress` | 工具执行进度 | | `system_info` | 系统级通知 | | `pong` | 响应 ping | | `device_update` | IoT 设备状态更新 | | `background_thinking` | 后台思考状态变更 | | `queued` | 消息已加入处理队列(会话繁忙时) | > **广播机制**:服务端推送分为两类: > - **用户消息回显**(`type: "response"`, `role: "user"`):通过 `SendToUserExcept` 广播,排除发送者自身(发送者本地已渲染),仅同步到同用户的其他设备。 > - **AI 回复消息**(`stream_start`、`stream_end`、`response`/`review`、`multi_message`、`stream_segments` 等 `role: "assistant"` 的消息):通过 `SendToUser` 广播给所有设备,包括发送者。 > **消息类型分类 (`msg_type`)**:所有 `response`、`multi_message`、`history_response`、`stream_chunk`、`thinking`、`tool_progress`、`system_info` 类型的服务端消息中,`msg_type` 字段均由后端自动分类填充,前端只需直接读取 `msg_type` 并据此渲染,无需解析消息内容来猜测类型。 > > `msg_type` 可选值: > - `chat` — 普通聊天消息 > - `action` — 动作/旁白消息(如 `昔涟轻轻推开窗户`),前端以斜体灰色样式渲染 > - `markdown` — Markdown 格式消息,前端使用安全渲染器转换后显示(支持标题、列表、表格、代码块、链接等) > - `code` — 独立代码块消息,前端以深色背景 + 语言标签渲染,可包含 `metadata.language` 指明编程语言 > - `thinking` — 后台思考过程,前端显示为可折叠详情块 > - `tool_progress` — 工具执行进度,前端显示进度条 > - `system_info` — 系统通知,前端居中显示为 toast 样式 > > **`review` 消息类型详情:** > > 当 AI 回复包含多种格式内容(如工具调用结果中的 Markdown 文档或代码片段)时,后端解析器将回复拆分为多条 `review_messages`,每条独立指定 `type` 和 `content`: > > - `action` — 动作/旁白文本,由 `...` XML 标签标记(向后兼容旧括号 `()` 和 `()` 格式),不做 Markdown 渲染,禁止断句拆分 > - `chat` — 普通聊天文本,可按句长断句 > - `markdown` — Markdown 格式文本,禁止断句拆分,前端使用安全渲染器(先 HTML 转义再转换 Markdown 语法) > - `code` — 代码块,禁止断句拆分,前端深色背景渲染,`metadata.language` 字段携带语言标识 > - `search_result` — 搜索工具调用结果摘要(后端内部使用,通常转为 `markdown` 或 `chat` 类型展示) > > Markdown 渲染器支持语法:标题 (h1-h6)、粗体/斜体、行内代码/围栏代码块、链接、图片、无序/有序列表、引用块、表格、水平线。 --- ### 流式响应流程 ``` Client Gateway AI-Core | | | |-- {type:"message"} --> | | | |-- POST /api/v1/chat --> | | | (SSE streaming) | | |<-- data: {delta:"..."} | |<-- {type:"stream_start"} | | |<-- {type:"review"} | (多条结构化消息) | |<-- {type:"stream_segments"} | (断句事件) | |<-- {type:"stream_end"} | (含 full text) | ``` ### 消息排队机制 同一会话的消息处理为串行化队列。若上一轮 AI 回复尚未完成时用户发送新消息,新消息会加入等待队列,并在当前处理完成后自动消费。 ``` Client Gateway | | |-- msg1 (type:"message") --> | |<-- {type:"stream_start"} | → AI-Core 处理中... | | |-- msg2 (type:"message") --> | |<-- {type:"queued"} | → 加入队列等待 | | |<-- {type:"stream_end"} (msg1) | → msg1 完成 |<-- {type:"stream_start"} (msg2) | → 自动取出 msg2 处理 |<-- ... | |<-- {type:"stream_end"} (msg2) | ``` > `queued` 消息表明用户消息已接收但尚未开始处理,客户端可据此显示"排队中"状态。 --- ### 语音输入流程 ``` Client Gateway Voice-Service | | | |-- {type:"voice_input", | | | audio_data:""} --> | | | |-- POST /transcribe --> | | |<-- {text:"..."} | |<-- {type:"voice_transcript", | | | text:"转录结果"} | | | | | | (Gateway 自动将转录文本 | | | 作为 message 发给 AI-Core) | | |<-- {type:"stream_start"} | | |<-- ... 正常流式回复 ... | | ``` --- ## 3. 会话管理 所有接口需要 JWT。Admin 可操作所有用户;非 admin 仅限自己的数据。 ### POST /sessions — 创建会话 ```json // 请求 (全部可选,空 body 也可) { "session_id": "string (可选,不传自动生成)", "title": "string (默认 '新的对话')", "is_main": false } // 响应 201 { "id": "string", "user_id": "string", "title": "string", "is_main": false, "created_at": 1717000000000, "updated_at": 1717000000000 } ``` ### GET /sessions — 列表 `?user_id=xxx` — admin 可查任意用户;非 admin 只能查自己。 ```json // 响应 200 { "sessions": [ Session, ... ] } ``` ### GET /sessions/:id — 详情 同 Session 结构。 错误: 404 `{"error":"会话不存在","errorType":"session_not_found","hint":"该会话可能已被删除或尚未创建"}` ### DELETE /sessions/:id — 删除 `{"status":"deleted"}` ### DELETE /sessions — 清空全部 `?user_id=xxx` → `{"status":"deleted"}` ### GET /sessions/:id/messages — 消息 `?limit=50&offset=0` ```json // 响应 200 { "messages": [ { "id": 1, "session_id": "string", "role": "user|assistant|system|action", "msg_type": "chat|action|markdown|code", "content": "string", "created_at": 1717000000000 } ] } ``` ### DELETE /sessions/:id/messages — 清空服务器本地所有消息 `{"status":"cleared"}` ### GET /sessions/:id/export — 导出 `?format=json|markdown|txt(默认 json)` 返回文件下载。JSON 导出格式: ```json { "session": { "id", "title", "created_at", "updated_at" }, "messages": [ { "role", "content", "created_at" } ] } ``` --- ## 4. 消息搜索 ### GET /messages/search — 全文搜索 `?q=&user_id=xxx&limit=50&offset=0` ```json // 响应 200 { "results": [ { "message_id": "string", "session_id": "string", "session_title": "string", "role": "string", "content": "string", "created_at": 1717000000000 } ], "total": 10, "query": "keyword", "limit": 50, "offset": 0 } ``` --- ## 5. 语音 STT / TTS ### POST /voice/transcribe — 语音转文字 Content-Type: `multipart/form-data`。字段 `audio` (file)。最大 10MB。接受 PCM/WAV/MP3/OGG/FLAC/WebM 等格式。 ```json // 响应 200 { "success": true, "text": "识别结果文本" } // 错误 { "success": false, "error": "语音识别失败: ..." } ``` ### POST /voice/tts — 文字转语音 Content-Type: `application/json`。 代理到 Voice-Service `POST /api/v1/tts/synthesize`。 ### GET /voice/tts/voices — 发音人列表 代理到 Voice-Service `GET /api/v1/tts/voices`。 ### GET /voice/tts/status — TTS 状态 ### GET /voice/status — 语音服务完整状态 (STT + TTS) Voice-Service 不可达时返回 502: ```json {"error":"Voice-Service 不可达: ...","errorType":"voice_service_unreachable"} ``` --- ## 6. 文件管理 ### POST /files/upload — 上传 Content-Type: `multipart/form-data`。字段 `file`。最大 20MB。 允许 MIME 类型:`image/jpeg,png,gif,webp,svg+xml` | `application/pdf,msword,vnd.openxmlformats-officedocument.wordprocessingml.document` | `text/plain,markdown` | `audio/mpeg,wav,ogg,webm` | `video/mp4,webm` ```json // 响应 201 { "id": "uuid", "filename": "string (脱敏后)", "mime_type": "string", "size": 1024, "url": "/api/v1/files//download" } ``` 错误: 400 `{"error":"文件大小超过限制 (最大 20MB)","errorType":"file_too_large"}`, 400 `{"error":"不支持的文件类型: ...","errorType":"unsupported_type"}` > **文件在 AI 对话中的传递链路(推荐新流程)**: > 1. **客户端**先调用 [`POST /api/v1/files/upload`](#post-filesupload) 上传图片,获得 `file_id` 和 `thumbnail_url` > 2. **客户端**发送消息时,`attachments` 中携带 `file_id`(轻量引用,不再内嵌 base64) > 3. **Gateway** 收到 `file_id` 后,从 `FileStore` 解析为本地下载 URL(`http://127.0.0.1:{port}/api/v1/files/{id}/download`) > 4. **AI-Core** 下载该 URL 并转为 base64 data URL,以多模态格式传给外部 LLM API > > **向后兼容**:`attachments[].url` 仍支持 base64 data URI或相对路径,Gateway 会将相对路径补全为绝对 URL。 ### GET /files — 列表 `?page=1&limit=20` ```json // 响应 200 { "files": [ { "id": "uuid", "user_id": "string", "filename": "string", "mime_type": "string", "size": 1024, "hash": "sha256hex", "is_public": false, "created_at": 1717000000000, "url": "string", "thumbnail_url": "string (仅图片)" } ], "total": 100, "page": 1, "limit": 20 } ``` ### GET /files/:id — 元数据 返回单个 File 对象。 ### GET /files/:id/download — 下载 文件流下载。404 → `{"error":"文件实体不存在(可能已被清理)","errorType":"file_missing"}` ### GET /files/:id/thumbnail — 缩略图 图片:JPEG 缩略图 (max 300x300)。非图片:SVG 占位图标。`Cache-Control: public, max-age=86400` ### DELETE /files/:id — 删除 `{"status":"deleted"}` --- ## 7. 图片分析 ### POST /images/analyze — 分析 两种方式: - **JSON:** `{"file_id": "uuid"}` — 分析已上传文件 - **Multipart:** 字段 `file` 或 `image` — 直接上传分析 (max 10MB),支持 JPEG/PNG/GIF ```json // 响应 200 { "format": "jpeg", "width": 1920, "height": 1080, "file_size": 204800, "description": "AI 生成的图片描述", "top_colors": [ { "hex": "#4A90D9", "percent": 35.2 } ], "exif": { "Make": "Canon" }, "analyzed_by": "openai_vision|local" } ``` ### GET /images/analyze/:file_id — 按已上传文件分析 同上。 --- ## 8. 知识库 ### POST /knowledge/bases — 创建知识库 ```json // 请求 { "name": "string (必填)", "description": "string" } // 响应 201 { "id": "uuid", "user_id": "string", "name": "string", "description": "string", "created_at": "...", "updated_at": "...", "doc_count": 0 } ``` ### GET /knowledge/bases — 列表 ```json { "knowledge_bases": [ KnowledgeBase ], "total": 10 } ``` ### GET /knowledge/bases/:id — 详情(含文档列表) ```json { "knowledge_base": KnowledgeBase, "documents": [ KnowledgeDocument ] } ``` ### PUT /knowledge/bases/:id — 更新 ```json { "name": "string (必填)", "description": "string" } → { "status": "updated" } ``` ### DELETE /knowledge/bases/:id — 删除 `{"status":"deleted"}` --- ### POST /knowledge/bases/:id/documents — 添加文档 ```json // 请求 { "title": "string (必填)", "content": "string (text 类型时)", "source_type": "text|file|url (默认 text)", "file_id": "string (file 类型必填)" } // 响应 201 { "id": "uuid", "kb_id": "string", "user_id": "string", "title": "string", "source_type": "string", "source_ref": "string", "content_type": "string", "raw_content": "string", "chunk_count": 5, "created_at": "...", "updated_at": "..." } ``` 注意:`source_type=file` 时 gateway 读取文件内容(仅支持文本类型和 `application/json`)。 ### GET /knowledge/bases/:id/documents — 文档列表 `{"documents": [ KnowledgeDocument ], "total": 10}` ### GET /knowledge/documents/:id — 文档详情(含分块) ```json { "document": KnowledgeDocument, "chunks": [ KnowledgeChunk ] } ``` ### DELETE /knowledge/documents/:id — 删除 `{"status":"deleted"}` --- ### POST /knowledge/search — 语义搜索 ```json // 请求 { "query": "string (必填)", "kb_ids": ["uuid"], // 可选,空=搜索全部 "limit": 5 // 1-50 } // 响应 200 { "chunks": [ SearchChunkResult ], "total": 5, "query": "string" } ``` --- ## 9. 记忆管理 代理到 Memory-Service。 ### GET /memory/search — 搜索 `?q=&user_id=xxx` → 代理到 Memory-Service `POST /memories/query` ### GET /memory — 列表 `?user_id=xxx` → 代理到 Memory-Service `GET /memories` ### POST /memory — 添加 ```json { "content": "string (必填)", "category": "string (默认 other)", "priority": 1 } ``` ### DELETE /memory — 删除 `?id=` Memory-Service 不可达时返回 502: ```json {"error":"Memory-Service 不可达: ...","errorType":"memory_service_unreachable"} ``` --- ## 10. 自动化规则与场景 ### 规则 #### GET /automation/rules — 列表 ```json { "rules": [ { "id": "32位hex", "user_id": "string", "name": "string", "description": "string", "trigger_type": "string", "trigger_config": {}, "conditions": {}, "actions": {}, "enabled": true, "created_at": "..." } ], "count": 5 } ``` #### POST /automation/rules — 创建 ```json // 请求 { "name": "string (必填)", "description": "string", "trigger_type": "string (必填)", "trigger_config": {}, "conditions": {}, "actions": {} (必填), "enabled": true } // 响应 201 → {"success": true, "rule": Rule} ``` #### GET /automation/rules/:id — 详情 `{"rule": Rule}` | 404 → `{"error":"规则不存在"}` #### PUT /automation/rules/:id — 更新 所有字段可选(partial update)。`{"success": true, "rule": Rule}` #### DELETE /automation/rules/:id — 删除 `{"success": true}` #### POST /automation/rules/:id/trigger — 手动触发 `{"success": true, "message": "规则已触发"}` --- ### 场景 #### GET /automation/scenes — 列表 `{"scenes": [ Scene ], "count": 5}` #### POST /automation/scenes — 创建 ```json { "name": "string (必填)", "icon": "string", "rule_ids": ["rule_id_1", "rule_id_2"] } → {"success": true, "scene": Scene} ``` #### GET /automation/scenes/:id — 详情 `{"scene": Scene}` #### PUT /automation/scenes/:id — 更新 所有字段可选。`{"success": true, "scene": Scene}` #### DELETE /automation/scenes/:id — 删除 `{"success": true}` #### POST /automation/scenes/:id/execute — 执行 `{"success": true, "message": "场景已执行"}` --- ## 11. 通知推送 ### POST /notifications/push — 推送通知 ```json // 请求 { "user_id": "string (必填)", "type": "info|warning|success|thinking|reminder (必填)", "title": "string (必填)", "body": "string (必填)", "data": {} } // 响应 200 { "success": true, "notification": { "id": "uuid", "type": "info", "title": "...", "user_id": "...", "timestamp": "2024-01-01T12:00:00Z", "delivered": true } } ``` delivered = true 表示目标用户有活跃 WebSocket 连接。 --- ## 12. 提醒管理 ### GET /reminders — 列表 `?user_id=xxx&status=pending|completed|cancelled&limit=50&offset=0` ```json // 响应 200 { "reminders": [ { "id": "string", "user_id": "string", "title": "string", "description": "string", "remind_at": "2024-01-01T15:00:00Z", "status": "pending", "repeat_type": "none|daily|weekly|monthly", "session_id": "string", "notified": false, "created_at": "...", "completed_at": null } ], "count": 5 } ``` ### POST /reminders — 创建 ```json // 请求 { "title": "string (必填)", "description": "string", "remind_at": "2024-01-01T15:00:00Z (必填, ISO 8601)", "repeat_type": "none|daily|weekly|monthly (默认 none)", "session_id": "string" } // 响应 201 { "success": true, "reminder": Reminder } ``` 错误: 400 `{"error":"时间格式无效,请使用 ISO 8601 格式 (例如 2024-01-01T15:00:00Z)"}` ### PUT /reminders/:id — 更新 所有字段可选 (partial update)。设置 `status=completed|cancelled` 会自动写入 `completed_at`。 `{"success":true, "reminder":Reminder}` | 404 `{"error":"提醒不存在"}` ### DELETE /reminders/:id — 删除 `{"success":true}` --- ## 13. Webhook 第三方接入 Auth: `X-Webhook-Key` header。 ### POST /webhook/generic — 通用 Webhook ```json // 请求 { "message": "string (必填)", "user_id": "string (默认 webhook_generic,自动加 ext_ 前缀)", "session_id": "string (默认 webhook_ + 12 随机字符)", "mode": "text|voice_msg (默认 text)", "platform": "string (默认 generic)" } // 响应 200 { "reply": "AI 回复文本", "session_id": "string", "message_id": "string", "finish_reason": "stop" } ``` 错误: 400 `{"error":"消息不能为空"}`, 502 `{"error":"AI 服务暂不可用: ..."}` ### POST /webhook/discord — Discord 交互 接收标准 Discord Interaction: - `type=1` (PING) → `{"type":1}` - `type=2` (APPLICATION_COMMAND) → 处理 `/chat message:` 命令 ```json // 响应 200 { "type": 4, "data": { "content": "AI 回复" } } ``` --- ## 14. Admin 管理 需要 JWT + admin 权限(`user_id == "admin"`)。非 admin 返回 **403**。 ### 会话管理 #### GET /admin/sessions — 活跃会话列表 ```json { "sessions": [ SessionState ], "total": 5 } ``` #### GET /admin/sessions/active — 按用户分组 ```json { "users": { "user_id": [ SessionState ] } } ``` #### GET /admin/sessions/:id — 指定会话详情 404 → `{"error":"会话不存在","errorType":"session_not_found"}` --- ### 客户端管理 #### GET /admin/clients — 已知客户端 `?user_id=admin` ```json { "clients": [ { "client_id": "string", "device_name": "string", "user_agent": "string", "note": "string", "last_seen": 1717000000000, "online": true } ], "total": 3 } ``` #### PUT /admin/clients/:id/note — 设置备注 ```json { "note": "string" } → { "status": "ok", "client_id": "string", "note": "string" } ``` 404 → `{"error":"客户端未找到"}` --- ### 模型配置管理 #### GET /admin/models/providers — Provider 列表 ```json { "providers": [ { "name": "string", "base_url": "string", "api_key": "string" } ], "total": 2 } ``` #### POST /admin/models/providers/:name — 创建/更新 Provider ```json { "name": "...", "base_url": "...", "api_key": "..." } → { "status": "saved", "name": "string" } ``` #### DELETE /admin/models/providers/:name — 删除 `{"status":"deleted","name":"string"}` #### GET /admin/models/models — Model 列表 ```json { "models": [ { "id": "string", "name": "string", "provider": "string", "description": "string", "priority": 1, "tags": [], "params": { "temperature": 0.7 }, "enabled": true, "updated_at": "..." } ], "total": 5 } ``` #### POST /admin/models/models/:id — 创建/更新 Model ```json { "id": "...", "name": "...", "provider": "...", "params": {}, ... } → { "status": "saved", "id": "string" } ``` #### DELETE /admin/models/models/:id — 删除 `{"status":"deleted","id":"string"}` #### GET /admin/models/routing — 路由规则列表 #### POST /admin/models/routing/:purpose — 创建/更新路由规则 ```json { "purpose": "...", "fallback_chain": ["model1", "model2"], "required": true } → { "status": "saved", "purpose": "string" } ``` #### DELETE /admin/models/routing/:purpose — 删除 #### POST /admin/models/health-check — 测试 Provider 连接 ```json { "provider": "string (必填)" } → { "provider": "string", "message": "Provider 配置已保存,连接测试请通过实际 LLM 调用验证" } ``` #### GET /admin/models/fetch-models/:name — 代理获取远程模型列表 `?url=` → 返回该 Provider 支持的模型列表。 --- ## 15. 健康检查 ### GET /health — 健康检查 Auth: 无。 ```json { "status": "ok", "service": "cyrene-gateway", "ws_connections": 3 } ``` --- ## 附录:错误格式 所有 API 错误统一为: ```json { "error": "错误描述", "errorType": "error_code (可选,客户端可据此判断)", "hint": "解决建议 (可选)" } ``` ### errorType 列表 | errorType | 含义 | |-----------|------| | `session_not_found` | 会话不存在 | | `file_too_large` | 文件超过大小限制 | | `unsupported_type` | 不支持的 MIME 类型 | | `file_missing` | 文件实体已清理 | | `memory_service_unreachable` | Memory-Service 不可达 | | `voice_service_unreachable` | Voice-Service 不可达 | | `admin_only` | 仅限管理员操作 | ### HTTP 状态码 | 状态码 | 场景 | |--------|------| | 200 | 成功 | | 201 | 创建成功 | | 400 | 请求参数错误 | | 401 | 未认证 / Token 无效 | | 403 | 无权限 | | 404 | 资源不存在 | | 409 | 资源冲突 (如用户名已存在) | | 413 | 请求体过大 | | 502 | 下游服务不可达 |