Appearance
项目 WebSocket
ws://host/api/v1/projects/{project_id}/ws?token=xxx项目 WebSocket 是融合端点,在单一连接中同时处理画布操作和对话通信,通过 domain 字段区分。
消息域
| 域 | 说明 |
|---|---|
canvas | 画布操作(节点/边/组的 CRUD) |
conversation | 对话消息(与 对话 WebSocket 协议相同) |
Canvas 域消息
客户端 → 服务端
所有画布消息必须包含 domain: "canvas" 和 action 字段。
批量创建
json
{
"domain": "canvas",
"action": "create",
"payload": [
{
"type": "node",
"data": {
"type": "text",
"temp_id": "n1",
"x": 100,
"y": 200,
"width": 200,
"height": 100,
"rotation": 0,
"data": {
"label": "标题",
"text": "内容"
}
}
},
{
"type": "edge",
"data": {
"temp_id": "e1",
"source_id": "n1",
"target_id": "existing-node-uuid",
"description": "连接描述"
}
},
{
"type": "group",
"data": {
"temp_id": "g1",
"name": "分组名称",
"node_ids": [],
"node_temp_ids": ["n1"]
}
}
],
"request_id": "req-canvas-001"
}临时 ID 映射:
- 节点/边/组可指定
temp_id(1-36 字符,无需 UUID 格式) - 边的
source_id/target_id可引用temp_id或已存在节点的 UUID - 组的
node_temp_ids引用同批次节点的temp_id - 服务端自动将
temp_id映射为真实 UUID 并在响应中返回映射关系
批量限制:单次最多 100 项,原子性执行(全部成功或全部回滚)。
批量更新
json
{
"domain": "canvas",
"action": "update",
"payload": [
{
"type": "node",
"data": {
"id": "real-node-uuid",
"x": 300,
"y": 400
}
}
]
}更新只需发送变更字段,未包含的字段保持不变。
批量删除
json
{
"domain": "canvas",
"action": "delete",
"ids": [
{ "type": "node", "id": "node-uuid-1" },
{ "type": "edge", "id": "edge-uuid-1" }
]
}查询节点
json
{
"domain": "canvas",
"action": "list",
"payload": {
"type": "node"
}
}服务端 → 客户端
画布操作的响应:
json
{
"domain": "canvas",
"action": "create",
"success": true,
"data": {
"items": [...],
"temp_id_mapping": {
"n1": "real-uuid-1",
"e1": "real-uuid-2",
"g1": "real-uuid-3"
}
},
"request_id": "req-canvas-001"
}错误响应:
json
{
"domain": "canvas",
"action": "create",
"success": false,
"error": "节点坐标超出范围",
"request_id": "req-canvas-001"
}Conversation 域消息
在项目 WebSocket 中发送对话消息时,除了 对话 WebSocket 的标准字段外,还需要:
- 添加
domain: "conversation"字段 - 添加
conversation_id字段(指定目标对话)
json
{
"domain": "conversation",
"conversation_id": "d4e5f6a7-...",
"type": "append_message",
"payload": {
"message": {
"role": "user",
"content": "帮我在画布上创建一个流程图"
}
},
"request_id": "req-conv-001"
}服务端的对话响应消息格式与 对话 WebSocket 完全相同。
画布节点类型参考
| 节点 type | 可用字段 | 说明 |
|---|---|---|
text | label, text | 文本节点 |
image | label, file_ids | 图片节点 |
video | label, file_ids | 视频节点 |
code | label, language, code | 代码节点 |
markdown | label, content | Markdown 节点 |
file | label, file_ids | 通用文件节点 |
所有节点共享的定位字段:x、y、width、height、rotation。
测试要点
测试建议
- 域隔离:canvas 域的错误不应影响 conversation 域
- temp_id 映射正确性:边引用同批次节点的 temp_id 应正确解析
- 批量原子性:批量创建中一项失败,整批应回滚
- AI 画布操作:通过对话让 AI 操作画布,验证工具确认流程
- 对话切换:在同一项目 WS 中切换不同的
conversation_id - 并发安全:画布操作和对话补全同时进行