@elizaos/cli 1.3.2 → 1.4.2
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 +46 -0
- package/dist/{bun-exec-6CQHTS4F.js → bun-exec-ULMPAIQC.js} +1 -1
- package/dist/{chunk-E6XYTE3A.js → chunk-D3QSET5H.js} +69 -72
- package/dist/{chunk-FDEDLANP.js → chunk-FQYWRHLX.js} +1 -1
- package/dist/{chunk-T2QDIXGU.js → chunk-FSSUAWXQ.js} +3 -3
- package/dist/{chunk-D3Q2UZLZ.js → chunk-I4L4T7QX.js} +1 -1
- package/dist/{chunk-5GUS4CFO.js → chunk-SMZBJQJR.js} +1 -1
- package/dist/commands/agent/actions/index.js +3 -3
- package/dist/commands/agent/index.js +3 -3
- package/dist/commands/create/actions/index.js +4 -4
- package/dist/commands/create/index.js +5 -5
- package/dist/index.js +134 -109
- package/dist/{plugin-creator-H26ZLR6H.js → plugin-creator-TCUFII32.js} +2 -2
- package/dist/{registry-433S5F3Y.js → registry-RF6PW3EN.js} +3 -3
- package/dist/templates/plugin-quick-starter/README.md +52 -10
- package/dist/templates/plugin-quick-starter/package.json +2 -2
- package/dist/templates/plugin-quick-starter/src/__tests__/e2e/README.md +140 -0
- package/dist/templates/plugin-quick-starter/src/__tests__/e2e/plugin-quick-starter.e2e.ts +339 -0
- package/dist/templates/plugin-quick-starter/src/__tests__/plugin.test.ts +55 -17
- package/dist/templates/plugin-quick-starter/src/plugin.ts +14 -14
- package/dist/templates/plugin-starter/README.md +124 -49
- package/dist/templates/plugin-starter/package.json +2 -2
- package/dist/templates/plugin-starter/src/__tests__/e2e/README.md +44 -9
- package/{templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts → dist/templates/plugin-starter/src/__tests__/e2e/plugin-starter.e2e.ts} +13 -20
- package/dist/templates/plugin-starter/src/plugin.ts +5 -7
- package/dist/templates/project-starter/README.md +24 -11
- package/dist/templates/project-starter/package.json +4 -4
- package/dist/templates/project-starter/src/__tests__/actions.test.ts +2 -2
- package/dist/templates/project-starter/src/__tests__/e2e/README.md +103 -0
- package/dist/templates/project-starter/src/__tests__/e2e/project-starter.e2e.ts +575 -0
- package/dist/templates/project-starter/src/__tests__/integration.test.ts +1 -1
- package/dist/templates/project-starter/src/__tests__/models.test.ts +3 -3
- package/dist/templates/project-starter/src/__tests__/plugin.test.ts +3 -3
- package/dist/templates/project-starter/src/__tests__/provider.test.ts +2 -2
- package/dist/templates/project-starter/src/index.ts +4 -3
- package/dist/templates/project-starter/src/plugin.ts +5 -5
- package/dist/templates/project-tee-starter/README.md +44 -5
- package/dist/templates/project-tee-starter/package.json +4 -4
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/build-order.test.ts +1 -1
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/character.test.ts +1 -1
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/config.test.ts +1 -1
- package/dist/templates/project-tee-starter/src/__tests__/e2e/README.md +128 -0
- package/dist/templates/project-tee-starter/src/__tests__/e2e/project-tee-starter.e2e.ts +280 -0
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/env.test.ts +1 -1
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/error-handling.test.ts +2 -2
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/events.test.ts +1 -1
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/file-structure.test.ts +2 -2
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/integration.test.ts +2 -2
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/models.test.ts +1 -1
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/plugin.test.ts +1 -1
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/provider.test.ts +2 -2
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/routes.test.ts +1 -1
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/tee-validation.test.ts +1 -1
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/test-utils.ts +2 -2
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/vite-config-utils.ts +14 -2
- package/dist/templates/project-tee-starter/src/index.ts +2 -0
- package/dist/templates/project-tee-starter/src/plugin.ts +19 -7
- package/dist/{utils-DBLSDYBF.js → utils-5HPZSIF6.js} +3 -3
- package/package.json +6 -6
- package/templates/plugin-quick-starter/README.md +52 -10
- package/templates/plugin-quick-starter/package.json +2 -2
- package/templates/plugin-quick-starter/src/__tests__/e2e/README.md +140 -0
- package/templates/plugin-quick-starter/src/__tests__/e2e/plugin-quick-starter.e2e.ts +339 -0
- package/templates/plugin-quick-starter/src/__tests__/plugin.test.ts +55 -17
- package/templates/plugin-quick-starter/src/plugin.ts +14 -14
- package/templates/plugin-starter/README.md +124 -49
- package/templates/plugin-starter/package.json +2 -2
- package/templates/plugin-starter/src/__tests__/e2e/README.md +44 -9
- package/{dist/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts → templates/plugin-starter/src/__tests__/e2e/plugin-starter.e2e.ts} +13 -20
- package/templates/plugin-starter/src/plugin.ts +5 -7
- package/templates/project-starter/README.md +24 -11
- package/templates/project-starter/package.json +4 -4
- package/templates/project-starter/src/__tests__/actions.test.ts +2 -2
- package/templates/project-starter/src/__tests__/e2e/README.md +103 -0
- package/templates/project-starter/src/__tests__/e2e/project-starter.e2e.ts +575 -0
- package/templates/project-starter/src/__tests__/integration.test.ts +1 -1
- package/templates/project-starter/src/__tests__/models.test.ts +3 -3
- package/templates/project-starter/src/__tests__/plugin.test.ts +3 -3
- package/templates/project-starter/src/__tests__/provider.test.ts +2 -2
- package/templates/project-starter/src/index.ts +4 -3
- package/templates/project-starter/src/plugin.ts +5 -5
- package/templates/project-tee-starter/README.md +44 -5
- package/templates/project-tee-starter/package.json +4 -4
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/build-order.test.ts +1 -1
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/character.test.ts +1 -1
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/config.test.ts +1 -1
- package/templates/project-tee-starter/src/__tests__/e2e/README.md +128 -0
- package/templates/project-tee-starter/src/__tests__/e2e/project-tee-starter.e2e.ts +280 -0
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/env.test.ts +1 -1
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/error-handling.test.ts +2 -2
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/events.test.ts +1 -1
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/file-structure.test.ts +2 -2
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/integration.test.ts +2 -2
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/models.test.ts +1 -1
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/plugin.test.ts +1 -1
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/provider.test.ts +2 -2
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/routes.test.ts +1 -1
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/tee-validation.test.ts +1 -1
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/test-utils.ts +2 -2
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/vite-config-utils.ts +14 -2
- package/templates/project-tee-starter/src/index.ts +2 -0
- package/templates/project-tee-starter/src/plugin.ts +19 -7
- package/dist/templates/plugin-starter/src/tests.ts +0 -6
- package/dist/templates/project-starter/src/__tests__/e2e/index.ts +0 -14
- package/dist/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +0 -246
- package/dist/templates/project-starter/src/__tests__/e2e/project.test.ts +0 -155
- package/dist/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +0 -421
- package/dist/templates/project-tee-starter/e2e/project.test.ts +0 -38
- package/dist/templates/project-tee-starter/e2e/starter-plugin.test.ts +0 -92
- package/templates/plugin-starter/src/tests.ts +0 -6
- package/templates/project-starter/src/__tests__/e2e/index.ts +0 -14
- package/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +0 -246
- package/templates/project-starter/src/__tests__/e2e/project.test.ts +0 -155
- package/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +0 -421
- package/templates/project-tee-starter/e2e/project.test.ts +0 -38
- package/templates/project-tee-starter/e2e/starter-plugin.test.ts +0 -92
- /package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/actions.test.ts +0 -0
- /package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/frontend.test.ts +0 -0
- /package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/utils/core-test-utils.ts +0 -0
- /package/templates/project-tee-starter/{__tests__ → src/__tests__}/actions.test.ts +0 -0
- /package/templates/project-tee-starter/{__tests__ → src/__tests__}/frontend.test.ts +0 -0
- /package/templates/project-tee-starter/{__tests__ → src/__tests__}/utils/core-test-utils.ts +0 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Content,
|
|
3
|
+
type HandlerCallback,
|
|
4
|
+
type Memory,
|
|
5
|
+
type UUID,
|
|
6
|
+
type Plugin,
|
|
7
|
+
type Action,
|
|
8
|
+
type Provider,
|
|
9
|
+
type IAgentRuntime,
|
|
10
|
+
type TestSuite,
|
|
11
|
+
logger,
|
|
12
|
+
} from '@elizaos/core';
|
|
13
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
14
|
+
|
|
15
|
+
// Define proper interfaces for E2E testing
|
|
16
|
+
interface E2ETestFiles {
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface E2ETestContent extends Content {
|
|
21
|
+
text?: string;
|
|
22
|
+
actions?: string[];
|
|
23
|
+
source?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* E2E (End-to-End) Test Suite for ElizaOS Plugin Quick Starter
|
|
28
|
+
* =============================================================
|
|
29
|
+
*
|
|
30
|
+
* This file contains end-to-end tests that run within a real ElizaOS runtime environment.
|
|
31
|
+
* Unlike unit tests that test individual components in isolation, e2e tests validate
|
|
32
|
+
* the entire plugin behavior in a production-like environment.
|
|
33
|
+
*
|
|
34
|
+
* NOTE: The tests are properly structured and included in the plugin build.
|
|
35
|
+
* If the test runner is not detecting these tests, it may be looking at the wrong
|
|
36
|
+
* plugin name or there may be a test runner configuration issue. The tests are
|
|
37
|
+
* exported correctly through src/plugin.ts and included in the plugin's tests array.
|
|
38
|
+
*
|
|
39
|
+
* HOW E2E TESTS WORK:
|
|
40
|
+
* -------------------
|
|
41
|
+
* 1. Tests are executed by the ElizaOS test runner using `elizaos test e2e`
|
|
42
|
+
* 2. Each test receives a real runtime instance with the plugin loaded
|
|
43
|
+
* 3. Tests can interact with the runtime just like in production
|
|
44
|
+
* 4. Tests throw errors to indicate failure (no assertion library needed)
|
|
45
|
+
*
|
|
46
|
+
* WRITING NEW E2E TESTS:
|
|
47
|
+
* ----------------------
|
|
48
|
+
* 1. Add a new test object to the `tests` array below
|
|
49
|
+
* 2. Each test must have:
|
|
50
|
+
* - `name`: A unique identifier for the test
|
|
51
|
+
* - `fn`: An async function that receives the runtime and performs the test
|
|
52
|
+
*
|
|
53
|
+
* Example structure:
|
|
54
|
+
* ```typescript
|
|
55
|
+
* {
|
|
56
|
+
* name: 'my_new_test',
|
|
57
|
+
* fn: async (runtime: IAgentRuntime) => {
|
|
58
|
+
* // Your test logic here
|
|
59
|
+
* if (someCondition !== expected) {
|
|
60
|
+
* throw new Error('Test failed: reason');
|
|
61
|
+
* }
|
|
62
|
+
* }
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* BEST PRACTICES:
|
|
67
|
+
* ---------------
|
|
68
|
+
* - Test real user scenarios, not implementation details
|
|
69
|
+
* - Use descriptive test names that explain what's being tested
|
|
70
|
+
* - Include clear error messages that help diagnose failures
|
|
71
|
+
* - Test both success and failure paths
|
|
72
|
+
* - Clean up any resources created during tests
|
|
73
|
+
*
|
|
74
|
+
* QUICK STARTER SPECIFICS:
|
|
75
|
+
* ------------------------
|
|
76
|
+
* The quick starter plugin is a minimal template designed for rapid prototyping.
|
|
77
|
+
* Tests focus on:
|
|
78
|
+
* - Basic plugin loading and registration
|
|
79
|
+
* - Simple action execution
|
|
80
|
+
* - Provider functionality
|
|
81
|
+
* - Minimal service lifecycle
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Quick Starter Plugin E2E Test Suite
|
|
86
|
+
*
|
|
87
|
+
* This test suite validates the basic functionality of the quick starter plugin.
|
|
88
|
+
*/
|
|
89
|
+
export const QuickStarterPluginTestSuite: TestSuite = {
|
|
90
|
+
name: 'Plugin Quick Starter E2E Tests',
|
|
91
|
+
tests: [
|
|
92
|
+
{
|
|
93
|
+
name: 'plugin_should_be_loaded',
|
|
94
|
+
fn: async (runtime: IAgentRuntime) => {
|
|
95
|
+
// Check if the plugin is registered
|
|
96
|
+
const plugin = runtime.plugins.find((p: Plugin) => p.name === 'plugin-quick-starter');
|
|
97
|
+
|
|
98
|
+
if (!plugin) {
|
|
99
|
+
throw new Error('Plugin quick-starter is not loaded in the runtime');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
logger.info('✓ Plugin quick-starter loaded successfully');
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'should_have_quick_action_registered',
|
|
107
|
+
fn: async (runtime: IAgentRuntime) => {
|
|
108
|
+
// Check if the quick action is registered
|
|
109
|
+
const action = runtime.actions.find((a: Action) => a.name === 'QUICK_ACTION');
|
|
110
|
+
|
|
111
|
+
if (!action) {
|
|
112
|
+
throw new Error('QUICK_ACTION is not registered');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Verify action has required properties
|
|
116
|
+
if (!action.name || action.name !== 'QUICK_ACTION') {
|
|
117
|
+
throw new Error('Action name is incorrect');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!action.handler || typeof action.handler !== 'function') {
|
|
121
|
+
throw new Error('Action handler is not a function');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
logger.info('✓ QUICK_ACTION registered correctly');
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: 'quick_action_should_execute_successfully',
|
|
129
|
+
fn: async (runtime: IAgentRuntime) => {
|
|
130
|
+
// Create a test message
|
|
131
|
+
const testMessage = {
|
|
132
|
+
id: 'quick-test-1' as UUID,
|
|
133
|
+
userId: 'test-user' as UUID,
|
|
134
|
+
agentId: runtime.agentId,
|
|
135
|
+
entityId: 'test-user' as UUID,
|
|
136
|
+
roomId: 'quick-test-room' as UUID,
|
|
137
|
+
content: {
|
|
138
|
+
text: 'quick test',
|
|
139
|
+
action: null,
|
|
140
|
+
} as Content,
|
|
141
|
+
createdAt: Date.now(),
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
let callbackExecuted = false;
|
|
145
|
+
let responseText = '';
|
|
146
|
+
|
|
147
|
+
// Create a callback to capture the response
|
|
148
|
+
const callback: HandlerCallback = async (
|
|
149
|
+
response: Content,
|
|
150
|
+
files?: E2ETestFiles
|
|
151
|
+
): Promise<Memory[]> => {
|
|
152
|
+
callbackExecuted = true;
|
|
153
|
+
responseText = response.text || '';
|
|
154
|
+
const responseMemory: Memory = {
|
|
155
|
+
id: 'response-quick' as UUID,
|
|
156
|
+
entityId: runtime.agentId,
|
|
157
|
+
agentId: runtime.agentId,
|
|
158
|
+
roomId: 'quick-test-room' as UUID,
|
|
159
|
+
content: response,
|
|
160
|
+
createdAt: Date.now(),
|
|
161
|
+
embedding: [],
|
|
162
|
+
};
|
|
163
|
+
return [responseMemory];
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// Get the action
|
|
167
|
+
const action = runtime.actions.find((a: Action) => a.name === 'QUICK_ACTION');
|
|
168
|
+
if (!action) {
|
|
169
|
+
throw new Error('QUICK_ACTION not found');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Execute the action handler
|
|
173
|
+
const result = await action.handler(runtime, testMessage, undefined, {}, callback);
|
|
174
|
+
|
|
175
|
+
// Verify the action executed successfully
|
|
176
|
+
if (!result || !result.success) {
|
|
177
|
+
throw new Error('Quick action did not execute successfully');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (!callbackExecuted) {
|
|
181
|
+
throw new Error('Callback was not executed');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!responseText || responseText.trim() === '') {
|
|
185
|
+
throw new Error('Response text is empty');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
logger.info(`✓ Quick action executed successfully with response: "${responseText}"`);
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: 'quick_provider_should_provide_data',
|
|
193
|
+
fn: async (runtime: IAgentRuntime) => {
|
|
194
|
+
// Check if the provider is registered
|
|
195
|
+
const provider = runtime.providers.find((p: Provider) => p.name === 'QUICK_PROVIDER');
|
|
196
|
+
|
|
197
|
+
if (!provider) {
|
|
198
|
+
throw new Error('QUICK_PROVIDER is not registered');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Test the provider's get method
|
|
202
|
+
const mockMessage = {
|
|
203
|
+
id: 'provider-test-1' as UUID,
|
|
204
|
+
userId: 'test-user' as UUID,
|
|
205
|
+
agentId: runtime.agentId,
|
|
206
|
+
entityId: 'test-user' as UUID,
|
|
207
|
+
roomId: 'provider-test-room' as UUID,
|
|
208
|
+
content: { text: 'test' },
|
|
209
|
+
createdAt: Date.now(),
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const result = await provider.get(runtime, mockMessage, { values: {}, data: {}, text: '' });
|
|
213
|
+
|
|
214
|
+
// Verify provider returns data
|
|
215
|
+
if (!result) {
|
|
216
|
+
throw new Error('Provider returned no result');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!result.text || result.text.trim() === '') {
|
|
220
|
+
throw new Error('Provider returned empty text');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
logger.info(`✓ Quick provider returned data: "${result.text}"`);
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: 'quick_service_should_be_available',
|
|
228
|
+
fn: async (runtime: IAgentRuntime) => {
|
|
229
|
+
// Check if the starter service is available
|
|
230
|
+
const service = runtime.getService('starter');
|
|
231
|
+
|
|
232
|
+
if (!service) {
|
|
233
|
+
logger.warn('⚠ Starter service not available (optional service)');
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
logger.info('✓ Starter service is available');
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: 'plugin_should_integrate_with_agent_correctly',
|
|
242
|
+
fn: async (runtime: IAgentRuntime) => {
|
|
243
|
+
// Test that the plugin integrates properly with the agent
|
|
244
|
+
const testMessage = {
|
|
245
|
+
id: 'integration-test-1' as UUID,
|
|
246
|
+
userId: 'test-user' as UUID,
|
|
247
|
+
agentId: runtime.agentId,
|
|
248
|
+
entityId: 'test-user' as UUID,
|
|
249
|
+
roomId: 'integration-test-room' as UUID,
|
|
250
|
+
content: {
|
|
251
|
+
text: 'test quick plugin integration',
|
|
252
|
+
action: null,
|
|
253
|
+
} as Content,
|
|
254
|
+
createdAt: Date.now(),
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
let responseReceived = false;
|
|
258
|
+
|
|
259
|
+
// Process message through the runtime
|
|
260
|
+
await runtime.processActions(
|
|
261
|
+
testMessage,
|
|
262
|
+
[],
|
|
263
|
+
undefined,
|
|
264
|
+
async (response: Content): Promise<Memory[]> => {
|
|
265
|
+
responseReceived = true;
|
|
266
|
+
const responseMemory: Memory = {
|
|
267
|
+
id: 'response-integration' as UUID,
|
|
268
|
+
entityId: runtime.agentId,
|
|
269
|
+
agentId: runtime.agentId,
|
|
270
|
+
roomId: 'integration-test-room' as UUID,
|
|
271
|
+
content: response,
|
|
272
|
+
createdAt: Date.now(),
|
|
273
|
+
embedding: [],
|
|
274
|
+
};
|
|
275
|
+
return [responseMemory];
|
|
276
|
+
}
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
// Basic integration check - agent should process messages
|
|
280
|
+
if (!responseReceived) {
|
|
281
|
+
logger.warn('⚠ No response received (this may be normal if no action was triggered)');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
logger.info('✓ Plugin integrates with agent runtime correctly');
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
name: 'plugin_database_adapter_should_be_registered',
|
|
289
|
+
fn: async (runtime: IAgentRuntime) => {
|
|
290
|
+
// Verify that the runtime has a database adapter
|
|
291
|
+
// This is a basic check to ensure the plugin can work with the database
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
// Try to get the connection - this should exist
|
|
295
|
+
const connection = await runtime.getConnection();
|
|
296
|
+
if (connection) {
|
|
297
|
+
logger.info('✓ Plugin can access database connection');
|
|
298
|
+
} else {
|
|
299
|
+
throw new Error('No database connection available');
|
|
300
|
+
}
|
|
301
|
+
} catch (error) {
|
|
302
|
+
// If there's an error getting connection, it might be expected in test environment
|
|
303
|
+
logger.info('⚠ Database connection test skipped (test environment limitation)');
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
name: 'plugin_should_handle_errors_gracefully',
|
|
309
|
+
fn: async (runtime: IAgentRuntime) => {
|
|
310
|
+
// Test error handling with invalid input
|
|
311
|
+
const invalidMessage = {
|
|
312
|
+
id: 'error-test-1' as UUID,
|
|
313
|
+
userId: 'test-user' as UUID,
|
|
314
|
+
agentId: runtime.agentId,
|
|
315
|
+
entityId: 'test-user' as UUID,
|
|
316
|
+
roomId: 'error-test-room' as UUID,
|
|
317
|
+
content: null, // Invalid content
|
|
318
|
+
createdAt: Date.now(),
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
try {
|
|
322
|
+
// Attempt to create memory with invalid message
|
|
323
|
+
await runtime.createMemory(invalidMessage as any, 'messages', false);
|
|
324
|
+
|
|
325
|
+
// If we get here without error, that's also acceptable
|
|
326
|
+
logger.info('✓ Plugin handled invalid input without crashing');
|
|
327
|
+
} catch (error) {
|
|
328
|
+
// Error handling is working
|
|
329
|
+
logger.info(
|
|
330
|
+
'✓ Plugin properly handles errors:',
|
|
331
|
+
error instanceof Error ? error.message : String(error)
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
],
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
export default QuickStarterPluginTestSuite;
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
ModelType,
|
|
10
10
|
logger,
|
|
11
11
|
EventType,
|
|
12
|
+
Action,
|
|
12
13
|
} from '@elizaos/core';
|
|
13
14
|
import dotenv from 'dotenv';
|
|
14
15
|
import {
|
|
@@ -19,6 +20,38 @@ import {
|
|
|
19
20
|
testFixtures,
|
|
20
21
|
} from './test-utils';
|
|
21
22
|
|
|
23
|
+
// Define proper interfaces for test mocking
|
|
24
|
+
interface MockLoggerMethod {
|
|
25
|
+
calls?: any[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface MockLogger {
|
|
29
|
+
info: MockLoggerMethod;
|
|
30
|
+
error: MockLoggerMethod;
|
|
31
|
+
debug: MockLoggerMethod;
|
|
32
|
+
warn: MockLoggerMethod;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface PluginConfig {
|
|
36
|
+
EXAMPLE_PLUGIN_VARIABLE?: string | number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface TestCallbackContent {
|
|
40
|
+
text?: string;
|
|
41
|
+
actions?: string[];
|
|
42
|
+
source?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface TestActionResult {
|
|
46
|
+
text?: string;
|
|
47
|
+
success: boolean;
|
|
48
|
+
data?: {
|
|
49
|
+
actions?: string[];
|
|
50
|
+
source?: string;
|
|
51
|
+
};
|
|
52
|
+
error?: Error;
|
|
53
|
+
}
|
|
54
|
+
|
|
22
55
|
// Setup environment variables
|
|
23
56
|
dotenv.config();
|
|
24
57
|
|
|
@@ -79,7 +112,7 @@ describe('Plugin Configuration', () => {
|
|
|
79
112
|
const invalidConfig = { EXAMPLE_PLUGIN_VARIABLE: 123 }; // Should be string
|
|
80
113
|
|
|
81
114
|
if (starterPlugin.init) {
|
|
82
|
-
await expect(starterPlugin.init(invalidConfig as
|
|
115
|
+
await expect(starterPlugin.init(invalidConfig as PluginConfig, runtime)).rejects.toThrow(
|
|
83
116
|
'Invalid plugin configuration'
|
|
84
117
|
);
|
|
85
118
|
}
|
|
@@ -88,21 +121,22 @@ describe('Plugin Configuration', () => {
|
|
|
88
121
|
|
|
89
122
|
describe('Hello World Action', () => {
|
|
90
123
|
let runtime: IAgentRuntime;
|
|
91
|
-
let helloWorldAction:
|
|
124
|
+
let helloWorldAction: Action;
|
|
92
125
|
|
|
93
126
|
beforeEach(() => {
|
|
94
127
|
runtime = createMockRuntime();
|
|
95
|
-
helloWorldAction = starterPlugin
|
|
128
|
+
helloWorldAction = starterPlugin?.actions?.[0] as Action;
|
|
96
129
|
// Clear all spies before each test
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
130
|
+
const mockLogger = logger as unknown as MockLogger;
|
|
131
|
+
mockLogger.info.calls = [];
|
|
132
|
+
mockLogger.error.calls = [];
|
|
133
|
+
mockLogger.debug.calls = [];
|
|
134
|
+
mockLogger.warn.calls = [];
|
|
101
135
|
});
|
|
102
136
|
|
|
103
137
|
it('should have hello world action', () => {
|
|
104
138
|
expect(helloWorldAction).toBeDefined();
|
|
105
|
-
expect(helloWorldAction?.name).toBe('
|
|
139
|
+
expect(helloWorldAction?.name).toBe('QUICK_ACTION');
|
|
106
140
|
});
|
|
107
141
|
|
|
108
142
|
it('should always validate messages (current implementation)', async () => {
|
|
@@ -180,9 +214,9 @@ describe('Hello World Action', () => {
|
|
|
180
214
|
content: { text: 'say hello', source: 'test' },
|
|
181
215
|
});
|
|
182
216
|
|
|
183
|
-
let callbackContent:
|
|
217
|
+
let callbackContent: TestCallbackContent | null = null;
|
|
184
218
|
const callback: HandlerCallback = async (content: Content) => {
|
|
185
|
-
callbackContent = content;
|
|
219
|
+
callbackContent = content as TestCallbackContent;
|
|
186
220
|
return [];
|
|
187
221
|
};
|
|
188
222
|
|
|
@@ -191,12 +225,13 @@ describe('Hello World Action', () => {
|
|
|
191
225
|
expect(result).toHaveProperty('text', 'Hello world!');
|
|
192
226
|
expect(result).toHaveProperty('success', true);
|
|
193
227
|
expect(result).toHaveProperty('data');
|
|
194
|
-
|
|
195
|
-
expect(
|
|
228
|
+
const typedResult = result as TestActionResult;
|
|
229
|
+
expect(typedResult.data).toHaveProperty('actions', ['QUICK_ACTION']);
|
|
230
|
+
expect(typedResult.data).toHaveProperty('source', 'test');
|
|
196
231
|
|
|
197
232
|
expect(callbackContent).toEqual({
|
|
198
233
|
text: 'Hello world!',
|
|
199
|
-
actions: ['
|
|
234
|
+
actions: ['QUICK_ACTION'],
|
|
200
235
|
source: 'test',
|
|
201
236
|
});
|
|
202
237
|
});
|
|
@@ -224,7 +259,8 @@ describe('Hello World Action', () => {
|
|
|
224
259
|
|
|
225
260
|
expect(result).toHaveProperty('success', false);
|
|
226
261
|
expect(result).toHaveProperty('error');
|
|
227
|
-
|
|
262
|
+
const typedResult = result as TestActionResult;
|
|
263
|
+
expect(typedResult.error?.message).toBe('Callback error');
|
|
228
264
|
// Quick-starter plugin doesn't log errors
|
|
229
265
|
});
|
|
230
266
|
|
|
@@ -278,7 +314,7 @@ describe('Hello World Provider', () => {
|
|
|
278
314
|
|
|
279
315
|
it('should have hello world provider', () => {
|
|
280
316
|
expect(provider).toBeDefined();
|
|
281
|
-
expect(provider?.name).toBe('
|
|
317
|
+
expect(provider?.name).toBe('QUICK_PROVIDER');
|
|
282
318
|
});
|
|
283
319
|
|
|
284
320
|
it('should provide hello world data', async () => {
|
|
@@ -310,9 +346,11 @@ describe('Hello World Provider', () => {
|
|
|
310
346
|
const result2 = await provider.get(runtime, message, state);
|
|
311
347
|
|
|
312
348
|
// Text and structure should be consistent
|
|
349
|
+
expect(result1.text).toBeDefined();
|
|
350
|
+
expect(result2.text).toBeDefined();
|
|
313
351
|
expect(result1.text).toBe(result2.text);
|
|
314
|
-
expect(result1.values).toEqual(result2.values);
|
|
315
|
-
expect(result1.data).toEqual(result2.data);
|
|
352
|
+
expect(result1.values || {}).toEqual(result2.values || {});
|
|
353
|
+
expect(result1.data || {}).toEqual(result2.data || {});
|
|
316
354
|
});
|
|
317
355
|
});
|
|
318
356
|
|
|
@@ -51,9 +51,9 @@ const configSchema = z.object({
|
|
|
51
51
|
* @property {Function} handler - Asynchronous function to handle the action and generate a response.
|
|
52
52
|
* @property {Object[]} examples - An array of example inputs and expected outputs for the action.
|
|
53
53
|
*/
|
|
54
|
-
const
|
|
55
|
-
name: '
|
|
56
|
-
similes: ['GREET', 'SAY_HELLO'],
|
|
54
|
+
const quickAction: Action = {
|
|
55
|
+
name: 'QUICK_ACTION',
|
|
56
|
+
similes: ['GREET', 'SAY_HELLO', 'HELLO_WORLD'],
|
|
57
57
|
description: 'Responds with a simple hello world message',
|
|
58
58
|
|
|
59
59
|
validate: async (
|
|
@@ -79,7 +79,7 @@ const helloWorldAction: Action = {
|
|
|
79
79
|
if (callback) {
|
|
80
80
|
await callback({
|
|
81
81
|
text: response,
|
|
82
|
-
actions: ['
|
|
82
|
+
actions: ['QUICK_ACTION'],
|
|
83
83
|
source: message.content.source,
|
|
84
84
|
});
|
|
85
85
|
}
|
|
@@ -88,7 +88,7 @@ const helloWorldAction: Action = {
|
|
|
88
88
|
text: response,
|
|
89
89
|
success: true,
|
|
90
90
|
data: {
|
|
91
|
-
actions: ['
|
|
91
|
+
actions: ['QUICK_ACTION'],
|
|
92
92
|
source: message.content.source,
|
|
93
93
|
},
|
|
94
94
|
};
|
|
@@ -112,7 +112,7 @@ const helloWorldAction: Action = {
|
|
|
112
112
|
name: '{{name2}}',
|
|
113
113
|
content: {
|
|
114
114
|
text: 'hello world!',
|
|
115
|
-
actions: ['
|
|
115
|
+
actions: ['QUICK_ACTION'],
|
|
116
116
|
},
|
|
117
117
|
},
|
|
118
118
|
],
|
|
@@ -123,8 +123,8 @@ const helloWorldAction: Action = {
|
|
|
123
123
|
* Example Hello World Provider
|
|
124
124
|
* This demonstrates the simplest possible provider implementation
|
|
125
125
|
*/
|
|
126
|
-
const
|
|
127
|
-
name: '
|
|
126
|
+
const quickProvider: Provider = {
|
|
127
|
+
name: 'QUICK_PROVIDER',
|
|
128
128
|
description: 'A simple example provider',
|
|
129
129
|
|
|
130
130
|
get: async (
|
|
@@ -235,31 +235,31 @@ export const starterPlugin: Plugin = {
|
|
|
235
235
|
[EventType.MESSAGE_RECEIVED]: [
|
|
236
236
|
async (params: MessagePayload) => {
|
|
237
237
|
logger.debug('MESSAGE_RECEIVED event received');
|
|
238
|
-
logger.debug(
|
|
238
|
+
logger.debug({ message: params.message }, 'Message:');
|
|
239
239
|
},
|
|
240
240
|
],
|
|
241
241
|
[EventType.VOICE_MESSAGE_RECEIVED]: [
|
|
242
242
|
async (params: MessagePayload) => {
|
|
243
243
|
logger.debug('VOICE_MESSAGE_RECEIVED event received');
|
|
244
|
-
logger.debug(
|
|
244
|
+
logger.debug({ message: params.message }, 'Message:');
|
|
245
245
|
},
|
|
246
246
|
],
|
|
247
247
|
[EventType.WORLD_CONNECTED]: [
|
|
248
248
|
async (params: WorldPayload) => {
|
|
249
249
|
logger.debug('WORLD_CONNECTED event received');
|
|
250
|
-
logger.debug(
|
|
250
|
+
logger.debug({ world: params.world }, 'World:');
|
|
251
251
|
},
|
|
252
252
|
],
|
|
253
253
|
[EventType.WORLD_JOINED]: [
|
|
254
254
|
async (params: WorldPayload) => {
|
|
255
255
|
logger.debug('WORLD_JOINED event received');
|
|
256
|
-
logger.debug(
|
|
256
|
+
logger.debug({ world: params.world }, 'World:');
|
|
257
257
|
},
|
|
258
258
|
],
|
|
259
259
|
},
|
|
260
260
|
services: [StarterService],
|
|
261
|
-
actions: [
|
|
262
|
-
providers: [
|
|
261
|
+
actions: [quickAction],
|
|
262
|
+
providers: [quickProvider],
|
|
263
263
|
// dependencies: ['@elizaos/plugin-knowledge'], <--- plugin dependencies go here (if requires another plugin)
|
|
264
264
|
};
|
|
265
265
|
|