Files
zclaw_openfang/docs/knowledge-base/websocket-protocol.md
iven 0d4fa96b82
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
refactor: 统一项目名称从OpenFang到ZCLAW
重构所有代码和文档中的项目名称,将OpenFang统一更新为ZCLAW。包括:
- 配置文件中的项目名称
- 代码注释和文档引用
- 环境变量和路径
- 类型定义和接口名称
- 测试用例和模拟数据

同时优化部分代码结构,移除未使用的模块,并更新相关依赖项。
2026-03-27 07:36:03 +08:00

283 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ZCLAW WebSocket 协议实际实现
> **重要**: ZCLAW 实际的 WebSocket 协议与官方文档有差异。本文档记录实际测试验证的协议格式。
**测试日期**: 2026-03-14
**ZCLAW 版本**: 0.4.0
**测试环境**: Windows 11, Node.js v24
---
## 1. WebSocket 连接
### 端点 URL
```
ws://127.0.0.1:50051/api/agents/{agentId}/ws
```
- **端口**: 50051 (非文档中的 4200)
- **agentId**: 必须是真实的 Agent UUID不能使用 "default"
### 获取 Agent ID
```bash
curl http://127.0.0.1:50051/api/agents
```
返回示例:
```json
[
{
"id": "f77004c8-418f-4132-b7d4-7ecb9d66f44c",
"name": "General Assistant",
"model_provider": "zhipu",
"model_name": "glm-4-flash",
"state": "Running"
}
]
```
---
## 2. 消息格式
### 发送消息 (实际格式)
```json
{
"type": "message",
"content": "Hello, how are you?",
"session_id": "session_123"
}
```
### 文档中的格式 (错误)
```json
// ❌ 这是错误的格式,不要使用
{
"type": "chat",
"message": {
"role": "user",
"content": "Hello"
}
}
```
---
## 3. 事件类型
### 连接事件
| 事件类型 | 说明 | 数据格式 |
|---------|------|----------|
| `connected` | 连接成功 | `{"agent_id": "uuid", "type": "connected"}` |
| `agents_updated` | Agent 列表更新 | `{"agents": [...], "type": "agents_updated"}` |
### 聊天事件
| 事件类型 | 说明 | 数据格式 |
|---------|------|----------|
| `typing` | 输入状态 | `{"state": "start" 或 "stop", "type": "typing"}` |
| `phase` | 阶段变化 | `{"phase": "streaming" 或 "done", "type": "phase"}` |
| `text_delta` | 文本增量 | `{"content": "文本内容", "type": "text_delta"}` |
| `response` | 完整响应 | `{"content": "...", "input_tokens": 100, "output_tokens": 50, "type": "response"}` |
| `error` | 错误 | `{"content": "错误信息", "type": "error"}` |
### 文档中的事件 (错误)
| 文档事件 | 实际事件 |
|---------|---------|
| `stream.delta.content` | `text_delta.content` |
| `stream.phase` | `phase` |
---
## 4. 事件序列
完整的聊天事件序列:
```
1. connected - 连接成功
2. typing (start) - 开始输入
3. agents_updated - Agent 状态更新
4. phase (streaming)- 流式输出开始
5. text_delta - 文本增量 (可能多次)
6. phase (done) - 流式输出完成
7. typing (stop) - 输入结束
8. response - 完整响应 (含 token 统计)
```
---
## 5. 代码示例
### Node.js WebSocket 客户端
```javascript
const WebSocket = require('ws');
const agentId = 'f77004c8-418f-4132-b7d4-7ecb9d66f44c';
const ws = new WebSocket(`ws://127.0.0.1:50051/api/agents/${agentId}/ws`);
let fullContent = '';
ws.on('open', () => {
// 发送消息 - 使用正确的格式
ws.send(JSON.stringify({
type: 'message',
content: 'Hello!',
session_id: 'test_session'
}));
});
ws.on('message', (data) => {
const event = JSON.parse(data.toString());
switch (event.type) {
case 'text_delta':
// 累积文本内容
fullContent += event.content || '';
break;
case 'response':
console.log('Complete:', fullContent);
console.log('Tokens:', event.input_tokens, event.output_tokens);
break;
case 'error':
console.error('Error:', event.content);
break;
}
});
```
### React + Zustand 集成
```typescript
// chatStore.ts
sendMessage: async (content: string) => {
const client = getGatewayClient();
if (client.getState() === 'connected') {
await client.chatStream(content, {
onDelta: (delta: string) => {
// 更新消息内容
set((state) => ({
messages: state.messages.map((m) =>
m.id === assistantId
? { ...m, content: m.content + delta }
: m
),
}));
},
onComplete: () => {
set({ isStreaming: false });
},
onError: (error: string) => {
// 处理错误
},
});
}
}
```
---
## 6. Vite 代理配置
必须启用 WebSocket 代理:
```typescript
// vite.config.ts
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://127.0.0.1:50051',
changeOrigin: true,
secure: false,
ws: true, // ✅ 必须启用
},
},
},
});
```
---
## 7. 常见错误
### 错误: "Unexpected server response: 400"
**原因**: Agent ID 无效或格式错误
**解决**: 使用真实的 Agent UUID不要使用 "default"
### 错误: "Missing API key: No LLM provider configured"
**原因**: Agent 使用的 LLM 提供商未配置 API Key
**解决**:
1. 检查 `~/.zclaw/.env` 文件
2. 确保对应提供商的 API Key 已设置
3. 或使用已配置的 Agent (如 General Assistant - zhipu)
### 错误: WebSocket 连接成功但无响应
**原因**: 消息格式错误
**解决**: 确保使用 `{ type: 'message', content, session_id }` 格式
---
## 8. REST API 端点
### 健康检查
```bash
GET /api/health
# {"status":"ok","version":"0.4.0"}
```
### Agent 列表
```bash
GET /api/agents
# 返回所有 Agent 数组
```
### Hands 列表
```bash
GET /api/hands
# 返回所有 Hands 数组
```
### REST 聊天 (非流式)
```bash
POST /api/agents/{agentId}/message
Content-Type: application/json
{"message": "Hello"}
```
---
## 9. 相关文件
| 文件 | 说明 |
|------|------|
| `desktop/src/lib/gateway-client.ts` | WebSocket 客户端实现 |
| `desktop/src/store/chatStore.ts` | 聊天状态管理 |
| `desktop/vite.config.ts` | Vite 代理配置 |
---
## 更新历史
| 日期 | 变更 |
|------|------|
| 2026-03-14 | 初始版本,记录协议差异和实际实现 |