@lcap/wave-sandbox-sdk 0.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.
package/README.md ADDED
@@ -0,0 +1,1154 @@
1
+ # Wave Sandbox SDK
2
+
3
+ 浏览器端的 Wave Sandbox SDK,用于与 Wave Sandbox Server 进行通信,提供文件系统操作、命令执行、端口监听和项目管理等功能。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install wave-sandbox-sdk
9
+ # 或
10
+ pnpm add wave-sandbox-sdk
11
+ # 或
12
+ yarn add wave-sandbox-sdk
13
+ ```
14
+
15
+ ## 快速开始
16
+
17
+ ```typescript
18
+ import { WaveSandboxClient } from 'wave-sandbox-sdk';
19
+
20
+ // 创建客户端实例
21
+ const client = new WaveSandboxClient({
22
+ url: 'http://localhost:3030',
23
+ projectId: 'optional-project-id', // 可选,用于工作空间模式
24
+ options: {
25
+ autoConnect: true,
26
+ reconnection: true,
27
+ reconnectionDelay: 1000,
28
+ reconnectionAttempts: 5,
29
+ },
30
+ });
31
+
32
+ // 监听连接事件
33
+ client.onConnect(() => {
34
+ console.log('已连接到服务器');
35
+ });
36
+
37
+ // 使用各个模块...
38
+ ```
39
+
40
+ ## API 文档
41
+
42
+ ### WaveSandboxClient
43
+
44
+ 主客户端类,提供与服务器的连接和各个功能模块。
45
+
46
+ #### 构造函数
47
+
48
+ ```typescript
49
+ new WaveSandboxClient(options: SDKOptions)
50
+ ```
51
+
52
+ **参数:**
53
+
54
+ - `options.url` (string): 服务器地址,例如 `'http://localhost:3030'`
55
+ - `options.projectId` (string, 可选): 项目 ID,用于工作空间模式
56
+ - `options.options` (object, 可选): Socket.IO 连接选项
57
+ - `autoConnect` (boolean): 是否自动连接,默认 `true`
58
+ - `reconnection` (boolean): 是否自动重连,默认 `true`
59
+ - `reconnectionDelay` (number): 重连延迟(毫秒),默认 `1000`
60
+ - `reconnectionAttempts` (number): 最大重连次数,默认 `5`
61
+
62
+ #### 方法
63
+
64
+ - `connect()`: 手动连接到服务器
65
+ - `disconnect()`: 断开连接
66
+ - `onConnect(callback)`: 监听连接事件,返回取消监听的函数
67
+ - `onDisconnect(callback)`: 监听断开连接事件,返回取消监听的函数
68
+ - `onError(callback)`: 监听错误事件,返回取消监听的函数
69
+
70
+ #### 属性
71
+
72
+ - `connected` (boolean): 是否已连接
73
+ - `id` (string | undefined): Socket ID
74
+ - `exec`: 命令执行模块
75
+ - `fileSystem` / `fs`: 文件系统模块(`fs` 是 `fileSystem` 的简写别名)
76
+ - `port`: 端口监听模块
77
+ - `project`: 项目模块
78
+ - `agent`: Agent 模块
79
+
80
+ ---
81
+
82
+ ### 命令执行模块 (ExecModule)
83
+
84
+ 执行命令并监听输出。
85
+
86
+ #### 方法
87
+
88
+ ##### `exec(sessionId: string, command: string): Promise<number>`
89
+
90
+ 执行命令。
91
+
92
+ **参数:**
93
+ - `sessionId`: 会话 ID,用于标识命令执行会话
94
+ - `command`: 要执行的命令
95
+
96
+ **返回:** Promise<number> 命令退出码
97
+
98
+ **示例:**
99
+ ```typescript
100
+ const exitCode = await client.exec.exec('session-1', 'ls -la');
101
+ console.log('退出码:', exitCode);
102
+ ```
103
+
104
+ ##### `abort(sessionId: string): Promise<void>`
105
+
106
+ 中止命令执行。
107
+
108
+ **参数:**
109
+ - `sessionId`: 会话 ID
110
+
111
+ **示例:**
112
+ ```typescript
113
+ await client.exec.abort('session-1');
114
+ ```
115
+
116
+ ##### `onOutput(sessionId: string, callback: (data: Uint8Array) => void): () => void`
117
+
118
+ 监听命令输出。
119
+
120
+ **参数:**
121
+ - `sessionId`: 会话 ID
122
+ - `callback`: 输出回调函数,接收 Uint8Array 数据
123
+
124
+ **返回:** 取消监听的函数
125
+
126
+ **示例:**
127
+ ```typescript
128
+ const unsubscribe = client.exec.onOutput('session-1', (data) => {
129
+ const text = new TextDecoder().decode(data);
130
+ console.log('输出:', text);
131
+ });
132
+
133
+ // 取消监听
134
+ unsubscribe();
135
+ ```
136
+
137
+ **完整示例:**
138
+ ```typescript
139
+ const sessionId = 'my-session';
140
+
141
+ // 监听输出
142
+ const unsubscribe = client.exec.onOutput(sessionId, (data) => {
143
+ const text = new TextDecoder().decode(data);
144
+ process.stdout.write(text);
145
+ });
146
+
147
+ try {
148
+ // 执行命令
149
+ const exitCode = await client.exec.exec(sessionId, 'npm install');
150
+ console.log(`命令执行完成,退出码: ${exitCode}`);
151
+ } catch (error) {
152
+ console.error('执行失败:', error);
153
+ } finally {
154
+ unsubscribe();
155
+ }
156
+ ```
157
+
158
+ ---
159
+
160
+ ### 文件系统模块 (FileSystemModule)
161
+
162
+ 提供文件系统操作功能。
163
+
164
+ #### 方法
165
+
166
+ ##### `stat(filePath: string): Promise<FileStat>`
167
+
168
+ 获取文件状态信息。
169
+
170
+ **参数:**
171
+ - `filePath`: 文件路径
172
+
173
+ **返回:** Promise<FileStat> 文件状态信息
174
+
175
+ **示例:**
176
+ ```typescript
177
+ const stat = await client.fs.stat('package.json');
178
+ console.log('文件类型:', stat.type);
179
+ console.log('文件大小:', stat.size);
180
+ console.log('修改时间:', new Date(stat.mtime));
181
+ ```
182
+
183
+ ##### `readFile(filePath: string): Promise<string>`
184
+
185
+ 读取文件内容(文本形式)。
186
+
187
+ **参数:**
188
+ - `filePath`: 文件路径
189
+
190
+ **返回:** Promise<string> 文件文本内容
191
+
192
+ **示例:**
193
+ ```typescript
194
+ const content = await client.fs.readFile('package.json');
195
+ console.log(content);
196
+ ```
197
+
198
+ ##### `read(filePath: string, asText?: boolean): Promise<string | Blob>`
199
+
200
+ 读取文件。
201
+
202
+ **参数:**
203
+ - `filePath`: 文件路径
204
+ - `asText`: 是否以文本形式读取,默认 `false`(返回 Blob)
205
+
206
+ **返回:** Promise<string | Blob> 文件内容
207
+
208
+ **示例:**
209
+ ```typescript
210
+ // 读取文本文件
211
+ const text = await client.fs.read('readme.md', true);
212
+
213
+ // 读取二进制文件
214
+ const blob = await client.fs.read('image.png');
215
+ const url = URL.createObjectURL(blob);
216
+ ```
217
+
218
+ ##### `readdir(filePath: string): Promise<DirectoryItem[]>`
219
+
220
+ 读取目录内容。
221
+
222
+ **参数:**
223
+ - `filePath`: 目录路径
224
+
225
+ **返回:** Promise<DirectoryItem[]> 目录项数组,每个项为 `[文件名, 文件类型]`
226
+
227
+ **示例:**
228
+ ```typescript
229
+ const items = await client.fs.readdir('.');
230
+ items.forEach(([name, type]) => {
231
+ console.log(`${name} - 类型: ${type}`);
232
+ });
233
+ ```
234
+
235
+ ##### `writeFile(filePath: string, data: string | Blob | ArrayBuffer | Uint8Array, chunkSize?: number): Promise<void>`
236
+
237
+ 写入文件(流式)。
238
+
239
+ **参数:**
240
+ - `filePath`: 文件路径
241
+ - `data`: 文件数据(可以是字符串、Blob、ArrayBuffer 或 Uint8Array)
242
+ - `chunkSize`: 分块大小(字节),默认 64KB
243
+
244
+ **示例:**
245
+ ```typescript
246
+ // 写入文本
247
+ await client.fs.writeFile('test.txt', 'Hello World');
248
+
249
+ // 写入二进制数据
250
+ const buffer = new Uint8Array([1, 2, 3, 4, 5]);
251
+ await client.fs.writeFile('data.bin', buffer);
252
+
253
+ // 写入 Blob
254
+ const blob = new Blob(['content'], { type: 'text/plain' });
255
+ await client.fs.writeFile('file.txt', blob);
256
+ ```
257
+
258
+ ##### `mkdir(filePath: string): Promise<string | undefined>`
259
+
260
+ 创建目录。
261
+
262
+ **参数:**
263
+ - `filePath`: 目录路径
264
+
265
+ **示例:**
266
+ ```typescript
267
+ await client.fs.mkdir('new-folder');
268
+ ```
269
+
270
+ ##### `rename(oldPath: string, newPath: string): Promise<void>`
271
+
272
+ 重命名文件或目录。
273
+
274
+ **参数:**
275
+ - `oldPath`: 原路径
276
+ - `newPath`: 新路径
277
+
278
+ **示例:**
279
+ ```typescript
280
+ await client.fs.rename('old.txt', 'new.txt');
281
+ ```
282
+
283
+ ##### `rm(filePath: string): Promise<void>`
284
+
285
+ 删除文件或目录。
286
+
287
+ **参数:**
288
+ - `filePath`: 文件或目录路径
289
+
290
+ **示例:**
291
+ ```typescript
292
+ await client.fs.rm('file.txt');
293
+ await client.fs.rm('directory');
294
+ ```
295
+
296
+ ##### `watch(paths: string[], ignored: string[], callback: (event: FileChangeEvent) => void): () => void`
297
+
298
+ 监听文件变化。
299
+
300
+ **参数:**
301
+ - `paths`: 要监听的文件路径数组
302
+ - `ignored`: 要忽略的文件路径数组
303
+ - `callback`: 文件变化回调函数
304
+
305
+ **返回:** 取消监听的函数
306
+
307
+ **示例:**
308
+ ```typescript
309
+ const unsubscribe = client.fs.watch(
310
+ ['.'],
311
+ ['node_modules', '.git'],
312
+ (event) => {
313
+ console.log(`文件 ${event.type}: ${event.path}`);
314
+ }
315
+ );
316
+
317
+ // 取消监听
318
+ unsubscribe();
319
+ ```
320
+
321
+ ---
322
+
323
+ ### 端口监听模块 (PortModule)
324
+
325
+ 监听端口状态变化。
326
+
327
+ #### 方法
328
+
329
+ ##### `getPorts(count?: number): Promise<number[]>`
330
+
331
+ 获取可用端口。
332
+
333
+ **参数:**
334
+ - `count`: 需要获取的端口数量,默认 `2`
335
+
336
+ **返回:** Promise<number[]> 可用端口数组
337
+
338
+ **示例:**
339
+ ```typescript
340
+ const ports = await client.port.getPorts(3);
341
+ console.log('可用端口:', ports); // [6606, 6607, 6608]
342
+ ```
343
+
344
+ ##### `startWatch(ports: number[]): Promise<void>`
345
+
346
+ 开始监听端口状态。
347
+
348
+ **参数:**
349
+ - `ports`: 要监听的端口数组
350
+
351
+ **示例:**
352
+ ```typescript
353
+ await client.port.startWatch([3000, 3001]);
354
+ ```
355
+
356
+ ##### `stopWatch(): Promise<void>`
357
+
358
+ 停止监听端口状态。
359
+
360
+ **示例:**
361
+ ```typescript
362
+ await client.port.stopWatch();
363
+ ```
364
+
365
+ ##### `onStatusChanged(callback: (event: PortStatusChangedEvent) => void): () => void`
366
+
367
+ 监听端口状态变化。
368
+
369
+ **参数:**
370
+ - `callback`: 端口状态变化回调函数
371
+
372
+ **返回:** 取消监听的函数
373
+
374
+ **示例:**
375
+ ```typescript
376
+ const unsubscribe = client.port.onStatusChanged((event) => {
377
+ console.log(`端口 ${event.port} 状态: ${event.type}`);
378
+ });
379
+
380
+ // 取消监听
381
+ unsubscribe();
382
+ ```
383
+
384
+ **完整示例:**
385
+ ```typescript
386
+ // 获取可用端口
387
+ const ports = await client.port.getPorts(2);
388
+
389
+ // 监听端口状态变化
390
+ const unsubscribe = client.port.onStatusChanged((event) => {
391
+ if (event.type === 'open') {
392
+ console.log(`端口 ${event.port} 已打开`);
393
+ } else {
394
+ console.log(`端口 ${event.port} 已关闭`);
395
+ }
396
+ });
397
+
398
+ // 开始监听
399
+ await client.port.startWatch(ports);
400
+
401
+ // 停止监听
402
+ await client.port.stopWatch();
403
+ unsubscribe();
404
+ ```
405
+
406
+ ---
407
+
408
+ ### 项目模块 (ProjectModule)
409
+
410
+ 管理项目信息和文件。
411
+
412
+ #### 方法
413
+
414
+ ##### `getInfo(): Promise<ProjectInfo>`
415
+
416
+ 获取项目信息。
417
+
418
+ **返回:** Promise<ProjectInfo> 项目信息
419
+
420
+ **示例:**
421
+ ```typescript
422
+ const info = await client.project.getInfo();
423
+ console.log('项目 ID:', info.projectId);
424
+ console.log('工作目录:', info.workdir);
425
+ console.log('工作空间模式:', info.workspace);
426
+ ```
427
+
428
+ ##### `getFiles(): Promise<ProjectFile[]>`
429
+
430
+ 获取项目文件列表。
431
+
432
+ **返回:** Promise<ProjectFile[]> 项目文件数组
433
+
434
+ **示例:**
435
+ ```typescript
436
+ const files = await client.project.getFiles();
437
+ files.forEach((file) => {
438
+ console.log('文件:', file.path);
439
+ });
440
+ ```
441
+
442
+ ##### `watch(): Promise<void>`
443
+
444
+ 开始监听项目变化。
445
+
446
+ **示例:**
447
+ ```typescript
448
+ await client.project.watch();
449
+ ```
450
+
451
+ ##### `unwatch(): Promise<void>`
452
+
453
+ 停止监听项目变化。
454
+
455
+ **示例:**
456
+ ```typescript
457
+ await client.project.unwatch();
458
+ ```
459
+
460
+ ##### `onFileChange(callback: (event: unknown) => void): () => void`
461
+
462
+ 监听项目文件变化。
463
+
464
+ **参数:**
465
+ - `callback`: 文件变化回调函数
466
+
467
+ **返回:** 取消监听的函数
468
+
469
+ **示例:**
470
+ ```typescript
471
+ const unsubscribe = client.project.onFileChange((event) => {
472
+ console.log('项目文件变化:', event);
473
+ });
474
+
475
+ // 取消监听
476
+ unsubscribe();
477
+ ```
478
+
479
+ ---
480
+
481
+ ### Agent 模块 (AgentModule)
482
+
483
+ 与 AI Agent 进行交互,发送消息并监听 Agent 的各种事件。
484
+
485
+ #### 方法
486
+
487
+ ##### `sendMessage(options: SendMessageOptions): Promise<string>`
488
+
489
+ 发送消息给 Agent。
490
+
491
+ **参数:**
492
+ - `options.id`: 消息 ID
493
+ - `options.sessionId`: 会话 ID
494
+ - `options.message`: 消息内容
495
+ - `options.attachments`: 附件数组(可选)
496
+
497
+ **返回:** Promise<string> 返回 assistantMessageId
498
+
499
+ **示例:**
500
+ ```typescript
501
+ const assistantMessageId = await client.agent.sendMessage({
502
+ id: 'msg-1',
503
+ sessionId: 'session-1',
504
+ message: 'Hello, agent!',
505
+ attachments: [
506
+ {
507
+ path: './file.txt',
508
+ mimeType: 'text/plain',
509
+ },
510
+ ],
511
+ });
512
+ console.log('Assistant Message ID:', assistantMessageId);
513
+ ```
514
+
515
+ ##### `abortMessage(messageId: string): Promise<void>`
516
+
517
+ 中止消息处理。
518
+
519
+ **参数:**
520
+ - `messageId`: 要中止的消息 ID
521
+
522
+ **示例:**
523
+ ```typescript
524
+ await client.agent.abortMessage('msg-1');
525
+ ```
526
+
527
+ ##### `removeSession(sessionId: string): Promise<void>`
528
+
529
+ 删除 session,包括日志记录和 agent 对象。如果当前正在处理该 session 的消息,则抛出错误。
530
+
531
+ **参数:**
532
+ - `sessionId`: 要删除的会话 ID
533
+
534
+ **抛出:**
535
+ - 如果当前正在处理该 session 的消息,则抛出错误
536
+
537
+ **示例:**
538
+ ```typescript
539
+ try {
540
+ await client.agent.removeSession('session-1');
541
+ console.log('Session 已删除');
542
+ } catch (error) {
543
+ console.error('删除失败:', error.message);
544
+ // 如果当前正在处理该 session 的消息,会抛出错误
545
+ }
546
+ ```
547
+
548
+ #### 事件监听
549
+
550
+ ##### `onMessageSend(callback: (event: MessageSendEvent) => void): () => void`
551
+
552
+ 监听消息发送事件。
553
+
554
+ **示例:**
555
+ ```typescript
556
+ const unsubscribe = client.agent.onMessageSend((event) => {
557
+ console.log('消息已发送:', event.assistantMessageId);
558
+ });
559
+ ```
560
+
561
+ ##### `onMessageRunning(callback: (event: MessageRunningEvent) => void): () => void`
562
+
563
+ 监听消息运行事件。
564
+
565
+ **示例:**
566
+ ```typescript
567
+ const unsubscribe = client.agent.onMessageRunning((event) => {
568
+ console.log('消息运行中:', event.assistantMessageId);
569
+ });
570
+ ```
571
+
572
+ ##### `onMessageFinished(callback: (event: MessageFinishedEvent) => void): () => void`
573
+
574
+ 监听消息完成事件。
575
+
576
+ **示例:**
577
+ ```typescript
578
+ const unsubscribe = client.agent.onMessageFinished((event) => {
579
+ console.log('消息完成:', event.status);
580
+ });
581
+ ```
582
+
583
+ ##### `onMessageQueueChanged(callback: (event: MessageQueueChangedEvent) => void): () => void`
584
+
585
+ 监听消息队列变化事件。
586
+
587
+ **示例:**
588
+ ```typescript
589
+ const unsubscribe = client.agent.onMessageQueueChanged((event) => {
590
+ console.log('队列长度:', event.queue.length);
591
+ console.log('当前消息:', event.current);
592
+ });
593
+ ```
594
+
595
+ ##### `onInitializing(callback: (event: InitializingEvent) => void): () => void`
596
+
597
+ 监听 Agent 初始化事件。
598
+
599
+ **示例:**
600
+ ```typescript
601
+ const unsubscribe = client.agent.onInitializing((event) => {
602
+ console.log('Agent 初始化中:', event.sessionId);
603
+ });
604
+ ```
605
+
606
+ ##### `onInitialized(callback: (event: InitializedEvent) => void): () => void`
607
+
608
+ 监听 Agent 初始化完成事件。
609
+
610
+ **示例:**
611
+ ```typescript
612
+ const unsubscribe = client.agent.onInitialized((event) => {
613
+ console.log('Agent 初始化完成:', event.sessionId);
614
+ });
615
+ ```
616
+
617
+ ##### `onMessageBlockAdded(callback: (event: MessageBlockAddedEvent) => void): () => void`
618
+
619
+ 监听消息块添加事件。
620
+
621
+ **示例:**
622
+ ```typescript
623
+ const unsubscribe = client.agent.onMessageBlockAdded((event) => {
624
+ event.data.blocks.forEach((block) => {
625
+ console.log('添加块:', block.type);
626
+ });
627
+ });
628
+ ```
629
+
630
+ ##### `onMessageBlockUpdated(callback: (event: MessageBlockUpdatedEvent) => void): () => void`
631
+
632
+ 监听消息块更新事件(用于流式内容更新)。
633
+
634
+ **示例:**
635
+ ```typescript
636
+ const unsubscribe = client.agent.onMessageBlockUpdated((event) => {
637
+ console.log('消息块更新:', event.data.type, event.data.content);
638
+ });
639
+ ```
640
+
641
+ ##### `onMessageToolBlockUpdated(callback: (event: MessageToolBlockUpdatedEvent) => void): () => void`
642
+
643
+ 监听工具块更新事件。
644
+
645
+ **示例:**
646
+ ```typescript
647
+ const unsubscribe = client.agent.onMessageToolBlockUpdated((event) => {
648
+ console.log('工具块更新:', event.data.name, event.data.stage);
649
+ });
650
+ ```
651
+
652
+ ##### `onMessageSubagentBlockStatusUpdated(callback: (event: MessageSubagentBlockStatusUpdatedEvent) => void): () => void`
653
+
654
+ 监听子代理块状态更新事件。
655
+
656
+ **示例:**
657
+ ```typescript
658
+ const unsubscribe = client.agent.onMessageSubagentBlockStatusUpdated((event) => {
659
+ console.log('子代理状态更新:', event.data.status);
660
+ });
661
+ ```
662
+
663
+ ##### `onMessageSubagentBlockContentUpdated(callback: (event: MessageSubagentBlockContentUpdatedEvent) => void): () => void`
664
+
665
+ 监听子代理块内容更新事件。
666
+
667
+ **示例:**
668
+ ```typescript
669
+ const unsubscribe = client.agent.onMessageSubagentBlockContentUpdated((event) => {
670
+ console.log('子代理内容更新:', event.data.content);
671
+ });
672
+ ```
673
+
674
+ ##### `onMessageErrorBlockAdded(callback: (event: MessageErrorBlockAddedEvent) => void): () => void`
675
+
676
+ 监听错误块添加事件。
677
+
678
+ **示例:**
679
+ ```typescript
680
+ const unsubscribe = client.agent.onMessageErrorBlockAdded((event) => {
681
+ console.error('错误:', event.data.error);
682
+ });
683
+ ```
684
+
685
+ ##### `onMessageCommandOutputMessageAdded(callback: (event: MessageCommandOutputMessageAddedEvent) => void): () => void`
686
+
687
+ 监听命令输出消息添加事件。
688
+
689
+ **示例:**
690
+ ```typescript
691
+ const unsubscribe = client.agent.onMessageCommandOutputMessageAdded((event) => {
692
+ console.log('命令输出开始:', event.data.command);
693
+ });
694
+ ```
695
+
696
+ ##### `onMessageCommandOutputMessageUpdated(callback: (event: MessageCommandOutputMessageUpdatedEvent) => void): () => void`
697
+
698
+ 监听命令输出消息更新事件。
699
+
700
+ **示例:**
701
+ ```typescript
702
+ const unsubscribe = client.agent.onMessageCommandOutputMessageUpdated((event) => {
703
+ console.log('命令输出更新:', event.data.command, event.data.output);
704
+ });
705
+ ```
706
+
707
+ ##### `onMessageCommandOutputMessageCompleted(callback: (event: MessageCommandOutputMessageCompletedEvent) => void): () => void`
708
+
709
+ 监听命令输出消息完成事件。
710
+
711
+ **示例:**
712
+ ```typescript
713
+ const unsubscribe = client.agent.onMessageCommandOutputMessageCompleted((event) => {
714
+ console.log('命令完成:', event.data.command, '退出码:', event.data.exitCode);
715
+ });
716
+ ```
717
+
718
+ ##### `onMcpServersChange(callback: (event: McpServersChangeEvent) => void): () => void`
719
+
720
+ 监听 MCP 服务器变化事件。
721
+
722
+ **示例:**
723
+ ```typescript
724
+ const unsubscribe = client.agent.onMcpServersChange((event) => {
725
+ console.log('MCP 服务器变化:', event.servers);
726
+ });
727
+ ```
728
+
729
+ ##### `onDocumentParseStart(callback: (event: DocumentParseStartEvent) => void): () => void`
730
+
731
+ 监听文档解析开始事件。
732
+
733
+ **示例:**
734
+ ```typescript
735
+ const unsubscribe = client.agent.onDocumentParseStart((event) => {
736
+ console.log('文档解析开始:', event.url, event.mimeType);
737
+ });
738
+ ```
739
+
740
+ ##### `onDocumentParseComplete(callback: (event: DocumentParseCompleteEvent) => void): () => void`
741
+
742
+ 监听文档解析完成事件。
743
+
744
+ **示例:**
745
+ ```typescript
746
+ const unsubscribe = client.agent.onDocumentParseComplete((event) => {
747
+ console.log('文档解析完成:', event.outputPath, `共 ${event.pageCount} 页`);
748
+ });
749
+ ```
750
+
751
+ ##### `onDocumentParseError(callback: (event: DocumentParseErrorEvent) => void): () => void`
752
+
753
+ 监听文档解析错误事件。
754
+
755
+ **示例:**
756
+ ```typescript
757
+ const unsubscribe = client.agent.onDocumentParseError((event) => {
758
+ console.error('文档解析失败:', event.error);
759
+ });
760
+ ```
761
+
762
+ ##### `on<T = unknown>(eventName: string, callback: (event: T) => void): () => void`
763
+
764
+ 通用事件监听方法,用于监听自定义事件。事件名称必须以 `'agent:'` 开头。支持泛型参数指定事件数据类型。
765
+
766
+ **示例:**
767
+ ```typescript
768
+ // 监听自定义事件,使用泛型指定事件类型
769
+ interface CustomEventData {
770
+ data: string;
771
+ timestamp: number;
772
+ }
773
+
774
+ const unsubscribe = client.agent.on<CustomEventData>('agent:custom-event', (event) => {
775
+ console.log('自定义事件:', event.data);
776
+ console.log('时间戳:', event.timestamp);
777
+ // event 的类型自动推断为 CustomEventData,无需类型断言
778
+ });
779
+
780
+ // 监听其他自定义事件,使用泛型
781
+ const unsubscribe2 = client.agent.on<{ message: string }>('agent:another-custom-event', (event) => {
782
+ console.log('消息:', event.message);
783
+ });
784
+
785
+ // 不指定泛型时,event 类型为 unknown
786
+ const unsubscribe3 = client.agent.on('agent:unknown-event', (event) => {
787
+ // event 类型为 unknown,需要类型断言
788
+ const typedEvent = event as { value: number };
789
+ console.log('值:', typedEvent.value);
790
+ });
791
+ ```
792
+
793
+ **完整示例:**
794
+ ```typescript
795
+ const sessionId = 'my-session';
796
+
797
+ // 监听消息完成事件
798
+ const unsubscribeFinished = client.agent.onMessageFinished((event) => {
799
+ console.log('消息处理完成:', event.status);
800
+ });
801
+
802
+ // 监听消息块添加事件
803
+ const unsubscribeBlockAdded = client.agent.onMessageBlockAdded((event) => {
804
+ event.data.blocks.forEach((block) => {
805
+ if (block.type === 'text') {
806
+ console.log('文本块:', block.content);
807
+ } else if (block.type === 'tool') {
808
+ console.log('工具块:', block.name);
809
+ }
810
+ });
811
+ });
812
+
813
+ try {
814
+ // 发送消息
815
+ const assistantMessageId = await client.agent.sendMessage({
816
+ id: 'msg-1',
817
+ sessionId,
818
+ message: '请帮我创建一个文件',
819
+ });
820
+
821
+ console.log('消息已发送,等待处理...');
822
+ } catch (error) {
823
+ console.error('发送失败:', error);
824
+ } finally {
825
+ // 取消监听
826
+ unsubscribeFinished();
827
+ unsubscribeBlockAdded();
828
+ }
829
+ ```
830
+
831
+ ---
832
+
833
+ ## 类型定义
834
+
835
+ ### FileStat
836
+
837
+ ```typescript
838
+ interface FileStat {
839
+ type: FileType; // 文件类型
840
+ size: number; // 文件大小(字节)
841
+ ctime: number; // 创建时间(毫秒时间戳)
842
+ mtime: number; // 修改时间(毫秒时间戳)
843
+ }
844
+ ```
845
+
846
+ ### FileType
847
+
848
+ ```typescript
849
+ enum FileType {
850
+ Unknown = 0,
851
+ File = 1,
852
+ Directory = 2,
853
+ SymbolicLink = 64,
854
+ }
855
+ ```
856
+
857
+ ### FileChangeEvent
858
+
859
+ ```typescript
860
+ interface FileChangeEvent {
861
+ type: 'add' | 'change' | 'unlink' | 'addDir' | 'unlinkDir';
862
+ path: string;
863
+ }
864
+ ```
865
+
866
+ ### PortStatusChangedEvent
867
+
868
+ ```typescript
869
+ interface PortStatusChangedEvent {
870
+ port: number;
871
+ type: 'open' | 'close';
872
+ }
873
+ ```
874
+
875
+ ### ProjectInfo
876
+
877
+ ```typescript
878
+ interface ProjectInfo {
879
+ projectId: string;
880
+ workdir: string;
881
+ workspace: boolean;
882
+ }
883
+ ```
884
+
885
+ ### SendMessageOptions
886
+
887
+ ```typescript
888
+ interface SendMessageOptions {
889
+ id: string;
890
+ sessionId: string;
891
+ message: string;
892
+ attachments?: Attachment[];
893
+ }
894
+ ```
895
+
896
+ ### Attachment
897
+
898
+ ```typescript
899
+ interface Attachment {
900
+ url?: string;
901
+ path?: string;
902
+ mimeType: string;
903
+ content?: string;
904
+ }
905
+ ```
906
+
907
+ ### MessageSendEvent
908
+
909
+ ```typescript
910
+ interface MessageSendEvent {
911
+ sessionId: string;
912
+ assistantMessageId: string;
913
+ senderMessageId: string;
914
+ options: SendMessageOptions;
915
+ }
916
+ ```
917
+
918
+ ### MessageRunningEvent
919
+
920
+ ```typescript
921
+ interface MessageRunningEvent {
922
+ sessionId: string;
923
+ assistantMessageId: string;
924
+ senderMessageId: string;
925
+ }
926
+ ```
927
+
928
+ ### MessageFinishedEvent
929
+
930
+ ```typescript
931
+ interface MessageFinishedEvent {
932
+ sessionId: string;
933
+ assistantMessageId?: string;
934
+ senderMessageId: string;
935
+ status: 'pending' | 'running' | 'finished' | 'error' | 'aborted';
936
+ }
937
+ ```
938
+
939
+ ### MessageQueueChangedEvent
940
+
941
+ ```typescript
942
+ interface MessageQueueChangedEvent {
943
+ queue: ProcessQueueItem[];
944
+ current: {
945
+ sessionId: string;
946
+ assistantMessageId?: string;
947
+ senderMessageId: string;
948
+ };
949
+ }
950
+ ```
951
+
952
+ ### MessageBlockAddedEvent
953
+
954
+ ```typescript
955
+ interface MessageBlockAddedEvent {
956
+ sessionId: string;
957
+ assistantMessageId?: string;
958
+ senderMessageId: string;
959
+ data: {
960
+ blocks: Array<TextBlock | ToolBlock | ErrorBlock | SubagentBlock>;
961
+ };
962
+ }
963
+ ```
964
+
965
+ ### MessageBlockUpdatedEvent
966
+
967
+ ```typescript
968
+ interface MessageBlockUpdatedEvent {
969
+ sessionId: string;
970
+ assistantMessageId?: string;
971
+ senderMessageId: string;
972
+ data: {
973
+ type: 'text';
974
+ content: string;
975
+ };
976
+ }
977
+ ```
978
+
979
+ ### MessageToolBlockUpdatedEvent
980
+
981
+ ```typescript
982
+ interface MessageToolBlockUpdatedEvent {
983
+ sessionId: string;
984
+ assistantMessageId?: string;
985
+ senderMessageId: string;
986
+ data: ToolBlock;
987
+ }
988
+ ```
989
+
990
+ ### DocumentParseStartEvent
991
+
992
+ ```typescript
993
+ interface DocumentParseStartEvent {
994
+ sessionId: string;
995
+ senderMessageId: string;
996
+ index: number;
997
+ url: string;
998
+ mimeType: string;
999
+ }
1000
+ ```
1001
+
1002
+ ### DocumentParseCompleteEvent
1003
+
1004
+ ```typescript
1005
+ interface DocumentParseCompleteEvent {
1006
+ sessionId: string;
1007
+ senderMessageId: string;
1008
+ index: number;
1009
+ url: string;
1010
+ mimeType: string;
1011
+ outputPath: string;
1012
+ contentLength?: number;
1013
+ pageCount?: number;
1014
+ }
1015
+ ```
1016
+
1017
+ ### DocumentParseErrorEvent
1018
+
1019
+ ```typescript
1020
+ interface DocumentParseErrorEvent {
1021
+ sessionId: string;
1022
+ senderMessageId: string;
1023
+ index: number;
1024
+ url: string;
1025
+ mimeType: string;
1026
+ error: string;
1027
+ }
1028
+ ```
1029
+
1030
+ ### AgentEventMap
1031
+
1032
+ Agent 预定义事件名称到事件数据类型的映射,用于类型定义和类型推断。
1033
+
1034
+ ```typescript
1035
+ type AgentEventMap = {
1036
+ 'agent:message-send': MessageSendEvent;
1037
+ 'agent:message-running': MessageRunningEvent;
1038
+ 'agent:message-finished': MessageFinishedEvent;
1039
+ 'agent:message-queue-changed': MessageQueueChangedEvent;
1040
+ 'agent:initializing': InitializingEvent;
1041
+ 'agent:initialized': InitializedEvent;
1042
+ 'agent:message-block-added': MessageBlockAddedEvent;
1043
+ 'agent:message-block-updated': MessageBlockUpdatedEvent;
1044
+ 'agent:message-tool-block-updated': MessageToolBlockUpdatedEvent;
1045
+ 'agent:message-subagent-block-status-updated': MessageSubagentBlockStatusUpdatedEvent;
1046
+ 'agent:message-subagent-block-content-updated': MessageSubagentBlockContentUpdatedEvent;
1047
+ 'agent:message-error-block-added': MessageErrorBlockAddedEvent;
1048
+ 'agent:message-command-output-message-added': MessageCommandOutputMessageAddedEvent;
1049
+ 'agent:message-command-output-message-updated': MessageCommandOutputMessageUpdatedEvent;
1050
+ 'agent:message-command-output-message-completed': MessageCommandOutputMessageCompletedEvent;
1051
+ 'agent:mcp-servers-change': McpServersChangeEvent;
1052
+ 'agent:document-parse-start': DocumentParseStartEvent;
1053
+ 'agent:document-parse-complete': DocumentParseCompleteEvent;
1054
+ 'agent:document-parse-error': DocumentParseErrorEvent;
1055
+ };
1056
+ ```
1057
+
1058
+ ### AgentEventName
1059
+
1060
+ Agent 预定义事件名称类型,是 `AgentEventMap` 的键类型。
1061
+
1062
+ ```typescript
1063
+ type AgentEventName = keyof AgentEventMap;
1064
+ ```
1065
+
1066
+ ---
1067
+
1068
+ ## 完整示例
1069
+
1070
+ ```typescript
1071
+ import { WaveSandboxClient } from 'wave-sandbox-sdk';
1072
+
1073
+ async function main() {
1074
+ // 创建客户端
1075
+ const client = new WaveSandboxClient({
1076
+ url: 'http://localhost:3030',
1077
+ projectId: 'my-project',
1078
+ });
1079
+
1080
+ // 等待连接
1081
+ await new Promise<void>((resolve) => {
1082
+ if (client.connected) {
1083
+ resolve();
1084
+ } else {
1085
+ client.onConnect(() => resolve());
1086
+ }
1087
+ });
1088
+
1089
+ try {
1090
+ // 读取文件
1091
+ const content = await client.fs.readFile('package.json');
1092
+ console.log('文件内容:', content);
1093
+
1094
+ // 写入文件
1095
+ await client.fs.writeFile('test.txt', 'Hello World');
1096
+
1097
+ // 执行命令
1098
+ const sessionId = 'session-1';
1099
+ client.exec.onOutput(sessionId, (data) => {
1100
+ console.log(new TextDecoder().decode(data));
1101
+ });
1102
+ const exitCode = await client.exec.exec(sessionId, 'ls -la');
1103
+ console.log('退出码:', exitCode);
1104
+
1105
+ // 获取可用端口
1106
+ const ports = await client.port.getPorts(2);
1107
+ console.log('可用端口:', ports);
1108
+
1109
+ // 监听文件变化
1110
+ const unsubscribe = client.fs.watch(['.'], ['node_modules'], (event) => {
1111
+ console.log(`文件 ${event.type}: ${event.path}`);
1112
+ });
1113
+
1114
+ // 使用 Agent 模块
1115
+ const sessionId = 'my-session';
1116
+ client.agent.onMessageFinished((event) => {
1117
+ console.log('Agent 消息完成:', event.status);
1118
+ });
1119
+ const assistantMessageId = await client.agent.sendMessage({
1120
+ id: 'msg-1',
1121
+ sessionId,
1122
+ message: 'Hello, agent!',
1123
+ });
1124
+ console.log('Assistant Message ID:', assistantMessageId);
1125
+
1126
+ // 删除 session(确保没有正在处理的消息)
1127
+ try {
1128
+ await client.agent.removeSession(sessionId);
1129
+ console.log('Session 已删除');
1130
+ } catch (error) {
1131
+ console.error('删除失败:', error.message);
1132
+ }
1133
+
1134
+ // 5 秒后取消监听
1135
+ setTimeout(() => {
1136
+ unsubscribe();
1137
+ }, 5000);
1138
+ } catch (error) {
1139
+ console.error('错误:', error);
1140
+ } finally {
1141
+ // 断开连接
1142
+ client.disconnect();
1143
+ }
1144
+ }
1145
+
1146
+ main();
1147
+ ```
1148
+
1149
+ ---
1150
+
1151
+ ## License
1152
+
1153
+ MIT
1154
+