@teneo-protocol/sdk 1.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 (281) hide show
  1. package/.dockerignore +14 -0
  2. package/.env.test.example +14 -0
  3. package/.eslintrc.json +26 -0
  4. package/.github/workflows/claude-code-review.yml +78 -0
  5. package/.github/workflows/claude-reviewer.yml +64 -0
  6. package/.github/workflows/publish-npm.yml +38 -0
  7. package/.github/workflows/push-to-main.yml +23 -0
  8. package/.node-version +1 -0
  9. package/.prettierrc +11 -0
  10. package/Dockerfile +25 -0
  11. package/LICENCE +661 -0
  12. package/README.md +709 -0
  13. package/dist/constants.d.ts +42 -0
  14. package/dist/constants.d.ts.map +1 -0
  15. package/dist/constants.js +45 -0
  16. package/dist/constants.js.map +1 -0
  17. package/dist/core/websocket-client.d.ts +261 -0
  18. package/dist/core/websocket-client.d.ts.map +1 -0
  19. package/dist/core/websocket-client.js +875 -0
  20. package/dist/core/websocket-client.js.map +1 -0
  21. package/dist/formatters/response-formatter.d.ts +354 -0
  22. package/dist/formatters/response-formatter.d.ts.map +1 -0
  23. package/dist/formatters/response-formatter.js +575 -0
  24. package/dist/formatters/response-formatter.js.map +1 -0
  25. package/dist/handlers/message-handler-registry.d.ts +155 -0
  26. package/dist/handlers/message-handler-registry.d.ts.map +1 -0
  27. package/dist/handlers/message-handler-registry.js +216 -0
  28. package/dist/handlers/message-handler-registry.js.map +1 -0
  29. package/dist/handlers/message-handlers/agent-selected-handler.d.ts +112 -0
  30. package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -0
  31. package/dist/handlers/message-handlers/agent-selected-handler.js +40 -0
  32. package/dist/handlers/message-handlers/agent-selected-handler.js.map +1 -0
  33. package/dist/handlers/message-handlers/agents-list-handler.d.ts +14 -0
  34. package/dist/handlers/message-handlers/agents-list-handler.d.ts.map +1 -0
  35. package/dist/handlers/message-handlers/agents-list-handler.js +25 -0
  36. package/dist/handlers/message-handlers/agents-list-handler.js.map +1 -0
  37. package/dist/handlers/message-handlers/auth-error-handler.d.ts +71 -0
  38. package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -0
  39. package/dist/handlers/message-handlers/auth-error-handler.js +30 -0
  40. package/dist/handlers/message-handlers/auth-error-handler.js.map +1 -0
  41. package/dist/handlers/message-handlers/auth-message-handler.d.ts +18 -0
  42. package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -0
  43. package/dist/handlers/message-handlers/auth-message-handler.js +60 -0
  44. package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -0
  45. package/dist/handlers/message-handlers/auth-required-handler.d.ts +76 -0
  46. package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -0
  47. package/dist/handlers/message-handlers/auth-required-handler.js +23 -0
  48. package/dist/handlers/message-handlers/auth-required-handler.js.map +1 -0
  49. package/dist/handlers/message-handlers/auth-success-handler.d.ts +18 -0
  50. package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -0
  51. package/dist/handlers/message-handlers/auth-success-handler.js +51 -0
  52. package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -0
  53. package/dist/handlers/message-handlers/base-handler.d.ts +55 -0
  54. package/dist/handlers/message-handlers/base-handler.d.ts.map +1 -0
  55. package/dist/handlers/message-handlers/base-handler.js +83 -0
  56. package/dist/handlers/message-handlers/base-handler.js.map +1 -0
  57. package/dist/handlers/message-handlers/challenge-handler.d.ts +73 -0
  58. package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -0
  59. package/dist/handlers/message-handlers/challenge-handler.js +47 -0
  60. package/dist/handlers/message-handlers/challenge-handler.js.map +1 -0
  61. package/dist/handlers/message-handlers/error-message-handler.d.ts +76 -0
  62. package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -0
  63. package/dist/handlers/message-handlers/error-message-handler.js +29 -0
  64. package/dist/handlers/message-handlers/error-message-handler.js.map +1 -0
  65. package/dist/handlers/message-handlers/index.d.ts +28 -0
  66. package/dist/handlers/message-handlers/index.d.ts.map +1 -0
  67. package/dist/handlers/message-handlers/index.js +100 -0
  68. package/dist/handlers/message-handlers/index.js.map +1 -0
  69. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts +122 -0
  70. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -0
  71. package/dist/handlers/message-handlers/list-rooms-response-handler.js +30 -0
  72. package/dist/handlers/message-handlers/list-rooms-response-handler.js.map +1 -0
  73. package/dist/handlers/message-handlers/ping-pong-handler.d.ts +104 -0
  74. package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -0
  75. package/dist/handlers/message-handlers/ping-pong-handler.js +36 -0
  76. package/dist/handlers/message-handlers/ping-pong-handler.js.map +1 -0
  77. package/dist/handlers/message-handlers/regular-message-handler.d.ts +56 -0
  78. package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -0
  79. package/dist/handlers/message-handlers/regular-message-handler.js +59 -0
  80. package/dist/handlers/message-handlers/regular-message-handler.js.map +1 -0
  81. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +81 -0
  82. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -0
  83. package/dist/handlers/message-handlers/subscribe-response-handler.js +48 -0
  84. package/dist/handlers/message-handlers/subscribe-response-handler.js.map +1 -0
  85. package/dist/handlers/message-handlers/task-response-handler.d.ts +14 -0
  86. package/dist/handlers/message-handlers/task-response-handler.d.ts.map +1 -0
  87. package/dist/handlers/message-handlers/task-response-handler.js +44 -0
  88. package/dist/handlers/message-handlers/task-response-handler.js.map +1 -0
  89. package/dist/handlers/message-handlers/types.d.ts +51 -0
  90. package/dist/handlers/message-handlers/types.d.ts.map +1 -0
  91. package/dist/handlers/message-handlers/types.js +7 -0
  92. package/dist/handlers/message-handlers/types.js.map +1 -0
  93. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +81 -0
  94. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -0
  95. package/dist/handlers/message-handlers/unsubscribe-response-handler.js +48 -0
  96. package/dist/handlers/message-handlers/unsubscribe-response-handler.js.map +1 -0
  97. package/dist/handlers/webhook-handler.d.ts +202 -0
  98. package/dist/handlers/webhook-handler.d.ts.map +1 -0
  99. package/dist/handlers/webhook-handler.js +511 -0
  100. package/dist/handlers/webhook-handler.js.map +1 -0
  101. package/dist/index.d.ts +71 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +217 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/managers/agent-registry.d.ts +173 -0
  106. package/dist/managers/agent-registry.d.ts.map +1 -0
  107. package/dist/managers/agent-registry.js +310 -0
  108. package/dist/managers/agent-registry.js.map +1 -0
  109. package/dist/managers/connection-manager.d.ts +134 -0
  110. package/dist/managers/connection-manager.d.ts.map +1 -0
  111. package/dist/managers/connection-manager.js +176 -0
  112. package/dist/managers/connection-manager.js.map +1 -0
  113. package/dist/managers/index.d.ts +9 -0
  114. package/dist/managers/index.d.ts.map +1 -0
  115. package/dist/managers/index.js +16 -0
  116. package/dist/managers/index.js.map +1 -0
  117. package/dist/managers/message-router.d.ts +112 -0
  118. package/dist/managers/message-router.d.ts.map +1 -0
  119. package/dist/managers/message-router.js +260 -0
  120. package/dist/managers/message-router.js.map +1 -0
  121. package/dist/managers/room-manager.d.ts +165 -0
  122. package/dist/managers/room-manager.d.ts.map +1 -0
  123. package/dist/managers/room-manager.js +227 -0
  124. package/dist/managers/room-manager.js.map +1 -0
  125. package/dist/teneo-sdk.d.ts +703 -0
  126. package/dist/teneo-sdk.d.ts.map +1 -0
  127. package/dist/teneo-sdk.js +907 -0
  128. package/dist/teneo-sdk.js.map +1 -0
  129. package/dist/types/config.d.ts +1047 -0
  130. package/dist/types/config.d.ts.map +1 -0
  131. package/dist/types/config.js +720 -0
  132. package/dist/types/config.js.map +1 -0
  133. package/dist/types/error-codes.d.ts +29 -0
  134. package/dist/types/error-codes.d.ts.map +1 -0
  135. package/dist/types/error-codes.js +41 -0
  136. package/dist/types/error-codes.js.map +1 -0
  137. package/dist/types/events.d.ts +616 -0
  138. package/dist/types/events.d.ts.map +1 -0
  139. package/dist/types/events.js +261 -0
  140. package/dist/types/events.js.map +1 -0
  141. package/dist/types/health.d.ts +40 -0
  142. package/dist/types/health.d.ts.map +1 -0
  143. package/dist/types/health.js +6 -0
  144. package/dist/types/health.js.map +1 -0
  145. package/dist/types/index.d.ts +10 -0
  146. package/dist/types/index.d.ts.map +1 -0
  147. package/dist/types/index.js +123 -0
  148. package/dist/types/index.js.map +1 -0
  149. package/dist/types/messages.d.ts +3734 -0
  150. package/dist/types/messages.d.ts.map +1 -0
  151. package/dist/types/messages.js +482 -0
  152. package/dist/types/messages.js.map +1 -0
  153. package/dist/types/validation.d.ts +81 -0
  154. package/dist/types/validation.d.ts.map +1 -0
  155. package/dist/types/validation.js +115 -0
  156. package/dist/types/validation.js.map +1 -0
  157. package/dist/utils/bounded-queue.d.ts +127 -0
  158. package/dist/utils/bounded-queue.d.ts.map +1 -0
  159. package/dist/utils/bounded-queue.js +181 -0
  160. package/dist/utils/bounded-queue.js.map +1 -0
  161. package/dist/utils/circuit-breaker.d.ts +141 -0
  162. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  163. package/dist/utils/circuit-breaker.js +215 -0
  164. package/dist/utils/circuit-breaker.js.map +1 -0
  165. package/dist/utils/deduplication-cache.d.ts +110 -0
  166. package/dist/utils/deduplication-cache.d.ts.map +1 -0
  167. package/dist/utils/deduplication-cache.js +177 -0
  168. package/dist/utils/deduplication-cache.js.map +1 -0
  169. package/dist/utils/event-waiter.d.ts +101 -0
  170. package/dist/utils/event-waiter.d.ts.map +1 -0
  171. package/dist/utils/event-waiter.js +118 -0
  172. package/dist/utils/event-waiter.js.map +1 -0
  173. package/dist/utils/index.d.ts +51 -0
  174. package/dist/utils/index.d.ts.map +1 -0
  175. package/dist/utils/index.js +72 -0
  176. package/dist/utils/index.js.map +1 -0
  177. package/dist/utils/logger.d.ts +22 -0
  178. package/dist/utils/logger.d.ts.map +1 -0
  179. package/dist/utils/logger.js +91 -0
  180. package/dist/utils/logger.js.map +1 -0
  181. package/dist/utils/rate-limiter.d.ts +122 -0
  182. package/dist/utils/rate-limiter.d.ts.map +1 -0
  183. package/dist/utils/rate-limiter.js +190 -0
  184. package/dist/utils/rate-limiter.js.map +1 -0
  185. package/dist/utils/retry-policy.d.ts +191 -0
  186. package/dist/utils/retry-policy.d.ts.map +1 -0
  187. package/dist/utils/retry-policy.js +225 -0
  188. package/dist/utils/retry-policy.js.map +1 -0
  189. package/dist/utils/secure-private-key.d.ts +113 -0
  190. package/dist/utils/secure-private-key.d.ts.map +1 -0
  191. package/dist/utils/secure-private-key.js +188 -0
  192. package/dist/utils/secure-private-key.js.map +1 -0
  193. package/dist/utils/signature-verifier.d.ts +143 -0
  194. package/dist/utils/signature-verifier.d.ts.map +1 -0
  195. package/dist/utils/signature-verifier.js +238 -0
  196. package/dist/utils/signature-verifier.js.map +1 -0
  197. package/dist/utils/ssrf-validator.d.ts +36 -0
  198. package/dist/utils/ssrf-validator.d.ts.map +1 -0
  199. package/dist/utils/ssrf-validator.js +195 -0
  200. package/dist/utils/ssrf-validator.js.map +1 -0
  201. package/examples/.env.example +17 -0
  202. package/examples/basic-usage.ts +211 -0
  203. package/examples/production-dashboard/.env.example +153 -0
  204. package/examples/production-dashboard/package.json +39 -0
  205. package/examples/production-dashboard/public/dashboard.html +642 -0
  206. package/examples/production-dashboard/server.ts +753 -0
  207. package/examples/webhook-integration.ts +239 -0
  208. package/examples/x-influencer-battle-redesign.html +1065 -0
  209. package/examples/x-influencer-battle-server.ts +217 -0
  210. package/examples/x-influencer-battle.html +787 -0
  211. package/package.json +65 -0
  212. package/src/constants.ts +43 -0
  213. package/src/core/websocket-client.test.ts +512 -0
  214. package/src/core/websocket-client.ts +1056 -0
  215. package/src/formatters/response-formatter.test.ts +571 -0
  216. package/src/formatters/response-formatter.ts +677 -0
  217. package/src/handlers/message-handler-registry.ts +239 -0
  218. package/src/handlers/message-handlers/agent-selected-handler.ts +40 -0
  219. package/src/handlers/message-handlers/agents-list-handler.ts +26 -0
  220. package/src/handlers/message-handlers/auth-error-handler.ts +31 -0
  221. package/src/handlers/message-handlers/auth-message-handler.ts +66 -0
  222. package/src/handlers/message-handlers/auth-required-handler.ts +23 -0
  223. package/src/handlers/message-handlers/auth-success-handler.ts +57 -0
  224. package/src/handlers/message-handlers/base-handler.ts +101 -0
  225. package/src/handlers/message-handlers/challenge-handler.ts +57 -0
  226. package/src/handlers/message-handlers/error-message-handler.ts +27 -0
  227. package/src/handlers/message-handlers/index.ts +77 -0
  228. package/src/handlers/message-handlers/list-rooms-response-handler.ts +28 -0
  229. package/src/handlers/message-handlers/ping-pong-handler.ts +30 -0
  230. package/src/handlers/message-handlers/regular-message-handler.ts +65 -0
  231. package/src/handlers/message-handlers/subscribe-response-handler.ts +47 -0
  232. package/src/handlers/message-handlers/task-response-handler.ts +45 -0
  233. package/src/handlers/message-handlers/types.ts +77 -0
  234. package/src/handlers/message-handlers/unsubscribe-response-handler.ts +47 -0
  235. package/src/handlers/webhook-handler.test.ts +789 -0
  236. package/src/handlers/webhook-handler.ts +576 -0
  237. package/src/index.ts +269 -0
  238. package/src/managers/agent-registry.test.ts +466 -0
  239. package/src/managers/agent-registry.ts +347 -0
  240. package/src/managers/connection-manager.ts +195 -0
  241. package/src/managers/index.ts +9 -0
  242. package/src/managers/message-router.ts +349 -0
  243. package/src/managers/room-manager.ts +248 -0
  244. package/src/teneo-sdk.ts +1022 -0
  245. package/src/types/config.test.ts +325 -0
  246. package/src/types/config.ts +799 -0
  247. package/src/types/error-codes.ts +44 -0
  248. package/src/types/events.test.ts +302 -0
  249. package/src/types/events.ts +382 -0
  250. package/src/types/health.ts +46 -0
  251. package/src/types/index.ts +199 -0
  252. package/src/types/messages.test.ts +660 -0
  253. package/src/types/messages.ts +570 -0
  254. package/src/types/validation.ts +123 -0
  255. package/src/utils/bounded-queue.test.ts +356 -0
  256. package/src/utils/bounded-queue.ts +205 -0
  257. package/src/utils/circuit-breaker.test.ts +394 -0
  258. package/src/utils/circuit-breaker.ts +262 -0
  259. package/src/utils/deduplication-cache.test.ts +380 -0
  260. package/src/utils/deduplication-cache.ts +198 -0
  261. package/src/utils/event-waiter.test.ts +381 -0
  262. package/src/utils/event-waiter.ts +172 -0
  263. package/src/utils/index.ts +74 -0
  264. package/src/utils/logger.ts +87 -0
  265. package/src/utils/rate-limiter.test.ts +341 -0
  266. package/src/utils/rate-limiter.ts +211 -0
  267. package/src/utils/retry-policy.test.ts +558 -0
  268. package/src/utils/retry-policy.ts +272 -0
  269. package/src/utils/secure-private-key.test.ts +356 -0
  270. package/src/utils/secure-private-key.ts +205 -0
  271. package/src/utils/signature-verifier.test.ts +464 -0
  272. package/src/utils/signature-verifier.ts +298 -0
  273. package/src/utils/ssrf-validator.test.ts +372 -0
  274. package/src/utils/ssrf-validator.ts +224 -0
  275. package/tests/integration/real-server.test.ts +740 -0
  276. package/tests/integration/websocket.test.ts +381 -0
  277. package/tests/integration-setup.ts +16 -0
  278. package/tests/setup.ts +34 -0
  279. package/tsconfig.json +32 -0
  280. package/vitest.config.ts +42 -0
  281. package/vitest.integration.config.ts +23 -0
@@ -0,0 +1,907 @@
1
+ "use strict";
2
+ /**
3
+ * Main Teneo Protocol SDK class
4
+ * Provides a unified interface for external platforms to interact with Teneo agents
5
+ * Uses manager classes to follow Single Responsibility Principle
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.TeneoSDK = exports.AgentCommandSchema = exports.SendMessageOptionsSchema = void 0;
9
+ const eventemitter3_1 = require("eventemitter3");
10
+ const zod_1 = require("zod");
11
+ const types_1 = require("./types");
12
+ const events_1 = require("./types/events");
13
+ const error_codes_1 = require("./types/error-codes");
14
+ const websocket_client_1 = require("./core/websocket-client");
15
+ const webhook_handler_1 = require("./handlers/webhook-handler");
16
+ const response_formatter_1 = require("./formatters/response-formatter");
17
+ const managers_1 = require("./managers");
18
+ const logger_1 = require("./utils/logger");
19
+ const validation_1 = require("./types/validation");
20
+ // Zod schemas for SDK-specific interfaces
21
+ exports.SendMessageOptionsSchema = zod_1.z.object({
22
+ room: validation_1.RoomIdSchema.optional(),
23
+ from: zod_1.z.string().optional(),
24
+ waitForResponse: zod_1.z.boolean().optional(),
25
+ timeout: zod_1.z.number().min(1000).max(300000).optional(),
26
+ format: zod_1.z.union([types_1.ResponseFormatSchema, zod_1.z.literal("raw"), zod_1.z.literal("humanized")]).optional()
27
+ });
28
+ exports.AgentCommandSchema = zod_1.z.object({
29
+ agent: validation_1.AgentIdSchema,
30
+ command: validation_1.AgentCommandContentSchema,
31
+ room: validation_1.RoomIdSchema.optional()
32
+ });
33
+ class TeneoSDK extends eventemitter3_1.EventEmitter {
34
+ /**
35
+ * Creates a new instance of the Teneo Protocol SDK.
36
+ * Initializes all core components, managers, and validates the provided configuration.
37
+ * The SDK handles WebSocket connections, authentication, message routing, and webhook delivery.
38
+ *
39
+ * @param config - Partial SDK configuration object (only wsUrl is required)
40
+ * @param config.wsUrl - WebSocket URL to connect to (e.g., 'wss://teneo.example.com')
41
+ * @param config.privateKey - Optional Ethereum private key for wallet-based authentication
42
+ * @param config.walletAddress - Optional wallet address (derived from privateKey if not provided)
43
+ * @param config.autoJoinRooms - Optional array of room IDs to subscribe to automatically on connection
44
+ * @param config.webhookUrl - Optional webhook URL for receiving event notifications
45
+ * @param config.reconnect - Enable automatic reconnection (default: true)
46
+ * @param config.logLevel - Logging level: 'debug', 'info', 'warn', 'error', 'silent' (default: 'info')
47
+ * @param config.responseFormat - Response format: 'raw', 'humanized', 'both' (default: 'humanized')
48
+ *
49
+ * @throws {SDKError} If configuration is invalid (ErrorCode.INVALID_CONFIG)
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * // Minimal configuration
54
+ * const sdk = new TeneoSDK({
55
+ * wsUrl: 'wss://teneo.example.com',
56
+ * privateKey: '0x...'
57
+ * });
58
+ *
59
+ * // Full configuration
60
+ * const sdk = new TeneoSDK({
61
+ * wsUrl: 'wss://teneo.example.com',
62
+ * privateKey: '0x...',
63
+ * autoJoinRooms: ['general', 'announcements'],
64
+ * webhookUrl: 'https://api.example.com/webhooks',
65
+ * logLevel: 'debug',
66
+ * responseFormat: 'both',
67
+ * reconnect: true,
68
+ * maxReconnectAttempts: 10
69
+ * });
70
+ *
71
+ * // Using builder pattern (recommended for complex configs)
72
+ * const sdk = TeneoSDK.builder()
73
+ * .wsUrl('wss://teneo.example.com')
74
+ * .privateKey('0x...')
75
+ * .withAutoJoinRooms(['general'])
76
+ * .build();
77
+ * ```
78
+ *
79
+ * @see {@link SDKConfigBuilder} for fluent configuration API
80
+ * @see {@link TeneoSDK.builder} for creating a configuration builder
81
+ */
82
+ constructor(config) {
83
+ super();
84
+ this.isDestroyed = false;
85
+ try {
86
+ // Validate partial config first
87
+ const partialConfig = types_1.PartialSDKConfigSchema.parse(config);
88
+ // Merge with defaults
89
+ const fullConfig = { ...types_1.DEFAULT_CONFIG, ...partialConfig };
90
+ // Validate full configuration
91
+ this.config = (0, types_1.validateConfig)(fullConfig);
92
+ // Initialize logger
93
+ this.logger = this.config.logger ?? this.createDefaultLogger();
94
+ // Initialize core components
95
+ this.wsClient = new websocket_client_1.WebSocketClient(this.config);
96
+ this.webhookHandler = new webhook_handler_1.WebhookHandler(this.config, this.logger);
97
+ this.responseFormatter = new response_formatter_1.ResponseFormatter({
98
+ format: this.config.responseFormat ?? "humanized",
99
+ includeMetadata: this.config.includeMetadata ?? false
100
+ });
101
+ // Initialize managers
102
+ this.connection = new managers_1.ConnectionManager(this.wsClient, this.logger);
103
+ this.rooms = new managers_1.RoomManager(this.wsClient, this.logger);
104
+ this.wsClient.setRoomManager(this.rooms); // Enable subscription tracking in handlers
105
+ this.agents = new managers_1.AgentRegistry(this.logger);
106
+ this.messages = new managers_1.MessageRouter(this.wsClient, this.webhookHandler, this.responseFormatter, this.logger, {
107
+ messageTimeout: this.config.messageTimeout,
108
+ responseFormat: this.config.responseFormat
109
+ });
110
+ // Set up event forwarding
111
+ this.setupEventForwarding();
112
+ this.logger.info("TeneoSDK initialized", { wsUrl: this.config.wsUrl });
113
+ }
114
+ catch (error) {
115
+ if (error instanceof zod_1.z.ZodError) {
116
+ throw new events_1.SDKError("Invalid SDK configuration", error_codes_1.ErrorCode.INVALID_CONFIG, error, false);
117
+ }
118
+ throw error;
119
+ }
120
+ }
121
+ /**
122
+ * Establishes a connection to the Teneo network via WebSocket.
123
+ * Handles authentication automatically and joins any configured auto-join rooms.
124
+ * Emits 'connection:open', 'auth:success', and 'ready' events on successful connection.
125
+ *
126
+ * @returns Promise that resolves when connection and authentication are complete
127
+ * @throws {SDKError} If the SDK has been destroyed (ErrorCode.SDK_DESTROYED)
128
+ * @throws {ConnectionError} If WebSocket connection fails
129
+ * @throws {AuthenticationError} If authentication fails
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const sdk = new TeneoSDK({ wsUrl: 'wss://example.com', privateKey: '0x...' });
134
+ * await sdk.connect();
135
+ * console.log('Connected to Teneo network');
136
+ * ```
137
+ */
138
+ async connect() {
139
+ if (this.isDestroyed) {
140
+ throw new events_1.SDKError("SDK has been destroyed", error_codes_1.ErrorCode.SDK_DESTROYED, null, false);
141
+ }
142
+ try {
143
+ this.logger.info("Connecting to Teneo network");
144
+ await this.connection.connect();
145
+ // Auto-join rooms if configured
146
+ if (this.config.autoJoinRooms && this.config.autoJoinRooms.length > 0) {
147
+ for (const room of this.config.autoJoinRooms) {
148
+ await this.rooms.subscribeToRoom(room);
149
+ }
150
+ }
151
+ this.logger.info("Successfully connected to Teneo network");
152
+ }
153
+ catch (error) {
154
+ this.logger.error("Failed to connect to Teneo network", error);
155
+ throw error;
156
+ }
157
+ }
158
+ /**
159
+ * Disconnects from the Teneo network and cleans up all active connections.
160
+ * Clears all timers, pending messages, and stops automatic reconnection attempts.
161
+ * Emits 'disconnect' event after disconnection is complete.
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * sdk.disconnect();
166
+ * console.log('Disconnected from Teneo network');
167
+ * ```
168
+ */
169
+ disconnect() {
170
+ this.logger.info("Disconnecting from Teneo network");
171
+ this.connection.disconnect();
172
+ }
173
+ /**
174
+ * Sends a message to agents via the coordinator, which intelligently selects
175
+ * the most appropriate agent based on the message content and agent capabilities.
176
+ * Can optionally wait for and return the agent's response.
177
+ *
178
+ * @param content - The message content to send to agents
179
+ * @param options - Optional message configuration
180
+ * @param options.room - Room to send message to (defaults to configured default room)
181
+ * @param options.from - Sender address (defaults to authenticated wallet address)
182
+ * @param options.waitForResponse - Whether to wait for agent response (default: false)
183
+ * @param options.timeout - Response timeout in milliseconds (default: 60000, max: 300000)
184
+ * @param options.format - Response format: 'raw', 'humanized', or 'both'
185
+ * @returns Promise that resolves to FormattedResponse if waitForResponse is true, void otherwise
186
+ * @throws {SDKError} If not connected to the network (ErrorCode.NOT_CONNECTED)
187
+ * @throws {ValidationError} If content is empty or options are invalid
188
+ * @throws {TimeoutError} If waitForResponse is true and timeout is exceeded
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * // Fire-and-forget message
193
+ * await sdk.sendMessage('What is the weather today?');
194
+ *
195
+ * // Wait for response
196
+ * const response = await sdk.sendMessage('What is 2+2?', {
197
+ * waitForResponse: true,
198
+ * timeout: 30000
199
+ * });
200
+ * console.log(response.humanized); // Agent's response in human-readable format
201
+ * ```
202
+ */
203
+ async sendMessage(content, options) {
204
+ return this.messages.sendMessage(content, options);
205
+ }
206
+ /**
207
+ * Sends a direct command to a specific agent, bypassing the coordinator.
208
+ * Use this when you know exactly which agent should handle the request.
209
+ * The command is formatted as "@agentName command" internally.
210
+ *
211
+ * @param command - The direct agent command configuration
212
+ * @param command.agent - The agent ID or name to send the command to
213
+ * @param command.command - The command text to send to the agent
214
+ * @param command.room - Room to send command to (defaults to configured default room)
215
+ * @returns Promise that resolves when the command is sent
216
+ * @throws {SDKError} If not connected to the network (ErrorCode.NOT_CONNECTED)
217
+ * @throws {ValidationError} If agent or command are empty, or room is not configured
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * // Send command to specific agent
222
+ * await sdk.sendDirectCommand({
223
+ * agent: 'weather-agent',
224
+ * command: 'Get forecast for New York',
225
+ * room: 'general'
226
+ * });
227
+ * ```
228
+ */
229
+ async sendDirectCommand(command) {
230
+ return this.messages.sendDirectCommand(command);
231
+ }
232
+ /**
233
+ * Subscribes to a specified room in the Teneo network.
234
+ * Agents in the room will be able to see and respond to your messages.
235
+ * Emits 'room:subscribed' event when successfully subscribed.
236
+ *
237
+ * @param roomId - The ID of the room to subscribe to
238
+ * @returns Promise that resolves when the room has been subscribed
239
+ * @throws {SDKError} If not connected to the network (ErrorCode.NOT_CONNECTED)
240
+ * @throws {ValidationError} If roomId is empty or invalid
241
+ *
242
+ * @example
243
+ * ```typescript
244
+ * await sdk.subscribeToRoom('general');
245
+ * console.log('Subscribed to general room');
246
+ * ```
247
+ */
248
+ async subscribeToRoom(roomId) {
249
+ return this.rooms.subscribeToRoom(roomId);
250
+ }
251
+ /**
252
+ * Unsubscribes from a specified room in the Teneo network.
253
+ * You will no longer receive messages from agents in this room.
254
+ * Emits 'room:unsubscribed' event when successfully unsubscribed.
255
+ *
256
+ * @param roomId - The ID of the room to unsubscribe from
257
+ * @returns Promise that resolves when the room has been unsubscribed
258
+ * @throws {SDKError} If not connected to the network (ErrorCode.NOT_CONNECTED)
259
+ * @throws {ValidationError} If roomId is empty or invalid
260
+ *
261
+ * @example
262
+ * ```typescript
263
+ * await sdk.unsubscribeFromRoom('general');
264
+ * console.log('Unsubscribed from general room');
265
+ * ```
266
+ */
267
+ async unsubscribeFromRoom(roomId) {
268
+ return this.rooms.unsubscribeFromRoom(roomId);
269
+ }
270
+ /**
271
+ * Lists all rooms available to the user.
272
+ * Fetches room list from the server including owned and shared rooms.
273
+ * Emits 'room:list' event when the list is received.
274
+ *
275
+ * @returns Promise that resolves to array of room information
276
+ * @throws {SDKError} If not connected to the network (ErrorCode.NOT_CONNECTED)
277
+ *
278
+ * @example
279
+ * ```typescript
280
+ * const rooms = await sdk.listRooms();
281
+ * rooms.forEach(room => {
282
+ * console.log(`${room.name} (${room.is_public ? 'public' : 'private'})`);
283
+ * console.log(`Owner: ${room.is_owner}`);
284
+ * });
285
+ * ```
286
+ */
287
+ async listRooms() {
288
+ return this.rooms.listRooms();
289
+ }
290
+ /**
291
+ * Gets all rooms currently subscribed to.
292
+ * Returns array of room IDs that you're actively listening to for messages.
293
+ *
294
+ * @returns Array of subscribed room IDs
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * const rooms = sdk.getSubscribedRooms();
299
+ * console.log(`Subscribed to ${rooms.length} rooms:`, rooms);
300
+ * // Example output: Subscribed to 3 rooms: ['general', 'support', 'trading']
301
+ * ```
302
+ */
303
+ getSubscribedRooms() {
304
+ return this.rooms.getSubscribedRooms();
305
+ }
306
+ /**
307
+ * Gets a list of all available agents in the Teneo network.
308
+ * The list is automatically updated when new agents join or leave.
309
+ * Returns a read-only array to prevent external modification.
310
+ *
311
+ * @returns Read-only array of all available agents
312
+ *
313
+ * @example
314
+ * ```typescript
315
+ * const agents = sdk.getAgents();
316
+ * console.log(`Found ${agents.length} agents:`);
317
+ * agents.forEach(agent => {
318
+ * console.log(`- ${agent.name}: ${agent.description}`);
319
+ * });
320
+ * ```
321
+ */
322
+ getAgents() {
323
+ return this.agents.getAgents();
324
+ }
325
+ /**
326
+ * Gets a specific agent by its unique ID.
327
+ * Returns undefined if no agent with the specified ID exists.
328
+ *
329
+ * @param agentId - The unique identifier of the agent to retrieve
330
+ * @returns The agent object if found, undefined otherwise
331
+ *
332
+ * @example
333
+ * ```typescript
334
+ * const agent = sdk.getAgent('weather-agent-001');
335
+ * if (agent) {
336
+ * console.log(`Found agent: ${agent.name}`);
337
+ * console.log(`Status: ${agent.status}`);
338
+ * } else {
339
+ * console.log('Agent not found');
340
+ * }
341
+ * ```
342
+ */
343
+ getAgent(agentId) {
344
+ return this.agents.getAgent(agentId);
345
+ }
346
+ /**
347
+ * Finds all agents that have a specific capability using O(1) indexed lookup (PERF-3).
348
+ * Much faster than filtering through all agents manually.
349
+ * Uses capability index for constant-time lookups regardless of agent count.
350
+ *
351
+ * @param capability - The capability name to search for (case-insensitive)
352
+ * @returns Read-only array of agents with the specified capability
353
+ * @throws {ValidationError} If capability name is invalid
354
+ *
355
+ * @example
356
+ * ```typescript
357
+ * // Find all weather-capable agents
358
+ * const weatherAgents = sdk.findAgentsByCapability('weather-forecast');
359
+ * console.log(`Found ${weatherAgents.length} weather agents`);
360
+ *
361
+ * weatherAgents.forEach(agent => {
362
+ * console.log(`- ${agent.name}: ${agent.description}`);
363
+ * });
364
+ * ```
365
+ */
366
+ findAgentsByCapability(capability) {
367
+ return this.agents.findByCapability(capability);
368
+ }
369
+ /**
370
+ * Finds agents by name using O(k) token-based search (PERF-3).
371
+ * Supports partial matching - searches for tokens within agent names.
372
+ * Tokenizes both the search query and agent names for flexible matching.
373
+ *
374
+ * @param name - Name or partial name to search for (case-insensitive)
375
+ * @returns Read-only array of agents matching the search
376
+ * @throws {ValidationError} If name is invalid
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * // Find all agents with "weather" in their name
381
+ * const agents = sdk.findAgentsByName('weather');
382
+ * // Matches: "Weather Agent", "Weather Forecast Bot", "Advanced Weather API", etc.
383
+ *
384
+ * console.log(`Found ${agents.length} agents matching 'weather'`);
385
+ * ```
386
+ */
387
+ findAgentsByName(name) {
388
+ return this.agents.findByName(name);
389
+ }
390
+ /**
391
+ * Finds all agents with a specific status using O(1) indexed lookup (PERF-3).
392
+ * Uses status index for constant-time lookups regardless of agent count.
393
+ *
394
+ * @param status - Agent status: 'online' or 'offline' (case-insensitive)
395
+ * @returns Read-only array of agents with the specified status
396
+ * @throws {ValidationError} If status is invalid
397
+ *
398
+ * @example
399
+ * ```typescript
400
+ * // Get all online agents
401
+ * const onlineAgents = sdk.findAgentsByStatus('online');
402
+ * console.log(`${onlineAgents.length} agents are currently online`);
403
+ *
404
+ * // Get offline agents
405
+ * const offlineAgents = sdk.findAgentsByStatus('offline');
406
+ * ```
407
+ */
408
+ findAgentsByStatus(status) {
409
+ return this.agents.findByStatus(status);
410
+ }
411
+ /**
412
+ * Gets a list of all available rooms in the Teneo network.
413
+ * Includes rooms you have access to based on your authentication.
414
+ * Returns a read-only array to prevent external modification.
415
+ *
416
+ * @returns Read-only array of all available rooms
417
+ *
418
+ * @example
419
+ * ```typescript
420
+ * const rooms = sdk.getRooms();
421
+ * console.log(`Available rooms: ${rooms.length}`);
422
+ * rooms.forEach(room => {
423
+ * console.log(`- ${room.id} (${room.name})`);
424
+ * });
425
+ * ```
426
+ */
427
+ getRooms() {
428
+ return this.rooms.getRooms();
429
+ }
430
+ /**
431
+ * Gets a specific room by its unique ID.
432
+ * Returns undefined if no room with the specified ID exists or if you don't have access.
433
+ *
434
+ * @param roomId - The unique identifier of the room to retrieve
435
+ * @returns The room object if found, undefined otherwise
436
+ *
437
+ * @example
438
+ * ```typescript
439
+ * const room = sdk.getRoom('general');
440
+ * if (room) {
441
+ * console.log(`Found room: ${room.name}`);
442
+ * console.log(`Members: ${room.members?.length ?? 0}`);
443
+ * } else {
444
+ * console.log('Room not found or no access');
445
+ * }
446
+ * ```
447
+ */
448
+ getRoom(roomId) {
449
+ return this.rooms.getRoom(roomId);
450
+ }
451
+ /**
452
+ * Configures webhook URL and headers for receiving real-time event notifications.
453
+ * Webhooks allow you to receive events at your server endpoint via HTTP POST requests.
454
+ * Events include messages, agent responses, errors, and connection state changes.
455
+ *
456
+ * @param url - The webhook URL endpoint to receive events (must be HTTPS unless localhost)
457
+ * @param headers - Optional custom HTTP headers to include with webhook requests
458
+ * @throws {WebhookError} If URL is invalid or insecure (non-HTTPS and not localhost)
459
+ *
460
+ * @example
461
+ * ```typescript
462
+ * sdk.configureWebhook('https://api.example.com/webhooks/teneo', {
463
+ * 'Authorization': 'Bearer your-token',
464
+ * 'X-Custom-Header': 'value'
465
+ * });
466
+ *
467
+ * // Listen for webhook events
468
+ * sdk.on('webhook:sent', (payload, url) => {
469
+ * console.log('Webhook sent:', payload.event);
470
+ * });
471
+ * ```
472
+ */
473
+ configureWebhook(url, headers) {
474
+ this.webhookHandler.configure({
475
+ url,
476
+ headers,
477
+ retries: this.config.webhookRetries,
478
+ timeout: this.config.webhookTimeout
479
+ });
480
+ }
481
+ /**
482
+ * Gets the current WebSocket connection state including connection status,
483
+ * authentication status, reconnection attempts, and timestamps.
484
+ *
485
+ * @returns Object containing detailed connection state information
486
+ * @returns {boolean} returns.connected - Whether WebSocket is currently connected
487
+ * @returns {boolean} returns.authenticated - Whether authentication is complete
488
+ * @returns {boolean} returns.reconnecting - Whether currently attempting to reconnect
489
+ * @returns {number} returns.reconnectAttempts - Number of reconnection attempts made
490
+ * @returns {Date} returns.lastConnectedAt - Timestamp of last successful connection
491
+ * @returns {Date} returns.lastDisconnectedAt - Timestamp of last disconnection
492
+ * @returns {Error} returns.lastError - Last error that occurred
493
+ *
494
+ * @example
495
+ * ```typescript
496
+ * const state = sdk.getConnectionState();
497
+ * console.log(`Connected: ${state.connected}`);
498
+ * console.log(`Authenticated: ${state.authenticated}`);
499
+ * if (state.reconnecting) {
500
+ * console.log(`Reconnection attempts: ${state.reconnectAttempts}`);
501
+ * }
502
+ * ```
503
+ */
504
+ getConnectionState() {
505
+ return this.connection.getConnectionState();
506
+ }
507
+ /**
508
+ * Gets the current authentication state including wallet address, rooms, and permissions.
509
+ * Updated after successful authentication and includes user profile information.
510
+ *
511
+ * @returns Object containing detailed authentication state information
512
+ * @returns {boolean} returns.authenticated - Whether authentication is complete
513
+ * @returns {string} returns.walletAddress - Authenticated wallet address
514
+ * @returns {string} returns.challenge - Authentication challenge string
515
+ * @returns {string[]} returns.rooms - Array of room IDs the user has access to
516
+ * @returns {Room[]} returns.roomObjects - Full room objects with details
517
+ *
518
+ * @example
519
+ * ```typescript
520
+ * const authState = sdk.getAuthState();
521
+ * if (authState.authenticated) {
522
+ * console.log(`Authenticated as: ${authState.walletAddress}`);
523
+ * console.log(`Access to ${authState.rooms?.length ?? 0} rooms`);
524
+ * } else {
525
+ * console.log('Not authenticated');
526
+ * }
527
+ * ```
528
+ */
529
+ getAuthState() {
530
+ return this.connection.getAuthState();
531
+ }
532
+ /**
533
+ * Quick check for whether the WebSocket connection is currently active.
534
+ * This is a convenience getter that returns only the connection status.
535
+ * For detailed state information, use getConnectionState().
536
+ *
537
+ * @returns True if connected to the Teneo network, false otherwise
538
+ *
539
+ * @example
540
+ * ```typescript
541
+ * if (sdk.isConnected) {
542
+ * await sdk.sendMessage('Hello!');
543
+ * } else {
544
+ * console.log('Not connected');
545
+ * await sdk.connect();
546
+ * }
547
+ * ```
548
+ */
549
+ get isConnected() {
550
+ return this.connection.isConnected;
551
+ }
552
+ /**
553
+ * Quick check for whether authentication is complete.
554
+ * This is a convenience getter that returns only the authentication status.
555
+ * For detailed auth information, use getAuthState().
556
+ *
557
+ * @returns True if authenticated with the Teneo network, false otherwise
558
+ *
559
+ * @example
560
+ * ```typescript
561
+ * if (sdk.isAuthenticated) {
562
+ * console.log('Ready to send messages');
563
+ * } else {
564
+ * console.log('Waiting for authentication...');
565
+ * }
566
+ * ```
567
+ */
568
+ get isAuthenticated() {
569
+ return this.connection.isAuthenticated;
570
+ }
571
+ /**
572
+ * Configures how agent responses are formatted when received.
573
+ * Supports raw JSON, humanized text, or both formats simultaneously.
574
+ * Also controls metadata inclusion and pretty-printing options.
575
+ *
576
+ * @param options - Response formatting configuration options
577
+ * @param options.format - Format type: 'raw' (JSON), 'humanized' (text), or 'both'
578
+ * @param options.includeMetadata - Whether to include metadata in responses (timestamps, agent info, etc.)
579
+ * @param options.includeTimestamps - Whether to include timestamps in formatted output
580
+ * @param options.prettyPrint - Whether to pretty-print JSON output
581
+ *
582
+ * @example
583
+ * ```typescript
584
+ * // Get both raw JSON and humanized text
585
+ * sdk.setResponseFormat({
586
+ * format: 'both',
587
+ * includeMetadata: true
588
+ * });
589
+ *
590
+ * const response = await sdk.sendMessage('Hello', { waitForResponse: true });
591
+ * console.log(response.humanized); // Human-readable text
592
+ * console.log(response.raw); // Original JSON
593
+ * console.log(response.metadata); // Timestamp, agent info, etc.
594
+ * ```
595
+ */
596
+ setResponseFormat(options) {
597
+ // Update formatter with new options
598
+ this.responseFormatter.setFormatOptions(options);
599
+ // Update config if format is specified
600
+ if (options.format !== undefined) {
601
+ this.config.responseFormat = options.format;
602
+ }
603
+ if (options.includeMetadata !== undefined) {
604
+ this.config.includeMetadata = options.includeMetadata;
605
+ }
606
+ }
607
+ /**
608
+ * Gets the current status of the webhook system including configuration,
609
+ * queue status, and pending/failed webhook deliveries.
610
+ *
611
+ * @returns Object containing webhook status information
612
+ * @returns {boolean} returns.configured - Whether a webhook URL is configured
613
+ * @returns {WebhookConfig} returns.config - Current webhook configuration (URL, headers, retries, etc.)
614
+ * @returns {Object} returns.queue - Webhook delivery queue status
615
+ * @returns {number} returns.queue.pending - Number of webhooks pending delivery
616
+ * @returns {boolean} returns.queue.processing - Whether webhooks are currently being processed
617
+ * @returns {number} returns.queue.failed - Number of failed webhook deliveries in queue
618
+ *
619
+ * @example
620
+ * ```typescript
621
+ * const status = sdk.getWebhookStatus();
622
+ * if (status.configured) {
623
+ * console.log(`Webhook URL: ${status.config.url}`);
624
+ * console.log(`Pending: ${status.queue.pending}`);
625
+ * console.log(`Failed: ${status.queue.failed}`);
626
+ * } else {
627
+ * console.log('Webhook not configured');
628
+ * }
629
+ * ```
630
+ */
631
+ getWebhookStatus() {
632
+ return {
633
+ configured: this.webhookHandler.isConfigured,
634
+ config: this.webhookHandler.getConfig(),
635
+ queue: this.webhookHandler.getQueueStatus()
636
+ };
637
+ }
638
+ /**
639
+ * Retries all failed webhook deliveries in the queue.
640
+ * Resets attempt counters and immediately attempts to deliver all failed webhooks.
641
+ * Useful for recovering from temporary network issues or webhook endpoint downtime.
642
+ *
643
+ * @example
644
+ * ```typescript
645
+ * const status = sdk.getWebhookStatus();
646
+ * if (status.queue.failed > 0) {
647
+ * console.log(`Retrying ${status.queue.failed} failed webhooks...`);
648
+ * sdk.retryFailedWebhooks();
649
+ * }
650
+ * ```
651
+ */
652
+ retryFailedWebhooks() {
653
+ this.webhookHandler.retryFailed();
654
+ }
655
+ /**
656
+ * Clears all pending and failed webhooks from the delivery queue.
657
+ * Use this to discard webhooks that are no longer relevant or to recover from queue issues.
658
+ * Warning: This will permanently discard all queued webhook events.
659
+ *
660
+ * @example
661
+ * ```typescript
662
+ * // Clear stale webhooks after reconfiguration
663
+ * sdk.clearWebhookQueue();
664
+ * sdk.configureWebhook('https://api.example.com/new-endpoint');
665
+ * console.log('Webhook queue cleared and reconfigured');
666
+ * ```
667
+ */
668
+ clearWebhookQueue() {
669
+ this.webhookHandler.clearQueue();
670
+ }
671
+ /**
672
+ * Gets comprehensive health status of all SDK components.
673
+ * Useful for monitoring, debugging, and operational dashboards.
674
+ * Returns status of connection, webhooks, rate limiting, agents, and rooms.
675
+ *
676
+ * Overall health status calculation:
677
+ * - healthy: All components operational
678
+ * - degraded: Some components have issues but SDK is functional (e.g., webhook failures, circuit open)
679
+ * - unhealthy: Critical components are not operational (e.g., disconnected, authentication failed)
680
+ *
681
+ * @returns Complete health status object with all component states
682
+ * @returns {string} returns.status - Overall health: 'healthy', 'degraded', or 'unhealthy'
683
+ * @returns {string} returns.timestamp - ISO timestamp of health check
684
+ * @returns {Object} returns.connection - WebSocket connection health
685
+ * @returns {Object} returns.webhook - Webhook delivery health including circuit breaker state
686
+ * @returns {Object} returns.rateLimit - Rate limiter status (if configured)
687
+ * @returns {Object} returns.agents - Agent registry health
688
+ * @returns {Object} returns.rooms - Room management health
689
+ *
690
+ * @example
691
+ * ```typescript
692
+ * const health = sdk.getHealth();
693
+ * console.log(`SDK Status: ${health.status}`);
694
+ * console.log(`Connected: ${health.connection.status}`);
695
+ * console.log(`Agents: ${health.agents.count}`);
696
+ * console.log(`Webhook Circuit: ${health.webhook.circuitState}`);
697
+ *
698
+ * if (health.status !== 'healthy') {
699
+ * console.warn('SDK is degraded or unhealthy');
700
+ * if (!health.connection.authenticated) {
701
+ * console.log('Authentication issue');
702
+ * }
703
+ * if (health.webhook.failed > 0) {
704
+ * console.log(`${health.webhook.failed} failed webhooks`);
705
+ * }
706
+ * }
707
+ * ```
708
+ */
709
+ getHealth() {
710
+ const connectionState = this.connection.getConnectionState();
711
+ const webhookStatus = this.getWebhookStatus();
712
+ const rateLimitStatus = this.wsClient.getRateLimiterStatus();
713
+ // Determine connection status
714
+ let connectionStatus;
715
+ if (connectionState.reconnecting) {
716
+ connectionStatus = "reconnecting";
717
+ }
718
+ else if (connectionState.connected) {
719
+ connectionStatus = "connected";
720
+ }
721
+ else {
722
+ connectionStatus = "disconnected";
723
+ }
724
+ // Determine webhook health
725
+ let webhookHealth = "healthy";
726
+ if (!webhookStatus.configured) {
727
+ // Webhook not configured is not unhealthy
728
+ webhookHealth = "healthy";
729
+ }
730
+ else if (webhookStatus.queue.circuitState === "OPEN") {
731
+ webhookHealth = "unhealthy";
732
+ }
733
+ else if (webhookStatus.queue.failed > 0 || webhookStatus.queue.circuitState === "HALF_OPEN") {
734
+ webhookHealth = "degraded";
735
+ }
736
+ // Determine overall health
737
+ let overallStatus;
738
+ if (!connectionState.connected && !connectionState.reconnecting) {
739
+ overallStatus = "unhealthy";
740
+ }
741
+ else if (!connectionState.authenticated && connectionState.reconnecting) {
742
+ overallStatus = "degraded";
743
+ }
744
+ else if (webhookHealth === "unhealthy") {
745
+ overallStatus = "degraded";
746
+ }
747
+ else if (webhookHealth === "degraded") {
748
+ overallStatus = "degraded";
749
+ }
750
+ else {
751
+ overallStatus = "healthy";
752
+ }
753
+ return {
754
+ status: overallStatus,
755
+ timestamp: new Date().toISOString(),
756
+ connection: {
757
+ status: connectionStatus,
758
+ authenticated: connectionState.authenticated,
759
+ reconnectAttempts: connectionState.reconnectAttempts
760
+ },
761
+ webhook: {
762
+ configured: webhookStatus.configured,
763
+ status: webhookHealth,
764
+ pending: webhookStatus.queue.pending,
765
+ failed: webhookStatus.queue.failed,
766
+ circuitState: webhookStatus.queue.circuitState
767
+ },
768
+ rateLimit: rateLimitStatus,
769
+ agents: {
770
+ count: this.agents.getAgents().length
771
+ },
772
+ rooms: {
773
+ count: this.rooms.getRooms().length,
774
+ subscribedRooms: this.rooms.getSubscribedRooms()
775
+ }
776
+ };
777
+ }
778
+ /**
779
+ * Destroys the SDK instance and cleans up all resources.
780
+ * Disconnects from the network, clears all managers, removes event listeners,
781
+ * and marks the SDK as destroyed. After calling destroy(), the SDK instance
782
+ * cannot be reused - create a new instance instead.
783
+ * Emits 'destroy' event before completion.
784
+ *
785
+ * @example
786
+ * ```typescript
787
+ * // Clean up when shutting down
788
+ * sdk.destroy();
789
+ * console.log('SDK destroyed and resources cleaned up');
790
+ *
791
+ * // Create new instance if needed
792
+ * const newSdk = new TeneoSDK(config);
793
+ * ```
794
+ */
795
+ destroy() {
796
+ if (this.isDestroyed)
797
+ return;
798
+ this.logger.info("Destroying TeneoSDK");
799
+ this.isDestroyed = true;
800
+ // Destroy managers
801
+ this.connection.destroy();
802
+ this.rooms.destroy();
803
+ this.agents.destroy();
804
+ this.messages.destroy();
805
+ // Destroy other components
806
+ this.webhookHandler.destroy();
807
+ this.removeAllListeners();
808
+ this.emit("destroy");
809
+ }
810
+ /**
811
+ * Set up event forwarding from managers
812
+ */
813
+ setupEventForwarding() {
814
+ // Forward connection events from ConnectionManager
815
+ this.connection.on("connection:open", () => this.emit("connection:open"));
816
+ this.connection.on("connection:close", (code, reason) => this.emit("connection:close", code, reason));
817
+ this.connection.on("connection:error", (error) => this.emit("connection:error", error));
818
+ this.connection.on("connection:reconnecting", (attempt) => this.emit("connection:reconnecting", attempt));
819
+ this.connection.on("connection:reconnected", () => this.emit("connection:reconnected"));
820
+ this.connection.on("connection:state", (state) => this.emit("connection:state", state));
821
+ // Forward auth events from ConnectionManager
822
+ this.connection.on("auth:challenge", (challenge) => this.emit("auth:challenge", challenge));
823
+ this.connection.on("auth:success", (state) => {
824
+ this.logger.debug("Received auth:success event in SDK", {
825
+ authenticated: state?.authenticated,
826
+ hasRooms: !!state?.roomObjects
827
+ });
828
+ // Update rooms from auth state
829
+ if (state.roomObjects) {
830
+ this.rooms.updateRoomsFromAuth(state.roomObjects);
831
+ }
832
+ this.emit("auth:success", state);
833
+ });
834
+ this.connection.on("auth:error", (error) => this.emit("auth:error", error));
835
+ this.connection.on("auth:state", (state) => this.emit("auth:state", state));
836
+ // Forward message events from MessageRouter
837
+ this.messages.on("message:sent", (message) => this.emit("message:sent", message));
838
+ this.messages.on("message:received", (message) => this.emit("message:received", message));
839
+ this.messages.on("message:error", (error, message) => this.emit("message:error", error, message));
840
+ // Forward agent events from MessageRouter
841
+ this.messages.on("agent:selected", (data) => this.emit("agent:selected", data));
842
+ this.messages.on("agent:response", (response) => this.emit("agent:response", response));
843
+ // Forward coordinator events from MessageRouter
844
+ this.messages.on("coordinator:processing", (request) => this.emit("coordinator:processing", request));
845
+ this.messages.on("coordinator:selected", (agentId, reasoning) => this.emit("coordinator:selected", agentId, reasoning));
846
+ this.messages.on("coordinator:error", (error) => this.emit("coordinator:error", error));
847
+ // Handle agent list updates from WebSocketClient
848
+ this.wsClient.on("agent:list", (agents) => {
849
+ this.agents.updateAgents(agents);
850
+ });
851
+ // Forward room events from WebSocketClient (emitted by handlers)
852
+ this.wsClient.on("room:subscribed", (data) => this.emit("room:subscribed", data));
853
+ this.wsClient.on("room:unsubscribed", (data) => this.emit("room:unsubscribed", data));
854
+ // Forward room events from RoomManager (if any direct emissions are added later)
855
+ this.rooms.on("room:subscribed", (data) => this.emit("room:subscribed", data));
856
+ this.rooms.on("room:unsubscribed", (data) => this.emit("room:unsubscribed", data));
857
+ // Forward webhook events from WebhookHandler
858
+ this.webhookHandler.on("webhook:sent", (payload, url) => this.emit("webhook:sent", payload, url));
859
+ this.webhookHandler.on("webhook:success", (response, url) => this.emit("webhook:success", response, url));
860
+ this.webhookHandler.on("webhook:error", (error, url) => this.emit("webhook:error", error, url));
861
+ this.webhookHandler.on("webhook:retry", (attempt, url) => this.emit("webhook:retry", attempt, url));
862
+ // Forward error events from ConnectionManager
863
+ this.connection.on("error", (error) => {
864
+ this.emit("error", error);
865
+ // Fire and forget - don't block event emission
866
+ this.webhookHandler
867
+ .sendWebhook("error", error, { code: error.code })
868
+ .catch((webhookError) => {
869
+ this.logger.error("Failed to send webhook for error event", webhookError);
870
+ });
871
+ });
872
+ // Forward lifecycle events from ConnectionManager
873
+ this.connection.on("ready", () => this.emit("ready"));
874
+ this.connection.on("disconnect", () => this.emit("disconnect"));
875
+ }
876
+ /**
877
+ * Create default logger using pino
878
+ */
879
+ createDefaultLogger() {
880
+ return (0, logger_1.createPinoLogger)(this.config.logLevel ?? "info", "TeneoSDK");
881
+ }
882
+ /**
883
+ * Creates a new SDK configuration builder for fluent configuration.
884
+ * The builder pattern provides a more intuitive way to configure the SDK
885
+ * with method chaining and validation at each step.
886
+ *
887
+ * @returns A new SDKConfigBuilder instance for fluent configuration
888
+ *
889
+ * @example
890
+ * ```typescript
891
+ * const sdk = TeneoSDK.builder()
892
+ * .wsUrl('wss://teneo.example.com')
893
+ * .privateKey('0x...')
894
+ * .withAutoJoinRooms(['general'])
895
+ * .logLevel('debug')
896
+ * .webhookUrl('https://api.example.com/webhooks')
897
+ * .build();
898
+ *
899
+ * await sdk.connect();
900
+ * ```
901
+ */
902
+ static builder() {
903
+ return new types_1.SDKConfigBuilder();
904
+ }
905
+ }
906
+ exports.TeneoSDK = TeneoSDK;
907
+ //# sourceMappingURL=teneo-sdk.js.map