@teneo-protocol/sdk 2.2.2 → 3.0.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 (231) hide show
  1. package/.github/ISSUE_TEMPLATE/config.yml +1 -1
  2. package/CHANGELOG.md +366 -15
  3. package/CONCEPTS.md +182 -44
  4. package/README.md +524 -94
  5. package/dist/constants.d.ts +3 -1
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/constants.js +5 -3
  8. package/dist/constants.js.map +1 -1
  9. package/dist/core/websocket-client.d.ts.map +1 -1
  10. package/dist/core/websocket-client.js +9 -5
  11. package/dist/core/websocket-client.js.map +1 -1
  12. package/dist/formatters/response-formatter.d.ts +6 -6
  13. package/dist/handlers/message-handlers/agent-details-response-handler.d.ts +1080 -756
  14. package/dist/handlers/message-handlers/agent-details-response-handler.d.ts.map +1 -1
  15. package/dist/handlers/message-handlers/agent-details-response-handler.js +2 -2
  16. package/dist/handlers/message-handlers/agent-details-response-handler.js.map +1 -1
  17. package/dist/handlers/message-handlers/agent-error-handler.d.ts +91 -0
  18. package/dist/handlers/message-handlers/agent-error-handler.d.ts.map +1 -0
  19. package/dist/handlers/message-handlers/agent-error-handler.js +44 -0
  20. package/dist/handlers/message-handlers/agent-error-handler.js.map +1 -0
  21. package/dist/handlers/message-handlers/agent-selected-handler.d.ts +6 -0
  22. package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -1
  23. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts +1080 -756
  24. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts.map +1 -1
  25. package/dist/handlers/message-handlers/agent-status-update-handler.js +2 -7
  26. package/dist/handlers/message-handlers/agent-status-update-handler.js.map +1 -1
  27. package/dist/handlers/message-handlers/all-agents-response-handler.d.ts +135 -54
  28. package/dist/handlers/message-handlers/all-agents-response-handler.d.ts.map +1 -1
  29. package/dist/handlers/message-handlers/all-agents-response-handler.js +2 -2
  30. package/dist/handlers/message-handlers/all-agents-response-handler.js.map +1 -1
  31. package/dist/handlers/message-handlers/auth-error-handler.d.ts +6 -0
  32. package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -1
  33. package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -1
  34. package/dist/handlers/message-handlers/auth-message-handler.js +6 -1
  35. package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -1
  36. package/dist/handlers/message-handlers/auth-required-handler.d.ts +6 -0
  37. package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -1
  38. package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -1
  39. package/dist/handlers/message-handlers/auth-success-handler.js +6 -1
  40. package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -1
  41. package/dist/handlers/message-handlers/base-handler.d.ts +2 -1
  42. package/dist/handlers/message-handlers/base-handler.d.ts.map +1 -1
  43. package/dist/handlers/message-handlers/base-handler.js +24 -4
  44. package/dist/handlers/message-handlers/base-handler.js.map +1 -1
  45. package/dist/handlers/message-handlers/challenge-handler.d.ts +6 -0
  46. package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -1
  47. package/dist/handlers/message-handlers/error-message-handler.d.ts +6 -0
  48. package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -1
  49. package/dist/handlers/message-handlers/index.d.ts +4 -0
  50. package/dist/handlers/message-handlers/index.d.ts.map +1 -1
  51. package/dist/handlers/message-handlers/index.js +23 -1
  52. package/dist/handlers/message-handlers/index.js.map +1 -1
  53. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts +1116 -756
  54. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts.map +1 -1
  55. package/dist/handlers/message-handlers/list-available-agents-handler.js +23 -10
  56. package/dist/handlers/message-handlers/list-available-agents-handler.js.map +1 -1
  57. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts +1080 -756
  58. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts.map +1 -1
  59. package/dist/handlers/message-handlers/list-room-agents-handler.js +2 -6
  60. package/dist/handlers/message-handlers/list-room-agents-handler.js.map +1 -1
  61. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -1
  62. package/dist/handlers/message-handlers/list-rooms-response-handler.js +2 -5
  63. package/dist/handlers/message-handlers/list-rooms-response-handler.js.map +1 -1
  64. package/dist/handlers/message-handlers/ping-pong-handler.d.ts +52 -4
  65. package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -1
  66. package/dist/handlers/message-handlers/ping-pong-handler.js +23 -4
  67. package/dist/handlers/message-handlers/ping-pong-handler.js.map +1 -1
  68. package/dist/handlers/message-handlers/rate-limit-notification-handler.d.ts.map +1 -1
  69. package/dist/handlers/message-handlers/rate-limit-notification-handler.js +3 -2
  70. package/dist/handlers/message-handlers/rate-limit-notification-handler.js.map +1 -1
  71. package/dist/handlers/message-handlers/regular-message-handler.d.ts +6 -0
  72. package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -1
  73. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +12 -6
  74. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
  75. package/dist/handlers/message-handlers/success-handler.d.ts +82 -0
  76. package/dist/handlers/message-handlers/success-handler.d.ts.map +1 -0
  77. package/dist/handlers/message-handlers/success-handler.js +24 -0
  78. package/dist/handlers/message-handlers/success-handler.js.map +1 -0
  79. package/dist/handlers/message-handlers/task-confirmed-handler.d.ts +110 -0
  80. package/dist/handlers/message-handlers/task-confirmed-handler.d.ts.map +1 -0
  81. package/dist/handlers/message-handlers/task-confirmed-handler.js +46 -0
  82. package/dist/handlers/message-handlers/task-confirmed-handler.js.map +1 -0
  83. package/dist/handlers/message-handlers/trigger-wallet-tx-handler.d.ts +244 -0
  84. package/dist/handlers/message-handlers/trigger-wallet-tx-handler.d.ts.map +1 -0
  85. package/dist/handlers/message-handlers/trigger-wallet-tx-handler.js +58 -0
  86. package/dist/handlers/message-handlers/trigger-wallet-tx-handler.js.map +1 -0
  87. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +12 -6
  88. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
  89. package/dist/handlers/message-handlers/user-authenticated-handler.js +2 -2
  90. package/dist/handlers/message-handlers/user-authenticated-handler.js.map +1 -1
  91. package/dist/handlers/message-handlers/user-count-handler.js +2 -2
  92. package/dist/handlers/message-handlers/user-count-handler.js.map +1 -1
  93. package/dist/index.d.ts +3 -3
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +11 -4
  96. package/dist/index.js.map +1 -1
  97. package/dist/managers/admin-manager.d.ts +3 -1
  98. package/dist/managers/admin-manager.d.ts.map +1 -1
  99. package/dist/managers/admin-manager.js +4 -3
  100. package/dist/managers/admin-manager.js.map +1 -1
  101. package/dist/managers/agent-room-manager.d.ts +89 -11
  102. package/dist/managers/agent-room-manager.d.ts.map +1 -1
  103. package/dist/managers/agent-room-manager.js +99 -35
  104. package/dist/managers/agent-room-manager.js.map +1 -1
  105. package/dist/managers/index.d.ts +1 -1
  106. package/dist/managers/index.d.ts.map +1 -1
  107. package/dist/managers/index.js.map +1 -1
  108. package/dist/managers/message-router.d.ts +45 -5
  109. package/dist/managers/message-router.d.ts.map +1 -1
  110. package/dist/managers/message-router.js +96 -24
  111. package/dist/managers/message-router.js.map +1 -1
  112. package/dist/managers/room-manager.d.ts +29 -7
  113. package/dist/managers/room-manager.d.ts.map +1 -1
  114. package/dist/managers/room-manager.js +37 -11
  115. package/dist/managers/room-manager.js.map +1 -1
  116. package/dist/payments/index.d.ts +3 -1
  117. package/dist/payments/index.d.ts.map +1 -1
  118. package/dist/payments/index.js +17 -3
  119. package/dist/payments/index.js.map +1 -1
  120. package/dist/payments/networks.d.ts +59 -0
  121. package/dist/payments/networks.d.ts.map +1 -0
  122. package/dist/payments/networks.js +192 -0
  123. package/dist/payments/networks.js.map +1 -0
  124. package/dist/payments/payment-client.d.ts +55 -10
  125. package/dist/payments/payment-client.d.ts.map +1 -1
  126. package/dist/payments/payment-client.js +172 -51
  127. package/dist/payments/payment-client.js.map +1 -1
  128. package/dist/teneo-sdk.d.ts +215 -41
  129. package/dist/teneo-sdk.d.ts.map +1 -1
  130. package/dist/teneo-sdk.js +361 -84
  131. package/dist/teneo-sdk.js.map +1 -1
  132. package/dist/types/config.d.ts +334 -25
  133. package/dist/types/config.d.ts.map +1 -1
  134. package/dist/types/config.js +114 -22
  135. package/dist/types/config.js.map +1 -1
  136. package/dist/types/events.d.ts +60 -14
  137. package/dist/types/events.d.ts.map +1 -1
  138. package/dist/types/events.js.map +1 -1
  139. package/dist/types/index.d.ts +1 -1
  140. package/dist/types/index.d.ts.map +1 -1
  141. package/dist/types/index.js +11 -4
  142. package/dist/types/index.js.map +1 -1
  143. package/dist/types/messages.d.ts +13110 -7451
  144. package/dist/types/messages.d.ts.map +1 -1
  145. package/dist/types/messages.js +195 -44
  146. package/dist/types/messages.js.map +1 -1
  147. package/dist/utils/pricing-resolver.d.ts +1 -1
  148. package/dist/utils/pricing-resolver.d.ts.map +1 -1
  149. package/dist/utils/pricing-resolver.js +9 -1
  150. package/dist/utils/pricing-resolver.js.map +1 -1
  151. package/examples/agent-room-management-example.ts +5 -5
  152. package/examples/basic-usage.ts +26 -6
  153. package/examples/claude-agent-x-follower/index.ts +1 -1
  154. package/examples/minimal-chat.ts +4 -3
  155. package/examples/n8n-teneo/index.ts +2 -2
  156. package/examples/nestjs-dashboard/README.md +1 -1
  157. package/examples/nestjs-dashboard/src/teneo/agents.controller.ts +3 -3
  158. package/examples/nestjs-dashboard/src/teneo/rooms.controller.ts +5 -5
  159. package/examples/nestjs-dashboard/src/teneo/teneo.service.ts +8 -8
  160. package/examples/openai-teneo/index.ts +1 -1
  161. package/examples/payment-flow.ts +143 -0
  162. package/examples/production-dashboard/README.md +6 -8
  163. package/examples/production-dashboard/server.ts +22 -10
  164. package/examples/room-management-example.ts +2 -2
  165. package/examples/usage/01-connect.ts +0 -3
  166. package/examples/usage/02-list-agents.ts +0 -2
  167. package/examples/usage/03-pick-agent.ts +3 -4
  168. package/examples/usage/04-find-by-capability.ts +10 -12
  169. package/examples/usage/05-webhook-example.ts +2 -4
  170. package/examples/usage/06-simple-api-server.ts +13 -9
  171. package/examples/usage/07-event-listener.ts +1 -13
  172. package/examples/usage/README.md +33 -7
  173. package/examples/webhook-integration.ts +9 -9
  174. package/examples/x-influencer-battle-server.ts +1 -1
  175. package/package.json +1 -1
  176. package/scripts/diagnose-connection.ts +86 -0
  177. package/scripts/investigate-payload.ts +163 -0
  178. package/scripts/list-agents.ts +58 -0
  179. package/scripts/live-multi-network-test.ts +230 -0
  180. package/src/constants.ts +5 -3
  181. package/src/core/websocket-client.ts +10 -9
  182. package/src/handlers/message-handlers/agent-details-response-handler.ts +2 -2
  183. package/src/handlers/message-handlers/agent-error-handler.ts +47 -0
  184. package/src/handlers/message-handlers/agent-status-update-handler.ts +2 -7
  185. package/src/handlers/message-handlers/all-agents-response-handler.ts +2 -2
  186. package/src/handlers/message-handlers/auth-message-handler.ts +7 -1
  187. package/src/handlers/message-handlers/auth-success-handler.ts +7 -1
  188. package/src/handlers/message-handlers/base-handler.ts +24 -4
  189. package/src/handlers/message-handlers/index.ts +24 -0
  190. package/src/handlers/message-handlers/list-available-agents-handler.ts +24 -11
  191. package/src/handlers/message-handlers/list-room-agents-handler.ts +2 -6
  192. package/src/handlers/message-handlers/list-rooms-response-handler.ts +2 -5
  193. package/src/handlers/message-handlers/ping-pong-handler.ts +29 -4
  194. package/src/handlers/message-handlers/rate-limit-notification-handler.ts +3 -2
  195. package/src/handlers/message-handlers/success-handler.ts +26 -0
  196. package/src/handlers/message-handlers/task-confirmed-handler.ts +49 -0
  197. package/src/handlers/message-handlers/trigger-wallet-tx-handler.ts +62 -0
  198. package/src/handlers/message-handlers/user-authenticated-handler.ts +2 -2
  199. package/src/handlers/message-handlers/user-count-handler.ts +2 -2
  200. package/src/index.ts +12 -4
  201. package/src/managers/admin-manager.ts +6 -3
  202. package/src/managers/agent-room-manager.ts +155 -26
  203. package/src/managers/index.ts +6 -1
  204. package/src/managers/message-router.ts +122 -27
  205. package/src/managers/room-manager.ts +39 -11
  206. package/src/payments/index.ts +20 -5
  207. package/src/payments/networks.ts +208 -0
  208. package/src/payments/payment-client.ts +211 -56
  209. package/src/teneo-sdk.ts +402 -71
  210. package/src/types/config.test.ts +24 -4
  211. package/src/types/config.ts +123 -25
  212. package/src/types/events.ts +36 -2
  213. package/src/types/index.ts +16 -3
  214. package/src/types/messages.ts +235 -60
  215. package/src/utils/pricing-resolver.ts +10 -2
  216. package/tests/direct-agent-test.ts +1 -1
  217. package/tests/integration/real-server.test.ts +1 -1
  218. package/tests/integration/websocket.test.ts +3 -3
  219. package/tests/multi-network-payment.test.ts +309 -0
  220. package/tests/multi-network.test.ts +296 -0
  221. package/tests/payment-flow-test.ts +6 -4
  222. package/tests/unit/handlers/agent-error-handler.test.ts +388 -0
  223. package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +9 -6
  224. package/tests/unit/handlers/agent-status-update-handler.test.ts +11 -16
  225. package/tests/unit/handlers/list-available-agents-handler.test.ts +11 -14
  226. package/tests/unit/handlers/list-room-agents-handler.test.ts +11 -15
  227. package/tests/unit/handlers/room-operation-response-handler.test.ts +9 -6
  228. package/tests/unit/handlers/trigger-wallet-tx-handler.test.ts +431 -0
  229. package/tests/unit/managers/admin-manager.test.ts +183 -0
  230. package/tests/unit/managers/agent-room-manager.test.ts +189 -33
  231. package/tests/unit/sdk-new-methods.test.ts +221 -0
@@ -24,6 +24,40 @@ export interface AgentRoomInfo {
24
24
  added_at?: string;
25
25
  }
26
26
 
27
+ /**
28
+ * Options for listing available agents with pagination
29
+ */
30
+ export interface ListAvailableAgentsOptions {
31
+ /** Number of agents to return (default: server decides) */
32
+ limit?: number;
33
+ /** Pagination offset */
34
+ offset?: number;
35
+ /** Include full agent details */
36
+ includeDetails?: boolean;
37
+ /** Return minimal agent info only */
38
+ minimal?: boolean;
39
+ /** Sort order: alphabetical or by other criteria */
40
+ sortBy?: "a-z" | "requests";
41
+ /** Include agents already in the room */
42
+ includeInRoom?: boolean;
43
+ }
44
+
45
+ /**
46
+ * Paginated result from listAvailableAgents with options
47
+ */
48
+ export interface PaginatedAgentsResult {
49
+ /** List of agents */
50
+ agents: AgentRoomInfo[];
51
+ /** Total number of matching agents */
52
+ total: number;
53
+ /** Current offset */
54
+ offset: number;
55
+ /** Page size */
56
+ limit: number;
57
+ /** Whether there are more agents to load */
58
+ hasMore: boolean;
59
+ }
60
+
27
61
  // Cache TTL: 5 minutes
28
62
  const CACHE_TTL_MS = 5 * 60 * 1000;
29
63
 
@@ -380,17 +414,25 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
380
414
  * @param useCache - Whether to use cached data (default: true)
381
415
  * @returns Promise that resolves with array of available agents
382
416
  * @throws {SDKError} If not connected or operation fails
417
+ */
418
+ public async listAvailableAgents(roomId: string, useCache?: boolean): Promise<AgentRoomInfo[]>;
419
+ /**
420
+ * Lists agents available to add to a room with pagination and filtering options.
421
+ * Does not use cache when called with options.
383
422
  *
384
- * @example
385
- * ```typescript
386
- * const availableAgents = await sdk.listAvailableAgents('room-123');
387
- * console.log(`${availableAgents.length} agents can be added`);
388
- * ```
423
+ * @param roomId - ID of the room to check available agents for
424
+ * @param options - Pagination and filter options
425
+ * @returns Promise that resolves with paginated agents result
426
+ * @throws {SDKError} If not connected or operation fails
389
427
  */
390
428
  public async listAvailableAgents(
391
429
  roomId: string,
392
- useCache: boolean = true
393
- ): Promise<AgentRoomInfo[]> {
430
+ options: ListAvailableAgentsOptions
431
+ ): Promise<PaginatedAgentsResult>;
432
+ public async listAvailableAgents(
433
+ roomId: string,
434
+ useCacheOrOptions?: boolean | ListAvailableAgentsOptions
435
+ ): Promise<AgentRoomInfo[] | PaginatedAgentsResult> {
394
436
  if (!this.wsClient.isConnected) {
395
437
  throw new SDKError("Not connected to Teneo Protocol", ErrorCode.NOT_CONNECTED);
396
438
  }
@@ -398,8 +440,12 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
398
440
  // Validate input
399
441
  this.validateRoomId(roomId);
400
442
 
401
- // Check cache if enabled
402
- if (useCache) {
443
+ // Determine if using pagination options or legacy boolean
444
+ const isPaginated = typeof useCacheOrOptions === "object" && useCacheOrOptions !== null;
445
+ const useCache = isPaginated ? false : ((useCacheOrOptions as boolean) ?? true);
446
+
447
+ // Check cache if enabled (only for legacy non-paginated calls)
448
+ if (!isPaginated && useCache) {
403
449
  const cached = this.availableAgentsCache.get(roomId);
404
450
  if (cached) {
405
451
  this.logger.debug("AgentRoomManager: Returning cached available agents", {
@@ -410,13 +456,24 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
410
456
  }
411
457
  }
412
458
 
413
- this.logger.debug("AgentRoomManager: Listing available agents", { roomId });
459
+ this.logger.debug("AgentRoomManager: Listing available agents", { roomId, isPaginated });
460
+
461
+ // Build message data with optional pagination params
462
+ const data: Record<string, unknown> = { room_id: roomId };
463
+
464
+ if (isPaginated) {
465
+ const options = useCacheOrOptions as ListAvailableAgentsOptions;
466
+ if (options.limit !== undefined) data.limit = options.limit;
467
+ if (options.offset !== undefined) data.offset = options.offset;
468
+ if (options.includeDetails !== undefined) data.include_details = options.includeDetails;
469
+ if (options.minimal !== undefined) data.minimal = options.minimal;
470
+ if (options.sortBy !== undefined) data.sort_by = options.sortBy;
471
+ if (options.includeInRoom !== undefined) data.include_in_room = options.includeInRoom;
472
+ }
414
473
 
415
474
  const message = {
416
475
  type: "list_available_agents" as const,
417
- data: {
418
- room_id: roomId
419
- }
476
+ data
420
477
  };
421
478
 
422
479
  return new Promise((resolve, reject) => {
@@ -425,9 +482,27 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
425
482
  reject(new SDKError("List available agents timeout", ErrorCode.TIMEOUT));
426
483
  }, 30000);
427
484
 
428
- const onSuccess = (agents: AgentRoomInfo[]) => {
485
+ const onSuccess = (
486
+ agents: AgentRoomInfo[],
487
+ paginationMeta?: {
488
+ total?: number;
489
+ offset?: number;
490
+ limit?: number;
491
+ hasMore?: boolean;
492
+ }
493
+ ) => {
429
494
  cleanup();
430
- resolve(agents);
495
+ if (isPaginated) {
496
+ resolve({
497
+ agents,
498
+ total: paginationMeta?.total ?? agents.length,
499
+ offset: paginationMeta?.offset ?? 0,
500
+ limit: paginationMeta?.limit ?? agents.length,
501
+ hasMore: paginationMeta?.hasMore ?? false
502
+ });
503
+ } else {
504
+ resolve(agents);
505
+ }
431
506
  };
432
507
 
433
508
  const onError = (error: Error) => {
@@ -461,17 +536,29 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
461
536
  *
462
537
  * @example
463
538
  * ```typescript
464
- * const agents = sdk.getRoomAgents('room-123');
539
+ * const agents = sdk.getCachedRoomAgents('room-123');
465
540
  * if (agents) {
466
541
  * console.log(`Found ${agents.length} agents in cache`);
467
542
  * }
468
543
  * ```
469
544
  */
470
- public getRoomAgents(roomId: string): AgentRoomInfo[] | undefined {
545
+ public getCachedRoomAgents(roomId: string): AgentRoomInfo[] | undefined {
471
546
  const cached = this.roomAgentsCache.get(roomId);
472
547
  return cached ? cached.map((agent) => ({ ...agent })) : undefined;
473
548
  }
474
549
 
550
+ /**
551
+ * @deprecated Use getCachedRoomAgents() instead. This method returns cached data only.
552
+ *
553
+ * Gets agents currently in a room from cache (synchronous).
554
+ *
555
+ * @param roomId - Room ID to query
556
+ * @returns Array of agents or undefined if not cached
557
+ */
558
+ public getRoomAgents(roomId: string): AgentRoomInfo[] | undefined {
559
+ return this.getCachedRoomAgents(roomId);
560
+ }
561
+
475
562
  /**
476
563
  * Gets available agents for a room from cache (synchronous).
477
564
  * Returns undefined if not cached or cache expired.
@@ -481,17 +568,29 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
481
568
  *
482
569
  * @example
483
570
  * ```typescript
484
- * const available = sdk.getAvailableAgents('room-123');
571
+ * const available = sdk.getCachedAvailableAgents('room-123');
485
572
  * if (available) {
486
573
  * console.log(`${available.length} agents can be added`);
487
574
  * }
488
575
  * ```
489
576
  */
490
- public getAvailableAgents(roomId: string): AgentRoomInfo[] | undefined {
577
+ public getCachedAvailableAgents(roomId: string): AgentRoomInfo[] | undefined {
491
578
  const cached = this.availableAgentsCache.get(roomId);
492
579
  return cached ? cached.map((agent) => ({ ...agent })) : undefined;
493
580
  }
494
581
 
582
+ /**
583
+ * @deprecated Use getCachedAvailableAgents() instead. This method returns cached data only.
584
+ *
585
+ * Gets available agents for a room from cache (synchronous).
586
+ *
587
+ * @param roomId - Room ID to query
588
+ * @returns Array of available agents or undefined if not cached
589
+ */
590
+ public getAvailableAgents(roomId: string): AgentRoomInfo[] | undefined {
591
+ return this.getCachedAvailableAgents(roomId);
592
+ }
593
+
495
594
  /**
496
595
  * Checks if an agent is currently in a room (from cache).
497
596
  * Returns undefined if cache is invalid.
@@ -502,18 +601,36 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
502
601
  *
503
602
  * @example
504
603
  * ```typescript
505
- * const isInRoom = sdk.isAgentInRoom('room-123', 'agent-456');
506
- * if (isInRoom === true) {
604
+ * const inRoom = sdk.checkAgentInRoom('room-123', 'agent-456');
605
+ * if (inRoom === true) {
507
606
  * console.log('Agent is in this room');
607
+ * } else if (inRoom === false) {
608
+ * console.log('Agent is not in this room');
609
+ * } else {
610
+ * console.log('Cache unavailable - need to fetch');
508
611
  * }
509
612
  * ```
510
613
  */
511
- public isAgentInRoom(roomId: string, agentId: string): boolean | undefined {
512
- const agents = this.getRoomAgents(roomId);
614
+ public checkAgentInRoom(roomId: string, agentId: string): boolean | undefined {
615
+ const agents = this.getCachedRoomAgents(roomId);
513
616
  if (!agents) return undefined;
514
617
  return agents.some((agent) => agent.agent_id === agentId);
515
618
  }
516
619
 
620
+ /**
621
+ * @deprecated Use checkAgentInRoom() instead. The 'is*' naming convention implies boolean-only,
622
+ * but this method returns boolean | undefined to indicate cache validity.
623
+ *
624
+ * Checks if an agent is currently in a room (from cache).
625
+ *
626
+ * @param roomId - Room ID to check
627
+ * @param agentId - Agent ID to check
628
+ * @returns True if agent in room, false if not, undefined if cache invalid
629
+ */
630
+ public isAgentInRoom(roomId: string, agentId: string): boolean | undefined {
631
+ return this.checkAgentInRoom(roomId, agentId);
632
+ }
633
+
517
634
  /**
518
635
  * Gets the count of agents in a room (from cache).
519
636
  * Returns undefined if cache is invalid.
@@ -523,17 +640,29 @@ export class AgentRoomManager extends EventEmitter<SDKEvents> {
523
640
  *
524
641
  * @example
525
642
  * ```typescript
526
- * const count = sdk.getRoomAgentCount('room-123');
643
+ * const count = sdk.getCachedRoomAgentCount('room-123');
527
644
  * if (count !== undefined) {
528
645
  * console.log(`Room has ${count} agents`);
529
646
  * }
530
647
  * ```
531
648
  */
532
- public getRoomAgentCount(roomId: string): number | undefined {
533
- const agents = this.getRoomAgents(roomId);
649
+ public getCachedRoomAgentCount(roomId: string): number | undefined {
650
+ const agents = this.getCachedRoomAgents(roomId);
534
651
  return agents ? agents.length : undefined;
535
652
  }
536
653
 
654
+ /**
655
+ * @deprecated Use getCachedRoomAgentCount() instead. This method returns cached data only.
656
+ *
657
+ * Gets the count of agents in a room (from cache).
658
+ *
659
+ * @param roomId - Room ID to count agents for
660
+ * @returns Number of agents or undefined if cache invalid
661
+ */
662
+ public getRoomAgentCount(roomId: string): number | undefined {
663
+ return this.getCachedRoomAgentCount(roomId);
664
+ }
665
+
537
666
  // ============================================================================
538
667
  // CACHE MANAGEMENT (Public methods)
539
668
  // ============================================================================
@@ -6,7 +6,12 @@
6
6
  export { ConnectionManager } from "./connection-manager";
7
7
  export { RoomManager } from "./room-manager";
8
8
  export { RoomManagementManager } from "./room-management-manager";
9
- export { AgentRoomManager, type AgentRoomInfo } from "./agent-room-manager";
9
+ export {
10
+ AgentRoomManager,
11
+ type AgentRoomInfo,
12
+ type ListAvailableAgentsOptions,
13
+ type PaginatedAgentsResult
14
+ } from "./agent-room-manager";
10
15
  export { AgentRegistry } from "./agent-registry";
11
16
  export {
12
17
  MessageRouter,
@@ -29,7 +29,8 @@ import {
29
29
  AgentCommandContentSchema
30
30
  } from "../types/validation";
31
31
  import { waitForEvent } from "../utils/event-waiter";
32
- import { PaymentClient, buildX402ResourceUrl } from "../payments/payment-client";
32
+ import { PaymentClient, buildX402ResourceUrl, usdcToUnits } from "../payments/payment-client";
33
+ import { getDefaultNetwork, getNetwork } from "../payments/networks";
33
34
  import type { SecurePrivateKey } from "../utils/secure-private-key";
34
35
 
35
36
  export interface SendMessageOptions {
@@ -38,12 +39,26 @@ export interface SendMessageOptions {
38
39
  waitForResponse?: boolean;
39
40
  timeout?: number;
40
41
  format?: ResponseFormat | "raw" | "humanized";
42
+ network?: string; // Network name override (peaq, base, avalanche) (v2.3.0)
43
+ networkChainId?: number; // Chain ID override (v2.3.0)
41
44
  }
42
45
 
43
46
  export interface AgentCommand {
44
47
  agent: string;
45
48
  command: string;
46
49
  room: string;
50
+ network?: string | number; // Per-request network override (v2.3.0)
51
+ }
52
+
53
+ /**
54
+ * Settlement data from backend for x402x-router-settlement extension
55
+ */
56
+ export interface SettlementData {
57
+ settlementRouter: string;
58
+ salt: string;
59
+ facilitatorFee: string;
60
+ hook: string;
61
+ hookData: string;
47
62
  }
48
63
 
49
64
  /**
@@ -57,6 +72,10 @@ export interface QuoteResult {
57
72
  command: string;
58
73
  pricing: PricingInfo;
59
74
  expiresAt: Date;
75
+ /** Backend-provided settlement data for x402x-router-settlement */
76
+ settlement: SettlementData;
77
+ /** Per-request network override, carried from requestQuote to confirmQuote (v2.3.0) */
78
+ networkOverride?: string | number;
60
79
  }
61
80
 
62
81
  export interface MessageRouterConfig {
@@ -66,8 +85,9 @@ export interface MessageRouterConfig {
66
85
  maxPricePerRequest?: number;
67
86
  quoteTimeout?: number;
68
87
  wsUrl?: string;
69
- paymentNetwork?: string;
88
+ paymentNetwork?: string; // CAIP-2 format (e.g., "eip155:3338")
70
89
  paymentAsset?: string;
90
+ network?: string; // Network name (e.g., "peaq", "base", "avalanche")
71
91
  }
72
92
 
73
93
  export class MessageRouter extends EventEmitter<SDKEvents> {
@@ -85,8 +105,9 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
85
105
  private readonly maxPricePerRequest?: number;
86
106
  private readonly quoteTimeout: number;
87
107
  private readonly wsUrl: string;
88
- private readonly paymentNetwork: string;
108
+ private readonly paymentNetwork: string; // CAIP-2 format if set
89
109
  private readonly paymentAsset: string;
110
+ private readonly networkName: string; // Network name (peaq, base, avalanche)
90
111
 
91
112
  constructor(
92
113
  wsClient: WebSocketClient,
@@ -108,21 +129,61 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
108
129
  this.maxPricePerRequest = config.maxPricePerRequest;
109
130
  this.quoteTimeout = config.quoteTimeout ?? 30000;
110
131
  this.wsUrl = config.wsUrl ?? "";
111
- this.paymentNetwork = config.paymentNetwork ?? "eip155:3338";
112
- // USDC contract address on PEAQ network
113
- this.paymentAsset = config.paymentAsset ?? "0xbbA60da06c2c5424f03f7434542280FCAd453d10";
132
+
133
+ // Store config values - dynamic network resolution happens lazily in getPaymentNetwork/Asset()
134
+ // because networks are only initialized after connect() is called
135
+ this.paymentNetwork = config.paymentNetwork ?? "";
136
+ this.paymentAsset = config.paymentAsset ?? "";
137
+ this.networkName = config.network ?? "";
114
138
 
115
139
  this.setupEventForwarding();
116
140
  }
117
141
 
142
+ /**
143
+ * Gets the payment network CAIP-2 identifier, resolving from network name or default.
144
+ * Only call this after connect() has been called (networks initialized).
145
+ */
146
+ private getResolvedPaymentNetwork(networkOverride?: string | number): string {
147
+ // Priority: per-request override > paymentNetwork (CAIP-2) > networkName > default
148
+ if (networkOverride) {
149
+ const network = getNetwork(networkOverride);
150
+ return network.caip2;
151
+ }
152
+ if (this.paymentNetwork) {
153
+ return this.paymentNetwork;
154
+ }
155
+ if (this.networkName) {
156
+ const network = getNetwork(this.networkName);
157
+ return network.caip2;
158
+ }
159
+ const defaultNetwork = getDefaultNetwork();
160
+ return defaultNetwork.caip2;
161
+ }
162
+
163
+ /**
164
+ * Gets the payment asset, resolving from network name or default.
165
+ * Only call this after connect() has been called (networks initialized).
166
+ */
167
+ private getResolvedPaymentAsset(): string {
168
+ if (this.paymentAsset) {
169
+ return this.paymentAsset;
170
+ }
171
+ if (this.networkName) {
172
+ const network = getNetwork(this.networkName);
173
+ return network.usdcContract;
174
+ }
175
+ const defaultNetwork = getDefaultNetwork();
176
+ return defaultNetwork.usdcContract;
177
+ }
178
+
118
179
  /**
119
180
  * Sets up the payment client for quote-approve flow.
120
181
  * Must be called before using requestQuote/confirmQuote with paid tasks.
121
182
  */
122
183
  public setPaymentClient(secureKey: SecurePrivateKey, walletAddress: string): void {
123
184
  this.paymentClient = new PaymentClient(secureKey, walletAddress, {
124
- network: this.paymentNetwork,
125
- asset: this.paymentAsset
185
+ network: this.getResolvedPaymentNetwork(),
186
+ asset: this.getResolvedPaymentAsset()
126
187
  });
127
188
  }
128
189
 
@@ -146,11 +207,11 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
146
207
  * @example
147
208
  * ```typescript
148
209
  * // Fire and forget
149
- * await messageRouter.sendMessage('What is the weather?', { room: 'general' });
210
+ * await messageRouter.sendMessage('What is the weather?', { room: 'room-id' });
150
211
  *
151
212
  * // Wait for response
152
213
  * const response = await messageRouter.sendMessage('Calculate 2+2', {
153
- * room: 'general',
214
+ * room: 'room-id',
154
215
  * waitForResponse: true,
155
216
  * timeout: 30000
156
217
  * });
@@ -173,11 +234,13 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
173
234
 
174
235
  // Use quote-approve flow with auto-approval (v2.2.0)
175
236
  if (this.autoApproveQuotes) {
237
+ const networkOverride = options.network || options.networkChainId;
176
238
  this.logger.debug("MessageRouter: Using quote-approve flow", {
177
239
  content: validatedContent,
178
- room
240
+ room,
241
+ network: networkOverride
179
242
  });
180
- const quote = await this.requestQuote(validatedContent, room);
243
+ const quote = await this.requestQuote(validatedContent, room, networkOverride);
181
244
  return await this.confirmQuote(quote.taskId, {
182
245
  waitForResponse: options.waitForResponse,
183
246
  timeout: options.timeout ?? this.messageTimeout
@@ -211,17 +274,28 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
211
274
  * @param command.agent - Agent ID or name to send command to
212
275
  * @param command.command - Command text to send
213
276
  * @param command.room - Room to send in (required)
214
- * @returns Promise that resolves when command is sent
277
+ * @param command.network - Optional per-request network override (name like "base" or chain ID like 8453)
278
+ * @param waitForResponse - Whether to wait for agent response (default: false)
279
+ * @returns Promise resolving to FormattedResponse if waiting, void otherwise
215
280
  * @throws {SDKError} If not connected
216
281
  * @throws {ValidationError} If agent/command empty or room not specified
217
282
  *
218
283
  * @example
219
284
  * ```typescript
285
+ * // Basic usage
220
286
  * await messageRouter.sendDirectCommand({
221
287
  * agent: 'weather-agent',
222
288
  * command: 'Get forecast for Tokyo',
223
- * room: 'general'
289
+ * room: 'room-id'
224
290
  * });
291
+ *
292
+ * // With per-request network override
293
+ * await messageRouter.sendDirectCommand({
294
+ * agent: 'x-agent-enterprise-v2',
295
+ * command: 'user @elonmusk',
296
+ * room: 'room-id',
297
+ * network: 'base'
298
+ * }, true);
225
299
  * ```
226
300
  */
227
301
  public async sendDirectCommand(
@@ -244,8 +318,8 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
244
318
 
245
319
  // Use quote-approve flow with auto-approval (v2.2.0)
246
320
  if (this.autoApproveQuotes) {
247
- this.logger.debug("MessageRouter: Using quote-approve flow", { content, room });
248
- const quote = await this.requestQuote(content, room);
321
+ this.logger.debug("MessageRouter: Using quote-approve flow", { content, room, network: command.network });
322
+ const quote = await this.requestQuote(content, room, command.network);
249
323
  return await this.confirmQuote(quote.taskId, {
250
324
  waitForResponse,
251
325
  timeout: this.messageTimeout
@@ -284,13 +358,15 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
284
358
  * Requests a quote for a task without auto-approval.
285
359
  * Returns the quote data for manual confirmation.
286
360
  */
287
- public async requestQuote(content: string, room: string): Promise<QuoteResult> {
361
+ public async requestQuote(content: string, room: string, networkOverride?: string | number): Promise<QuoteResult> {
288
362
  if (!this.wsClient.isConnected) {
289
363
  throw new SDKError("Not connected to Teneo network", ErrorCode.NOT_CONNECTED);
290
364
  }
291
365
 
292
- const message = createRequestTask(content, room);
293
- this.logger.debug("MessageRouter: Requesting quote", { content, room });
366
+ // Include payment network in request so backend returns correct contract addresses
367
+ const resolvedNetwork = this.getResolvedPaymentNetwork(networkOverride);
368
+ const message = createRequestTask(content, room, resolvedNetwork);
369
+ this.logger.debug("MessageRouter: Requesting quote", { content, room, network: resolvedNetwork });
294
370
 
295
371
  await this.wsClient.sendMessage(message);
296
372
 
@@ -306,9 +382,25 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
306
382
  agentWallet: quote.data.agent_wallet,
307
383
  command: quote.data.command,
308
384
  pricing: quote.data.pricing,
309
- expiresAt: new Date(quote.data.expires_at)
385
+ expiresAt: new Date(quote.data.expires_at),
386
+ // Backend-provided settlement data for x402x-router-settlement
387
+ settlement: {
388
+ settlementRouter: quote.data.settlement_router,
389
+ salt: quote.data.salt,
390
+ facilitatorFee: quote.data.facilitator_fee,
391
+ hook: quote.data.hook,
392
+ hookData: quote.data.hook_data ?? "0x"
393
+ },
394
+ networkOverride
310
395
  };
311
396
 
397
+ this.logger.debug("MessageRouter: Quote received with settlement data", {
398
+ taskId: result.taskId,
399
+ settlementRouter: result.settlement.settlementRouter,
400
+ salt: result.settlement.salt?.substring(0, 20) + "...",
401
+ hook: result.settlement.hook
402
+ });
403
+
312
404
  this.pendingQuotes.set(result.taskId, result);
313
405
  return result;
314
406
  }
@@ -335,9 +427,9 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
335
427
  throw new SDKError("Quote has expired", ErrorCode.QUOTE_EXPIRED);
336
428
  }
337
429
 
338
- // Check price limit
430
+ // Check price limit (pricePerUnit is in USDC, convert to micro-units)
431
+ const priceInUnits = usdcToUnits(quote.pricing.pricePerUnit);
339
432
  if (this.maxPricePerRequest !== undefined) {
340
- const priceInUnits = quote.pricing.pricePerUnit * 1_000_000;
341
433
  if (priceInUnits > this.maxPricePerRequest) {
342
434
  this.emit("payment:blocked", {
343
435
  agentId: quote.agentId,
@@ -357,14 +449,17 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
357
449
  // Create payment header if payment client is configured and price > 0
358
450
  if (this.paymentClient && quote.pricing.pricePerUnit > 0) {
359
451
  try {
452
+ // Pass backend-provided settlement data to payment header creation
360
453
  paymentHeader = await this.paymentClient.createPaymentHeader(
361
- quote.pricing.pricePerUnit * 1_000_000,
454
+ priceInUnits,
362
455
  quote.agentWallet,
363
- buildX402ResourceUrl(this.wsUrl)
456
+ buildX402ResourceUrl(this.wsUrl),
457
+ quote.networkOverride, // Per-request network override (v2.3.0)
458
+ quote.settlement // Backend-provided settlement data
364
459
  );
365
460
  this.emit("payment:attached", {
366
461
  agentId: quote.agentId,
367
- amount: quote.pricing.pricePerUnit * 1_000_000,
462
+ amount: priceInUnits,
368
463
  command: quote.command
369
464
  });
370
465
  } catch (error) {
@@ -452,12 +547,12 @@ export class MessageRouter extends EventEmitter<SDKEvents> {
452
547
  }
453
548
 
454
549
  // Fallback: If server doesn't support client_request_id,
455
- // match the first response from the expected room within 60 seconds
550
+ // match the first response from the expected room within the time window
456
551
  // This handles servers that don't echo back client_request_id
457
552
  const timeSinceRequest = Date.now() - requestTimestamp;
458
553
  const responseRoom = r.raw?.room;
459
554
  const isFromExpectedRoom = responseRoom === message.room;
460
- const isWithinTimeWindow = timeSinceRequest < 60000; // 60 second window
555
+ const isWithinTimeWindow = timeSinceRequest < TIMEOUTS.RESPONSE_MATCH_WINDOW;
461
556
 
462
557
  if (isFromExpectedRoom && isWithinTimeWindow && !responseRequestId) {
463
558
  this.logger.debug("Matching response without client_request_id (server fallback)", {