@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.
Files changed (240) hide show
  1. package/README.md +9 -16
  2. package/dist/assets/{index-CCyz05Yl.js → index-CmuPnu0u.js} +72 -89
  3. package/dist/assets/index-CmuPnu0u.js.br +0 -0
  4. package/dist/assets/index-CmuPnu0u.js.map +1 -0
  5. package/dist/assets/{index-Cxd2b7is.js → index-DDQnwxzL.js} +1318 -13721
  6. package/dist/assets/{index-Cxd2b7is.js.map → index-DDQnwxzL.js.map} +1 -1
  7. package/dist/assets/index-Df1AFSuJ.css +1 -0
  8. package/dist/assets/index-Df1AFSuJ.css.br +0 -0
  9. package/dist/assets/vendor-DSdxb8P-.js.map +1 -1
  10. package/dist/{chunk-Y755OOSP.js → chunk-7HYEGM5V.js} +877 -1550
  11. package/dist/{chunk-HZQCHL3J.js → chunk-B4KJXECB.js} +13 -18
  12. package/dist/{chunk-Z6GVELRX.js → chunk-GWQB7PBK.js} +58 -29
  13. package/dist/{chunk-CVADLFW6.js → chunk-LQ6XHF53.js} +4543 -3043
  14. package/dist/{chunk-JWONHNLD.js → chunk-RIAWNDYI.js} +2 -9
  15. package/dist/{chunk-IEKLJDUU.js → chunk-WS4DWCDZ.js} +54 -32
  16. package/dist/commands/agent/actions/index.d.ts +5 -1
  17. package/dist/commands/agent/actions/index.js +5 -3
  18. package/dist/commands/agent/index.js +3 -3
  19. package/dist/commands/create/actions/index.js +4 -4
  20. package/dist/commands/create/index.js +5 -5
  21. package/dist/{fileFromPath-DCRQMDLJ.js → fileFromPath-KB6XMTJ4.js} +1 -0
  22. package/dist/index.html +2 -2
  23. package/dist/index.js +9351 -102236
  24. package/dist/{migrator-KZLCVEIH.js → migrator-JREQPDN3.js} +42 -220
  25. package/dist/pglite.data +0 -0
  26. package/dist/pglite.wasm +0 -0
  27. package/dist/plugin-creator-T4K2673C.js +910 -0
  28. package/dist/{registry-W7CIK4O2.js → registry-CBMRMYCG.js} +3 -3
  29. package/dist/templates/plugin-starter/README.md +255 -0
  30. package/dist/templates/plugin-starter/bunfig.toml +6 -0
  31. package/dist/templates/plugin-starter/cypress.config.ts +18 -0
  32. package/dist/templates/plugin-starter/index.html +13 -0
  33. package/dist/templates/plugin-starter/package.json +95 -0
  34. package/dist/templates/plugin-starter/postcss.config.js +3 -0
  35. package/dist/templates/plugin-starter/scripts/test-e2e-manual.js +201 -0
  36. package/dist/templates/plugin-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +404 -0
  37. package/dist/templates/plugin-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +287 -0
  38. package/dist/templates/plugin-starter/src/__tests__/cypress/support/commands.ts +38 -0
  39. package/dist/templates/plugin-starter/src/__tests__/cypress/support/component-index.html +11 -0
  40. package/dist/templates/plugin-starter/src/__tests__/cypress/support/component.ts +33 -0
  41. package/dist/templates/plugin-starter/src/__tests__/cypress/support/e2e.ts +11 -0
  42. package/dist/templates/plugin-starter/src/__tests__/cypress/tsconfig.json +10 -0
  43. package/dist/templates/plugin-starter/src/__tests__/e2e/README.md +47 -0
  44. package/dist/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts +320 -0
  45. package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/integration.test.ts +22 -17
  46. package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/plugin.test.ts +8 -8
  47. package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/test-utils.ts +17 -17
  48. package/dist/templates/plugin-starter/src/frontend/index.css +77 -0
  49. package/dist/templates/plugin-starter/src/frontend/index.tsx +164 -0
  50. package/dist/templates/plugin-starter/src/frontend/utils.ts +6 -0
  51. package/dist/templates/plugin-starter/src/index.ts +274 -0
  52. package/dist/templates/plugin-starter/src/tests.ts +6 -0
  53. package/dist/templates/plugin-starter/tailwind.config.js +62 -0
  54. package/dist/templates/plugin-starter/tsconfig.build.json +11 -0
  55. package/dist/templates/plugin-starter/tsconfig.json +28 -0
  56. package/dist/templates/plugin-starter/tsup.config.ts +20 -0
  57. package/dist/templates/plugin-starter/vite.config.ts +20 -0
  58. package/dist/templates/project-starter/.env.example +153 -0
  59. package/dist/templates/project-starter/README.md +109 -0
  60. package/dist/templates/project-starter/bunfig.toml +6 -0
  61. package/dist/templates/project-starter/cypress.config.ts +31 -0
  62. package/dist/templates/project-starter/index.html +13 -0
  63. package/dist/templates/project-starter/package.json +83 -0
  64. package/dist/templates/project-starter/postcss.config.js +3 -0
  65. package/dist/templates/project-starter/scripts/test-all.sh +101 -0
  66. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/actions.test.ts +6 -6
  67. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/character.test.ts +3 -3
  68. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/config.test.ts +18 -18
  69. package/dist/templates/project-starter/src/__tests__/cypress/component/Accessibility.cy.tsx +271 -0
  70. package/dist/templates/project-starter/src/__tests__/cypress/component/ApiIntegration.cy.tsx +220 -0
  71. package/dist/templates/project-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +146 -0
  72. package/dist/templates/project-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +51 -0
  73. package/dist/templates/project-starter/src/__tests__/cypress/e2e/agent-chat.cy.ts +235 -0
  74. package/dist/templates/project-starter/src/__tests__/cypress/e2e/dashboard.cy.ts +146 -0
  75. package/dist/templates/project-starter/src/__tests__/cypress/e2e/user-workflow.cy.ts +257 -0
  76. package/dist/templates/project-starter/src/__tests__/cypress/support/commands.ts +44 -0
  77. package/dist/templates/project-starter/src/__tests__/cypress/support/component-index.html +11 -0
  78. package/dist/templates/project-starter/src/__tests__/cypress/support/component.ts +33 -0
  79. package/dist/templates/project-starter/src/__tests__/cypress/support/e2e.ts +179 -0
  80. package/dist/templates/project-starter/src/__tests__/e2e/index.ts +14 -0
  81. package/dist/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +246 -0
  82. package/dist/templates/project-starter/src/__tests__/e2e/project.test.ts +155 -0
  83. package/dist/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +421 -0
  84. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/env.test.ts +2 -2
  85. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/error-handling.test.ts +17 -17
  86. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/events.test.ts +7 -7
  87. package/dist/templates/project-starter/src/__tests__/file-structure.test.ts +135 -0
  88. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/integration.test.ts +25 -25
  89. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/models.test.ts +6 -6
  90. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/plugin.test.ts +9 -9
  91. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/provider.test.ts +7 -7
  92. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/routes.test.ts +3 -3
  93. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/test-utils.ts +17 -17
  94. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/utils/core-test-utils.ts +3 -3
  95. package/dist/templates/project-starter/src/frontend/index.css +77 -0
  96. package/dist/templates/project-starter/src/frontend/index.html +19 -0
  97. package/dist/templates/project-starter/src/frontend/index.tsx +98 -0
  98. package/dist/templates/project-starter/src/frontend/utils.ts +6 -0
  99. package/dist/templates/project-starter/src/index.ts +153 -0
  100. package/dist/templates/project-starter/src/plugin.ts +255 -0
  101. package/dist/templates/project-starter/tailwind.config.js +62 -0
  102. package/dist/templates/project-starter/tsconfig.build.json +20 -0
  103. package/dist/templates/project-starter/tsconfig.json +39 -0
  104. package/dist/templates/project-starter/tsup.config.ts +19 -0
  105. package/dist/templates/project-starter/vite.config.ts +39 -0
  106. package/dist/templates/project-tee-starter/.dockerignore +20 -0
  107. package/dist/templates/project-tee-starter/.env.example +55 -0
  108. package/dist/templates/project-tee-starter/Dockerfile +66 -0
  109. package/dist/templates/project-tee-starter/GUIDE.md +235 -0
  110. package/dist/templates/project-tee-starter/README.md +173 -0
  111. package/dist/templates/project-tee-starter/__tests__/actions.test.ts +9 -0
  112. package/dist/templates/project-tee-starter/__tests__/character.test.ts +86 -0
  113. package/dist/templates/project-tee-starter/__tests__/config.test.ts +31 -0
  114. package/dist/templates/project-tee-starter/__tests__/env.test.ts +87 -0
  115. package/dist/templates/project-tee-starter/__tests__/error-handling.test.ts +30 -0
  116. package/dist/templates/project-tee-starter/__tests__/events.test.ts +21 -0
  117. package/{templates/project-starter → dist/templates/project-tee-starter}/__tests__/file-structure.test.ts +6 -6
  118. package/dist/templates/project-tee-starter/__tests__/integration.test.ts +205 -0
  119. package/dist/templates/project-tee-starter/__tests__/models.test.ts +22 -0
  120. package/dist/templates/project-tee-starter/__tests__/plugin.test.ts +38 -0
  121. package/dist/templates/project-tee-starter/__tests__/provider.test.ts +189 -0
  122. package/dist/templates/project-tee-starter/__tests__/routes.test.ts +21 -0
  123. package/dist/templates/project-tee-starter/__tests__/test-utils.ts +121 -0
  124. package/dist/templates/project-tee-starter/__tests__/utils/core-test-utils.ts +167 -0
  125. package/dist/templates/project-tee-starter/assets/mr-tee-portrait.jpg +0 -0
  126. package/dist/templates/project-tee-starter/bunfig.toml +6 -0
  127. package/dist/templates/project-tee-starter/docker-compose.yaml +57 -0
  128. package/dist/templates/project-tee-starter/e2e/project.test.ts +38 -0
  129. package/dist/templates/project-tee-starter/e2e/starter-plugin.test.ts +92 -0
  130. package/dist/templates/project-tee-starter/package.json +74 -0
  131. package/dist/templates/project-tee-starter/src/character.ts +257 -0
  132. package/dist/templates/project-tee-starter/src/index.ts +33 -0
  133. package/dist/templates/project-tee-starter/src/plugin.ts +169 -0
  134. package/dist/templates/project-tee-starter/tsconfig.build.json +13 -0
  135. package/dist/templates/project-tee-starter/tsconfig.json +30 -0
  136. package/dist/templates/project-tee-starter/tsup.config.ts +19 -0
  137. package/dist/{utils-2G2QVMW3.js → utils-TIALZU53.js} +9 -7
  138. package/package.json +28 -9
  139. package/templates/plugin-starter/README.md +38 -13
  140. package/templates/plugin-starter/bunfig.toml +6 -0
  141. package/templates/plugin-starter/cypress.config.ts +18 -0
  142. package/templates/plugin-starter/index.html +13 -0
  143. package/templates/plugin-starter/package.json +19 -7
  144. package/templates/plugin-starter/postcss.config.js +3 -0
  145. package/templates/plugin-starter/scripts/test-e2e-manual.js +201 -0
  146. package/templates/plugin-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +404 -0
  147. package/templates/plugin-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +287 -0
  148. package/templates/plugin-starter/src/__tests__/cypress/support/commands.ts +38 -0
  149. package/templates/plugin-starter/src/__tests__/cypress/support/component-index.html +11 -0
  150. package/templates/plugin-starter/src/__tests__/cypress/support/component.ts +33 -0
  151. package/templates/plugin-starter/src/__tests__/cypress/support/e2e.ts +11 -0
  152. package/templates/plugin-starter/src/__tests__/cypress/tsconfig.json +10 -0
  153. package/templates/plugin-starter/src/__tests__/e2e/README.md +47 -0
  154. package/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts +320 -0
  155. package/templates/plugin-starter/src/__tests__/integration.test.ts +138 -0
  156. package/templates/plugin-starter/src/__tests__/plugin.test.ts +182 -0
  157. package/templates/plugin-starter/src/__tests__/test-utils.ts +162 -0
  158. package/templates/plugin-starter/src/frontend/index.css +77 -0
  159. package/templates/plugin-starter/src/frontend/index.tsx +164 -0
  160. package/templates/plugin-starter/src/frontend/utils.ts +6 -0
  161. package/templates/plugin-starter/src/index.ts +30 -7
  162. package/templates/plugin-starter/src/tests.ts +6 -0
  163. package/templates/plugin-starter/tailwind.config.js +62 -0
  164. package/templates/plugin-starter/tsconfig.json +8 -8
  165. package/templates/plugin-starter/vite.config.ts +20 -0
  166. package/templates/project-starter/bunfig.toml +6 -0
  167. package/templates/project-starter/cypress.config.ts +31 -0
  168. package/templates/project-starter/index.html +13 -0
  169. package/templates/project-starter/package.json +37 -14
  170. package/templates/project-starter/postcss.config.js +3 -0
  171. package/templates/project-starter/scripts/test-all.sh +101 -0
  172. package/templates/project-starter/src/__tests__/actions.test.ts +155 -0
  173. package/templates/project-starter/src/__tests__/character.test.ts +86 -0
  174. package/templates/project-starter/src/__tests__/config.test.ts +193 -0
  175. package/templates/project-starter/src/__tests__/cypress/component/Accessibility.cy.tsx +271 -0
  176. package/templates/project-starter/src/__tests__/cypress/component/ApiIntegration.cy.tsx +220 -0
  177. package/templates/project-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +146 -0
  178. package/templates/project-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +51 -0
  179. package/templates/project-starter/src/__tests__/cypress/e2e/agent-chat.cy.ts +235 -0
  180. package/templates/project-starter/src/__tests__/cypress/e2e/dashboard.cy.ts +146 -0
  181. package/templates/project-starter/src/__tests__/cypress/e2e/user-workflow.cy.ts +257 -0
  182. package/templates/project-starter/src/__tests__/cypress/support/commands.ts +44 -0
  183. package/templates/project-starter/src/__tests__/cypress/support/component-index.html +11 -0
  184. package/templates/project-starter/src/__tests__/cypress/support/component.ts +33 -0
  185. package/templates/project-starter/src/__tests__/cypress/support/e2e.ts +179 -0
  186. package/templates/project-starter/src/__tests__/e2e/index.ts +14 -0
  187. package/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +246 -0
  188. package/templates/project-starter/src/__tests__/e2e/project.test.ts +155 -0
  189. package/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +421 -0
  190. package/templates/project-starter/src/__tests__/env.test.ts +87 -0
  191. package/templates/project-starter/src/__tests__/error-handling.test.ts +177 -0
  192. package/templates/project-starter/src/__tests__/events.test.ts +144 -0
  193. package/templates/project-starter/src/__tests__/file-structure.test.ts +135 -0
  194. package/templates/project-starter/src/__tests__/integration.test.ts +209 -0
  195. package/templates/project-starter/src/__tests__/models.test.ts +152 -0
  196. package/templates/project-starter/src/__tests__/plugin.test.ts +393 -0
  197. package/templates/project-starter/src/__tests__/provider.test.ts +325 -0
  198. package/templates/project-starter/src/__tests__/routes.test.ts +79 -0
  199. package/templates/project-starter/src/__tests__/test-utils.ts +121 -0
  200. package/templates/project-starter/src/__tests__/utils/core-test-utils.ts +180 -0
  201. package/templates/project-starter/src/frontend/index.css +77 -0
  202. package/templates/project-starter/src/frontend/index.html +19 -0
  203. package/templates/project-starter/src/frontend/index.tsx +98 -0
  204. package/templates/project-starter/src/frontend/utils.ts +6 -0
  205. package/templates/project-starter/src/index.ts +3 -0
  206. package/templates/project-starter/tailwind.config.js +62 -0
  207. package/templates/project-starter/tsconfig.build.json +9 -2
  208. package/templates/project-starter/tsconfig.json +15 -6
  209. package/templates/project-starter/tsup.config.ts +1 -1
  210. package/templates/project-starter/vite.config.ts +39 -0
  211. package/templates/project-tee-starter/__tests__/actions.test.ts +1 -1
  212. package/templates/project-tee-starter/__tests__/character.test.ts +1 -1
  213. package/templates/project-tee-starter/__tests__/config.test.ts +1 -1
  214. package/templates/project-tee-starter/__tests__/env.test.ts +2 -2
  215. package/templates/project-tee-starter/__tests__/error-handling.test.ts +1 -1
  216. package/templates/project-tee-starter/__tests__/events.test.ts +1 -1
  217. package/templates/project-tee-starter/__tests__/file-structure.test.ts +5 -5
  218. package/templates/project-tee-starter/__tests__/integration.test.ts +22 -26
  219. package/templates/project-tee-starter/__tests__/models.test.ts +1 -1
  220. package/templates/project-tee-starter/__tests__/plugin.test.ts +6 -12
  221. package/templates/project-tee-starter/__tests__/provider.test.ts +6 -6
  222. package/templates/project-tee-starter/__tests__/routes.test.ts +1 -1
  223. package/templates/project-tee-starter/__tests__/test-utils.ts +15 -15
  224. package/templates/project-tee-starter/__tests__/utils/core-test-utils.ts +3 -3
  225. package/templates/project-tee-starter/bunfig.toml +6 -0
  226. package/templates/project-tee-starter/package.json +10 -12
  227. package/dist/assets/index-CCyz05Yl.js.br +0 -0
  228. package/dist/assets/index-CCyz05Yl.js.map +0 -1
  229. package/dist/assets/index-DeXwJbtm.css +0 -1
  230. package/dist/assets/index-DeXwJbtm.css.br +0 -0
  231. package/dist/chunk-CEE6RKN5.js +0 -2746
  232. package/dist/chunk-TUAYJIF2.js +0 -3649
  233. package/dist/plugin-creator-IK6H4LVZ.js +0 -29165
  234. package/templates/plugin-starter/e2e/starter-plugin.test.ts +0 -171
  235. package/templates/plugin-starter/images/README.md +0 -24
  236. package/templates/plugin-starter/vitest.config.ts +0 -16
  237. package/templates/project-starter/e2e/project.test.ts +0 -34
  238. package/templates/project-starter/e2e/starter-plugin.test.ts +0 -217
  239. package/templates/project-starter/vitest.config.ts +0 -16
  240. 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
+ });