@teneo-protocol/sdk 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/.github/workflows/publish-npm.yml +8 -6
  2. package/CHANGELOG.md +265 -0
  3. package/README.md +406 -53
  4. package/dist/core/websocket-client.d.ts +12 -0
  5. package/dist/core/websocket-client.d.ts.map +1 -1
  6. package/dist/core/websocket-client.js +22 -2
  7. package/dist/core/websocket-client.js.map +1 -1
  8. package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts +76 -0
  9. package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts.map +1 -0
  10. package/dist/handlers/message-handlers/agent-room-operation-response-handler.js +70 -0
  11. package/dist/handlers/message-handlers/agent-room-operation-response-handler.js.map +1 -0
  12. package/dist/handlers/message-handlers/agent-selected-handler.d.ts +92 -38
  13. package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -1
  14. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts +904 -0
  15. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts.map +1 -0
  16. package/dist/handlers/message-handlers/agent-status-update-handler.js +51 -0
  17. package/dist/handlers/message-handlers/agent-status-update-handler.js.map +1 -0
  18. package/dist/handlers/message-handlers/auth-error-handler.d.ts +45 -31
  19. package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -1
  20. package/dist/handlers/message-handlers/auth-message-handler.d.ts +6 -0
  21. package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -1
  22. package/dist/handlers/message-handlers/auth-message-handler.js +65 -5
  23. package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -1
  24. package/dist/handlers/message-handlers/auth-required-handler.d.ts +49 -31
  25. package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -1
  26. package/dist/handlers/message-handlers/auth-success-handler.d.ts +6 -0
  27. package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -1
  28. package/dist/handlers/message-handlers/auth-success-handler.js +46 -4
  29. package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -1
  30. package/dist/handlers/message-handlers/challenge-handler.d.ts +45 -31
  31. package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -1
  32. package/dist/handlers/message-handlers/error-message-handler.d.ts +49 -31
  33. package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -1
  34. package/dist/handlers/message-handlers/index.d.ts +5 -0
  35. package/dist/handlers/message-handlers/index.d.ts.map +1 -1
  36. package/dist/handlers/message-handlers/index.js +23 -1
  37. package/dist/handlers/message-handlers/index.js.map +1 -1
  38. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts +877 -0
  39. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts.map +1 -0
  40. package/dist/handlers/message-handlers/list-available-agents-handler.js +38 -0
  41. package/dist/handlers/message-handlers/list-available-agents-handler.js.map +1 -0
  42. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts +886 -0
  43. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts.map +1 -0
  44. package/dist/handlers/message-handlers/list-room-agents-handler.js +51 -0
  45. package/dist/handlers/message-handlers/list-room-agents-handler.js.map +1 -0
  46. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts +178 -89
  47. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -1
  48. package/dist/handlers/message-handlers/ping-pong-handler.d.ts +62 -58
  49. package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -1
  50. package/dist/handlers/message-handlers/regular-message-handler.d.ts +31 -29
  51. package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -1
  52. package/dist/handlers/message-handlers/room-operation-response-handler.d.ts +328 -0
  53. package/dist/handlers/message-handlers/room-operation-response-handler.d.ts.map +1 -0
  54. package/dist/handlers/message-handlers/room-operation-response-handler.js +92 -0
  55. package/dist/handlers/message-handlers/room-operation-response-handler.js.map +1 -0
  56. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +53 -31
  57. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
  58. package/dist/handlers/message-handlers/types.d.ts +2 -0
  59. package/dist/handlers/message-handlers/types.d.ts.map +1 -1
  60. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +53 -31
  61. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
  62. package/dist/managers/agent-room-manager.d.ts +222 -0
  63. package/dist/managers/agent-room-manager.d.ts.map +1 -0
  64. package/dist/managers/agent-room-manager.js +508 -0
  65. package/dist/managers/agent-room-manager.js.map +1 -0
  66. package/dist/managers/index.d.ts +2 -0
  67. package/dist/managers/index.d.ts.map +1 -1
  68. package/dist/managers/index.js +5 -1
  69. package/dist/managers/index.js.map +1 -1
  70. package/dist/managers/room-management-manager.d.ts +213 -0
  71. package/dist/managers/room-management-manager.d.ts.map +1 -0
  72. package/dist/managers/room-management-manager.js +440 -0
  73. package/dist/managers/room-management-manager.js.map +1 -0
  74. package/dist/managers/room-manager.d.ts +4 -4
  75. package/dist/managers/room-manager.d.ts.map +1 -1
  76. package/dist/managers/room-manager.js.map +1 -1
  77. package/dist/teneo-sdk.d.ts +333 -13
  78. package/dist/teneo-sdk.d.ts.map +1 -1
  79. package/dist/teneo-sdk.js +468 -1
  80. package/dist/teneo-sdk.js.map +1 -1
  81. package/dist/types/config.d.ts +63 -54
  82. package/dist/types/config.d.ts.map +1 -1
  83. package/dist/types/config.js +8 -4
  84. package/dist/types/config.js.map +1 -1
  85. package/dist/types/error-codes.d.ts +2 -0
  86. package/dist/types/error-codes.d.ts.map +1 -1
  87. package/dist/types/error-codes.js +3 -0
  88. package/dist/types/error-codes.js.map +1 -1
  89. package/dist/types/events.d.ts +132 -68
  90. package/dist/types/events.d.ts.map +1 -1
  91. package/dist/types/events.js.map +1 -1
  92. package/dist/types/index.d.ts +1 -1
  93. package/dist/types/index.d.ts.map +1 -1
  94. package/dist/types/index.js +27 -2
  95. package/dist/types/index.js.map +1 -1
  96. package/dist/types/messages.d.ts +11396 -2559
  97. package/dist/types/messages.d.ts.map +1 -1
  98. package/dist/types/messages.js +294 -27
  99. package/dist/types/messages.js.map +1 -1
  100. package/examples/.env.example +1 -1
  101. package/examples/agent-room-management-example.ts +334 -0
  102. package/examples/claude-agent-x-follower/.env.example +2 -2
  103. package/examples/claude-agent-x-follower/QUICKSTART.md +1 -1
  104. package/examples/claude-agent-x-follower/README.md +1 -1
  105. package/examples/n8n-teneo/.env.example +2 -2
  106. package/examples/n8n-teneo/README.md +1 -1
  107. package/examples/openai-teneo/.env.example +2 -2
  108. package/examples/openai-teneo/README.md +1 -1
  109. package/examples/production-dashboard/.env.example +2 -2
  110. package/examples/production-dashboard/README.md +89 -12
  111. package/examples/production-dashboard/public/dashboard.html +1173 -601
  112. package/examples/production-dashboard/server.ts +347 -5
  113. package/examples/room-management-example.ts +285 -0
  114. package/examples/usage/.env.example +1 -1
  115. package/examples/usage/01-connect.ts +1 -1
  116. package/examples/usage/02-list-agents.ts +1 -1
  117. package/examples/usage/03-pick-agent.ts +1 -1
  118. package/examples/usage/04-find-by-capability.ts +1 -1
  119. package/examples/usage/05-webhook-example.ts +1 -1
  120. package/examples/usage/06-simple-api-server.ts +1 -1
  121. package/examples/usage/07-event-listener.ts +1 -1
  122. package/examples/usage/README.md +1 -1
  123. package/package.json +9 -1
  124. package/src/core/websocket-client.ts +26 -2
  125. package/src/handlers/message-handlers/agent-room-operation-response-handler.ts +83 -0
  126. package/src/handlers/message-handlers/agent-status-update-handler.ts +58 -0
  127. package/src/handlers/message-handlers/auth-message-handler.ts +73 -5
  128. package/src/handlers/message-handlers/auth-success-handler.ts +58 -6
  129. package/src/handlers/message-handlers/index.ts +19 -0
  130. package/src/handlers/message-handlers/list-available-agents-handler.ts +41 -0
  131. package/src/handlers/message-handlers/list-room-agents-handler.ts +61 -0
  132. package/src/handlers/message-handlers/room-operation-response-handler.ts +105 -0
  133. package/src/handlers/message-handlers/types.ts +6 -0
  134. package/src/managers/agent-room-manager.ts +609 -0
  135. package/src/managers/index.ts +2 -0
  136. package/src/managers/room-management-manager.ts +523 -0
  137. package/src/managers/room-manager.ts +4 -5
  138. package/src/teneo-sdk.ts +505 -4
  139. package/src/types/config.ts +10 -5
  140. package/src/types/error-codes.ts +4 -0
  141. package/src/types/events.ts +24 -0
  142. package/src/types/index.ts +55 -0
  143. package/src/types/messages.ts +374 -41
  144. package/tests/integration/room-management.test.ts +514 -0
  145. package/tests/integration/websocket.test.ts +1 -1
  146. package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +394 -0
  147. package/tests/unit/handlers/agent-status-update-handler.test.ts +407 -0
  148. package/tests/unit/handlers/auth-success-handler-rooms.test.ts +699 -0
  149. package/tests/unit/handlers/list-available-agents-handler.test.ts +256 -0
  150. package/tests/unit/handlers/list-room-agents-handler.test.ts +294 -0
  151. package/tests/unit/handlers/room-operation-response-handler.test.ts +527 -0
  152. package/tests/unit/managers/agent-room-manager.test.ts +534 -0
  153. package/tests/unit/managers/room-management-manager.test.ts +438 -0
@@ -0,0 +1,407 @@
1
+ /**
2
+ * Unit tests for AgentStatusUpdateHandler
3
+ * Tests real-time agent status update handling and cache invalidation
4
+ */
5
+
6
+ import { describe, it, expect, beforeEach, vi } from "vitest";
7
+ import { AgentStatusUpdateHandler } from "../../../src/handlers/message-handlers/agent-status-update-handler";
8
+ import { HandlerContext } from "../../../src/handlers/message-handlers/types";
9
+ import { Logger } from "../../../src/types";
10
+
11
+ describe("AgentStatusUpdateHandler", () => {
12
+ let handler: AgentStatusUpdateHandler;
13
+ let mockContext: HandlerContext;
14
+ let mockLogger: Logger;
15
+ let mockAgentRoomManager: any;
16
+ let emitSpy: ReturnType<typeof vi.fn>;
17
+ let sendWebhookSpy: ReturnType<typeof vi.fn>;
18
+
19
+ beforeEach(() => {
20
+ // Create mock logger
21
+ mockLogger = {
22
+ debug: vi.fn(),
23
+ info: vi.fn(),
24
+ warn: vi.fn(),
25
+ error: vi.fn()
26
+ };
27
+
28
+ // Create mock agent room manager
29
+ mockAgentRoomManager = {
30
+ handleStatusUpdate: vi.fn()
31
+ };
32
+
33
+ // Create spies
34
+ emitSpy = vi.fn();
35
+ sendWebhookSpy = vi.fn().mockResolvedValue(undefined);
36
+
37
+ // Create mock context
38
+ mockContext = {
39
+ emit: emitSpy,
40
+ sendWebhook: sendWebhookSpy,
41
+ logger: mockLogger,
42
+ getConnectionState: vi.fn(),
43
+ getAuthState: vi.fn(),
44
+ updateConnectionState: vi.fn(),
45
+ updateAuthState: vi.fn(),
46
+ sendMessage: vi.fn(),
47
+ agentRoomManager: mockAgentRoomManager
48
+ } as any;
49
+
50
+ // Create handler instance
51
+ handler = new AgentStatusUpdateHandler();
52
+ });
53
+
54
+ describe("Handler Metadata", () => {
55
+ it("should have correct type", () => {
56
+ expect(handler.type).toBe("agent_status_update");
57
+ });
58
+
59
+ it("should have schema defined", () => {
60
+ expect(handler.schema).toBeDefined();
61
+ });
62
+
63
+ it("should identify messages it can handle", () => {
64
+ const message = { type: "agent_status_update", data: {} };
65
+ expect(handler.canHandle(message as any)).toBe(true);
66
+ });
67
+
68
+ it("should not handle other message types", () => {
69
+ const message = { type: "other_type", data: {} };
70
+ expect(handler.canHandle(message as any)).toBe(false);
71
+ });
72
+ });
73
+
74
+ describe("Status Update Handling", () => {
75
+ it("should handle agent status update", async () => {
76
+ const message = {
77
+ type: "agent_status_update" as const,
78
+ data: {
79
+ room_id: "room-123",
80
+ agent_id: "agent-456",
81
+ status: "offline"
82
+ }
83
+ };
84
+
85
+ await handler.handle(message, mockContext);
86
+
87
+ // Should invalidate cache via agent room manager
88
+ expect(mockAgentRoomManager.handleStatusUpdate).toHaveBeenCalledWith(
89
+ "room-123",
90
+ "agent-456",
91
+ "offline"
92
+ );
93
+
94
+ // Should emit event
95
+ expect(emitSpy).toHaveBeenCalledWith("agent_room:status_update", {
96
+ roomId: "room-123",
97
+ agentId: "agent-456",
98
+ status: "offline",
99
+ agent: undefined
100
+ });
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
+ );
112
+
113
+ // Should log
114
+ expect(mockLogger.info).toHaveBeenCalledWith(
115
+ "Agent status updated",
116
+ expect.objectContaining({
117
+ roomId: "room-123",
118
+ agentId: "agent-456",
119
+ status: "offline"
120
+ })
121
+ );
122
+ });
123
+
124
+ it("should handle status update with agent details", async () => {
125
+ const agentDetails = {
126
+ agent_id: "agent-456",
127
+ agent_name: "Weather Agent",
128
+ description: "Provides weather info",
129
+ status: "online"
130
+ };
131
+
132
+ const message = {
133
+ type: "agent_status_update" as const,
134
+ data: {
135
+ room_id: "room-123",
136
+ agent_id: "agent-456",
137
+ status: "online",
138
+ agent: agentDetails
139
+ }
140
+ };
141
+
142
+ await handler.handle(message, mockContext);
143
+
144
+ // Should emit event with agent details
145
+ expect(emitSpy).toHaveBeenCalledWith("agent_room:status_update", {
146
+ roomId: "room-123",
147
+ agentId: "agent-456",
148
+ status: "online",
149
+ agent: agentDetails
150
+ });
151
+ });
152
+
153
+ it("should handle online status", async () => {
154
+ const message = {
155
+ type: "agent_status_update" as const,
156
+ data: {
157
+ room_id: "room-789",
158
+ agent_id: "agent-999",
159
+ status: "online"
160
+ }
161
+ };
162
+
163
+ await handler.handle(message, mockContext);
164
+
165
+ expect(mockAgentRoomManager.handleStatusUpdate).toHaveBeenCalledWith(
166
+ "room-789",
167
+ "agent-999",
168
+ "online"
169
+ );
170
+ });
171
+
172
+ it("should work without agentRoomManager in context", async () => {
173
+ const contextWithoutManager = { ...mockContext, agentRoomManager: undefined };
174
+
175
+ const message = {
176
+ type: "agent_status_update" as const,
177
+ data: {
178
+ room_id: "room-123",
179
+ agent_id: "agent-456",
180
+ status: "offline"
181
+ }
182
+ };
183
+
184
+ await handler.handle(message, contextWithoutManager);
185
+
186
+ // Should still emit event
187
+ expect(emitSpy).toHaveBeenCalledWith("agent_room:status_update", {
188
+ roomId: "room-123",
189
+ agentId: "agent-456",
190
+ status: "offline",
191
+ agent: undefined
192
+ });
193
+ });
194
+
195
+ it("should work with agentRoomManager without handleStatusUpdate method", async () => {
196
+ const invalidManager = { someOtherMethod: vi.fn() };
197
+ const contextWithInvalidManager = {
198
+ ...mockContext,
199
+ agentRoomManager: invalidManager
200
+ };
201
+
202
+ const message = {
203
+ type: "agent_status_update" as const,
204
+ data: {
205
+ room_id: "room-123",
206
+ agent_id: "agent-456",
207
+ status: "offline"
208
+ }
209
+ };
210
+
211
+ // Should not throw
212
+ await handler.handle(message, contextWithInvalidManager);
213
+
214
+ // Should still emit event
215
+ expect(emitSpy).toHaveBeenCalledWith("agent_room:status_update", {
216
+ roomId: "room-123",
217
+ agentId: "agent-456",
218
+ status: "offline",
219
+ agent: undefined
220
+ });
221
+ });
222
+ });
223
+
224
+ describe("Webhook Errors", () => {
225
+ it("should handle webhook failures gracefully", async () => {
226
+ const webhookError = new Error("Webhook failed");
227
+ sendWebhookSpy.mockRejectedValueOnce(webhookError);
228
+
229
+ const message = {
230
+ type: "agent_status_update" as const,
231
+ data: {
232
+ room_id: "room-123",
233
+ agent_id: "agent-456",
234
+ status: "offline"
235
+ }
236
+ };
237
+
238
+ // Should not throw
239
+ await handler.handle(message, mockContext);
240
+
241
+ // Should still emit event and invalidate cache
242
+ expect(emitSpy).toHaveBeenCalledWith("agent_room:status_update", expect.any(Object));
243
+ expect(mockAgentRoomManager.handleStatusUpdate).toHaveBeenCalled();
244
+ });
245
+ });
246
+
247
+ describe("Message Validation", () => {
248
+ it("should handle invalid message structure", async () => {
249
+ const invalidMessage = {
250
+ type: "agent_status_update",
251
+ // Missing data field
252
+ } as any;
253
+
254
+ await handler.handle(invalidMessage, mockContext);
255
+
256
+ // Should log error
257
+ expect(mockLogger.error).toHaveBeenCalledWith(
258
+ expect.stringContaining("Error handling agent_status_update"),
259
+ expect.any(Error)
260
+ );
261
+
262
+ // Should emit message:error event
263
+ expect(emitSpy).toHaveBeenCalledWith(
264
+ "message:error",
265
+ expect.any(Error),
266
+ invalidMessage
267
+ );
268
+ });
269
+
270
+ it("should accept valid message with extra fields", async () => {
271
+ const message = {
272
+ type: "agent_status_update" as const,
273
+ data: {
274
+ room_id: "room-123",
275
+ agent_id: "agent-456",
276
+ status: "online",
277
+ extra_field: "should be ignored",
278
+ another_extra: 123
279
+ }
280
+ };
281
+
282
+ // Should not throw
283
+ await handler.handle(message, mockContext);
284
+
285
+ expect(emitSpy).toHaveBeenCalledWith("agent_room:status_update", expect.any(Object));
286
+ });
287
+ });
288
+
289
+ describe("Debug Logging", () => {
290
+ it("should log debug info", async () => {
291
+ const message = {
292
+ type: "agent_status_update" as const,
293
+ data: {
294
+ room_id: "room-123",
295
+ agent_id: "agent-456",
296
+ status: "offline"
297
+ }
298
+ };
299
+
300
+ await handler.handle(message, mockContext);
301
+
302
+ expect(mockLogger.debug).toHaveBeenCalledWith(
303
+ "Handling agent_status_update",
304
+ expect.objectContaining({
305
+ roomId: "room-123",
306
+ agentId: "agent-456",
307
+ status: "offline"
308
+ })
309
+ );
310
+ });
311
+
312
+ it("should log debug info with agent details", async () => {
313
+ const message = {
314
+ type: "agent_status_update" as const,
315
+ data: {
316
+ room_id: "room-123",
317
+ agent_id: "agent-456",
318
+ status: "online",
319
+ agent: {
320
+ agent_id: "agent-456",
321
+ agent_name: "Test Agent"
322
+ }
323
+ }
324
+ };
325
+
326
+ await handler.handle(message, mockContext);
327
+
328
+ expect(mockLogger.debug).toHaveBeenCalledWith(
329
+ "Handling agent_status_update",
330
+ expect.objectContaining({
331
+ roomId: "room-123",
332
+ agentId: "agent-456",
333
+ status: "online",
334
+ hasAgent: true
335
+ })
336
+ );
337
+ });
338
+ });
339
+
340
+ describe("Multiple Status Updates", () => {
341
+ it("should handle multiple status updates for different agents", async () => {
342
+ const message1 = {
343
+ type: "agent_status_update" as const,
344
+ data: {
345
+ room_id: "room-123",
346
+ agent_id: "agent-1",
347
+ status: "offline"
348
+ }
349
+ };
350
+
351
+ const message2 = {
352
+ type: "agent_status_update" as const,
353
+ data: {
354
+ room_id: "room-123",
355
+ agent_id: "agent-2",
356
+ status: "online"
357
+ }
358
+ };
359
+
360
+ await handler.handle(message1, mockContext);
361
+ await handler.handle(message2, mockContext);
362
+
363
+ expect(mockAgentRoomManager.handleStatusUpdate).toHaveBeenCalledTimes(2);
364
+ expect(mockAgentRoomManager.handleStatusUpdate).toHaveBeenCalledWith(
365
+ "room-123",
366
+ "agent-1",
367
+ "offline"
368
+ );
369
+ expect(mockAgentRoomManager.handleStatusUpdate).toHaveBeenCalledWith(
370
+ "room-123",
371
+ "agent-2",
372
+ "online"
373
+ );
374
+ });
375
+
376
+ it("should handle multiple status updates for same agent", async () => {
377
+ const message1 = {
378
+ type: "agent_status_update" as const,
379
+ data: {
380
+ room_id: "room-123",
381
+ agent_id: "agent-1",
382
+ status: "online"
383
+ }
384
+ };
385
+
386
+ const message2 = {
387
+ type: "agent_status_update" as const,
388
+ data: {
389
+ room_id: "room-123",
390
+ agent_id: "agent-1",
391
+ status: "offline"
392
+ }
393
+ };
394
+
395
+ await handler.handle(message1, mockContext);
396
+ await handler.handle(message2, mockContext);
397
+
398
+ expect(mockAgentRoomManager.handleStatusUpdate).toHaveBeenCalledTimes(2);
399
+ // Last call should be offline
400
+ expect(mockAgentRoomManager.handleStatusUpdate).toHaveBeenLastCalledWith(
401
+ "room-123",
402
+ "agent-1",
403
+ "offline"
404
+ );
405
+ });
406
+ });
407
+ });