agenthub-multiagent-mcp 1.1.2 → 1.1.4
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/README.md +170 -151
- package/dist/client.d.ts +3 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -1
- package/dist/client.js.map +1 -1
- package/dist/client.test.d.ts +2 -0
- package/dist/client.test.d.ts.map +1 -1
- package/dist/client.test.js +16 -1
- package/dist/client.test.js.map +1 -1
- package/dist/e2e.test.d.ts +1 -0
- package/dist/e2e.test.d.ts.map +1 -1
- package/dist/e2e.test.js +3 -1
- package/dist/e2e.test.js.map +1 -1
- package/dist/heartbeat.d.ts +11 -1
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +41 -3
- package/dist/heartbeat.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +13 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/tools.test.js +6 -1
- package/dist/tools/tools.test.js.map +1 -1
- package/package.json +53 -53
- package/src/client.test.ts +223 -208
- package/src/client.ts +293 -286
- package/src/e2e.test.ts +300 -298
- package/src/heartbeat.ts +45 -3
- package/src/index.ts +123 -123
- package/src/tools/index.ts +672 -666
- package/src/tools/tools.test.ts +522 -517
- package/vitest.config.ts +8 -0
package/src/e2e.test.ts
CHANGED
|
@@ -1,298 +1,300 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* End-to-end multi-agent communication tests
|
|
3
|
-
*
|
|
4
|
-
* These tests simulate real-world multi-agent scenarios:
|
|
5
|
-
* - Multiple agents registering and communicating
|
|
6
|
-
* - Channel-based group communication
|
|
7
|
-
* - Message status tracking
|
|
8
|
-
* - Agent coordination workflows
|
|
9
|
-
*
|
|
10
|
-
* Requires the AgentHub server to be running on localhost:8787
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
await client.registerAgent(agents.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
expect(
|
|
75
|
-
|
|
76
|
-
expect(taskMessage
|
|
77
|
-
expect(taskMessage?.
|
|
78
|
-
expect(taskMessage?.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
expect(responseMessage
|
|
124
|
-
expect(responseMessage?.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
expect(backendBroadcast
|
|
176
|
-
expect(frontendBroadcast
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
let
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
expect(backendAnswer
|
|
271
|
-
expect(frontendAnswer
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end multi-agent communication tests
|
|
3
|
+
*
|
|
4
|
+
* These tests simulate real-world multi-agent scenarios:
|
|
5
|
+
* - Multiple agents registering and communicating
|
|
6
|
+
* - Channel-based group communication
|
|
7
|
+
* - Message status tracking
|
|
8
|
+
* - Agent coordination workflows
|
|
9
|
+
*
|
|
10
|
+
* Requires the AgentHub server to be running on localhost:8787
|
|
11
|
+
* Set AGENTHUB_INTEGRATION_TESTS=1 to run these tests
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
15
|
+
import { ApiClient } from "./client.js";
|
|
16
|
+
|
|
17
|
+
const TEST_URL = process.env.AGENTHUB_URL || "http://localhost:8787";
|
|
18
|
+
const TEST_API_KEY = process.env.AGENTHUB_API_KEY || "test-key-123";
|
|
19
|
+
const RUN_INTEGRATION = process.env.AGENTHUB_INTEGRATION_TESTS === "1";
|
|
20
|
+
|
|
21
|
+
describe.skipIf(!RUN_INTEGRATION)("E2E: Multi-Agent Communication", () => {
|
|
22
|
+
let client: ApiClient;
|
|
23
|
+
const timestamp = Date.now();
|
|
24
|
+
|
|
25
|
+
// Create 3 agents for testing
|
|
26
|
+
const agents = {
|
|
27
|
+
coordinator: `coordinator-${timestamp}`,
|
|
28
|
+
backend: `backend-${timestamp}`,
|
|
29
|
+
frontend: `frontend-${timestamp}`,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
beforeAll(async () => {
|
|
33
|
+
client = new ApiClient(TEST_URL, TEST_API_KEY);
|
|
34
|
+
|
|
35
|
+
// Register all agents
|
|
36
|
+
await client.registerAgent(agents.coordinator, "Coordinator Agent");
|
|
37
|
+
await client.registerAgent(agents.backend, "Backend Developer");
|
|
38
|
+
await client.registerAgent(agents.frontend, "Frontend Developer");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterAll(async () => {
|
|
42
|
+
// Cleanup - disconnect all agents
|
|
43
|
+
for (const agentId of Object.values(agents)) {
|
|
44
|
+
try {
|
|
45
|
+
await client.disconnect(agentId);
|
|
46
|
+
} catch {
|
|
47
|
+
// Ignore cleanup errors
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe("Scenario: Task Assignment Flow", () => {
|
|
53
|
+
let taskMessageId: string;
|
|
54
|
+
let responseMessageId: string;
|
|
55
|
+
|
|
56
|
+
it("step 1: coordinator assigns task to backend", async () => {
|
|
57
|
+
const result = await client.sendMessage({
|
|
58
|
+
from_agent: agents.coordinator,
|
|
59
|
+
to_agent: agents.backend,
|
|
60
|
+
type: "task",
|
|
61
|
+
subject: "Implement API endpoint",
|
|
62
|
+
body: "Please implement the /users endpoint with CRUD operations",
|
|
63
|
+
priority: "high",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
expect(result.message_id).toBeDefined();
|
|
67
|
+
expect(result.status).toBe("pending");
|
|
68
|
+
taskMessageId = result.message_id;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("step 2: backend receives task in inbox", async () => {
|
|
72
|
+
const inbox = await client.getInbox(agents.backend, false);
|
|
73
|
+
|
|
74
|
+
expect(inbox.total).toBeGreaterThan(0);
|
|
75
|
+
const taskMessage = inbox.messages.find((m) => m.id === taskMessageId);
|
|
76
|
+
expect(taskMessage).toBeDefined();
|
|
77
|
+
expect(taskMessage?.from_agent).toBe(agents.coordinator);
|
|
78
|
+
expect(taskMessage?.subject).toBe("Implement API endpoint");
|
|
79
|
+
expect(taskMessage?.type).toBe("task");
|
|
80
|
+
expect(taskMessage?.priority).toBe("high");
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("step 3: backend marks task as read", async () => {
|
|
84
|
+
// First deliver
|
|
85
|
+
await fetch(`${TEST_URL}/messages/${taskMessageId}/status`, {
|
|
86
|
+
method: "PATCH",
|
|
87
|
+
headers: {
|
|
88
|
+
"Content-Type": "application/json",
|
|
89
|
+
"X-API-Key": TEST_API_KEY,
|
|
90
|
+
},
|
|
91
|
+
body: JSON.stringify({ status: "delivered" }),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const result = await client.markRead(taskMessageId);
|
|
95
|
+
expect(result.updated).toBe(true);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("step 4: backend starts work on the task", async () => {
|
|
99
|
+
const result = await client.startWork(
|
|
100
|
+
agents.backend,
|
|
101
|
+
"Implementing /users endpoint",
|
|
102
|
+
"API Development"
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
expect(result.acknowledged).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("step 5: backend sends completion response", async () => {
|
|
109
|
+
const result = await client.reply(
|
|
110
|
+
taskMessageId,
|
|
111
|
+
agents.backend,
|
|
112
|
+
"Task completed. The /users endpoint is now live with full CRUD support."
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
expect(result.message_id).toBeDefined();
|
|
116
|
+
responseMessageId = result.message_id;
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("step 6: coordinator receives completion in inbox", async () => {
|
|
120
|
+
const inbox = await client.getInbox(agents.coordinator, false);
|
|
121
|
+
|
|
122
|
+
const responseMessage = inbox.messages.find((m) => m.id === responseMessageId);
|
|
123
|
+
expect(responseMessage).toBeDefined();
|
|
124
|
+
expect(responseMessage?.from_agent).toBe(agents.backend);
|
|
125
|
+
expect(responseMessage?.type).toBe("response");
|
|
126
|
+
expect(responseMessage?.reply_to).toBe(taskMessageId);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe("Scenario: Broadcast Announcements", () => {
|
|
131
|
+
let broadcastId: string;
|
|
132
|
+
|
|
133
|
+
it("step 1: coordinator broadcasts announcement", async () => {
|
|
134
|
+
const result = await client.sendMessage({
|
|
135
|
+
from_agent: agents.coordinator,
|
|
136
|
+
broadcast: true,
|
|
137
|
+
type: "status",
|
|
138
|
+
subject: "Sprint Planning Meeting",
|
|
139
|
+
body: "Sprint planning in 30 minutes. Please prepare your updates.",
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
expect(result.message_id).toBeDefined();
|
|
143
|
+
broadcastId = result.message_id;
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("step 2: backend receives broadcast", async () => {
|
|
147
|
+
const inbox = await client.getInbox(agents.backend, false);
|
|
148
|
+
|
|
149
|
+
const broadcast = inbox.messages.find(
|
|
150
|
+
(m) => m.broadcast && m.subject === "Sprint Planning Meeting"
|
|
151
|
+
);
|
|
152
|
+
expect(broadcast).toBeDefined();
|
|
153
|
+
expect(broadcast?.from_agent).toBe(agents.coordinator);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("step 3: frontend receives broadcast", async () => {
|
|
157
|
+
const inbox = await client.getInbox(agents.frontend, false);
|
|
158
|
+
|
|
159
|
+
const broadcast = inbox.messages.find(
|
|
160
|
+
(m) => m.broadcast && m.subject === "Sprint Planning Meeting"
|
|
161
|
+
);
|
|
162
|
+
expect(broadcast).toBeDefined();
|
|
163
|
+
expect(broadcast?.from_agent).toBe(agents.coordinator);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("step 4: broadcast is tracked correctly", async () => {
|
|
167
|
+
// Note: In this implementation, broadcasters may receive their own broadcasts
|
|
168
|
+
// This test verifies the broadcast was delivered to multiple agents
|
|
169
|
+
const backendInbox = await client.getInbox(agents.backend, false);
|
|
170
|
+
const frontendInbox = await client.getInbox(agents.frontend, false);
|
|
171
|
+
|
|
172
|
+
const backendBroadcast = backendInbox.messages.find((m) => m.id === broadcastId);
|
|
173
|
+
const frontendBroadcast = frontendInbox.messages.find((m) => m.id === broadcastId);
|
|
174
|
+
|
|
175
|
+
expect(backendBroadcast).toBeDefined();
|
|
176
|
+
expect(frontendBroadcast).toBeDefined();
|
|
177
|
+
expect(backendBroadcast?.broadcast).toBe(true);
|
|
178
|
+
expect(frontendBroadcast?.broadcast).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe("Scenario: Agent Status Tracking", () => {
|
|
183
|
+
it("all agents should be visible in agent list", async () => {
|
|
184
|
+
const result = await client.listAgents();
|
|
185
|
+
|
|
186
|
+
const registeredAgents = result.agents.filter((a) =>
|
|
187
|
+
Object.values(agents).includes(a.id)
|
|
188
|
+
);
|
|
189
|
+
expect(registeredAgents.length).toBe(3);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("backend should show as busy after starting work", async () => {
|
|
193
|
+
const agent = await client.getAgent(agents.backend);
|
|
194
|
+
|
|
195
|
+
expect(agent.status).toBe("busy");
|
|
196
|
+
expect(agent.current_task).toContain("Implementing");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("frontend should show as online (not busy)", async () => {
|
|
200
|
+
const agent = await client.getAgent(agents.frontend);
|
|
201
|
+
|
|
202
|
+
expect(agent.status).toBe("online");
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("agents can update their status", async () => {
|
|
206
|
+
await client.heartbeat(agents.frontend, "busy");
|
|
207
|
+
const agent = await client.getAgent(agents.frontend);
|
|
208
|
+
|
|
209
|
+
expect(agent.status).toBe("busy");
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe("Scenario: Multi-Agent Q&A", () => {
|
|
214
|
+
let questionId: string;
|
|
215
|
+
let backendAnswerId: string;
|
|
216
|
+
let frontendAnswerId: string;
|
|
217
|
+
|
|
218
|
+
it("step 1: coordinator asks question to backend", async () => {
|
|
219
|
+
const result = await client.sendMessage({
|
|
220
|
+
from_agent: agents.coordinator,
|
|
221
|
+
to_agent: agents.backend,
|
|
222
|
+
type: "question",
|
|
223
|
+
subject: "API Rate Limiting",
|
|
224
|
+
body: "What's the current rate limit configuration?",
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
questionId = result.message_id;
|
|
228
|
+
expect(questionId).toBeDefined();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it("step 2: backend answers the question", async () => {
|
|
232
|
+
const result = await client.reply(
|
|
233
|
+
questionId,
|
|
234
|
+
agents.backend,
|
|
235
|
+
"Rate limit is set to 100 requests/minute per API key."
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
backendAnswerId = result.message_id;
|
|
239
|
+
expect(backendAnswerId).toBeDefined();
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it("step 3: coordinator asks frontend a different question", async () => {
|
|
243
|
+
const result = await client.sendMessage({
|
|
244
|
+
from_agent: agents.coordinator,
|
|
245
|
+
to_agent: agents.frontend,
|
|
246
|
+
type: "question",
|
|
247
|
+
subject: "UI Framework",
|
|
248
|
+
body: "Which UI framework are we using for the dashboard?",
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const frontendQuestionId = result.message_id;
|
|
252
|
+
|
|
253
|
+
// Frontend answers
|
|
254
|
+
const answerResult = await client.reply(
|
|
255
|
+
frontendQuestionId,
|
|
256
|
+
agents.frontend,
|
|
257
|
+
"We're using React with TailwindCSS for the dashboard."
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
frontendAnswerId = answerResult.message_id;
|
|
261
|
+
expect(frontendAnswerId).toBeDefined();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it("step 4: coordinator has received all answers", async () => {
|
|
265
|
+
const inbox = await client.getInbox(agents.coordinator, false);
|
|
266
|
+
|
|
267
|
+
const backendAnswer = inbox.messages.find((m) => m.id === backendAnswerId);
|
|
268
|
+
const frontendAnswer = inbox.messages.find((m) => m.id === frontendAnswerId);
|
|
269
|
+
|
|
270
|
+
expect(backendAnswer).toBeDefined();
|
|
271
|
+
expect(frontendAnswer).toBeDefined();
|
|
272
|
+
expect(backendAnswer?.type).toBe("response");
|
|
273
|
+
expect(frontendAnswer?.type).toBe("response");
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
describe("Scenario: Urgent Priority Handling", () => {
|
|
278
|
+
it("should handle urgent priority messages", async () => {
|
|
279
|
+
const result = await client.sendMessage({
|
|
280
|
+
from_agent: agents.coordinator,
|
|
281
|
+
to_agent: agents.backend,
|
|
282
|
+
type: "task",
|
|
283
|
+
subject: "CRITICAL: Production Bug",
|
|
284
|
+
body: "There's a critical bug in production. Please investigate immediately.",
|
|
285
|
+
priority: "urgent",
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
expect(result.message_id).toBeDefined();
|
|
289
|
+
|
|
290
|
+
// Verify the message has urgent priority
|
|
291
|
+
const inbox = await client.getInbox(agents.backend, false);
|
|
292
|
+
const urgentMessage = inbox.messages.find(
|
|
293
|
+
(m) => m.subject === "CRITICAL: Production Bug"
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
expect(urgentMessage).toBeDefined();
|
|
297
|
+
expect(urgentMessage?.priority).toBe("urgent");
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
});
|