2075 lines
56 KiB
Markdown
2075 lines
56 KiB
Markdown
# 微信 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;长任务和流式生成有可恢复事件;上传、解析失败、并发冲突和断线重连都有明确结果。
|