feat(hands): restructure Hands UI with Chinese localization

Major changes:
- Add HandList.tsx component for left sidebar
- Add HandTaskPanel.tsx for middle content area
- Restructure Sidebar tabs: 分身/HANDS/Workflow
- Remove Hands tab from RightPanel
- Localize all UI text to Chinese
- Archive legacy OpenClaw documentation
- Add Hands integration lessons document
- Update feature checklist with new components

UI improvements:
- Left sidebar now shows Hands list with status icons
- Middle area shows selected Hand's tasks and results
- Consistent styling with Tailwind CSS
- Chinese status labels and buttons

Documentation:
- Create docs/archive/openclaw-legacy/ for old docs
- Add docs/knowledge-base/hands-integration-lessons.md
- Update docs/knowledge-base/feature-checklist.md
- Update docs/knowledge-base/README.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-14 23:16:32 +08:00
parent 67e1da635d
commit 07079293f4
126 changed files with 36229 additions and 1035 deletions

View 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 | 初始版本,记录协议差异和实际实现 |