@xalia/agent 0.5.7 → 0.6.0
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 +23 -8
- package/dist/agent/src/agent/agent.js +176 -96
- package/dist/agent/src/agent/agentUtils.js +82 -59
- package/dist/agent/src/agent/compressingContextManager.js +102 -0
- package/dist/agent/src/agent/context.js +189 -0
- package/dist/agent/src/agent/dummyLLM.js +46 -5
- package/dist/agent/src/agent/mcpServerManager.js +23 -24
- package/dist/agent/src/agent/nullAgentEventHandler.js +21 -0
- package/dist/agent/src/agent/nullPlatform.js +14 -0
- package/dist/agent/src/agent/openAILLMStreaming.js +26 -14
- package/dist/agent/src/agent/promptProvider.js +63 -0
- package/dist/agent/src/agent/repeatLLM.js +5 -5
- package/dist/agent/src/agent/sudoMcpServerManager.js +23 -21
- package/dist/agent/src/agent/tokenAuth.js +7 -7
- package/dist/agent/src/agent/tools.js +1 -1
- package/dist/agent/src/chat/client/chatClient.js +733 -0
- package/dist/agent/src/chat/client/connection.js +209 -0
- package/dist/agent/src/chat/client/connection.test.js +188 -0
- package/dist/agent/src/chat/client/constants.js +5 -0
- package/dist/agent/src/chat/client/index.js +15 -0
- package/dist/agent/src/chat/client/interfaces.js +2 -0
- package/dist/agent/src/chat/client/responseHandler.js +105 -0
- package/dist/agent/src/chat/client/sessionClient.js +331 -0
- package/dist/agent/src/chat/client/teamManager.js +2 -0
- package/dist/agent/src/chat/{apiKeyManager.js → data/apiKeyManager.js} +4 -0
- package/dist/agent/src/chat/data/dataModels.js +2 -0
- package/dist/agent/src/chat/data/database.js +749 -0
- package/dist/agent/src/chat/data/dbMcpServerConfigs.js +47 -0
- package/dist/agent/src/chat/protocol/connectionMessages.js +5 -0
- package/dist/agent/src/chat/protocol/constants.js +50 -0
- package/dist/agent/src/chat/protocol/errors.js +22 -0
- package/dist/agent/src/chat/protocol/messages.js +110 -0
- package/dist/agent/src/chat/server/chatContextManager.js +405 -0
- package/dist/agent/src/chat/server/connectionManager.js +352 -0
- package/dist/agent/src/chat/server/connectionManager.test.js +159 -0
- package/dist/agent/src/chat/server/conversation.js +198 -0
- package/dist/agent/src/chat/server/errorUtils.js +23 -0
- package/dist/agent/src/chat/server/openSession.js +869 -0
- package/dist/agent/src/chat/server/server.js +177 -0
- package/dist/agent/src/chat/server/sessionFileManager.js +161 -0
- package/dist/agent/src/chat/server/sessionRegistry.js +700 -0
- package/dist/agent/src/chat/server/sessionRegistry.test.js +97 -0
- package/dist/agent/src/chat/server/test-utils/mockFactories.js +307 -0
- package/dist/agent/src/chat/server/tools.js +243 -0
- package/dist/agent/src/chat/utils/agentSessionMap.js +66 -0
- package/dist/agent/src/chat/utils/approvalManager.js +85 -0
- package/dist/agent/src/{utils → chat/utils}/asyncLock.js +3 -3
- package/dist/agent/src/chat/{asyncQueue.js → utils/asyncQueue.js} +12 -2
- package/dist/agent/src/chat/utils/htmlToText.js +84 -0
- package/dist/agent/src/chat/utils/multiAsyncQueue.js +42 -0
- package/dist/agent/src/chat/utils/search.js +145 -0
- package/dist/agent/src/chat/utils/userResolver.js +46 -0
- package/dist/agent/src/chat/utils/websocket.js +16 -0
- package/dist/agent/src/test/agent.test.js +332 -0
- package/dist/agent/src/test/approvalManager.test.js +58 -0
- package/dist/agent/src/test/chatContextManager.test.js +392 -0
- package/dist/agent/src/test/clientServerConnection.test.js +158 -0
- package/dist/agent/src/test/compressingContextManager.test.js +65 -0
- package/dist/agent/src/test/context.test.js +83 -0
- package/dist/agent/src/test/conversation.test.js +89 -0
- package/dist/agent/src/test/db.test.js +271 -83
- package/dist/agent/src/test/dbMcpServerConfigs.test.js +72 -0
- package/dist/agent/src/test/dbTestTools.js +99 -0
- package/dist/agent/src/test/imageLoad.test.js +8 -7
- package/dist/agent/src/test/mcpServerManager.test.js +23 -20
- package/dist/agent/src/test/multiAsyncQueue.test.js +101 -0
- package/dist/agent/src/test/openaiStreaming.test.js +64 -35
- package/dist/agent/src/test/prompt.test.js +5 -4
- package/dist/agent/src/test/promptProvider.test.js +28 -0
- package/dist/agent/src/test/responseHandler.test.js +61 -0
- package/dist/agent/src/test/sudoMcpServerManager.test.js +24 -25
- package/dist/agent/src/test/testTools.js +109 -0
- package/dist/agent/src/test/tools.test.js +31 -0
- package/dist/agent/src/tool/agentChat.js +21 -10
- package/dist/agent/src/tool/agentMain.js +1 -1
- package/dist/agent/src/tool/chatMain.js +241 -58
- package/dist/agent/src/tool/commandPrompt.js +22 -17
- package/dist/agent/src/tool/files.js +20 -16
- package/dist/agent/src/tool/nodePlatform.js +47 -3
- package/dist/agent/src/tool/options.js +4 -4
- package/dist/agent/src/tool/prompt.js +19 -13
- package/eslint.config.mjs +14 -1
- package/package.json +14 -6
- package/scripts/chat_server +8 -0
- package/scripts/setup_chat +7 -2
- package/scripts/shutdown_chat_server +3 -0
- package/scripts/test_chat +135 -17
- package/src/agent/agent.ts +283 -138
- package/src/agent/agentUtils.ts +143 -108
- package/src/agent/compressingContextManager.ts +164 -0
- package/src/agent/context.ts +268 -0
- package/src/agent/dummyLLM.ts +76 -8
- package/src/agent/iAgentEventHandler.ts +54 -0
- package/src/agent/iplatform.ts +1 -0
- package/src/agent/mcpServerManager.ts +35 -31
- package/src/agent/nullAgentEventHandler.ts +20 -0
- package/src/agent/nullPlatform.ts +13 -0
- package/src/agent/openAILLMStreaming.ts +26 -13
- package/src/agent/promptProvider.ts +87 -0
- package/src/agent/repeatLLM.ts +5 -5
- package/src/agent/sudoMcpServerManager.ts +30 -29
- package/src/agent/tokenAuth.ts +7 -7
- package/src/agent/tools.ts +3 -1
- package/src/chat/client/chatClient.ts +900 -0
- package/src/chat/client/connection.test.ts +241 -0
- package/src/chat/client/connection.ts +276 -0
- package/src/chat/client/constants.ts +3 -0
- package/src/chat/client/index.ts +18 -0
- package/src/chat/client/interfaces.ts +34 -0
- package/src/chat/client/responseHandler.ts +131 -0
- package/src/chat/client/sessionClient.ts +443 -0
- package/src/chat/client/teamManager.ts +29 -0
- package/src/chat/{apiKeyManager.ts → data/apiKeyManager.ts} +6 -2
- package/src/chat/data/dataModels.ts +85 -0
- package/src/chat/data/database.ts +982 -0
- package/src/chat/data/dbMcpServerConfigs.ts +59 -0
- package/src/chat/protocol/connectionMessages.ts +49 -0
- package/src/chat/protocol/constants.ts +55 -0
- package/src/chat/protocol/errors.ts +16 -0
- package/src/chat/protocol/messages.ts +682 -0
- package/src/chat/server/README.md +127 -0
- package/src/chat/server/chatContextManager.ts +612 -0
- package/src/chat/server/connectionManager.test.ts +266 -0
- package/src/chat/server/connectionManager.ts +541 -0
- package/src/chat/server/conversation.ts +269 -0
- package/src/chat/server/errorUtils.ts +28 -0
- package/src/chat/server/openSession.ts +1332 -0
- package/src/chat/server/server.ts +177 -0
- package/src/chat/server/sessionFileManager.ts +239 -0
- package/src/chat/server/sessionRegistry.test.ts +138 -0
- package/src/chat/server/sessionRegistry.ts +1064 -0
- package/src/chat/server/test-utils/mockFactories.ts +422 -0
- package/src/chat/server/tools.ts +265 -0
- package/src/chat/utils/agentSessionMap.ts +76 -0
- package/src/chat/utils/approvalManager.ts +111 -0
- package/src/{utils → chat/utils}/asyncLock.ts +3 -3
- package/src/chat/{asyncQueue.ts → utils/asyncQueue.ts} +14 -3
- package/src/chat/utils/htmlToText.ts +61 -0
- package/src/chat/utils/multiAsyncQueue.ts +52 -0
- package/src/chat/utils/search.ts +139 -0
- package/src/chat/utils/userResolver.ts +48 -0
- package/src/chat/utils/websocket.ts +16 -0
- package/src/test/agent.test.ts +487 -0
- package/src/test/approvalManager.test.ts +73 -0
- package/src/test/chatContextManager.test.ts +521 -0
- package/src/test/clientServerConnection.test.ts +207 -0
- package/src/test/compressingContextManager.test.ts +82 -0
- package/src/test/context.test.ts +105 -0
- package/src/test/conversation.test.ts +109 -0
- package/src/test/db.test.ts +358 -89
- package/src/test/dbMcpServerConfigs.test.ts +112 -0
- package/src/test/dbTestTools.ts +153 -0
- package/src/test/imageLoad.test.ts +7 -6
- package/src/test/mcpServerManager.test.ts +21 -16
- package/src/test/multiAsyncQueue.test.ts +125 -0
- package/src/test/openaiStreaming.test.ts +71 -36
- package/src/test/prompt.test.ts +4 -3
- package/src/test/promptProvider.test.ts +33 -0
- package/src/test/responseHandler.test.ts +78 -0
- package/src/test/sudoMcpServerManager.test.ts +32 -30
- package/src/test/testTools.ts +146 -0
- package/src/test/tools.test.ts +39 -0
- package/src/tool/agentChat.ts +26 -12
- package/src/tool/agentMain.ts +1 -1
- package/src/tool/chatMain.ts +292 -100
- package/src/tool/commandPrompt.ts +28 -19
- package/src/tool/files.ts +25 -19
- package/src/tool/nodePlatform.ts +52 -3
- package/src/tool/options.ts +4 -2
- package/src/tool/prompt.ts +22 -15
- package/test_data/dummyllm_script_crash.json +32 -0
- package/test_data/frog.png.b64 +1 -0
- package/vitest.config.ts +39 -0
- package/dist/agent/src/chat/client.js +0 -349
- package/dist/agent/src/chat/conversationManager.js +0 -392
- package/dist/agent/src/chat/db.js +0 -209
- package/dist/agent/src/chat/frontendClient.js +0 -74
- package/dist/agent/src/chat/server.js +0 -158
- package/src/chat/client.ts +0 -455
- package/src/chat/conversationManager.ts +0 -595
- package/src/chat/db.ts +0 -290
- package/src/chat/frontendClient.ts +0 -123
- package/src/chat/messages.ts +0 -235
- package/src/chat/server.ts +0 -177
- /package/dist/agent/src/{chat/messages.js → agent/iAgentEventHandler.js} +0 -0
- /package/{frog.png → test_data/frog.png} +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
3
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
4
|
+
import { ConnectionManager } from "./connectionManager";
|
|
5
|
+
import type { ClientToServer, ServerToClient } from "../protocol/messages";
|
|
6
|
+
import {
|
|
7
|
+
createMockApiKeyManager,
|
|
8
|
+
createMockSessionRegistry,
|
|
9
|
+
createMockWebSocket,
|
|
10
|
+
setupStandardMockBehaviors,
|
|
11
|
+
MOCK_USERS,
|
|
12
|
+
} from "./test-utils/mockFactories";
|
|
13
|
+
import {
|
|
14
|
+
ClientConnectionData,
|
|
15
|
+
ServerConnectionData,
|
|
16
|
+
} from "../protocol/connectionMessages";
|
|
17
|
+
|
|
18
|
+
// Mock dependencies
|
|
19
|
+
vi.mock("../data/apiKeyManager");
|
|
20
|
+
vi.mock("ws");
|
|
21
|
+
|
|
22
|
+
describe("ConnectionManager", () => {
|
|
23
|
+
let connectionManager: ConnectionManager<ClientToServer, ServerToClient>;
|
|
24
|
+
let mockApiKeyManager: ReturnType<typeof createMockApiKeyManager>;
|
|
25
|
+
let mockSessionRegistry: ReturnType<typeof createMockSessionRegistry>;
|
|
26
|
+
let mockWebSocket: ReturnType<typeof createMockWebSocket>;
|
|
27
|
+
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
vi.resetAllMocks();
|
|
30
|
+
|
|
31
|
+
// Create mocks using factories
|
|
32
|
+
mockApiKeyManager = createMockApiKeyManager();
|
|
33
|
+
mockSessionRegistry = createMockSessionRegistry();
|
|
34
|
+
mockWebSocket = createMockWebSocket();
|
|
35
|
+
|
|
36
|
+
// Setup standard behaviors
|
|
37
|
+
setupStandardMockBehaviors({
|
|
38
|
+
apiKeyManager: mockApiKeyManager,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Create ConnectionManager instance using reflection
|
|
42
|
+
// to access private constructor. Since the constructor is private,
|
|
43
|
+
// we need to use type assertion
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
connectionManager = new (ConnectionManager as any)(
|
|
46
|
+
mockApiKeyManager.mock,
|
|
47
|
+
mockSessionRegistry.mock
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
afterEach(() => {
|
|
52
|
+
vi.restoreAllMocks();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe("handleConnection", () => {
|
|
56
|
+
it("should send connection_ready after successful setup", async () => {
|
|
57
|
+
await connectionManager.handleConnection(
|
|
58
|
+
mockWebSocket.mock,
|
|
59
|
+
"valid-api-key",
|
|
60
|
+
{ headers: {} }
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
// Wait for deferred send
|
|
64
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
65
|
+
|
|
66
|
+
expect(mockApiKeyManager.spies.verifyApiKey).toHaveBeenCalledWith(
|
|
67
|
+
"valid-api-key"
|
|
68
|
+
);
|
|
69
|
+
expect(mockWebSocket.spies.send).toHaveBeenCalledWith(
|
|
70
|
+
expect.stringMatching(/"t":"ready"/)
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should reject connection with invalid API key", async () => {
|
|
75
|
+
await connectionManager.handleConnection(
|
|
76
|
+
mockWebSocket.mock,
|
|
77
|
+
"invalid-api-key"
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
expect(mockWebSocket.spies.close).toHaveBeenCalledWith(
|
|
81
|
+
4000,
|
|
82
|
+
"Connection setup failed"
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("should setup WebSocket event handlers", async () => {
|
|
87
|
+
await connectionManager.handleConnection(
|
|
88
|
+
mockWebSocket.mock,
|
|
89
|
+
"valid-api-key"
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
expect(mockWebSocket.spies.on).toHaveBeenCalledWith(
|
|
93
|
+
"message",
|
|
94
|
+
expect.any(Function)
|
|
95
|
+
);
|
|
96
|
+
expect(mockWebSocket.spies.on).toHaveBeenCalledWith(
|
|
97
|
+
"close",
|
|
98
|
+
expect.any(Function)
|
|
99
|
+
);
|
|
100
|
+
expect(mockWebSocket.spies.on).toHaveBeenCalledWith(
|
|
101
|
+
"error",
|
|
102
|
+
expect.any(Function)
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe("user communication", () => {
|
|
108
|
+
beforeEach(async () => {
|
|
109
|
+
await connectionManager.handleConnection(
|
|
110
|
+
mockWebSocket.mock,
|
|
111
|
+
"valid-api-key"
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("should send messages to connected users", () => {
|
|
116
|
+
const testMessage: ServerConnectionData<ServerToClient> = {
|
|
117
|
+
t: "data",
|
|
118
|
+
d: {
|
|
119
|
+
type: "user_msg",
|
|
120
|
+
user_uuid: "user_1",
|
|
121
|
+
session_id: "session_1",
|
|
122
|
+
message: "message text",
|
|
123
|
+
message_idx: 12,
|
|
124
|
+
// connection_id: "test-123",
|
|
125
|
+
// user_uuid: MOCK_USERS.owner.uuid,
|
|
126
|
+
// client_message_id: "test-123",
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
connectionManager.sendToUsers(
|
|
131
|
+
new Set([MOCK_USERS.owner.uuid]),
|
|
132
|
+
testMessage.d
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
expect(mockWebSocket.spies.send).toHaveBeenCalledWith(
|
|
136
|
+
JSON.stringify(testMessage)
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("should return API key for connected user", () => {
|
|
141
|
+
const apiKey = connectionManager.getLiveUserApiKey(MOCK_USERS.owner.uuid);
|
|
142
|
+
expect(apiKey).toBe("valid-api-key");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("should return undefined for non-existent user", () => {
|
|
146
|
+
const apiKey = connectionManager.getLiveUserApiKey(
|
|
147
|
+
MOCK_USERS.nonExistent.uuid
|
|
148
|
+
);
|
|
149
|
+
expect(apiKey).toBeUndefined();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("connection cleanup", () => {
|
|
154
|
+
beforeEach(async () => {
|
|
155
|
+
await connectionManager.handleConnection(
|
|
156
|
+
mockWebSocket.mock,
|
|
157
|
+
"valid-api-key"
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("should clean up connection state on close", () => {
|
|
162
|
+
// Get the close handler from mock calls
|
|
163
|
+
const closeHandlerCall = mockWebSocket.spies.on.mock.calls.find(
|
|
164
|
+
(call) => call[0] === "close"
|
|
165
|
+
);
|
|
166
|
+
expect(closeHandlerCall).toBeDefined();
|
|
167
|
+
|
|
168
|
+
if (closeHandlerCall) {
|
|
169
|
+
const closeHandler = closeHandlerCall[1];
|
|
170
|
+
closeHandler();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// After cleanup, API key should no longer be available
|
|
174
|
+
const apiKey = connectionManager.getLiveUserApiKey(MOCK_USERS.owner.uuid);
|
|
175
|
+
expect(apiKey).toBeUndefined();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("should clean up connection state on error", () => {
|
|
179
|
+
// Get the error handler from mock calls
|
|
180
|
+
const errorHandlerCall = mockWebSocket.spies.on.mock.calls.find(
|
|
181
|
+
(call) => call[0] === "error"
|
|
182
|
+
);
|
|
183
|
+
expect(errorHandlerCall).toBeDefined();
|
|
184
|
+
|
|
185
|
+
if (errorHandlerCall) {
|
|
186
|
+
const errorHandler = errorHandlerCall[1];
|
|
187
|
+
errorHandler(new Error("WebSocket error"));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// After cleanup, API key should no longer be available
|
|
191
|
+
const apiKey = connectionManager.getLiveUserApiKey(MOCK_USERS.owner.uuid);
|
|
192
|
+
expect(apiKey).toBeUndefined();
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe("message routing", () => {
|
|
197
|
+
let messageHandler: (data: Buffer) => Promise<void>;
|
|
198
|
+
|
|
199
|
+
beforeEach(async () => {
|
|
200
|
+
await connectionManager.handleConnection(
|
|
201
|
+
mockWebSocket.mock,
|
|
202
|
+
"valid-api-key"
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
// Extract the message handler
|
|
206
|
+
const messageHandlerCall = mockWebSocket.spies.on.mock.calls.find(
|
|
207
|
+
(call) => call[0] === "message"
|
|
208
|
+
);
|
|
209
|
+
expect(messageHandlerCall).toBeDefined();
|
|
210
|
+
if (!messageHandlerCall) {
|
|
211
|
+
throw new Error("Message handler not found");
|
|
212
|
+
}
|
|
213
|
+
messageHandler = messageHandlerCall[1];
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("should route session_create to SessionRegistry", async () => {
|
|
217
|
+
mockSessionRegistry.spies.processMessage.mockResolvedValue(undefined);
|
|
218
|
+
|
|
219
|
+
const message: ClientConnectionData<ClientToServer> = {
|
|
220
|
+
t: "data",
|
|
221
|
+
d: {
|
|
222
|
+
type: "control_session_create",
|
|
223
|
+
title: "Test Session",
|
|
224
|
+
agent_profile_id: "agent-123",
|
|
225
|
+
client_message_id: "msg-123",
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
await messageHandler(Buffer.from(JSON.stringify(message)));
|
|
230
|
+
|
|
231
|
+
expect(mockSessionRegistry.spies.processMessage).toHaveBeenCalledWith(
|
|
232
|
+
expect.any(String), // connectionId
|
|
233
|
+
MOCK_USERS.owner.uuid,
|
|
234
|
+
message.d
|
|
235
|
+
);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it("should route session messages to SessionRegistry", async () => {
|
|
239
|
+
const message: ClientConnectionData<ClientToServer> = {
|
|
240
|
+
t: "data",
|
|
241
|
+
d: {
|
|
242
|
+
type: "msg",
|
|
243
|
+
session_id: "session-123",
|
|
244
|
+
message: "Hello world!",
|
|
245
|
+
client_message_id: "msg-123",
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
await messageHandler(Buffer.from(JSON.stringify(message)));
|
|
250
|
+
|
|
251
|
+
expect(mockSessionRegistry.spies.processMessage).toHaveBeenCalledWith(
|
|
252
|
+
expect.any(String), // connectionId
|
|
253
|
+
MOCK_USERS.owner.uuid,
|
|
254
|
+
message.d
|
|
255
|
+
);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it("should handle invalid JSON gracefully", async () => {
|
|
259
|
+
await messageHandler(Buffer.from("invalid json"));
|
|
260
|
+
|
|
261
|
+
expect(mockWebSocket.spies.send).toHaveBeenCalledWith(
|
|
262
|
+
expect.stringMatching(/"t":"error"/)
|
|
263
|
+
);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
});
|