@louloulinx/metagpt 0.1.3

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 (113) hide show
  1. package/.eslintrc.json +23 -0
  2. package/.prettierrc +7 -0
  3. package/LICENSE +21 -0
  4. package/README-CN.md +754 -0
  5. package/README.md +238 -0
  6. package/bun.lock +1023 -0
  7. package/doc/TutorialAssistant.md +114 -0
  8. package/doc/VercelLLMProvider.md +164 -0
  9. package/eslint.config.js +55 -0
  10. package/examples/data-interpreter-example.ts +173 -0
  11. package/examples/qwen-direct-example.ts +60 -0
  12. package/examples/qwen-example.ts +62 -0
  13. package/examples/tutorial-assistant-example.ts +97 -0
  14. package/jest.config.ts +22 -0
  15. package/output/tutorials/Go/350/257/255/350/250/200/347/274/226/347/250/213/346/225/231/347/250/213_2025-02-25T09-35-15-436Z.md +2208 -0
  16. package/output/tutorials/Rust/346/225/231/347/250/213_2025-02-25T08-27-27-632Z.md +1967 -0
  17. package/output/tutorials//345/246/202/344/275/225/344/275/277/347/224/250TypeScript/345/274/200/345/217/221Node.js/345/272/224/347/224/250_2025-02-25T08-14-39-605Z.md +1721 -0
  18. package/output/tutorials//346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/346/225/231/347/250/213_2025-02-25T10-45-03-605Z.md +902 -0
  19. package/output/tutorials//346/232/250/345/215/227/345/244/247/345/255/246/346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/345/244/215/350/257/225/350/265/204/346/226/231_2025-02-25T11-16-59-133Z.md +719 -0
  20. package/package.json +58 -0
  21. package/plan-cn.md +321 -0
  22. package/plan.md +154 -0
  23. package/src/actions/analyze-task.ts +65 -0
  24. package/src/actions/base-action.ts +103 -0
  25. package/src/actions/di/execute-nb-code.ts +247 -0
  26. package/src/actions/di/write-analysis-code.ts +234 -0
  27. package/src/actions/write-tutorial.ts +232 -0
  28. package/src/config/browser.ts +33 -0
  29. package/src/config/config.ts +345 -0
  30. package/src/config/embedding.ts +26 -0
  31. package/src/config/llm.ts +36 -0
  32. package/src/config/mermaid.ts +37 -0
  33. package/src/config/omniparse.ts +25 -0
  34. package/src/config/redis.ts +34 -0
  35. package/src/config/s3.ts +33 -0
  36. package/src/config/search.ts +30 -0
  37. package/src/config/workspace.ts +20 -0
  38. package/src/index.ts +40 -0
  39. package/src/management/team.ts +168 -0
  40. package/src/memory/longterm.ts +218 -0
  41. package/src/memory/manager.ts +160 -0
  42. package/src/memory/types.ts +100 -0
  43. package/src/memory/working.ts +154 -0
  44. package/src/monitoring/system.ts +413 -0
  45. package/src/monitoring/types.ts +230 -0
  46. package/src/plugin/manager.ts +79 -0
  47. package/src/plugin/types.ts +114 -0
  48. package/src/provider/vercel-llm.ts +314 -0
  49. package/src/rag/base-rag.ts +194 -0
  50. package/src/rag/document-qa.ts +102 -0
  51. package/src/roles/base-role.ts +155 -0
  52. package/src/roles/data-interpreter.ts +360 -0
  53. package/src/roles/engineer.ts +1 -0
  54. package/src/roles/tutorial-assistant.ts +217 -0
  55. package/src/skills/base-skill.ts +144 -0
  56. package/src/skills/code-review.ts +120 -0
  57. package/src/tools/base-tool.ts +155 -0
  58. package/src/tools/file-system.ts +204 -0
  59. package/src/tools/tool-recommend.d.ts +14 -0
  60. package/src/tools/tool-recommend.ts +31 -0
  61. package/src/types/action.ts +38 -0
  62. package/src/types/config.ts +129 -0
  63. package/src/types/document.ts +354 -0
  64. package/src/types/llm.ts +64 -0
  65. package/src/types/memory.ts +36 -0
  66. package/src/types/message.ts +193 -0
  67. package/src/types/rag.ts +86 -0
  68. package/src/types/role.ts +67 -0
  69. package/src/types/skill.ts +71 -0
  70. package/src/types/task.ts +32 -0
  71. package/src/types/team.ts +55 -0
  72. package/src/types/tool.ts +77 -0
  73. package/src/types/workflow.ts +133 -0
  74. package/src/utils/common.ts +73 -0
  75. package/src/utils/yaml.ts +67 -0
  76. package/src/websocket/browser-client.ts +187 -0
  77. package/src/websocket/client.ts +186 -0
  78. package/src/websocket/server.ts +169 -0
  79. package/src/websocket/types.ts +125 -0
  80. package/src/workflow/executor.ts +193 -0
  81. package/src/workflow/executors/action-executor.ts +72 -0
  82. package/src/workflow/executors/condition-executor.ts +118 -0
  83. package/src/workflow/executors/parallel-executor.ts +201 -0
  84. package/src/workflow/executors/role-executor.ts +76 -0
  85. package/src/workflow/executors/sequence-executor.ts +196 -0
  86. package/tests/actions.test.ts +105 -0
  87. package/tests/benchmark/performance.test.ts +147 -0
  88. package/tests/config/config.test.ts +115 -0
  89. package/tests/config.test.ts +106 -0
  90. package/tests/e2e/setup.ts +74 -0
  91. package/tests/e2e/workflow.test.ts +88 -0
  92. package/tests/llm.test.ts +84 -0
  93. package/tests/memory/memory.test.ts +164 -0
  94. package/tests/memory.test.ts +63 -0
  95. package/tests/monitoring/monitoring.test.ts +225 -0
  96. package/tests/plugin/plugin.test.ts +183 -0
  97. package/tests/provider/bailian-llm.test.ts +98 -0
  98. package/tests/rag.test.ts +162 -0
  99. package/tests/roles.test.ts +88 -0
  100. package/tests/skills.test.ts +166 -0
  101. package/tests/team.test.ts +143 -0
  102. package/tests/tools.test.ts +170 -0
  103. package/tests/types/document.test.ts +181 -0
  104. package/tests/types/message.test.ts +122 -0
  105. package/tests/utils/yaml.test.ts +110 -0
  106. package/tests/utils.test.ts +74 -0
  107. package/tests/websocket/browser-client.test.ts +1 -0
  108. package/tests/websocket/websocket.test.ts +42 -0
  109. package/tests/workflow/parallel-executor.test.ts +224 -0
  110. package/tests/workflow/sequence-executor.test.ts +207 -0
  111. package/tests/workflow.test.ts +290 -0
  112. package/tsconfig.json +27 -0
  113. package/typedoc.json +25 -0
@@ -0,0 +1,187 @@
1
+ import type { Message } from '../types/message';
2
+ import {
3
+ WebSocketMessageSchema,
4
+ WebSocketMessageType,
5
+ } from './types';
6
+ import type {
7
+ WebSocketClient,
8
+ WebSocketClientOptions,
9
+ WebSocketMessage,
10
+ WebSocketStreamOptions,
11
+ } from './types';
12
+
13
+ /**
14
+ * Browser-compatible WebSocket client implementation
15
+ *
16
+ * Features:
17
+ * - Uses native browser WebSocket API
18
+ * - Automatic reconnection with configurable attempts and intervals
19
+ * - Message validation using Zod schema
20
+ * - Support for streaming large messages in chunks
21
+ * - Progress tracking for streaming operations
22
+ * - Error handling and event callbacks
23
+ */
24
+ export class BrowserWebSocketClient implements WebSocketClient {
25
+ private ws: WebSocket | null = null;
26
+ private reconnectAttempts = 0;
27
+ private reconnectTimeout: number | null = null;
28
+
29
+ /**
30
+ * Create a new browser WebSocket client instance
31
+ * @param options - Configuration options for the client
32
+ */
33
+ constructor(private options: WebSocketClientOptions) {
34
+ this.options = {
35
+ reconnect: true,
36
+ reconnectInterval: 1000,
37
+ maxReconnectAttempts: 5,
38
+ ...options,
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Connect to WebSocket server with automatic reconnection support
44
+ * @throws Error if connection fails and max reconnection attempts are reached
45
+ */
46
+ public async connect(): Promise<void> {
47
+ return new Promise((resolve, reject) => {
48
+ try {
49
+ this.ws = new WebSocket(this.options.url, this.options.protocols);
50
+
51
+ // Handle successful connection
52
+ this.ws.onopen = () => {
53
+ this.reconnectAttempts = 0;
54
+ this.options.onConnect?.();
55
+ resolve();
56
+ };
57
+
58
+ // Handle incoming messages with validation
59
+ this.ws.onmessage = (event: MessageEvent) => {
60
+ try {
61
+ const message = WebSocketMessageSchema.parse(JSON.parse(event.data));
62
+ this.options.onMessage?.(message);
63
+ } catch (error: unknown) {
64
+ const message = error instanceof Error ? error.message : String(error);
65
+ this.options.onError?.(new Error(`Invalid message format: ${message}`));
66
+ }
67
+ };
68
+
69
+ // Handle connection errors
70
+ this.ws.onerror = (event: Event) => {
71
+ const error = new Error('WebSocket connection error');
72
+ this.options.onError?.(error);
73
+ reject(error);
74
+ };
75
+
76
+ // Handle disconnection and reconnection
77
+ this.ws.onclose = () => {
78
+ this.options.onDisconnect?.();
79
+ if (this.options.reconnect && this.reconnectAttempts < this.options.maxReconnectAttempts!) {
80
+ this.reconnectTimeout = window.setTimeout(() => {
81
+ this.reconnectAttempts++;
82
+ this.connect().catch(error => {
83
+ if (error instanceof Error) {
84
+ this.options.onError?.(error);
85
+ } else {
86
+ this.options.onError?.(new Error(String(error)));
87
+ }
88
+ });
89
+ }, this.options.reconnectInterval);
90
+ }
91
+ };
92
+ } catch (error: unknown) {
93
+ if (error instanceof Error) {
94
+ reject(error);
95
+ } else {
96
+ reject(new Error(String(error)));
97
+ }
98
+ }
99
+ });
100
+ }
101
+
102
+ /**
103
+ * Disconnect from WebSocket server and cleanup resources
104
+ */
105
+ public async disconnect(): Promise<void> {
106
+ if (this.reconnectTimeout !== null) {
107
+ window.clearTimeout(this.reconnectTimeout);
108
+ this.reconnectTimeout = null;
109
+ }
110
+
111
+ if (this.ws) {
112
+ this.ws.close();
113
+ this.ws = null;
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Send a message to the WebSocket server
119
+ * @param message - Message to send (either Message or WebSocketMessage format)
120
+ * @throws Error if client is not connected
121
+ */
122
+ public async send(message: Message | WebSocketMessage): Promise<void> {
123
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
124
+ throw new Error('WebSocket is not connected');
125
+ }
126
+
127
+ const wsMessage = 'type' in message ? message : {
128
+ type: WebSocketMessageType.MESSAGE,
129
+ payload: message,
130
+ timestamp: Date.now(),
131
+ id: crypto.randomUUID(),
132
+ };
133
+
134
+ this.ws.send(JSON.stringify(wsMessage));
135
+ }
136
+
137
+ /**
138
+ * Stream a large message in chunks with progress tracking
139
+ * @param message - Message to stream
140
+ * @param options - Streaming options (chunk size, delay, progress callback)
141
+ * @yields Each chunk of the message
142
+ */
143
+ public async *stream(
144
+ message: Message,
145
+ options: WebSocketStreamOptions = {}
146
+ ): AsyncIterableIterator<string> {
147
+ const {
148
+ chunkSize = 1024,
149
+ delay = 0,
150
+ onProgress,
151
+ } = options;
152
+
153
+ const content = message.content;
154
+ const totalChunks = Math.ceil(content.length / chunkSize);
155
+
156
+ for (let i = 0; i < totalChunks; i++) {
157
+ const chunk = content.slice(i * chunkSize, (i + 1) * chunkSize);
158
+ const progress = Math.round(((i + 1) / totalChunks) * 100);
159
+
160
+ await this.send({
161
+ type: i === totalChunks - 1 ? WebSocketMessageType.STREAM_END : WebSocketMessageType.STREAM,
162
+ payload: {
163
+ ...message,
164
+ content: chunk,
165
+ progress,
166
+ },
167
+ timestamp: Date.now(),
168
+ id: crypto.randomUUID(),
169
+ });
170
+
171
+ onProgress?.(progress);
172
+ yield chunk;
173
+
174
+ if (delay > 0) {
175
+ await new Promise(resolve => setTimeout(resolve, delay));
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Check if client is currently connected to the server
182
+ * @returns true if connected, false otherwise
183
+ */
184
+ public isConnected(): boolean {
185
+ return this.ws?.readyState === WebSocket.OPEN;
186
+ }
187
+ }
@@ -0,0 +1,186 @@
1
+ import WebSocket from 'ws';
2
+ import type { Message } from '../types/message';
3
+ import {
4
+ WebSocketMessageSchema,
5
+ WebSocketMessageType,
6
+ } from './types';
7
+ import type {
8
+ WebSocketClient,
9
+ WebSocketClientOptions,
10
+ WebSocketMessage,
11
+ WebSocketStreamOptions,
12
+ } from './types';
13
+
14
+ /**
15
+ * WebSocket client implementation with reconnection and streaming support
16
+ *
17
+ * Features:
18
+ * - Automatic reconnection with configurable attempts and intervals
19
+ * - Message validation using Zod schema
20
+ * - Support for streaming large messages in chunks
21
+ * - Progress tracking for streaming operations
22
+ * - Error handling and event callbacks
23
+ */
24
+ export class WebSocketClientImpl implements WebSocketClient {
25
+ private ws: WebSocket | null = null;
26
+ private reconnectAttempts = 0;
27
+ private reconnectTimeout: ReturnType<typeof setTimeout> | null = null;
28
+
29
+ /**
30
+ * Create a new WebSocket client instance
31
+ * @param options - Configuration options for the client
32
+ */
33
+ constructor(private options: WebSocketClientOptions) {
34
+ this.options = {
35
+ reconnect: true,
36
+ reconnectInterval: 1000,
37
+ maxReconnectAttempts: 5,
38
+ ...options,
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Connect to WebSocket server with automatic reconnection support
44
+ * @throws Error if connection fails and max reconnection attempts are reached
45
+ */
46
+ public async connect(): Promise<void> {
47
+ return new Promise((resolve, reject) => {
48
+ try {
49
+ this.ws = new WebSocket(this.options.url, this.options.protocols);
50
+
51
+ // Handle successful connection
52
+ this.ws.on('open', () => {
53
+ this.reconnectAttempts = 0;
54
+ this.options.onConnect?.();
55
+ resolve();
56
+ });
57
+
58
+ // Handle incoming messages with validation
59
+ this.ws.on('message', (data: string) => {
60
+ try {
61
+ const message = WebSocketMessageSchema.parse(JSON.parse(data));
62
+ this.options.onMessage?.(message);
63
+ } catch (error: unknown) {
64
+ const message = error instanceof Error ? error.message : String(error);
65
+ this.options.onError?.(new Error(`Invalid message format: ${message}`));
66
+ }
67
+ });
68
+
69
+ // Handle connection errors
70
+ this.ws.on('error', (error: Error) => {
71
+ this.options.onError?.(error);
72
+ reject(error);
73
+ });
74
+
75
+ // Handle disconnection and reconnection
76
+ this.ws.on('close', () => {
77
+ this.options.onDisconnect?.();
78
+ if (this.options.reconnect && this.reconnectAttempts < this.options.maxReconnectAttempts!) {
79
+ this.reconnectTimeout = setTimeout(() => {
80
+ this.reconnectAttempts++;
81
+ this.connect().catch(error => {
82
+ if (error instanceof Error) {
83
+ this.options.onError?.(error);
84
+ } else {
85
+ this.options.onError?.(new Error(String(error)));
86
+ }
87
+ });
88
+ }, this.options.reconnectInterval);
89
+ }
90
+ });
91
+ } catch (error: unknown) {
92
+ if (error instanceof Error) {
93
+ reject(error);
94
+ } else {
95
+ reject(new Error(String(error)));
96
+ }
97
+ }
98
+ });
99
+ }
100
+
101
+ /**
102
+ * Disconnect from WebSocket server and cleanup resources
103
+ */
104
+ public async disconnect(): Promise<void> {
105
+ if (this.reconnectTimeout) {
106
+ clearTimeout(this.reconnectTimeout);
107
+ this.reconnectTimeout = null;
108
+ }
109
+
110
+ if (this.ws) {
111
+ this.ws.close();
112
+ this.ws = null;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Send a message to the WebSocket server
118
+ * @param message - Message to send (either Message or WebSocketMessage format)
119
+ * @throws Error if client is not connected
120
+ */
121
+ public async send(message: Message | WebSocketMessage): Promise<void> {
122
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
123
+ throw new Error('WebSocket is not connected');
124
+ }
125
+
126
+ const wsMessage = 'type' in message ? message : {
127
+ type: WebSocketMessageType.MESSAGE,
128
+ payload: message,
129
+ timestamp: Date.now(),
130
+ id: crypto.randomUUID(),
131
+ };
132
+
133
+ this.ws.send(JSON.stringify(wsMessage));
134
+ }
135
+
136
+ /**
137
+ * Stream a large message in chunks with progress tracking
138
+ * @param message - Message to stream
139
+ * @param options - Streaming options (chunk size, delay, progress callback)
140
+ * @yields Each chunk of the message
141
+ */
142
+ public async *stream(
143
+ message: Message,
144
+ options: WebSocketStreamOptions = {}
145
+ ): AsyncIterableIterator<string> {
146
+ const {
147
+ chunkSize = 1024,
148
+ delay = 0,
149
+ onProgress,
150
+ } = options;
151
+
152
+ const content = message.content;
153
+ const totalChunks = Math.ceil(content.length / chunkSize);
154
+
155
+ for (let i = 0; i < totalChunks; i++) {
156
+ const chunk = content.slice(i * chunkSize, (i + 1) * chunkSize);
157
+ const progress = Math.round(((i + 1) / totalChunks) * 100);
158
+
159
+ await this.send({
160
+ type: i === totalChunks - 1 ? WebSocketMessageType.STREAM_END : WebSocketMessageType.STREAM,
161
+ payload: {
162
+ ...message,
163
+ content: chunk,
164
+ progress,
165
+ },
166
+ timestamp: Date.now(),
167
+ id: crypto.randomUUID(),
168
+ });
169
+
170
+ onProgress?.(progress);
171
+ yield chunk;
172
+
173
+ if (delay > 0) {
174
+ await new Promise(resolve => setTimeout(resolve, delay));
175
+ }
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Check if client is currently connected to the server
181
+ * @returns true if connected, false otherwise
182
+ */
183
+ public isConnected(): boolean {
184
+ return this.ws?.readyState === WebSocket.OPEN;
185
+ }
186
+ }
@@ -0,0 +1,169 @@
1
+ import { WebSocketServer as WSServer } from 'ws';
2
+ import type { Message } from '../types/message';
3
+ import {
4
+ WebSocketMessageSchema,
5
+ WebSocketMessageType,
6
+ } from './types';
7
+ import type {
8
+ WebSocketMessage,
9
+ WebSocketServer,
10
+ WebSocketServerOptions,
11
+ } from './types';
12
+
13
+ /**
14
+ * WebSocket server implementation with client management and broadcasting support
15
+ *
16
+ * Features:
17
+ * - Client connection management
18
+ * - Message validation using Zod schema
19
+ * - Broadcasting to all connected clients
20
+ * - Automatic cleanup of disconnected clients
21
+ * - Error handling and event callbacks
22
+ */
23
+ export class WebSocketServerImpl implements WebSocketServer {
24
+ private wss: WSServer | null = null;
25
+ private clients: Set<WebSocket> = new Set();
26
+
27
+ /**
28
+ * Create a new WebSocket server instance
29
+ * @param options - Configuration options for the server
30
+ */
31
+ constructor(private options: WebSocketServerOptions) {}
32
+
33
+ /**
34
+ * Start the WebSocket server and begin accepting connections
35
+ * @throws Error if server fails to start
36
+ */
37
+ public async start(): Promise<void> {
38
+ return new Promise((resolve, reject) => {
39
+ try {
40
+ this.wss = new WSServer({
41
+ port: this.options.port,
42
+ host: this.options.host,
43
+ path: this.options.path,
44
+ });
45
+
46
+ // Handle new client connections
47
+ this.wss.on('connection', (client: WebSocket) => {
48
+ this.clients.add(client);
49
+ this.options.onConnection?.(client);
50
+
51
+ // Handle incoming messages with validation
52
+ client.on('message', async (data: string) => {
53
+ try {
54
+ const message = WebSocketMessageSchema.parse(JSON.parse(data));
55
+ this.options.onMessage?.(message, client);
56
+ } catch (error: unknown) {
57
+ const message = error instanceof Error ? error.message : String(error);
58
+ this.options.onError?.(new Error(`Invalid message format: ${message}`));
59
+ }
60
+ });
61
+
62
+ // Remove client on disconnection
63
+ client.on('close', () => {
64
+ this.clients.delete(client);
65
+ });
66
+
67
+ // Handle client errors and cleanup
68
+ client.on('error', (error: Error) => {
69
+ this.options.onError?.(error);
70
+ this.clients.delete(client);
71
+ });
72
+ });
73
+
74
+ // Handle server errors
75
+ this.wss.on('error', (error: Error) => {
76
+ this.options.onError?.(error);
77
+ reject(error);
78
+ });
79
+
80
+ // Server is ready to accept connections
81
+ this.wss.on('listening', () => {
82
+ resolve();
83
+ });
84
+ } catch (error: unknown) {
85
+ if (error instanceof Error) {
86
+ reject(error);
87
+ } else {
88
+ reject(new Error(String(error)));
89
+ }
90
+ }
91
+ });
92
+ }
93
+
94
+ /**
95
+ * Stop the WebSocket server and close all client connections
96
+ * @throws Error if server fails to stop cleanly
97
+ */
98
+ public async stop(): Promise<void> {
99
+ return new Promise((resolve, reject) => {
100
+ if (!this.wss) {
101
+ resolve();
102
+ return;
103
+ }
104
+
105
+ this.wss.close((error) => {
106
+ if (error) {
107
+ reject(error);
108
+ } else {
109
+ this.wss = null;
110
+ this.clients.clear();
111
+ resolve();
112
+ }
113
+ });
114
+ });
115
+ }
116
+
117
+ /**
118
+ * Broadcast a message to all connected clients
119
+ * @param message - Message to broadcast (either Message or WebSocketMessage format)
120
+ * Automatically removes disconnected clients during broadcast
121
+ */
122
+ public async broadcast(message: Message | WebSocketMessage): Promise<void> {
123
+ const wsMessage = 'type' in message ? message : {
124
+ type: WebSocketMessageType.MESSAGE,
125
+ payload: message,
126
+ timestamp: Date.now(),
127
+ id: crypto.randomUUID(),
128
+ };
129
+
130
+ const data = JSON.stringify(wsMessage);
131
+ const deadClients = new Set<WebSocket>();
132
+
133
+ // Send message to all connected clients
134
+ for (const client of this.clients) {
135
+ try {
136
+ if (client.readyState === WebSocket.OPEN) {
137
+ client.send(data);
138
+ } else {
139
+ deadClients.add(client);
140
+ }
141
+ } catch (error: unknown) {
142
+ const message = error instanceof Error ? error.message : String(error);
143
+ this.options.onError?.(new Error(`Failed to send message to client: ${message}`));
144
+ deadClients.add(client);
145
+ }
146
+ }
147
+
148
+ // Clean up dead clients
149
+ for (const client of deadClients) {
150
+ this.clients.delete(client);
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Get array of all currently connected clients
156
+ * @returns Array of WebSocket client instances
157
+ */
158
+ public getClients(): WebSocket[] {
159
+ return Array.from(this.clients);
160
+ }
161
+
162
+ /**
163
+ * Check if server is currently running
164
+ * @returns true if server is running, false otherwise
165
+ */
166
+ public isRunning(): boolean {
167
+ return this.wss !== null;
168
+ }
169
+ }
@@ -0,0 +1,125 @@
1
+ import { z } from 'zod';
2
+ import type { Message } from '../types/message';
3
+
4
+ /**
5
+ * WebSocket message types for different communication scenarios
6
+ */
7
+ export enum WebSocketMessageType {
8
+ /** Connection established */
9
+ CONNECT = 'connect',
10
+ /** Connection terminated */
11
+ DISCONNECT = 'disconnect',
12
+ /** Regular message */
13
+ MESSAGE = 'message',
14
+ /** Error occurred */
15
+ ERROR = 'error',
16
+ /** Streaming chunk */
17
+ STREAM = 'stream',
18
+ /** End of stream */
19
+ STREAM_END = 'stream_end',
20
+ }
21
+
22
+ /**
23
+ * Schema for WebSocket messages with validation
24
+ */
25
+ export const WebSocketMessageSchema = z.object({
26
+ /** Message type from WebSocketMessageType enum */
27
+ type: z.nativeEnum(WebSocketMessageType),
28
+ /** Message payload - can be any valid JSON data */
29
+ payload: z.any(),
30
+ /** Timestamp of message creation */
31
+ timestamp: z.number().default(() => Date.now()),
32
+ /** Unique message identifier */
33
+ id: z.string().uuid().default(() => crypto.randomUUID()),
34
+ });
35
+
36
+ /**
37
+ * WebSocket message type
38
+ */
39
+ export type WebSocketMessage = z.infer<typeof WebSocketMessageSchema>;
40
+
41
+ /**
42
+ * Configuration options for WebSocket client
43
+ */
44
+ export interface WebSocketClientOptions {
45
+ /** WebSocket server URL */
46
+ url: string;
47
+ /** WebSocket protocols */
48
+ protocols?: string | string[];
49
+ /** Whether to attempt reconnection on disconnect */
50
+ reconnect?: boolean;
51
+ /** Interval between reconnection attempts in ms */
52
+ reconnectInterval?: number;
53
+ /** Maximum number of reconnection attempts */
54
+ maxReconnectAttempts?: number;
55
+ /** Callback for received messages */
56
+ onMessage?: (message: WebSocketMessage) => void;
57
+ /** Callback for errors */
58
+ onError?: (error: Error) => void;
59
+ /** Callback for successful connection */
60
+ onConnect?: () => void;
61
+ /** Callback for disconnection */
62
+ onDisconnect?: () => void;
63
+ }
64
+
65
+ /**
66
+ * Configuration options for WebSocket server
67
+ */
68
+ export interface WebSocketServerOptions {
69
+ /** Port to listen on */
70
+ port: number;
71
+ /** Host to bind to */
72
+ host?: string;
73
+ /** URL path for WebSocket endpoint */
74
+ path?: string;
75
+ /** Callback for new client connections */
76
+ onConnection?: (client: WebSocket) => void;
77
+ /** Callback for received messages */
78
+ onMessage?: (message: WebSocketMessage, client: WebSocket) => void;
79
+ /** Callback for errors */
80
+ onError?: (error: Error) => void;
81
+ }
82
+
83
+ /**
84
+ * Options for streaming messages over WebSocket
85
+ */
86
+ export interface WebSocketStreamOptions {
87
+ /** Size of each chunk in bytes */
88
+ chunkSize?: number;
89
+ /** Delay between chunks in ms */
90
+ delay?: number;
91
+ /** Callback for streaming progress */
92
+ onProgress?: (progress: number) => void;
93
+ }
94
+
95
+ /**
96
+ * Interface for WebSocket client implementation
97
+ */
98
+ export interface WebSocketClient {
99
+ /** Connect to WebSocket server */
100
+ connect(): Promise<void>;
101
+ /** Disconnect from WebSocket server */
102
+ disconnect(): Promise<void>;
103
+ /** Send a message */
104
+ send(message: Message | WebSocketMessage): Promise<void>;
105
+ /** Stream a message in chunks */
106
+ stream(message: Message, options?: WebSocketStreamOptions): AsyncIterableIterator<string>;
107
+ /** Check connection status */
108
+ isConnected(): boolean;
109
+ }
110
+
111
+ /**
112
+ * Interface for WebSocket server implementation
113
+ */
114
+ export interface WebSocketServer {
115
+ /** Start the WebSocket server */
116
+ start(): Promise<void>;
117
+ /** Stop the WebSocket server */
118
+ stop(): Promise<void>;
119
+ /** Broadcast a message to all clients */
120
+ broadcast(message: Message | WebSocketMessage): Promise<void>;
121
+ /** Get list of connected clients */
122
+ getClients(): WebSocket[];
123
+ /** Check server status */
124
+ isRunning(): boolean;
125
+ }