@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
@@ -0,0 +1,388 @@
1
+ /**
2
+ * Unit tests for AgentErrorHandler
3
+ * Tests response handling for agent failure notifications
4
+ */
5
+
6
+ import { describe, it, expect, beforeEach, vi } from "vitest";
7
+ import { AgentErrorHandler } from "../../../src/handlers/message-handlers/agent-error-handler";
8
+ import { HandlerContext } from "../../../src/handlers/message-handlers/types";
9
+ import { Logger } from "../../../src/types";
10
+
11
+ describe("AgentErrorHandler", () => {
12
+ let handler: AgentErrorHandler;
13
+ let mockContext: HandlerContext;
14
+ let mockLogger: Logger;
15
+ let emitSpy: ReturnType<typeof vi.fn>;
16
+ let sendWebhookSpy: ReturnType<typeof vi.fn>;
17
+
18
+ beforeEach(() => {
19
+ // Create mock logger
20
+ mockLogger = {
21
+ debug: vi.fn(),
22
+ info: vi.fn(),
23
+ warn: vi.fn(),
24
+ error: vi.fn()
25
+ };
26
+
27
+ // Create spies
28
+ emitSpy = vi.fn();
29
+ sendWebhookSpy = vi.fn().mockResolvedValue(undefined);
30
+
31
+ // Create mock context
32
+ mockContext = {
33
+ emit: emitSpy,
34
+ sendWebhook: sendWebhookSpy,
35
+ logger: mockLogger,
36
+ getConnectionState: vi.fn(),
37
+ getAuthState: vi.fn(),
38
+ updateConnectionState: vi.fn(),
39
+ updateAuthState: vi.fn(),
40
+ sendMessage: vi.fn()
41
+ };
42
+
43
+ // Create handler instance
44
+ handler = new AgentErrorHandler();
45
+ });
46
+
47
+ describe("Handler Metadata", () => {
48
+ it("should have correct type", () => {
49
+ expect(handler.type).toBe("agent_error");
50
+ });
51
+
52
+ it("should have schema defined", () => {
53
+ expect(handler.schema).toBeDefined();
54
+ });
55
+
56
+ it("should identify messages it can handle", () => {
57
+ const message = { type: "agent_error", data: {} };
58
+ expect(handler.canHandle(message as any)).toBe(true);
59
+ });
60
+
61
+ it("should not handle other message types", () => {
62
+ const message = { type: "other_type", data: {} };
63
+ expect(handler.canHandle(message as any)).toBe(false);
64
+ });
65
+ });
66
+
67
+ describe("Response Handling", () => {
68
+ it("should handle message with all fields", async () => {
69
+ const message = {
70
+ type: "agent_error" as const,
71
+ content: "Agent failed to process request",
72
+ from: "weather-agent",
73
+ data: {
74
+ task_id: "task-123",
75
+ client_request_id: "req-456"
76
+ },
77
+ room: "room-789"
78
+ };
79
+
80
+ await handler.handle(message, mockContext);
81
+
82
+ // Should emit event with correct shape
83
+ expect(emitSpy).toHaveBeenCalledWith("agent:error", {
84
+ agentName: "weather-agent",
85
+ content: "Agent failed to process request",
86
+ taskId: "task-123",
87
+ clientRequestId: "req-456",
88
+ room: "room-789"
89
+ });
90
+
91
+ // Should send webhook with correct data
92
+ expect(sendWebhookSpy).toHaveBeenCalledWith(
93
+ "agent_error",
94
+ expect.objectContaining({
95
+ agentName: "weather-agent",
96
+ content: "Agent failed to process request",
97
+ taskId: "task-123",
98
+ clientRequestId: "req-456",
99
+ room: "room-789"
100
+ }),
101
+ undefined
102
+ );
103
+ });
104
+
105
+ it("should handle message with minimal fields", async () => {
106
+ const message = {
107
+ type: "agent_error" as const
108
+ };
109
+
110
+ await handler.handle(message, mockContext);
111
+
112
+ // Should emit event with undefined optional fields
113
+ expect(emitSpy).toHaveBeenCalledWith("agent:error", {
114
+ agentName: undefined,
115
+ content: undefined,
116
+ taskId: undefined,
117
+ clientRequestId: undefined,
118
+ room: undefined
119
+ });
120
+ });
121
+
122
+ it("should handle missing optional data fields", async () => {
123
+ const message = {
124
+ type: "agent_error" as const,
125
+ content: "Something went wrong",
126
+ from: "search-agent"
127
+ };
128
+
129
+ await handler.handle(message, mockContext);
130
+
131
+ // Should emit event with undefined data-derived fields
132
+ expect(emitSpy).toHaveBeenCalledWith("agent:error", {
133
+ agentName: "search-agent",
134
+ content: "Something went wrong",
135
+ taskId: undefined,
136
+ clientRequestId: undefined,
137
+ room: undefined
138
+ });
139
+ });
140
+
141
+ it("should handle message with data but no task_id or client_request_id", async () => {
142
+ const message = {
143
+ type: "agent_error" as const,
144
+ content: "Timeout error",
145
+ from: "code-agent",
146
+ data: {},
147
+ room: "room-abc"
148
+ };
149
+
150
+ await handler.handle(message, mockContext);
151
+
152
+ expect(emitSpy).toHaveBeenCalledWith("agent:error", {
153
+ agentName: "code-agent",
154
+ content: "Timeout error",
155
+ taskId: undefined,
156
+ clientRequestId: undefined,
157
+ room: "room-abc"
158
+ });
159
+ });
160
+ });
161
+
162
+ describe("Event Emission", () => {
163
+ it("should emit agent:error with correct shape", async () => {
164
+ const message = {
165
+ type: "agent_error" as const,
166
+ content: "Internal agent failure",
167
+ from: "translate-agent",
168
+ data: {
169
+ task_id: "task-abc",
170
+ client_request_id: "req-def"
171
+ },
172
+ room: "room-ghi"
173
+ };
174
+
175
+ await handler.handle(message, mockContext);
176
+
177
+ expect(emitSpy).toHaveBeenCalledTimes(1);
178
+ expect(emitSpy).toHaveBeenCalledWith("agent:error", {
179
+ agentName: "translate-agent",
180
+ content: "Internal agent failure",
181
+ taskId: "task-abc",
182
+ clientRequestId: "req-def",
183
+ room: "room-ghi"
184
+ });
185
+ });
186
+
187
+ it("should emit event before webhook is sent", async () => {
188
+ const callOrder: string[] = [];
189
+ emitSpy.mockImplementation(() => callOrder.push("emit"));
190
+ sendWebhookSpy.mockImplementation(() => {
191
+ callOrder.push("webhook");
192
+ return Promise.resolve(undefined);
193
+ });
194
+
195
+ const message = {
196
+ type: "agent_error" as const,
197
+ content: "Error",
198
+ from: "agent-x"
199
+ };
200
+
201
+ await handler.handle(message, mockContext);
202
+
203
+ expect(callOrder[0]).toBe("emit");
204
+ });
205
+ });
206
+
207
+ describe("Webhook", () => {
208
+ it("should send webhook with correct data", async () => {
209
+ const message = {
210
+ type: "agent_error" as const,
211
+ content: "Agent crashed",
212
+ from: "math-agent",
213
+ data: {
214
+ task_id: "task-w1",
215
+ client_request_id: "req-w2"
216
+ },
217
+ room: "room-w3"
218
+ };
219
+
220
+ await handler.handle(message, mockContext);
221
+
222
+ expect(sendWebhookSpy).toHaveBeenCalledWith(
223
+ "agent_error",
224
+ {
225
+ agentName: "math-agent",
226
+ content: "Agent crashed",
227
+ taskId: "task-w1",
228
+ clientRequestId: "req-w2",
229
+ room: "room-w3"
230
+ },
231
+ undefined
232
+ );
233
+ });
234
+
235
+ it("should handle webhook failure gracefully", async () => {
236
+ const webhookError = new Error("Webhook failed");
237
+ sendWebhookSpy.mockRejectedValueOnce(webhookError);
238
+
239
+ const message = {
240
+ type: "agent_error" as const,
241
+ content: "Agent error occurred",
242
+ from: "data-agent",
243
+ data: {
244
+ task_id: "task-fail"
245
+ }
246
+ };
247
+
248
+ // Should not throw
249
+ await handler.handle(message, mockContext);
250
+
251
+ // Should still emit event
252
+ expect(emitSpy).toHaveBeenCalledWith(
253
+ "agent:error",
254
+ expect.objectContaining({
255
+ agentName: "data-agent",
256
+ content: "Agent error occurred",
257
+ taskId: "task-fail"
258
+ })
259
+ );
260
+ });
261
+ });
262
+
263
+ describe("Message Validation", () => {
264
+ it("should handle invalid message structure", async () => {
265
+ const invalidMessage = {
266
+ type: "agent_error",
267
+ data: {
268
+ task_id: 12345 // Should be string
269
+ }
270
+ } as any;
271
+
272
+ await handler.handle(invalidMessage, mockContext);
273
+
274
+ // Should log validation warning at debug level (resilience pattern)
275
+ expect(mockLogger.debug).toHaveBeenCalledWith(
276
+ expect.stringContaining("agent_error message validation warning"),
277
+ expect.any(Object)
278
+ );
279
+
280
+ // Handler processes the message resiliently (uses optional chaining)
281
+ // So it logs "Agent error received" at warn level
282
+ expect(mockLogger.warn).toHaveBeenCalledWith(
283
+ "Agent error received",
284
+ expect.objectContaining({
285
+ taskId: 12345
286
+ })
287
+ );
288
+ });
289
+
290
+ it("should accept valid message with extra fields (passthrough)", async () => {
291
+ const message = {
292
+ type: "agent_error" as const,
293
+ content: "Error with extras",
294
+ from: "extra-agent",
295
+ data: {
296
+ task_id: "task-extra",
297
+ client_request_id: "req-extra",
298
+ some_extra_field: "should be ignored"
299
+ },
300
+ room: "room-extra",
301
+ unknown_field: "also ignored"
302
+ };
303
+
304
+ // Should not throw
305
+ await handler.handle(message, mockContext);
306
+
307
+ expect(emitSpy).toHaveBeenCalledWith(
308
+ "agent:error",
309
+ expect.objectContaining({
310
+ agentName: "extra-agent",
311
+ content: "Error with extras"
312
+ })
313
+ );
314
+ });
315
+ });
316
+
317
+ describe("Debug Logging", () => {
318
+ it("should log at debug level", async () => {
319
+ const message = {
320
+ type: "agent_error" as const,
321
+ content: "Debug test error",
322
+ from: "debug-agent",
323
+ data: {
324
+ task_id: "task-dbg"
325
+ }
326
+ };
327
+
328
+ await handler.handle(message, mockContext);
329
+
330
+ expect(mockLogger.debug).toHaveBeenCalledWith(
331
+ "Handling agent_error",
332
+ expect.objectContaining({
333
+ from: "debug-agent",
334
+ taskId: "task-dbg",
335
+ content: "Debug test error"
336
+ })
337
+ );
338
+ });
339
+
340
+ it("should log at warn level", async () => {
341
+ const message = {
342
+ type: "agent_error" as const,
343
+ content: "Warn test error",
344
+ from: "warn-agent",
345
+ data: {
346
+ task_id: "task-wrn"
347
+ }
348
+ };
349
+
350
+ await handler.handle(message, mockContext);
351
+
352
+ expect(mockLogger.warn).toHaveBeenCalledWith(
353
+ "Agent error received",
354
+ expect.objectContaining({
355
+ agentName: "warn-agent",
356
+ content: "Warn test error",
357
+ taskId: "task-wrn"
358
+ })
359
+ );
360
+ });
361
+
362
+ it("should log with undefined fields when data is missing", async () => {
363
+ const message = {
364
+ type: "agent_error" as const
365
+ };
366
+
367
+ await handler.handle(message, mockContext);
368
+
369
+ expect(mockLogger.debug).toHaveBeenCalledWith(
370
+ "Handling agent_error",
371
+ expect.objectContaining({
372
+ from: undefined,
373
+ taskId: undefined,
374
+ content: undefined
375
+ })
376
+ );
377
+
378
+ expect(mockLogger.warn).toHaveBeenCalledWith(
379
+ "Agent error received",
380
+ expect.objectContaining({
381
+ agentName: undefined,
382
+ content: undefined,
383
+ taskId: undefined
384
+ })
385
+ );
386
+ });
387
+ });
388
+ });
@@ -306,14 +306,17 @@ describe("AgentRoomOperationResponseHandler", () => {
306
306
 
307
307
  await handler.handle(invalidMessage, mockContext);
308
308
 
309
- // Should log error
310
- expect(mockLogger.error).toHaveBeenCalledWith(
311
- expect.stringContaining("Error handling agent_room_operation_response"),
312
- expect.any(Error)
309
+ // Should log validation warning at debug level (resilience pattern)
310
+ expect(mockLogger.debug).toHaveBeenCalledWith(
311
+ expect.stringContaining("agent_room_operation_response message validation warning"),
312
+ expect.any(Object)
313
313
  );
314
314
 
315
- // Should emit message:error event
316
- expect(emitSpy).toHaveBeenCalledWith("message:error", expect.any(Error), invalidMessage);
315
+ // Should log handler processing failure at warn level
316
+ expect(mockLogger.warn).toHaveBeenCalledWith(
317
+ expect.stringContaining("Handler agent_room_operation_response failed to process message"),
318
+ expect.any(Object)
319
+ );
317
320
  });
318
321
 
319
322
  it("should accept valid message with extra fields", async () => {
@@ -99,16 +99,8 @@ describe("AgentStatusUpdateHandler", () => {
99
99
  agent: undefined
100
100
  });
101
101
 
102
- // Should send webhook
103
- expect(sendWebhookSpy).toHaveBeenCalledWith(
104
- "agent_status_update",
105
- expect.objectContaining({
106
- room_id: "room-123",
107
- agent_id: "agent-456",
108
- status: "offline"
109
- }),
110
- undefined
111
- );
102
+ // Should NOT send webhook (deliberately disabled to avoid spam)
103
+ expect(sendWebhookSpy).not.toHaveBeenCalled();
112
104
 
113
105
  // Should log
114
106
  expect(mockLogger.info).toHaveBeenCalledWith(
@@ -253,14 +245,17 @@ describe("AgentStatusUpdateHandler", () => {
253
245
 
254
246
  await handler.handle(invalidMessage, mockContext);
255
247
 
256
- // Should log error
257
- expect(mockLogger.error).toHaveBeenCalledWith(
258
- expect.stringContaining("Error handling agent_status_update"),
259
- expect.any(Error)
248
+ // Should log validation warning at debug level (resilience pattern)
249
+ expect(mockLogger.debug).toHaveBeenCalledWith(
250
+ expect.stringContaining("agent_status_update message validation warning"),
251
+ expect.any(Object)
260
252
  );
261
253
 
262
- // Should emit message:error event
263
- expect(emitSpy).toHaveBeenCalledWith("message:error", expect.any(Error), invalidMessage);
254
+ // Should log handler processing failure at warn level
255
+ expect(mockLogger.warn).toHaveBeenCalledWith(
256
+ expect.stringContaining("Handler agent_status_update failed to process message"),
257
+ expect.any(Object)
258
+ );
264
259
  });
265
260
 
266
261
  it("should accept valid message with extra fields", async () => {
@@ -83,14 +83,8 @@ describe("ListAvailableAgentsHandler", () => {
83
83
  // Should emit event
84
84
  expect(emitSpy).toHaveBeenCalledWith("agent_room:available_agents_listed", agents);
85
85
 
86
- // Should send webhook
87
- expect(sendWebhookSpy).toHaveBeenCalledWith(
88
- "available_agents_listed",
89
- expect.objectContaining({
90
- agents
91
- }),
92
- undefined
93
- );
86
+ // Should NOT send webhook (this is a query response)
87
+ expect(sendWebhookSpy).not.toHaveBeenCalled();
94
88
 
95
89
  // Should log
96
90
  expect(mockLogger.info).toHaveBeenCalledWith(
@@ -194,14 +188,17 @@ describe("ListAvailableAgentsHandler", () => {
194
188
 
195
189
  await handler.handle(invalidMessage, mockContext);
196
190
 
197
- // Should log error
198
- expect(mockLogger.error).toHaveBeenCalledWith(
199
- expect.stringContaining("Error handling available_agents_response"),
200
- expect.any(Error)
191
+ // Should log validation warning at debug level (resilience pattern)
192
+ expect(mockLogger.debug).toHaveBeenCalledWith(
193
+ expect.stringContaining("available_agents_response message validation warning"),
194
+ expect.any(Object)
201
195
  );
202
196
 
203
- // Should emit message:error event
204
- expect(emitSpy).toHaveBeenCalledWith("message:error", expect.any(Error), invalidMessage);
197
+ // Should log handler processing failure at warn level
198
+ expect(mockLogger.warn).toHaveBeenCalledWith(
199
+ expect.stringContaining("Handler available_agents_response failed to process message"),
200
+ expect.any(Object)
201
+ );
205
202
  });
206
203
 
207
204
  it("should accept valid message with extra fields", async () => {
@@ -94,15 +94,8 @@ describe("ListRoomAgentsHandler", () => {
94
94
  // Should emit event
95
95
  expect(emitSpy).toHaveBeenCalledWith("agent_room:agents_listed", "room-123", agents);
96
96
 
97
- // Should send webhook
98
- expect(sendWebhookSpy).toHaveBeenCalledWith(
99
- "room_agents_listed",
100
- expect.objectContaining({
101
- room_id: "room-123",
102
- agents
103
- }),
104
- undefined
105
- );
97
+ // Should NOT send webhook (this is a query response)
98
+ expect(sendWebhookSpy).not.toHaveBeenCalled();
106
99
 
107
100
  // Should log
108
101
  expect(mockLogger.info).toHaveBeenCalledWith(
@@ -233,14 +226,17 @@ describe("ListRoomAgentsHandler", () => {
233
226
 
234
227
  await handler.handle(invalidMessage, mockContext);
235
228
 
236
- // Should log error
237
- expect(mockLogger.error).toHaveBeenCalledWith(
238
- expect.stringContaining("Error handling room_agents_response"),
239
- expect.any(Error)
229
+ // Should log validation warning at debug level (resilience pattern)
230
+ expect(mockLogger.debug).toHaveBeenCalledWith(
231
+ expect.stringContaining("room_agents_response message validation warning"),
232
+ expect.any(Object)
240
233
  );
241
234
 
242
- // Should emit message:error event
243
- expect(emitSpy).toHaveBeenCalledWith("message:error", expect.any(Error), invalidMessage);
235
+ // Should log handler processing failure at warn level
236
+ expect(mockLogger.warn).toHaveBeenCalledWith(
237
+ expect.stringContaining("Handler room_agents_response failed to process message"),
238
+ expect.any(Object)
239
+ );
244
240
  });
245
241
 
246
242
  it("should accept valid message with extra fields", async () => {
@@ -414,14 +414,17 @@ describe("RoomOperationResponseHandler", () => {
414
414
 
415
415
  await handler.handle(invalidMessage, mockContext);
416
416
 
417
- // Should log error
418
- expect(mockLogger.error).toHaveBeenCalledWith(
419
- expect.stringContaining("Error handling room_operation_response"),
420
- expect.any(Error)
417
+ // Should log validation warning at debug level (resilience pattern)
418
+ expect(mockLogger.debug).toHaveBeenCalledWith(
419
+ expect.stringContaining("room_operation_response message validation warning"),
420
+ expect.any(Object)
421
421
  );
422
422
 
423
- // Should emit message:error event
424
- expect(emitSpy).toHaveBeenCalledWith("message:error", expect.any(Error), invalidMessage);
423
+ // Should log handler processing failure at warn level
424
+ expect(mockLogger.warn).toHaveBeenCalledWith(
425
+ expect.stringContaining("Handler room_operation_response failed to process message"),
426
+ expect.any(Object)
427
+ );
425
428
  });
426
429
 
427
430
  it("should accept valid message with extra fields", async () => {