# 微信 AI 助手 API 接口设计 > 依据当前 `src/` 页面字段、数据结构和交互设计。本文定义目标契约,不表示这些接口已经实现。 > > 适用范围:单机 Windows、单个本地操作者、Tauri 桌面端、本机 SQLite 业务状态、本机 sidecar。默认不引入账号、租户、Workspace 或远程同步。 ## 1. 设计结论 ### 1.1 协议选择 | 场景 | 协议 | 原因 | |---|---|---| | 列表、详情、筛选、创建、更新、启停、删除、配置保存 | HTTP JSON | 一次请求对应一个确定结果,便于重试、校验、审计和错误处理 | | 文件上传 | HTTP `multipart/form-data`;大文件使用分片 HTTP | WebSocket 不适合传二进制大文件;HTTP 更容易限制大小、校验哈希和断点续传 | | 智能体测试流式回复 | WebSocket | 同一会话需要发送消息、接收 token 增量、完成或失败事件 | | 蒸馏任务进度 | WebSocket | 后台任务跨页面持续运行,需要实时阶段和进度事件 | | 引擎状态、启动检查、结构化日志 | WebSocket | 状态和日志持续产生,轮询会增加延迟和重复流量 | | 知识文件解析状态 | WebSocket | PDF、DOCX、PPT/PPTX 的文本提取可能耗时;图片和视频只做上传、校验及预览,不做自动识别 | | 标注截图、窗口选择、区域保存、桌面窗口控制 | Tauri IPC | 全程由本地 React/Tauri/Rust 处理,不进入 HTTP、WebSocket 或 Go 后端服务 | | 主题、当前 Tab、临时弹窗状态 | 前端本地状态 | 纯 UI 状态,不进入业务 API | ### 1.2 服务地址 - HTTP:`http://127.0.0.1:8766/api/v1` - WebSocket:`ws://127.0.0.1:8766/api/v1/ws?ticket={singleUseTicket}` - 现有视觉预览服务使用 `127.0.0.1:8765`,业务 API 使用 `8766`,避免端口冲突。 - 服务必须只监听 loopback,不监听局域网地址。 ### 1.3 安全边界 1. Tauri 启动 sidecar 时生成随机 `sessionToken`,HTTP 使用 `Authorization: Bearer {sessionToken}`。 2. WebSocket 不在 URL 中携带长期 token。前端先申请 30 秒有效、单次使用的 `ticket`。 3. 模型 API Key 进入系统密钥库;任何 GET 响应只返回 `keyConfigured`,不得返回明文或掩码后的原始值。 4. 日志禁止记录 API Key、完整系统提示词、无关聊天原文、剪贴板内容和本机绝对文件路径。 5. 所有资源更新使用 `revision` 做乐观并发控制;版本不匹配返回 `409 REVISION_CONFLICT`。 6. 删除知识库、智能体、员工等不可逆操作必须由前端二次确认,并在请求中传 `confirmation`。 --- ## 2. 通用规范 ### 2.1 数据格式 - JSON 字段统一使用 `camelCase`,与 React/Tauri 当前数据结构一致。 - 时间统一为 UTC RFC 3339,例如 `2026-07-21T08:30:15.238Z`。 - 文件大小统一为整数 `sizeBytes`,`KB/MB` 仅由前端格式化。 - 比率统一为 `0~1` 小数,例如 `successRate: 0.984`;分数使用 `0~100`。 - ID 不使用名称,建议前缀:`kb_`、`kv_`、`file_`、`agent_`、`employee_`、`distill_`、`test_`、`log_`。 - 列表使用 cursor 分页;页面当前数据量虽小,接口仍保持可扩展。 ### 2.2 成功响应 ```json { "data": {}, "meta": { "requestId": "req_01J3...", "nextCursor": null, "total": 6 } } ``` - 单资源接口可省略 `nextCursor` 和 `total`。 - `204 No Content` 用于成功删除且无响应体的场景。 ### 2.3 错误响应 ```json { "error": { "code": "VALIDATION_ERROR", "message": "请求字段校验失败", "retryable": false, "fieldErrors": { "title": "知识标题不能为空" }, "details": null }, "requestId": "req_01J3..." } ``` 常用状态码和错误码: | HTTP | code | 含义 | |---:|---|---| | 400 | `VALIDATION_ERROR` | 字段格式、枚举或业务前置条件错误 | | 401 | `UNAUTHORIZED` | 本机 session token 无效或过期 | | 404 | `NOT_FOUND` | 资源不存在或已删除 | | 409 | `REVISION_CONFLICT` | 乐观锁版本冲突 | | 409 | `STATE_CONFLICT` | 当前状态不允许该操作 | | 413 | `FILE_TOO_LARGE` | 文件超过用途限制 | | 415 | `UNSUPPORTED_FILE_TYPE` | 文件扩展名、MIME 或内容签名不受支持 | | 422 | `FILE_PARSE_FAILED` | 文件上传成功但无法解析 | | 429 | `RATE_LIMITED` | 模型或任务并发达到限制 | | 500 | `INTERNAL_ERROR` | 未分类内部错误 | | 502 | `MODEL_UPSTREAM_ERROR` | 模型供应商错误 | | 504 | `MODEL_TIMEOUT` | 模型调用超时 | ### 2.4 列表参数 ```text ?query=退款&status=enabled&type=file&limit=20&cursor=eyJpZCI6... ``` | 参数 | 类型 | 默认 | 说明 | |---|---|---:|---| | `query` | string | `""` | 名称、标签或正文关键字,最大 100 字 | | `status` | string | `all` | 各资源定义的状态枚举 | | `limit` | integer | 20 | `1~100` | | `cursor` | string | 无 | 服务端返回的游标,不允许客户端解析 | | `sort` | string | `updatedAt:desc` | 白名单排序字段与方向 | ### 2.5 幂等性 以下 POST 请求必须携带 `Idempotency-Key`: - 创建知识库草稿、发布知识版本; - 创建智能体、发送测试消息; - 创建蒸馏任务、发布员工; - 启动或停止引擎。 服务端在 24 小时内对相同 key 和相同请求体返回首次结果;同 key 不同请求体返回 `409 IDEMPOTENCY_CONFLICT`。 --- ## 3. 核心数据对象 ### 3.1 FileAsset ```json { "id": "file_01J3...", "purpose": "knowledge_source", "fileName": "refund-policy.pdf", "contentType": "application/pdf", "extension": "pdf", "sizeBytes": 2516582, "sha256": "6fe1...", "kind": "text", "status": "ready", "parseStatus": "completed", "extractedTextLength": 12680, "convertedTextFileId": "filetxt_01J3...", "warnings": [ { "code": "EMBEDDED_IMAGES_SKIPPED", "message": "文档中的 3 张图片已省略" } ], "error": null, "previewStatus": "ready", "description": null, "descriptionSource": null, "createdAt": "2026-07-21T08:30:15.238Z" } ``` 枚举: - `purpose`: `knowledge_source | agent_test_attachment | distill_source | report_export` - `kind`: `text | image | video | binary` - `status`: `uploading | uploaded | processing | ready | failed | deleted` - `parseStatus`: `not_required | queued | processing | completed | failed` - `previewStatus`: `none | processing | ready | failed` - `descriptionSource`: 当前只允许 `manual | null`,禁止返回 `ai | ocr | vision` 图片或视频知识文件示例: ```json { "id": "file_01J4...", "purpose": "knowledge_source", "fileName": "refund-process.png", "contentType": "image/png", "extension": "png", "sizeBytes": 356240, "sha256": "7a2d...", "kind": "image", "status": "ready", "parseStatus": "not_required", "extractedTextLength": 0, "convertedTextFileId": null, "warnings": [], "error": null, "previewStatus": "ready", "description": "退款申请、审核和到账三个步骤的流程图。", "descriptionSource": "manual", "createdAt": "2026-07-21T08:31:15.238Z" } ``` ### 3.2 KnowledgeSummary ```json { "id": "kb_refund", "title": "售后常见问题与退款边界", "type": "file", "tags": ["售后", "退款"], "status": "enabled", "currentVersion": "v1.7", "referenceCount": 82, "fileCount": 4, "updatedAt": "2026-06-05T01:42:00Z", "revision": 7 } ``` - `type`: `file | image | video | mixed` - `status`: `draft | processing | enabled | disabled | failed` ### 3.3 AgentSummary ```json { "id": "agent_intent", "name": "客户意图识别", "type": "builtin", "enabled": true, "version": "v2.1", "tags": ["线索分级", "异议判断", "下一步建议"], "knowledgeCount": 3, "recentCallCount": 16, "lastTestStatus": "passed", "updatedAt": "2026-06-16T10:20:00Z", "revision": 4 } ``` - `type`: `builtin | custom` - `lastTestStatus`: `not_run | running | passed | failed` ### 3.4 DistillJobSummary ```json { "id": "distill_01J3...", "name": "销售冠军 Aileen 话术蒸馏", "state": "extracting", "stage": "strategy_extraction", "progress": 0.72, "estimatedRemainingSeconds": 180, "sourceCount": 1, "successCount": 248, "failedCount": 7, "createdAt": "2026-07-21T08:30:15.238Z", "updatedAt": "2026-07-21T08:34:10.000Z", "revision": 9 } ``` - `state`: `draft | queued | extracting | evaluating | ready_to_publish | completed | cancelled | failed` - `stage`: `source_validation | data_cleaning | scene_clustering | strategy_extraction | boundary_induction | counterexample_generation | evaluation | completed` ### 3.5 EmployeeSummary ```json { "id": "employee_1", "name": "销售冠军 Aileen", "version": "v3.2", "enabled": true, "traits": ["高意向逼单", "异议拆解", "温和推进"], "domain": "private_sales", "score": 96, "weeklyCallCount": 28, "updatedAt": "2026-06-18T09:00:00Z", "revision": 3 } ``` --- ## 4. 应用初始化与实时连接 ### 4.1 获取启动数据 `GET /bootstrap` 请求:无 body。 响应: ```json { "data": { "apiVersion": "1.0", "serverVersion": "0.1.0", "platform": "windows", "capabilities": { "knowledge": true, "agents": true, "distillation": true, "engine": true, "nativeAnnotation": true }, "engineState": { "lifecycle": "idle", "autoSendPaused": false, "annotationComplete": true, "updatedAt": "2026-07-21T08:30:15.238Z" }, "badges": { "clone": 3, "knowledge": 0, "agents": 1, "distill": 0 } } } ``` 用途:主窗口一次请求获得能力开关、引擎初始状态和底部 Tab badge。主题仍存本地,不进入接口。 ### 4.2 申请 WebSocket ticket `POST /realtime-tickets` 请求: ```json { "clientId": "desktop-main-7cb8", "lastEventId": "evt_01J3...", "subscriptions": ["engine", "logs", "distill:distill_01J3", "files:file_01J3"] } ``` 字段: | 字段 | 类型 | 必填 | 说明 | |---|---|---:|---| | `clientId` | string | 是 | 每个窗口唯一,最大 64 字 | | `lastEventId` | string/null | 否 | 断线续传起点 | | `subscriptions` | string[] | 否 | 初始订阅频道,最多 50 个 | 响应: ```json { "data": { "ticket": "wst_01J3...", "webSocketUrl": "ws://127.0.0.1:8766/api/v1/ws?ticket=wst_01J3...", "expiresAt": "2026-07-21T08:30:45.238Z", "heartbeatSeconds": 20 } } ``` --- ## 5. 微信分身、引擎与日志 ### 5.1 引擎状态 `GET /engine/state` 响应 `EngineState`: ```json { "data": { "lifecycle": "running", "agent": "running", "visionStream": "running", "wechatWindow": "connected", "annotationComplete": true, "autoSendPaused": false, "activeConversationId": null, "consecutiveErrors": 0, "lastError": null, "startedAt": "2026-07-21T08:30:15.238Z", "updatedAt": "2026-07-21T08:30:18.000Z", "revision": 12 } } ``` 枚举: - `lifecycle`: `idle | checking | starting | running | stopping | error` - `agent` / `visionStream`: `stopped | starting | running | error` - `wechatWindow`: `unknown | connected | missing | changed` ### 5.2 执行启动检查 `POST /engine/startup-checks` 请求: ```json { "forceRefresh": true } ``` 响应 `202 Accepted`: ```json { "data": { "runId": "check_01J3...", "state": "running", "checks": [ { "id": "config", "label": "基础配置", "status": "waiting", "passed": null, "detail": null }, { "id": "annotation", "label": "界面标注", "status": "waiting", "passed": null, "detail": null }, { "id": "window", "label": "微信窗口连接情况", "status": "waiting", "passed": null, "detail": null } ] } } ``` 后续通过 `engine.startup_check.updated` WS 事件返回逐项状态;最终结果也可通过 `GET /engine/startup-checks/{runId}` 查询。 ### 5.3 启动引擎 `POST /engine/start` 请求: ```json { "startupCheckRunId": "check_01J3...", "expectedRevision": 12 } ``` 响应 `202 Accepted`:返回最新 `EngineState`。若检查未通过,返回 `409 STARTUP_CHECK_FAILED`,`details.failedCheckIds` 指明失败项。 ### 5.4 停止引擎 `POST /engine/stop` 请求: ```json { "expectedRevision": 13, "reason": "operator_request" } ``` 响应 `202 Accepted`:返回 `lifecycle: "stopping"` 的 `EngineState`,最终状态通过 WS 推送。 ### 5.5 暂停或恢复自动发送 `PATCH /engine/auto-send` 请求: ```json { "paused": true, "expectedRevision": 14 } ``` 响应:返回最新 `EngineState`。当前界面的“暂停自动发送/恢复自动发送”直接绑定此接口。 ### 5.6 日志列表 `GET /logs?level=warning&module=model&query=req_91fa&limit=100&cursor=...` 响应: ```json { "data": { "items": [ { "id": "log_01J3...", "time": "2026-07-21T08:30:15.238Z", "level": "warning", "module": "model", "message": "model gateway latency is higher than expected", "requestId": "req_91fa", "context": { "fromSnapshotId": "snapshot_9821", "toSnapshotId": "snapshot_9822" } } ] }, "meta": { "requestId": "req_...", "nextCursor": null, "total": 1 } } ``` - `level`: `info | warning | error` - `module`: `agent | vision | capture | retriever | model | policy | sender` 暂停接收仅停止当前窗口的 WS 消费,不调用后端、不暂停引擎。清空视图只清前端缓存,不删除审计日志。 ### 5.7 导出日志 `POST /logs/exports` 请求: ```json { "filter": { "level": "all", "module": "all", "query": "" }, "format": "jsonl", "from": "2026-07-20T00:00:00Z", "to": "2026-07-21T23:59:59Z" } ``` 响应 `202 Accepted`: ```json { "data": { "exportId": "export_01J3...", "status": "processing", "fileId": null } } ``` 完成后发送 `export.completed`,payload 中提供 `fileId`;前端调用 `GET /files/{fileId}/content` 下载。 --- ## 6. 文件上传、解析与预览 ### 6.1 用途限制 | purpose | 支持格式 | 单文件限制 | 数量限制 | |---|---|---:|---:| | `agent_test_attachment` | PDF、DOCX、PPT、PPTX、TXT、MD、CSV、JSON | 20 MB | 每条消息最多 5 个 | | `knowledge_source` | TXT、PDF、DOCX、PPT、PPTX、PNG、JPG/JPEG、GIF、WEBP、MP4、WEBM、MOV | 文档/图片 100 MB;视频 2 GB | 每个草稿最多 100 个 | | `distill_source` | TXT、MD、CSV、JSON、PDF、DOCX、PPT、PPTX | 500 MB | 每个任务最多 50 个 | 服务端必须同时校验扩展名、MIME 和文件头;不能只信任浏览器提交的 `contentType`。 知识文件首期处理边界: 1. TXT 按 UTF-8 规范化保存;PDF 只提取已有文本层;DOCX 提取段落和表格文字;PPT/PPTX 提取文本框、表格和备注文字。 2. 文档中的嵌入图片直接省略,不调用 OCR、视觉模型或图片理解。 3. 图片和视频可以作为独立知识来源上传、保存和预览,但不执行 OCR、图片理解、视频理解、ASR、关键帧提取或自动摘要。 4. 图片和视频的 `description` 只能由操作者人工填写,`descriptionSource` 固定为 `manual`;后端不得自动生成或补全描述。 5. 媒体文件有人工描述时,知识检索只索引标题、标签和人工描述;没有描述时只索引标题和标签,原始媒体内容不进入文本检索。 6. 扫描版 PDF 或只有图片、没有可提取文字的 Office 文档返回 `422 NO_EXTRACTABLE_TEXT`,不能标记为文档转换成功。 7. 文档转换结果生成独立 UTF-8 `.txt` 文件,并通过 `convertedTextFileId` 关联原文件;知识版本正文由转换后的 TXT 和媒体人工描述组成。 ### 6.2 小文件直接上传 `POST /files` Content-Type:`multipart/form-data` 表单字段: | 字段 | 类型 | 必填 | 说明 | |---|---|---:|---| | `file` | binary | 是 | 文件内容 | | `purpose` | enum | 是 | 上述用途 | | `clientFileId` | string | 是 | 前端本次选择生成的 UUID,用于去重 | | `sha256` | string | 否 | 客户端可计算时传入 | 响应 `201 Created`:返回 `FileAsset`。文本类文件通常返回 `parseStatus: "queued"`,不能把上传成功展示成解析成功。 ### 6.3 大文件分片初始化 `POST /file-uploads` 请求: ```json { "purpose": "knowledge_source", "fileName": "product-training.mp4", "contentType": "video/mp4", "sizeBytes": 734003200, "sha256": "可选整体哈希", "clientFileId": "8fb2a9e5-..." } ``` 响应: ```json { "data": { "uploadId": "upload_01J3...", "chunkSizeBytes": 8388608, "uploadedParts": [], "expiresAt": "2026-07-22T08:30:15.238Z" } } ``` ### 6.4 上传分片 `PUT /file-uploads/{uploadId}/parts/{partNumber}` Headers: ```text Content-Type: application/octet-stream Content-Length: 8388608 Content-Range: bytes 0-8388607/734003200 X-Chunk-SHA256: 1c9e... ``` 响应: ```json { "data": { "partNumber": 1, "sizeBytes": 8388608, "sha256": "1c9e...", "accepted": true } } ``` 重复上传同一分片且哈希相同必须幂等;哈希不同返回 `409 CHUNK_CONFLICT`。 ### 6.5 完成分片上传 `POST /file-uploads/{uploadId}/complete` 请求: ```json { "parts": [ { "partNumber": 1, "sha256": "1c9e..." }, { "partNumber": 2, "sha256": "41af..." } ] } ``` 响应 `201 Created`:返回 `FileAsset`。 ### 6.6 查询和取消上传 - `GET /file-uploads/{uploadId}`:返回已上传分片,用于断点续传。 - `DELETE /file-uploads/{uploadId}`:删除临时分片,返回 `204`。 ### 6.7 查询文件 `GET /files/{fileId}`:返回 `FileAsset`。 文件解析过程通过 WS 推送 `file.processing.updated`: ```json { "fileId": "file_01J3...", "status": "processing", "parseStatus": "processing", "progress": 0.64, "stage": "extracting_text", "extractedTextLength": 0, "error": null } ``` ### 6.8 文档转换与媒体预览 - `GET /files/{fileId}/text?offset=0&limit=20000`:分页预览文档转换后的纯文本。 - `GET /files/{fileId}/text-file`:下载 UTF-8 `.txt` 转换结果,响应为 `text/plain; charset=utf-8`。 - `GET /files/{fileId}/content`:下载原文件或预览图片、视频;支持 `Range`。 - `PATCH /files/{fileId}`:只用于操作者保存图片或视频的人工描述。 文档转换规则: - PDF 只读取文本层,不对页面截图或扫描内容执行 OCR。 - DOCX 中的段落、表格文本按文档顺序输出;图片、形状内不可直接读取的图像文字省略。 - PPT/PPTX 中的文本框、表格和备注按页输出;每页使用稳定页码分隔,图片内容省略。 - 成功提取到正文但省略了图片时,`parseStatus` 为 `completed`,同时返回 `EMBEDDED_IMAGES_SKIPPED` warning。 - 没有任何可提取正文时,`parseStatus` 为 `failed`,`error.code` 为 `NO_EXTRACTABLE_TEXT`。 媒体处理规则: - 图片、视频上传完成并通过文件安全校验后,`parseStatus` 固定为 `not_required`。 - 服务端只生成安全预览能力,不识别画面、不抽取文字、不识别语音、不生成描述。 - `description` 完全来自人工输入,服务端原样保存;空描述允许保存,但媒体内容本身不会进入 FTS5 正文索引。 `PATCH /files/{fileId}` 请求: ```json { "description": "退款申请、审核和到账三个步骤的流程图。", "descriptionSource": "manual", "expectedRevision": 1 } ``` 服务端必须拒绝 `descriptionSource` 不是 `manual` 的请求;响应返回最新 `FileAsset`。 文本响应: ```json { "data": { "fileId": "file_01J3...", "text": "第一章 退款申请范围……", "offset": 0, "returnedLength": 12680, "totalLength": 12680, "truncated": false } } ``` ### 6.9 删除文件 `DELETE /files/{fileId}?expectedRevision=1` - 未绑定草稿或消息时返回 `204`。 - 已被已发布版本引用时返回 `409 FILE_IN_USE`,不能物理删除。 --- ## 7. 知识库接口 ### 7.1 知识库列表与全文搜索 `GET /knowledge-bases?query=退款&status=all&limit=20&cursor=...` 响应:`data.items: KnowledgeSummary[]`。 搜索范围由设置中的 `knowledgeSearchFields` 决定;页面输入“标题、标签或完整正文”时,服务端返回匹配后的知识库摘要,不把完整正文放进列表响应。 ### 7.2 创建草稿 `POST /knowledge-drafts` 请求: ```json { "mode": "create", "knowledgeId": null, "baseVersion": null, "title": "售后退款政策", "description": "用于回答售后退款范围、异常订单与客户安抚相关问题。", "tags": ["私域成交", "售后"] } ``` 更新知识库时: ```json { "mode": "update", "knowledgeId": "kb_refund", "baseVersion": "v1.7" } ``` 响应: ```json { "data": { "id": "kbdraft_01J3...", "mode": "create", "knowledgeId": null, "baseVersion": null, "title": "售后退款政策", "description": "用于回答……", "tags": ["私域成交", "售后"], "fileIds": [], "state": "draft", "revision": 1, "updatedAt": "2026-07-21T08:30:15.238Z" } } ``` ### 7.3 保存草稿基本信息 `PATCH /knowledge-drafts/{draftId}` 请求: ```json { "title": "售后退款政策", "description": "用于回答售后问题。", "tags": ["私域成交", "售后"], "expectedRevision": 1 } ``` 校验:`title` 1~100 字;`description` 最大 2000 字;标签最多 20 个,每个 1~30 字,去重后保存。 响应:返回完整草稿和递增后的 `revision`。 ### 7.4 绑定或移除来源文件 `POST /knowledge-drafts/{draftId}/files` ```json { "fileIds": ["file_01J3...", "file_01J4..."], "expectedRevision": 2 } ``` 响应: ```json { "data": { "draftId": "kbdraft_01J3...", "files": [{ "id": "file_01J3...", "fileName": "refund-policy.pdf", "sizeBytes": 2516582, "kind": "text", "status": "ready", "parseStatus": "completed" }], "readyCount": 1, "processingCount": 1, "failedCount": 0, "revision": 3 } } ``` `DELETE /knowledge-drafts/{draftId}/files/{fileId}?expectedRevision=3`:从草稿移除,返回更新后的文件汇总。 ### 7.5 草稿预览汇总 `GET /knowledge-drafts/{draftId}/preview` 响应: ```json { "data": { "draftId": "kbdraft_01J3...", "sourceCount": 3, "ready": true, "files": [{ "id": "file_01J3...", "fileName": "refund-policy.pdf", "sizeBytes": 2516582, "kind": "text", "status": "ready", "parseStatus": "completed" }], "totalTextLength": 26000, "blockingErrors": [] } } ``` `ready` 只有在至少一个来源且所有必需解析完成时为 `true`。 ### 7.6 发布知识库或保存新版本 `POST /knowledge-drafts/{draftId}/publish` 请求: ```json { "versionNote": "补充异常订单处理边界", "enableAfterPublish": true, "expectedRevision": 4 } ``` 响应 `201 Created`: ```json { "data": { "knowledge": { "id": "kb_refund", "title": "售后常见问题与退款边界", "type": "file", "tags": ["售后", "退款"], "status": "enabled", "currentVersion": "v1.8", "referenceCount": 0, "fileCount": 1, "updatedAt": "2026-07-21T08:40:00Z", "revision": 1 }, "version": { "id": "kv_01J3...", "knowledgeId": "kb_refund", "version": "v1.8", "versionNote": "补充异常订单处理边界", "fileIds": ["file_01J3..."], "textLength": 26000, "contentHash": "5c82...", "createdAt": "2026-07-21T08:40:00Z" } } } ``` 版本号由服务端生成,客户端不得自行加一。若 `baseVersion` 已落后,返回 `409 REVISION_CONFLICT`。 ### 7.7 知识库详情 `GET /knowledge-bases/{knowledgeId}` 响应: ```json { "data": { "id": "kb_refund", "title": "售后常见问题与退款边界", "description": "涵盖退款期限、数字商品限制、异常订单处理和安抚话术边界。", "tags": ["售后", "退款"], "type": "file", "status": "enabled", "currentVersion": "v1.7", "creator": { "id": "local_operator", "displayName": "本机管理员" }, "effectiveAt": "2026-06-05T01:42:00Z", "lastRetrievedAt": "2026-07-21T08:18:00Z", "metrics": { "weeklyHitCount": 32, "agentReferenceCount": 3, "employeeBindingCount": 2, "textLength": 26000 }, "revision": 7, "updatedAt": "2026-06-05T01:42:00Z" } } ``` ### 7.8 详情子资源 - `GET /knowledge-bases/{id}/files`:当前版本的 `FileAsset[]`。 - `GET /knowledge-bases/{id}/references?type=all`:引用关系。 - `GET /knowledge-bases/{id}/versions?limit=20&cursor=...`:版本历史。 引用关系项: ```json { "resourceType": "agent", "resourceId": "agent_quote", "name": "报价策略生成", "enabled": true, "boundVersion": "v1.7" } ``` 版本项: ```json { "id": "kv_01J3...", "version": "v1.7", "versionNote": "修正数字商品退款边界", "isCurrent": true, "createdAt": "2026-06-05T01:42:00Z" } ``` ### 7.9 启停和删除 `PATCH /knowledge-bases/{id}/status` ```json { "enabled": false, "expectedRevision": 7 } ``` 响应:返回最新 `KnowledgeSummary`。停用后已绑定关系保留,但检索时不能命中。 `DELETE /knowledge-bases/{id}` ```json { "confirmation": "售后常见问题与退款边界", "expectedRevision": 8 } ``` 有引用关系时默认返回 `409 RESOURCE_IN_USE` 和引用摘要;不提供静默级联删除。 --- ## 8. 智能体接口 ### 8.1 列表 `GET /agents?query=报价&type=all&enabled=all&limit=20&cursor=...` 响应:`data.items: AgentSummary[]`。 筛选枚举:`type=all|builtin|custom`,`enabled=all|true|false`。 ### 8.2 创建智能体草稿 `POST /agent-drafts` 请求: ```json { "mode": "create", "agentId": null, "name": "报价策略生成", "description": "根据客户意向、商品成本和优惠边界生成报价建议。", "tags": ["利润保护", "阶梯报价", "优惠边界"] } ``` 更新模式传 `mode: "update"` 和 `agentId`。响应: ```json { "data": { "id": "agentdraft_01J3...", "mode": "create", "agentId": null, "name": "报价策略生成", "description": "根据客户意向……", "tags": ["利润保护", "阶梯报价", "优惠边界"], "systemPrompt": "", "knowledgeIds": [], "lastTestSessionId": null, "lastTestStatus": "not_run", "revision": 1 } } ``` ### 8.3 保存基本信息、提示词和授权 `PATCH /agent-drafts/{draftId}` 请求可部分更新: ```json { "name": "报价策略生成", "description": "根据客户意向、商品成本和优惠边界生成报价建议。", "tags": ["利润保护", "阶梯报价", "优惠边界"], "systemPrompt": "你是报价策略助手……", "knowledgeIds": ["kb_price", "kb_discount"], "expectedRevision": 1 } ``` 校验:名称 1~80 字;描述最大 2000 字;标签最多 20 个;系统提示词最大 20000 字;只能授权已生效知识库。 响应:返回完整草稿和新 `revision`。 ### 8.4 发布或更新智能体 `POST /agent-drafts/{draftId}/publish` 请求: ```json { "releaseNote": "首次发布报价策略生成智能体。", "enableAfterPublish": true, "expectedRevision": 3 } ``` 前置条件:`lastTestStatus` 必须为 `passed`,且测试使用的 `draftRevision` 必须等于当前草稿 revision;提示词或授权变更后旧测试失效。 响应: ```json { "data": { "agent": { "id": "agent_quote", "name": "报价策略生成", "type": "custom", "enabled": true, "version": "v1.0", "tags": ["利润保护", "阶梯报价", "优惠边界"], "knowledgeCount": 2, "recentCallCount": 0, "lastTestStatus": "passed", "updatedAt": "2026-07-21T08:50:00Z", "revision": 1 }, "release": { "version": "v1.0", "releaseNote": "首次发布报价策略生成智能体。", "createdAt": "2026-07-21T08:50:00Z" } } } ``` ### 8.5 详情 `GET /agents/{agentId}` 响应: ```json { "data": { "id": "agent_intent", "name": "客户意图识别", "type": "builtin", "enabled": true, "version": "v2.1", "description": "识别客户所处阶段、购买意向、核心异议,并输出下一步跟进建议。", "tags": ["线索分级", "异议判断", "下一步建议"], "systemPrompt": "你是报价策略助手……", "permissions": [ { "code": "knowledge.query", "label": "查询知识库", "granted": true }, { "code": "conversation.read_current", "label": "读取当前会话", "granted": true }, { "code": "message.send", "label": "直接发送消息", "granted": false } ], "knowledge": [ { "id": "kb_refund", "title": "售后退款政策", "version": "v1.7", "enabled": true } ], "metrics": { "recentCallCount": 16, "successRate": 0.984, "averageLatencyMs": 1200, "knowledgeCount": 3 }, "updatedAt": "2026-06-16T10:20:00Z", "revision": 4 } } ``` ### 8.6 权限和测试记录 - `GET /agents/{id}/permissions`:返回上述 `permissions` 和 `knowledge`。 - `GET /agents/{id}/test-records?limit=20&cursor=...`。 测试记录项: ```json { "id": "test_01J3...", "scenario": "高意向询价", "status": "passed", "latencyMs": 1200, "draftRevision": 3, "createdAt": "2026-06-18T09:30:00Z", "error": null } ``` ### 8.7 启停和删除 `PATCH /agents/{id}/status` ```json { "enabled": false, "expectedRevision": 4 } ``` `DELETE /agents/{id}` ```json { "confirmation": "客户意图识别", "expectedRevision": 5 } ``` 内置智能体可按产品规则返回 `403 BUILTIN_AGENT_READ_ONLY`;若允许删除,必须明确为隐藏/禁用而非物理删除。 --- ## 9. 智能体测试会话与 WebSocket 流式回复 ### 9.1 创建测试会话 `POST /agent-test-sessions` 请求: ```json { "agentId": "agent_intent", "draftId": null, "draftRevision": null, "mode": "published" } ``` 编辑器沙箱传: ```json { "agentId": null, "draftId": "agentdraft_01J3...", "draftRevision": 3, "mode": "draft" } ``` 响应: ```json { "data": { "sessionId": "testsession_01J3...", "state": "ready", "channel": "agent-test:testsession_01J3...", "maxFilesPerMessage": 5, "maxFileSizeBytes": 20971520, "acceptedExtensions": ["pdf", "docx", "ppt", "pptx", "txt", "md", "csv", "json"], "expiresAt": "2026-07-21T10:00:00Z" } } ``` ### 9.2 发送测试消息 使用 WebSocket command,不把文件二进制放进 WS。附件必须先通过 `POST /files` 上传。 ```json { "type": "agent.test.message.send", "requestId": "client_req_8", "payload": { "sessionId": "testsession_01J3...", "clientMessageId": "bce8e547-...", "content": "客户预算为 10000 元,可以如何报价?", "fileIds": ["file_01J3..."] } } ``` 校验:`content` 与 `fileIds` 至少一个非空;内容最大 20000 字;附件最多 5 个;附件 purpose 必须为 `agent_test_attachment` 且解析完成。 服务端事件顺序: 1. `agent.test.message.accepted` 2. 零到多个 `agent.test.message.delta` 3. `agent.test.message.completed` 或 `agent.test.message.failed` accepted: ```json { "sessionId": "testsession_01J3...", "messageId": "msg_01J3...", "clientMessageId": "bce8e547-...", "assistantMessageId": "msg_01J4...", "acceptedAt": "2026-07-21T08:55:00Z" } ``` delta: ```json { "sessionId": "testsession_01J3...", "assistantMessageId": "msg_01J4...", "sequence": 7, "delta": "建议先核对", "accumulatedLength": 28 } ``` completed: ```json { "sessionId": "testsession_01J3...", "assistantMessageId": "msg_01J4...", "content": "建议先核对客户需求……", "finishReason": "stop", "usage": { "inputTokens": 412, "outputTokens": 96 }, "latencyMs": 1320, "testResult": { "status": "passed", "draftRevision": 3, "warnings": [] }, "completedAt": "2026-07-21T08:55:01.320Z" } ``` failed: ```json { "sessionId": "testsession_01J3...", "assistantMessageId": "msg_01J4...", "code": "MODEL_TIMEOUT", "message": "模型在 8000ms 内未返回", "retryable": true } ``` ### 9.3 历史与取消 - `GET /agent-test-sessions/{sessionId}/messages?limit=100&cursor=...`:恢复弹窗后的对话。 - WS command `agent.test.generation.cancel`:`{ sessionId, assistantMessageId }`。 - `DELETE /agent-test-sessions/{sessionId}`:结束会话并清理未引用测试附件。 消息对象: ```json { "id": "msg_01J3...", "role": "user", "content": "客户预算为 10000 元", "files": [ { "id": "file_01J3...", "fileName": "budget.txt", "sizeBytes": 126 } ], "state": "completed", "createdAt": "2026-07-21T08:55:00Z" } ``` --- ## 10. 蒸馏任务接口 ### 10.1 当前任务和员工列表 - `GET /distill-jobs?state=active&limit=10`:返回 `DistillJobSummary[]`,用于“当前任务”。 - `GET /employees?query=Aileen&enabled=all&limit=20&cursor=...`:返回 `EmployeeSummary[]`。 ### 10.2 创建蒸馏草稿 `POST /distill-drafts` 请求: ```json { "name": "销售冠军 Aileen 话术蒸馏", "minimumValidConversations": 50 } ``` 响应: ```json { "data": { "id": "distilldraft_01J3...", "name": "销售冠军 Aileen 话术蒸馏", "fileIds": [], "minimumValidConversations": 50, "state": "draft", "revision": 1 } } ``` ### 10.3 绑定上传文件 `POST /distill-drafts/{draftId}/files` ```json { "fileIds": ["file_01J3..."], "expectedRevision": 1 } ``` 响应:返回草稿、文件列表和有效内容统计: ```json { "data": { "draftId": "distilldraft_01J3...", "files": [{ "id": "file_01J3...", "fileName": "champion-scripts.docx", "sizeBytes": 245760, "kind": "text", "status": "ready", "parseStatus": "completed" }], "statistics": { "validConversationCount": 1286, "scriptCount": 38, "invalidRecordCount": 7 }, "revision": 2 } } ``` 当前来源页只保留文件上传;不设计导入微信聊天、选择已有案例或日期范围字段。 ### 10.4 保存草稿 `PATCH /distill-drafts/{draftId}` ```json { "name": "销售冠军 Aileen 话术蒸馏", "minimumValidConversations": 50, "expectedRevision": 2 } ``` 响应:返回完整草稿。 ### 10.5 开始能力提取 `POST /distill-drafts/{draftId}/start` ```json { "expectedRevision": 3 } ``` 响应 `202 Accepted`:返回 `DistillJobSummary`。文件未解析完成、有效记录不足或草稿为空时返回 `400 VALIDATION_ERROR`。 任务进度通过 `distill.progress.updated` 推送: ```json { "jobId": "distill_01J3...", "state": "extracting", "stage": "strategy_extraction", "stageLabel": "策略提取", "progress": 0.72, "processedCount": 1286, "totalCount": 1286, "stageCurrent": 13, "stageTotal": 18, "estimatedRemainingSeconds": 180, "recognizedCapabilities": ["高意向识别", "异议拆解", "温和推进", "优惠边界", "长期跟进"], "updatedAt": "2026-07-21T09:05:00Z", "revision": 9 } ``` ### 10.6 查询任务详情 `GET /distill-jobs/{jobId}` 响应: ```json { "data": { "summary": { "id": "distill_01J3...", "name": "销售冠军 Aileen 话术蒸馏", "state": "extracting", "stage": "strategy_extraction", "progress": 0.72, "estimatedRemainingSeconds": 180, "sourceCount": 1, "successCount": 248, "failedCount": 7, "createdAt": "2026-07-21T08:30:15.238Z", "updatedAt": "2026-07-21T08:34:10Z", "revision": 9 }, "stages": [ { "code": "data_cleaning", "label": "数据清洗", "state": "completed", "current": 1286, "total": 1286 }, { "code": "scene_clustering", "label": "场景聚类", "state": "completed", "current": 18, "total": 18 }, { "code": "strategy_extraction", "label": "策略提取", "state": "running", "current": 13, "total": 18 }, { "code": "boundary_induction", "label": "边界归纳", "state": "waiting", "current": 0, "total": null }, { "code": "counterexample_generation", "label": "反例生成", "state": "waiting", "current": 0, "total": null } ], "recognizedCapabilities": ["高意向识别", "异议拆解", "温和推进", "优惠边界", "长期跟进"], "error": null } } ``` 页面已移除失败样本入口,因此不提供面向 UI 的失败样本明细接口;`failedCount` 只作为任务健康摘要和日志字段。 ### 10.7 效果评估 `GET /distill-jobs/{jobId}/evaluation` 响应: ```json { "data": { "jobId": "distill_01J3...", "state": "completed", "overallScore": 92, "publishThreshold": 85, "publishable": true, "metrics": { "sceneHitRate": 0.94, "refusalAccuracy": 0.91, "overreachRate": 0.003, "consistency": 0.89 }, "cases": [ { "id": "case_1", "name": "高意向询价", "result": "建议合理", "passed": true }, { "id": "case_2", "name": "超边界优惠", "result": "已拒绝越权", "passed": true }, { "id": "case_3", "name": "售后退款混合场景", "result": "回答包含不确定信息", "passed": false } ], "completedAt": "2026-07-21T09:10:00Z" } } ``` `POST /distill-jobs/{jobId}/evaluation-runs`:重新评估,响应 `202`,进度通过 WS 推送。 `POST /distill-jobs/{jobId}/evaluation-exports`:生成报告,响应结构同日志导出。 ### 10.8 发布员工 `POST /distill-jobs/{jobId}/publish` 请求: ```json { "name": "销售冠军 Aileen", "domain": "private_sales", "agentIds": ["agent_intent", "agent_quote"], "knowledgeIds": ["kb_price", "kb_discount", "kb_refund"], "enableAfterPublish": true, "expectedRevision": 11 } ``` - `domain`: `private_sales | b2b_consulting | after_sales` - 至少一个授权能力;知识授权可为空;只允许授权已启用资源。 响应 `201 Created`: ```json { "data": { "employee": { "id": "employee_1", "name": "销售冠军 Aileen", "version": "v1.0", "enabled": true, "traits": ["高意向识别", "异议拆解"], "domain": "private_sales", "score": 92, "weeklyCallCount": 0, "updatedAt": "2026-07-21T09:15:00Z", "revision": 1 }, "sourceJobId": "distill_01J3...", "publishedAt": "2026-07-21T09:15:00Z" } } ``` ### 10.9 取消任务 `POST /distill-jobs/{jobId}/cancel` ```json { "expectedRevision": 9, "reason": "operator_request" } ``` 仅 `queued | extracting | evaluating` 可取消。响应返回 `state: "cancelled"` 的任务摘要。 --- ## 11. 员工详情接口 ### 11.1 详情 `GET /employees/{employeeId}` 响应: ```json { "data": { "id": "employee_1", "name": "销售冠军 Aileen", "version": "v3.2", "enabled": true, "domain": "private_sales", "traits": ["高意向逼单", "异议拆解", "温和推进"], "profile": { "applicableScenario": "已有明确需求、处于报价或决策阶段的私域客户", "prohibitedBehavior": "承诺未授权折扣、绕过人工确认直接发送敏感信息" }, "metrics": { "overallScore": 96, "weeklyCallCount": 28, "adoptionRate": 0.82, "exceptionCount": 1 }, "agentBindings": [ { "id": "agent_intent", "name": "客户意图识别", "granted": true } ], "knowledgeBindings": [ { "id": "kb_price", "title": "产品价格表", "bound": true } ], "updatedAt": "2026-06-18T09:00:00Z", "revision": 3 } } ``` ### 11.2 启停、画像和授权 `PATCH /employees/{id}/status` ```json { "enabled": false, "expectedRevision": 3 } ``` `PATCH /employees/{id}/profile` ```json { "name": "销售冠军 Aileen", "domain": "private_sales", "traits": ["高意向逼单", "异议拆解", "温和推进"], "applicableScenario": "已有明确需求、处于报价或决策阶段的私域客户", "prohibitedBehavior": "承诺未授权折扣", "expectedRevision": 4 } ``` `PUT /employees/{id}/bindings` ```json { "agentIds": ["agent_intent", "agent_quote"], "knowledgeIds": ["kb_price", "kb_discount", "kb_sales_champion"], "expectedRevision": 5 } ``` 均返回最新员工详情。 ### 11.3 详情页各 Tab - `GET /employees/{id}/evaluation`:结构同蒸馏评估摘要。 - `GET /employees/{id}/versions?limit=20&cursor=...`。 - `GET /employees/{id}/calls?limit=50&cursor=...`。 调用记录项: ```json { "id": "call_01J3...", "time": "2026-07-21T04:26:00Z", "scenario": "高意向询价", "result": "suggestion_adopted", "resultLabel": "建议已采纳", "requestId": "req_01J3..." } ``` ### 11.4 重新蒸馏和复制 `POST /employees/{id}/redistill` ```json { "baseVersion": "v3.2" } ``` 响应 `201`:返回预填的 `distillDraftId`。 `POST /employees/{id}/clone` ```json { "name": "销售冠军 Aileen 副本", "copyBindings": true } ``` 响应 `201`:返回新员工详情,默认 `enabled: false`。 --- ## 12. 设置接口 ### 12.1 获取全部配置 `GET /settings` 响应: ```json { "data": { "revision": 12, "model": { "provider": "volcengine", "endpoint": "https://ark.cn-beijing.volces.com/api/v3", "modelName": "doubao-pro-32k", "requestTimeoutMs": 8000, "keyConfigured": true, "keyUpdatedAt": "2026-07-20T09:00:00Z" }, "prompt": { "fixedPrompt": "你是本地微信分身助手,需要遵守托管策略、回复边界与用户授权。", "customPrompt": "保持友好、简洁、可信赖。优先调用知识库和已授权员工能力。", "customPromptMaxLength": 4000 }, "replyRules": { "quietHoursEnabled": false, "quietHours": { "start": "22:00", "end": "08:00", "timezone": "Asia/Shanghai" }, "autoAddFriend": false, "proactiveContact": false, "distillationEnabled": true }, "featureGates": { "agentsEnabled": true, "employeesEnabled": true, "knowledgeEnabled": true }, "knowledgeSearch": { "algorithm": "sqlite_fts5_bm25", "maxResults": 5, "fields": ["title", "tags", "fullText"], "activeKnowledgeIds": ["kb_sales_champion", "kb_refund"] }, "hosting": { "enabled": false, "localMessageServiceEnabled": true, "confirmBeforeSend": true, "abnormalPauseEnabled": true, "consecutiveErrorLimit": 3, "messageWaitSeconds": 30 }, "updatedAt": "2026-07-21T08:00:00Z" } } ``` ### 12.2 保存配置 `PUT /settings` 请求传完整可编辑配置,但不传 `fixedPrompt`、`keyConfigured`、`keyUpdatedAt`: ```json { "expectedRevision": 12, "model": { "provider": "volcengine", "endpoint": "https://ark.cn-beijing.volces.com/api/v3", "modelName": "doubao-pro-32k", "requestTimeoutMs": 8000 }, "prompt": { "customPrompt": "保持友好、简洁、可信赖。" }, "replyRules": { "quietHoursEnabled": false, "quietHours": { "start": "22:00", "end": "08:00", "timezone": "Asia/Shanghai" }, "autoAddFriend": false, "proactiveContact": false, "distillationEnabled": true }, "featureGates": { "agentsEnabled": true, "employeesEnabled": true, "knowledgeEnabled": true }, "knowledgeSearch": { "maxResults": 5, "fields": ["title", "tags", "fullText"], "activeKnowledgeIds": ["kb_sales_champion", "kb_refund"] }, "hosting": { "enabled": false, "localMessageServiceEnabled": true, "confirmBeforeSend": true, "abnormalPauseEnabled": true, "consecutiveErrorLimit": 3, "messageWaitSeconds": 30 } } ``` 响应:完整最新配置。前端“恢复”必须恢复最近一次 GET/PUT 成功的数据,不能只清除 dirty 状态。 ### 12.3 API Key `PUT /settings/model-api-key` ```json { "apiKey": "真实密钥" } ``` 响应: ```json { "data": { "keyConfigured": true, "keyUpdatedAt": "2026-07-21T09:30:00Z" } } ``` `DELETE /settings/model-api-key`:返回 `204`。密钥只在此 PUT 请求中出现一次。 ### 12.4 测试模型连接 `POST /settings/model-connection-tests` 使用当前未保存表单值: ```json { "provider": "volcengine", "endpoint": "https://ark.cn-beijing.volces.com/api/v3", "modelName": "doubao-pro-32k", "requestTimeoutMs": 8000, "useStoredApiKey": true } ``` 响应: ```json { "data": { "success": true, "latencyMs": 324, "provider": "volcengine", "modelName": "doubao-pro-32k", "checkedAt": "2026-07-21T09:31:00Z" } } ``` 失败时仍返回对应 HTTP 错误和明确 code:`MODEL_AUTH_FAILED | MODEL_NOT_FOUND | MODEL_TIMEOUT | MODEL_NETWORK_UNREACHABLE`。 ### 12.5 组合提示词预览 `POST /settings/prompt-previews` ```json { "customPrompt": "保持友好、简洁、可信赖。" } ``` 响应: ```json { "data": { "fixedPrompt": "你是本地微信分身助手……", "customPrompt": "保持友好、简洁、可信赖。", "combinedPrompt": "你是本地微信分身助手……\n\n保持友好、简洁、可信赖。", "characterCount": 52 } } ``` ### 12.6 黑白名单 `GET /contact-lists?type=allow|block&query=张三` 响应项: ```json { "id": "contact_rule_01J3...", "type": "allow", "displayName": "张三", "headerFingerprint": "sha256:...", "source": "manual", "createdAt": "2026-07-21T09:32:00Z" } ``` `POST /contact-lists` ```json { "type": "allow", "displayName": "张三", "headerFingerprint": "sha256:...", "source": "manual" } ``` `DELETE /contact-lists/{ruleId}`:返回 `204`。 仅名称不足以稳定识别微信会话;生产数据必须包含当前会话头生成的 `headerFingerprint`。 ### 12.7 管理页逐项开关 以下接口复用资源状态,不额外创建第二套启停数据: - 智能体:`PATCH /agents/{id}/status` - 员工:`PATCH /employees/{id}/status` - 知识库:`PATCH /knowledge-bases/{id}/status` - 三个总开关:`PUT /settings` 中的 `featureGates` --- ## 13. WebSocket 通用协议 ### 13.1 连接和订阅 连接成功事件: ```json { "eventId": "evt_01J3...", "type": "connection.ready", "occurredAt": "2026-07-21T09:35:00Z", "payload": { "clientId": "desktop-main-7cb8", "heartbeatSeconds": 20, "resumeAccepted": true } } ``` 客户端订阅: ```json { "type": "subscribe", "requestId": "client_req_1", "payload": { "channels": ["engine", "logs", "distill:distill_01J3", "files:file_01J3"] } } ``` 服务端确认: ```json { "eventId": "evt_01J4...", "type": "ack", "occurredAt": "2026-07-21T09:35:00.010Z", "requestId": "client_req_1", "payload": { "acceptedChannels": ["engine", "logs", "distill:distill_01J3", "files:file_01J3"] } } ``` ### 13.2 服务端事件包络 ```json { "eventId": "evt_01J5...", "type": "engine.state.changed", "occurredAt": "2026-07-21T09:35:01Z", "requestId": "req_01J3...", "resource": { "type": "engine", "id": "local" }, "payload": {} } ``` ### 13.3 事件清单 | type | channel | payload | |---|---|---| | `engine.state.changed` | `engine` | 完整 `EngineState`,不是局部 patch | | `engine.startup_check.updated` | `engine` | `runId`、`state`、完整 `checks[]` | | `engine.annotation.changed` | `engine` | `annotationComplete`、`revision`、`updatedAt` | | `log.appended` | `logs` | 单条完整 `LogEvent` | | `file.processing.updated` | `files:{fileId}` | 文件处理进度对象 | | `knowledge.changed` | `knowledge:{id}` | `KnowledgeSummary` | | `agent.changed` | `agent:{id}` | `AgentSummary` | | `agent.test.message.accepted` | `agent-test:{sessionId}` | 消息受理对象 | | `agent.test.message.delta` | `agent-test:{sessionId}` | token 增量对象 | | `agent.test.message.completed` | `agent-test:{sessionId}` | 完成对象 | | `agent.test.message.failed` | `agent-test:{sessionId}` | 错误对象 | | `distill.progress.updated` | `distill:{jobId}` | 完整进度对象 | | `distill.evaluation.updated` | `distill:{jobId}` | 评估状态和结果摘要 | | `employee.changed` | `employee:{id}` | `EmployeeSummary` | | `settings.changed` | `settings` | `revision`、`changedSections[]`;前端收到后重新 GET | | `export.completed` | `exports:{exportId}` | `exportId`、`status`、`fileId`、`error` | ### 13.4 心跳、重连和顺序 - 服务端每 20 秒发送 `ping`,客户端 10 秒内返回 `pong`。 - 事件在单连接内按 `eventId` 顺序发送;业务顺序以资源 `revision` 为准。 - 前端忽略 `revision` 小于当前状态的迟到事件。 - 断线后指数退避:1s、2s、4s、8s,最大 15s。 - 重连时用最后一个已处理 `eventId` 申请新 ticket;事件缓存建议保留 10 分钟。 - 无法续传时 `connection.ready.payload.resumeAccepted=false`,前端必须重新 GET 当前页面资源。 - WS 只负责通知和流式增量;创建、更新、删除仍由 HTTP 完成。 --- ## 14. Tauri 原生 IPC:不得改成 HTTP/WS 的能力 这些接口仍是 API 契约,但调用形式只允许 `invoke(command, payload)`。标注调试全程在本机 React/Tauri/Rust 内完成,直接操作本机窗口、截图和应用生命周期。 本地边界: 1. `src/pages/AnnotationPage.jsx` 和 `src/overlay.js` 不调用业务 HTTP 或 WebSocket。 2. 截图字节、截图路径、窗口句柄、窗口元数据、标注区域和未保存会话状态不得发送给 Go 后端服务。 3. Go 后端不提供标注调试接口,也不读取标注调试状态;保存和加载只通过 Tauri/Rust 本地存储。 4. Tauri event 只在本机 WebView 窗口之间传递,不桥接到业务 WebSocket。 ### 14.1 标注区域对象 ```json { "id": "region_01J3...", "name": "聊天内容", "type": "chat_content", "description": "微信当前会话消息区", "bbox_image": [120, 180, 860, 1240], "bbox_source": [80, 120, 573.333, 826.667], "bbox_screen": [420, 280, 1160, 1340], "scaleFactor": 1.5 } ``` 坐标统一为 XYXY:`[x1, y1, x2, y2]`。生产必需类型: - `conversation_header` - `chat_content` - `input_box` - `send_button` `custom` 只能附加,不能代替必需类型。 ### 14.2 IPC 命令 | command | 请求 | 返回 | |---|---|---| | `enter_window_select_mode` | `{}` | `{ mode: "window_select" }` | | `capture_screen` | `{}` | `CaptureResult` | | `read_screenshot_bytes` | `{ path }` | `number[]` 或二进制 buffer | | `load_regions` | `{}` | `AnnotationConfig | null` | | `save_regions` | `{ annotation: AnnotationConfig }` | `{ path, revision, updatedAt }` | | `start_vision_stream` | `{}` | `{ state: "running" }` | | `stop_vision_stream` | `{}` | `{ state: "stopped" }` | | `start_agent` | `{}` | `{ state: "running" }` | | `stop_agent` | `{}` | `{ state: "stopped" }` | | `open_popup_window` | `{ route }` | `{ label }` | | `close_current_window` | `{}` | `null` | | `exit_application` | `{}` | `null` | `CaptureResult`: ```json { "screenshotPath": "受限应用数据目录中的路径", "screenshotWidth": 1440, "screenshotHeight": 900, "scaleFactor": 1.5, "source": { "id": "win-window:12345", "kind": "window", "label": "WeChat", "appName": "WeChat.exe", "title": "微信", "pid": 4312, "x": 200, "y": 100, "width": 960, "height": 600, "scaleFactor": 1.5 }, "screenListMs": 12, "captureMs": 40, "saveMs": 8, "totalMs": 60 } ``` `AnnotationConfig`: ```json { "app": "wechat", "screenshotPath": "受限应用数据目录中的路径", "screenshotWidth": 1440, "screenshotHeight": 900, "scaleFactor": 1.5, "source": {}, "regions": [], "createdAt": "2026-07-21T09:40:00Z", "updatedAt": "2026-07-21T09:42:00Z", "revision": 3 } ``` 原生保存成功后由 Tauri event 发送: ```json { "event": "annotation-completion-changed", "payload": true } ``` 引擎状态变化沿用: ```json { "event": "engine-state-changed", "payload": { "enabled": true } } ``` 标注调试状态只允许 Tauri/Rust 本地模块读取。HTTP 业务服务和 Go 后端不得读取、同步或转发截图、窗口信息及标注区域。 --- ## 15. 页面到接口映射 | 页面/窗口 | 源文件 | 初始加载 | 用户操作 | 实时事件 | |---|---|---|---|---| | 微信分身 | `src/pages/ClonePage.jsx` | `/bootstrap`、`/engine/state` | 启动检查、启动/停止引擎、暂停自动发送;标注走 Tauri IPC | `engine.*`、`log.appended` | | 运行日志 | `src/windows/EngineLogsWindow.jsx` | `GET /logs` | 导出日志;清空/暂停是前端视图操作 | `log.appended`、`export.completed` | | 知识库列表 | `src/pages/KnowledgePage.jsx` | `GET /knowledge-bases` | 搜索、打开详情 | `knowledge.changed` 可选 | | 新增/更新知识库 | `src/windows/KnowledgeWindows.jsx` | 创建/读取 knowledge draft | 上传文档、图片或视频;预览转换后的 TXT;人工填写媒体描述;移除、发布 | `file.processing.updated`、`knowledge.changed` | | 知识库详情、预览、引用、版本 | `src/windows/KnowledgeWindows.jsx` | knowledge detail/files/references/versions | 预览、下载、启停、更新、删除 | `knowledge.changed`、文件处理事件 | | 智能体市场 | `src/pages/SkillsPage.jsx` | `GET /agents` | 搜索、筛选、启停、打开详情 | `agent.changed` 可选 | | 新增/更新智能体 | `src/windows/SkillWindow.jsx` | 创建/读取 agent draft | 基本信息、提示词、知识授权、测试、发布 | 测试会话事件 | | 智能体详情 | `src/windows/SkillWindow.jsx` | `GET /agents/{id}` | 更新、测试、启停、删除 | `agent.changed` | | 测试智能体 | `src/components/AgentChatPanel.jsx` | 创建 test session、加载 messages | 上传附件、发送、取消生成 | `agent.test.*` | | 员工蒸馏主页 | `src/pages/DistillPage.jsx` | active jobs、employees | 搜索、取消任务、打开详情 | `distill.progress.updated` | | 开始蒸馏 | `src/windows/DistillWindows.jsx` | 创建/读取 distill draft | 上传文件、开始提取、重新评估、导出、发布 | `file.processing.updated`、`distill.*` | | 员工详情 | `src/windows/DistillWindows.jsx` | `GET /employees/{id}` | 启停、编辑画像、管理授权、重新蒸馏、复制 | `employee.changed` | | 设置 | `src/windows/SettingsContent.jsx` | `GET /settings` | 保存/恢复、Key 更换/删除、连接测试、名单 CRUD | `settings.changed` | | 标注调试页 | `src/pages/AnnotationPage.jsx` | Tauri `capture_screen/load_regions` | 画框、编辑、删除、保存 | Tauri annotation event | | 原生透明标注层 | `src/overlay.js` | Tauri overlay state | 选窗、画框、编辑、删除、保存或取消 | Tauri annotation event | --- ## 16. 前端交互约束 1. 所有页面首次打开必须显示 loading,失败显示真实错误和重试入口;不得用 mock 数据补成功状态。 2. 按钮发起 mutation 后立即禁用,直到响应完成;重复点击依赖 `Idempotency-Key` 兜底。 3. 搜索输入建议 250ms debounce;新的请求发出时取消旧请求,避免旧结果覆盖新结果。 4. 详情窗口更新后关闭原窗口没有问题,但重新打开详情必须 GET 最新资源,不能依赖 `localStorage` 或 `BroadcastChannel` 作为业务事实源。 5. WS 事件只更新同 revision 或更新 revision;发生缺号或冲突时重新 GET。 6. 文件选择后先展示本地文件名和上传进度;只有 `FileAsset.status=ready` 才显示“格式有效/可预览”。 7. 智能体测试期间禁用下一步、附件移除和重复发送;`completed` 后才标记测试通过。 8. 蒸馏后台运行时关闭窗口不取消任务;再次打开按 jobId 查询并续订频道。 9. 删除响应成功后从列表移除;`409 RESOURCE_IN_USE` 必须显示引用资源,不得假装删除成功。 10. 配置保存以服务端返回的完整对象替换本地表单基线;连接测试不自动保存配置。 --- ## 17. 实施顺序 1. **基础层**:HTTP client、错误模型、session token、SQLite repository、revision、WebSocket ticket/重连。 2. **设置与知识库**:消除 API Key、本地配置、知识列表和创建流程中的 mock/localStorage。 3. **文件中心**:上传、解析、预览、清理和处理进度事件。 4. **智能体**:草稿、授权、测试 WS 流式输出、发布和详情。 5. **蒸馏与员工**:后台任务、进度、评估、发布和详情子资源。 6. **引擎与日志**:将现有 Tauri/sidecar 状态映射成结构化 HTTP/WS 契约,同时保留标注为 Tauri IPC。 完成判定:页面展示字段均来自上述响应;所有可操作按钮有真实 mutation;长任务和流式生成有可恢复事件;上传、解析失败、并发冲突和断线重连都有明确结果。