@teneo-protocol/sdk 2.0.0 → 2.2.1

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 (329) hide show
  1. package/.eslintrc.json +11 -2
  2. package/.github/CODEOWNERS +2 -0
  3. package/.github/ISSUE_TEMPLATE/01-bug.yml +85 -0
  4. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
  6. package/.github/workflows/claude-code-review.yml +8 -3
  7. package/.github/workflows/claude-reviewer.yml +6 -4
  8. package/.github/workflows/publish-npm.yml +1 -0
  9. package/.github/workflows/push-to-main.yml +1 -1
  10. package/.github/workflows/top-issue.yml +102 -0
  11. package/CHANGELOG.md +69 -0
  12. package/CONCEPTS.md +747 -0
  13. package/README.md +178 -8
  14. package/dist/constants.js +8 -8
  15. package/dist/constants.js.map +1 -1
  16. package/dist/core/websocket-client.d.ts +15 -3
  17. package/dist/core/websocket-client.d.ts.map +1 -1
  18. package/dist/core/websocket-client.js +52 -13
  19. package/dist/core/websocket-client.js.map +1 -1
  20. package/dist/formatters/response-formatter.js +4 -0
  21. package/dist/formatters/response-formatter.js.map +1 -1
  22. package/dist/handlers/message-handler-registry.js +2 -1
  23. package/dist/handlers/message-handler-registry.js.map +1 -1
  24. package/dist/handlers/message-handlers/agent-details-response-handler.d.ts +1666 -0
  25. package/dist/handlers/message-handlers/agent-details-response-handler.d.ts.map +1 -0
  26. package/dist/handlers/message-handlers/agent-details-response-handler.js +38 -0
  27. package/dist/handlers/message-handlers/agent-details-response-handler.js.map +1 -0
  28. package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts.map +1 -1
  29. package/dist/handlers/message-handlers/agent-room-operation-response-handler.js +2 -5
  30. package/dist/handlers/message-handlers/agent-room-operation-response-handler.js.map +1 -1
  31. package/dist/handlers/message-handlers/agent-selected-handler.js +2 -5
  32. package/dist/handlers/message-handlers/agent-selected-handler.js.map +1 -1
  33. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts +783 -0
  34. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts.map +1 -1
  35. package/dist/handlers/message-handlers/agent-status-update-handler.js +2 -5
  36. package/dist/handlers/message-handlers/agent-status-update-handler.js.map +1 -1
  37. package/dist/handlers/message-handlers/agents-list-handler.js +2 -5
  38. package/dist/handlers/message-handlers/agents-list-handler.js.map +1 -1
  39. package/dist/handlers/message-handlers/all-agents-response-handler.d.ts +439 -0
  40. package/dist/handlers/message-handlers/all-agents-response-handler.d.ts.map +1 -0
  41. package/dist/handlers/message-handlers/all-agents-response-handler.js +36 -0
  42. package/dist/handlers/message-handlers/all-agents-response-handler.js.map +1 -0
  43. package/dist/handlers/message-handlers/auth-error-handler.js +2 -5
  44. package/dist/handlers/message-handlers/auth-error-handler.js.map +1 -1
  45. package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -1
  46. package/dist/handlers/message-handlers/auth-message-handler.js +6 -5
  47. package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -1
  48. package/dist/handlers/message-handlers/auth-required-handler.js +2 -5
  49. package/dist/handlers/message-handlers/auth-required-handler.js.map +1 -1
  50. package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -1
  51. package/dist/handlers/message-handlers/auth-success-handler.js +6 -5
  52. package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -1
  53. package/dist/handlers/message-handlers/base-handler.d.ts +4 -4
  54. package/dist/handlers/message-handlers/base-handler.d.ts.map +1 -1
  55. package/dist/handlers/message-handlers/base-handler.js +3 -1
  56. package/dist/handlers/message-handlers/base-handler.js.map +1 -1
  57. package/dist/handlers/message-handlers/challenge-handler.js +3 -2
  58. package/dist/handlers/message-handlers/challenge-handler.js.map +1 -1
  59. package/dist/handlers/message-handlers/error-message-handler.js +2 -5
  60. package/dist/handlers/message-handlers/error-message-handler.js.map +1 -1
  61. package/dist/handlers/message-handlers/index.d.ts +6 -0
  62. package/dist/handlers/message-handlers/index.d.ts.map +1 -1
  63. package/dist/handlers/message-handlers/index.js +33 -1
  64. package/dist/handlers/message-handlers/index.js.map +1 -1
  65. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts +783 -0
  66. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts.map +1 -1
  67. package/dist/handlers/message-handlers/list-available-agents-handler.js +2 -5
  68. package/dist/handlers/message-handlers/list-available-agents-handler.js.map +1 -1
  69. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts +783 -0
  70. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts.map +1 -1
  71. package/dist/handlers/message-handlers/list-room-agents-handler.js +2 -5
  72. package/dist/handlers/message-handlers/list-room-agents-handler.js.map +1 -1
  73. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts +4 -201
  74. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -1
  75. package/dist/handlers/message-handlers/list-rooms-response-handler.js +5 -7
  76. package/dist/handlers/message-handlers/list-rooms-response-handler.js.map +1 -1
  77. package/dist/handlers/message-handlers/ping-pong-handler.js +4 -10
  78. package/dist/handlers/message-handlers/ping-pong-handler.js.map +1 -1
  79. package/dist/handlers/message-handlers/rate-limit-notification-handler.d.ts +94 -0
  80. package/dist/handlers/message-handlers/rate-limit-notification-handler.d.ts.map +1 -0
  81. package/dist/handlers/message-handlers/rate-limit-notification-handler.js +35 -0
  82. package/dist/handlers/message-handlers/rate-limit-notification-handler.js.map +1 -0
  83. package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -1
  84. package/dist/handlers/message-handlers/regular-message-handler.js +4 -6
  85. package/dist/handlers/message-handlers/regular-message-handler.js.map +1 -1
  86. package/dist/handlers/message-handlers/room-operation-response-handler.d.ts.map +1 -1
  87. package/dist/handlers/message-handlers/room-operation-response-handler.js +2 -5
  88. package/dist/handlers/message-handlers/room-operation-response-handler.js.map +1 -1
  89. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
  90. package/dist/handlers/message-handlers/subscribe-response-handler.js +4 -6
  91. package/dist/handlers/message-handlers/subscribe-response-handler.js.map +1 -1
  92. package/dist/handlers/message-handlers/task-quote-handler.d.ts +14 -0
  93. package/dist/handlers/message-handlers/task-quote-handler.d.ts.map +1 -0
  94. package/dist/handlers/message-handlers/task-quote-handler.js +29 -0
  95. package/dist/handlers/message-handlers/task-quote-handler.js.map +1 -0
  96. package/dist/handlers/message-handlers/task-response-handler.js +2 -5
  97. package/dist/handlers/message-handlers/task-response-handler.js.map +1 -1
  98. package/dist/handlers/message-handlers/types.d.ts +21 -9
  99. package/dist/handlers/message-handlers/types.d.ts.map +1 -1
  100. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
  101. package/dist/handlers/message-handlers/unsubscribe-response-handler.js +4 -6
  102. package/dist/handlers/message-handlers/unsubscribe-response-handler.js.map +1 -1
  103. package/dist/handlers/message-handlers/user-authenticated-handler.d.ts +40 -0
  104. package/dist/handlers/message-handlers/user-authenticated-handler.d.ts.map +1 -0
  105. package/dist/handlers/message-handlers/user-authenticated-handler.js +28 -0
  106. package/dist/handlers/message-handlers/user-authenticated-handler.js.map +1 -0
  107. package/dist/handlers/message-handlers/user-count-handler.d.ts +49 -0
  108. package/dist/handlers/message-handlers/user-count-handler.d.ts.map +1 -0
  109. package/dist/handlers/message-handlers/user-count-handler.js +31 -0
  110. package/dist/handlers/message-handlers/user-count-handler.js.map +1 -0
  111. package/dist/handlers/webhook-handler.d.ts +1 -1
  112. package/dist/handlers/webhook-handler.d.ts.map +1 -1
  113. package/dist/handlers/webhook-handler.js +14 -5
  114. package/dist/handlers/webhook-handler.js.map +1 -1
  115. package/dist/index.d.ts +7 -2
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.js +20 -3
  118. package/dist/index.js.map +1 -1
  119. package/dist/managers/admin-manager.d.ts +116 -0
  120. package/dist/managers/admin-manager.d.ts.map +1 -0
  121. package/dist/managers/admin-manager.js +169 -0
  122. package/dist/managers/admin-manager.js.map +1 -0
  123. package/dist/managers/agent-registry.d.ts +52 -1
  124. package/dist/managers/agent-registry.d.ts.map +1 -1
  125. package/dist/managers/agent-registry.js +145 -6
  126. package/dist/managers/agent-registry.js.map +1 -1
  127. package/dist/managers/agent-room-manager.d.ts +1 -7
  128. package/dist/managers/agent-room-manager.d.ts.map +1 -1
  129. package/dist/managers/agent-room-manager.js +83 -36
  130. package/dist/managers/agent-room-manager.js.map +1 -1
  131. package/dist/managers/connection-manager.js +2 -0
  132. package/dist/managers/connection-manager.js.map +1 -1
  133. package/dist/managers/index.d.ts +2 -1
  134. package/dist/managers/index.d.ts.map +1 -1
  135. package/dist/managers/index.js +3 -1
  136. package/dist/managers/index.js.map +1 -1
  137. package/dist/managers/message-router.d.ts +56 -5
  138. package/dist/managers/message-router.d.ts.map +1 -1
  139. package/dist/managers/message-router.js +155 -8
  140. package/dist/managers/message-router.js.map +1 -1
  141. package/dist/managers/room-management-manager.d.ts.map +1 -1
  142. package/dist/managers/room-management-manager.js +9 -7
  143. package/dist/managers/room-management-manager.js.map +1 -1
  144. package/dist/managers/room-manager.d.ts +7 -5
  145. package/dist/managers/room-manager.d.ts.map +1 -1
  146. package/dist/managers/room-manager.js +14 -10
  147. package/dist/managers/room-manager.js.map +1 -1
  148. package/dist/payments/index.d.ts +5 -0
  149. package/dist/payments/index.d.ts.map +1 -0
  150. package/dist/payments/index.js +21 -0
  151. package/dist/payments/index.js.map +1 -0
  152. package/dist/payments/payment-client.d.ts +74 -0
  153. package/dist/payments/payment-client.d.ts.map +1 -0
  154. package/dist/payments/payment-client.js +207 -0
  155. package/dist/payments/payment-client.js.map +1 -0
  156. package/dist/teneo-sdk.d.ts +135 -21
  157. package/dist/teneo-sdk.d.ts.map +1 -1
  158. package/dist/teneo-sdk.js +268 -26
  159. package/dist/teneo-sdk.js.map +1 -1
  160. package/dist/types/categories.d.ts +22 -0
  161. package/dist/types/categories.d.ts.map +1 -0
  162. package/dist/types/categories.js +40 -0
  163. package/dist/types/categories.js.map +1 -0
  164. package/dist/types/config.d.ts +79 -8
  165. package/dist/types/config.d.ts.map +1 -1
  166. package/dist/types/config.js +62 -5
  167. package/dist/types/config.js.map +1 -1
  168. package/dist/types/error-codes.d.ts +8 -0
  169. package/dist/types/error-codes.d.ts.map +1 -1
  170. package/dist/types/error-codes.js +9 -0
  171. package/dist/types/error-codes.js.map +1 -1
  172. package/dist/types/events.d.ts +44 -0
  173. package/dist/types/events.d.ts.map +1 -1
  174. package/dist/types/events.js +19 -1
  175. package/dist/types/events.js.map +1 -1
  176. package/dist/types/index.d.ts +3 -2
  177. package/dist/types/index.d.ts.map +1 -1
  178. package/dist/types/index.js +33 -3
  179. package/dist/types/index.js.map +1 -1
  180. package/dist/types/messages.d.ts +11203 -407
  181. package/dist/types/messages.d.ts.map +1 -1
  182. package/dist/types/messages.js +251 -8
  183. package/dist/types/messages.js.map +1 -1
  184. package/dist/utils/bounded-queue.d.ts.map +1 -1
  185. package/dist/utils/bounded-queue.js +5 -2
  186. package/dist/utils/bounded-queue.js.map +1 -1
  187. package/dist/utils/circuit-breaker.js +11 -4
  188. package/dist/utils/circuit-breaker.js.map +1 -1
  189. package/dist/utils/deduplication-cache.js +3 -1
  190. package/dist/utils/deduplication-cache.js.map +1 -1
  191. package/dist/utils/event-waiter.d.ts +3 -3
  192. package/dist/utils/event-waiter.d.ts.map +1 -1
  193. package/dist/utils/index.d.ts +1 -0
  194. package/dist/utils/index.d.ts.map +1 -1
  195. package/dist/utils/index.js +4 -1
  196. package/dist/utils/index.js.map +1 -1
  197. package/dist/utils/logger.js.map +1 -1
  198. package/dist/utils/pricing-resolver.d.ts +26 -0
  199. package/dist/utils/pricing-resolver.d.ts.map +1 -0
  200. package/dist/utils/pricing-resolver.js +85 -0
  201. package/dist/utils/pricing-resolver.js.map +1 -0
  202. package/dist/utils/rate-limiter.d.ts.map +1 -1
  203. package/dist/utils/rate-limiter.js +6 -0
  204. package/dist/utils/rate-limiter.js.map +1 -1
  205. package/dist/utils/retry-policy.js +1 -0
  206. package/dist/utils/retry-policy.js.map +1 -1
  207. package/dist/utils/secure-private-key.js +3 -1
  208. package/dist/utils/secure-private-key.js.map +1 -1
  209. package/dist/utils/signature-verifier.d.ts.map +1 -1
  210. package/dist/utils/signature-verifier.js +3 -1
  211. package/dist/utils/signature-verifier.js.map +1 -1
  212. package/examples/.env.example +1 -1
  213. package/examples/agent-room-management-example.ts +10 -9
  214. package/examples/basic-usage.ts +3 -4
  215. package/examples/claude-agent-x-follower/.env.example +1 -1
  216. package/examples/claude-agent-x-follower/QUICKSTART.md +2 -2
  217. package/examples/claude-agent-x-follower/README.md +2 -2
  218. package/examples/claude-agent-x-follower/index.ts +120 -96
  219. package/examples/n8n-teneo/.env.example +1 -1
  220. package/examples/n8n-teneo/README.md +1 -1
  221. package/examples/n8n-teneo/index.ts +54 -44
  222. package/examples/nestjs-dashboard/.env.example +11 -0
  223. package/examples/nestjs-dashboard/README.md +297 -0
  224. package/examples/nestjs-dashboard/nest-cli.json +10 -0
  225. package/examples/nestjs-dashboard/package.json +44 -0
  226. package/examples/nestjs-dashboard/pnpm-lock.yaml +3079 -0
  227. package/examples/nestjs-dashboard/src/app.controller.ts +24 -0
  228. package/examples/nestjs-dashboard/src/app.module.ts +15 -0
  229. package/examples/nestjs-dashboard/src/main.ts +32 -0
  230. package/examples/nestjs-dashboard/src/public/dashboard.html +1144 -0
  231. package/examples/nestjs-dashboard/src/teneo/agents.controller.ts +54 -0
  232. package/examples/nestjs-dashboard/src/teneo/events.controller.ts +65 -0
  233. package/examples/nestjs-dashboard/src/teneo/messages.controller.ts +47 -0
  234. package/examples/nestjs-dashboard/src/teneo/rooms.controller.ts +258 -0
  235. package/examples/nestjs-dashboard/src/teneo/teneo.module.ts +13 -0
  236. package/examples/nestjs-dashboard/src/teneo/teneo.service.ts +484 -0
  237. package/examples/nestjs-dashboard/tsconfig.json +22 -0
  238. package/examples/openai-teneo/.env.example +1 -1
  239. package/examples/openai-teneo/README.md +2 -2
  240. package/examples/openai-teneo/index.ts +82 -71
  241. package/examples/production-dashboard/.env.example +1 -1
  242. package/examples/production-dashboard/README.md +1 -1
  243. package/examples/production-dashboard/server.ts +2 -2
  244. package/examples/room-management-example.ts +5 -8
  245. package/examples/usage/.env.example +1 -1
  246. package/examples/usage/01-connect.ts +3 -4
  247. package/examples/usage/02-list-agents.ts +2 -3
  248. package/examples/usage/03-pick-agent.ts +2 -3
  249. package/examples/usage/04-find-by-capability.ts +2 -3
  250. package/examples/usage/05-webhook-example.ts +2 -3
  251. package/examples/usage/06-simple-api-server.ts +2 -3
  252. package/examples/usage/07-event-listener.ts +2 -3
  253. package/examples/webhook-integration.ts +1 -1
  254. package/examples/x-influencer-battle-server.ts +2 -2
  255. package/package.json +4 -1
  256. package/src/core/websocket-client.test.ts +8 -3
  257. package/src/core/websocket-client.ts +36 -6
  258. package/src/formatters/response-formatter.test.ts +2 -0
  259. package/src/formatters/response-formatter.ts +3 -3
  260. package/src/handlers/message-handlers/agent-details-response-handler.ts +42 -0
  261. package/src/handlers/message-handlers/agent-room-operation-response-handler.ts +2 -8
  262. package/src/handlers/message-handlers/agent-status-update-handler.ts +3 -9
  263. package/src/handlers/message-handlers/all-agents-response-handler.ts +39 -0
  264. package/src/handlers/message-handlers/auth-message-handler.ts +5 -0
  265. package/src/handlers/message-handlers/auth-success-handler.ts +6 -1
  266. package/src/handlers/message-handlers/base-handler.ts +20 -7
  267. package/src/handlers/message-handlers/index.ts +34 -0
  268. package/src/handlers/message-handlers/list-room-agents-handler.ts +2 -5
  269. package/src/handlers/message-handlers/list-rooms-response-handler.ts +6 -4
  270. package/src/handlers/message-handlers/rate-limit-notification-handler.ts +45 -0
  271. package/src/handlers/message-handlers/regular-message-handler.ts +3 -2
  272. package/src/handlers/message-handlers/room-operation-response-handler.ts +3 -6
  273. package/src/handlers/message-handlers/subscribe-response-handler.ts +12 -2
  274. package/src/handlers/message-handlers/task-quote-handler.ts +31 -0
  275. package/src/handlers/message-handlers/types.ts +37 -9
  276. package/src/handlers/message-handlers/unsubscribe-response-handler.ts +12 -2
  277. package/src/handlers/message-handlers/user-authenticated-handler.ts +31 -0
  278. package/src/handlers/message-handlers/user-count-handler.ts +34 -0
  279. package/src/handlers/webhook-handler.test.ts +3 -2
  280. package/src/handlers/webhook-handler.ts +13 -7
  281. package/src/index.ts +22 -1
  282. package/src/managers/admin-manager.ts +249 -0
  283. package/src/managers/agent-registry.test.ts +2 -1
  284. package/src/managers/agent-registry.ts +170 -2
  285. package/src/managers/agent-room-manager.ts +98 -42
  286. package/src/managers/index.ts +13 -1
  287. package/src/managers/message-router.ts +215 -17
  288. package/src/managers/room-management-manager.ts +4 -7
  289. package/src/managers/room-manager.ts +11 -15
  290. package/src/payments/index.ts +22 -0
  291. package/src/payments/payment-client.ts +240 -0
  292. package/src/teneo-sdk.ts +302 -27
  293. package/src/types/categories.ts +45 -0
  294. package/src/types/config.ts +70 -2
  295. package/src/types/error-codes.ts +10 -0
  296. package/src/types/events.test.ts +1 -0
  297. package/src/types/events.ts +43 -0
  298. package/src/types/index.ts +56 -0
  299. package/src/types/messages.test.ts +2 -1
  300. package/src/types/messages.ts +309 -6
  301. package/src/utils/bounded-queue.test.ts +1 -1
  302. package/src/utils/bounded-queue.ts +2 -1
  303. package/src/utils/circuit-breaker.test.ts +1 -1
  304. package/src/utils/deduplication-cache.test.ts +1 -1
  305. package/src/utils/event-waiter.test.ts +1 -1
  306. package/src/utils/event-waiter.ts +3 -3
  307. package/src/utils/index.ts +7 -0
  308. package/src/utils/logger.ts +8 -8
  309. package/src/utils/pricing-resolver.ts +128 -0
  310. package/src/utils/rate-limiter.test.ts +1 -1
  311. package/src/utils/rate-limiter.ts +1 -0
  312. package/src/utils/signature-verifier.test.ts +2 -2
  313. package/src/utils/signature-verifier.ts +3 -2
  314. package/tests/.env.example +7 -0
  315. package/tests/direct-agent-test.ts +151 -0
  316. package/tests/integration/real-server.test.ts +2 -0
  317. package/tests/integration/room-management.test.ts +10 -8
  318. package/tests/integration/websocket.test.ts +4 -1
  319. package/tests/payment-flow-test.ts +147 -0
  320. package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +17 -29
  321. package/tests/unit/handlers/agent-status-update-handler.test.ts +2 -6
  322. package/tests/unit/handlers/auth-success-handler-rooms.test.ts +1 -3
  323. package/tests/unit/handlers/list-available-agents-handler.test.ts +4 -12
  324. package/tests/unit/handlers/list-room-agents-handler.test.ts +2 -6
  325. package/tests/unit/handlers/room-operation-response-handler.test.ts +9 -36
  326. package/tests/unit/managers/agent-room-manager.test.ts +9 -16
  327. package/tests/unit/managers/room-management-manager.test.ts +21 -39
  328. package/tsconfig.json +2 -2
  329. package/vitest.config.ts +1 -0
@@ -4,26 +4,52 @@
4
4
  */
5
5
 
6
6
  import { EventEmitter } from "eventemitter3";
7
- import { Agent, Logger } from "../types";
8
- import { SDKEvents } from "../types/events";
7
+ import { Agent, AgentCategory, Logger, AgentRoomInfo } from "../types";
8
+ import { SDKEvents, SDKError } from "../types/events";
9
+ import { ErrorCode } from "../types/error-codes";
9
10
  import { AgentIdSchema, SearchQuerySchema } from "../types/validation";
11
+ import { WebSocketClient } from "../core/websocket-client";
12
+
13
+ /**
14
+ * Pending request for agent details with promise sharing for concurrent requests
15
+ */
16
+ interface PendingDetailsRequest {
17
+ promise: Promise<AgentRoomInfo>;
18
+ resolve: (agent: AgentRoomInfo) => void;
19
+ reject: (error: Error) => void;
20
+ timeout: ReturnType<typeof setTimeout>;
21
+ }
10
22
 
11
23
  export class AgentRegistry extends EventEmitter<SDKEvents> {
12
24
  private readonly logger: Logger;
13
25
  private readonly agents = new Map<string, Agent>();
14
26
  private cachedAgents?: Readonly<Agent>[];
15
27
  private isAgentsCacheDirty = true;
28
+ private wsClient?: WebSocketClient;
16
29
 
17
30
  // PERF-3: Search indices for O(1) lookups
18
31
  private capabilityIndex = new Map<string, Set<string>>();
19
32
  private nameTokenIndex = new Map<string, Set<string>>();
20
33
  private statusIndex = new Map<string, Set<string>>();
34
+ private categoryIndex = new Map<AgentCategory, Set<string>>();
35
+
36
+ // Pending agent details requests
37
+ private readonly pendingDetailsRequests = new Map<string, PendingDetailsRequest>();
38
+ private readonly detailsTimeout = 30000; // 30 seconds
21
39
 
22
40
  constructor(logger: Logger) {
23
41
  super();
24
42
  this.logger = logger;
25
43
  }
26
44
 
45
+ /**
46
+ * Sets the WebSocket client for making requests.
47
+ * @internal
48
+ */
49
+ public setWebSocketClient(wsClient: WebSocketClient): void {
50
+ this.wsClient = wsClient;
51
+ }
52
+
27
53
  /**
28
54
  * Gets a cached list of all available agents in the network.
29
55
  * Uses lazy caching with dirty flag for optimal performance.
@@ -200,6 +226,39 @@ export class AgentRegistry extends EventEmitter<SDKEvents> {
200
226
  .map((agent) => ({ ...agent }));
201
227
  }
202
228
 
229
+ /**
230
+ * Finds all agents that have a specific category.
231
+ * Uses O(1) category index lookup instead of O(n) filtering.
232
+ *
233
+ * @param category - The category to search for
234
+ * @returns Read-only array of agents with the specified category
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * const tradingAgents = agentRegistry.findByCategory('Trading');
239
+ * console.log(`Found ${tradingAgents.length} trading agents`);
240
+ * ```
241
+ */
242
+ public findByCategory(category: AgentCategory): ReadonlyArray<Agent> {
243
+ // Ensure cache is up to date
244
+ if (this.isAgentsCacheDirty || !this.cachedAgents) {
245
+ this.rebuildCache();
246
+ }
247
+
248
+ // O(1) index lookup
249
+ const agentIds = this.categoryIndex.get(category);
250
+
251
+ if (!agentIds || agentIds.size === 0) {
252
+ return [];
253
+ }
254
+
255
+ // Map agent IDs to agent objects with defensive copies
256
+ return Array.from(agentIds)
257
+ .map((id) => this.agents.get(id))
258
+ .filter((agent): agent is Agent => agent !== undefined)
259
+ .map((agent) => ({ ...agent }));
260
+ }
261
+
203
262
  /**
204
263
  * Updates the registry with a new list of agents.
205
264
  * Merges with existing agents and marks cache as dirty.
@@ -244,6 +303,97 @@ export class AgentRegistry extends EventEmitter<SDKEvents> {
244
303
  this.isAgentsCacheDirty = true;
245
304
  }
246
305
 
306
+ /**
307
+ * Fetches detailed information about a specific agent from the server.
308
+ * Makes a request to the server for full agent details including capabilities,
309
+ * commands, pricing, and more.
310
+ *
311
+ * Multiple concurrent calls for the same agent will share the same request,
312
+ * avoiding redundant server calls and preventing race conditions.
313
+ *
314
+ * @param agentId - The unique identifier of the agent
315
+ * @returns Promise that resolves with full agent details
316
+ * @throws {SDKError} If not connected or request times out
317
+ * @throws {ValidationError} If agentId is invalid
318
+ *
319
+ * @example
320
+ * ```typescript
321
+ * const details = await agentRegistry.getAgentDetails('weather-agent-001');
322
+ * console.log(`Agent: ${details.agent_name}`);
323
+ * console.log(`Capabilities: ${details.capabilities?.length}`);
324
+ * console.log(`Status: ${details.status}`);
325
+ * ```
326
+ */
327
+ public async getAgentDetails(agentId: string): Promise<AgentRoomInfo> {
328
+ if (!this.wsClient || !this.wsClient.isConnected) {
329
+ throw new SDKError("Not connected to Teneo Protocol", ErrorCode.NOT_CONNECTED);
330
+ }
331
+
332
+ // Validate agent ID
333
+ const validatedAgentId = AgentIdSchema.parse(agentId);
334
+
335
+ // Check if there's already a pending request for this agent - reuse it
336
+ const existingRequest = this.pendingDetailsRequests.get(validatedAgentId);
337
+ if (existingRequest) {
338
+ this.logger.debug("AgentRegistry: Reusing pending request for agent details", {
339
+ agentId: validatedAgentId
340
+ });
341
+ return existingRequest.promise;
342
+ }
343
+
344
+ this.logger.info("AgentRegistry: Requesting agent details", { agentId: validatedAgentId });
345
+
346
+ // Send get_agent_details message
347
+ const message = {
348
+ type: "get_agent_details" as const,
349
+ agent_id: validatedAgentId
350
+ };
351
+
352
+ await this.wsClient.sendMessage(message);
353
+
354
+ // Create promise with stored resolve/reject for later resolution
355
+ let resolvePromise: (agent: AgentRoomInfo) => void;
356
+ let rejectPromise: (error: Error) => void;
357
+
358
+ const promise = new Promise<AgentRoomInfo>((resolve, reject) => {
359
+ resolvePromise = resolve;
360
+ rejectPromise = reject;
361
+ });
362
+
363
+ const timeout = setTimeout(() => {
364
+ this.pendingDetailsRequests.delete(validatedAgentId);
365
+ rejectPromise!(new SDKError("Agent details request timed out", ErrorCode.TIMEOUT_ERROR));
366
+ }, this.detailsTimeout);
367
+
368
+ this.pendingDetailsRequests.set(validatedAgentId, {
369
+ promise,
370
+ resolve: resolvePromise!,
371
+ reject: rejectPromise!,
372
+ timeout
373
+ });
374
+
375
+ return promise;
376
+ }
377
+
378
+ /**
379
+ * Handles incoming agent_details_response from server.
380
+ * @internal
381
+ */
382
+ public handleAgentDetails(agent: AgentRoomInfo): void {
383
+ this.logger.debug("AgentRegistry: Received agent details", {
384
+ agentId: agent.agent_id,
385
+ agentName: agent.agent_name
386
+ });
387
+
388
+ // Resolve pending request
389
+ const pending = this.pendingDetailsRequests.get(agent.agent_id);
390
+ if (pending) {
391
+ clearTimeout(pending.timeout);
392
+ this.pendingDetailsRequests.delete(agent.agent_id);
393
+ pending.resolve(agent);
394
+ }
395
+ }
396
+
247
397
  /**
248
398
  * Clears all agents from the registry.
249
399
  * Removes all cached agents and marks cache as dirty.
@@ -257,6 +407,13 @@ export class AgentRegistry extends EventEmitter<SDKEvents> {
257
407
  public clear(): void {
258
408
  this.agents.clear();
259
409
  this.isAgentsCacheDirty = true;
410
+
411
+ // Clear pending requests
412
+ for (const [, pending] of this.pendingDetailsRequests) {
413
+ clearTimeout(pending.timeout);
414
+ pending.reject(new SDKError("Agent registry cleared", ErrorCode.SDK_DESTROYED));
415
+ }
416
+ this.pendingDetailsRequests.clear();
260
417
  }
261
418
 
262
419
  /**
@@ -291,6 +448,7 @@ export class AgentRegistry extends EventEmitter<SDKEvents> {
291
448
  this.capabilityIndex.clear();
292
449
  this.nameTokenIndex.clear();
293
450
  this.statusIndex.clear();
451
+ this.categoryIndex.clear();
294
452
 
295
453
  // Populate indices
296
454
  for (const agent of this.agents.values()) {
@@ -320,6 +478,16 @@ export class AgentRegistry extends EventEmitter<SDKEvents> {
320
478
  this.statusIndex.set(status, new Set());
321
479
  }
322
480
  this.statusIndex.get(status)!.add(agent.id);
481
+
482
+ // Index categories
483
+ if (agent.categories) {
484
+ for (const category of agent.categories) {
485
+ if (!this.categoryIndex.has(category)) {
486
+ this.categoryIndex.set(category, new Set());
487
+ }
488
+ this.categoryIndex.get(category)!.add(agent.id);
489
+ }
490
+ }
323
491
  }
324
492
 
325
493
  this.isAgentsCacheDirty = false;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AgentRoomManager - Manages agent-room associations (v2.0.0)
3
3
  * Allows room owners to control which agents are available in their rooms
4
- * Implements caching with 5-minute TTL for performance
4
+ * Implements caching with 5-minute TTL and LRU eviction for performance
5
5
  */
6
6
 
7
7
  import { EventEmitter } from "eventemitter3";
@@ -27,16 +27,96 @@ export interface AgentRoomInfo {
27
27
  // Cache TTL: 5 minutes
28
28
  const CACHE_TTL_MS = 5 * 60 * 1000;
29
29
 
30
+ // Maximum number of rooms to cache (LRU eviction beyond this)
31
+ const MAX_CACHED_ROOMS = 1000;
32
+
33
+ /**
34
+ * Simple LRU cache with TTL support
35
+ * Uses Map's insertion order for LRU tracking
36
+ */
37
+ class LRUCache<T> {
38
+ private readonly cache = new Map<string, T>();
39
+ private readonly timestamps = new Map<string, number>();
40
+ private readonly maxSize: number;
41
+ private readonly ttlMs: number;
42
+
43
+ constructor(maxSize: number, ttlMs: number) {
44
+ this.maxSize = maxSize;
45
+ this.ttlMs = ttlMs;
46
+ }
47
+
48
+ get(key: string): T | undefined {
49
+ const value = this.cache.get(key);
50
+ if (value === undefined) return undefined;
51
+
52
+ // Check TTL
53
+ const timestamp = this.timestamps.get(key);
54
+ if (timestamp && Date.now() - timestamp >= this.ttlMs) {
55
+ this.delete(key);
56
+ return undefined;
57
+ }
58
+
59
+ // Move to end (most recently used) by re-inserting
60
+ this.cache.delete(key);
61
+ this.cache.set(key, value);
62
+
63
+ return value;
64
+ }
65
+
66
+ set(key: string, value: T): void {
67
+ // Delete first to update insertion order
68
+ this.cache.delete(key);
69
+ this.timestamps.delete(key);
70
+
71
+ // Evict oldest entries if at capacity
72
+ while (this.cache.size >= this.maxSize) {
73
+ const oldestKey = this.cache.keys().next().value;
74
+ if (oldestKey !== undefined) {
75
+ this.cache.delete(oldestKey);
76
+ this.timestamps.delete(oldestKey);
77
+ }
78
+ }
79
+
80
+ this.cache.set(key, value);
81
+ this.timestamps.set(key, Date.now());
82
+ }
83
+
84
+ delete(key: string): void {
85
+ this.cache.delete(key);
86
+ this.timestamps.delete(key);
87
+ }
88
+
89
+ has(key: string): boolean {
90
+ return this.get(key) !== undefined;
91
+ }
92
+
93
+ isValid(key: string): boolean {
94
+ const timestamp = this.timestamps.get(key);
95
+ if (!timestamp) return false;
96
+ return Date.now() - timestamp < this.ttlMs;
97
+ }
98
+
99
+ clear(): void {
100
+ this.cache.clear();
101
+ this.timestamps.clear();
102
+ }
103
+
104
+ get size(): number {
105
+ return this.cache.size;
106
+ }
107
+ }
108
+
30
109
  export class AgentRoomManager extends EventEmitter<SDKEvents> {
31
110
  private readonly wsClient: WebSocketClient;
32
111
  private readonly logger: Logger;
33
112
  private readonly roomManagementManager: RoomManagementManager; // Reference to check ownership
34
113
 
35
- // Caches with TTL
36
- private readonly roomAgentsCache = new Map<string, AgentRoomInfo[]>();
37
- private readonly availableAgentsCache = new Map<string, AgentRoomInfo[]>();
38
- private readonly roomAgentsCacheTime = new Map<string, number>();
39
- private readonly availableAgentsCacheTime = new Map<string, number>();
114
+ // LRU caches with TTL (max 1000 rooms each)
115
+ private readonly roomAgentsCache = new LRUCache<AgentRoomInfo[]>(MAX_CACHED_ROOMS, CACHE_TTL_MS);
116
+ private readonly availableAgentsCache = new LRUCache<AgentRoomInfo[]>(
117
+ MAX_CACHED_ROOMS,
118
+ CACHE_TTL_MS
119
+ );
40
120
 
41
121
  constructor(
42
122
  wsClient: WebSocketClient,
@@ -70,7 +150,7 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
70
150
  */
71
151
  public async addAgentToRoom(roomId: string, agentId: string): Promise<void> {
72
152
  if (!this.wsClient.isConnected) {
73
- throw new SDKError("Not connected to Teneo network", ErrorCode.NOT_CONNECTED);
153
+ throw new SDKError("Not connected to Teneo Protocol", ErrorCode.NOT_CONNECTED);
74
154
  }
75
155
 
76
156
  // Validate inputs
@@ -152,7 +232,7 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
152
232
  */
153
233
  public async removeAgentFromRoom(roomId: string, agentId: string): Promise<void> {
154
234
  if (!this.wsClient.isConnected) {
155
- throw new SDKError("Not connected to Teneo network", ErrorCode.NOT_CONNECTED);
235
+ throw new SDKError("Not connected to Teneo Protocol", ErrorCode.NOT_CONNECTED);
156
236
  }
157
237
 
158
238
  // Validate inputs
@@ -230,19 +310,16 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
230
310
  * const freshAgents = await sdk.listRoomAgents('room-123', false);
231
311
  * ```
232
312
  */
233
- public async listRoomAgents(
234
- roomId: string,
235
- useCache: boolean = true
236
- ): Promise<AgentRoomInfo[]> {
313
+ public async listRoomAgents(roomId: string, useCache: boolean = true): Promise<AgentRoomInfo[]> {
237
314
  if (!this.wsClient.isConnected) {
238
- throw new SDKError("Not connected to Teneo network", ErrorCode.NOT_CONNECTED);
315
+ throw new SDKError("Not connected to Teneo Protocol", ErrorCode.NOT_CONNECTED);
239
316
  }
240
317
 
241
318
  // Validate input
242
319
  this.validateRoomId(roomId);
243
320
 
244
321
  // Check cache if enabled
245
- if (useCache && this.isCacheValid(this.roomAgentsCacheTime, roomId)) {
322
+ if (useCache) {
246
323
  const cached = this.roomAgentsCache.get(roomId);
247
324
  if (cached) {
248
325
  this.logger.debug("AgentRoomManager: Returning cached room agents", {
@@ -315,14 +392,14 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
315
392
  useCache: boolean = true
316
393
  ): Promise<AgentRoomInfo[]> {
317
394
  if (!this.wsClient.isConnected) {
318
- throw new SDKError("Not connected to Teneo network", ErrorCode.NOT_CONNECTED);
395
+ throw new SDKError("Not connected to Teneo Protocol", ErrorCode.NOT_CONNECTED);
319
396
  }
320
397
 
321
398
  // Validate input
322
399
  this.validateRoomId(roomId);
323
400
 
324
401
  // Check cache if enabled
325
- if (useCache && this.isCacheValid(this.availableAgentsCacheTime, roomId)) {
402
+ if (useCache) {
326
403
  const cached = this.availableAgentsCache.get(roomId);
327
404
  if (cached) {
328
405
  this.logger.debug("AgentRoomManager: Returning cached available agents", {
@@ -391,9 +468,6 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
391
468
  * ```
392
469
  */
393
470
  public getRoomAgents(roomId: string): AgentRoomInfo[] | undefined {
394
- if (!this.isCacheValid(this.roomAgentsCacheTime, roomId)) {
395
- return undefined;
396
- }
397
471
  const cached = this.roomAgentsCache.get(roomId);
398
472
  return cached ? cached.map((agent) => ({ ...agent })) : undefined;
399
473
  }
@@ -414,9 +488,6 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
414
488
  * ```
415
489
  */
416
490
  public getAvailableAgents(roomId: string): AgentRoomInfo[] | undefined {
417
- if (!this.isCacheValid(this.availableAgentsCacheTime, roomId)) {
418
- return undefined;
419
- }
420
491
  const cached = this.availableAgentsCache.get(roomId);
421
492
  return cached ? cached.map((agent) => ({ ...agent })) : undefined;
422
493
  }
@@ -493,8 +564,6 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
493
564
  public clearAllCaches(): void {
494
565
  this.roomAgentsCache.clear();
495
566
  this.availableAgentsCache.clear();
496
- this.roomAgentsCacheTime.clear();
497
- this.availableAgentsCacheTime.clear();
498
567
  this.logger.debug("AgentRoomManager: All caches cleared");
499
568
  }
500
569
 
@@ -524,10 +593,10 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
524
593
  */
525
594
  public cacheRoomAgents(roomId: string, agents: AgentRoomInfo[]): void {
526
595
  this.roomAgentsCache.set(roomId, agents);
527
- this.roomAgentsCacheTime.set(roomId, Date.now());
528
596
  this.logger.debug("AgentRoomManager: Cached room agents", {
529
597
  roomId,
530
- count: agents.length
598
+ count: agents.length,
599
+ cacheSize: this.roomAgentsCache.size
531
600
  });
532
601
  }
533
602
 
@@ -537,10 +606,10 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
537
606
  */
538
607
  public cacheAvailableAgents(roomId: string, agents: AgentRoomInfo[]): void {
539
608
  this.availableAgentsCache.set(roomId, agents);
540
- this.availableAgentsCacheTime.set(roomId, Date.now());
541
609
  this.logger.debug("AgentRoomManager: Cached available agents", {
542
610
  roomId,
543
- count: agents.length
611
+ count: agents.length,
612
+ cacheSize: this.availableAgentsCache.size
544
613
  });
545
614
  }
546
615
 
@@ -548,25 +617,12 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
548
617
  // PRIVATE HELPERS
549
618
  // ============================================================================
550
619
 
551
- /**
552
- * Checks if cache is still valid (within TTL)
553
- */
554
- private isCacheValid(cacheTimeMap: Map<string, number>, roomId: string): boolean {
555
- const cacheTime = cacheTimeMap.get(roomId);
556
- if (!cacheTime) return false;
557
-
558
- const age = Date.now() - cacheTime;
559
- return age < CACHE_TTL_MS;
560
- }
561
-
562
620
  /**
563
621
  * Invalidates all caches for a specific room
564
622
  */
565
623
  private invalidateRoomCaches(roomId: string): void {
566
624
  this.roomAgentsCache.delete(roomId);
567
625
  this.availableAgentsCache.delete(roomId);
568
- this.roomAgentsCacheTime.delete(roomId);
569
- this.availableAgentsCacheTime.delete(roomId);
570
626
  }
571
627
 
572
628
  /**
@@ -604,6 +660,6 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
604
660
  const ownedRooms = this.roomManagementManager.getOwnedRooms?.();
605
661
  if (!ownedRooms) return true; // Skip check if method not available
606
662
 
607
- return ownedRooms.some((room: any) => room.id === roomId);
663
+ return ownedRooms.some((room) => room.id === roomId);
608
664
  }
609
665
  }
@@ -8,4 +8,16 @@ export { RoomManager } from "./room-manager";
8
8
  export { RoomManagementManager } from "./room-management-manager";
9
9
  export { AgentRoomManager, type AgentRoomInfo } from "./agent-room-manager";
10
10
  export { AgentRegistry } from "./agent-registry";
11
- export { MessageRouter, type SendMessageOptions, type AgentCommand } from "./message-router";
11
+ export {
12
+ MessageRouter,
13
+ type SendMessageOptions,
14
+ type AgentCommand,
15
+ type QuoteResult,
16
+ type MessageRouterConfig
17
+ } from "./message-router";
18
+ export {
19
+ AdminManager,
20
+ type AdminManagerEvents,
21
+ type ListAllAgentsOptions,
22
+ type AllAgentsResult
23
+ } from "./admin-manager";