@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
@@ -15,7 +15,7 @@ import { TeneoSDK, SDKConfigBuilder } from "../../dist/index.js";
15
15
 
16
16
  // Load configuration from environment
17
17
  const WS_URL =
18
- process.env.WS_URL || "wss://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/ws";
18
+ process.env.WS_URL || "wss://your-teneo-server.com/ws";
19
19
  const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
20
20
  const DEFAULT_ROOM = process.env.DEFAULT_ROOM || "general";
21
21
 
@@ -15,7 +15,7 @@ import { TeneoSDK, SDKConfigBuilder } from "../../dist/index.js";
15
15
 
16
16
  // Load configuration from environment
17
17
  const WS_URL =
18
- process.env.WS_URL || "wss://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/ws";
18
+ process.env.WS_URL || "wss://your-teneo-server.com/ws";
19
19
  const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
20
20
  const DEFAULT_ROOM = process.env.DEFAULT_ROOM || "general";
21
21
 
@@ -16,7 +16,7 @@ import { TeneoSDK, SDKConfigBuilder, FormattedResponse } from "../../dist/index.
16
16
 
17
17
  // Load configuration from environment
18
18
  const WS_URL =
19
- process.env.WS_URL || "wss://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/ws";
19
+ process.env.WS_URL || "wss://your-teneo-server.com/ws";
20
20
  const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
21
21
  const DEFAULT_ROOM = process.env.DEFAULT_ROOM || "general";
22
22
 
@@ -16,7 +16,7 @@ import { TeneoSDK, SDKConfigBuilder } from "../../dist/index.js";
16
16
 
17
17
  // Load configuration from environment
18
18
  const WS_URL =
19
- process.env.WS_URL || "wss://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/ws";
19
+ process.env.WS_URL || "wss://your-teneo-server.com/ws";
20
20
  const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
21
21
  const DEFAULT_ROOM = process.env.DEFAULT_ROOM || "general";
22
22
 
@@ -27,7 +27,7 @@ import type { Request, Response } from "express";
27
27
 
28
28
  // Load configuration from environment
29
29
  const WS_URL =
30
- process.env.WS_URL || "wss://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/ws";
30
+ process.env.WS_URL || "wss://your-teneo-server.com/ws";
31
31
  const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
32
32
  const DEFAULT_ROOM = process.env.DEFAULT_ROOM || "general";
33
33
  const WEBHOOK_PORT = parseInt(process.env.WEBHOOK_PORT || "3001");
@@ -22,7 +22,7 @@ import { TeneoSDK, SDKConfigBuilder } from "../../dist/index.js";
22
22
 
23
23
  // Load configuration from environment
24
24
  const WS_URL =
25
- process.env.WS_URL || "wss://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/ws";
25
+ process.env.WS_URL || "wss://your-teneo-server.com/ws";
26
26
  const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
27
27
  const DEFAULT_ROOM = process.env.DEFAULT_ROOM || "general";
28
28
  const PORT = parseInt(process.env.PORT || "3000");
@@ -16,7 +16,7 @@ import { TeneoSDK, SDKConfigBuilder } from "../../dist/index.js";
16
16
 
17
17
  // Load configuration from environment
18
18
  const WS_URL =
19
- process.env.WS_URL || "wss://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/ws";
19
+ process.env.WS_URL || "wss://your-teneo-server.com/ws";
20
20
  const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
21
21
  const DEFAULT_ROOM = process.env.DEFAULT_ROOM || "general";
22
22
 
@@ -29,7 +29,7 @@ Create a `.env` file in the project root or export these variables:
29
29
  ```bash
30
30
  # Required
31
31
  PRIVATE_KEY=your_ethereum_private_key_here
32
- WS_URL=wss://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/ws
32
+ WS_URL=wss://your-teneo-server.com/ws
33
33
 
34
34
  # Optional
35
35
  DEFAULT_ROOM=general
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teneo-protocol/sdk",
3
- "version": "1.0.1",
3
+ "version": "2.0.0",
4
4
  "description": "TypeScript SDK for external platforms to interact with Teneo agents",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -15,6 +15,14 @@
15
15
  ],
16
16
  "author": "Teneo Protocol",
17
17
  "license": "AGPL-3.0",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/TeneoProtocolAI/teneo-sdk.git"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/TeneoProtocolAI/teneo-sdk/issues"
24
+ },
25
+ "homepage": "https://github.com/TeneoProtocolAI/teneo-sdk#readme",
18
26
  "dependencies": {
19
27
  "eventemitter3": "^5.0.1",
20
28
  "node-fetch": "^3.3.2",
@@ -56,6 +56,8 @@ export class WebSocketClient extends EventEmitter<SDKEvents> {
56
56
  private deduplicationCache?: DeduplicationCache;
57
57
  private reconnectPolicy: RetryPolicy;
58
58
  private roomManager?: any; // Reference to RoomManager for handler context
59
+ private roomManagementManager?: any; // Reference to RoomManagementManager for handler context (v2.0.0)
60
+ private agentRoomManager?: any; // Reference to AgentRoomManager for handler context (v2.0.0)
59
61
  private intentionalDisconnect: boolean = false; // Track intentional disconnect to prevent reconnection
60
62
 
61
63
  private connectionState: ConnectionState = {
@@ -211,6 +213,22 @@ export class WebSocketClient extends EventEmitter<SDKEvents> {
211
213
  this.roomManager = roomManager;
212
214
  }
213
215
 
216
+ /**
217
+ * Sets the room management manager for room CRUD operations (v2.0.0)
218
+ * @internal
219
+ */
220
+ public setRoomManagementManager(roomManagementManager: any): void {
221
+ this.roomManagementManager = roomManagementManager;
222
+ }
223
+
224
+ /**
225
+ * Sets the agent room manager for agent-room operations (v2.0.0)
226
+ * @internal
227
+ */
228
+ public setAgentRoomManager(agentRoomManager: any): void {
229
+ this.agentRoomManager = agentRoomManager;
230
+ }
231
+
214
232
  /**
215
233
  * Establishes a WebSocket connection to the Teneo server.
216
234
  * Handles connection timeout, authentication challenge-response flow,
@@ -296,7 +314,11 @@ export class WebSocketClient extends EventEmitter<SDKEvents> {
296
314
  if (parseResult.success) {
297
315
  this.handleMessage(parseResult.data as BaseMessage);
298
316
  } else {
299
- this.logger.error("Invalid message format", parseResult.error);
317
+ // Use warn instead of error - allows SDK to be more resilient
318
+ this.logger.warn("Received message with unknown or invalid format", {
319
+ type: rawMessage?.type,
320
+ error: parseResult.error?.message
321
+ });
300
322
  this.emit(
301
323
  "message:error",
302
324
  new ValidationError("Invalid message format", parseResult.error),
@@ -494,7 +516,7 @@ export class WebSocketClient extends EventEmitter<SDKEvents> {
494
516
  this.logger.error("Failed to send message", error);
495
517
  reject(error);
496
518
  } else {
497
- this.logger.debug("Message sent", { type: validatedMessage.type });
519
+ this.logger.debug("Message sent", validatedMessage);
498
520
  this.emit("message:sent", validatedMessage);
499
521
  resolve();
500
522
  }
@@ -653,6 +675,8 @@ export class WebSocketClient extends EventEmitter<SDKEvents> {
653
675
  updateConnectionState: (update: any) => this.updateConnectionState(update),
654
676
  updateAuthState: (update: any) => this.updateAuthState(update),
655
677
  roomManager: this.roomManager,
678
+ roomManagementManager: this.roomManagementManager,
679
+ agentRoomManager: this.agentRoomManager,
656
680
  account: this.account,
657
681
  sendMessage: (message: BaseMessage) => this.sendMessage(message)
658
682
  };
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Handler for agent_room_operation_response messages (v2.0.0)
3
+ * Processes responses from agent-room operations (add, remove)
4
+ */
5
+
6
+ import {
7
+ AgentRoomOperationResponse,
8
+ AgentRoomOperationResponseSchema
9
+ } from "../../types";
10
+ import { BaseMessageHandler } from "./base-handler";
11
+ import { HandlerContext } from "./types";
12
+ import { SDKError } from "../../types/events";
13
+ import { ErrorCode } from "../../types/error-codes";
14
+
15
+ export class AgentRoomOperationResponseHandler extends BaseMessageHandler<AgentRoomOperationResponse> {
16
+ readonly type = "agent_room_operation_response" as const;
17
+ readonly schema = AgentRoomOperationResponseSchema;
18
+
19
+ protected handleValidated(
20
+ message: AgentRoomOperationResponse,
21
+ context: HandlerContext
22
+ ): void {
23
+ const { success, message: errorMessage, room_id, agent_id } = message.data;
24
+
25
+ context.logger.debug("Handling agent_room_operation_response", {
26
+ success,
27
+ roomId: room_id,
28
+ agentId: agent_id
29
+ });
30
+
31
+ if (!success) {
32
+ // Operation failed - emit error events
33
+ const error = new SDKError(
34
+ errorMessage || "Agent room operation failed",
35
+ ErrorCode.OPERATION_FAILED
36
+ );
37
+
38
+ context.logger.error("Agent room operation failed", {
39
+ roomId: room_id,
40
+ agentId: agent_id,
41
+ error: errorMessage
42
+ });
43
+
44
+ // Emit both add and remove error events - listeners will filter by room/agent ID
45
+ this.emit(context, "agent_room:add_error", error, room_id);
46
+ this.emit(context, "agent_room:remove_error", error, room_id);
47
+
48
+ // Send webhook
49
+ this.sendWebhook(context, "agent_room_operation_error", {
50
+ success: false,
51
+ message: errorMessage,
52
+ room_id,
53
+ agent_id
54
+ });
55
+
56
+ return;
57
+ }
58
+
59
+ // Operation succeeded
60
+ if (room_id && agent_id) {
61
+ context.logger.info("Agent room operation succeeded", {
62
+ roomId: room_id,
63
+ agentId: agent_id
64
+ });
65
+
66
+ // Emit success events
67
+ // The promise handlers in AgentRoomManager will filter by room_id and agent_id
68
+ this.emit(context, "agent_room:agent_added", room_id, agent_id);
69
+ this.emit(context, "agent_room:agent_removed", room_id, agent_id);
70
+
71
+ // Send webhook
72
+ this.sendWebhook(context, "agent_room_operation", {
73
+ success: true,
74
+ room_id,
75
+ agent_id,
76
+ message: "Agent room operation completed successfully"
77
+ });
78
+ } else {
79
+ // Unexpected: success but missing required fields
80
+ context.logger.warn("Agent room operation succeeded but missing room_id or agent_id");
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Handler for agent_status_update messages (v2.0.0)
3
+ * Processes real-time agent status updates for rooms
4
+ */
5
+
6
+ import {
7
+ AgentStatusUpdateMessage,
8
+ AgentStatusUpdateMessageSchema
9
+ } from "../../types";
10
+ import { BaseMessageHandler } from "./base-handler";
11
+ import { HandlerContext } from "./types";
12
+
13
+ export class AgentStatusUpdateHandler extends BaseMessageHandler<AgentStatusUpdateMessage> {
14
+ readonly type = "agent_status_update" as const;
15
+ readonly schema = AgentStatusUpdateMessageSchema;
16
+
17
+ protected handleValidated(
18
+ message: AgentStatusUpdateMessage,
19
+ context: HandlerContext
20
+ ): void {
21
+ const { room_id, agent_id, status, agent } = message.data;
22
+
23
+ context.logger.debug("Handling agent_status_update", {
24
+ roomId: room_id,
25
+ agentId: agent_id,
26
+ status,
27
+ hasAgent: !!agent
28
+ });
29
+
30
+ // Invalidate cache for this room via agent room manager
31
+ const agentRoomManager = (context as any).agentRoomManager;
32
+ if (agentRoomManager && typeof agentRoomManager.handleStatusUpdate === "function") {
33
+ agentRoomManager.handleStatusUpdate(room_id, agent_id, status);
34
+ }
35
+
36
+ context.logger.info("Agent status updated", {
37
+ roomId: room_id,
38
+ agentId: agent_id,
39
+ status
40
+ });
41
+
42
+ // Emit status update event
43
+ this.emit(context, "agent_room:status_update", {
44
+ roomId: room_id,
45
+ agentId: agent_id,
46
+ status,
47
+ agent
48
+ });
49
+
50
+ // Send webhook
51
+ this.sendWebhook(context, "agent_status_update", {
52
+ room_id,
53
+ agent_id,
54
+ status,
55
+ agent
56
+ });
57
+ }
58
+ }
@@ -26,8 +26,27 @@ export class AuthMessageHandler extends BaseMessageHandler<AuthMessage> {
26
26
  isCachedAuth ? "Using cached authentication" : "Authentication successful"
27
27
  );
28
28
 
29
- // Extract rooms
30
- const rooms = this.extractRooms(message.data?.rooms);
29
+ // Extract rooms from both 'rooms' (public) and 'private_rooms' (owned private) arrays
30
+ const publicRooms = this.extractRooms(message.data?.rooms);
31
+ const privateRooms = this.extractRooms(message.data?.private_rooms);
32
+
33
+ // Combine all rooms, ensuring correct ownership flags
34
+ // Public rooms from 'rooms' array are NOT owned by the user
35
+ // Private rooms from 'private_rooms' array ARE owned by the user
36
+ const allRooms = [
37
+ ...publicRooms.map((r) => ({
38
+ ...r,
39
+ is_owner: false, // Explicitly set to false - public rooms are not owned
40
+ is_public: r.is_public !== undefined ? r.is_public : true // Ensure is_public is set
41
+ })),
42
+ ...privateRooms.map((r) => ({
43
+ ...r,
44
+ is_owner: true, // Explicitly set to true - private_rooms array means owned
45
+ is_public: r.is_public !== undefined ? r.is_public : false // Ensure is_public is set
46
+ }))
47
+ ];
48
+
49
+ const { privateRoomIds, sharedRoomIds } = this.categorizeRooms(allRooms);
31
50
 
32
51
  // Update connection state
33
52
  this.updateConnectionState(context, { authenticated: true });
@@ -40,11 +59,37 @@ export class AuthMessageHandler extends BaseMessageHandler<AuthMessage> {
40
59
  isWhitelisted: message.data?.is_whitelisted,
41
60
  isAdmin: message.data?.is_admin_whitelisted,
42
61
  nftVerified: message.data?.nft_verified,
43
- rooms: rooms.map((r) => r.id),
44
- roomObjects: rooms,
45
- privateRoomId: message.data?.private_room_id
62
+ rooms: allRooms.map((r) => r.id),
63
+ roomObjects: allRooms,
64
+ privateRoomId: message.data?.private_room_id,
65
+ // v2.0.0: New fields
66
+ privateRoomIds, // Rooms user owns
67
+ sharedRoomIds, // Rooms user is member of
68
+ maxPrivateRooms: message.data?.max_private_rooms // Max rooms user can create
46
69
  });
47
70
 
71
+ // Initialize room management manager with room data (v2.0.0)
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ const roomMgmt = (context as any).roomManagementManager;
74
+ if (roomMgmt) {
75
+ // Set room limit
76
+ if (message.data?.max_private_rooms) {
77
+ roomMgmt.setRoomLimit(message.data.max_private_rooms);
78
+ }
79
+
80
+ // Categorize and cache rooms
81
+ const ownedRooms = allRooms.filter((r) => r.is_owner === true);
82
+ const sharedRooms = allRooms.filter((r) => r.is_owner === false);
83
+ roomMgmt.setOwnedRooms(ownedRooms);
84
+ roomMgmt.setSharedRooms(sharedRooms);
85
+
86
+ context.logger.debug("Room management initialized from auth message", {
87
+ owned: ownedRooms.length,
88
+ shared: sharedRooms.length,
89
+ limit: message.data?.max_private_rooms
90
+ });
91
+ }
92
+
48
93
  // Get updated auth state
49
94
  const authState = context.getAuthState();
50
95
 
@@ -63,4 +108,27 @@ export class AuthMessageHandler extends BaseMessageHandler<AuthMessage> {
63
108
  }
64
109
  return rooms;
65
110
  }
111
+
112
+ /**
113
+ * Categorize rooms into owned vs member rooms based on is_owner flag
114
+ * @param rooms - Array of room info objects
115
+ * @returns Object with privateRoomIds (owned) and sharedRoomIds (member)
116
+ */
117
+ private categorizeRooms(rooms: Room[]): {
118
+ privateRoomIds: string[];
119
+ sharedRoomIds: string[];
120
+ } {
121
+ const privateRoomIds: string[] = [];
122
+ const sharedRoomIds: string[] = [];
123
+
124
+ for (const room of rooms) {
125
+ if (room.is_owner) {
126
+ if (room.id) privateRoomIds.push(room.id);
127
+ } else {
128
+ if (room.id) sharedRoomIds.push(room.id);
129
+ }
130
+ }
131
+
132
+ return { privateRoomIds, sharedRoomIds };
133
+ }
66
134
  }
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { z } from "zod";
7
- import { AuthSuccessMessage, AuthSuccessMessageSchema, Room } from "../../types";
7
+ import { AuthSuccessMessage, AuthSuccessMessageSchema, RoomInfo } from "../../types";
8
8
  import { BaseMessageHandler } from "./base-handler";
9
9
  import { HandlerContext } from "./types";
10
10
 
@@ -18,8 +18,9 @@ export class AuthSuccessHandler extends BaseMessageHandler<AuthSuccessMessage> {
18
18
  ): Promise<void> {
19
19
  context.logger.info("Authentication successful");
20
20
 
21
- // Extract rooms
21
+ // Extract and categorize rooms
22
22
  const rooms = this.extractRooms(message.data.rooms);
23
+ const { privateRoomIds, sharedRoomIds } = this.categorizeRooms(rooms);
23
24
 
24
25
  // Update connection state
25
26
  this.updateConnectionState(context, { authenticated: true });
@@ -32,14 +33,42 @@ export class AuthSuccessHandler extends BaseMessageHandler<AuthSuccessMessage> {
32
33
  isWhitelisted: message.data.is_whitelisted,
33
34
  isAdmin: message.data.is_admin_whitelisted,
34
35
  nftVerified: message.data.nft_verified,
35
- rooms: rooms.map((r) => r.id),
36
- roomObjects: rooms,
37
- privateRoomId: message.data.private_room_id
36
+
37
+ // Backward compatibility: deprecated fields
38
+ rooms: rooms.map((r) => r.id), // All room IDs
39
+ privateRoomId: message.data.private_room_id, // DEPRECATED: single private room ID
40
+
41
+ // v2.0.0: New fields
42
+ roomObjects: rooms, // Full room objects with is_owner field
43
+ privateRoomIds, // Rooms user owns
44
+ sharedRoomIds, // Rooms user is member of
45
+ maxPrivateRooms: message.data.max_private_rooms // Max rooms user can create
38
46
  });
39
47
 
40
48
  // Get updated auth state
41
49
  const authState = context.getAuthState();
42
50
 
51
+ // Initialize room management manager with room data (v2.0.0)
52
+ const roomMgmt = (context as any).roomManagementManager;
53
+ if (roomMgmt) {
54
+ // Set room limit
55
+ if (message.data.max_private_rooms) {
56
+ roomMgmt.setRoomLimit(message.data.max_private_rooms);
57
+ }
58
+
59
+ // Categorize and cache rooms
60
+ const ownedRooms = rooms.filter((r) => r.is_owner);
61
+ const sharedRooms = rooms.filter((r) => !r.is_owner);
62
+ roomMgmt.setOwnedRooms(ownedRooms);
63
+ roomMgmt.setSharedRooms(sharedRooms);
64
+
65
+ context.logger.debug("Room management initialized", {
66
+ owned: ownedRooms.length,
67
+ shared: sharedRooms.length,
68
+ limit: message.data.max_private_rooms
69
+ });
70
+ }
71
+
43
72
  // Emit events
44
73
  this.emit(context, "auth:success", authState);
45
74
  this.emit(context, "ready");
@@ -48,10 +77,33 @@ export class AuthSuccessHandler extends BaseMessageHandler<AuthSuccessMessage> {
48
77
  /**
49
78
  * Extract and normalize rooms from auth data
50
79
  */
51
- private extractRooms(rooms?: Room[]): Room[] {
80
+ private extractRooms(rooms?: RoomInfo[] | null): RoomInfo[] {
52
81
  if (!rooms || !Array.isArray(rooms)) {
53
82
  return [];
54
83
  }
55
84
  return rooms;
56
85
  }
86
+
87
+ /**
88
+ * Categorize rooms into owned vs member rooms based on is_owner flag
89
+ * @param rooms - Array of room info objects
90
+ * @returns Object with privateRoomIds (owned) and sharedRoomIds (member)
91
+ */
92
+ private categorizeRooms(rooms: RoomInfo[]): {
93
+ privateRoomIds: string[];
94
+ sharedRoomIds: string[];
95
+ } {
96
+ const privateRoomIds: string[] = [];
97
+ const sharedRoomIds: string[] = [];
98
+
99
+ for (const room of rooms) {
100
+ if (room.is_owner) {
101
+ privateRoomIds.push(room.id);
102
+ } else {
103
+ sharedRoomIds.push(room.id);
104
+ }
105
+ }
106
+
107
+ return { privateRoomIds, sharedRoomIds };
108
+ }
57
109
  }
@@ -22,6 +22,11 @@ export { PingHandler, PongHandler } from "./ping-pong-handler";
22
22
  export { SubscribeResponseHandler } from "./subscribe-response-handler";
23
23
  export { UnsubscribeResponseHandler } from "./unsubscribe-response-handler";
24
24
  export { ListRoomsResponseHandler } from "./list-rooms-response-handler";
25
+ export { RoomOperationResponseHandler } from "./room-operation-response-handler";
26
+ export { AgentRoomOperationResponseHandler } from "./agent-room-operation-response-handler";
27
+ export { ListRoomAgentsHandler } from "./list-room-agents-handler";
28
+ export { ListAvailableAgentsHandler } from "./list-available-agents-handler";
29
+ export { AgentStatusUpdateHandler } from "./agent-status-update-handler";
25
30
 
26
31
  // Import for convenience function
27
32
  import { TaskResponseHandler } from "./task-response-handler";
@@ -38,6 +43,11 @@ import { PingHandler, PongHandler } from "./ping-pong-handler";
38
43
  import { SubscribeResponseHandler } from "./subscribe-response-handler";
39
44
  import { UnsubscribeResponseHandler } from "./unsubscribe-response-handler";
40
45
  import { ListRoomsResponseHandler } from "./list-rooms-response-handler";
46
+ import { RoomOperationResponseHandler } from "./room-operation-response-handler";
47
+ import { AgentRoomOperationResponseHandler } from "./agent-room-operation-response-handler";
48
+ import { ListRoomAgentsHandler } from "./list-room-agents-handler";
49
+ import { ListAvailableAgentsHandler } from "./list-available-agents-handler";
50
+ import { AgentStatusUpdateHandler } from "./agent-status-update-handler";
41
51
  import { MessageHandler } from "./types";
42
52
 
43
53
  /**
@@ -70,6 +80,15 @@ export function getDefaultHandlers(
70
80
  new UnsubscribeResponseHandler(),
71
81
  new ListRoomsResponseHandler(),
72
82
 
83
+ // Room Management handlers (v2.0.0)
84
+ new RoomOperationResponseHandler(),
85
+
86
+ // Agent Room Management handlers (v2.0.0)
87
+ new AgentRoomOperationResponseHandler(),
88
+ new ListRoomAgentsHandler(),
89
+ new ListAvailableAgentsHandler(),
90
+ new AgentStatusUpdateHandler(),
91
+
73
92
  // Keepalive handlers
74
93
  new PingHandler(),
75
94
  new PongHandler()
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Handler for available_agents_response messages (v2.0.0)
3
+ * Processes responses from list_available_agents requests
4
+ */
5
+
6
+ import { AvailableAgentsResponse, AvailableAgentsResponseSchema } from "../../types";
7
+ import { BaseMessageHandler } from "./base-handler";
8
+ import { HandlerContext } from "./types";
9
+ import { AgentRoomInfo } from "../../managers/agent-room-manager";
10
+
11
+ export class ListAvailableAgentsHandler extends BaseMessageHandler<AvailableAgentsResponse> {
12
+ readonly type = "available_agents_response" as const;
13
+ readonly schema = AvailableAgentsResponseSchema;
14
+
15
+ protected handleValidated(message: AvailableAgentsResponse, context: HandlerContext): void {
16
+ const { agents } = message.data;
17
+
18
+ context.logger.debug("Handling available_agents_response", {
19
+ agentCount: agents?.length || 0
20
+ });
21
+
22
+ // Parse agents array (handle undefined as empty array)
23
+ const agentList: AgentRoomInfo[] = agents || [];
24
+
25
+ context.logger.info("Available agents listed", {
26
+ count: agentList.length
27
+ });
28
+
29
+ // Note: We don't cache this globally since it's room-specific
30
+ // The AgentRoomManager will cache it with the room context
31
+
32
+ // Emit success event
33
+ this.emit(context, "agent_room:available_agents_listed", agentList);
34
+
35
+ // Send webhook
36
+ this.sendWebhook(context, "available_agents_listed", {
37
+ agents: agentList,
38
+ count: agentList.length
39
+ });
40
+ }
41
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Handler for room_agents_response messages (v2.0.0)
3
+ * Processes responses from list_room_agents requests
4
+ */
5
+
6
+ import { RoomAgentsResponse, RoomAgentsResponseSchema } from "../../types";
7
+ import { BaseMessageHandler } from "./base-handler";
8
+ import { HandlerContext } from "./types";
9
+ import { SDKError } from "../../types/events";
10
+ import { ErrorCode } from "../../types/error-codes";
11
+ import { AgentRoomInfo } from "../../managers/agent-room-manager";
12
+
13
+ export class ListRoomAgentsHandler extends BaseMessageHandler<RoomAgentsResponse> {
14
+ readonly type = "room_agents_response" as const;
15
+ readonly schema = RoomAgentsResponseSchema;
16
+
17
+ protected handleValidated(
18
+ message: RoomAgentsResponse,
19
+ context: HandlerContext
20
+ ): void {
21
+ const { room_id, agents } = message.data;
22
+
23
+ context.logger.debug("Handling room_agents_response", {
24
+ roomId: room_id,
25
+ agentCount: agents?.length || 0
26
+ });
27
+
28
+ if (!room_id) {
29
+ const error = new SDKError(
30
+ "Room agents response missing room_id",
31
+ ErrorCode.VALIDATION_ERROR
32
+ );
33
+ this.emit(context, "agent_room:list_error", error, undefined);
34
+ return;
35
+ }
36
+
37
+ // Parse agents array (handle undefined as empty array)
38
+ const agentList: AgentRoomInfo[] = agents || [];
39
+
40
+ context.logger.info("Room agents listed", {
41
+ roomId: room_id,
42
+ count: agentList.length
43
+ });
44
+
45
+ // Cache via agent room manager if available
46
+ const agentRoomManager = (context as any).agentRoomManager;
47
+ if (agentRoomManager && typeof agentRoomManager.cacheRoomAgents === "function") {
48
+ agentRoomManager.cacheRoomAgents(room_id, agentList);
49
+ }
50
+
51
+ // Emit success event
52
+ this.emit(context, "agent_room:agents_listed", room_id, agentList);
53
+
54
+ // Send webhook
55
+ this.sendWebhook(context, "room_agents_listed", {
56
+ room_id,
57
+ agents: agentList,
58
+ count: agentList.length
59
+ });
60
+ }
61
+ }