@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.
- package/.github/ISSUE_TEMPLATE/config.yml +1 -1
- package/CHANGELOG.md +366 -15
- package/CONCEPTS.md +182 -44
- package/README.md +524 -94
- package/dist/constants.d.ts +3 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +5 -3
- package/dist/constants.js.map +1 -1
- package/dist/core/websocket-client.d.ts.map +1 -1
- package/dist/core/websocket-client.js +9 -5
- package/dist/core/websocket-client.js.map +1 -1
- package/dist/formatters/response-formatter.d.ts +6 -6
- package/dist/handlers/message-handlers/agent-details-response-handler.d.ts +1080 -756
- package/dist/handlers/message-handlers/agent-details-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/agent-details-response-handler.js +2 -2
- package/dist/handlers/message-handlers/agent-details-response-handler.js.map +1 -1
- package/dist/handlers/message-handlers/agent-error-handler.d.ts +91 -0
- package/dist/handlers/message-handlers/agent-error-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/agent-error-handler.js +44 -0
- package/dist/handlers/message-handlers/agent-error-handler.js.map +1 -0
- package/dist/handlers/message-handlers/agent-selected-handler.d.ts +6 -0
- package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/agent-status-update-handler.d.ts +1080 -756
- package/dist/handlers/message-handlers/agent-status-update-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/agent-status-update-handler.js +2 -7
- package/dist/handlers/message-handlers/agent-status-update-handler.js.map +1 -1
- package/dist/handlers/message-handlers/all-agents-response-handler.d.ts +135 -54
- package/dist/handlers/message-handlers/all-agents-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/all-agents-response-handler.js +2 -2
- package/dist/handlers/message-handlers/all-agents-response-handler.js.map +1 -1
- package/dist/handlers/message-handlers/auth-error-handler.d.ts +6 -0
- package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-message-handler.js +6 -1
- package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -1
- package/dist/handlers/message-handlers/auth-required-handler.d.ts +6 -0
- package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-success-handler.js +6 -1
- package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -1
- package/dist/handlers/message-handlers/base-handler.d.ts +2 -1
- package/dist/handlers/message-handlers/base-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/base-handler.js +24 -4
- package/dist/handlers/message-handlers/base-handler.js.map +1 -1
- package/dist/handlers/message-handlers/challenge-handler.d.ts +6 -0
- package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/error-message-handler.d.ts +6 -0
- package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/index.d.ts +4 -0
- package/dist/handlers/message-handlers/index.d.ts.map +1 -1
- package/dist/handlers/message-handlers/index.js +23 -1
- package/dist/handlers/message-handlers/index.js.map +1 -1
- package/dist/handlers/message-handlers/list-available-agents-handler.d.ts +1116 -756
- package/dist/handlers/message-handlers/list-available-agents-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/list-available-agents-handler.js +23 -10
- package/dist/handlers/message-handlers/list-available-agents-handler.js.map +1 -1
- package/dist/handlers/message-handlers/list-room-agents-handler.d.ts +1080 -756
- package/dist/handlers/message-handlers/list-room-agents-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/list-room-agents-handler.js +2 -6
- package/dist/handlers/message-handlers/list-room-agents-handler.js.map +1 -1
- package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/list-rooms-response-handler.js +2 -5
- package/dist/handlers/message-handlers/list-rooms-response-handler.js.map +1 -1
- package/dist/handlers/message-handlers/ping-pong-handler.d.ts +52 -4
- package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/ping-pong-handler.js +23 -4
- package/dist/handlers/message-handlers/ping-pong-handler.js.map +1 -1
- package/dist/handlers/message-handlers/rate-limit-notification-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/rate-limit-notification-handler.js +3 -2
- package/dist/handlers/message-handlers/rate-limit-notification-handler.js.map +1 -1
- package/dist/handlers/message-handlers/regular-message-handler.d.ts +6 -0
- package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +12 -6
- package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/success-handler.d.ts +82 -0
- package/dist/handlers/message-handlers/success-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/success-handler.js +24 -0
- package/dist/handlers/message-handlers/success-handler.js.map +1 -0
- package/dist/handlers/message-handlers/task-confirmed-handler.d.ts +110 -0
- package/dist/handlers/message-handlers/task-confirmed-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/task-confirmed-handler.js +46 -0
- package/dist/handlers/message-handlers/task-confirmed-handler.js.map +1 -0
- package/dist/handlers/message-handlers/trigger-wallet-tx-handler.d.ts +244 -0
- package/dist/handlers/message-handlers/trigger-wallet-tx-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/trigger-wallet-tx-handler.js +58 -0
- package/dist/handlers/message-handlers/trigger-wallet-tx-handler.js.map +1 -0
- package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +12 -6
- package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/user-authenticated-handler.js +2 -2
- package/dist/handlers/message-handlers/user-authenticated-handler.js.map +1 -1
- package/dist/handlers/message-handlers/user-count-handler.js +2 -2
- package/dist/handlers/message-handlers/user-count-handler.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -4
- package/dist/index.js.map +1 -1
- package/dist/managers/admin-manager.d.ts +3 -1
- package/dist/managers/admin-manager.d.ts.map +1 -1
- package/dist/managers/admin-manager.js +4 -3
- package/dist/managers/admin-manager.js.map +1 -1
- package/dist/managers/agent-room-manager.d.ts +89 -11
- package/dist/managers/agent-room-manager.d.ts.map +1 -1
- package/dist/managers/agent-room-manager.js +99 -35
- package/dist/managers/agent-room-manager.js.map +1 -1
- package/dist/managers/index.d.ts +1 -1
- package/dist/managers/index.d.ts.map +1 -1
- package/dist/managers/index.js.map +1 -1
- package/dist/managers/message-router.d.ts +45 -5
- package/dist/managers/message-router.d.ts.map +1 -1
- package/dist/managers/message-router.js +96 -24
- package/dist/managers/message-router.js.map +1 -1
- package/dist/managers/room-manager.d.ts +29 -7
- package/dist/managers/room-manager.d.ts.map +1 -1
- package/dist/managers/room-manager.js +37 -11
- package/dist/managers/room-manager.js.map +1 -1
- package/dist/payments/index.d.ts +3 -1
- package/dist/payments/index.d.ts.map +1 -1
- package/dist/payments/index.js +17 -3
- package/dist/payments/index.js.map +1 -1
- package/dist/payments/networks.d.ts +59 -0
- package/dist/payments/networks.d.ts.map +1 -0
- package/dist/payments/networks.js +192 -0
- package/dist/payments/networks.js.map +1 -0
- package/dist/payments/payment-client.d.ts +55 -10
- package/dist/payments/payment-client.d.ts.map +1 -1
- package/dist/payments/payment-client.js +172 -51
- package/dist/payments/payment-client.js.map +1 -1
- package/dist/teneo-sdk.d.ts +215 -41
- package/dist/teneo-sdk.d.ts.map +1 -1
- package/dist/teneo-sdk.js +361 -84
- package/dist/teneo-sdk.js.map +1 -1
- package/dist/types/config.d.ts +334 -25
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +114 -22
- package/dist/types/config.js.map +1 -1
- package/dist/types/events.d.ts +60 -14
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/events.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +11 -4
- package/dist/types/index.js.map +1 -1
- package/dist/types/messages.d.ts +13110 -7451
- package/dist/types/messages.d.ts.map +1 -1
- package/dist/types/messages.js +195 -44
- package/dist/types/messages.js.map +1 -1
- package/dist/utils/pricing-resolver.d.ts +1 -1
- package/dist/utils/pricing-resolver.d.ts.map +1 -1
- package/dist/utils/pricing-resolver.js +9 -1
- package/dist/utils/pricing-resolver.js.map +1 -1
- package/examples/agent-room-management-example.ts +5 -5
- package/examples/basic-usage.ts +26 -6
- package/examples/claude-agent-x-follower/index.ts +1 -1
- package/examples/minimal-chat.ts +4 -3
- package/examples/n8n-teneo/index.ts +2 -2
- package/examples/nestjs-dashboard/README.md +1 -1
- package/examples/nestjs-dashboard/src/teneo/agents.controller.ts +3 -3
- package/examples/nestjs-dashboard/src/teneo/rooms.controller.ts +5 -5
- package/examples/nestjs-dashboard/src/teneo/teneo.service.ts +8 -8
- package/examples/openai-teneo/index.ts +1 -1
- package/examples/payment-flow.ts +143 -0
- package/examples/production-dashboard/README.md +6 -8
- package/examples/production-dashboard/server.ts +22 -10
- package/examples/room-management-example.ts +2 -2
- package/examples/usage/01-connect.ts +0 -3
- package/examples/usage/02-list-agents.ts +0 -2
- package/examples/usage/03-pick-agent.ts +3 -4
- package/examples/usage/04-find-by-capability.ts +10 -12
- package/examples/usage/05-webhook-example.ts +2 -4
- package/examples/usage/06-simple-api-server.ts +13 -9
- package/examples/usage/07-event-listener.ts +1 -13
- package/examples/usage/README.md +33 -7
- package/examples/webhook-integration.ts +9 -9
- package/examples/x-influencer-battle-server.ts +1 -1
- package/package.json +1 -1
- package/scripts/diagnose-connection.ts +86 -0
- package/scripts/investigate-payload.ts +163 -0
- package/scripts/list-agents.ts +58 -0
- package/scripts/live-multi-network-test.ts +230 -0
- package/src/constants.ts +5 -3
- package/src/core/websocket-client.ts +10 -9
- package/src/handlers/message-handlers/agent-details-response-handler.ts +2 -2
- package/src/handlers/message-handlers/agent-error-handler.ts +47 -0
- package/src/handlers/message-handlers/agent-status-update-handler.ts +2 -7
- package/src/handlers/message-handlers/all-agents-response-handler.ts +2 -2
- package/src/handlers/message-handlers/auth-message-handler.ts +7 -1
- package/src/handlers/message-handlers/auth-success-handler.ts +7 -1
- package/src/handlers/message-handlers/base-handler.ts +24 -4
- package/src/handlers/message-handlers/index.ts +24 -0
- package/src/handlers/message-handlers/list-available-agents-handler.ts +24 -11
- package/src/handlers/message-handlers/list-room-agents-handler.ts +2 -6
- package/src/handlers/message-handlers/list-rooms-response-handler.ts +2 -5
- package/src/handlers/message-handlers/ping-pong-handler.ts +29 -4
- package/src/handlers/message-handlers/rate-limit-notification-handler.ts +3 -2
- package/src/handlers/message-handlers/success-handler.ts +26 -0
- package/src/handlers/message-handlers/task-confirmed-handler.ts +49 -0
- package/src/handlers/message-handlers/trigger-wallet-tx-handler.ts +62 -0
- package/src/handlers/message-handlers/user-authenticated-handler.ts +2 -2
- package/src/handlers/message-handlers/user-count-handler.ts +2 -2
- package/src/index.ts +12 -4
- package/src/managers/admin-manager.ts +6 -3
- package/src/managers/agent-room-manager.ts +155 -26
- package/src/managers/index.ts +6 -1
- package/src/managers/message-router.ts +122 -27
- package/src/managers/room-manager.ts +39 -11
- package/src/payments/index.ts +20 -5
- package/src/payments/networks.ts +208 -0
- package/src/payments/payment-client.ts +211 -56
- package/src/teneo-sdk.ts +402 -71
- package/src/types/config.test.ts +24 -4
- package/src/types/config.ts +123 -25
- package/src/types/events.ts +36 -2
- package/src/types/index.ts +16 -3
- package/src/types/messages.ts +235 -60
- package/src/utils/pricing-resolver.ts +10 -2
- package/tests/direct-agent-test.ts +1 -1
- package/tests/integration/real-server.test.ts +1 -1
- package/tests/integration/websocket.test.ts +3 -3
- package/tests/multi-network-payment.test.ts +309 -0
- package/tests/multi-network.test.ts +296 -0
- package/tests/payment-flow-test.ts +6 -4
- package/tests/unit/handlers/agent-error-handler.test.ts +388 -0
- package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +9 -6
- package/tests/unit/handlers/agent-status-update-handler.test.ts +11 -16
- package/tests/unit/handlers/list-available-agents-handler.test.ts +11 -14
- package/tests/unit/handlers/list-room-agents-handler.test.ts +11 -15
- package/tests/unit/handlers/room-operation-response-handler.test.ts +9 -6
- package/tests/unit/handlers/trigger-wallet-tx-handler.test.ts +431 -0
- package/tests/unit/managers/admin-manager.test.ts +183 -0
- package/tests/unit/managers/agent-room-manager.test.ts +189 -33
- 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
|
|
310
|
-
expect(mockLogger.
|
|
311
|
-
expect.stringContaining("
|
|
312
|
-
expect.any(
|
|
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
|
|
316
|
-
expect(
|
|
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).
|
|
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
|
|
257
|
-
expect(mockLogger.
|
|
258
|
-
expect.stringContaining("
|
|
259
|
-
expect.any(
|
|
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
|
|
263
|
-
expect(
|
|
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).
|
|
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
|
|
198
|
-
expect(mockLogger.
|
|
199
|
-
expect.stringContaining("
|
|
200
|
-
expect.any(
|
|
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
|
|
204
|
-
expect(
|
|
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).
|
|
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
|
|
237
|
-
expect(mockLogger.
|
|
238
|
-
expect.stringContaining("
|
|
239
|
-
expect.any(
|
|
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
|
|
243
|
-
expect(
|
|
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
|
|
418
|
-
expect(mockLogger.
|
|
419
|
-
expect.stringContaining("
|
|
420
|
-
expect.any(
|
|
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
|
|
424
|
-
expect(
|
|
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 () => {
|