openclaw-plugin-fast-task 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +826 -20
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # OpenClaw Plugin - Fast Task
2
2
 
3
- OpenClaw 插件,支持通过 WebSocket 读写 workspace 文件。
3
+ OpenClaw 插件,支持通过 WebSocket 进行节点注册、点对点聊天以及 workspace 文件操作。
4
4
 
5
5
  ## 功能特性
6
6
 
7
- - ✅ **WebSocket 通信** - 与 WebSocket 服务器通信
8
- - ✅ **Workspace 文件操作** - 读写 OpenClaw workspace 文件(AGENTS.md, SOUL.md, USER.md 等)
9
- - ✅ **节点注册** - 向服务器注册节点信息
10
- - ✅ **动态配置** - 从配置文件动态获取 workspace 路径
7
+ - ✅ **WebSocket 通信** - 与 WebSocket 服务器建立持久连接
8
+ - ✅ **节点注册 (whoIAm)** - 自动向服务器注册节点身份和配置
9
+ - ✅ **点对点聊天** - 支持与 Agent 进行实时对话
10
+ - ✅ **Workspace 文件操作** - 读写 OpenClaw workspace 文件
11
+ - ✅ **Agent 管理** - 列出、查询 Agent 信息和绑定关系
12
+ - ✅ **自动重连** - 连接断开时自动重连
11
13
 
12
14
  ## 安装
13
15
 
@@ -17,11 +19,14 @@ openclaw plugins install openclaw-plugin-fast-task
17
19
 
18
20
  # 或从 npm 安装
19
21
  npm install openclaw-plugin-fast-task
20
- ```
21
22
 
22
- ## 使用
23
+ # 本地开发
24
+ npm run build
25
+ npm pack
26
+ openclaw plugins install ./openclaw-plugin-fast-task-1.0.0.tgz
27
+ ```
23
28
 
24
- ### 配置
29
+ ## 配置
25
30
 
26
31
  在 OpenClaw 配置文件中添加:
27
32
 
@@ -46,10 +51,365 @@ npm install openclaw-plugin-fast-task
46
51
  }
47
52
  ```
48
53
 
49
- ### WebSocket 命令
54
+ **配置说明:**
55
+ - `wsHost`: WebSocket 服务器地址
56
+ - `enabled`: 是否启用该通道
57
+ - `dmPolicy`: 私聊策略(`open`/`allowlist`/`pairing`)
58
+
59
+ ---
60
+
61
+ ## 核心功能
62
+
63
+ ### 动态 Client ID 设计
64
+
65
+ 本插件采用**动态 Client ID** 架构,所有消息路由由 WebSocket 服务器统一管理。
66
+
67
+ **设计优势:**
68
+ - ✅ **解耦客户端和服务端**:客户端不需要预设自己的 ID 或目标 ID
69
+ - ✅ **灵活的路由**:服务器可以根据业务逻辑动态管理消息路由
70
+ - ✅ **易于扩展**:支持多租户、负载均衡、消息广播等高级功能
71
+ - ✅ **自动分配**:新连接自动获得唯一 ID,无需手动配置
72
+
73
+ **工作原理:**
74
+
75
+ 1. **连接建立**:客户端连接到 WebSocket 服务器
76
+ 2. **ID 分配**:服务器为每个连接分配唯一的 `client_id`(如 `ws_client_001`)
77
+ 3. **消息转发**:
78
+ - 客户端发送消息时不包含 `from` 字段
79
+ - 服务器在转发时自动添加 `from: <client_id>`
80
+ 4. **回复路由**:
81
+ - 插件回复时使用 `to: <message.from>`
82
+ - 服务器根据 `to` 字段将消息路由到对应的客户端
83
+
84
+ **客户端视角:**
85
+ ```javascript
86
+ // 客户端只发送核心数据,不需要关心 from/to
87
+ ws.send(JSON.stringify({
88
+ type: 'direct',
89
+ data: {
90
+ chatType: 'toAgent',
91
+ content: '你好'
92
+ }
93
+ }));
94
+
95
+ // 服务器会自动添加 from 字段转发给 Agent
96
+ ```
97
+
98
+ **服务器职责:**
99
+ ```javascript
100
+ // 服务器维护 client_id 映射
101
+ const clients = new Map(); // ws -> client_id
102
+ ws.on('connection', (socket) => {
103
+ const clientId = `ws_client_${Date.now()}_${Math.random()}`;
104
+ clients.set(socket, clientId);
105
+
106
+ // 转发消息时添加 from
107
+ socket.on('message', (data) => {
108
+ const msg = JSON.parse(data);
109
+ msg.from = clientId; // 添加 from 字段
110
+ forwardToAgent(msg);
111
+ });
112
+ });
113
+ ```
114
+
115
+ ---
116
+
117
+ ### 1. 节点注册 (whoIAm)
118
+
119
+ 当 WebSocket 连接建立后,服务器发送 `welcome` 消息,插件自动响应 `whoIAm` 消息进行节点注册。
120
+
121
+ #### 服务器发送 welcome 消息
122
+ ```json
123
+ {
124
+ "type": "welcome",
125
+ "timestamp": "2026-03-27T12:00:00Z"
126
+ }
127
+ ```
128
+
129
+ #### 插件响应 whoIAm 注册
130
+ ```json
131
+ {
132
+ "type": "whoIAm",
133
+ "data": {
134
+ "chatType": "register",
135
+ "cli": "agent",
136
+ "config": {
137
+ "agents": {
138
+ "list": [
139
+ {
140
+ "id": "main",
141
+ "name": "主智能体",
142
+ "model": "claude-sonnet-4-6"
143
+ }
144
+ ]
145
+ },
146
+ "bindings": [...],
147
+ "channels": {...}
148
+ }
149
+ }
150
+ }
151
+ ```
152
+
153
+ **whoIAm 注册信息包含:**
154
+ - `chatType`: 固定为 "register"
155
+ - `cli`: 客户端类型(agent)
156
+ - `config`: 完整的 OpenClaw 配置(包含所有 Agent、绑定、通道配置)
157
+
158
+ **注册后服务器可以:**
159
+ - 识别节点身份和可用的 Agent
160
+ - 查询 Agent 列表和详细信息
161
+ - 了解 Agent 的绑定关系
162
+ - 执行 workspace 文件操作
163
+
164
+ ---
165
+
166
+ ### 2. 点对点聊天
167
+
168
+ #### 动态 Client ID 机制
169
+
170
+ WebSocket 服务器为每个连接的客户端动态分配 `client_id`,消息的 `from` 和 `to` 字段使用这些动态 ID 进行路由。
171
+
172
+ **工作流程:**
173
+ ```
174
+ 客户端 A 连接 ──────> 服务器分配: client_id = "ws_client_001"
175
+ 客户端 B 连接 ──────> 服务器分配: client_id = "ws_client_002"
176
+
177
+ 服务器转发消息时动态设置 from/to:
178
+ - 消息来自客户端 A ──> from: "ws_client_001"
179
+ - 回复给客户端 A ────> to: "ws_client_001"
180
+ ```
181
+
182
+ #### 发送消息给 Agent
183
+
184
+ **WebSocket 服务器向插件转发消息:**
185
+
186
+ ```json
187
+ {
188
+ "type": "direct",
189
+ "from": "ws_client_001",
190
+ "timestamp": "2026-03-27T12:00:00Z",
191
+ "data": {
192
+ "chatType": "toAgent",
193
+ "content": "你好,请介绍一下自己",
194
+ "files": {
195
+ "url": "https://example.com/image.png",
196
+ "fileName": "image.png"
197
+ }
198
+ }
199
+ }
200
+ ```
201
+
202
+ **字段说明:**
203
+ - `type`: 消息类型,固定为 "direct"
204
+ - `from`: 发送者的动态 client_id(由 WebSocket 服务器分配)
205
+ - `data.chatType`: 固定为 "toAgent"
206
+ - `data.content`: 消息文本内容
207
+ - `data.files`: 可选的媒体文件(图片、文档等)
208
+
209
+ **注意:** `from` 字段是 WebSocket 服务器在转发消息时动态添加的,表示消息来源的 client_id。
210
+
211
+ #### Agent 回复消息
212
+
213
+ Agent 处理完消息后,回复给原始发送者:
214
+
215
+ ```json
216
+ {
217
+ "type": "direct",
218
+ "to": "ws_client_001",
219
+ "timestamp": "2026-03-27T12:00:01Z",
220
+ "data": {
221
+ "chatType": "agent_chat",
222
+ "payload": {
223
+ "text": "你好!我是 OpenClaw 智能体,可以帮助你..."
224
+ },
225
+ "info": "回复成功",
226
+ "content": ""
227
+ }
228
+ }
229
+ ```
230
+
231
+ **回复逻辑:**
232
+ - 插件收到消息时,`message.from` 是发送者的 client_id
233
+ - Agent 处理完后,设置 `to: message.from` 回复给原发送者
234
+ - 不需要手动指定接收者,由 WebSocket 服务器根据 `to` 字段的路由转发
235
+
236
+ **回复类型:**
237
+ 1. **agent_chat**: 正常回复
238
+ ```json
239
+ {
240
+ "chatType": "agent_chat",
241
+ "payload": { "text": "回复内容" }
242
+ }
243
+ ```
244
+
245
+ 2. **agent_error**: 错误信息
246
+ ```json
247
+ {
248
+ "chatType": "agent_error",
249
+ "error": "错误描述",
250
+ "info": "额外信息"
251
+ }
252
+ ```
253
+
254
+ 3. **agent_idle**: Agent 空闲状态
255
+ ```json
256
+ {
257
+ "chatType": "agent_idle",
258
+ "content": "agent is idle"
259
+ }
260
+ ```
261
+
262
+ ---
263
+
264
+ ### 3. 网关命令 (Gateway Commands)
265
+
266
+ 通过 `chatType: "toCmd"` 执行各种系统命令。
267
+
268
+ #### 3.1 列出所有 Agent
269
+
270
+ **客户端发送请求(不需要 from 字段):**
271
+ ```json
272
+ {
273
+ "type": "direct",
274
+ "data": {
275
+ "chatType": "toCmd",
276
+ "gateWay": {
277
+ "cmd": "agents.list"
278
+ }
279
+ }
280
+ }
281
+ ```
282
+
283
+ **服务器添加 from 字段后转发给插件:**
284
+ ```json
285
+ {
286
+ "type": "direct",
287
+ "from": "ws_client_001", // 服务器添加
288
+ "data": {
289
+ "chatType": "toCmd",
290
+ "gateWay": {
291
+ "cmd": "agents.list"
292
+ }
293
+ }
294
+ }
295
+ ```
296
+
297
+ **插件响应(使用 to 字段路由回原客户端):**
298
+ ```json
299
+ {
300
+ "type": "direct",
301
+ "to": "ws_client_001",
302
+ "data": {
303
+ "chatType": "agents.list",
304
+ "agentIds": ["main", "helper", "coder"]
305
+ }
306
+ }
307
+ ```
308
+
309
+ #### 3.2 查询 Agent 信息
310
+
311
+ **客户端请求:**
312
+ ```json
313
+ {
314
+ "type": "direct",
315
+ "data": {
316
+ "chatType": "toCmd",
317
+ "gateWay": {
318
+ "cmd": "agent.info",
319
+ "id": "main"
320
+ }
321
+ }
322
+ }
323
+ ```
324
+
325
+ **服务器转发(添加 from):**
326
+ ```json
327
+ {
328
+ "type": "direct",
329
+ "from": "ws_client_001",
330
+ "data": {
331
+ "chatType": "toCmd",
332
+ "gateWay": {
333
+ "cmd": "agent.info",
334
+ "id": "main"
335
+ }
336
+ }
337
+ }
338
+ ```
339
+
340
+ **插件响应:**
341
+ ```json
342
+ {
343
+ "type": "direct",
344
+ "to": "ws_client_001",
345
+ "data": {
346
+ "chatType": "agent.info",
347
+ "info": {
348
+ "id": "main",
349
+ "name": "主智能体",
350
+ "model": "claude-sonnet-4-6",
351
+ "description": "负责主要对话"
352
+ }
353
+ }
354
+ }
355
+ ```
356
+
357
+ #### 3.3 查询 Agent 绑定关系
358
+
359
+ **客户端请求:**
360
+ ```json
361
+ {
362
+ "type": "direct",
363
+ "data": {
364
+ "chatType": "toCmd",
365
+ "gateWay": {
366
+ "cmd": "agents.bindings"
367
+ }
368
+ }
369
+ }
370
+ ```
371
+
372
+ **服务器转发(添加 from):**
373
+ ```json
374
+ {
375
+ "type": "direct",
376
+ "from": "ws_client_001",
377
+ "data": {
378
+ "chatType": "toCmd",
379
+ "gateWay": {
380
+ "cmd": "agents.bindings"
381
+ }
382
+ }
383
+ }
384
+ ```
385
+
386
+ **插件响应:**
387
+ ```json
388
+ {
389
+ "type": "direct",
390
+ "to": "ws_client_001",
391
+ "data": {
392
+ "chatType": "agents.bindings",
393
+ "info": [
394
+ {
395
+ "agentId": "main",
396
+ "match": {
397
+ "channel": "fast_task",
398
+ "accountId": "default"
399
+ }
400
+ }
401
+ ]
402
+ }
403
+ }
404
+ ```
405
+
406
+ ---
407
+
408
+ ### 4. Workspace 文件操作
50
409
 
51
- #### 读取 Workspace 文件
410
+ #### 4.1 读取 Workspace 文件
52
411
 
412
+ **客户端请求:**
53
413
  ```json
54
414
  {
55
415
  "type": "direct",
@@ -63,8 +423,41 @@ npm install openclaw-plugin-fast-task
63
423
  }
64
424
  ```
65
425
 
66
- #### 写入 Workspace 文件
426
+ **服务器转发(添加 from):**
427
+ ```json
428
+ {
429
+ "type": "direct",
430
+ "from": "ws_client_001",
431
+ "data": {
432
+ "chatType": "toCmd",
433
+ "gateWay": {
434
+ "cmd": "workspace.read",
435
+ "file": "AGENTS.md"
436
+ }
437
+ }
438
+ }
439
+ ```
440
+
441
+ **插件响应:**
442
+ ```json
443
+ {
444
+ "type": "direct",
445
+ "to": "ws_client_001",
446
+ "data": {
447
+ "chatType": "workspace.read",
448
+ "file": "AGENTS.md",
449
+ "success": true,
450
+ "exists": true,
451
+ "content": "# Agent 指南\n...",
452
+ "path": "/path/to/workspace/AGENTS.md",
453
+ "message": "Successfully read AGENTS.md"
454
+ }
455
+ }
456
+ ```
457
+
458
+ #### 4.2 写入 Workspace 文件
67
459
 
460
+ **客户端请求:**
68
461
  ```json
69
462
  {
70
463
  "type": "direct",
@@ -73,23 +466,436 @@ npm install openclaw-plugin-fast-task
73
466
  "gateWay": {
74
467
  "cmd": "workspace.write",
75
468
  "file": "AGENTS.md",
76
- "content": "# 新内容"
469
+ "content": "# 新的 Agent 配置\n..."
470
+ }
471
+ }
472
+ }
473
+ ```
474
+
475
+ **服务器转发(添加 from):**
476
+ ```json
477
+ {
478
+ "type": "direct",
479
+ "from": "ws_client_001",
480
+ "data": {
481
+ "chatType": "toCmd",
482
+ "gateWay": {
483
+ "cmd": "workspace.write",
484
+ "file": "AGENTS.md",
485
+ "content": "# 新的 Agent 配置\n..."
486
+ }
487
+ }
488
+ }
489
+ ```
490
+
491
+ **插件响应:**
492
+ ```json
493
+ {
494
+ "type": "direct",
495
+ "to": "ws_client_001",
496
+ "data": {
497
+ "chatType": "workspace.write",
498
+ "file": "AGENTS.md",
499
+ "success": true,
500
+ "path": "/path/to/workspace/AGENTS.md",
501
+ "message": "Successfully wrote to AGENTS.md"
502
+ }
503
+ }
504
+ ```
505
+
506
+ #### 4.3 列出所有 Workspace 文件
507
+
508
+ **客户端请求:**
509
+ ```json
510
+ {
511
+ "type": "direct",
512
+ "data": {
513
+ "chatType": "toCmd",
514
+ "gateWay": {
515
+ "cmd": "workspace.list"
516
+ }
517
+ }
518
+ }
519
+ ```
520
+
521
+ **服务器转发(添加 from):**
522
+ ```json
523
+ {
524
+ "type": "direct",
525
+ "from": "ws_client_001",
526
+ "data": {
527
+ "chatType": "toCmd",
528
+ "gateWay": {
529
+ "cmd": "workspace.list"
77
530
  }
78
531
  }
79
532
  }
80
533
  ```
81
534
 
535
+ **插件响应:**
536
+ ```json
537
+ {
538
+ "type": "direct",
539
+ "to": "ws_client_001",
540
+ "data": {
541
+ "chatType": "workspace.list",
542
+ "success": true,
543
+ "files": [
544
+ {
545
+ "name": "AGENTS.md",
546
+ "exists": true,
547
+ "path": "/workspace/AGENTS.md"
548
+ },
549
+ {
550
+ "name": "SOUL.md",
551
+ "exists": true,
552
+ "path": "/workspace/SOUL.md"
553
+ }
554
+ ],
555
+ "summary": {
556
+ "total": 8,
557
+ "existing": 5,
558
+ "missing": 3
559
+ }
560
+ }
561
+ }
562
+ ```
563
+
564
+ ---
565
+
82
566
  ## 支持的 Workspace 文件
83
567
 
84
- - `AGENTS.md` - 智能体操作指南
85
- - `SOUL.md` - 人设、语气和边界
86
- - `TOOLS.md` - 工具说明
87
- - `IDENTITY.md` - 智能体名称和风格
88
- - `USER.md` - 用户信息
89
- - `HEARTBEAT.md` - 心跳检查清单
90
- - `BOOT.md` - 启动检查清单
91
- - `MEMORY.md` - 长期记忆
568
+ | 文件名 | 说明 |
569
+ |--------|------|
570
+ | `AGENTS.md` | 智能体操作指南 |
571
+ | `SOUL.md` | 人设、语气和边界 |
572
+ | `TOOLS.md` | 工具说明 |
573
+ | `IDENTITY.md` | 智能体名称和风格 |
574
+ | `USER.md` | 用户信息 |
575
+ | `HEARTBEAT.md` | 心跳检查清单 |
576
+ | `BOOT.md` | 启动检查清单 |
577
+ | `MEMORY.md` | 长期记忆 |
578
+
579
+ ---
580
+
581
+ ## 消息流程图
582
+
583
+ ```
584
+ ┌─────────────────────────────────────────────────────────────┐
585
+ │ WebSocket 服务器 │
586
+ │ - 为每个连接动态分配 client_id │
587
+ │ - 转发消息时添加 from/to 字段 │
588
+ └────────┬────────────────────────────────────────────────────┘
589
+
590
+ │ 1. 客户端连接
591
+ │ 服务器分配: client_id = "ws_client_001"
592
+
593
+ ┌─────────────────────────────────────────────────────────────┐
594
+ │ 发送 welcome 消息 │
595
+ │ { type: "welcome" } │
596
+ └────────┬────────────────────────────────────────────────────┘
597
+
598
+ │ 2. 插件响应 whoIAm 注册
599
+
600
+ ┌─────────────────────────────────────────────────────────────┐
601
+ │ { type: "whoIAm", data: { chatType: "register", ... } } │
602
+ │ - 服务器保存节点配置 │
603
+ │ - 服务器记录 client_id 与节点的映射 │
604
+ └────────┬────────────────────────────────────────────────────┘
605
+
606
+ │ 3. 其他客户端发送消息
607
+
608
+ ┌─────────────────────────────────────────────────────────────┐
609
+ │ 客户端 A (ws_client_002) 发送: │
610
+ │ { type: "direct", data: { chatType: "toAgent", ... } } │
611
+ └────────┬────────────────────────────────────────────────────┘
612
+
613
+ │ 4. 服务器添加 from 字段并转发
614
+
615
+ ┌─────────────────────────────────────────────────────────────┐
616
+ │ { │
617
+ │ type: "direct", │
618
+ │ from: "ws_client_002", ← 服务器添加的动态 client_id │
619
+ │ data: { chatType: "toAgent", ... } │
620
+ │ } │
621
+ └────────┬────────────────────────────────────────────────────┘
622
+
623
+ │ 5. 插件收到消息,处理 Agent 推理
624
+
625
+ ┌─────────────────────────────────────────────────────────────┐
626
+ │ Agent 推理完成,准备回复 │
627
+ │ - 读取 message.from = "ws_client_002" │
628
+ │ - 设置回复的 to = "ws_client_002" │
629
+ └────────┬────────────────────────────────────────────────────┘
630
+
631
+ │ 6. 发送回复
632
+
633
+ ┌─────────────────────────────────────────────────────────────┐
634
+ │ { │
635
+ │ type: "direct", │
636
+ │ to: "ws_client_002", ← 回复到原发送者的 client_id │
637
+ │ data: { chatType: "agent_chat", ... } │
638
+ │ } │
639
+ └────────┬────────────────────────────────────────────────────┘
640
+
641
+ │ 7. 服务器根据 to 字段路由回客户端 A
642
+
643
+ ┌─────────────────────────────────────────────────────────────┐
644
+ │ 客户端 A 收到回复 │
645
+ └─────────────────────────────────────────────────────────────┘
646
+ ```
647
+
648
+ **关键点:**
649
+ - 服务器为每个连接分配唯一的 `client_id`
650
+ - `from` 和 `to` 字段由服务器动态管理,客户端不需要预设
651
+ - 插件回复时使用 `message.from` 作为 `to`,确保回复给正确的发送者
652
+ - 服务器根据 `to` 字段将消息路由到对应的客户端
653
+
654
+ ---
655
+
656
+ ## 完整使用示例
657
+
658
+ ### 场景 1: 启动并注册节点
659
+
660
+ ```javascript
661
+ // 服务器端代码示例
662
+ const WebSocket = require('ws');
663
+ const wss = new WebSocket.Server({ port: 8765 });
664
+
665
+ // 为每个连接动态分配 client_id
666
+ let clientIdCounter = 0;
667
+ const clientMap = new Map(); // ws -> client_id
668
+
669
+ wss.on('connection', (ws) => {
670
+ const clientId = `ws_client_${++clientIdCounter}`;
671
+ clientMap.set(ws, clientId);
672
+
673
+ console.log(`新节点连接: ${clientId}`);
674
+
675
+ // 发送欢迎消息,触发节点注册
676
+ ws.send(JSON.stringify({
677
+ type: 'welcome',
678
+ timestamp: new Date().toISOString()
679
+ }));
680
+
681
+ // 监听节点的 whoIAm 注册
682
+ ws.on('message', (data) => {
683
+ const msg = JSON.parse(data);
684
+
685
+ if (msg.type === 'whoIAm') {
686
+ console.log(`节点 ${clientId} 注册成功`);
687
+ // 保存节点信息
688
+ registeredNodes.set(clientId, msg.data.config);
689
+ }
690
+ });
691
+
692
+ // 清理断开的连接
693
+ ws.on('close', () => {
694
+ clientMap.delete(ws);
695
+ registeredNodes.delete(clientId);
696
+ console.log(`节点 ${clientId} 断开连接`);
697
+ });
698
+ });
699
+
700
+ // 获取连接的 client_id
701
+ function getClientId(ws) {
702
+ return clientMap.get(ws);
703
+ }
704
+ ```
705
+
706
+ ### 场景 2: 与 Agent 对话(使用动态 client_id)
707
+
708
+ ```javascript
709
+ // WebSocket 服务器转发客户端消息
710
+ function forwardMessageToAgent(clientWs, userMessage) {
711
+ const fromClientId = getClientId(clientWs);
712
+
713
+ // 服务器添加 from 字段后转发给 Agent
714
+ const message = {
715
+ type: 'direct',
716
+ from: fromClientId, // 动态分配的 client_id
717
+ timestamp: new Date().toISOString(),
718
+ data: {
719
+ chatType: 'toAgent',
720
+ content: userMessage
721
+ }
722
+ };
723
+
724
+ // 发送给 Agent 插件
725
+ agentWs.send(JSON.stringify(message));
726
+ }
727
+
728
+ // Agent 回复时,使用 to 字段路由回原客户端
729
+ // (插件代码中:to: message.from)
730
+ ```
731
+
732
+ ### 场景 3: 查询并操作 Workspace
733
+
734
+ ```javascript
735
+ // 客户端通过服务器查询 Workspace
736
+ const ws = new WebSocket('ws://localhost:8765');
737
+
738
+ ws.on('open', () => {
739
+ // 1. 列出所有文件(不需要 from,服务器自动添加)
740
+ ws.send(JSON.stringify({
741
+ type: 'direct',
742
+ data: {
743
+ chatType: 'toCmd',
744
+ gateWay: { cmd: 'workspace.list' }
745
+ }
746
+ }));
747
+ });
748
+
749
+ // 服务器在转发时添加 from 字段
750
+ // Agent 回复时使用 to 字段路由回正确的客户端
751
+ ```
752
+
753
+ ---
754
+
755
+ ## 开发和调试
756
+
757
+ ### 构建项目
758
+
759
+ ```bash
760
+ # 安装依赖
761
+ npm install
762
+
763
+ # 开发模式(自动编译)
764
+ npm run dev
765
+
766
+ # 生产构建
767
+ npm run build
768
+
769
+ # 清理构建文件
770
+ npm run clean
771
+ ```
772
+
773
+ ### 查看日志
774
+
775
+ ```bash
776
+ # 查看 Gateway 日志
777
+ openclaw logs --grep "fast_task"
778
+
779
+ # 查看 WebSocket 连接状态
780
+ openclaw logs --grep "WebSocket"
781
+
782
+ # 查看 Agent 交互
783
+ openclaw logs --grep "Agent"
784
+ ```
785
+
786
+ ### 测试连接
787
+
788
+ ```bash
789
+ # 使用 wscat 测试 WebSocket 连接
790
+ wscat -c ws://localhost:8765
791
+
792
+ # 连接后发送测试消息
793
+ > {"type":"direct","data":{"chatType":"toCmd","gateWay":{"cmd":"agents.list"}}}
794
+ ```
795
+
796
+ ---
797
+
798
+ ## 架构说明
799
+
800
+ ### 核心模块
801
+
802
+ - **ws_client.ts**: WebSocket 客户端实现
803
+ - 连接管理(自动重连)
804
+ - 消息收发
805
+ - whoIAm 注册逻辑
806
+
807
+ - **channel_gateway.ts**: Gateway 适配器
808
+ - 启动/停止账户
809
+ - 管理 WebSocket 生命周期
810
+
811
+ - **workspace.ts**: Workspace 文件操作
812
+ - 读写配置文件
813
+ - 文件验证
814
+
815
+ ### 消息类型 (MessageType)
816
+
817
+ | Type | 说明 |
818
+ |------|------|
819
+ | `welcome` | 服务器欢迎消息,触发注册 |
820
+ | `whoIAm` | 节点身份注册 |
821
+ | `direct` | 点对点消息(聊天或命令) |
822
+
823
+ ### ChatType 分类
824
+
825
+ | ChatType | 分类 | 说明 |
826
+ |----------|------|------|
827
+ | `register` | 注册 | whoIAm 注册 |
828
+ | `toAgent` | 聊天 | 发送到 Agent 处理 |
829
+ | `toCmd` | 命令 | 执行网关命令 |
830
+ | `agent_chat` | 回复 | Agent 正常回复 |
831
+ | `agent_error` | 回复 | Agent 错误信息 |
832
+ | `agent_idle` | 回复 | Agent 空闲状态 |
833
+
834
+ ---
835
+
836
+ ## 常见问题
837
+
838
+ ### Q: 如何确认节点已成功注册?
839
+
840
+ A: 检查日志中是否有 "✓ WebSocket 已连接" 和 whoIAm 消息已发送的日志。
841
+
842
+ ### Q: Agent 不回复消息怎么办?
843
+
844
+ A: 检查:
845
+ 1. 消息格式是否正确(chatType: "toAgent")
846
+ 2. 服务器是否正确添加了 `from` 字段
847
+ 3. Agent 是否已正确绑定
848
+ 4. 插件是否正确读取了 `message.from` 并设置回复的 `to`
849
+
850
+ ### Q: 如何重启 WebSocket 连接?
851
+
852
+ A: 使用 OpenClaw 命令:
853
+ ```bash
854
+ openclaw gateway restart
855
+ ```
856
+
857
+ ### Q: 支持多节点吗?
858
+
859
+ A: 是的,每个节点在连接时都会发送自己的 whoIAm 信息,服务器可以为每个连接分配独立的 client_id 并管理多个节点。
860
+
861
+ ### Q: from 和 to 字段是由谁管理的?
862
+
863
+ A: 由 **WebSocket 服务器** 统一管理:
864
+ - 服务器在转发客户端消息时添加 `from` 字段
865
+ - 插件回复时使用 `to` 字段指定接收者
866
+ - 服务器根据 `to` 字段将消息路由到正确的客户端
867
+
868
+ ### Q: 客户端需要知道自己的 client_id 吗?
869
+
870
+ A: 不需要。客户端只需要发送消息内容,服务器会自动处理路由。但在调试时,可以通过服务器的响应消息中的 `to` 字段了解自己的 client_id。
871
+
872
+ ### Q: 如何实现消息广播?
873
+
874
+ A: 服务器可以在转发消息时将 `to` 设置为特殊值(如 `"broadcast"` 或 `null`),插件收到后可以识别并广播到所有连接的客户端。
875
+
876
+ ### Q: 连接断开后 client_id 会保留吗?
877
+
878
+ A: 这取决于服务器实现。建议:
879
+ - 短期断开:服务器保留 client_id 映射,重连后恢复
880
+ - 长期断开:清除映射,重新连接时分配新的 client_id
881
+ - 可以使用心跳机制检测连接状态
882
+
883
+ ---
884
+
885
+ ## 相关文档
886
+
887
+ - [WebSocket 客户端详解](docs/websocket_client_消息调度详解.md)
888
+ - [自建 WS 服务 IM 调度](docs/自建ws服务im调度.md)
889
+ - [IM Agent 设计方案](docs/im_agent设计方案.md)
890
+
891
+ ---
92
892
 
93
893
  ## 许可证
94
894
 
95
895
  MIT
896
+
897
+ ---
898
+
899
+ ## 作者
900
+
901
+ XPDD <1239694214@qq.com>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-plugin-fast-task",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "OpenClaw plugin for fast task management with WebSocket support and workspace file operations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",