Files
zclaw_openfang/docs/knowledge-base/websocket-protocol.md
iven 6f72442531 docs(guide): rewrite CLAUDE.md with ZCLAW-first perspective
Major changes:
- Shift from "OpenFang desktop client" to "independent AI Agent desktop app"
- Add decision principle: "Is this useful for ZCLAW? Does it affect ZCLAW?"
- Simplify project structure and tech stack sections
- Replace OpenClaw vs OpenFang comparison with unified backend approach
- Consolidate troubleshooting from scattered sections into organized FAQ
- Update Hands system documentation with 8 capabilities and status
- Stream
2026-03-20 19:30:09 +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.

# OpenFang WebSocket 协议实际实现
> **重要**: OpenFang 实际的 WebSocket 协议与官方文档有差异。本文档记录实际测试验证的协议格式。
**测试日期**: 2026-03-14
**OpenFang 版本**: 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. 检查 `~/.openfang/.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 | 初始版本,记录协议差异和实际实现 |