@teneo-protocol/sdk 1.0.1 → 2.0.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.
Files changed (153) hide show
  1. package/.github/workflows/publish-npm.yml +8 -6
  2. package/CHANGELOG.md +265 -0
  3. package/README.md +406 -53
  4. package/dist/core/websocket-client.d.ts +12 -0
  5. package/dist/core/websocket-client.d.ts.map +1 -1
  6. package/dist/core/websocket-client.js +22 -2
  7. package/dist/core/websocket-client.js.map +1 -1
  8. package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts +76 -0
  9. package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts.map +1 -0
  10. package/dist/handlers/message-handlers/agent-room-operation-response-handler.js +70 -0
  11. package/dist/handlers/message-handlers/agent-room-operation-response-handler.js.map +1 -0
  12. package/dist/handlers/message-handlers/agent-selected-handler.d.ts +92 -38
  13. package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -1
  14. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts +904 -0
  15. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts.map +1 -0
  16. package/dist/handlers/message-handlers/agent-status-update-handler.js +51 -0
  17. package/dist/handlers/message-handlers/agent-status-update-handler.js.map +1 -0
  18. package/dist/handlers/message-handlers/auth-error-handler.d.ts +45 -31
  19. package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -1
  20. package/dist/handlers/message-handlers/auth-message-handler.d.ts +6 -0
  21. package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -1
  22. package/dist/handlers/message-handlers/auth-message-handler.js +65 -5
  23. package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -1
  24. package/dist/handlers/message-handlers/auth-required-handler.d.ts +49 -31
  25. package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -1
  26. package/dist/handlers/message-handlers/auth-success-handler.d.ts +6 -0
  27. package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -1
  28. package/dist/handlers/message-handlers/auth-success-handler.js +46 -4
  29. package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -1
  30. package/dist/handlers/message-handlers/challenge-handler.d.ts +45 -31
  31. package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -1
  32. package/dist/handlers/message-handlers/error-message-handler.d.ts +49 -31
  33. package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -1
  34. package/dist/handlers/message-handlers/index.d.ts +5 -0
  35. package/dist/handlers/message-handlers/index.d.ts.map +1 -1
  36. package/dist/handlers/message-handlers/index.js +23 -1
  37. package/dist/handlers/message-handlers/index.js.map +1 -1
  38. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts +877 -0
  39. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts.map +1 -0
  40. package/dist/handlers/message-handlers/list-available-agents-handler.js +38 -0
  41. package/dist/handlers/message-handlers/list-available-agents-handler.js.map +1 -0
  42. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts +886 -0
  43. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts.map +1 -0
  44. package/dist/handlers/message-handlers/list-room-agents-handler.js +51 -0
  45. package/dist/handlers/message-handlers/list-room-agents-handler.js.map +1 -0
  46. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts +178 -89
  47. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -1
  48. package/dist/handlers/message-handlers/ping-pong-handler.d.ts +62 -58
  49. package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -1
  50. package/dist/handlers/message-handlers/regular-message-handler.d.ts +31 -29
  51. package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -1
  52. package/dist/handlers/message-handlers/room-operation-response-handler.d.ts +328 -0
  53. package/dist/handlers/message-handlers/room-operation-response-handler.d.ts.map +1 -0
  54. package/dist/handlers/message-handlers/room-operation-response-handler.js +92 -0
  55. package/dist/handlers/message-handlers/room-operation-response-handler.js.map +1 -0
  56. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +53 -31
  57. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
  58. package/dist/handlers/message-handlers/types.d.ts +2 -0
  59. package/dist/handlers/message-handlers/types.d.ts.map +1 -1
  60. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +53 -31
  61. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
  62. package/dist/managers/agent-room-manager.d.ts +222 -0
  63. package/dist/managers/agent-room-manager.d.ts.map +1 -0
  64. package/dist/managers/agent-room-manager.js +508 -0
  65. package/dist/managers/agent-room-manager.js.map +1 -0
  66. package/dist/managers/index.d.ts +2 -0
  67. package/dist/managers/index.d.ts.map +1 -1
  68. package/dist/managers/index.js +5 -1
  69. package/dist/managers/index.js.map +1 -1
  70. package/dist/managers/room-management-manager.d.ts +213 -0
  71. package/dist/managers/room-management-manager.d.ts.map +1 -0
  72. package/dist/managers/room-management-manager.js +440 -0
  73. package/dist/managers/room-management-manager.js.map +1 -0
  74. package/dist/managers/room-manager.d.ts +4 -4
  75. package/dist/managers/room-manager.d.ts.map +1 -1
  76. package/dist/managers/room-manager.js.map +1 -1
  77. package/dist/teneo-sdk.d.ts +333 -13
  78. package/dist/teneo-sdk.d.ts.map +1 -1
  79. package/dist/teneo-sdk.js +468 -1
  80. package/dist/teneo-sdk.js.map +1 -1
  81. package/dist/types/config.d.ts +63 -54
  82. package/dist/types/config.d.ts.map +1 -1
  83. package/dist/types/config.js +8 -4
  84. package/dist/types/config.js.map +1 -1
  85. package/dist/types/error-codes.d.ts +2 -0
  86. package/dist/types/error-codes.d.ts.map +1 -1
  87. package/dist/types/error-codes.js +3 -0
  88. package/dist/types/error-codes.js.map +1 -1
  89. package/dist/types/events.d.ts +132 -68
  90. package/dist/types/events.d.ts.map +1 -1
  91. package/dist/types/events.js.map +1 -1
  92. package/dist/types/index.d.ts +1 -1
  93. package/dist/types/index.d.ts.map +1 -1
  94. package/dist/types/index.js +27 -2
  95. package/dist/types/index.js.map +1 -1
  96. package/dist/types/messages.d.ts +11396 -2559
  97. package/dist/types/messages.d.ts.map +1 -1
  98. package/dist/types/messages.js +294 -27
  99. package/dist/types/messages.js.map +1 -1
  100. package/examples/.env.example +1 -1
  101. package/examples/agent-room-management-example.ts +334 -0
  102. package/examples/claude-agent-x-follower/.env.example +2 -2
  103. package/examples/claude-agent-x-follower/QUICKSTART.md +1 -1
  104. package/examples/claude-agent-x-follower/README.md +1 -1
  105. package/examples/n8n-teneo/.env.example +2 -2
  106. package/examples/n8n-teneo/README.md +1 -1
  107. package/examples/openai-teneo/.env.example +2 -2
  108. package/examples/openai-teneo/README.md +1 -1
  109. package/examples/production-dashboard/.env.example +2 -2
  110. package/examples/production-dashboard/README.md +89 -12
  111. package/examples/production-dashboard/public/dashboard.html +1173 -601
  112. package/examples/production-dashboard/server.ts +347 -5
  113. package/examples/room-management-example.ts +285 -0
  114. package/examples/usage/.env.example +1 -1
  115. package/examples/usage/01-connect.ts +1 -1
  116. package/examples/usage/02-list-agents.ts +1 -1
  117. package/examples/usage/03-pick-agent.ts +1 -1
  118. package/examples/usage/04-find-by-capability.ts +1 -1
  119. package/examples/usage/05-webhook-example.ts +1 -1
  120. package/examples/usage/06-simple-api-server.ts +1 -1
  121. package/examples/usage/07-event-listener.ts +1 -1
  122. package/examples/usage/README.md +1 -1
  123. package/package.json +9 -1
  124. package/src/core/websocket-client.ts +26 -2
  125. package/src/handlers/message-handlers/agent-room-operation-response-handler.ts +83 -0
  126. package/src/handlers/message-handlers/agent-status-update-handler.ts +58 -0
  127. package/src/handlers/message-handlers/auth-message-handler.ts +73 -5
  128. package/src/handlers/message-handlers/auth-success-handler.ts +58 -6
  129. package/src/handlers/message-handlers/index.ts +19 -0
  130. package/src/handlers/message-handlers/list-available-agents-handler.ts +41 -0
  131. package/src/handlers/message-handlers/list-room-agents-handler.ts +61 -0
  132. package/src/handlers/message-handlers/room-operation-response-handler.ts +105 -0
  133. package/src/handlers/message-handlers/types.ts +6 -0
  134. package/src/managers/agent-room-manager.ts +609 -0
  135. package/src/managers/index.ts +2 -0
  136. package/src/managers/room-management-manager.ts +523 -0
  137. package/src/managers/room-manager.ts +4 -5
  138. package/src/teneo-sdk.ts +505 -4
  139. package/src/types/config.ts +10 -5
  140. package/src/types/error-codes.ts +4 -0
  141. package/src/types/events.ts +24 -0
  142. package/src/types/index.ts +55 -0
  143. package/src/types/messages.ts +374 -41
  144. package/tests/integration/room-management.test.ts +514 -0
  145. package/tests/integration/websocket.test.ts +1 -1
  146. package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +394 -0
  147. package/tests/unit/handlers/agent-status-update-handler.test.ts +407 -0
  148. package/tests/unit/handlers/auth-success-handler-rooms.test.ts +699 -0
  149. package/tests/unit/handlers/list-available-agents-handler.test.ts +256 -0
  150. package/tests/unit/handlers/list-room-agents-handler.test.ts +294 -0
  151. package/tests/unit/handlers/room-operation-response-handler.test.ts +527 -0
  152. package/tests/unit/managers/agent-room-manager.test.ts +534 -0
  153. package/tests/unit/managers/room-management-manager.test.ts +438 -0
@@ -0,0 +1,514 @@
1
+ /**
2
+ * Integration tests for Room Management (v2.0.0)
3
+ * Tests complete room CRUD flow with mock WebSocket server
4
+ */
5
+
6
+ import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from "vitest";
7
+ import WebSocket, { WebSocketServer } from "ws";
8
+ import { TeneoSDK } from "../../src";
9
+ import { SDKConfigBuilder } from "../../src/types";
10
+ import { privateKeyToAccount } from "viem/accounts";
11
+ import { generatePrivateKey } from "viem/accounts";
12
+ import { RoomInfo } from "../../src/types";
13
+
14
+ // TODO: Fix integration test setup - mock server needs proper event handling
15
+ describe.skip("Room Management Integration Tests", () => {
16
+ let server: WebSocketServer;
17
+ let sdk: TeneoSDK;
18
+ let serverPort: number;
19
+ let privateKey: string;
20
+ let walletAddress: string;
21
+
22
+ // Mock server to simulate Teneo WebSocket server
23
+ beforeAll(() => {
24
+ serverPort = 8082;
25
+ privateKey = generatePrivateKey();
26
+ const account = privateKeyToAccount(privateKey);
27
+ walletAddress = account.address;
28
+
29
+ // Create WebSocket server
30
+ server = new WebSocketServer({ port: serverPort });
31
+
32
+ // Room storage for testing
33
+ const rooms = new Map<string, RoomInfo>();
34
+ let roomCounter = 1;
35
+
36
+ server.on("connection", (ws) => {
37
+ ws.on("message", (data) => {
38
+ const message = JSON.parse(data.toString());
39
+
40
+ // Handle different message types
41
+ switch (message.type) {
42
+ case "request_challenge":
43
+ ws.send(
44
+ JSON.stringify({
45
+ type: "challenge",
46
+ data: {
47
+ challenge: "test-challenge-" + Date.now(),
48
+ timestamp: Date.now()
49
+ }
50
+ })
51
+ );
52
+ break;
53
+
54
+ case "auth":
55
+ // Send auth success with room management info
56
+ ws.send(
57
+ JSON.stringify({
58
+ type: "auth_success",
59
+ data: {
60
+ id: "client-123",
61
+ type: "user",
62
+ address: message.data.address,
63
+ nft_verified: false,
64
+ is_whitelisted: true,
65
+ rooms: Array.from(rooms.values()),
66
+ max_private_rooms: 5 // v2.0: Room limit
67
+ }
68
+ })
69
+ );
70
+ break;
71
+
72
+ case "create_room":
73
+ // Create new room
74
+ const newRoomId = `room-${roomCounter++}`;
75
+ const newRoom: RoomInfo = {
76
+ id: newRoomId,
77
+ name: message.name,
78
+ description: message.description,
79
+ is_public: message.is_public || false,
80
+ created_by: walletAddress,
81
+ created_at: new Date().toISOString(),
82
+ updated_at: new Date().toISOString(),
83
+ is_owner: true
84
+ };
85
+ rooms.set(newRoomId, newRoom);
86
+
87
+ // Send success response
88
+ ws.send(
89
+ JSON.stringify({
90
+ type: "room_operation_response",
91
+ data: {
92
+ success: true,
93
+ room: newRoom,
94
+ message: "Room created successfully"
95
+ }
96
+ })
97
+ );
98
+ break;
99
+
100
+ case "update_room":
101
+ // Update existing room
102
+ const roomId = message.room_id;
103
+ const existingRoom = rooms.get(roomId);
104
+
105
+ if (!existingRoom) {
106
+ ws.send(
107
+ JSON.stringify({
108
+ type: "room_operation_response",
109
+ data: {
110
+ success: false,
111
+ message: "Room not found",
112
+ room_id: roomId
113
+ }
114
+ })
115
+ );
116
+ return;
117
+ }
118
+
119
+ // Update room
120
+ const updatedRoom: RoomInfo = {
121
+ ...existingRoom,
122
+ name: message.name ?? existingRoom.name,
123
+ description: message.description ?? existingRoom.description,
124
+ updated_at: new Date().toISOString()
125
+ };
126
+ rooms.set(roomId, updatedRoom);
127
+
128
+ // Send success response
129
+ ws.send(
130
+ JSON.stringify({
131
+ type: "room_operation_response",
132
+ data: {
133
+ success: true,
134
+ room: updatedRoom,
135
+ message: "Room updated successfully"
136
+ }
137
+ })
138
+ );
139
+ break;
140
+
141
+ case "delete_room":
142
+ // Delete room
143
+ const deleteRoomId = message.room_id;
144
+ const roomToDelete = rooms.get(deleteRoomId);
145
+
146
+ if (!roomToDelete) {
147
+ ws.send(
148
+ JSON.stringify({
149
+ type: "room_operation_response",
150
+ data: {
151
+ success: false,
152
+ message: "Room not found",
153
+ room_id: deleteRoomId
154
+ }
155
+ })
156
+ );
157
+ return;
158
+ }
159
+
160
+ rooms.delete(deleteRoomId);
161
+
162
+ // Send success response
163
+ ws.send(
164
+ JSON.stringify({
165
+ type: "room_operation_response",
166
+ data: {
167
+ success: true,
168
+ room_id: deleteRoomId,
169
+ message: "Room deleted successfully"
170
+ }
171
+ })
172
+ );
173
+ break;
174
+
175
+ case "ping":
176
+ ws.send(JSON.stringify({ type: "pong" }));
177
+ break;
178
+ }
179
+ });
180
+ });
181
+ });
182
+
183
+ afterAll(() => {
184
+ server.close();
185
+ });
186
+
187
+ beforeEach(async () => {
188
+ // Create SDK instance
189
+ const config = new SDKConfigBuilder()
190
+ .withWebSocketUrl(`ws://localhost:${serverPort}`)
191
+ .withAuthentication(privateKey)
192
+ .withReconnection(false) // Disable for tests
193
+ .build();
194
+
195
+ sdk = new TeneoSDK(config);
196
+
197
+ // Wait for connection and auth
198
+ await new Promise<void>((resolve, reject) => {
199
+ const timeout = setTimeout(() => {
200
+ reject(new Error("Connection timeout"));
201
+ }, 5000);
202
+
203
+ sdk.once("ready", () => {
204
+ clearTimeout(timeout);
205
+ resolve();
206
+ });
207
+
208
+ sdk.once("error", (error) => {
209
+ clearTimeout(timeout);
210
+ reject(error);
211
+ });
212
+
213
+ // Connect to server
214
+ sdk.connect().catch(reject);
215
+ });
216
+ });
217
+
218
+ afterEach(async () => {
219
+ if (sdk) {
220
+ await sdk.destroy();
221
+ }
222
+ });
223
+
224
+ describe("Room Creation", () => {
225
+ it("should create a private room", async () => {
226
+ const roomOptions = {
227
+ name: "Test Private Room",
228
+ description: "A test private room"
229
+ };
230
+
231
+ const room = await sdk.createRoom(roomOptions);
232
+
233
+ expect(room).toBeDefined();
234
+ expect(room.id).toBeDefined();
235
+ expect(room.name).toBe(roomOptions.name);
236
+ expect(room.description).toBe(roomOptions.description);
237
+ expect(room.is_public).toBe(false);
238
+ expect(room.is_owner).toBe(true);
239
+ expect(room.created_by).toBeDefined();
240
+ expect(room.created_at).toBeDefined();
241
+
242
+ // Should be in owned rooms
243
+ const ownedRooms = sdk.getOwnedRooms();
244
+ expect(ownedRooms).toHaveLength(1);
245
+ expect(ownedRooms[0].id).toBe(room.id);
246
+ });
247
+
248
+
249
+ it("should emit room:created event", async () => {
250
+ const roomOptions = {
251
+ name: "Event Test Room"
252
+ };
253
+
254
+ const eventPromise = new Promise<RoomInfo>((resolve) => {
255
+ sdk.once("room:created", (room) => {
256
+ resolve(room);
257
+ });
258
+ });
259
+
260
+ const room = await sdk.createRoom(roomOptions);
261
+ const emittedRoom = await eventPromise;
262
+
263
+ expect(emittedRoom.id).toBe(room.id);
264
+ expect(emittedRoom.name).toBe(room.name);
265
+ });
266
+
267
+ it("should validate room name", async () => {
268
+ await expect(sdk.createRoom({ name: "" })).rejects.toThrow("Room name cannot be empty");
269
+
270
+ await expect(sdk.createRoom({ name: "a".repeat(101) })).rejects.toThrow(
271
+ "Room name too long"
272
+ );
273
+ });
274
+
275
+ it("should validate room description", async () => {
276
+ await expect(
277
+ sdk.createRoom({
278
+ name: "Test",
279
+ description: "a".repeat(501)
280
+ })
281
+ ).rejects.toThrow("Room description too long");
282
+ });
283
+ });
284
+
285
+ describe("Room Updates", () => {
286
+ it("should update room name", async () => {
287
+ // Create room first
288
+ const room = await sdk.createRoom({ name: "Original Name" });
289
+
290
+ // Update name
291
+ const updatedRoom = await sdk.updateRoom(room.id, { name: "Updated Name" });
292
+
293
+ expect(updatedRoom.id).toBe(room.id);
294
+ expect(updatedRoom.name).toBe("Updated Name");
295
+
296
+ // Should be updated in cache
297
+ const cachedRoom = sdk.getRoomById(room.id);
298
+ expect(cachedRoom?.name).toBe("Updated Name");
299
+ });
300
+
301
+ it("should update room description", async () => {
302
+ const room = await sdk.createRoom({ name: "Test Room" });
303
+
304
+ const updatedRoom = await sdk.updateRoom(room.id, {
305
+ description: "New description"
306
+ });
307
+
308
+ expect(updatedRoom.description).toBe("New description");
309
+ });
310
+
311
+ it("should update both name and description", async () => {
312
+ const room = await sdk.createRoom({ name: "Test Room" });
313
+
314
+ const updatedRoom = await sdk.updateRoom(room.id, {
315
+ name: "New Name",
316
+ description: "New description"
317
+ });
318
+
319
+ expect(updatedRoom.name).toBe("New Name");
320
+ expect(updatedRoom.description).toBe("New description");
321
+ });
322
+
323
+ it("should emit room:updated event", async () => {
324
+ const room = await sdk.createRoom({ name: "Test Room" });
325
+
326
+ const eventPromise = new Promise<RoomInfo>((resolve) => {
327
+ sdk.once("room:updated", (updatedRoom) => {
328
+ resolve(updatedRoom);
329
+ });
330
+ });
331
+
332
+ await sdk.updateRoom(room.id, { name: "Updated" });
333
+ const emittedRoom = await eventPromise;
334
+
335
+ expect(emittedRoom.id).toBe(room.id);
336
+ expect(emittedRoom.name).toBe("Updated");
337
+ });
338
+
339
+ it("should validate update parameters", async () => {
340
+ const room = await sdk.createRoom({ name: "Test Room" });
341
+
342
+ await expect(sdk.updateRoom(room.id, {})).rejects.toThrow("At least one field");
343
+
344
+ await expect(sdk.updateRoom(room.id, { name: "" })).rejects.toThrow(
345
+ "Room name cannot be empty"
346
+ );
347
+ });
348
+ });
349
+
350
+ describe("Room Deletion", () => {
351
+ it("should delete a room", async () => {
352
+ // Create room first
353
+ const room = await sdk.createRoom({ name: "Room to Delete" });
354
+
355
+ expect(sdk.getOwnedRoomCount()).toBe(1);
356
+
357
+ // Delete room
358
+ await sdk.deleteRoom(room.id);
359
+
360
+ // Should be removed from cache
361
+ expect(sdk.getOwnedRoomCount()).toBe(0);
362
+ expect(sdk.getRoomById(room.id)).toBeUndefined();
363
+ });
364
+
365
+ it("should emit room:deleted event", async () => {
366
+ const room = await sdk.createRoom({ name: "Test Room" });
367
+
368
+ const eventPromise = new Promise<string>((resolve) => {
369
+ sdk.once("room:deleted", (roomId) => {
370
+ resolve(roomId);
371
+ });
372
+ });
373
+
374
+ await sdk.deleteRoom(room.id);
375
+ const deletedRoomId = await eventPromise;
376
+
377
+ expect(deletedRoomId).toBe(room.id);
378
+ });
379
+ });
380
+
381
+ describe("Complete Room Lifecycle", () => {
382
+ it("should create, update, and delete a room", async () => {
383
+ // Create
384
+ const room = await sdk.createRoom({
385
+ name: "Lifecycle Test Room",
386
+ description: "Initial description"
387
+ });
388
+
389
+ expect(room.name).toBe("Lifecycle Test Room");
390
+ expect(sdk.getOwnedRoomCount()).toBe(1);
391
+
392
+ // Update
393
+ const updatedRoom = await sdk.updateRoom(room.id, {
394
+ name: "Updated Lifecycle Room",
395
+ description: "Updated description"
396
+ });
397
+
398
+ expect(updatedRoom.name).toBe("Updated Lifecycle Room");
399
+ expect(updatedRoom.description).toBe("Updated description");
400
+ expect(sdk.getOwnedRoomCount()).toBe(1);
401
+
402
+ // Delete
403
+ await sdk.deleteRoom(room.id);
404
+
405
+ expect(sdk.getOwnedRoomCount()).toBe(0);
406
+ expect(sdk.getRoomById(room.id)).toBeUndefined();
407
+ });
408
+ });
409
+
410
+ describe("Room Query Methods", () => {
411
+ it("should get owned rooms", async () => {
412
+ await sdk.createRoom({ name: "Room 1" });
413
+ await sdk.createRoom({ name: "Room 2" });
414
+
415
+ const ownedRooms = sdk.getOwnedRooms();
416
+ expect(ownedRooms).toHaveLength(2);
417
+ });
418
+
419
+ it("should get room by ID", async () => {
420
+ const room = await sdk.createRoom({ name: "Test Room" });
421
+
422
+ const found = sdk.getRoomById(room.id);
423
+ expect(found).toBeDefined();
424
+ expect(found?.name).toBe("Test Room");
425
+ });
426
+
427
+ it("should return undefined for non-existent room", () => {
428
+ const room = sdk.getRoomById("non-existent-id");
429
+ expect(room).toBeUndefined();
430
+ });
431
+
432
+ it("should get owned room count", async () => {
433
+ expect(sdk.getOwnedRoomCount()).toBe(0);
434
+
435
+ await sdk.createRoom({ name: "Room 1" });
436
+ expect(sdk.getOwnedRoomCount()).toBe(1);
437
+
438
+ await sdk.createRoom({ name: "Room 2" });
439
+ expect(sdk.getOwnedRoomCount()).toBe(2);
440
+ });
441
+
442
+ it("should get room limit", () => {
443
+ const limit = sdk.getRoomLimit();
444
+ expect(limit).toBe(5); // Set in mock server
445
+ });
446
+
447
+ it("should check if can create room", () => {
448
+ expect(sdk.canCreateRoom()).toBe(true);
449
+ });
450
+ });
451
+
452
+ describe("Return Value Immutability", () => {
453
+ it("should return defensive copies", async () => {
454
+ await sdk.createRoom({ name: "Test Room" });
455
+
456
+ const rooms1 = sdk.getOwnedRooms();
457
+ const rooms2 = sdk.getOwnedRooms();
458
+
459
+ // Should be different array instances
460
+ expect(rooms1).not.toBe(rooms2);
461
+ // But have same content
462
+ expect(rooms1[0].id).toBe(rooms2[0].id);
463
+
464
+ // Modifying returned array shouldn't affect internal state
465
+ rooms1[0].name = "Modified";
466
+ const rooms3 = sdk.getOwnedRooms();
467
+ expect(rooms3[0].name).not.toBe("Modified");
468
+ });
469
+ });
470
+
471
+ describe("Multiple Rooms", () => {
472
+ it("should handle creating multiple rooms", async () => {
473
+ const room1 = await sdk.createRoom({ name: "Room 1" });
474
+ const room2 = await sdk.createRoom({ name: "Room 2" });
475
+ const room3 = await sdk.createRoom({ name: "Room 3" });
476
+
477
+ expect(sdk.getOwnedRoomCount()).toBe(3);
478
+
479
+ const rooms = sdk.getOwnedRooms();
480
+ expect(rooms.map((r) => r.name)).toContain("Room 1");
481
+ expect(rooms.map((r) => r.name)).toContain("Room 2");
482
+ expect(rooms.map((r) => r.name)).toContain("Room 3");
483
+ });
484
+
485
+ it("should handle updating multiple rooms", async () => {
486
+ const room1 = await sdk.createRoom({ name: "Room 1" });
487
+ const room2 = await sdk.createRoom({ name: "Room 2" });
488
+
489
+ await sdk.updateRoom(room1.id, { name: "Updated Room 1" });
490
+ await sdk.updateRoom(room2.id, { name: "Updated Room 2" });
491
+
492
+ const rooms = sdk.getOwnedRooms();
493
+ expect(rooms.find((r) => r.id === room1.id)?.name).toBe("Updated Room 1");
494
+ expect(rooms.find((r) => r.id === room2.id)?.name).toBe("Updated Room 2");
495
+ });
496
+
497
+ it("should handle deleting multiple rooms", async () => {
498
+ const room1 = await sdk.createRoom({ name: "Room 1" });
499
+ const room2 = await sdk.createRoom({ name: "Room 2" });
500
+ const room3 = await sdk.createRoom({ name: "Room 3" });
501
+
502
+ expect(sdk.getOwnedRoomCount()).toBe(3);
503
+
504
+ await sdk.deleteRoom(room1.id);
505
+ expect(sdk.getOwnedRoomCount()).toBe(2);
506
+
507
+ await sdk.deleteRoom(room2.id);
508
+ expect(sdk.getOwnedRoomCount()).toBe(1);
509
+
510
+ await sdk.deleteRoom(room3.id);
511
+ expect(sdk.getOwnedRoomCount()).toBe(0);
512
+ });
513
+ });
514
+ });
@@ -310,7 +310,7 @@ describe("WebSocket Integration Tests", () => {
310
310
  });
311
311
 
312
312
  describe("Integration with Real Server", () => {
313
- const REAL_SERVER_URL = "wss://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/ws";
313
+ const REAL_SERVER_URL = "wss://your-teneo-server.com/ws";
314
314
  let sdk: TeneoSDK;
315
315
  let privateKey: string;
316
316