@teneo-protocol/sdk 1.0.0 → 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 (211) 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 +13 -0
  5. package/dist/core/websocket-client.d.ts.map +1 -1
  6. package/dist/core/websocket-client.js +34 -3
  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/regular-message-handler.js +1 -0
  53. package/dist/handlers/message-handlers/regular-message-handler.js.map +1 -1
  54. package/dist/handlers/message-handlers/room-operation-response-handler.d.ts +328 -0
  55. package/dist/handlers/message-handlers/room-operation-response-handler.d.ts.map +1 -0
  56. package/dist/handlers/message-handlers/room-operation-response-handler.js +92 -0
  57. package/dist/handlers/message-handlers/room-operation-response-handler.js.map +1 -0
  58. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +53 -31
  59. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
  60. package/dist/handlers/message-handlers/types.d.ts +2 -0
  61. package/dist/handlers/message-handlers/types.d.ts.map +1 -1
  62. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +53 -31
  63. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
  64. package/dist/managers/agent-room-manager.d.ts +222 -0
  65. package/dist/managers/agent-room-manager.d.ts.map +1 -0
  66. package/dist/managers/agent-room-manager.js +508 -0
  67. package/dist/managers/agent-room-manager.js.map +1 -0
  68. package/dist/managers/index.d.ts +2 -0
  69. package/dist/managers/index.d.ts.map +1 -1
  70. package/dist/managers/index.js +5 -1
  71. package/dist/managers/index.js.map +1 -1
  72. package/dist/managers/message-router.d.ts +1 -1
  73. package/dist/managers/message-router.d.ts.map +1 -1
  74. package/dist/managers/message-router.js +41 -4
  75. package/dist/managers/message-router.js.map +1 -1
  76. package/dist/managers/room-management-manager.d.ts +213 -0
  77. package/dist/managers/room-management-manager.d.ts.map +1 -0
  78. package/dist/managers/room-management-manager.js +440 -0
  79. package/dist/managers/room-management-manager.js.map +1 -0
  80. package/dist/managers/room-manager.d.ts +4 -4
  81. package/dist/managers/room-manager.d.ts.map +1 -1
  82. package/dist/managers/room-manager.js +1 -1
  83. package/dist/managers/room-manager.js.map +1 -1
  84. package/dist/teneo-sdk.d.ts +362 -14
  85. package/dist/teneo-sdk.d.ts.map +1 -1
  86. package/dist/teneo-sdk.js +497 -7
  87. package/dist/teneo-sdk.js.map +1 -1
  88. package/dist/types/config.d.ts +63 -54
  89. package/dist/types/config.d.ts.map +1 -1
  90. package/dist/types/config.js +9 -5
  91. package/dist/types/config.js.map +1 -1
  92. package/dist/types/error-codes.d.ts +2 -0
  93. package/dist/types/error-codes.d.ts.map +1 -1
  94. package/dist/types/error-codes.js +3 -0
  95. package/dist/types/error-codes.js.map +1 -1
  96. package/dist/types/events.d.ts +132 -68
  97. package/dist/types/events.d.ts.map +1 -1
  98. package/dist/types/events.js.map +1 -1
  99. package/dist/types/index.d.ts +1 -1
  100. package/dist/types/index.d.ts.map +1 -1
  101. package/dist/types/index.js +27 -2
  102. package/dist/types/index.js.map +1 -1
  103. package/dist/types/messages.d.ts +11396 -2559
  104. package/dist/types/messages.d.ts.map +1 -1
  105. package/dist/types/messages.js +294 -27
  106. package/dist/types/messages.js.map +1 -1
  107. package/dist/types/validation.d.ts.map +1 -1
  108. package/dist/types/validation.js +1 -1
  109. package/dist/types/validation.js.map +1 -1
  110. package/dist/utils/bounded-queue.d.ts +1 -1
  111. package/dist/utils/bounded-queue.js +6 -6
  112. package/dist/utils/circuit-breaker.d.ts.map +1 -1
  113. package/dist/utils/circuit-breaker.js.map +1 -1
  114. package/dist/utils/event-waiter.d.ts.map +1 -1
  115. package/dist/utils/event-waiter.js +2 -1
  116. package/dist/utils/event-waiter.js.map +1 -1
  117. package/dist/utils/rate-limiter.d.ts.map +1 -1
  118. package/dist/utils/rate-limiter.js +4 -6
  119. package/dist/utils/rate-limiter.js.map +1 -1
  120. package/dist/utils/secure-private-key.d.ts.map +1 -1
  121. package/dist/utils/secure-private-key.js +9 -15
  122. package/dist/utils/secure-private-key.js.map +1 -1
  123. package/dist/utils/signature-verifier.d.ts +2 -2
  124. package/dist/utils/signature-verifier.d.ts.map +1 -1
  125. package/dist/utils/signature-verifier.js +5 -5
  126. package/dist/utils/signature-verifier.js.map +1 -1
  127. package/examples/.env.example +1 -1
  128. package/examples/agent-room-management-example.ts +334 -0
  129. package/examples/claude-agent-x-follower/.env.example +117 -0
  130. package/examples/claude-agent-x-follower/QUICKSTART.md +243 -0
  131. package/examples/claude-agent-x-follower/README.md +540 -0
  132. package/examples/claude-agent-x-follower/index.ts +248 -0
  133. package/examples/claude-agent-x-follower/package.json +37 -0
  134. package/examples/claude-agent-x-follower/tsconfig.json +20 -0
  135. package/examples/n8n-teneo/.env.example +127 -0
  136. package/examples/n8n-teneo/Dockerfile +42 -0
  137. package/examples/n8n-teneo/README.md +564 -0
  138. package/examples/n8n-teneo/docker-compose.yml +71 -0
  139. package/examples/n8n-teneo/index.ts +177 -0
  140. package/examples/n8n-teneo/package.json +22 -0
  141. package/examples/n8n-teneo/tsconfig.json +12 -0
  142. package/examples/n8n-teneo/workflows/x-timeline.json +66 -0
  143. package/examples/openai-teneo/.env.example +130 -0
  144. package/examples/openai-teneo/README.md +635 -0
  145. package/examples/openai-teneo/index.ts +280 -0
  146. package/examples/openai-teneo/package.json +24 -0
  147. package/examples/openai-teneo/tsconfig.json +16 -0
  148. package/examples/production-dashboard/.env.example +5 -3
  149. package/examples/production-dashboard/README.md +839 -0
  150. package/examples/production-dashboard/pnpm-lock.yaml +92 -0
  151. package/examples/production-dashboard/public/dashboard.html +1150 -504
  152. package/examples/production-dashboard/server.ts +428 -12
  153. package/examples/room-management-example.ts +285 -0
  154. package/examples/usage/.env.example +17 -0
  155. package/examples/usage/01-connect.ts +116 -0
  156. package/examples/usage/02-list-agents.ts +153 -0
  157. package/examples/usage/03-pick-agent.ts +201 -0
  158. package/examples/usage/04-find-by-capability.ts +237 -0
  159. package/examples/usage/05-webhook-example.ts +319 -0
  160. package/examples/usage/06-simple-api-server.ts +396 -0
  161. package/examples/usage/07-event-listener.ts +402 -0
  162. package/examples/usage/README.md +383 -0
  163. package/examples/usage/package.json +42 -0
  164. package/package.json +13 -3
  165. package/src/core/websocket-client.ts +43 -9
  166. package/src/formatters/response-formatter.test.ts +8 -2
  167. package/src/handlers/message-handlers/agent-room-operation-response-handler.ts +83 -0
  168. package/src/handlers/message-handlers/agent-status-update-handler.ts +58 -0
  169. package/src/handlers/message-handlers/auth-message-handler.ts +73 -5
  170. package/src/handlers/message-handlers/auth-success-handler.ts +58 -6
  171. package/src/handlers/message-handlers/index.ts +19 -0
  172. package/src/handlers/message-handlers/list-available-agents-handler.ts +41 -0
  173. package/src/handlers/message-handlers/list-room-agents-handler.ts +61 -0
  174. package/src/handlers/message-handlers/regular-message-handler.ts +1 -0
  175. package/src/handlers/message-handlers/room-operation-response-handler.ts +105 -0
  176. package/src/handlers/message-handlers/types.ts +6 -0
  177. package/src/handlers/webhook-handler.test.ts +13 -10
  178. package/src/managers/agent-room-manager.ts +609 -0
  179. package/src/managers/index.ts +2 -0
  180. package/src/managers/message-router.ts +48 -6
  181. package/src/managers/room-management-manager.ts +523 -0
  182. package/src/managers/room-manager.ts +12 -6
  183. package/src/teneo-sdk.ts +543 -10
  184. package/src/types/config.ts +13 -6
  185. package/src/types/error-codes.ts +4 -0
  186. package/src/types/events.ts +24 -0
  187. package/src/types/index.ts +55 -0
  188. package/src/types/messages.ts +374 -41
  189. package/src/types/validation.ts +4 -1
  190. package/src/utils/bounded-queue.ts +9 -9
  191. package/src/utils/circuit-breaker.ts +4 -1
  192. package/src/utils/deduplication-cache.test.ts +2 -6
  193. package/src/utils/event-waiter.test.ts +4 -1
  194. package/src/utils/event-waiter.ts +5 -7
  195. package/src/utils/rate-limiter.test.ts +5 -17
  196. package/src/utils/rate-limiter.ts +6 -9
  197. package/src/utils/secure-private-key.test.ts +66 -59
  198. package/src/utils/secure-private-key.ts +10 -16
  199. package/src/utils/signature-verifier.test.ts +75 -70
  200. package/src/utils/signature-verifier.ts +7 -8
  201. package/src/utils/ssrf-validator.test.ts +3 -3
  202. package/tests/integration/room-management.test.ts +514 -0
  203. package/tests/integration/websocket.test.ts +1 -1
  204. package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +394 -0
  205. package/tests/unit/handlers/agent-status-update-handler.test.ts +407 -0
  206. package/tests/unit/handlers/auth-success-handler-rooms.test.ts +699 -0
  207. package/tests/unit/handlers/list-available-agents-handler.test.ts +256 -0
  208. package/tests/unit/handlers/list-room-agents-handler.test.ts +294 -0
  209. package/tests/unit/handlers/room-operation-response-handler.test.ts +527 -0
  210. package/tests/unit/managers/agent-room-manager.test.ts +534 -0
  211. package/tests/unit/managers/room-management-manager.test.ts +438 -0
package/src/teneo-sdk.ts CHANGED
@@ -12,7 +12,6 @@ import {
12
12
  PartialSDKConfigSchema,
13
13
  SDKConfigBuilder,
14
14
  Agent,
15
- Room,
16
15
  RoomInfo,
17
16
  Logger,
18
17
  validateConfig,
@@ -32,6 +31,8 @@ import {
32
31
  import {
33
32
  ConnectionManager,
34
33
  RoomManager,
34
+ RoomManagementManager,
35
+ AgentRoomManager,
35
36
  AgentRegistry,
36
37
  MessageRouter,
37
38
  SendMessageOptions,
@@ -71,6 +72,8 @@ export class TeneoSDK extends EventEmitter<SDKEvents> {
71
72
  // Managers
72
73
  private readonly connection: ConnectionManager;
73
74
  private readonly rooms: RoomManager;
75
+ private readonly roomManagement: RoomManagementManager;
76
+ private readonly agentRoom: AgentRoomManager;
74
77
  private readonly agents: AgentRegistry;
75
78
  private readonly messages: MessageRouter;
76
79
 
@@ -149,7 +152,11 @@ export class TeneoSDK extends EventEmitter<SDKEvents> {
149
152
  // Initialize managers
150
153
  this.connection = new ConnectionManager(this.wsClient, this.logger);
151
154
  this.rooms = new RoomManager(this.wsClient, this.logger);
155
+ this.roomManagement = new RoomManagementManager(this.wsClient, this.logger);
156
+ this.agentRoom = new AgentRoomManager(this.wsClient, this.logger, this.roomManagement);
152
157
  this.wsClient.setRoomManager(this.rooms); // Enable subscription tracking in handlers
158
+ this.wsClient.setRoomManagementManager(this.roomManagement); // Enable room CRUD in handlers (v2.0.0)
159
+ this.wsClient.setAgentRoomManager(this.agentRoom); // Enable agent-room operations in handlers (v2.0.0)
153
160
  this.agents = new AgentRegistry(this.logger);
154
161
  this.messages = new MessageRouter(
155
162
  this.wsClient,
@@ -290,8 +297,11 @@ export class TeneoSDK extends EventEmitter<SDKEvents> {
290
297
  * });
291
298
  * ```
292
299
  */
293
- public async sendDirectCommand(command: AgentCommand): Promise<FormattedResponse | void> {
294
- return this.messages.sendDirectCommand(command);
300
+ public async sendDirectCommand(
301
+ command: AgentCommand,
302
+ waitForResponse: boolean = false
303
+ ): Promise<FormattedResponse | void> {
304
+ return this.messages.sendDirectCommand(command, waitForResponse);
295
305
  }
296
306
 
297
307
  /**
@@ -498,7 +508,7 @@ export class TeneoSDK extends EventEmitter<SDKEvents> {
498
508
  * });
499
509
  * ```
500
510
  */
501
- public getRooms(): ReadonlyArray<Room> {
511
+ public getRooms(): ReadonlyArray<RoomInfo> {
502
512
  return this.rooms.getRooms();
503
513
  }
504
514
 
@@ -520,10 +530,387 @@ export class TeneoSDK extends EventEmitter<SDKEvents> {
520
530
  * }
521
531
  * ```
522
532
  */
523
- public getRoom(roomId: string): Room | undefined {
533
+ public getRoom(roomId: string): RoomInfo | undefined {
524
534
  return this.rooms.getRoom(roomId);
525
535
  }
526
536
 
537
+ // ============================================================================
538
+ // ROOM MANAGEMENT API (v2.0.0)
539
+ // ============================================================================
540
+
541
+ /**
542
+ * Creates a new private or public room.
543
+ * Checks room limit before creating (for private rooms).
544
+ * Emits 'room:created' event on success, 'room:create_error' on failure.
545
+ *
546
+ * @param options - Room creation options
547
+ * @param options.name - Room name (1-100 characters)
548
+ * @param options.description - Optional room description (max 500 characters)
549
+ * @param options.isPublic - Whether room is public (default: false)
550
+ * @returns Promise that resolves with created room info
551
+ * @throws {SDKError} If not connected, over limit, or validation fails
552
+ *
553
+ * @example
554
+ * ```typescript
555
+ * const room = await sdk.createRoom({
556
+ * name: 'My Project Room',
557
+ * description: 'Collaboration space for my project',
558
+ * isPublic: false
559
+ * });
560
+ * console.log(`Created room: ${room.id}`);
561
+ * ```
562
+ */
563
+ public async createRoom(options: {
564
+ name: string;
565
+ description?: string;
566
+ isPublic?: boolean;
567
+ }): Promise<RoomInfo> {
568
+ return this.roomManagement.createRoom(options);
569
+ }
570
+
571
+ /**
572
+ * Updates an existing room's name and/or description.
573
+ * User must own the room to update it.
574
+ * Emits 'room:updated' event on success, 'room:update_error' on failure.
575
+ *
576
+ * @param roomId - ID of room to update
577
+ * @param updates - Fields to update
578
+ * @param updates.name - New room name (1-100 characters)
579
+ * @param updates.description - New room description (max 500 characters)
580
+ * @returns Promise that resolves with updated room info
581
+ * @throws {SDKError} If not connected, not owner, or validation fails
582
+ *
583
+ * @example
584
+ * ```typescript
585
+ * const room = await sdk.updateRoom('room-123', {
586
+ * name: 'Updated Room Name',
587
+ * description: 'New description'
588
+ * });
589
+ * ```
590
+ */
591
+ public async updateRoom(
592
+ roomId: string,
593
+ updates: { name?: string; description?: string }
594
+ ): Promise<RoomInfo> {
595
+ return this.roomManagement.updateRoom(roomId, updates);
596
+ }
597
+
598
+ /**
599
+ * Deletes a room permanently.
600
+ * User must own the room to delete it.
601
+ * Emits 'room:deleted' event on success, 'room:delete_error' on failure.
602
+ *
603
+ * @param roomId - ID of room to delete
604
+ * @returns Promise that resolves when room is deleted
605
+ * @throws {SDKError} If not connected or not owner
606
+ *
607
+ * @example
608
+ * ```typescript
609
+ * await sdk.deleteRoom('room-123');
610
+ * console.log('Room deleted successfully');
611
+ * ```
612
+ */
613
+ public async deleteRoom(roomId: string): Promise<void> {
614
+ return this.roomManagement.deleteRoom(roomId);
615
+ }
616
+
617
+ /**
618
+ * Gets all rooms owned by the current user.
619
+ * Synchronous method that returns cached data from authentication.
620
+ *
621
+ * @returns Array of owned room info
622
+ *
623
+ * @example
624
+ * ```typescript
625
+ * const myRooms = sdk.getOwnedRooms();
626
+ * console.log(`I own ${myRooms.length} rooms`);
627
+ * myRooms.forEach(room => {
628
+ * console.log(`- ${room.name} (${room.id})`);
629
+ * });
630
+ * ```
631
+ */
632
+ public getOwnedRooms(): ReadonlyArray<Readonly<RoomInfo>> {
633
+ return this.roomManagement.getOwnedRooms();
634
+ }
635
+
636
+ /**
637
+ * Gets all rooms the user is a member of (but doesn't own).
638
+ * Synchronous method that returns cached data from authentication.
639
+ *
640
+ * @returns Array of shared room info
641
+ *
642
+ * @example
643
+ * ```typescript
644
+ * const sharedRooms = sdk.getSharedRooms();
645
+ * console.log(`I'm a member of ${sharedRooms.length} shared rooms`);
646
+ * ```
647
+ */
648
+ public getSharedRooms(): ReadonlyArray<Readonly<RoomInfo>> {
649
+ return this.roomManagement.getSharedRooms();
650
+ }
651
+
652
+ /**
653
+ * Gets all rooms the user has access to (both owned and shared).
654
+ * Convenience method that combines getOwnedRooms() and getSharedRooms().
655
+ * Synchronous method that returns cached data from authentication.
656
+ *
657
+ * @returns Array of all room info (owned + shared)
658
+ *
659
+ * @example
660
+ * ```typescript
661
+ * const allRooms = sdk.getAllRooms();
662
+ * console.log(`I have access to ${allRooms.length} total rooms`);
663
+ *
664
+ * // You can filter by ownership if needed
665
+ * const myRooms = allRooms.filter(r => r.is_owner);
666
+ * const sharedWithMe = allRooms.filter(r => !r.is_owner);
667
+ * ```
668
+ */
669
+ public getAllRooms(): ReadonlyArray<Readonly<RoomInfo>> {
670
+ return this.roomManagement.getAllRooms();
671
+ }
672
+
673
+ /**
674
+ * Gets the maximum number of private rooms the user can create.
675
+ * Based on user's subscription/plan.
676
+ *
677
+ * @returns Maximum private room limit
678
+ *
679
+ * @example
680
+ * ```typescript
681
+ * const limit = sdk.getRoomLimit();
682
+ * const current = sdk.getOwnedRoomCount();
683
+ * console.log(`Using ${current}/${limit} room slots`);
684
+ * ```
685
+ */
686
+ public getRoomLimit(): number {
687
+ return this.roomManagement.getRoomLimit();
688
+ }
689
+
690
+ /**
691
+ * Gets the current count of owned private rooms.
692
+ *
693
+ * @returns Number of rooms user owns
694
+ *
695
+ * @example
696
+ * ```typescript
697
+ * const count = sdk.getOwnedRoomCount();
698
+ * if (sdk.canCreateRoom()) {
699
+ * console.log(`Can create ${sdk.getRoomLimit() - count} more rooms`);
700
+ * }
701
+ * ```
702
+ */
703
+ public getOwnedRoomCount(): number {
704
+ return this.roomManagement.getOwnedRoomCount();
705
+ }
706
+
707
+ /**
708
+ * Checks if user can create another private room.
709
+ * Compares current owned room count against limit.
710
+ *
711
+ * @returns True if under limit, false otherwise
712
+ *
713
+ * @example
714
+ * ```typescript
715
+ * if (sdk.canCreateRoom()) {
716
+ * await sdk.createRoom({ name: 'New Room' });
717
+ * } else {
718
+ * console.log('Room limit reached! Upgrade your plan.');
719
+ * }
720
+ * ```
721
+ */
722
+ public canCreateRoom(): boolean {
723
+ return this.roomManagement.canCreateRoom();
724
+ }
725
+
726
+ // ============================================================================
727
+ // AGENT ROOM MANAGEMENT API (v2.0.0)
728
+ // ============================================================================
729
+
730
+ /**
731
+ * Adds an agent to a room. Only room owners can add agents.
732
+ * Emits 'agent_room:agent_added' on success, 'agent_room:add_error' on failure.
733
+ *
734
+ * @param roomId - ID of the room to add the agent to
735
+ * @param agentId - ID of the agent to add
736
+ * @returns Promise that resolves when agent is added
737
+ * @throws {SDKError} If not connected, not owner, or agent already in room
738
+ *
739
+ * @example
740
+ * ```typescript
741
+ * await sdk.addAgentToRoom('room-123', 'weather-agent');
742
+ * console.log('Agent added to room');
743
+ * ```
744
+ */
745
+ public async addAgentToRoom(roomId: string, agentId: string): Promise<void> {
746
+ return this.agentRoom.addAgentToRoom(roomId, agentId);
747
+ }
748
+
749
+ /**
750
+ * Removes an agent from a room. Only room owners can remove agents.
751
+ * Emits 'agent_room:agent_removed' on success, 'agent_room:remove_error' on failure.
752
+ *
753
+ * @param roomId - ID of the room to remove the agent from
754
+ * @param agentId - ID of the agent to remove
755
+ * @returns Promise that resolves when agent is removed
756
+ * @throws {SDKError} If not connected, not owner, or agent not in room
757
+ *
758
+ * @example
759
+ * ```typescript
760
+ * await sdk.removeAgentFromRoom('room-123', 'weather-agent');
761
+ * console.log('Agent removed from room');
762
+ * ```
763
+ */
764
+ public async removeAgentFromRoom(roomId: string, agentId: string): Promise<void> {
765
+ return this.agentRoom.removeAgentFromRoom(roomId, agentId);
766
+ }
767
+
768
+ /**
769
+ * Lists all agents in a room.
770
+ * Results are cached for 5 minutes for performance.
771
+ * Emits 'agent_room:agents_listed' when list is received.
772
+ *
773
+ * @param roomId - ID of the room to list agents for
774
+ * @param useCache - Whether to use cached data if available (default: true)
775
+ * @returns Promise that resolves to array of agents in the room
776
+ * @throws {SDKError} If not connected
777
+ *
778
+ * @example
779
+ * ```typescript
780
+ * const agents = await sdk.listRoomAgents('room-123');
781
+ * console.log(`Room has ${agents.length} agents`);
782
+ * agents.forEach(agent => {
783
+ * console.log(`- ${agent.agent_name} (${agent.status})`);
784
+ * });
785
+ * ```
786
+ */
787
+ public async listRoomAgents(roomId: string, useCache: boolean = true): Promise<any[]> {
788
+ return this.agentRoom.listRoomAgents(roomId, useCache);
789
+ }
790
+
791
+ /**
792
+ * Lists all agents available to be added to a room.
793
+ * Shows agents not currently in the room.
794
+ * Results are cached for 5 minutes for performance.
795
+ * Emits 'agent_room:available_agents_listed' when list is received.
796
+ *
797
+ * @param roomId - ID of the room to check available agents for
798
+ * @param useCache - Whether to use cached data if available (default: true)
799
+ * @returns Promise that resolves to array of available agents
800
+ * @throws {SDKError} If not connected
801
+ *
802
+ * @example
803
+ * ```typescript
804
+ * const available = await sdk.listAvailableAgents('room-123');
805
+ * console.log(`${available.length} agents available to add`);
806
+ * ```
807
+ */
808
+ public async listAvailableAgents(roomId: string, useCache: boolean = true): Promise<any[]> {
809
+ return this.agentRoom.listAvailableAgents(roomId, useCache);
810
+ }
811
+
812
+ /**
813
+ * Gets agents in a room from cache (synchronous).
814
+ * Returns undefined if not cached. Use listRoomAgents() to fetch.
815
+ *
816
+ * @param roomId - ID of the room
817
+ * @returns Array of agents if cached, undefined otherwise
818
+ *
819
+ * @example
820
+ * ```typescript
821
+ * const agents = sdk.getRoomAgents('room-123');
822
+ * if (agents) {
823
+ * console.log(`${agents.length} agents (cached)`);
824
+ * } else {
825
+ * await sdk.listRoomAgents('room-123'); // Fetch from server
826
+ * }
827
+ * ```
828
+ */
829
+ public getRoomAgents(roomId: string): any[] | undefined {
830
+ return this.agentRoom.getRoomAgents(roomId);
831
+ }
832
+
833
+ /**
834
+ * Gets available agents for a room from cache (synchronous).
835
+ * Returns undefined if not cached. Use listAvailableAgents() to fetch.
836
+ *
837
+ * @param roomId - ID of the room
838
+ * @returns Array of available agents if cached, undefined otherwise
839
+ *
840
+ * @example
841
+ * ```typescript
842
+ * const available = sdk.getAvailableAgents('room-123');
843
+ * if (available) {
844
+ * console.log(`${available.length} agents available (cached)`);
845
+ * }
846
+ * ```
847
+ */
848
+ public getAvailableAgents(roomId: string): any[] | undefined {
849
+ return this.agentRoom.getAvailableAgents(roomId);
850
+ }
851
+
852
+ /**
853
+ * Checks if an agent is in a room (synchronous, from cache).
854
+ * Returns undefined if room data not cached.
855
+ *
856
+ * @param roomId - ID of the room
857
+ * @param agentId - ID of the agent
858
+ * @returns True if agent is in room, false if not, undefined if not cached
859
+ *
860
+ * @example
861
+ * ```typescript
862
+ * const inRoom = sdk.isAgentInRoom('room-123', 'weather-agent');
863
+ * if (inRoom === true) {
864
+ * console.log('Agent is in room');
865
+ * } else if (inRoom === false) {
866
+ * console.log('Agent is not in room');
867
+ * } else {
868
+ * console.log('Room data not cached');
869
+ * }
870
+ * ```
871
+ */
872
+ public isAgentInRoom(roomId: string, agentId: string): boolean | undefined {
873
+ return this.agentRoom.isAgentInRoom(roomId, agentId);
874
+ }
875
+
876
+ /**
877
+ * Gets the count of agents in a room (synchronous, from cache).
878
+ * Returns undefined if room data not cached.
879
+ *
880
+ * @param roomId - ID of the room
881
+ * @returns Number of agents in room, or undefined if not cached
882
+ *
883
+ * @example
884
+ * ```typescript
885
+ * const count = sdk.getRoomAgentCount('room-123');
886
+ * if (count !== undefined) {
887
+ * console.log(`Room has ${count} agents`);
888
+ * }
889
+ * ```
890
+ */
891
+ public getRoomAgentCount(roomId: string): number | undefined {
892
+ return this.agentRoom.getRoomAgentCount(roomId);
893
+ }
894
+
895
+ /**
896
+ * Invalidates the agent-room cache for a specific room.
897
+ * Forces the next listRoomAgents() or listAvailableAgents() call to fetch fresh data.
898
+ * Useful after bulk operations or when you know the cache is stale.
899
+ *
900
+ * @param roomId - ID of the room to invalidate cache for
901
+ *
902
+ * @example
903
+ * ```typescript
904
+ * // After adding/removing agents
905
+ * await sdk.addAgentToRoom('room-123', 'agent-456');
906
+ * sdk.invalidateAgentRoomCache('room-123');
907
+ * const freshAgents = await sdk.listRoomAgents('room-123');
908
+ * ```
909
+ */
910
+ public invalidateAgentRoomCache(roomId: string): void {
911
+ this.agentRoom.invalidateCache(roomId);
912
+ }
913
+
527
914
  /**
528
915
  * Configures webhook URL and headers for receiving real-time event notifications.
529
916
  * Webhooks allow you to receive events at your server endpoint via HTTP POST requests.
@@ -719,6 +1106,39 @@ export class TeneoSDK extends EventEmitter<SDKEvents> {
719
1106
  };
720
1107
  }
721
1108
 
1109
+ /**
1110
+ * Gets the current message deduplication cache status (CB-4).
1111
+ * Returns statistics about the deduplication cache including size, TTL, and capacity.
1112
+ * Useful for monitoring deduplication behavior and cache health.
1113
+ * Returns undefined if deduplication is not configured or disabled.
1114
+ *
1115
+ * @returns Deduplication cache status object, or undefined if not configured
1116
+ * @returns {number} returns.cacheSize - Number of message IDs currently cached
1117
+ * @returns {number} returns.ttl - Time-to-live for cache entries in milliseconds
1118
+ * @returns {number} returns.maxSize - Maximum cache size capacity
1119
+ *
1120
+ * @example
1121
+ * ```typescript
1122
+ * const status = sdk.getDeduplicationStatus();
1123
+ * if (status) {
1124
+ * console.log(`Cache: ${status.cacheSize}/${status.maxSize}`);
1125
+ * console.log(`Utilization: ${(status.cacheSize / status.maxSize * 100).toFixed(1)}%`);
1126
+ * console.log(`TTL: ${status.ttl}ms`);
1127
+ * } else {
1128
+ * console.log('Deduplication not enabled');
1129
+ * }
1130
+ * ```
1131
+ */
1132
+ public getDeduplicationStatus():
1133
+ | {
1134
+ cacheSize: number;
1135
+ ttl: number;
1136
+ maxSize: number;
1137
+ }
1138
+ | undefined {
1139
+ return this.wsClient.getDeduplicationStatus();
1140
+ }
1141
+
722
1142
  /**
723
1143
  * Retries all failed webhook deliveries in the queue.
724
1144
  * Resets attempt counters and immediately attempts to deliver all failed webhooks.
@@ -915,7 +1335,9 @@ export class TeneoSDK extends EventEmitter<SDKEvents> {
915
1335
  this.connection.on("auth:success", (state) => {
916
1336
  this.logger.debug("Received auth:success event in SDK", {
917
1337
  authenticated: state?.authenticated,
918
- hasRooms: !!state?.roomObjects
1338
+ hasRooms: !!state?.roomObjects,
1339
+ ownedRooms: state?.privateRoomIds?.length || 0,
1340
+ sharedRooms: state?.sharedRoomIds?.length || 0
919
1341
  });
920
1342
 
921
1343
  // Update rooms from auth state
@@ -923,6 +1345,19 @@ export class TeneoSDK extends EventEmitter<SDKEvents> {
923
1345
  this.rooms.updateRoomsFromAuth(state.roomObjects);
924
1346
  }
925
1347
 
1348
+ // Ensure RoomManagementManager is synced with auth state
1349
+ // This handles cases where auth handlers might have already set it, but ensures consistency
1350
+ if (state.roomObjects && state.roomObjects.length > 0) {
1351
+ const ownedRooms = state.roomObjects.filter((r) => r.is_owner);
1352
+ const sharedRooms = state.roomObjects.filter((r) => !r.is_owner);
1353
+ this.roomManagement.setOwnedRooms(ownedRooms);
1354
+ this.roomManagement.setSharedRooms(sharedRooms);
1355
+
1356
+ if (state.maxPrivateRooms) {
1357
+ this.roomManagement.setRoomLimit(state.maxPrivateRooms);
1358
+ }
1359
+ }
1360
+
926
1361
  this.emit("auth:success", state);
927
1362
  });
928
1363
  this.connection.on("auth:error", (error) => this.emit("auth:error", error));
@@ -953,13 +1388,111 @@ export class TeneoSDK extends EventEmitter<SDKEvents> {
953
1388
  this.agents.updateAgents(agents);
954
1389
  });
955
1390
 
956
- // Forward room events from WebSocketClient (emitted by handlers)
1391
+ // Forward room events from WebSocketClient (emitted by room subscription handlers)
957
1392
  this.wsClient.on("room:subscribed", (data) => this.emit("room:subscribed", data));
958
1393
  this.wsClient.on("room:unsubscribed", (data) => this.emit("room:unsubscribed", data));
959
1394
 
960
- // Forward room events from RoomManager (if any direct emissions are added later)
961
- this.rooms.on("room:subscribed", (data) => this.emit("room:subscribed", data));
962
- this.rooms.on("room:unsubscribed", (data) => this.emit("room:unsubscribed", data));
1395
+ // Forward room management events from WebSocketClient (emitted by handlers) (v2.0.0)
1396
+ // These events are emitted by message handlers, so we listen on wsClient
1397
+ // We forward to RoomManagementManager first (for promise resolution), then emit on SDK
1398
+ this.wsClient.on("room:created", (room) => {
1399
+ // Update RoomManagementManager cache
1400
+ this.roomManagement.upsertRoom(room);
1401
+ // Emit on RoomManagementManager for promise resolution (see createRoom method)
1402
+ this.roomManagement.emit("room:created", room);
1403
+ // Emit on SDK for external listeners
1404
+ this.emit("room:created", room);
1405
+ });
1406
+ this.wsClient.on("room:updated", (room) => {
1407
+ // Update RoomManagementManager cache
1408
+ this.roomManagement.upsertRoom(room);
1409
+ // Emit on RoomManagementManager for promise resolution (see updateRoom method)
1410
+ this.roomManagement.emit("room:updated", room);
1411
+ // Emit on SDK for external listeners
1412
+ this.emit("room:updated", room);
1413
+ });
1414
+ this.wsClient.on("room:deleted", (roomId) => {
1415
+ // Remove from RoomManagementManager cache
1416
+ this.roomManagement.removeRoom(roomId);
1417
+ // Emit on RoomManagementManager for promise resolution (see deleteRoom method)
1418
+ this.roomManagement.emit("room:deleted", roomId);
1419
+ // Emit on SDK for external listeners
1420
+ this.emit("room:deleted", roomId);
1421
+ });
1422
+ this.wsClient.on("room:create_error", (error) => {
1423
+ // Emit on RoomManagementManager for promise rejection
1424
+ this.roomManagement.emit("room:create_error", error);
1425
+ // Emit on SDK for external listeners
1426
+ this.emit("room:create_error", error);
1427
+ });
1428
+ this.wsClient.on("room:update_error", (error, roomId) => {
1429
+ // Emit on RoomManagementManager for promise rejection
1430
+ this.roomManagement.emit("room:update_error", error, roomId);
1431
+ // Emit on SDK for external listeners
1432
+ this.emit("room:update_error", error, roomId);
1433
+ });
1434
+ this.wsClient.on("room:delete_error", (error, roomId) => {
1435
+ // Emit on RoomManagementManager for promise rejection
1436
+ this.roomManagement.emit("room:delete_error", error, roomId);
1437
+ // Emit on SDK for external listeners
1438
+ this.emit("room:delete_error", error, roomId);
1439
+ });
1440
+
1441
+ // Forward agent room management events from WebSocketClient (emitted by handlers) (v2.0.0)
1442
+ // These events are emitted by message handlers, so we listen on wsClient
1443
+ // We forward to AgentRoomManager first (for promise resolution), then emit on SDK
1444
+ this.wsClient.on("agent_room:agent_added", (roomId, agentId) => {
1445
+ // Emit on AgentRoomManager for promise resolution (see addAgentToRoom method)
1446
+ this.agentRoom.emit("agent_room:agent_added", roomId, agentId);
1447
+ // Emit on SDK for external listeners
1448
+ this.emit("agent_room:agent_added", roomId, agentId);
1449
+ });
1450
+ this.wsClient.on("agent_room:agent_removed", (roomId, agentId) => {
1451
+ // Emit on AgentRoomManager for promise resolution (see removeAgentFromRoom method)
1452
+ this.agentRoom.emit("agent_room:agent_removed", roomId, agentId);
1453
+ // Emit on SDK for external listeners
1454
+ this.emit("agent_room:agent_removed", roomId, agentId);
1455
+ });
1456
+ this.wsClient.on("agent_room:agents_listed", (roomId, agents) => {
1457
+ // Emit on AgentRoomManager for promise resolution
1458
+ this.agentRoom.emit("agent_room:agents_listed", roomId, agents);
1459
+ // Emit on SDK for external listeners
1460
+ this.emit("agent_room:agents_listed", roomId, agents);
1461
+ });
1462
+ this.wsClient.on("agent_room:available_agents_listed", (agents) => {
1463
+ // Emit on AgentRoomManager for promise resolution
1464
+ this.agentRoom.emit("agent_room:available_agents_listed", agents);
1465
+ // Emit on SDK for external listeners
1466
+ this.emit("agent_room:available_agents_listed", agents);
1467
+ });
1468
+ this.wsClient.on("agent_room:status_update", (data) => {
1469
+ // Emit on SDK for external listeners
1470
+ this.emit("agent_room:status_update", data);
1471
+ });
1472
+ this.wsClient.on("agent_room:add_error", (error, roomId) => {
1473
+ // Emit on AgentRoomManager for promise rejection
1474
+ this.agentRoom.emit("agent_room:add_error", error, roomId);
1475
+ // Emit on SDK for external listeners
1476
+ this.emit("agent_room:add_error", error, roomId);
1477
+ });
1478
+ this.wsClient.on("agent_room:remove_error", (error, roomId) => {
1479
+ // Emit on AgentRoomManager for promise rejection
1480
+ this.agentRoom.emit("agent_room:remove_error", error, roomId);
1481
+ // Emit on SDK for external listeners
1482
+ this.emit("agent_room:remove_error", error, roomId);
1483
+ });
1484
+ this.wsClient.on("agent_room:list_error", (error, roomId) => {
1485
+ // Emit on AgentRoomManager for promise rejection
1486
+ this.agentRoom.emit("agent_room:list_error", error, roomId);
1487
+ // Emit on SDK for external listeners
1488
+ this.emit("agent_room:list_error", error, roomId);
1489
+ });
1490
+ this.wsClient.on("agent_room:list_available_error", (error) => {
1491
+ // Emit on AgentRoomManager for promise rejection
1492
+ this.agentRoom.emit("agent_room:list_available_error", error);
1493
+ // Emit on SDK for external listeners
1494
+ this.emit("agent_room:list_available_error", error);
1495
+ });
963
1496
 
964
1497
  // Forward webhook events from WebhookHandler
965
1498
  this.webhookHandler.on("webhook:sent", (payload, url) =>
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { z } from "zod";
7
- import { ClientTypeSchema, RoomSchema, MessageTypeSchema, MessageType } from "./messages";
7
+ import { ClientTypeSchema, RoomInfoSchema, MessageTypeSchema, MessageType } from "./messages";
8
8
  import { RetryStrategySchema, type RetryStrategy } from "../utils/retry-policy";
9
9
  import type { SecurePrivateKey } from "../utils/secure-private-key";
10
10
 
@@ -47,7 +47,9 @@ const PrivateKeySchema = z.union([
47
47
  z.custom<SecurePrivateKey>(
48
48
  (val) => {
49
49
  // Check if it's a SecurePrivateKey instance
50
- return val && typeof val === 'object' && 'use' in val && 'destroy' in val && 'isDestroyed' in val;
50
+ return (
51
+ val && typeof val === "object" && "use" in val && "destroy" in val && "isDestroyed" in val
52
+ );
51
53
  },
52
54
  { message: "Must be a string or SecurePrivateKey instance" }
53
55
  )
@@ -144,11 +146,16 @@ export const AuthenticationStateSchema = z.object({
144
146
  isWhitelisted: z.boolean().optional(),
145
147
  isAdmin: z.boolean().optional(),
146
148
  nftVerified: z.boolean().optional(),
147
- rooms: z.array(z.string()).optional(), // Room IDs for backward compatibility
148
- roomObjects: z.array(RoomSchema).optional(), // Full room objects from auth
149
- privateRoomId: z.string().optional(),
149
+ rooms: z.array(z.string()).optional(), // Room IDs for backward compatibility (deprecated)
150
+ roomObjects: z.array(RoomInfoSchema).optional(), // Full room objects from auth (v2.0.0: uses RoomInfo)
151
+ privateRoomId: z.string().optional(), // DEPRECATED: Single room ID (use privateRoomIds instead)
150
152
  challenge: z.string().optional(),
151
- challengeTimestamp: z.number().optional()
153
+ challengeTimestamp: z.number().optional(),
154
+
155
+ // NEW in v2.0.0: Room categorization
156
+ privateRoomIds: z.array(z.string()).optional(), // IDs of rooms user owns
157
+ sharedRoomIds: z.array(z.string()).optional(), // IDs of rooms user is member of
158
+ maxPrivateRooms: z.number().optional() // Max rooms user can create
152
159
  });
153
160
 
154
161
  // Webhook config schema
@@ -38,6 +38,10 @@ export enum ErrorCode {
38
38
  // Rate limit
39
39
  RATE_LIMIT = "RATE_LIMIT",
40
40
 
41
+ // Room Management errors (v2.0.0)
42
+ OPERATION_FAILED = "OPERATION_FAILED",
43
+ PERMISSION_DENIED = "PERMISSION_DENIED",
44
+
41
45
  // Generic timeout (for backward compatibility)
42
46
  TIMEOUT_ERROR = "TIMEOUT_ERROR",
43
47
  TIMEOUT = "TIMEOUT"