@elizaos/cli 1.0.9 → 1.0.10
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 +9 -16
- package/dist/assets/{index-CCyz05Yl.js → index-CmuPnu0u.js} +72 -89
- package/dist/assets/index-CmuPnu0u.js.br +0 -0
- package/dist/assets/index-CmuPnu0u.js.map +1 -0
- package/dist/assets/{index-Cxd2b7is.js → index-DDQnwxzL.js} +1318 -13721
- package/dist/assets/{index-Cxd2b7is.js.map → index-DDQnwxzL.js.map} +1 -1
- package/dist/assets/index-Df1AFSuJ.css +1 -0
- package/dist/assets/index-Df1AFSuJ.css.br +0 -0
- package/dist/assets/vendor-DSdxb8P-.js.map +1 -1
- package/dist/{chunk-Y755OOSP.js → chunk-7HYEGM5V.js} +877 -1550
- package/dist/{chunk-HZQCHL3J.js → chunk-B4KJXECB.js} +13 -18
- package/dist/{chunk-Z6GVELRX.js → chunk-GWQB7PBK.js} +58 -29
- package/dist/{chunk-CVADLFW6.js → chunk-LQ6XHF53.js} +4543 -3043
- package/dist/{chunk-JWONHNLD.js → chunk-RIAWNDYI.js} +2 -9
- package/dist/{chunk-IEKLJDUU.js → chunk-WS4DWCDZ.js} +54 -32
- package/dist/commands/agent/actions/index.d.ts +5 -1
- package/dist/commands/agent/actions/index.js +5 -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/{fileFromPath-DCRQMDLJ.js → fileFromPath-KB6XMTJ4.js} +1 -0
- package/dist/index.html +2 -2
- package/dist/index.js +9351 -102236
- package/dist/{migrator-KZLCVEIH.js → migrator-JREQPDN3.js} +42 -220
- package/dist/pglite.data +0 -0
- package/dist/pglite.wasm +0 -0
- package/dist/plugin-creator-T4K2673C.js +910 -0
- package/dist/{registry-W7CIK4O2.js → registry-CBMRMYCG.js} +3 -3
- package/dist/templates/plugin-starter/README.md +255 -0
- package/dist/templates/plugin-starter/bunfig.toml +6 -0
- package/dist/templates/plugin-starter/cypress.config.ts +18 -0
- package/dist/templates/plugin-starter/index.html +13 -0
- package/dist/templates/plugin-starter/package.json +95 -0
- package/dist/templates/plugin-starter/postcss.config.js +3 -0
- package/dist/templates/plugin-starter/scripts/test-e2e-manual.js +201 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +404 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +287 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/support/commands.ts +38 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/support/component-index.html +11 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/support/component.ts +33 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/support/e2e.ts +11 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/tsconfig.json +10 -0
- package/dist/templates/plugin-starter/src/__tests__/e2e/README.md +47 -0
- package/dist/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts +320 -0
- package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/integration.test.ts +22 -17
- package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/plugin.test.ts +8 -8
- package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/test-utils.ts +17 -17
- package/dist/templates/plugin-starter/src/frontend/index.css +77 -0
- package/dist/templates/plugin-starter/src/frontend/index.tsx +164 -0
- package/dist/templates/plugin-starter/src/frontend/utils.ts +6 -0
- package/dist/templates/plugin-starter/src/index.ts +274 -0
- package/dist/templates/plugin-starter/src/tests.ts +6 -0
- package/dist/templates/plugin-starter/tailwind.config.js +62 -0
- package/dist/templates/plugin-starter/tsconfig.build.json +11 -0
- package/dist/templates/plugin-starter/tsconfig.json +28 -0
- package/dist/templates/plugin-starter/tsup.config.ts +20 -0
- package/dist/templates/plugin-starter/vite.config.ts +20 -0
- package/dist/templates/project-starter/.env.example +153 -0
- package/dist/templates/project-starter/README.md +109 -0
- package/dist/templates/project-starter/bunfig.toml +6 -0
- package/dist/templates/project-starter/cypress.config.ts +31 -0
- package/dist/templates/project-starter/index.html +13 -0
- package/dist/templates/project-starter/package.json +83 -0
- package/dist/templates/project-starter/postcss.config.js +3 -0
- package/dist/templates/project-starter/scripts/test-all.sh +101 -0
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/actions.test.ts +6 -6
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/character.test.ts +3 -3
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/config.test.ts +18 -18
- package/dist/templates/project-starter/src/__tests__/cypress/component/Accessibility.cy.tsx +271 -0
- package/dist/templates/project-starter/src/__tests__/cypress/component/ApiIntegration.cy.tsx +220 -0
- package/dist/templates/project-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +146 -0
- package/dist/templates/project-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +51 -0
- package/dist/templates/project-starter/src/__tests__/cypress/e2e/agent-chat.cy.ts +235 -0
- package/dist/templates/project-starter/src/__tests__/cypress/e2e/dashboard.cy.ts +146 -0
- package/dist/templates/project-starter/src/__tests__/cypress/e2e/user-workflow.cy.ts +257 -0
- package/dist/templates/project-starter/src/__tests__/cypress/support/commands.ts +44 -0
- package/dist/templates/project-starter/src/__tests__/cypress/support/component-index.html +11 -0
- package/dist/templates/project-starter/src/__tests__/cypress/support/component.ts +33 -0
- package/dist/templates/project-starter/src/__tests__/cypress/support/e2e.ts +179 -0
- package/dist/templates/project-starter/src/__tests__/e2e/index.ts +14 -0
- package/dist/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +246 -0
- package/dist/templates/project-starter/src/__tests__/e2e/project.test.ts +155 -0
- package/dist/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +421 -0
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/env.test.ts +2 -2
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/error-handling.test.ts +17 -17
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/events.test.ts +7 -7
- package/dist/templates/project-starter/src/__tests__/file-structure.test.ts +135 -0
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/integration.test.ts +25 -25
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/models.test.ts +6 -6
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/plugin.test.ts +9 -9
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/provider.test.ts +7 -7
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/routes.test.ts +3 -3
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/test-utils.ts +17 -17
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/utils/core-test-utils.ts +3 -3
- package/dist/templates/project-starter/src/frontend/index.css +77 -0
- package/dist/templates/project-starter/src/frontend/index.html +19 -0
- package/dist/templates/project-starter/src/frontend/index.tsx +98 -0
- package/dist/templates/project-starter/src/frontend/utils.ts +6 -0
- package/dist/templates/project-starter/src/index.ts +153 -0
- package/dist/templates/project-starter/src/plugin.ts +255 -0
- package/dist/templates/project-starter/tailwind.config.js +62 -0
- package/dist/templates/project-starter/tsconfig.build.json +20 -0
- package/dist/templates/project-starter/tsconfig.json +39 -0
- package/dist/templates/project-starter/tsup.config.ts +19 -0
- package/dist/templates/project-starter/vite.config.ts +39 -0
- package/dist/templates/project-tee-starter/.dockerignore +20 -0
- package/dist/templates/project-tee-starter/.env.example +55 -0
- package/dist/templates/project-tee-starter/Dockerfile +66 -0
- package/dist/templates/project-tee-starter/GUIDE.md +235 -0
- package/dist/templates/project-tee-starter/README.md +173 -0
- package/dist/templates/project-tee-starter/__tests__/actions.test.ts +9 -0
- package/dist/templates/project-tee-starter/__tests__/character.test.ts +86 -0
- package/dist/templates/project-tee-starter/__tests__/config.test.ts +31 -0
- package/dist/templates/project-tee-starter/__tests__/env.test.ts +87 -0
- package/dist/templates/project-tee-starter/__tests__/error-handling.test.ts +30 -0
- package/dist/templates/project-tee-starter/__tests__/events.test.ts +21 -0
- package/{templates/project-starter → dist/templates/project-tee-starter}/__tests__/file-structure.test.ts +6 -6
- package/dist/templates/project-tee-starter/__tests__/integration.test.ts +205 -0
- package/dist/templates/project-tee-starter/__tests__/models.test.ts +22 -0
- package/dist/templates/project-tee-starter/__tests__/plugin.test.ts +38 -0
- package/dist/templates/project-tee-starter/__tests__/provider.test.ts +189 -0
- package/dist/templates/project-tee-starter/__tests__/routes.test.ts +21 -0
- package/dist/templates/project-tee-starter/__tests__/test-utils.ts +121 -0
- package/dist/templates/project-tee-starter/__tests__/utils/core-test-utils.ts +167 -0
- package/dist/templates/project-tee-starter/assets/mr-tee-portrait.jpg +0 -0
- package/dist/templates/project-tee-starter/bunfig.toml +6 -0
- package/dist/templates/project-tee-starter/docker-compose.yaml +57 -0
- package/dist/templates/project-tee-starter/e2e/project.test.ts +38 -0
- package/dist/templates/project-tee-starter/e2e/starter-plugin.test.ts +92 -0
- package/dist/templates/project-tee-starter/package.json +74 -0
- package/dist/templates/project-tee-starter/src/character.ts +257 -0
- package/dist/templates/project-tee-starter/src/index.ts +33 -0
- package/dist/templates/project-tee-starter/src/plugin.ts +169 -0
- package/dist/templates/project-tee-starter/tsconfig.build.json +13 -0
- package/dist/templates/project-tee-starter/tsconfig.json +30 -0
- package/dist/templates/project-tee-starter/tsup.config.ts +19 -0
- package/dist/{utils-2G2QVMW3.js → utils-TIALZU53.js} +9 -7
- package/package.json +28 -9
- package/templates/plugin-starter/README.md +38 -13
- package/templates/plugin-starter/bunfig.toml +6 -0
- package/templates/plugin-starter/cypress.config.ts +18 -0
- package/templates/plugin-starter/index.html +13 -0
- package/templates/plugin-starter/package.json +19 -7
- package/templates/plugin-starter/postcss.config.js +3 -0
- package/templates/plugin-starter/scripts/test-e2e-manual.js +201 -0
- package/templates/plugin-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +404 -0
- package/templates/plugin-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +287 -0
- package/templates/plugin-starter/src/__tests__/cypress/support/commands.ts +38 -0
- package/templates/plugin-starter/src/__tests__/cypress/support/component-index.html +11 -0
- package/templates/plugin-starter/src/__tests__/cypress/support/component.ts +33 -0
- package/templates/plugin-starter/src/__tests__/cypress/support/e2e.ts +11 -0
- package/templates/plugin-starter/src/__tests__/cypress/tsconfig.json +10 -0
- package/templates/plugin-starter/src/__tests__/e2e/README.md +47 -0
- package/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts +320 -0
- package/templates/plugin-starter/src/__tests__/integration.test.ts +138 -0
- package/templates/plugin-starter/src/__tests__/plugin.test.ts +182 -0
- package/templates/plugin-starter/src/__tests__/test-utils.ts +162 -0
- package/templates/plugin-starter/src/frontend/index.css +77 -0
- package/templates/plugin-starter/src/frontend/index.tsx +164 -0
- package/templates/plugin-starter/src/frontend/utils.ts +6 -0
- package/templates/plugin-starter/src/index.ts +30 -7
- package/templates/plugin-starter/src/tests.ts +6 -0
- package/templates/plugin-starter/tailwind.config.js +62 -0
- package/templates/plugin-starter/tsconfig.json +8 -8
- package/templates/plugin-starter/vite.config.ts +20 -0
- package/templates/project-starter/bunfig.toml +6 -0
- package/templates/project-starter/cypress.config.ts +31 -0
- package/templates/project-starter/index.html +13 -0
- package/templates/project-starter/package.json +37 -14
- package/templates/project-starter/postcss.config.js +3 -0
- package/templates/project-starter/scripts/test-all.sh +101 -0
- package/templates/project-starter/src/__tests__/actions.test.ts +155 -0
- package/templates/project-starter/src/__tests__/character.test.ts +86 -0
- package/templates/project-starter/src/__tests__/config.test.ts +193 -0
- package/templates/project-starter/src/__tests__/cypress/component/Accessibility.cy.tsx +271 -0
- package/templates/project-starter/src/__tests__/cypress/component/ApiIntegration.cy.tsx +220 -0
- package/templates/project-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +146 -0
- package/templates/project-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +51 -0
- package/templates/project-starter/src/__tests__/cypress/e2e/agent-chat.cy.ts +235 -0
- package/templates/project-starter/src/__tests__/cypress/e2e/dashboard.cy.ts +146 -0
- package/templates/project-starter/src/__tests__/cypress/e2e/user-workflow.cy.ts +257 -0
- package/templates/project-starter/src/__tests__/cypress/support/commands.ts +44 -0
- package/templates/project-starter/src/__tests__/cypress/support/component-index.html +11 -0
- package/templates/project-starter/src/__tests__/cypress/support/component.ts +33 -0
- package/templates/project-starter/src/__tests__/cypress/support/e2e.ts +179 -0
- package/templates/project-starter/src/__tests__/e2e/index.ts +14 -0
- package/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +246 -0
- package/templates/project-starter/src/__tests__/e2e/project.test.ts +155 -0
- package/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +421 -0
- package/templates/project-starter/src/__tests__/env.test.ts +87 -0
- package/templates/project-starter/src/__tests__/error-handling.test.ts +177 -0
- package/templates/project-starter/src/__tests__/events.test.ts +144 -0
- package/templates/project-starter/src/__tests__/file-structure.test.ts +135 -0
- package/templates/project-starter/src/__tests__/integration.test.ts +209 -0
- package/templates/project-starter/src/__tests__/models.test.ts +152 -0
- package/templates/project-starter/src/__tests__/plugin.test.ts +393 -0
- package/templates/project-starter/src/__tests__/provider.test.ts +325 -0
- package/templates/project-starter/src/__tests__/routes.test.ts +79 -0
- package/templates/project-starter/src/__tests__/test-utils.ts +121 -0
- package/templates/project-starter/src/__tests__/utils/core-test-utils.ts +180 -0
- package/templates/project-starter/src/frontend/index.css +77 -0
- package/templates/project-starter/src/frontend/index.html +19 -0
- package/templates/project-starter/src/frontend/index.tsx +98 -0
- package/templates/project-starter/src/frontend/utils.ts +6 -0
- package/templates/project-starter/src/index.ts +3 -0
- package/templates/project-starter/tailwind.config.js +62 -0
- package/templates/project-starter/tsconfig.build.json +9 -2
- package/templates/project-starter/tsconfig.json +15 -6
- package/templates/project-starter/tsup.config.ts +1 -1
- package/templates/project-starter/vite.config.ts +39 -0
- package/templates/project-tee-starter/__tests__/actions.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/character.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/config.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/env.test.ts +2 -2
- package/templates/project-tee-starter/__tests__/error-handling.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/events.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/file-structure.test.ts +5 -5
- package/templates/project-tee-starter/__tests__/integration.test.ts +22 -26
- package/templates/project-tee-starter/__tests__/models.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/plugin.test.ts +6 -12
- package/templates/project-tee-starter/__tests__/provider.test.ts +6 -6
- package/templates/project-tee-starter/__tests__/routes.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/test-utils.ts +15 -15
- package/templates/project-tee-starter/__tests__/utils/core-test-utils.ts +3 -3
- package/templates/project-tee-starter/bunfig.toml +6 -0
- package/templates/project-tee-starter/package.json +10 -12
- package/dist/assets/index-CCyz05Yl.js.br +0 -0
- package/dist/assets/index-CCyz05Yl.js.map +0 -1
- package/dist/assets/index-DeXwJbtm.css +0 -1
- package/dist/assets/index-DeXwJbtm.css.br +0 -0
- package/dist/chunk-CEE6RKN5.js +0 -2746
- package/dist/chunk-TUAYJIF2.js +0 -3649
- package/dist/plugin-creator-IK6H4LVZ.js +0 -29165
- package/templates/plugin-starter/e2e/starter-plugin.test.ts +0 -171
- package/templates/plugin-starter/images/README.md +0 -24
- package/templates/plugin-starter/vitest.config.ts +0 -16
- package/templates/project-starter/e2e/project.test.ts +0 -34
- package/templates/project-starter/e2e/starter-plugin.test.ts +0 -217
- package/templates/project-starter/vitest.config.ts +0 -16
- package/templates/project-tee-starter/vitest.config.ts +0 -19
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Starter Plugin E2E Test Suite
|
|
5
|
+
*
|
|
6
|
+
* This comprehensive test suite demonstrates how to write end-to-end tests for ElizaOS plugins.
|
|
7
|
+
* These tests run in a REAL runtime environment provided by `elizaos test`, meaning:
|
|
8
|
+
*
|
|
9
|
+
* - All services are actually initialized and running
|
|
10
|
+
* - The database is real (in-memory PGLite for testing)
|
|
11
|
+
* - Actions, providers, and events are fully functional
|
|
12
|
+
* - The agent's AI/LLM capabilities are active
|
|
13
|
+
*
|
|
14
|
+
* STRUCTURE OF AN E2E TEST:
|
|
15
|
+
* 1. Each test receives a live IAgentRuntime instance
|
|
16
|
+
* 2. You interact with the runtime as if it were production
|
|
17
|
+
* 3. Test success = no errors thrown, test failure = throw an error
|
|
18
|
+
*
|
|
19
|
+
* HOW TO ADD NEW TESTS:
|
|
20
|
+
* 1. Add a new object to the `tests` array with:
|
|
21
|
+
* - `name`: A descriptive name for your test
|
|
22
|
+
* - `fn`: An async function that receives the runtime
|
|
23
|
+
* 2. In your test function:
|
|
24
|
+
* - Set up any required state (rooms, messages, etc.)
|
|
25
|
+
* - Execute the functionality you want to test
|
|
26
|
+
* - Assert the results (throw errors on failure)
|
|
27
|
+
* 3. Keep tests independent - don't rely on other tests' state
|
|
28
|
+
*
|
|
29
|
+
* TESTING PATTERNS DEMONSTRATED:
|
|
30
|
+
* - Character configuration validation
|
|
31
|
+
* - Plugin initialization
|
|
32
|
+
* - Action execution (both direct and natural language)
|
|
33
|
+
* - Provider functionality
|
|
34
|
+
* - Service lifecycle management
|
|
35
|
+
* - Natural language understanding
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
// Define a minimal TestSuite interface that matches what's needed
|
|
39
|
+
interface TestSuite {
|
|
40
|
+
name: string;
|
|
41
|
+
description: string;
|
|
42
|
+
tests: Array<{
|
|
43
|
+
name: string;
|
|
44
|
+
fn: (runtime: any) => Promise<any>;
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Define minimal interfaces for the types we need
|
|
49
|
+
type UUID = `${string}-${string}-${string}-${string}-${string}`;
|
|
50
|
+
|
|
51
|
+
interface Memory {
|
|
52
|
+
entityId: UUID;
|
|
53
|
+
roomId: UUID;
|
|
54
|
+
content: {
|
|
55
|
+
text: string;
|
|
56
|
+
source: string;
|
|
57
|
+
actions?: string[];
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface State {
|
|
62
|
+
values: Record<string, any>;
|
|
63
|
+
data: Record<string, any>;
|
|
64
|
+
text: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface Content {
|
|
68
|
+
text: string;
|
|
69
|
+
source?: string;
|
|
70
|
+
actions?: string[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class StarterTestSuite implements TestSuite {
|
|
74
|
+
name = 'starter';
|
|
75
|
+
description = 'E2E tests for the starter project demonstrating comprehensive testing patterns';
|
|
76
|
+
|
|
77
|
+
tests = [
|
|
78
|
+
{
|
|
79
|
+
/**
|
|
80
|
+
* Test 1: Character Configuration Validation
|
|
81
|
+
* This test ensures that the character is properly configured with all required fields.
|
|
82
|
+
* It's a good first test because it validates the basic setup before testing functionality.
|
|
83
|
+
*/
|
|
84
|
+
name: 'Character configuration test',
|
|
85
|
+
fn: async (runtime: any) => {
|
|
86
|
+
const character = runtime.character;
|
|
87
|
+
const requiredFields = ['name', 'bio', 'plugins', 'system', 'messageExamples'];
|
|
88
|
+
const missingFields = requiredFields.filter((field) => !(field in character));
|
|
89
|
+
|
|
90
|
+
if (missingFields.length > 0) {
|
|
91
|
+
throw new Error(`Missing required fields: ${missingFields.join(', ')}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Additional character property validations
|
|
95
|
+
if (character.name !== 'Eliza') {
|
|
96
|
+
throw new Error(`Expected character name to be 'Eliza', got '${character.name}'`);
|
|
97
|
+
}
|
|
98
|
+
if (!Array.isArray(character.plugins)) {
|
|
99
|
+
throw new Error('Character plugins should be an array');
|
|
100
|
+
}
|
|
101
|
+
if (!character.system) {
|
|
102
|
+
throw new Error('Character system prompt is required');
|
|
103
|
+
}
|
|
104
|
+
if (!Array.isArray(character.bio)) {
|
|
105
|
+
throw new Error('Character bio should be an array');
|
|
106
|
+
}
|
|
107
|
+
if (!Array.isArray(character.messageExamples)) {
|
|
108
|
+
throw new Error('Character message examples should be an array');
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
{
|
|
114
|
+
/**
|
|
115
|
+
* Test 2: Plugin Initialization
|
|
116
|
+
* This test verifies that plugins can be registered with the runtime.
|
|
117
|
+
* It's important to test this separately from action execution to isolate issues.
|
|
118
|
+
*/
|
|
119
|
+
name: 'Plugin initialization test',
|
|
120
|
+
fn: async (runtime: any) => {
|
|
121
|
+
// Test plugin initialization with empty config
|
|
122
|
+
try {
|
|
123
|
+
await runtime.registerPlugin({
|
|
124
|
+
name: 'starter',
|
|
125
|
+
description: 'A starter plugin for Eliza',
|
|
126
|
+
init: async () => {},
|
|
127
|
+
config: {},
|
|
128
|
+
});
|
|
129
|
+
} catch (error) {
|
|
130
|
+
throw new Error(`Failed to register plugin: ${(error as Error).message}`);
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
{
|
|
136
|
+
/**
|
|
137
|
+
* Test 3: Direct Action Execution
|
|
138
|
+
* This test explicitly requests the HELLO_WORLD action to verify it works correctly.
|
|
139
|
+
* This is useful for testing that the action itself is functioning before testing
|
|
140
|
+
* natural language understanding.
|
|
141
|
+
*/
|
|
142
|
+
name: 'Hello world action test - Direct execution',
|
|
143
|
+
fn: async (runtime: any) => {
|
|
144
|
+
const message: Memory = {
|
|
145
|
+
entityId: uuidv4() as UUID,
|
|
146
|
+
roomId: uuidv4() as UUID,
|
|
147
|
+
content: {
|
|
148
|
+
text: 'Can you say hello?',
|
|
149
|
+
source: 'test',
|
|
150
|
+
actions: ['HELLO_WORLD'], // Explicitly request the HELLO_WORLD action
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const state: State = {
|
|
155
|
+
values: {},
|
|
156
|
+
data: {},
|
|
157
|
+
text: '',
|
|
158
|
+
};
|
|
159
|
+
let responseReceived = false;
|
|
160
|
+
|
|
161
|
+
// Test the hello world action
|
|
162
|
+
try {
|
|
163
|
+
await runtime.processActions(message, [], state, async (content: Content) => {
|
|
164
|
+
if (content.text === 'hello world!' && content.actions?.includes('HELLO_WORLD')) {
|
|
165
|
+
responseReceived = true;
|
|
166
|
+
}
|
|
167
|
+
return [];
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (!responseReceived) {
|
|
171
|
+
// Try directly executing the action if processActions didn't work
|
|
172
|
+
const helloWorldAction = runtime.actions.find((a: any) => a.name === 'HELLO_WORLD');
|
|
173
|
+
if (helloWorldAction) {
|
|
174
|
+
await helloWorldAction.handler(
|
|
175
|
+
runtime,
|
|
176
|
+
message,
|
|
177
|
+
state,
|
|
178
|
+
{},
|
|
179
|
+
async (content: Content) => {
|
|
180
|
+
if (content.text === 'hello world!' && content.actions?.includes('HELLO_WORLD')) {
|
|
181
|
+
responseReceived = true;
|
|
182
|
+
}
|
|
183
|
+
return [];
|
|
184
|
+
},
|
|
185
|
+
[]
|
|
186
|
+
);
|
|
187
|
+
} else {
|
|
188
|
+
throw new Error('HELLO_WORLD action not found in runtime.actions');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!responseReceived) {
|
|
193
|
+
throw new Error('Hello world action did not produce expected response');
|
|
194
|
+
}
|
|
195
|
+
} catch (error) {
|
|
196
|
+
throw new Error(`Hello world action test failed: ${(error as Error).message}`);
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
{
|
|
202
|
+
/**
|
|
203
|
+
* Test 4: Natural Language Understanding - Hello World
|
|
204
|
+
* This is the KEY TEST that demonstrates how the agent should naturally understand
|
|
205
|
+
* a request to say "hello world" without explicitly specifying the action.
|
|
206
|
+
*
|
|
207
|
+
* This test simulates a real conversation where:
|
|
208
|
+
* 1. The user asks the agent to say "hello world" in natural language
|
|
209
|
+
* 2. The agent understands the request and decides to use the HELLO_WORLD action
|
|
210
|
+
* 3. The agent responds with "hello world!"
|
|
211
|
+
*
|
|
212
|
+
* This tests the full AI pipeline: understanding → decision making → action execution
|
|
213
|
+
*/
|
|
214
|
+
name: 'Natural language hello world test',
|
|
215
|
+
fn: async (runtime: any) => {
|
|
216
|
+
// Create a unique room for this conversation
|
|
217
|
+
const roomId = uuidv4() as UUID;
|
|
218
|
+
const userId = uuidv4() as UUID;
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
// Step 1: Send a natural language message asking for hello world
|
|
222
|
+
// Note: We do NOT specify any actions - the agent must understand and decide
|
|
223
|
+
const userMessage: Memory = {
|
|
224
|
+
entityId: userId,
|
|
225
|
+
roomId: roomId,
|
|
226
|
+
content: {
|
|
227
|
+
text: 'Please say hello world', // Natural language request
|
|
228
|
+
source: 'test',
|
|
229
|
+
// No actions specified - agent must understand the intent
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Step 2: Process the message through the agent's full pipeline
|
|
234
|
+
// This includes:
|
|
235
|
+
// - Natural language understanding
|
|
236
|
+
// - Intent recognition
|
|
237
|
+
// - Action selection
|
|
238
|
+
// - Response generation
|
|
239
|
+
let agentResponse: string | null = null;
|
|
240
|
+
let actionUsed: string | null = null;
|
|
241
|
+
|
|
242
|
+
// Set up a callback to capture the agent's response
|
|
243
|
+
const responseCallback = async (content: Content) => {
|
|
244
|
+
agentResponse = content.text;
|
|
245
|
+
if (content.actions && content.actions.length > 0) {
|
|
246
|
+
actionUsed = content.actions[0];
|
|
247
|
+
}
|
|
248
|
+
return [];
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// Process the message - this simulates a real conversation
|
|
252
|
+
await runtime.processMessage(userMessage, [], responseCallback);
|
|
253
|
+
|
|
254
|
+
// Alternative approach if processMessage isn't available
|
|
255
|
+
if (!agentResponse) {
|
|
256
|
+
// Try using the evaluate method which processes messages through the full pipeline
|
|
257
|
+
const state: State = {
|
|
258
|
+
values: {},
|
|
259
|
+
data: {},
|
|
260
|
+
text: userMessage.content.text,
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const result = await runtime.evaluate(userMessage, state, responseCallback);
|
|
264
|
+
|
|
265
|
+
// If evaluate doesn't work, try the action selection pipeline
|
|
266
|
+
if (!agentResponse && runtime.evaluateActions) {
|
|
267
|
+
const selectedActions = await runtime.evaluateActions(userMessage, state);
|
|
268
|
+
|
|
269
|
+
if (selectedActions && selectedActions.length > 0) {
|
|
270
|
+
// Execute the selected action
|
|
271
|
+
const action = runtime.actions.find((a: any) => a.name === selectedActions[0]);
|
|
272
|
+
if (action) {
|
|
273
|
+
await action.handler(runtime, userMessage, state, {}, responseCallback, []);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Step 3: Verify the agent understood and responded correctly
|
|
280
|
+
if (!agentResponse) {
|
|
281
|
+
throw new Error('Agent did not respond to natural language request');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Check that the response contains "hello world" (case insensitive)
|
|
285
|
+
const responseText = (agentResponse || '') as string;
|
|
286
|
+
if (!responseText.toLowerCase().includes('hello world')) {
|
|
287
|
+
throw new Error(
|
|
288
|
+
`Agent response did not contain "hello world". Got: "${agentResponse}"`
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Optionally verify that the HELLO_WORLD action was used
|
|
293
|
+
if (actionUsed && actionUsed !== 'HELLO_WORLD') {
|
|
294
|
+
console.log(`Note: Agent used action "${actionUsed}" instead of "HELLO_WORLD"`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Test passed! The agent successfully understood the natural language request
|
|
298
|
+
// and responded with "hello world"
|
|
299
|
+
} catch (error) {
|
|
300
|
+
throw new Error(`Natural language hello world test failed: ${(error as Error).message}`);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
|
|
305
|
+
{
|
|
306
|
+
/**
|
|
307
|
+
* Test 5: Provider Functionality
|
|
308
|
+
* Providers supply context to the agent. This test verifies that our
|
|
309
|
+
* HELLO_WORLD_PROVIDER is functioning and returning the expected data.
|
|
310
|
+
*/
|
|
311
|
+
name: 'Hello world provider test',
|
|
312
|
+
fn: async (runtime: any) => {
|
|
313
|
+
const message: Memory = {
|
|
314
|
+
entityId: uuidv4() as UUID,
|
|
315
|
+
roomId: uuidv4() as UUID,
|
|
316
|
+
content: {
|
|
317
|
+
text: 'What can you provide?',
|
|
318
|
+
source: 'test',
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const state: State = {
|
|
323
|
+
values: {},
|
|
324
|
+
data: {},
|
|
325
|
+
text: '',
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
// Test the hello world provider
|
|
329
|
+
try {
|
|
330
|
+
if (!runtime.providers || runtime.providers.length === 0) {
|
|
331
|
+
throw new Error('No providers found in runtime');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Find the specific provider we want to test
|
|
335
|
+
const helloWorldProvider = runtime.providers.find(
|
|
336
|
+
(p: any) => p.name === 'HELLO_WORLD_PROVIDER'
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
if (!helloWorldProvider) {
|
|
340
|
+
throw new Error('HELLO_WORLD_PROVIDER not found in runtime providers');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const result = await helloWorldProvider.get(runtime, message, state);
|
|
344
|
+
|
|
345
|
+
if (result.text !== 'I am a provider') {
|
|
346
|
+
throw new Error(`Expected provider to return "I am a provider", got "${result.text}"`);
|
|
347
|
+
}
|
|
348
|
+
} catch (error) {
|
|
349
|
+
throw new Error(`Hello world provider test failed: ${(error as Error).message}`);
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
|
|
354
|
+
{
|
|
355
|
+
/**
|
|
356
|
+
* Test 6: Service Lifecycle Management
|
|
357
|
+
* Services are long-running components. This test verifies that our
|
|
358
|
+
* starter service can be properly started, accessed, and stopped.
|
|
359
|
+
*/
|
|
360
|
+
name: 'Starter service test',
|
|
361
|
+
fn: async (runtime: any) => {
|
|
362
|
+
// Test service registration and lifecycle
|
|
363
|
+
try {
|
|
364
|
+
const service = runtime.getService('starter');
|
|
365
|
+
if (!service) {
|
|
366
|
+
throw new Error('Starter service not found');
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (
|
|
370
|
+
service.capabilityDescription !==
|
|
371
|
+
'This is a starter service which is attached to the agent through the starter plugin.'
|
|
372
|
+
) {
|
|
373
|
+
throw new Error('Incorrect service capability description');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
await service.stop();
|
|
377
|
+
} catch (error) {
|
|
378
|
+
throw new Error(`Starter service test failed: ${(error as Error).message}`);
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* TEMPLATE: How to add a new E2E test
|
|
385
|
+
* Copy this template and modify it for your specific test case
|
|
386
|
+
*/
|
|
387
|
+
/*
|
|
388
|
+
{
|
|
389
|
+
name: 'My new feature test',
|
|
390
|
+
fn: async (runtime: any) => {
|
|
391
|
+
try {
|
|
392
|
+
// 1. Set up test data
|
|
393
|
+
const testData = {
|
|
394
|
+
// Your test setup here
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
// 2. Execute the feature
|
|
398
|
+
const result = await runtime.someMethod(testData);
|
|
399
|
+
|
|
400
|
+
// 3. Verify the results
|
|
401
|
+
if (!result) {
|
|
402
|
+
throw new Error('Expected result but got nothing');
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (result.someProperty !== 'expected value') {
|
|
406
|
+
throw new Error(`Expected 'expected value' but got '${result.someProperty}'`);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Test passed if we reach here without throwing
|
|
410
|
+
} catch (error) {
|
|
411
|
+
// Always wrap errors with context for easier debugging
|
|
412
|
+
throw new Error(`My new feature test failed: ${error.message}`);
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
*/
|
|
417
|
+
];
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Export a default instance of the test suite for the E2E test runner
|
|
421
|
+
export default new StarterTestSuite();
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { describe, expect, it } from 'bun:test';
|
|
4
|
+
|
|
5
|
+
describe('Environment Setup', () => {
|
|
6
|
+
it('should verify configuration files exist', () => {
|
|
7
|
+
const requiredFiles = [
|
|
8
|
+
'package.json',
|
|
9
|
+
'tsconfig.json',
|
|
10
|
+
'tsconfig.build.json',
|
|
11
|
+
'tsup.config.ts',
|
|
12
|
+
'bunfig.toml',
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
for (const file of requiredFiles) {
|
|
16
|
+
const filePath = path.join(process.cwd(), file);
|
|
17
|
+
expect(fs.existsSync(filePath)).toBe(true);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should have proper src directory structure', () => {
|
|
22
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
23
|
+
expect(fs.existsSync(srcDir)).toBe(true);
|
|
24
|
+
|
|
25
|
+
const requiredSrcFiles = ['index.ts', 'plugin.ts'];
|
|
26
|
+
|
|
27
|
+
for (const file of requiredSrcFiles) {
|
|
28
|
+
const filePath = path.join(srcDir, file);
|
|
29
|
+
expect(fs.existsSync(filePath)).toBe(true);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should have a valid package.json with required fields', () => {
|
|
34
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
35
|
+
expect(fs.existsSync(packageJsonPath)).toBe(true);
|
|
36
|
+
|
|
37
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
38
|
+
expect(packageJson).toHaveProperty('name', '@elizaos/project-starter');
|
|
39
|
+
expect(packageJson).toHaveProperty('version');
|
|
40
|
+
expect(packageJson).toHaveProperty('type', 'module');
|
|
41
|
+
expect(packageJson).toHaveProperty('main');
|
|
42
|
+
expect(packageJson).toHaveProperty('module');
|
|
43
|
+
expect(packageJson).toHaveProperty('types');
|
|
44
|
+
expect(packageJson).toHaveProperty('dependencies');
|
|
45
|
+
expect(packageJson).toHaveProperty('devDependencies');
|
|
46
|
+
expect(packageJson).toHaveProperty('scripts');
|
|
47
|
+
|
|
48
|
+
// Check for required dependencies
|
|
49
|
+
expect(packageJson.dependencies).toHaveProperty('@elizaos/core');
|
|
50
|
+
|
|
51
|
+
// Check for required scripts
|
|
52
|
+
expect(packageJson.scripts).toHaveProperty('build');
|
|
53
|
+
expect(packageJson.scripts).toHaveProperty('test');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should have a valid tsconfig.json with required configuration', () => {
|
|
57
|
+
const tsconfigPath = path.join(process.cwd(), 'tsconfig.json');
|
|
58
|
+
expect(fs.existsSync(tsconfigPath)).toBe(true);
|
|
59
|
+
|
|
60
|
+
const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf8'));
|
|
61
|
+
expect(tsconfig).toHaveProperty('compilerOptions');
|
|
62
|
+
|
|
63
|
+
// Check compiler options
|
|
64
|
+
expect(tsconfig.compilerOptions).toHaveProperty('target');
|
|
65
|
+
expect(tsconfig.compilerOptions).toHaveProperty('module');
|
|
66
|
+
expect(tsconfig.compilerOptions).toHaveProperty('moduleResolution');
|
|
67
|
+
expect(tsconfig.compilerOptions).toHaveProperty('esModuleInterop');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should have a valid tsup.config.ts for building', () => {
|
|
71
|
+
const tsupConfigPath = path.join(process.cwd(), 'tsup.config.ts');
|
|
72
|
+
expect(fs.existsSync(tsupConfigPath)).toBe(true);
|
|
73
|
+
|
|
74
|
+
const tsupConfig = fs.readFileSync(tsupConfigPath, 'utf8');
|
|
75
|
+
expect(tsupConfig).toContain('defineConfig');
|
|
76
|
+
expect(tsupConfig).toContain('entry:');
|
|
77
|
+
expect(tsupConfig).toContain('src/index.ts');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should have a valid README.md file', () => {
|
|
81
|
+
const readmePath = path.join(process.cwd(), 'README.md');
|
|
82
|
+
expect(fs.existsSync(readmePath)).toBe(true);
|
|
83
|
+
|
|
84
|
+
const readme = fs.readFileSync(readmePath, 'utf8');
|
|
85
|
+
expect(readme).toContain('# Project Starter');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { describe, expect, it, spyOn, beforeEach, afterEach } from 'bun:test';
|
|
2
|
+
import plugin from '../plugin';
|
|
3
|
+
import { StarterService } from '../plugin';
|
|
4
|
+
import { logger } from '@elizaos/core';
|
|
5
|
+
import type { IAgentRuntime, Memory, State } from '@elizaos/core';
|
|
6
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
7
|
+
|
|
8
|
+
// Mock logger
|
|
9
|
+
spyOnmock('@elizaos/core', async () => {
|
|
10
|
+
const actual = await spyOnimportActual('@elizaos/core');
|
|
11
|
+
return {
|
|
12
|
+
...actual,
|
|
13
|
+
logger: {
|
|
14
|
+
info: spyOnfn(),
|
|
15
|
+
error: spyOnfn(),
|
|
16
|
+
warn: spyOnfn(),
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('Error Handling', () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
spyOnclearAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
// No global restore needed in bun:test;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('HELLO_WORLD Action Error Handling', () => {
|
|
31
|
+
it('should log errors in action handlers', async () => {
|
|
32
|
+
// Find the action
|
|
33
|
+
const action = plugin.actions?.find((a) => a.name === 'HELLO_WORLD');
|
|
34
|
+
|
|
35
|
+
if (action && action.handler) {
|
|
36
|
+
// Force the handler to throw an error
|
|
37
|
+
const mockError = new Error('Test error in action');
|
|
38
|
+
spyOn(console, 'error').mockImplementation(() => {});
|
|
39
|
+
|
|
40
|
+
// Create a custom mock runtime
|
|
41
|
+
const mockRuntime = {
|
|
42
|
+
// This is just a simple object for testing
|
|
43
|
+
} as unknown as IAgentRuntime;
|
|
44
|
+
|
|
45
|
+
const mockMessage = {
|
|
46
|
+
entityId: uuidv4(),
|
|
47
|
+
roomId: uuidv4(),
|
|
48
|
+
content: {
|
|
49
|
+
text: 'Hello!',
|
|
50
|
+
source: 'test',
|
|
51
|
+
},
|
|
52
|
+
} as Memory;
|
|
53
|
+
|
|
54
|
+
const mockState = {
|
|
55
|
+
values: {},
|
|
56
|
+
data: {},
|
|
57
|
+
text: '',
|
|
58
|
+
} as State;
|
|
59
|
+
|
|
60
|
+
const mockCallback = spyOnfn();
|
|
61
|
+
|
|
62
|
+
// Mock the logger.error to verify it's called
|
|
63
|
+
spyOn(logger, 'error');
|
|
64
|
+
|
|
65
|
+
// Test the error handling by observing the behavior
|
|
66
|
+
try {
|
|
67
|
+
await action.handler(mockRuntime, mockMessage, mockState, {}, mockCallback, []);
|
|
68
|
+
|
|
69
|
+
// If we get here, no error was thrown, which is okay
|
|
70
|
+
// In a real application, error handling might be internal
|
|
71
|
+
expect(mockCallback).toHaveBeenCalled();
|
|
72
|
+
} catch (error) {
|
|
73
|
+
// If error is thrown, ensure it's handled correctly
|
|
74
|
+
expect(logger.error).toHaveBeenCalled();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('Service Error Handling', () => {
|
|
81
|
+
it('should throw an error when stopping non-existent service', async () => {
|
|
82
|
+
const mockRuntime = {
|
|
83
|
+
getService: spyOnfn().mockReturnValue(null),
|
|
84
|
+
} as unknown as IAgentRuntime;
|
|
85
|
+
|
|
86
|
+
let caughtError = null;
|
|
87
|
+
try {
|
|
88
|
+
await StarterService.stop(mockRuntime);
|
|
89
|
+
} catch (error: any) {
|
|
90
|
+
caughtError = error;
|
|
91
|
+
expect(error.message).toBe('Starter service not found');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
expect(caughtError).not.toBeNull();
|
|
95
|
+
expect(mockRuntime.getService).toHaveBeenCalledWith('starter');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should handle service stop errors gracefully', async () => {
|
|
99
|
+
const mockServiceWithError = {
|
|
100
|
+
stop: spyOnfn().mockImplementation(() => {
|
|
101
|
+
throw new Error('Error stopping service');
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const mockRuntime = {
|
|
106
|
+
getService: spyOnfn().mockReturnValue(mockServiceWithError),
|
|
107
|
+
} as unknown as IAgentRuntime;
|
|
108
|
+
|
|
109
|
+
// The error should be propagated
|
|
110
|
+
let caughtError = null;
|
|
111
|
+
try {
|
|
112
|
+
await StarterService.stop(mockRuntime);
|
|
113
|
+
} catch (error: any) {
|
|
114
|
+
caughtError = error;
|
|
115
|
+
expect(error.message).toBe('Error stopping service');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
expect(caughtError).not.toBeNull();
|
|
119
|
+
expect(mockRuntime.getService).toHaveBeenCalledWith('starter');
|
|
120
|
+
expect(mockServiceWithError.stop).toHaveBeenCalled();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('Plugin Events Error Handling', () => {
|
|
125
|
+
it('should handle errors in event handlers gracefully', async () => {
|
|
126
|
+
if (plugin.events && plugin.events.MESSAGE_RECEIVED) {
|
|
127
|
+
const messageHandler = plugin.events.MESSAGE_RECEIVED[0];
|
|
128
|
+
|
|
129
|
+
// Create a mock that will trigger an error
|
|
130
|
+
const mockParams = {
|
|
131
|
+
message: {
|
|
132
|
+
id: 'test-id',
|
|
133
|
+
content: { text: 'Hello!' },
|
|
134
|
+
},
|
|
135
|
+
source: 'test',
|
|
136
|
+
runtime: {},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// Spy on the logger
|
|
140
|
+
spyOn(logger, 'error');
|
|
141
|
+
|
|
142
|
+
// This is a partial test - in a real handler, we'd have more robust error handling
|
|
143
|
+
try {
|
|
144
|
+
await messageHandler(mockParams as any);
|
|
145
|
+
// If it succeeds without error, that's good too
|
|
146
|
+
expect(true).toBe(true);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
// If it does error, make sure we can catch it
|
|
149
|
+
expect(error).toBeDefined();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
describe('Provider Error Handling', () => {
|
|
156
|
+
it('should handle errors in provider.get method', async () => {
|
|
157
|
+
const provider = plugin.providers?.find((p) => p.name === 'HELLO_WORLD_PROVIDER');
|
|
158
|
+
|
|
159
|
+
if (provider) {
|
|
160
|
+
// Create invalid inputs to test error handling
|
|
161
|
+
const mockRuntime = null as unknown as IAgentRuntime;
|
|
162
|
+
const mockMessage = null as unknown as Memory;
|
|
163
|
+
const mockState = null as unknown as State;
|
|
164
|
+
|
|
165
|
+
// The provider should handle null inputs gracefully
|
|
166
|
+
try {
|
|
167
|
+
await provider.get(mockRuntime, mockMessage, mockState);
|
|
168
|
+
// If we get here, it didn't throw - which is good
|
|
169
|
+
expect(true).toBe(true);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
// If it does throw, at least make sure it's a handled error
|
|
172
|
+
expect(logger.error).toHaveBeenCalled();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|