56 KiB
微信 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 安全边界
- Tauri 启动 sidecar 时生成随机
sessionToken,HTTP 使用Authorization: Bearer {sessionToken}。 - WebSocket 不在 URL 中携带长期 token。前端先申请 30 秒有效、单次使用的
ticket。 - 模型 API Key 进入系统密钥库;任何 GET 响应只返回
keyConfigured,不得返回明文或掩码后的原始值。 - 日志禁止记录 API Key、完整系统提示词、无关聊天原文、剪贴板内容和本机绝对文件路径。
- 所有资源更新使用
revision做乐观并发控制;版本不匹配返回409 REVISION_CONFLICT。 - 删除知识库、智能体、员工等不可逆操作必须由前端二次确认,并在请求中传
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 成功响应
{
"data": {},
"meta": {
"requestId": "req_01J3...",
"nextCursor": null,
"total": 6
}
}
- 单资源接口可省略
nextCursor和total。 204 No Content用于成功删除且无响应体的场景。
2.3 错误响应
{
"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 列表参数
?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
{
"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_exportkind:text | image | video | binarystatus:uploading | uploaded | processing | ready | failed | deletedparseStatus:not_required | queued | processing | completed | failedpreviewStatus:none | processing | ready | faileddescriptionSource: 当前只允许manual | null,禁止返回ai | ocr | vision
图片或视频知识文件示例:
{
"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
{
"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 | mixedstatus:draft | processing | enabled | disabled | failed
3.3 AgentSummary
{
"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 | customlastTestStatus:not_run | running | passed | failed
3.4 DistillJobSummary
{
"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 | failedstage:source_validation | data_cleaning | scene_clustering | strategy_extraction | boundary_induction | counterexample_generation | evaluation | completed
3.5 EmployeeSummary
{
"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。
响应:
{
"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
请求:
{
"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 个 |
响应:
{
"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:
{
"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 | erroragent/visionStream:stopped | starting | running | errorwechatWindow:unknown | connected | missing | changed
5.2 执行启动检查
POST /engine/startup-checks
请求:
{ "forceRefresh": true }
响应 202 Accepted:
{
"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
请求:
{
"startupCheckRunId": "check_01J3...",
"expectedRevision": 12
}
响应 202 Accepted:返回最新 EngineState。若检查未通过,返回 409 STARTUP_CHECK_FAILED,details.failedCheckIds 指明失败项。
5.4 停止引擎
POST /engine/stop
请求:
{ "expectedRevision": 13, "reason": "operator_request" }
响应 202 Accepted:返回 lifecycle: "stopping" 的 EngineState,最终状态通过 WS 推送。
5.5 暂停或恢复自动发送
PATCH /engine/auto-send
请求:
{ "paused": true, "expectedRevision": 14 }
响应:返回最新 EngineState。当前界面的“暂停自动发送/恢复自动发送”直接绑定此接口。
5.6 日志列表
GET /logs?level=warning&module=model&query=req_91fa&limit=100&cursor=...
响应:
{
"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 | errormodule:agent | vision | capture | retriever | model | policy | sender
暂停接收仅停止当前窗口的 WS 消费,不调用后端、不暂停引擎。清空视图只清前端缓存,不删除审计日志。
5.7 导出日志
POST /logs/exports
请求:
{
"filter": { "level": "all", "module": "all", "query": "" },
"format": "jsonl",
"from": "2026-07-20T00:00:00Z",
"to": "2026-07-21T23:59:59Z"
}
响应 202 Accepted:
{
"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。
知识文件首期处理边界:
- TXT 按 UTF-8 规范化保存;PDF 只提取已有文本层;DOCX 提取段落和表格文字;PPT/PPTX 提取文本框、表格和备注文字。
- 文档中的嵌入图片直接省略,不调用 OCR、视觉模型或图片理解。
- 图片和视频可以作为独立知识来源上传、保存和预览,但不执行 OCR、图片理解、视频理解、ASR、关键帧提取或自动摘要。
- 图片和视频的
description只能由操作者人工填写,descriptionSource固定为manual;后端不得自动生成或补全描述。 - 媒体文件有人工描述时,知识检索只索引标题、标签和人工描述;没有描述时只索引标题和标签,原始媒体内容不进入文本检索。
- 扫描版 PDF 或只有图片、没有可提取文字的 Office 文档返回
422 NO_EXTRACTABLE_TEXT,不能标记为文档转换成功。 - 文档转换结果生成独立 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
请求:
{
"purpose": "knowledge_source",
"fileName": "product-training.mp4",
"contentType": "video/mp4",
"sizeBytes": 734003200,
"sha256": "可选整体哈希",
"clientFileId": "8fb2a9e5-..."
}
响应:
{
"data": {
"uploadId": "upload_01J3...",
"chunkSizeBytes": 8388608,
"uploadedParts": [],
"expiresAt": "2026-07-22T08:30:15.238Z"
}
}
6.4 上传分片
PUT /file-uploads/{uploadId}/parts/{partNumber}
Headers:
Content-Type: application/octet-stream
Content-Length: 8388608
Content-Range: bytes 0-8388607/734003200
X-Chunk-SHA256: 1c9e...
响应:
{
"data": {
"partNumber": 1,
"sizeBytes": 8388608,
"sha256": "1c9e...",
"accepted": true
}
}
重复上传同一分片且哈希相同必须幂等;哈希不同返回 409 CHUNK_CONFLICT。
6.5 完成分片上传
POST /file-uploads/{uploadId}/complete
请求:
{
"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:
{
"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_SKIPPEDwarning。 - 没有任何可提取正文时,
parseStatus为failed,error.code为NO_EXTRACTABLE_TEXT。
媒体处理规则:
- 图片、视频上传完成并通过文件安全校验后,
parseStatus固定为not_required。 - 服务端只生成安全预览能力,不识别画面、不抽取文字、不识别语音、不生成描述。
description完全来自人工输入,服务端原样保存;空描述允许保存,但媒体内容本身不会进入 FTS5 正文索引。
PATCH /files/{fileId} 请求:
{
"description": "退款申请、审核和到账三个步骤的流程图。",
"descriptionSource": "manual",
"expectedRevision": 1
}
服务端必须拒绝 descriptionSource 不是 manual 的请求;响应返回最新 FileAsset。
文本响应:
{
"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
请求:
{
"mode": "create",
"knowledgeId": null,
"baseVersion": null,
"title": "售后退款政策",
"description": "用于回答售后退款范围、异常订单与客户安抚相关问题。",
"tags": ["私域成交", "售后"]
}
更新知识库时:
{
"mode": "update",
"knowledgeId": "kb_refund",
"baseVersion": "v1.7"
}
响应:
{
"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}
请求:
{
"title": "售后退款政策",
"description": "用于回答售后问题。",
"tags": ["私域成交", "售后"],
"expectedRevision": 1
}
校验:title 1100 字;30 字,去重后保存。description 最大 2000 字;标签最多 20 个,每个 1
响应:返回完整草稿和递增后的 revision。
7.4 绑定或移除来源文件
POST /knowledge-drafts/{draftId}/files
{
"fileIds": ["file_01J3...", "file_01J4..."],
"expectedRevision": 2
}
响应:
{
"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
响应:
{
"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
请求:
{
"versionNote": "补充异常订单处理边界",
"enableAfterPublish": true,
"expectedRevision": 4
}
响应 201 Created:
{
"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}
响应:
{
"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=...:版本历史。
引用关系项:
{
"resourceType": "agent",
"resourceId": "agent_quote",
"name": "报价策略生成",
"enabled": true,
"boundVersion": "v1.7"
}
版本项:
{
"id": "kv_01J3...",
"version": "v1.7",
"versionNote": "修正数字商品退款边界",
"isCurrent": true,
"createdAt": "2026-06-05T01:42:00Z"
}
7.9 启停和删除
PATCH /knowledge-bases/{id}/status
{ "enabled": false, "expectedRevision": 7 }
响应:返回最新 KnowledgeSummary。停用后已绑定关系保留,但检索时不能命中。
DELETE /knowledge-bases/{id}
{
"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
请求:
{
"mode": "create",
"agentId": null,
"name": "报价策略生成",
"description": "根据客户意向、商品成本和优惠边界生成报价建议。",
"tags": ["利润保护", "阶梯报价", "优惠边界"]
}
更新模式传 mode: "update" 和 agentId。响应:
{
"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}
请求可部分更新:
{
"name": "报价策略生成",
"description": "根据客户意向、商品成本和优惠边界生成报价建议。",
"tags": ["利润保护", "阶梯报价", "优惠边界"],
"systemPrompt": "你是报价策略助手……",
"knowledgeIds": ["kb_price", "kb_discount"],
"expectedRevision": 1
}
校验:名称 1~80 字;描述最大 2000 字;标签最多 20 个;系统提示词最大 20000 字;只能授权已生效知识库。
响应:返回完整草稿和新 revision。
8.4 发布或更新智能体
POST /agent-drafts/{draftId}/publish
请求:
{
"releaseNote": "首次发布报价策略生成智能体。",
"enableAfterPublish": true,
"expectedRevision": 3
}
前置条件:lastTestStatus 必须为 passed,且测试使用的 draftRevision 必须等于当前草稿 revision;提示词或授权变更后旧测试失效。
响应:
{
"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}
响应:
{
"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=...。
测试记录项:
{
"id": "test_01J3...",
"scenario": "高意向询价",
"status": "passed",
"latencyMs": 1200,
"draftRevision": 3,
"createdAt": "2026-06-18T09:30:00Z",
"error": null
}
8.7 启停和删除
PATCH /agents/{id}/status
{ "enabled": false, "expectedRevision": 4 }
DELETE /agents/{id}
{
"confirmation": "客户意图识别",
"expectedRevision": 5
}
内置智能体可按产品规则返回 403 BUILTIN_AGENT_READ_ONLY;若允许删除,必须明确为隐藏/禁用而非物理删除。
9. 智能体测试会话与 WebSocket 流式回复
9.1 创建测试会话
POST /agent-test-sessions
请求:
{
"agentId": "agent_intent",
"draftId": null,
"draftRevision": null,
"mode": "published"
}
编辑器沙箱传:
{
"agentId": null,
"draftId": "agentdraft_01J3...",
"draftRevision": 3,
"mode": "draft"
}
响应:
{
"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 上传。
{
"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 且解析完成。
服务端事件顺序:
agent.test.message.accepted- 零到多个
agent.test.message.delta agent.test.message.completed或agent.test.message.failed
accepted:
{
"sessionId": "testsession_01J3...",
"messageId": "msg_01J3...",
"clientMessageId": "bce8e547-...",
"assistantMessageId": "msg_01J4...",
"acceptedAt": "2026-07-21T08:55:00Z"
}
delta:
{
"sessionId": "testsession_01J3...",
"assistantMessageId": "msg_01J4...",
"sequence": 7,
"delta": "建议先核对",
"accumulatedLength": 28
}
completed:
{
"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:
{
"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}:结束会话并清理未引用测试附件。
消息对象:
{
"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
请求:
{
"name": "销售冠军 Aileen 话术蒸馏",
"minimumValidConversations": 50
}
响应:
{
"data": {
"id": "distilldraft_01J3...",
"name": "销售冠军 Aileen 话术蒸馏",
"fileIds": [],
"minimumValidConversations": 50,
"state": "draft",
"revision": 1
}
}
10.3 绑定上传文件
POST /distill-drafts/{draftId}/files
{
"fileIds": ["file_01J3..."],
"expectedRevision": 1
}
响应:返回草稿、文件列表和有效内容统计:
{
"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}
{
"name": "销售冠军 Aileen 话术蒸馏",
"minimumValidConversations": 50,
"expectedRevision": 2
}
响应:返回完整草稿。
10.5 开始能力提取
POST /distill-drafts/{draftId}/start
{ "expectedRevision": 3 }
响应 202 Accepted:返回 DistillJobSummary。文件未解析完成、有效记录不足或草稿为空时返回 400 VALIDATION_ERROR。
任务进度通过 distill.progress.updated 推送:
{
"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}
响应:
{
"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
响应:
{
"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
请求:
{
"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:
{
"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
{ "expectedRevision": 9, "reason": "operator_request" }
仅 queued | extracting | evaluating 可取消。响应返回 state: "cancelled" 的任务摘要。
11. 员工详情接口
11.1 详情
GET /employees/{employeeId}
响应:
{
"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
{ "enabled": false, "expectedRevision": 3 }
PATCH /employees/{id}/profile
{
"name": "销售冠军 Aileen",
"domain": "private_sales",
"traits": ["高意向逼单", "异议拆解", "温和推进"],
"applicableScenario": "已有明确需求、处于报价或决策阶段的私域客户",
"prohibitedBehavior": "承诺未授权折扣",
"expectedRevision": 4
}
PUT /employees/{id}/bindings
{
"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=...。
调用记录项:
{
"id": "call_01J3...",
"time": "2026-07-21T04:26:00Z",
"scenario": "高意向询价",
"result": "suggestion_adopted",
"resultLabel": "建议已采纳",
"requestId": "req_01J3..."
}
11.4 重新蒸馏和复制
POST /employees/{id}/redistill
{ "baseVersion": "v3.2" }
响应 201:返回预填的 distillDraftId。
POST /employees/{id}/clone
{ "name": "销售冠军 Aileen 副本", "copyBindings": true }
响应 201:返回新员工详情,默认 enabled: false。
12. 设置接口
12.1 获取全部配置
GET /settings
响应:
{
"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:
{
"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
{ "apiKey": "真实密钥" }
响应:
{
"data": {
"keyConfigured": true,
"keyUpdatedAt": "2026-07-21T09:30:00Z"
}
}
DELETE /settings/model-api-key:返回 204。密钥只在此 PUT 请求中出现一次。
12.4 测试模型连接
POST /settings/model-connection-tests
使用当前未保存表单值:
{
"provider": "volcengine",
"endpoint": "https://ark.cn-beijing.volces.com/api/v3",
"modelName": "doubao-pro-32k",
"requestTimeoutMs": 8000,
"useStoredApiKey": true
}
响应:
{
"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
{ "customPrompt": "保持友好、简洁、可信赖。" }
响应:
{
"data": {
"fixedPrompt": "你是本地微信分身助手……",
"customPrompt": "保持友好、简洁、可信赖。",
"combinedPrompt": "你是本地微信分身助手……\n\n保持友好、简洁、可信赖。",
"characterCount": 52
}
}
12.6 黑白名单
GET /contact-lists?type=allow|block&query=张三
响应项:
{
"id": "contact_rule_01J3...",
"type": "allow",
"displayName": "张三",
"headerFingerprint": "sha256:...",
"source": "manual",
"createdAt": "2026-07-21T09:32:00Z"
}
POST /contact-lists
{
"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 连接和订阅
连接成功事件:
{
"eventId": "evt_01J3...",
"type": "connection.ready",
"occurredAt": "2026-07-21T09:35:00Z",
"payload": {
"clientId": "desktop-main-7cb8",
"heartbeatSeconds": 20,
"resumeAccepted": true
}
}
客户端订阅:
{
"type": "subscribe",
"requestId": "client_req_1",
"payload": {
"channels": ["engine", "logs", "distill:distill_01J3", "files:file_01J3"]
}
}
服务端确认:
{
"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 服务端事件包络
{
"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 内完成,直接操作本机窗口、截图和应用生命周期。
本地边界:
src/pages/AnnotationPage.jsx和src/overlay.js不调用业务 HTTP 或 WebSocket。- 截图字节、截图路径、窗口句柄、窗口元数据、标注区域和未保存会话状态不得发送给 Go 后端服务。
- Go 后端不提供标注调试接口,也不读取标注调试状态;保存和加载只通过 Tauri/Rust 本地存储。
- Tauri event 只在本机 WebView 窗口之间传递,不桥接到业务 WebSocket。
14.1 标注区域对象
{
"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_headerchat_contentinput_boxsend_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 |
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:
{
"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:
{
"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 发送:
{
"event": "annotation-completion-changed",
"payload": true
}
引擎状态变化沿用:
{
"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. 前端交互约束
- 所有页面首次打开必须显示 loading,失败显示真实错误和重试入口;不得用 mock 数据补成功状态。
- 按钮发起 mutation 后立即禁用,直到响应完成;重复点击依赖
Idempotency-Key兜底。 - 搜索输入建议 250ms debounce;新的请求发出时取消旧请求,避免旧结果覆盖新结果。
- 详情窗口更新后关闭原窗口没有问题,但重新打开详情必须 GET 最新资源,不能依赖
localStorage或BroadcastChannel作为业务事实源。 - WS 事件只更新同 revision 或更新 revision;发生缺号或冲突时重新 GET。
- 文件选择后先展示本地文件名和上传进度;只有
FileAsset.status=ready才显示“格式有效/可预览”。 - 智能体测试期间禁用下一步、附件移除和重复发送;
completed后才标记测试通过。 - 蒸馏后台运行时关闭窗口不取消任务;再次打开按 jobId 查询并续订频道。
- 删除响应成功后从列表移除;
409 RESOURCE_IN_USE必须显示引用资源,不得假装删除成功。 - 配置保存以服务端返回的完整对象替换本地表单基线;连接测试不自动保存配置。
17. 实施顺序
- 基础层:HTTP client、错误模型、session token、SQLite repository、revision、WebSocket ticket/重连。
- 设置与知识库:消除 API Key、本地配置、知识列表和创建流程中的 mock/localStorage。
- 文件中心:上传、解析、预览、清理和处理进度事件。
- 智能体:草稿、授权、测试 WS 流式输出、发布和详情。
- 蒸馏与员工:后台任务、进度、评估、发布和详情子资源。
- 引擎与日志:将现有 Tauri/sidecar 状态映射成结构化 HTTP/WS 契约,同时保留标注为 Tauri IPC。
完成判定:页面展示字段均来自上述响应;所有可操作按钮有真实 mutation;长任务和流式生成有可恢复事件;上传、解析失败、并发冲突和断线重连都有明确结果。