@elizaos/cli 1.3.1 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -1
- package/dist/{bun-exec-6CQHTS4F.js → bun-exec-ULMPAIQC.js} +1 -1
- package/dist/{chunk-2ALAPQLV.js → chunk-D3QSET5H.js} +342 -360
- package/dist/{chunk-FDEDLANP.js → chunk-FQYWRHLX.js} +1 -1
- package/dist/{chunk-RM6LUTKD.js → chunk-FSSUAWXQ.js} +3 -3
- package/dist/chunk-GXWWPFBO.js +39 -0
- package/dist/{chunk-D3Q2UZLZ.js → chunk-I4L4T7QX.js} +1 -1
- package/dist/{chunk-KDNV7EA5.js → chunk-SMZBJQJR.js} +1 -1
- package/dist/commands/agent/actions/index.d.ts +5 -0
- package/dist/commands/agent/actions/index.js +4 -4
- package/dist/commands/agent/index.d.ts +2 -2
- package/dist/commands/agent/index.js +4 -4
- package/dist/commands/create/actions/index.js +5 -5
- package/dist/commands/create/index.js +6 -6
- package/dist/commands/shared/index.d.ts +11 -28
- package/dist/commands/shared/index.js +7 -3
- package/dist/index.js +599 -483
- package/dist/{plugin-creator-H26ZLR6H.js → plugin-creator-TCUFII32.js} +2 -2
- package/dist/{registry-N626N4VG.js → registry-RF6PW3EN.js} +4 -4
- package/dist/templates/plugin-quick-starter/README.md +52 -10
- package/dist/templates/plugin-quick-starter/package.json +10 -3
- package/dist/templates/plugin-quick-starter/src/__tests__/e2e/README.md +140 -0
- package/dist/templates/plugin-quick-starter/src/__tests__/e2e/plugin-quick-starter.e2e.ts +339 -0
- package/dist/templates/plugin-quick-starter/src/__tests__/plugin.test.ts +537 -146
- package/dist/templates/plugin-quick-starter/src/__tests__/test-utils.ts +316 -115
- package/dist/templates/plugin-quick-starter/src/plugin.ts +20 -26
- package/dist/templates/plugin-starter/README.md +124 -49
- package/dist/templates/plugin-starter/package.json +10 -3
- package/dist/templates/plugin-starter/src/__tests__/e2e/README.md +44 -9
- package/{templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts → dist/templates/plugin-starter/src/__tests__/e2e/plugin-starter.e2e.ts} +13 -20
- package/dist/templates/plugin-starter/src/__tests__/integration.test.ts +13 -13
- package/dist/templates/plugin-starter/src/__tests__/plugin.test.ts +556 -129
- package/dist/templates/plugin-starter/src/__tests__/test-utils.ts +347 -115
- package/dist/templates/plugin-starter/src/plugin.ts +21 -27
- package/dist/templates/project-starter/README.md +25 -12
- package/dist/templates/project-starter/package.json +4 -4
- package/dist/templates/project-starter/src/__tests__/actions.test.ts +2 -2
- package/dist/templates/project-starter/src/__tests__/e2e/README.md +103 -0
- package/dist/templates/project-starter/src/__tests__/e2e/project-starter.e2e.ts +575 -0
- package/dist/templates/project-starter/src/__tests__/env.test.ts +3 -1
- package/dist/templates/project-starter/src/__tests__/file-structure.test.ts +3 -2
- package/dist/templates/project-starter/src/__tests__/integration.test.ts +2 -2
- package/dist/templates/project-starter/src/__tests__/models.test.ts +3 -3
- package/dist/templates/project-starter/src/__tests__/plugin.test.ts +3 -3
- package/dist/templates/project-starter/src/__tests__/provider.test.ts +2 -2
- package/dist/templates/project-starter/src/index.ts +4 -3
- package/dist/templates/project-starter/src/plugin.ts +5 -5
- package/dist/templates/project-starter/tsup.config.ts +2 -1
- package/dist/templates/project-tee-starter/.dockerignore +64 -14
- package/dist/templates/project-tee-starter/Dockerfile +9 -5
- package/dist/templates/project-tee-starter/GUIDE.md +103 -42
- package/dist/templates/project-tee-starter/README.md +83 -24
- package/dist/templates/project-tee-starter/docker-compose.yaml +5 -2
- package/dist/templates/{plugin-starter/dist → project-tee-starter}/index.html +3 -3
- package/dist/templates/project-tee-starter/package.json +34 -14
- package/dist/templates/project-tee-starter/postcss.config.js +3 -0
- package/dist/templates/project-tee-starter/scripts/install-test-deps.js +52 -0
- package/dist/templates/project-tee-starter/scripts/test-all.sh +82 -0
- package/dist/templates/project-tee-starter/src/__tests__/build-order.test.ts +62 -0
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/character.test.ts +20 -18
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/config.test.ts +11 -4
- package/dist/templates/project-tee-starter/src/__tests__/e2e/README.md +128 -0
- package/dist/templates/project-tee-starter/src/__tests__/e2e/project-tee-starter.e2e.ts +280 -0
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/env.test.ts +3 -2
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/error-handling.test.ts +2 -2
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/events.test.ts +1 -1
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/file-structure.test.ts +16 -5
- package/dist/templates/project-tee-starter/src/__tests__/frontend.test.ts +459 -0
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/integration.test.ts +2 -2
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/models.test.ts +1 -1
- package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/plugin.test.ts +5 -3
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/provider.test.ts +2 -2
- package/dist/templates/project-tee-starter/src/__tests__/routes.test.ts +30 -0
- package/dist/templates/project-tee-starter/src/__tests__/tee-validation.test.ts +295 -0
- package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/test-utils.ts +2 -2
- package/dist/templates/project-tee-starter/src/__tests__/vite-config-utils.ts +51 -0
- package/dist/templates/project-tee-starter/src/frontend/index.css +106 -0
- package/dist/templates/project-tee-starter/src/frontend/index.html +20 -0
- package/dist/templates/project-tee-starter/src/frontend/index.tsx +370 -0
- package/dist/templates/project-tee-starter/src/frontend/panels.tsx +17 -0
- package/dist/templates/project-tee-starter/src/frontend/utils.ts +6 -0
- package/dist/templates/project-tee-starter/src/index.ts +8 -6
- package/dist/templates/project-tee-starter/src/plugin.ts +223 -61
- package/dist/templates/project-tee-starter/tailwind.config.js +62 -0
- package/dist/templates/project-tee-starter/tsconfig.build.json +2 -2
- package/dist/templates/project-tee-starter/tsconfig.json +8 -5
- package/dist/templates/project-tee-starter/tsup.config.ts +3 -2
- package/dist/templates/project-tee-starter/vite.config.ts +39 -0
- package/dist/url-utils-CKc_Ebt_.d.ts +35 -0
- package/dist/{utils-H66532NB.js → utils-5HPZSIF6.js} +4 -4
- package/package.json +7 -6
- package/templates/plugin-quick-starter/README.md +52 -10
- package/templates/plugin-quick-starter/package.json +10 -3
- package/templates/plugin-quick-starter/src/__tests__/e2e/README.md +140 -0
- package/templates/plugin-quick-starter/src/__tests__/e2e/plugin-quick-starter.e2e.ts +339 -0
- package/templates/plugin-quick-starter/src/__tests__/plugin.test.ts +537 -146
- package/templates/plugin-quick-starter/src/__tests__/test-utils.ts +316 -115
- package/templates/plugin-quick-starter/src/plugin.ts +20 -26
- package/templates/plugin-starter/README.md +124 -49
- package/templates/plugin-starter/package.json +10 -3
- package/templates/plugin-starter/src/__tests__/e2e/README.md +44 -9
- package/{dist/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts → templates/plugin-starter/src/__tests__/e2e/plugin-starter.e2e.ts} +13 -20
- package/templates/plugin-starter/src/__tests__/integration.test.ts +13 -13
- package/templates/plugin-starter/src/__tests__/plugin.test.ts +556 -129
- package/templates/plugin-starter/src/__tests__/test-utils.ts +347 -115
- package/templates/plugin-starter/src/plugin.ts +21 -27
- package/templates/project-starter/README.md +25 -12
- package/templates/project-starter/package.json +4 -4
- package/templates/project-starter/src/__tests__/actions.test.ts +2 -2
- package/templates/project-starter/src/__tests__/e2e/README.md +103 -0
- package/templates/project-starter/src/__tests__/e2e/project-starter.e2e.ts +575 -0
- package/templates/project-starter/src/__tests__/env.test.ts +3 -1
- package/templates/project-starter/src/__tests__/file-structure.test.ts +3 -2
- package/templates/project-starter/src/__tests__/integration.test.ts +2 -2
- package/templates/project-starter/src/__tests__/models.test.ts +3 -3
- package/templates/project-starter/src/__tests__/plugin.test.ts +3 -3
- package/templates/project-starter/src/__tests__/provider.test.ts +2 -2
- package/templates/project-starter/src/index.ts +4 -3
- package/templates/project-starter/src/plugin.ts +5 -5
- package/templates/project-starter/tsup.config.ts +2 -1
- package/templates/project-tee-starter/.dockerignore +64 -14
- package/templates/project-tee-starter/Dockerfile +9 -5
- package/templates/project-tee-starter/GUIDE.md +103 -42
- package/templates/project-tee-starter/README.md +83 -24
- package/templates/project-tee-starter/docker-compose.yaml +5 -2
- package/templates/{plugin-starter/dist → project-tee-starter}/index.html +3 -3
- package/templates/project-tee-starter/package.json +34 -14
- package/templates/project-tee-starter/postcss.config.js +3 -0
- package/templates/project-tee-starter/scripts/install-test-deps.js +52 -0
- package/templates/project-tee-starter/scripts/test-all.sh +82 -0
- package/templates/project-tee-starter/src/__tests__/build-order.test.ts +62 -0
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/character.test.ts +20 -18
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/config.test.ts +11 -4
- package/templates/project-tee-starter/src/__tests__/e2e/README.md +128 -0
- package/templates/project-tee-starter/src/__tests__/e2e/project-tee-starter.e2e.ts +280 -0
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/env.test.ts +3 -2
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/error-handling.test.ts +2 -2
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/events.test.ts +1 -1
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/file-structure.test.ts +16 -5
- package/templates/project-tee-starter/src/__tests__/frontend.test.ts +459 -0
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/integration.test.ts +2 -2
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/models.test.ts +1 -1
- package/templates/project-tee-starter/{__tests__ → src/__tests__}/plugin.test.ts +5 -3
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/provider.test.ts +2 -2
- package/templates/project-tee-starter/src/__tests__/routes.test.ts +30 -0
- package/templates/project-tee-starter/src/__tests__/tee-validation.test.ts +295 -0
- package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/test-utils.ts +2 -2
- package/templates/project-tee-starter/src/__tests__/vite-config-utils.ts +51 -0
- package/templates/project-tee-starter/src/frontend/index.css +106 -0
- package/templates/project-tee-starter/src/frontend/index.html +20 -0
- package/templates/project-tee-starter/src/frontend/index.tsx +370 -0
- package/templates/project-tee-starter/src/frontend/panels.tsx +17 -0
- package/templates/project-tee-starter/src/frontend/utils.ts +6 -0
- package/templates/project-tee-starter/src/index.ts +8 -6
- package/templates/project-tee-starter/src/plugin.ts +223 -61
- package/templates/project-tee-starter/tailwind.config.js +62 -0
- package/templates/project-tee-starter/tsconfig.build.json +2 -2
- package/templates/project-tee-starter/tsconfig.json +8 -5
- package/templates/project-tee-starter/tsup.config.ts +3 -2
- package/templates/project-tee-starter/vite.config.ts +39 -0
- package/dist/chunk-4O6EZU37.js +0 -14
- package/dist/migration-guides/advanced-migration-guide.md +0 -459
- package/dist/migration-guides/completion-requirements.md +0 -379
- package/dist/migration-guides/integrated-migration-loop.md +0 -392
- package/dist/migration-guides/migration-guide.md +0 -712
- package/dist/migration-guides/prompt-and-generation-guide.md +0 -702
- package/dist/migration-guides/state-and-providers-guide.md +0 -544
- package/dist/migration-guides/testing-guide.md +0 -1021
- package/dist/templates/plugin-starter/dist/assets/index-CgkejLs_.css +0 -1
- package/dist/templates/plugin-starter/dist/assets/index-D1cHX53P.js +0 -49
- package/dist/templates/plugin-starter/dist/index.js +0 -387
- package/dist/templates/plugin-starter/dist/index.js.map +0 -1
- package/dist/templates/plugin-starter/src/tests.ts +0 -6
- package/dist/templates/project-starter/src/__tests__/e2e/index.ts +0 -14
- package/dist/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +0 -246
- package/dist/templates/project-starter/src/__tests__/e2e/project.test.ts +0 -155
- package/dist/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +0 -421
- package/dist/templates/project-tee-starter/__tests__/routes.test.ts +0 -21
- package/dist/templates/project-tee-starter/e2e/project.test.ts +0 -38
- package/dist/templates/project-tee-starter/e2e/starter-plugin.test.ts +0 -92
- package/templates/plugin-starter/dist/.vite/manifest.json +0 -11
- package/templates/plugin-starter/dist/assets/index-CgkejLs_.css +0 -1
- package/templates/plugin-starter/dist/assets/index-D1cHX53P.js +0 -49
- package/templates/plugin-starter/dist/index.d.ts +0 -14
- package/templates/plugin-starter/dist/index.js +0 -387
- package/templates/plugin-starter/dist/index.js.map +0 -1
- package/templates/plugin-starter/src/tests.ts +0 -6
- package/templates/project-starter/src/__tests__/e2e/index.ts +0 -14
- package/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +0 -246
- package/templates/project-starter/src/__tests__/e2e/project.test.ts +0 -155
- package/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +0 -421
- package/templates/project-tee-starter/__tests__/routes.test.ts +0 -21
- package/templates/project-tee-starter/e2e/project.test.ts +0 -38
- package/templates/project-tee-starter/e2e/starter-plugin.test.ts +0 -92
- /package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/actions.test.ts +0 -0
- /package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/utils/core-test-utils.ts +0 -0
- /package/templates/project-tee-starter/{__tests__ → src/__tests__}/actions.test.ts +0 -0
- /package/templates/project-tee-starter/{__tests__ → src/__tests__}/utils/core-test-utils.ts +0 -0
|
@@ -1,12 +1,61 @@
|
|
|
1
1
|
import { describe, expect, it, spyOn, beforeEach, afterEach, beforeAll, afterAll } from 'bun:test';
|
|
2
2
|
import { starterPlugin, StarterService } from '../index';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type IAgentRuntime,
|
|
5
|
+
type Memory,
|
|
6
|
+
type State,
|
|
7
|
+
type Content,
|
|
8
|
+
type HandlerCallback,
|
|
9
|
+
ModelType,
|
|
10
|
+
logger,
|
|
11
|
+
EventType,
|
|
12
|
+
Action,
|
|
13
|
+
} from '@elizaos/core';
|
|
4
14
|
import dotenv from 'dotenv';
|
|
15
|
+
import {
|
|
16
|
+
createMockRuntime,
|
|
17
|
+
createTestMemory,
|
|
18
|
+
createTestState,
|
|
19
|
+
createUUID,
|
|
20
|
+
testFixtures,
|
|
21
|
+
} from './test-utils';
|
|
22
|
+
|
|
23
|
+
// Define proper interfaces for test mocking
|
|
24
|
+
interface MockLoggerMethod {
|
|
25
|
+
calls?: any[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface MockLogger {
|
|
29
|
+
info: MockLoggerMethod;
|
|
30
|
+
error: MockLoggerMethod;
|
|
31
|
+
debug: MockLoggerMethod;
|
|
32
|
+
warn: MockLoggerMethod;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface PluginConfig {
|
|
36
|
+
EXAMPLE_PLUGIN_VARIABLE?: string | number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface TestCallbackContent {
|
|
40
|
+
text?: string;
|
|
41
|
+
actions?: string[];
|
|
42
|
+
source?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface TestActionResult {
|
|
46
|
+
text?: string;
|
|
47
|
+
success: boolean;
|
|
48
|
+
data?: {
|
|
49
|
+
actions?: string[];
|
|
50
|
+
source?: string;
|
|
51
|
+
};
|
|
52
|
+
error?: Error;
|
|
53
|
+
}
|
|
5
54
|
|
|
6
55
|
// Setup environment variables
|
|
7
56
|
dotenv.config();
|
|
8
57
|
|
|
9
|
-
// Need to spy on logger
|
|
58
|
+
// Need to spy on logger
|
|
10
59
|
beforeAll(() => {
|
|
11
60
|
spyOn(logger, 'info');
|
|
12
61
|
spyOn(logger, 'error');
|
|
@@ -18,192 +67,534 @@ afterAll(() => {
|
|
|
18
67
|
// No global restore needed in bun:test
|
|
19
68
|
});
|
|
20
69
|
|
|
21
|
-
// Create a real runtime for testing
|
|
22
|
-
function createRealRuntime(): Partial<IAgentRuntime> {
|
|
23
|
-
const services = new Map<string, Service>();
|
|
24
|
-
|
|
25
|
-
// Create a real service instance if needed
|
|
26
|
-
const createService = (serviceType: string): Service | null => {
|
|
27
|
-
if (serviceType === StarterService.serviceType) {
|
|
28
|
-
return new StarterService({
|
|
29
|
-
character: {
|
|
30
|
-
name: 'Test Character',
|
|
31
|
-
system: 'You are a helpful assistant for testing.',
|
|
32
|
-
},
|
|
33
|
-
} as IAgentRuntime);
|
|
34
|
-
}
|
|
35
|
-
return null;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
character: {
|
|
40
|
-
name: 'Test Character',
|
|
41
|
-
system: 'You are a helpful assistant for testing.',
|
|
42
|
-
bio: 'A test character for unit testing',
|
|
43
|
-
plugins: [],
|
|
44
|
-
settings: {},
|
|
45
|
-
},
|
|
46
|
-
getSetting: (key: string) => null,
|
|
47
|
-
db: {
|
|
48
|
-
get: async (key: string) => null,
|
|
49
|
-
set: async (key: string, value: unknown) => true,
|
|
50
|
-
delete: async (key: string) => true,
|
|
51
|
-
getKeys: async (pattern: string) => [],
|
|
52
|
-
},
|
|
53
|
-
getService: <T extends Service>(serviceType: string): T | null => {
|
|
54
|
-
// Log the service request for debugging
|
|
55
|
-
logger.debug(`Requesting service: ${serviceType}`);
|
|
56
|
-
|
|
57
|
-
// Get from cache or create new
|
|
58
|
-
if (!services.has(serviceType)) {
|
|
59
|
-
logger.debug(`Creating new service: ${serviceType}`);
|
|
60
|
-
const service = createService(serviceType);
|
|
61
|
-
if (service) {
|
|
62
|
-
services.set(serviceType, service);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return (services.get(serviceType) as T) || null;
|
|
67
|
-
},
|
|
68
|
-
registerService: async (ServiceClass: typeof Service): Promise<void> => {
|
|
69
|
-
logger.debug(`Registering service: ${ServiceClass.serviceType}`);
|
|
70
|
-
const runtime = {
|
|
71
|
-
character: {
|
|
72
|
-
name: 'Test Character',
|
|
73
|
-
system: 'You are a helpful assistant for testing.',
|
|
74
|
-
bio: 'A test character for unit testing',
|
|
75
|
-
},
|
|
76
|
-
} as IAgentRuntime;
|
|
77
|
-
const service = await ServiceClass.start(runtime);
|
|
78
|
-
services.set(ServiceClass.serviceType, service);
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
70
|
describe('Plugin Configuration', () => {
|
|
84
71
|
it('should have correct plugin metadata', () => {
|
|
85
|
-
|
|
86
|
-
expect(starterPlugin.
|
|
87
|
-
expect(starterPlugin.
|
|
72
|
+
// Check that plugin has required metadata (values will change when template is used)
|
|
73
|
+
expect(starterPlugin.name).toBeDefined();
|
|
74
|
+
expect(starterPlugin.name).toMatch(/^[a-z0-9-]+$/); // Valid plugin name format
|
|
75
|
+
expect(starterPlugin.description).toBeDefined();
|
|
76
|
+
expect(starterPlugin.description.length).toBeGreaterThan(0);
|
|
77
|
+
expect(starterPlugin.actions).toBeDefined();
|
|
78
|
+
expect(starterPlugin.actions?.length).toBeGreaterThan(0);
|
|
79
|
+
expect(starterPlugin.providers).toBeDefined();
|
|
80
|
+
expect(starterPlugin.providers?.length).toBeGreaterThan(0);
|
|
81
|
+
expect(starterPlugin.services).toBeDefined();
|
|
82
|
+
expect(starterPlugin.services?.length).toBeGreaterThan(0);
|
|
83
|
+
expect(starterPlugin.models).toBeDefined();
|
|
84
|
+
expect(starterPlugin.models?.[ModelType.TEXT_SMALL]).toBeDefined();
|
|
85
|
+
expect(starterPlugin.models?.[ModelType.TEXT_LARGE]).toBeDefined();
|
|
86
|
+
expect(starterPlugin.routes).toBeDefined();
|
|
87
|
+
expect(starterPlugin.routes?.length).toBeGreaterThan(0);
|
|
88
|
+
expect(starterPlugin.events).toBeDefined();
|
|
88
89
|
});
|
|
89
90
|
|
|
90
|
-
it('should
|
|
91
|
-
|
|
91
|
+
it('should initialize with valid configuration', async () => {
|
|
92
|
+
const runtime = createMockRuntime();
|
|
93
|
+
const config = { EXAMPLE_PLUGIN_VARIABLE: 'test-value' };
|
|
94
|
+
|
|
95
|
+
if (starterPlugin.init) {
|
|
96
|
+
await starterPlugin.init(config, runtime);
|
|
97
|
+
expect(process.env.EXAMPLE_PLUGIN_VARIABLE).toBe('test-value');
|
|
98
|
+
}
|
|
92
99
|
});
|
|
93
100
|
|
|
94
|
-
it('should
|
|
95
|
-
const
|
|
101
|
+
it('should handle initialization without config', async () => {
|
|
102
|
+
const runtime = createMockRuntime();
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
if (starterPlugin.init) {
|
|
105
|
+
// Init should not throw even with empty config
|
|
106
|
+
await starterPlugin.init({}, runtime);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
99
109
|
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
it('should throw error for invalid configuration', async () => {
|
|
111
|
+
const runtime = createMockRuntime();
|
|
112
|
+
const invalidConfig = { EXAMPLE_PLUGIN_VARIABLE: 123 }; // Should be string
|
|
102
113
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
);
|
|
108
|
-
expect(true).toBe(true); // If we got here, init succeeded
|
|
109
|
-
}
|
|
110
|
-
} finally {
|
|
111
|
-
process.env.EXAMPLE_PLUGIN_VARIABLE = originalEnv;
|
|
114
|
+
if (starterPlugin.init) {
|
|
115
|
+
await expect(starterPlugin.init(invalidConfig as PluginConfig, runtime)).rejects.toThrow(
|
|
116
|
+
'Invalid plugin configuration'
|
|
117
|
+
);
|
|
112
118
|
}
|
|
113
119
|
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe('Hello World Action', () => {
|
|
123
|
+
let runtime: IAgentRuntime;
|
|
124
|
+
let helloWorldAction: Action;
|
|
125
|
+
|
|
126
|
+
beforeEach(() => {
|
|
127
|
+
runtime = createMockRuntime();
|
|
128
|
+
helloWorldAction = starterPlugin?.actions?.[0] as Action;
|
|
129
|
+
// Clear all spies before each test
|
|
130
|
+
const mockLogger = logger as unknown as MockLogger;
|
|
131
|
+
mockLogger.info.calls = [];
|
|
132
|
+
mockLogger.error.calls = [];
|
|
133
|
+
mockLogger.debug.calls = [];
|
|
134
|
+
mockLogger.warn.calls = [];
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should have hello world action', () => {
|
|
138
|
+
expect(helloWorldAction).toBeDefined();
|
|
139
|
+
expect(helloWorldAction?.name).toBe('QUICK_ACTION');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should always validate messages (current implementation)', async () => {
|
|
143
|
+
if (!helloWorldAction?.validate) {
|
|
144
|
+
throw new Error('Hello world action validate not found');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const validMessages = ['say hello', 'hello world', 'Please say HELLO', 'can you say hello?'];
|
|
148
|
+
|
|
149
|
+
// The current implementation always returns true
|
|
150
|
+
// This test documents the actual behavior
|
|
151
|
+
for (const text of validMessages) {
|
|
152
|
+
const message = createTestMemory({
|
|
153
|
+
content: { text, source: 'test' },
|
|
154
|
+
});
|
|
155
|
+
const isValid = await helloWorldAction.validate(runtime, message);
|
|
156
|
+
expect(isValid).toBe(true);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('should properly validate hello messages', async () => {
|
|
161
|
+
if (!helloWorldAction?.validate) {
|
|
162
|
+
throw new Error('Hello world action validate not found');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// The current implementation always returns true
|
|
166
|
+
// Test that it accepts all messages
|
|
167
|
+
const helloMessages = ['hello', 'hi there', 'hey!', 'greetings', 'howdy partner'];
|
|
168
|
+
for (const text of helloMessages) {
|
|
169
|
+
const message = createTestMemory({
|
|
170
|
+
content: { text, source: 'test' },
|
|
171
|
+
});
|
|
172
|
+
const isValid = await helloWorldAction.validate(runtime, message);
|
|
173
|
+
expect(isValid).toBe(true);
|
|
174
|
+
}
|
|
114
175
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
176
|
+
// Should also accept non-hello messages since validate always returns true
|
|
177
|
+
const nonHelloMessages = ['goodbye', 'what is the weather', 'tell me a joke'];
|
|
178
|
+
for (const text of nonHelloMessages) {
|
|
179
|
+
const message = createTestMemory({
|
|
180
|
+
content: { text, source: 'test' },
|
|
181
|
+
});
|
|
182
|
+
const isValid = await helloWorldAction.validate(runtime, message);
|
|
183
|
+
expect(isValid).toBe(true);
|
|
120
184
|
}
|
|
185
|
+
|
|
186
|
+
// Test empty string - also returns true
|
|
187
|
+
const emptyMessage = createTestMemory({
|
|
188
|
+
content: { text: '', source: 'test' },
|
|
189
|
+
});
|
|
190
|
+
const isEmptyValid = await helloWorldAction.validate(runtime, emptyMessage);
|
|
191
|
+
expect(isEmptyValid).toBe(true);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should validate even without text content', async () => {
|
|
195
|
+
if (!helloWorldAction?.validate) {
|
|
196
|
+
throw new Error('Hello world action validate not found');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const messageWithoutText = createTestMemory({
|
|
200
|
+
content: { source: 'test' } as Content,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const isValid = await helloWorldAction.validate(runtime, messageWithoutText);
|
|
204
|
+
// Always returns true since validate always returns true
|
|
205
|
+
expect(isValid).toBe(true);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should handle hello world action with callback', async () => {
|
|
209
|
+
if (!helloWorldAction?.handler) {
|
|
210
|
+
throw new Error('Hello world action handler not found');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const message = createTestMemory({
|
|
214
|
+
content: { text: 'say hello', source: 'test' },
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
let callbackContent: TestCallbackContent | null = null;
|
|
218
|
+
const callback: HandlerCallback = async (content: Content) => {
|
|
219
|
+
callbackContent = content as TestCallbackContent;
|
|
220
|
+
return [];
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const result = await helloWorldAction.handler(runtime, message, undefined, undefined, callback);
|
|
224
|
+
|
|
225
|
+
expect(result).toHaveProperty('text', 'Hello world!');
|
|
226
|
+
expect(result).toHaveProperty('success', true);
|
|
227
|
+
expect(result).toHaveProperty('data');
|
|
228
|
+
const typedResult = result as TestActionResult;
|
|
229
|
+
expect(typedResult.data).toHaveProperty('actions', ['QUICK_ACTION']);
|
|
230
|
+
expect(typedResult.data).toHaveProperty('source', 'test');
|
|
231
|
+
|
|
232
|
+
expect(callbackContent).toEqual({
|
|
233
|
+
text: 'Hello world!',
|
|
234
|
+
actions: ['QUICK_ACTION'],
|
|
235
|
+
source: 'test',
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('should handle errors gracefully', async () => {
|
|
240
|
+
if (!helloWorldAction?.handler) {
|
|
241
|
+
throw new Error('Hello world action handler not found');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const message = createTestMemory({
|
|
245
|
+
content: { text: 'say hello', source: 'test' },
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
const errorCallback: HandlerCallback = async () => {
|
|
249
|
+
throw new Error('Callback error');
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const result = await helloWorldAction.handler(
|
|
253
|
+
runtime,
|
|
254
|
+
message,
|
|
255
|
+
undefined,
|
|
256
|
+
undefined,
|
|
257
|
+
errorCallback
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
expect(result).toHaveProperty('success', false);
|
|
261
|
+
expect(result).toHaveProperty('error');
|
|
262
|
+
const typedResult = result as TestActionResult;
|
|
263
|
+
expect(typedResult.error?.message).toBe('Callback error');
|
|
264
|
+
// Quick-starter plugin doesn't log errors
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should handle missing callback gracefully', async () => {
|
|
268
|
+
if (!helloWorldAction?.handler) {
|
|
269
|
+
throw new Error('Hello world action handler not found');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const message = createTestMemory({
|
|
273
|
+
content: { text: 'say hello', source: 'test' },
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const result = await helloWorldAction.handler(
|
|
277
|
+
runtime,
|
|
278
|
+
message,
|
|
279
|
+
undefined,
|
|
280
|
+
undefined,
|
|
281
|
+
undefined
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
expect(result).toHaveProperty('text', 'Hello world!');
|
|
285
|
+
expect(result).toHaveProperty('success', true);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('should handle state parameter correctly', async () => {
|
|
289
|
+
if (!helloWorldAction?.handler) {
|
|
290
|
+
throw new Error('Hello world action handler not found');
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const message = createTestMemory({
|
|
294
|
+
content: { text: 'say hello', source: 'test' },
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const state = createTestState({
|
|
298
|
+
values: { customValue: 'test-state' },
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
const result = await helloWorldAction.handler(runtime, message, state, undefined, undefined);
|
|
302
|
+
|
|
303
|
+
expect(result).toHaveProperty('success', true);
|
|
121
304
|
});
|
|
122
305
|
});
|
|
123
306
|
|
|
124
|
-
describe('
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
307
|
+
describe('Hello World Provider', () => {
|
|
308
|
+
const provider = starterPlugin.providers?.[0];
|
|
309
|
+
let runtime: IAgentRuntime;
|
|
310
|
+
|
|
311
|
+
beforeEach(() => {
|
|
312
|
+
runtime = createMockRuntime();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('should have hello world provider', () => {
|
|
316
|
+
expect(provider).toBeDefined();
|
|
317
|
+
expect(provider?.name).toBe('QUICK_PROVIDER');
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it('should provide hello world data', async () => {
|
|
321
|
+
if (!provider?.get) {
|
|
322
|
+
throw new Error('Hello world provider not found');
|
|
129
323
|
}
|
|
324
|
+
|
|
325
|
+
const message = createTestMemory();
|
|
326
|
+
const state = createTestState();
|
|
327
|
+
|
|
328
|
+
const result = await provider.get(runtime, message, state);
|
|
329
|
+
|
|
330
|
+
expect(result).toHaveProperty('text', 'I am a provider');
|
|
331
|
+
expect(result).toHaveProperty('values');
|
|
332
|
+
expect(result.values).toEqual({});
|
|
333
|
+
expect(result).toHaveProperty('data');
|
|
334
|
+
expect(result.data).toEqual({});
|
|
130
335
|
});
|
|
131
336
|
|
|
132
|
-
it('should
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
expect(typeof starterPlugin.models[ModelType.TEXT_LARGE]).toBe('function');
|
|
337
|
+
it('should provide consistent structure across calls', async () => {
|
|
338
|
+
if (!provider?.get) {
|
|
339
|
+
throw new Error('Hello world provider not found');
|
|
136
340
|
}
|
|
341
|
+
|
|
342
|
+
const message = createTestMemory();
|
|
343
|
+
const state = createTestState();
|
|
344
|
+
|
|
345
|
+
const result1 = await provider.get(runtime, message, state);
|
|
346
|
+
const result2 = await provider.get(runtime, message, state);
|
|
347
|
+
|
|
348
|
+
// Text and structure should be consistent
|
|
349
|
+
expect(result1.text).toBeDefined();
|
|
350
|
+
expect(result2.text).toBeDefined();
|
|
351
|
+
expect(result1.text).toBe(result2.text);
|
|
352
|
+
expect(result1.values || {}).toEqual(result2.values || {});
|
|
353
|
+
expect(result1.data || {}).toEqual(result2.data || {});
|
|
137
354
|
});
|
|
355
|
+
});
|
|
138
356
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const runtime = createRealRuntime();
|
|
142
|
-
const result = await starterPlugin.models[ModelType.TEXT_SMALL](runtime as IAgentRuntime, {
|
|
143
|
-
prompt: 'test',
|
|
144
|
-
});
|
|
357
|
+
describe('Model Handlers', () => {
|
|
358
|
+
let runtime: IAgentRuntime;
|
|
145
359
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
360
|
+
beforeEach(() => {
|
|
361
|
+
runtime = createMockRuntime();
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('should handle TEXT_SMALL model', async () => {
|
|
365
|
+
const handler = starterPlugin.models?.[ModelType.TEXT_SMALL];
|
|
366
|
+
if (!handler) {
|
|
367
|
+
throw new Error('TEXT_SMALL model handler not found');
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const result = await handler(runtime, { prompt: 'Test prompt' });
|
|
371
|
+
|
|
372
|
+
expect(result).toContain('Never gonna give you up');
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it('should handle TEXT_LARGE model with custom parameters', async () => {
|
|
376
|
+
const handler = starterPlugin.models?.[ModelType.TEXT_LARGE];
|
|
377
|
+
if (!handler) {
|
|
378
|
+
throw new Error('TEXT_LARGE model handler not found');
|
|
150
379
|
}
|
|
380
|
+
|
|
381
|
+
const result = await handler(runtime, {
|
|
382
|
+
prompt: 'Test prompt with custom settings',
|
|
383
|
+
maxTokens: 1000,
|
|
384
|
+
temperature: 0.5,
|
|
385
|
+
frequencyPenalty: 0.5,
|
|
386
|
+
presencePenalty: 0.5,
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
expect(result).toContain('Never gonna make you cry');
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('should handle empty prompt', async () => {
|
|
393
|
+
const handler = starterPlugin.models?.[ModelType.TEXT_SMALL];
|
|
394
|
+
if (!handler) {
|
|
395
|
+
throw new Error('TEXT_SMALL model handler not found');
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const result = await handler(runtime, { prompt: '' });
|
|
399
|
+
|
|
400
|
+
expect(typeof result).toBe('string');
|
|
401
|
+
expect(result.length).toBeGreaterThan(0);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('should handle missing parameters', async () => {
|
|
405
|
+
const handler = starterPlugin.models?.[ModelType.TEXT_LARGE];
|
|
406
|
+
if (!handler) {
|
|
407
|
+
throw new Error('TEXT_LARGE model handler not found');
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const result = await handler(runtime, { prompt: 'Test prompt' });
|
|
411
|
+
|
|
412
|
+
expect(typeof result).toBe('string');
|
|
413
|
+
expect(result.length).toBeGreaterThan(0);
|
|
151
414
|
});
|
|
152
415
|
});
|
|
153
416
|
|
|
154
|
-
describe('
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
417
|
+
describe('API Routes', () => {
|
|
418
|
+
let runtime: IAgentRuntime;
|
|
419
|
+
|
|
420
|
+
beforeEach(() => {
|
|
421
|
+
runtime = createMockRuntime();
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
it('should handle status route', async () => {
|
|
425
|
+
const statusRoute = starterPlugin.routes?.[0];
|
|
426
|
+
if (!statusRoute?.handler) {
|
|
427
|
+
throw new Error('Status route handler not found');
|
|
428
|
+
}
|
|
158
429
|
|
|
159
|
-
|
|
160
|
-
|
|
430
|
+
const mockRes = {
|
|
431
|
+
json: (data: any) => {
|
|
432
|
+
mockRes._jsonData = data;
|
|
433
|
+
},
|
|
434
|
+
_jsonData: null as any,
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
await statusRoute.handler({}, mockRes, runtime);
|
|
161
438
|
|
|
162
|
-
|
|
163
|
-
expect(
|
|
439
|
+
expect(mockRes._jsonData).toBeDefined();
|
|
440
|
+
expect(mockRes._jsonData.status).toBe('ok');
|
|
441
|
+
expect(mockRes._jsonData.plugin).toBe('quick-starter');
|
|
442
|
+
expect(mockRes._jsonData.timestamp).toBeDefined();
|
|
164
443
|
});
|
|
165
444
|
|
|
166
|
-
it('should
|
|
167
|
-
const
|
|
445
|
+
it('should validate route configuration', () => {
|
|
446
|
+
const statusRoute = starterPlugin.routes?.[0];
|
|
168
447
|
|
|
169
|
-
|
|
170
|
-
|
|
448
|
+
expect(statusRoute).toBeDefined();
|
|
449
|
+
expect(statusRoute?.path).toBe('/api/status');
|
|
450
|
+
expect(statusRoute?.type).toBe('GET');
|
|
451
|
+
// Routes don't have a public property in the current implementation
|
|
452
|
+
expect(statusRoute?.handler).toBeDefined();
|
|
453
|
+
});
|
|
171
454
|
|
|
172
|
-
|
|
173
|
-
const
|
|
455
|
+
it('should handle request with query parameters', async () => {
|
|
456
|
+
const statusRoute = starterPlugin.routes?.[0];
|
|
457
|
+
if (!statusRoute?.handler) {
|
|
458
|
+
throw new Error('Status route handler not found');
|
|
459
|
+
}
|
|
174
460
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return service as T;
|
|
180
|
-
}
|
|
181
|
-
return null;
|
|
461
|
+
const mockReq = {
|
|
462
|
+
query: {
|
|
463
|
+
verbose: 'true',
|
|
464
|
+
},
|
|
182
465
|
};
|
|
183
466
|
|
|
184
|
-
|
|
185
|
-
|
|
467
|
+
const mockRes = {
|
|
468
|
+
json: (data: any) => {
|
|
469
|
+
mockRes._jsonData = data;
|
|
470
|
+
},
|
|
471
|
+
_jsonData: null as any,
|
|
472
|
+
};
|
|
186
473
|
|
|
187
|
-
|
|
188
|
-
expect(stopSpy).toHaveBeenCalled();
|
|
474
|
+
await statusRoute.handler(mockReq, mockRes, runtime);
|
|
189
475
|
|
|
190
|
-
|
|
191
|
-
|
|
476
|
+
expect(mockRes._jsonData).toBeDefined();
|
|
477
|
+
expect(mockRes._jsonData.status).toBe('ok');
|
|
192
478
|
});
|
|
479
|
+
});
|
|
193
480
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
//
|
|
481
|
+
describe('Event Handlers', () => {
|
|
482
|
+
beforeEach(() => {
|
|
483
|
+
// Clear logger spy calls
|
|
484
|
+
(logger.debug as any).calls = [];
|
|
485
|
+
(logger.info as any).calls = [];
|
|
486
|
+
(logger.error as any).calls = [];
|
|
487
|
+
});
|
|
197
488
|
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
|
|
489
|
+
it('should log when MESSAGE_RECEIVED event is triggered', async () => {
|
|
490
|
+
const handler = starterPlugin.events?.[EventType.MESSAGE_RECEIVED]?.[0];
|
|
491
|
+
if (!handler) {
|
|
492
|
+
throw new Error('MESSAGE_RECEIVED event handler not found');
|
|
493
|
+
}
|
|
201
494
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
495
|
+
const payload = testFixtures.messagePayload();
|
|
496
|
+
await handler(payload);
|
|
497
|
+
|
|
498
|
+
expect(logger.debug).toHaveBeenCalled();
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
it('should handle malformed event payload', async () => {
|
|
502
|
+
const handler = starterPlugin.events?.[EventType.MESSAGE_RECEIVED]?.[0];
|
|
503
|
+
if (!handler) {
|
|
504
|
+
throw new Error('MESSAGE_RECEIVED event handler not found');
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const malformedPayload = {
|
|
508
|
+
// Missing required fields
|
|
509
|
+
runtime: createMockRuntime(),
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
// Should not throw
|
|
513
|
+
// Handler doesn't actually use the payload, just logs
|
|
514
|
+
await handler(malformedPayload as any);
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
it('should handle event with empty message content', async () => {
|
|
518
|
+
const handler = starterPlugin.events?.[EventType.MESSAGE_RECEIVED]?.[0];
|
|
519
|
+
if (!handler) {
|
|
520
|
+
throw new Error('MESSAGE_RECEIVED event handler not found');
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
const payload = testFixtures.messagePayload({
|
|
524
|
+
content: {},
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
await handler(payload);
|
|
528
|
+
expect(logger.debug).toHaveBeenCalled();
|
|
529
|
+
});
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
describe('StarterService', () => {
|
|
533
|
+
let runtime: IAgentRuntime;
|
|
205
534
|
|
|
206
|
-
|
|
207
|
-
runtime
|
|
535
|
+
beforeEach(() => {
|
|
536
|
+
runtime = createMockRuntime();
|
|
537
|
+
// Clear logger spy calls
|
|
538
|
+
(logger.info as any).calls = [];
|
|
539
|
+
(logger.error as any).calls = [];
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
it('should start the service', async () => {
|
|
543
|
+
const service = await StarterService.start(runtime);
|
|
544
|
+
expect(service).toBeInstanceOf(StarterService);
|
|
545
|
+
expect(logger.info).toHaveBeenCalled();
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
it('should have correct service type', () => {
|
|
549
|
+
expect(StarterService.serviceType).toBe('starter');
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
it('should stop service correctly', async () => {
|
|
553
|
+
// Start service
|
|
554
|
+
const service = await StarterService.start(runtime);
|
|
555
|
+
|
|
556
|
+
// Create a new runtime with the service registered
|
|
557
|
+
const runtimeWithService = createMockRuntime({
|
|
558
|
+
getService: () => service as any,
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
// Stop service
|
|
562
|
+
await StarterService.stop(runtimeWithService);
|
|
563
|
+
expect(logger.info).toHaveBeenCalled();
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
it('should throw error when stopping non-existent service', async () => {
|
|
567
|
+
const emptyRuntime = createMockRuntime({
|
|
568
|
+
getService: () => null,
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
await expect(StarterService.stop(emptyRuntime)).rejects.toThrow('Starter service not found');
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
it('should handle multiple start/stop cycles', async () => {
|
|
575
|
+
// First cycle
|
|
576
|
+
const service1 = await StarterService.start(runtime);
|
|
577
|
+
expect(service1).toBeInstanceOf(StarterService);
|
|
578
|
+
|
|
579
|
+
const runtimeWithService1 = createMockRuntime({
|
|
580
|
+
getService: () => service1 as any,
|
|
581
|
+
});
|
|
582
|
+
await StarterService.stop(runtimeWithService1);
|
|
583
|
+
|
|
584
|
+
// Second cycle
|
|
585
|
+
const service2 = await StarterService.start(runtime);
|
|
586
|
+
expect(service2).toBeInstanceOf(StarterService);
|
|
587
|
+
|
|
588
|
+
const runtimeWithService2 = createMockRuntime({
|
|
589
|
+
getService: () => service2 as any,
|
|
590
|
+
});
|
|
591
|
+
await StarterService.stop(runtimeWithService2);
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
it('should provide capability description', async () => {
|
|
595
|
+
const service = await StarterService.start(runtime);
|
|
596
|
+
expect(service.capabilityDescription).toBe(
|
|
597
|
+
'This is a starter service which is attached to the agent through the starter plugin.'
|
|
598
|
+
);
|
|
208
599
|
});
|
|
209
600
|
});
|