Skip to content

Commit 78ef418

Browse files
authored
Refactor testing with agent-sdk v2 (#1619)
* Refactor log messages * "Improve message stream handling" * Add XMTP keys and delay * Refactor timeout message * Refactor condition syntax * Enable pull_request in AgentHealth * Refactor code and update scripts * Update workflow triggers * Remove debug logs in helper.ts * Remove stress test & logs * Add agent stress test workflow * Enable pull_request trigger * Update workflow triggers * Change console.log to debug * Update workflow triggers * Add key generation to tests * Enable PR in AgentGroups.yml * Refactor timeout constant * Remove XMTP keys usage * Disable pull_request trigger
1 parent 48b8e0a commit 78ef418

File tree

14 files changed

+211
-113
lines changed

14 files changed

+211
-113
lines changed

.cursor/rules/testing-framework.mdc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ alwaysApply: false
33

44
# Testing Worker Framework Rules
55

6+
-- When possible default to streamAllMessages
7+
68
## Core Testing Pattern
79

810
```typescript

.github/workflows/AgentGroups.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ jobs:
2626
- name: Setup test env
2727
uses: ./.github/actions/xmtp-test-setup
2828

29+
- name: Generate keys
30+
run: yarn gen:keys
31+
2932
- name: Run ${{ matrix.test }} ${{ matrix.env }}
3033
run: yarn test ${{ matrix.test }} --env ${{ matrix.env }} --no-fail --log off
3134

@@ -61,6 +64,9 @@ jobs:
6164
- name: Setup test env
6265
uses: ./.github/actions/xmtp-test-setup
6366

67+
- name: Generate keys
68+
run: yarn gen:keys
69+
6470
- name: ${{ matrix.test }} ${{ matrix.env }}
6571
run: yarn test ${{ matrix.test }} --env ${{ matrix.env }} --no-fail --log off
6672

.github/workflows/AgentHealth.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ jobs:
2626
- name: Setup test env
2727
uses: ./.github/actions/xmtp-test-setup
2828

29+
- name: Generate keys
30+
run: yarn gen:keys
31+
2932
- name: ${{ matrix.test }} ${{ matrix.env }}
3033
run: yarn test ${{ matrix.test }} --env ${{ matrix.env }} --no-fail --log off
3134

.github/workflows/AgentText.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ jobs:
2626
- name: Setup test env
2727
uses: ./.github/actions/xmtp-test-setup
2828

29+
- name: Generate keys
30+
run: yarn gen:keys
31+
2932
- name: ${{ matrix.test }} ${{ matrix.env }}
3033
run: yarn test ${{ matrix.test }} --env ${{ matrix.env }} --no-fail --log off
3134

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ We can test all XMTP bindings using three main applications. We use [xmtp.chat](
112112
- Bots: Bots for testing with multiple agents - [see section](https://github.com/xmtp/xmtp-qa-tools/tree/main/bots/)
113113
- [`key-check.eth`](https://github.com/xmtp/xmtp-qa-tools/tree/main/bots/key-check): key packages
114114
- [`hi.xmtp.eth`](https://github.com/xmtp/gm-bot): A bot that replies "gm" to all messages
115-
- Gen Keys: Generate wallet keys and encryption keys for XMTP testing - [see section](./cli/keys.ts)
115+
- Generate keys: Generate wallet keys and encryption keys for XMTP testing - [see section](./cli/keys.ts)
116116
- Creates `.env` file with `XMTP_WALLET_KEY`, `XMTP_DB_ENCRYPTION_KEY`, and `XMTP_ENV`
117117
- Usage: `yarn gen:keys [--env <environment>]`
118-
- Revoke Installations: Revoke XMTP installations for a given inbox ID - [see section](./cli/revoke.ts)
118+
- Revoke installations: Revoke XMTP installations for a given inbox ID - [see section](./cli/revoke.ts)
119119
- Can keep specific installations or revoke all except one
120120
- Usage: `yarn revoke <inbox-id> [--keep <ids>] [--env <environment>]`
121121
- Copilot: XMTP agent assistant for XMTP tasks via Slack or XMTP - [see section](./copilot/CLAUDE.md)

agents/monitoring/agents-dms.test.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ import { ActionsCodec } from "agents/utils/inline-actions/types/ActionsContent";
55
import { IntentCodec } from "agents/utils/inline-actions/types/IntentContent";
66
import { describe, it } from "vitest";
77
import productionAgents from "./agents";
8-
import { waitForResponse, type AgentConfig } from "./helper";
8+
import {
9+
AGENT_RESPONSE_TIMEOUT,
10+
waitForResponse,
11+
type AgentConfig,
12+
} from "./helper";
913

1014
const testName = "agents-dms";
11-
const TIMEOUT = 10000; // 10 seconds
1215

1316
describe(testName, () => {
1417
setupDurationTracking({ testName, initDataDog: true });
@@ -49,21 +52,19 @@ describe(testName, () => {
4952
},
5053
conversationId: conversation.id,
5154
senderInboxId: agent.client.inboxId,
52-
timeout: TIMEOUT,
55+
timeout: AGENT_RESPONSE_TIMEOUT,
5356
messageText: agentConfig.sendMessage,
5457
});
5558

5659
const responseTime = Math.max(result.responseTime || 0, 0.0001);
5760
sendMetric("response", responseTime, createMetricTags(agentConfig));
5861

59-
if (result.success && result.responseMessage) {
60-
const responseContent = result.responseMessage.content as string;
62+
if (result.success && result.responseMessage)
6163
console.log(
62-
`✅ ${agentConfig.name} responded in ${responseTime.toFixed(2)}ms - "${responseContent}"`,
64+
`✅ ${agentConfig.name} responded in ${responseTime.toFixed(2)}ms`,
6365
);
64-
} else {
66+
else
6567
console.error(`❌ ${agentConfig.name} - NO RESPONSE within timeout`);
66-
}
6768
} finally {
6869
await agent.stop();
6970
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { sendMetric, type ResponseMetricTags } from "@helpers/datadog";
2+
import { Agent, type XmtpEnv } from "@helpers/versions";
3+
import { setupDurationTracking } from "@helpers/vitest";
4+
import { ActionsCodec } from "agents/utils/inline-actions/types/ActionsContent";
5+
import { IntentCodec } from "agents/utils/inline-actions/types/IntentContent";
6+
import { describe, it } from "vitest";
7+
import productionAgents from "./agents";
8+
import {
9+
AGENT_RESPONSE_TIMEOUT,
10+
waitForResponse,
11+
type AgentConfig,
12+
} from "./helper";
13+
14+
const testName = "agents-stress";
15+
16+
describe(testName, () => {
17+
setupDurationTracking({ testName, initDataDog: true });
18+
const env = process.env.XMTP_ENV as XmtpEnv;
19+
const filteredAgents = productionAgents.filter((agent) =>
20+
agent.networks.includes(env),
21+
);
22+
23+
const createMetricTags = (agentConfig: AgentConfig): ResponseMetricTags => ({
24+
test: testName,
25+
metric_type: "agent",
26+
metric_subtype: "stress",
27+
live: agentConfig.live ? "true" : "false",
28+
agent: agentConfig.name,
29+
address: agentConfig.address,
30+
sdk: "",
31+
});
32+
33+
for (const agentConfig of filteredAgents) {
34+
it(`${testName}: ${agentConfig.name} Stress : ${agentConfig.address}`, async () => {
35+
const agent = await Agent.createFromEnv({
36+
codecs: [new ActionsCodec(), new IntentCodec()],
37+
});
38+
39+
try {
40+
const conversation = await agent.createDmWithAddress(
41+
agentConfig.address as `0x${string}`,
42+
);
43+
44+
console.log(
45+
`📤 Sending "${agentConfig.sendMessage}" to ${agentConfig.name} (${agentConfig.address})`,
46+
);
47+
48+
const result = await waitForResponse({
49+
client: agent.client as any,
50+
conversation: {
51+
send: (content: string) => conversation.send(content),
52+
},
53+
conversationId: conversation.id,
54+
senderInboxId: agent.client.inboxId,
55+
timeout: AGENT_RESPONSE_TIMEOUT,
56+
messageText: agentConfig.sendMessage,
57+
});
58+
59+
const responseTime = Math.max(result.responseTime || 0, 0.0001);
60+
sendMetric("response", responseTime, createMetricTags(agentConfig));
61+
62+
if (result.success && result.responseMessage)
63+
console.log(
64+
`✅ ${agentConfig.name} responded in ${responseTime.toFixed(2)}ms`,
65+
);
66+
else
67+
console.error(`❌ ${agentConfig.name} - NO RESPONSE within timeout`);
68+
} finally {
69+
await agent.stop();
70+
}
71+
});
72+
}
73+
});

agents/monitoring/agents-tagged.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ import { ActionsCodec } from "agents/utils/inline-actions/types/ActionsContent";
66
import { IntentCodec } from "agents/utils/inline-actions/types/IntentContent";
77
import { describe, it } from "vitest";
88
import productionAgents from "./agents";
9-
import { waitForResponse, type AgentConfig } from "./helper";
9+
import {
10+
AGENT_RESPONSE_TIMEOUT,
11+
waitForResponse,
12+
type AgentConfig,
13+
} from "./helper";
1014

1115
const testName = "agents-tagged";
12-
const TIMEOUT = 30000; // 30 seconds
1316

1417
describe(testName, () => {
1518
setupDurationTracking({ testName, initDataDog: true });
@@ -53,17 +56,16 @@ describe(testName, () => {
5356
},
5457
conversationId: conversation.id,
5558
senderInboxId: agent.client.inboxId,
56-
timeout: TIMEOUT,
59+
timeout: AGENT_RESPONSE_TIMEOUT,
5760
messageText: testMessage,
5861
});
5962

6063
const responseTime = Math.max(result.responseTime || 0, 0.0001);
6164
sendMetric("response", responseTime, createMetricTags(agentConfig));
6265

6366
if (result.success && result.responseMessage) {
64-
const responseContent = result.responseMessage.content as string;
6567
console.log(
66-
`✅ ${agentConfig.name} responded in ${responseTime.toFixed(2)}ms - "${responseContent}"`,
68+
`✅ ${agentConfig.name} responded in ${responseTime.toFixed(2)}ms`,
6769
);
6870
} else {
6971
console.error(`❌ ${agentConfig.name} - NO RESPONSE within timeout`);

agents/monitoring/agents-text.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ import { ActionsCodec } from "agents/utils/inline-actions/types/ActionsContent";
55
import { IntentCodec } from "agents/utils/inline-actions/types/IntentContent";
66
import { describe, it } from "vitest";
77
import productionAgents from "./agents";
8-
import { waitForResponse, type AgentConfig } from "./helper";
8+
import {
9+
AGENT_RESPONSE_TIMEOUT,
10+
waitForResponse,
11+
type AgentConfig,
12+
} from "./helper";
913

1014
const testName = "agents-text";
11-
const TIMEOUT = 30000; // 30 seconds
1215

1316
describe(testName, () => {
1417
setupDurationTracking({ testName, initDataDog: true });
@@ -49,7 +52,7 @@ describe(testName, () => {
4952
},
5053
conversationId: conversation.id,
5154
senderInboxId: agent.client.inboxId,
52-
timeout: TIMEOUT,
55+
timeout: AGENT_RESPONSE_TIMEOUT,
5356
messageText: agentConfig.sendMessage,
5457
messageFilter: (message) => {
5558
return message.contentType?.typeId === "text";
@@ -60,9 +63,8 @@ describe(testName, () => {
6063
sendMetric("response", responseTime, createMetricTags(agentConfig));
6164

6265
if (result.success && result.responseMessage) {
63-
const responseContent = result.responseMessage.content as string;
6466
console.log(
65-
`✅ ${agentConfig.name} responded in ${responseTime.toFixed(2)}ms - "${responseContent}"`,
67+
`✅ ${agentConfig.name} responded in ${responseTime.toFixed(2)}ms`,
6668
);
6769
} else {
6870
console.error(`❌ ${agentConfig.name} - NO RESPONSE within timeout`);

agents/monitoring/agents-untagged.test.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ import { ActionsCodec } from "agents/utils/inline-actions/types/ActionsContent";
66
import { IntentCodec } from "agents/utils/inline-actions/types/IntentContent";
77
import { describe, expect, it } from "vitest";
88
import productionAgents from "./agents";
9-
import { waitForResponse, type AgentConfig } from "./helper";
9+
import {
10+
AGENT_RESPONSE_TIMEOUT,
11+
waitForResponse,
12+
type AgentConfig,
13+
} from "./helper";
1014

1115
const testName = "agents-untagged";
12-
const TIMEOUT = 30000; // 30 seconds
1316

1417
describe(testName, () => {
1518
setupDurationTracking({ testName, initDataDog: true });
@@ -55,7 +58,7 @@ describe(testName, () => {
5558
},
5659
conversationId: conversation.id,
5760
senderInboxId: agent.client.inboxId,
58-
timeout: TIMEOUT,
61+
timeout: AGENT_RESPONSE_TIMEOUT,
5962
messageText: "hi",
6063
});
6164
} catch {
@@ -73,15 +76,15 @@ describe(testName, () => {
7376
},
7477
conversationId: conversation.id,
7578
senderInboxId: agent.client.inboxId,
76-
timeout: TIMEOUT,
79+
timeout: AGENT_RESPONSE_TIMEOUT,
7780
messageText: "hi",
7881
});
7982
} catch {
8083
// No response is expected for untagged messages
8184
result = {
8285
success: false,
8386
sendTime: 0,
84-
responseTime: TIMEOUT,
87+
responseTime: AGENT_RESPONSE_TIMEOUT,
8588
responseMessage: null,
8689
};
8790
}
@@ -90,9 +93,8 @@ describe(testName, () => {
9093
sendMetric("response", responseTime, createMetricTags(agentConfig));
9194

9295
if (result.success && result.responseMessage) {
93-
const responseContent = result.responseMessage.content as string;
9496
console.log(
95-
`⚠️ ${agentConfig.name} responded to untagged message in ${responseTime.toFixed(2)}ms - "${responseContent}"`,
97+
`⚠️ ${agentConfig.name} responded to untagged message in ${responseTime.toFixed(2)}ms`,
9698
);
9799
} else {
98100
console.log(

0 commit comments

Comments
 (0)