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
This commit is contained in:
282
docs/knowledge-base/websocket-protocol.md
Normal file
282
docs/knowledge-base/websocket-protocol.md
Normal file
@@ -0,0 +1,282 @@
|
||||
# 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 | 初始版本,记录协议差异和实际实现 |
|
||||
Reference in New Issue
Block a user