@elizaos/cli 1.0.8 → 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 (242) hide show
  1. package/README.md +9 -16
  2. package/dist/assets/{index-CZAd5zm2.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-CaEsCLCC.js → index-DDQnwxzL.js} +28798 -16391
  6. package/dist/assets/{index-CaEsCLCC.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-REBZFQYE.js → chunk-7HYEGM5V.js} +967 -1597
  11. package/dist/{chunk-W3HS2NP6.js → chunk-B4KJXECB.js} +13 -18
  12. package/dist/{chunk-33BHGAF7.js → chunk-GWQB7PBK.js} +59 -32
  13. package/dist/{chunk-CVADLFW6.js → chunk-LQ6XHF53.js} +4543 -3043
  14. package/dist/{chunk-GYTAJJOD.js → chunk-RIAWNDYI.js} +16 -2
  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 -4
  18. package/dist/commands/agent/index.js +3 -4
  19. package/dist/commands/create/actions/index.js +4 -5
  20. package/dist/commands/create/index.js +5 -6
  21. package/dist/{fileFromPath-DCRQMDLJ.js → fileFromPath-KB6XMTJ4.js} +1 -0
  22. package/dist/index.html +2 -2
  23. package/dist/index.js +9346 -102098
  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-XFOSZFU4.js → registry-CBMRMYCG.js} +3 -4
  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-DIZZ3HNZ.js → utils-TIALZU53.js} +9 -8
  138. package/package.json +29 -12
  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 +31 -8
  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 +9 -1
  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-CZAd5zm2.js.br +0 -0
  228. package/dist/assets/index-CZAd5zm2.js.map +0 -1
  229. package/dist/assets/index-DyA-lndn.css +0 -1
  230. package/dist/assets/index-DyA-lndn.css.br +0 -0
  231. package/dist/chunk-CEE6RKN5.js +0 -2746
  232. package/dist/chunk-MA2ZXPG6.js +0 -260
  233. package/dist/chunk-TUAYJIF2.js +0 -3649
  234. package/dist/lib-NAGYZHVV.js +0 -9
  235. package/dist/plugin-creator-IC42XOHG.js +0 -29165
  236. package/templates/plugin-starter/e2e/starter-plugin.test.ts +0 -171
  237. package/templates/plugin-starter/images/README.md +0 -24
  238. package/templates/plugin-starter/vitest.config.ts +0 -16
  239. package/templates/project-starter/e2e/project.test.ts +0 -34
  240. package/templates/project-starter/e2e/starter-plugin.test.ts +0 -217
  241. package/templates/project-starter/vitest.config.ts +0 -16
  242. package/templates/project-tee-starter/vitest.config.ts +0 -19
@@ -0,0 +1,393 @@
1
+ import { describe, expect, it, spyOn, beforeEach, afterEach, beforeAll, afterAll } from 'bun:test';
2
+ import plugin from '../plugin';
3
+ import { ModelType, logger } from '@elizaos/core';
4
+ import { StarterService } from '../plugin';
5
+ import dotenv from 'dotenv';
6
+
7
+ // Setup environment variables
8
+ dotenv.config();
9
+
10
+ // Need to spy on logger for documentation
11
+ beforeAll(() => {
12
+ spyOn(logger, 'info');
13
+ spyOn(logger, 'error');
14
+ spyOn(logger, 'warn');
15
+ spyOn(logger, 'debug');
16
+ });
17
+
18
+ afterAll(() => {
19
+ // No global restore needed in bun:test;
20
+ });
21
+
22
+ // Helper function to document test results
23
+ function documentTestResult(testName: string, result: any, error: Error | null = null) {
24
+ // Clean, useful test documentation for developers
25
+ logger.info(`✓ Testing: ${testName}`);
26
+
27
+ if (error) {
28
+ logger.error(`✗ Error: ${error.message}`);
29
+ if (error.stack) {
30
+ logger.error(`Stack: ${error.stack}`);
31
+ }
32
+ return;
33
+ }
34
+
35
+ if (result) {
36
+ if (typeof result === 'string') {
37
+ if (result.trim() && result.length > 0) {
38
+ const preview = result.length > 60 ? `${result.substring(0, 60)}...` : result;
39
+ logger.info(` → ${preview}`);
40
+ }
41
+ } else if (typeof result === 'object') {
42
+ try {
43
+ // Show key information in a clean format
44
+ const keys = Object.keys(result);
45
+ if (keys.length > 0) {
46
+ const preview = keys.slice(0, 3).join(', ');
47
+ const more = keys.length > 3 ? ` +${keys.length - 3} more` : '';
48
+ logger.info(` → {${preview}${more}}`);
49
+ }
50
+ } catch (e) {
51
+ logger.info(` → [Complex object]`);
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ // Create a real runtime for testing
58
+ function createRealRuntime() {
59
+ const services = new Map();
60
+
61
+ // Create a real service instance if needed
62
+ const createService = (serviceType: string) => {
63
+ if (serviceType === StarterService.serviceType) {
64
+ return new StarterService({
65
+ character: {
66
+ name: 'Test Character',
67
+ system: 'You are a helpful assistant for testing.',
68
+ },
69
+ } as any);
70
+ }
71
+ return null;
72
+ };
73
+
74
+ return {
75
+ character: {
76
+ name: 'Test Character',
77
+ system: 'You are a helpful assistant for testing.',
78
+ plugins: [],
79
+ settings: {},
80
+ },
81
+ getSetting: (key: string) => null,
82
+ models: plugin.models,
83
+ db: {
84
+ get: async (key: string) => null,
85
+ set: async (key: string, value: any) => true,
86
+ delete: async (key: string) => true,
87
+ getKeys: async (pattern: string) => [],
88
+ },
89
+ getService: (serviceType: string) => {
90
+ // Get from cache or create new
91
+ if (!services.has(serviceType)) {
92
+ services.set(serviceType, createService(serviceType));
93
+ }
94
+
95
+ return services.get(serviceType);
96
+ },
97
+ registerService: (serviceType: string, service: any) => {
98
+ services.set(serviceType, service);
99
+ },
100
+ };
101
+ }
102
+
103
+ describe('Plugin Configuration', () => {
104
+ it('should have correct plugin metadata', () => {
105
+ expect(plugin.name).toBe('starter');
106
+ expect(plugin.description).toBe('A starter plugin for Eliza');
107
+ expect(plugin.config).toBeDefined();
108
+
109
+ documentTestResult('Plugin metadata check', {
110
+ name: plugin.name,
111
+ description: plugin.description,
112
+ hasConfig: !!plugin.config,
113
+ });
114
+ });
115
+
116
+ it('should include the EXAMPLE_PLUGIN_VARIABLE in config', () => {
117
+ expect(plugin.config).toHaveProperty('EXAMPLE_PLUGIN_VARIABLE');
118
+
119
+ documentTestResult('Plugin config check', {
120
+ hasExampleVariable: plugin.config ? 'EXAMPLE_PLUGIN_VARIABLE' in plugin.config : false,
121
+ configKeys: Object.keys(plugin.config || {}),
122
+ });
123
+ });
124
+
125
+ it('should initialize properly', async () => {
126
+ const originalEnv = process.env.EXAMPLE_PLUGIN_VARIABLE;
127
+
128
+ try {
129
+ process.env.EXAMPLE_PLUGIN_VARIABLE = 'test-value';
130
+
131
+ // Initialize with config - using real runtime
132
+ const runtime = createRealRuntime();
133
+
134
+ let error: Error | null = null;
135
+ try {
136
+ await plugin.init?.({ EXAMPLE_PLUGIN_VARIABLE: 'test-value' }, runtime as any);
137
+ expect(true).toBe(true); // If we got here, init succeeded
138
+ } catch (e) {
139
+ error = e as Error;
140
+ logger.error('Plugin initialization error:', e);
141
+ }
142
+
143
+ documentTestResult(
144
+ 'Plugin initialization',
145
+ {
146
+ success: !error,
147
+ configValue: process.env.EXAMPLE_PLUGIN_VARIABLE,
148
+ },
149
+ error
150
+ );
151
+ } finally {
152
+ process.env.EXAMPLE_PLUGIN_VARIABLE = originalEnv;
153
+ }
154
+ });
155
+
156
+ it('should throw an error on invalid config', async () => {
157
+ // Test with empty string (less than min length 1)
158
+ if (plugin.init) {
159
+ const runtime = createRealRuntime();
160
+ let error: Error | null = null;
161
+
162
+ try {
163
+ await plugin.init({ EXAMPLE_PLUGIN_VARIABLE: '' }, runtime as any);
164
+ // Should not reach here
165
+ expect(true).toBe(false);
166
+ } catch (e) {
167
+ error = e as Error;
168
+ // This is expected - test passes
169
+ expect(error).toBeTruthy();
170
+ }
171
+
172
+ documentTestResult(
173
+ 'Plugin invalid config',
174
+ {
175
+ errorThrown: !!error,
176
+ errorMessage: error?.message || 'No error message',
177
+ },
178
+ error
179
+ );
180
+ }
181
+ });
182
+
183
+ it('should have a valid config', () => {
184
+ expect(plugin.config).toBeDefined();
185
+ if (plugin.config) {
186
+ // Check if the config has expected EXAMPLE_PLUGIN_VARIABLE property
187
+ expect(Object.keys(plugin.config)).toContain('EXAMPLE_PLUGIN_VARIABLE');
188
+ }
189
+ });
190
+ });
191
+
192
+ describe('Plugin Models', () => {
193
+ it('should have TEXT_SMALL model defined', () => {
194
+ if (plugin.models) {
195
+ expect(plugin.models).toHaveProperty(ModelType.TEXT_SMALL);
196
+ expect(typeof plugin.models[ModelType.TEXT_SMALL]).toBe('function');
197
+
198
+ documentTestResult('TEXT_SMALL model check', {
199
+ defined: ModelType.TEXT_SMALL in plugin.models,
200
+ isFunction: typeof plugin.models[ModelType.TEXT_SMALL] === 'function',
201
+ });
202
+ }
203
+ });
204
+
205
+ it('should have TEXT_LARGE model defined', () => {
206
+ if (plugin.models) {
207
+ expect(plugin.models).toHaveProperty(ModelType.TEXT_LARGE);
208
+ expect(typeof plugin.models[ModelType.TEXT_LARGE]).toBe('function');
209
+
210
+ documentTestResult('TEXT_LARGE model check', {
211
+ defined: ModelType.TEXT_LARGE in plugin.models,
212
+ isFunction: typeof plugin.models[ModelType.TEXT_LARGE] === 'function',
213
+ });
214
+ }
215
+ });
216
+
217
+ it('should return a response from TEXT_SMALL model', async () => {
218
+ if (plugin.models && plugin.models[ModelType.TEXT_SMALL]) {
219
+ const runtime = createRealRuntime();
220
+
221
+ let result = '';
222
+ let error: Error | null = null;
223
+
224
+ try {
225
+ logger.info('Using OpenAI for TEXT_SMALL model');
226
+ result = await plugin.models[ModelType.TEXT_SMALL](runtime as any, { prompt: 'test' });
227
+
228
+ // Check that we get a non-empty string response
229
+ expect(result).toBeTruthy();
230
+ expect(typeof result).toBe('string');
231
+ expect(result.length).toBeGreaterThan(10);
232
+ } catch (e) {
233
+ error = e as Error;
234
+ logger.error('TEXT_SMALL model test failed:', e);
235
+ }
236
+
237
+ documentTestResult('TEXT_SMALL model plugin test', result, error);
238
+ }
239
+ });
240
+ });
241
+
242
+ describe('StarterService', () => {
243
+ it('should start the service', async () => {
244
+ const runtime = createRealRuntime();
245
+ let startResult;
246
+ let error: Error | null = null;
247
+
248
+ try {
249
+ logger.info('Using OpenAI for TEXT_SMALL model');
250
+ startResult = await StarterService.start(runtime as any);
251
+
252
+ expect(startResult).toBeDefined();
253
+ expect(startResult.constructor.name).toBe('StarterService');
254
+
255
+ // Test real functionality - check stop method is available
256
+ expect(typeof startResult.stop).toBe('function');
257
+ } catch (e) {
258
+ error = e as Error;
259
+ logger.error('Service start error:', e);
260
+ }
261
+
262
+ documentTestResult(
263
+ 'StarterService start',
264
+ {
265
+ success: !!startResult,
266
+ serviceType: startResult?.constructor.name,
267
+ },
268
+ error
269
+ );
270
+ });
271
+
272
+ it('should throw an error on startup if the service is already registered', async () => {
273
+ const runtime = createRealRuntime();
274
+
275
+ // First registration should succeed
276
+ const result1 = await StarterService.start(runtime as any);
277
+ expect(result1).toBeTruthy();
278
+
279
+ let startupError: Error | null = null;
280
+
281
+ try {
282
+ // Second registration should fail
283
+ await StarterService.start(runtime as any);
284
+ expect(true).toBe(false); // Should not reach here
285
+ } catch (e) {
286
+ startupError = e as Error;
287
+ expect(e).toBeTruthy();
288
+ }
289
+
290
+ documentTestResult(
291
+ 'StarterService double start',
292
+ {
293
+ errorThrown: !!startupError,
294
+ errorMessage: startupError?.message || 'No error message',
295
+ },
296
+ startupError
297
+ );
298
+ });
299
+
300
+ it('should stop the service', async () => {
301
+ const runtime = createRealRuntime();
302
+ let error: Error | null = null;
303
+
304
+ try {
305
+ // Register a real service first
306
+ const service = new StarterService(runtime as any);
307
+ runtime.registerService(StarterService.serviceType, service);
308
+
309
+ // Spy on the real service's stop method
310
+ const stopSpy = spyOn(service, 'stop');
311
+
312
+ // Call the static stop method
313
+ await StarterService.stop(runtime as any);
314
+
315
+ // Verify the service's stop method was called
316
+ expect(stopSpy).toHaveBeenCalled();
317
+ } catch (e) {
318
+ error = e as Error;
319
+ logger.error('Service stop error:', e);
320
+ }
321
+
322
+ documentTestResult(
323
+ 'StarterService stop',
324
+ {
325
+ success: !error,
326
+ },
327
+ error
328
+ );
329
+ });
330
+
331
+ it('should throw an error when stopping a non-existent service', async () => {
332
+ const runtime = createRealRuntime();
333
+ // Don't register a service, so getService will return null
334
+
335
+ let error: Error | null = null;
336
+
337
+ try {
338
+ // We'll patch the getService function to ensure it returns null
339
+ const originalGetService = runtime.getService;
340
+ runtime.getService = () => null;
341
+
342
+ await StarterService.stop(runtime as any);
343
+ // Should not reach here
344
+ expect(true).toBe(false);
345
+ } catch (e) {
346
+ error = e as Error;
347
+ // This is expected - verify it's the right error
348
+ expect(error).toBeTruthy();
349
+ if (error instanceof Error) {
350
+ expect(error.message).toContain('Starter service not found');
351
+ }
352
+ }
353
+
354
+ documentTestResult(
355
+ 'StarterService non-existent stop',
356
+ {
357
+ errorThrown: !!error,
358
+ errorMessage: error?.message || 'No error message',
359
+ },
360
+ error
361
+ );
362
+ });
363
+
364
+ it('should stop a registered service', async () => {
365
+ const runtime = createRealRuntime();
366
+
367
+ // First start the service
368
+ const startResult = await StarterService.start(runtime as any);
369
+ expect(startResult).toBeTruthy();
370
+
371
+ let stopError: Error | unknown = null;
372
+ let stopSuccess = false;
373
+
374
+ try {
375
+ // Then stop it
376
+ await StarterService.stop(runtime as any);
377
+ stopSuccess = true;
378
+ } catch (e) {
379
+ stopError = e;
380
+ expect(true).toBe(false); // Should not reach here
381
+ }
382
+
383
+ documentTestResult(
384
+ 'StarterService stop',
385
+ {
386
+ success: stopSuccess,
387
+ errorThrown: !!stopError,
388
+ errorMessage: stopError instanceof Error ? stopError.message : String(stopError),
389
+ },
390
+ stopError instanceof Error ? stopError : null
391
+ );
392
+ });
393
+ });
@@ -0,0 +1,325 @@
1
+ import { describe, expect, it, spyOn, beforeAll, afterAll } from 'bun:test';
2
+ import plugin from '../plugin';
3
+ import type { IAgentRuntime, Memory, State, Provider } from '@elizaos/core';
4
+ import { logger } from '@elizaos/core';
5
+ import { v4 as uuidv4 } from 'uuid';
6
+ import dotenv from 'dotenv';
7
+
8
+ // Setup environment variables
9
+ dotenv.config();
10
+
11
+ // Set up logging to capture issues
12
+ beforeAll(() => {
13
+ spyOn(logger, 'info');
14
+ spyOn(logger, 'error');
15
+ spyOn(logger, 'warn');
16
+ spyOn(logger, 'debug');
17
+ });
18
+
19
+ afterAll(() => {
20
+ // No global restore needed in bun:test;
21
+ });
22
+
23
+ // Helper function to document test results
24
+ function documentTestResult(testName: string, result: any, error: Error | null = null) {
25
+ // Clean, useful test documentation for developers
26
+ logger.info(`✓ Testing: ${testName}`);
27
+
28
+ if (error) {
29
+ logger.error(`✗ Error: ${error.message}`);
30
+ if (error.stack) {
31
+ logger.error(`Stack: ${error.stack}`);
32
+ }
33
+ return;
34
+ }
35
+
36
+ if (result) {
37
+ if (typeof result === 'string') {
38
+ if (result.trim() && result.length > 0) {
39
+ const preview = result.length > 60 ? `${result.substring(0, 60)}...` : result;
40
+ logger.info(` → ${preview}`);
41
+ }
42
+ } else if (typeof result === 'object') {
43
+ try {
44
+ // Show key information in a clean format
45
+ const keys = Object.keys(result);
46
+ if (keys.length > 0) {
47
+ const preview = keys.slice(0, 3).join(', ');
48
+ const more = keys.length > 3 ? ` +${keys.length - 3} more` : '';
49
+ logger.info(` → {${preview}${more}}`);
50
+ }
51
+ } catch (e) {
52
+ logger.info(` → [Complex object]`);
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ // Create a realistic runtime for testing
59
+ function createRealRuntime(): IAgentRuntime {
60
+ return {
61
+ character: {
62
+ name: 'Test Character',
63
+ system: 'You are a helpful assistant for testing.',
64
+ plugins: [],
65
+ settings: {},
66
+ },
67
+ getSetting: (key: string) => null,
68
+ models: plugin.models,
69
+ db: {
70
+ get: async (key: string) => {
71
+ return null;
72
+ },
73
+ set: async (key: string, value: any) => {
74
+ return true;
75
+ },
76
+ delete: async (key: string) => {
77
+ return true;
78
+ },
79
+ getKeys: async (pattern: string) => {
80
+ return [];
81
+ },
82
+ },
83
+ memory: {
84
+ add: async (memory: any) => {
85
+ // Memory operations for testing
86
+ },
87
+ get: async (id: string) => {
88
+ return null;
89
+ },
90
+ getByEntityId: async (entityId: string) => {
91
+ return [];
92
+ },
93
+ getLatest: async (entityId: string) => {
94
+ return null;
95
+ },
96
+ getRecentMessages: async (options: any) => {
97
+ return [];
98
+ },
99
+ search: async (query: string) => {
100
+ return [];
101
+ },
102
+ },
103
+ getService: (serviceType: string) => {
104
+ return null;
105
+ },
106
+ } as unknown as IAgentRuntime;
107
+ }
108
+
109
+ // Create realistic memory object
110
+ function createRealMemory(): Memory {
111
+ const entityId = uuidv4();
112
+ const roomId = uuidv4();
113
+
114
+ return {
115
+ id: uuidv4(),
116
+ entityId,
117
+ roomId,
118
+ timestamp: Date.now(),
119
+ content: {
120
+ text: 'What can you provide?',
121
+ source: 'test',
122
+ actions: [],
123
+ },
124
+ metadata: {
125
+ type: 'custom',
126
+ sessionId: uuidv4(),
127
+ conversationId: uuidv4(),
128
+ },
129
+ } as Memory;
130
+ }
131
+
132
+ describe('Provider Tests', () => {
133
+ // Find the HELLO_WORLD_PROVIDER from the providers array
134
+ const helloWorldProvider = plugin.providers?.find(
135
+ (provider) => provider.name === 'HELLO_WORLD_PROVIDER'
136
+ );
137
+
138
+ describe('HELLO_WORLD_PROVIDER', () => {
139
+ it('should exist in the plugin', () => {
140
+ expect(plugin.providers).toBeDefined();
141
+ expect(Array.isArray(plugin.providers)).toBe(true);
142
+
143
+ if (plugin.providers) {
144
+ expect(plugin.providers.length).toBeGreaterThan(0);
145
+ const result = plugin.providers.find((p) => p.name === 'HELLO_WORLD_PROVIDER');
146
+ expect(result).toBeDefined();
147
+ documentTestResult('Provider exists check', {
148
+ found: !!result,
149
+ providers: plugin.providers.map((p) => p.name),
150
+ });
151
+ }
152
+ });
153
+
154
+ it('should have the correct structure', () => {
155
+ if (helloWorldProvider) {
156
+ expect(helloWorldProvider).toHaveProperty('name', 'HELLO_WORLD_PROVIDER');
157
+ expect(helloWorldProvider).toHaveProperty('description');
158
+ expect(helloWorldProvider).toHaveProperty('get');
159
+ expect(typeof helloWorldProvider.get).toBe('function');
160
+
161
+ documentTestResult('Provider structure check', {
162
+ name: helloWorldProvider.name,
163
+ description: helloWorldProvider.description,
164
+ hasGetMethod: typeof helloWorldProvider.get === 'function',
165
+ });
166
+ }
167
+ });
168
+
169
+ it('should have a description explaining its purpose', () => {
170
+ if (helloWorldProvider && helloWorldProvider.description) {
171
+ expect(typeof helloWorldProvider.description).toBe('string');
172
+ expect(helloWorldProvider.description.length).toBeGreaterThan(0);
173
+
174
+ documentTestResult('Provider description check', {
175
+ description: helloWorldProvider.description,
176
+ });
177
+ }
178
+ });
179
+
180
+ it('should return provider data from the get method', async () => {
181
+ if (helloWorldProvider) {
182
+ const runtime = createRealRuntime();
183
+ const message = createRealMemory();
184
+ const state = {
185
+ values: { example: 'test value' },
186
+ data: { additionalContext: 'some context' },
187
+ text: 'Current state context',
188
+ } as State;
189
+
190
+ let result: any = null;
191
+ let error: Error | null = null;
192
+
193
+ try {
194
+ logger.info('Calling provider.get with real implementation');
195
+ result = await helloWorldProvider.get(runtime, message, state);
196
+
197
+ expect(result).toBeDefined();
198
+ expect(result).toHaveProperty('text');
199
+ expect(result).toHaveProperty('values');
200
+ expect(result).toHaveProperty('data');
201
+
202
+ // Look for potential issues in the result
203
+ if (result && (!result.text || result.text.length === 0)) {
204
+ logger.warn('Provider returned empty text');
205
+ }
206
+
207
+ if (result && Object.keys(result.values).length === 0) {
208
+ logger.warn('Provider returned empty values object');
209
+ }
210
+
211
+ if (result && Object.keys(result.data).length === 0) {
212
+ logger.warn('Provider returned empty data object');
213
+ }
214
+ } catch (e) {
215
+ error = e as Error;
216
+ logger.error('Error in provider.get:', e);
217
+ }
218
+
219
+ documentTestResult('Provider get method', result, error);
220
+ }
221
+ });
222
+
223
+ it('should handle error conditions gracefully', async () => {
224
+ if (helloWorldProvider) {
225
+ const runtime = createRealRuntime();
226
+ // Create an invalid memory object to simulate an error scenario
227
+ const invalidMemory = {
228
+ // Missing properties that would be required
229
+ id: uuidv4(),
230
+ } as unknown as Memory;
231
+
232
+ const state = {
233
+ values: {},
234
+ data: {},
235
+ text: '',
236
+ } as State;
237
+
238
+ let result: any = null;
239
+ let error: Error | null = null;
240
+
241
+ try {
242
+ logger.info('Calling provider.get with invalid memory object');
243
+ result = await helloWorldProvider.get(runtime, invalidMemory, state);
244
+
245
+ // Even with invalid input, it should not throw errors
246
+ expect(result).toBeDefined();
247
+
248
+ // Log what actual implementation does with invalid input
249
+ logger.info('Provider handled invalid input without throwing');
250
+ } catch (e) {
251
+ error = e as Error;
252
+ logger.error('Provider threw an error with invalid input:', e);
253
+ }
254
+
255
+ documentTestResult('Provider error handling', result, error);
256
+ }
257
+ });
258
+ });
259
+
260
+ describe('Provider Registration', () => {
261
+ it('should include providers in the plugin definition', () => {
262
+ expect(plugin).toHaveProperty('providers');
263
+ expect(Array.isArray(plugin.providers)).toBe(true);
264
+
265
+ documentTestResult('Plugin providers check', {
266
+ hasProviders: !!plugin.providers,
267
+ providersCount: plugin.providers?.length || 0,
268
+ });
269
+ });
270
+
271
+ it('should correctly initialize providers array', () => {
272
+ // Providers should be an array with at least one provider
273
+ if (plugin.providers) {
274
+ expect(plugin.providers.length).toBeGreaterThan(0);
275
+
276
+ let allValid = true;
277
+ const invalidProviders: string[] = [];
278
+
279
+ // Each provider should have the required structure
280
+ plugin.providers.forEach((provider: Provider) => {
281
+ const isValid =
282
+ provider.name !== undefined &&
283
+ provider.description !== undefined &&
284
+ typeof provider.get === 'function';
285
+
286
+ if (!isValid) {
287
+ allValid = false;
288
+ invalidProviders.push(provider.name || 'unnamed');
289
+ }
290
+
291
+ expect(provider).toHaveProperty('name');
292
+ expect(provider).toHaveProperty('description');
293
+ expect(provider).toHaveProperty('get');
294
+ expect(typeof provider.get).toBe('function');
295
+ });
296
+
297
+ documentTestResult('Provider initialization check', {
298
+ providersCount: plugin.providers.length,
299
+ allValid,
300
+ invalidProviders,
301
+ });
302
+ }
303
+ });
304
+
305
+ it('should have unique provider names', () => {
306
+ if (plugin.providers) {
307
+ const providerNames = plugin.providers.map((provider) => provider.name);
308
+ const uniqueNames = new Set(providerNames);
309
+
310
+ const duplicates = providerNames.filter(
311
+ (name, index) => providerNames.indexOf(name) !== index
312
+ );
313
+
314
+ // There should be no duplicate provider names
315
+ expect(providerNames.length).toBe(uniqueNames.size);
316
+
317
+ documentTestResult('Provider uniqueness check', {
318
+ totalProviders: providerNames.length,
319
+ uniqueProviders: uniqueNames.size,
320
+ duplicates,
321
+ });
322
+ }
323
+ });
324
+ });
325
+ });