@elizaos/core 1.5.1 → 1.5.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/dist/browser/index.browser.js +120 -120
- package/dist/browser/index.browser.js.map +5 -21
- package/dist/browser/index.d.ts +3 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -5
- package/dist/node/index.d.ts +3 -1
- package/package.json +10 -4
- package/src/__tests__/action-chaining-simple.test.ts +203 -0
- package/src/__tests__/actions.test.ts +218 -0
- package/src/__tests__/buffer.test.ts +337 -0
- package/src/__tests__/character-validation.test.ts +309 -0
- package/src/__tests__/database.test.ts +750 -0
- package/src/__tests__/entities.test.ts +727 -0
- package/src/__tests__/env.test.ts +23 -0
- package/src/__tests__/environment.test.ts +285 -0
- package/src/__tests__/logger-browser-node.test.ts +716 -0
- package/src/__tests__/logger.test.ts +403 -0
- package/src/__tests__/messages.test.ts +196 -0
- package/src/__tests__/mockCharacter.ts +544 -0
- package/src/__tests__/parsing.test.ts +58 -0
- package/src/__tests__/prompts.test.ts +159 -0
- package/src/__tests__/roles.test.ts +331 -0
- package/src/__tests__/runtime-embedding.test.ts +343 -0
- package/src/__tests__/runtime.test.ts +978 -0
- package/src/__tests__/search.test.ts +15 -0
- package/src/__tests__/services-by-type.test.ts +204 -0
- package/src/__tests__/services.test.ts +136 -0
- package/src/__tests__/settings.test.ts +810 -0
- package/src/__tests__/utils.test.ts +1105 -0
- package/src/__tests__/uuid.test.ts +94 -0
- package/src/actions.ts +122 -0
- package/src/database.ts +579 -0
- package/src/entities.ts +406 -0
- package/src/index.browser.ts +48 -0
- package/src/index.node.ts +39 -0
- package/src/index.ts +50 -0
- package/src/logger.ts +527 -0
- package/src/prompts.ts +243 -0
- package/src/roles.ts +85 -0
- package/src/runtime.ts +2514 -0
- package/src/schemas/character.ts +149 -0
- package/src/search.ts +1543 -0
- package/src/sentry/instrument.browser.ts +65 -0
- package/src/sentry/instrument.node.ts +57 -0
- package/src/sentry/instrument.ts +82 -0
- package/src/services.ts +105 -0
- package/src/settings.ts +409 -0
- package/src/test_resources/constants.ts +12 -0
- package/src/test_resources/testSetup.ts +21 -0
- package/src/test_resources/types.ts +22 -0
- package/src/types/agent.ts +112 -0
- package/src/types/browser.ts +145 -0
- package/src/types/components.ts +184 -0
- package/src/types/database.ts +348 -0
- package/src/types/email.ts +162 -0
- package/src/types/environment.ts +129 -0
- package/src/types/events.ts +249 -0
- package/src/types/index.ts +29 -0
- package/src/types/knowledge.ts +65 -0
- package/src/types/lp.ts +124 -0
- package/src/types/memory.ts +228 -0
- package/src/types/message.ts +233 -0
- package/src/types/messaging.ts +57 -0
- package/src/types/model.ts +359 -0
- package/src/types/pdf.ts +77 -0
- package/src/types/plugin.ts +78 -0
- package/src/types/post.ts +271 -0
- package/src/types/primitives.ts +97 -0
- package/src/types/runtime.ts +190 -0
- package/src/types/service.ts +198 -0
- package/src/types/settings.ts +30 -0
- package/src/types/state.ts +60 -0
- package/src/types/task.ts +72 -0
- package/src/types/tee.ts +107 -0
- package/src/types/testing.ts +30 -0
- package/src/types/token.ts +96 -0
- package/src/types/transcription.ts +133 -0
- package/src/types/video.ts +108 -0
- package/src/types/wallet.ts +56 -0
- package/src/types/web-search.ts +146 -0
- package/src/utils/__tests__/buffer.test.ts +80 -0
- package/src/utils/__tests__/environment.test.ts +58 -0
- package/src/utils/__tests__/stringToUuid.test.ts +88 -0
- package/src/utils/buffer.ts +312 -0
- package/src/utils/environment.ts +316 -0
- package/src/utils/server-health.ts +117 -0
- package/src/utils.ts +1076 -0
- package/dist/tsconfig.build.tsbuildinfo +0 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import {
|
|
3
|
+
shouldRespondTemplate,
|
|
4
|
+
messageHandlerTemplate,
|
|
5
|
+
postCreationTemplate,
|
|
6
|
+
booleanFooter,
|
|
7
|
+
imageDescriptionTemplate,
|
|
8
|
+
} from '../prompts';
|
|
9
|
+
|
|
10
|
+
describe('Prompts', () => {
|
|
11
|
+
describe('Template Structure', () => {
|
|
12
|
+
it('shouldRespondTemplate should contain required placeholders and XML structure', () => {
|
|
13
|
+
expect(shouldRespondTemplate).toContain('{{agentName}}');
|
|
14
|
+
expect(shouldRespondTemplate).toContain('{{providers}}');
|
|
15
|
+
expect(shouldRespondTemplate).toContain('<response>');
|
|
16
|
+
expect(shouldRespondTemplate).toContain('</response>');
|
|
17
|
+
expect(shouldRespondTemplate).toContain('<name>');
|
|
18
|
+
expect(shouldRespondTemplate).toContain('<reasoning>');
|
|
19
|
+
expect(shouldRespondTemplate).toContain('<action>');
|
|
20
|
+
expect(shouldRespondTemplate).toMatch(/RESPOND \| IGNORE \| STOP/);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('messageHandlerTemplate should contain required placeholders and structure', () => {
|
|
24
|
+
expect(messageHandlerTemplate).toContain('{{agentName}}');
|
|
25
|
+
expect(messageHandlerTemplate).toContain('{{providers}}');
|
|
26
|
+
expect(messageHandlerTemplate).toContain('<response>');
|
|
27
|
+
expect(messageHandlerTemplate).toContain('</response>');
|
|
28
|
+
expect(messageHandlerTemplate).toContain('<thought>');
|
|
29
|
+
expect(messageHandlerTemplate).toContain('<actions>');
|
|
30
|
+
expect(messageHandlerTemplate).toContain('<providers>');
|
|
31
|
+
expect(messageHandlerTemplate).toContain('<text>');
|
|
32
|
+
|
|
33
|
+
// Check for important action ordering rules
|
|
34
|
+
expect(messageHandlerTemplate).toContain('IMPORTANT ACTION ORDERING RULES');
|
|
35
|
+
expect(messageHandlerTemplate).toContain('Actions are executed in the ORDER you list them');
|
|
36
|
+
|
|
37
|
+
// Ensure code block formatting rules are explicitly included
|
|
38
|
+
expect(messageHandlerTemplate).toContain('IMPORTANT CODE BLOCK FORMATTING RULES');
|
|
39
|
+
expect(messageHandlerTemplate).toContain('fenced code blocks');
|
|
40
|
+
expect(messageHandlerTemplate).toContain('single backticks');
|
|
41
|
+
|
|
42
|
+
// Check for provider selection rules
|
|
43
|
+
expect(messageHandlerTemplate).toContain('IMPORTANT PROVIDER SELECTION RULES');
|
|
44
|
+
expect(messageHandlerTemplate).toContain('ATTACHMENTS');
|
|
45
|
+
expect(messageHandlerTemplate).toContain('ENTITIES');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('postCreationTemplate should contain required placeholders and examples', () => {
|
|
49
|
+
expect(postCreationTemplate).toContain('{{agentName}}');
|
|
50
|
+
expect(postCreationTemplate).toContain('{{twitterUserName}}');
|
|
51
|
+
expect(postCreationTemplate).toContain('{{providers}}');
|
|
52
|
+
expect(postCreationTemplate).toContain('{{adjective}}');
|
|
53
|
+
expect(postCreationTemplate).toContain('{{topic}}');
|
|
54
|
+
expect(postCreationTemplate).toContain('<response>');
|
|
55
|
+
expect(postCreationTemplate).toContain('</response>');
|
|
56
|
+
expect(postCreationTemplate).toContain('<thought>');
|
|
57
|
+
expect(postCreationTemplate).toContain('<post>');
|
|
58
|
+
expect(postCreationTemplate).toContain('<imagePrompt>');
|
|
59
|
+
|
|
60
|
+
// Check for example outputs
|
|
61
|
+
expect(postCreationTemplate).toMatch(/Example task outputs:/);
|
|
62
|
+
expect(postCreationTemplate).toContain('A post about');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('booleanFooter should be a simple instruction', () => {
|
|
66
|
+
expect(booleanFooter).toBe('Respond with only a YES or a NO.');
|
|
67
|
+
expect(booleanFooter).toMatch(/^Respond with only a YES or a NO\.$/);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('imageDescriptionTemplate should contain proper XML structure', () => {
|
|
71
|
+
expect(imageDescriptionTemplate).toContain('<task>');
|
|
72
|
+
expect(imageDescriptionTemplate).toContain('<instructions>');
|
|
73
|
+
expect(imageDescriptionTemplate).toContain('<output>');
|
|
74
|
+
expect(imageDescriptionTemplate).toContain('<response>');
|
|
75
|
+
expect(imageDescriptionTemplate).toContain('</response>');
|
|
76
|
+
expect(imageDescriptionTemplate).toContain('<title>');
|
|
77
|
+
expect(imageDescriptionTemplate).toContain('<description>');
|
|
78
|
+
expect(imageDescriptionTemplate).toContain('<text>');
|
|
79
|
+
|
|
80
|
+
// Check for important instructions
|
|
81
|
+
expect(imageDescriptionTemplate).toContain('Analyze the provided image');
|
|
82
|
+
expect(imageDescriptionTemplate).toContain('Be objective and descriptive');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('Template Consistency', () => {
|
|
87
|
+
const templates = [
|
|
88
|
+
shouldRespondTemplate,
|
|
89
|
+
messageHandlerTemplate,
|
|
90
|
+
postCreationTemplate,
|
|
91
|
+
imageDescriptionTemplate,
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
it('all templates should have consistent XML output format instructions', () => {
|
|
95
|
+
templates.forEach((template) => {
|
|
96
|
+
expect(template).toContain('Do NOT include any thinking, reasoning, or <think> sections');
|
|
97
|
+
expect(template).toContain(
|
|
98
|
+
'IMPORTANT: Your response must ONLY contain the <response></response> XML block'
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('all templates should use proper XML closing tags', () => {
|
|
104
|
+
templates.forEach((template) => {
|
|
105
|
+
// Extract only the XML response format sections (not instructions mentioning tags)
|
|
106
|
+
const responseBlocks = template.match(/<response>[\s\S]*?<\/response>/g) || [];
|
|
107
|
+
|
|
108
|
+
responseBlocks.forEach((block) => {
|
|
109
|
+
// Get all open tags within response blocks
|
|
110
|
+
const openTags = (block.match(/<[^/][^>]+>/g) || [])
|
|
111
|
+
.filter((tag) => !tag.includes('/>'))
|
|
112
|
+
.filter((tag) => !tag.includes('think')); // Exclude mentioned-but-not-present tags
|
|
113
|
+
|
|
114
|
+
const closeTags = block.match(/<\/[^>]+>/g) || [];
|
|
115
|
+
|
|
116
|
+
// For each unique open tag, there should be a corresponding close tag
|
|
117
|
+
openTags.forEach((openTag) => {
|
|
118
|
+
const tagName = openTag.match(/<([^\s>]+)/)?.[1];
|
|
119
|
+
if (tagName && !['br', 'hr', 'img', 'input', 'meta', 'link'].includes(tagName)) {
|
|
120
|
+
expect(closeTags.some((closeTag) => closeTag.includes(tagName))).toBe(true);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Also check the main structural tags outside response blocks
|
|
126
|
+
const mainTags = ['task', 'providers', 'instructions', 'output', 'keys', 'actionNames'];
|
|
127
|
+
mainTags.forEach((tag) => {
|
|
128
|
+
if (template.includes(`<${tag}>`)) {
|
|
129
|
+
expect(template).toContain(`</${tag}>`);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe('Template Placeholders', () => {
|
|
137
|
+
it('should use consistent placeholder format', () => {
|
|
138
|
+
const placeholderPattern = /\{\{[^}]+\}\}/g;
|
|
139
|
+
|
|
140
|
+
const shouldRespondPlaceholders = shouldRespondTemplate.match(placeholderPattern) || [];
|
|
141
|
+
const messageHandlerPlaceholders = messageHandlerTemplate.match(placeholderPattern) || [];
|
|
142
|
+
const postCreationPlaceholders = postCreationTemplate.match(placeholderPattern) || [];
|
|
143
|
+
|
|
144
|
+
// All placeholders should use double curly braces
|
|
145
|
+
[
|
|
146
|
+
...shouldRespondPlaceholders,
|
|
147
|
+
...messageHandlerPlaceholders,
|
|
148
|
+
...postCreationPlaceholders,
|
|
149
|
+
].forEach((placeholder) => {
|
|
150
|
+
expect(placeholder).toMatch(/^\{\{[^}]+\}\}$/);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Common placeholders should be consistent across templates
|
|
154
|
+
expect(shouldRespondPlaceholders).toContain('{{agentName}}');
|
|
155
|
+
expect(messageHandlerPlaceholders).toContain('{{agentName}}');
|
|
156
|
+
expect(postCreationPlaceholders).toContain('{{agentName}}');
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
|
2
|
+
import { mock, spyOn } from 'bun:test';
|
|
3
|
+
import { getUserServerRole, findWorldsForOwner } from '../roles';
|
|
4
|
+
import { Role, type IAgentRuntime, type UUID, type World } from '../types';
|
|
5
|
+
import * as entities from '../entities';
|
|
6
|
+
import * as logger_module from '../logger';
|
|
7
|
+
|
|
8
|
+
describe('roles utilities', () => {
|
|
9
|
+
let mockRuntime: IAgentRuntime;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
mock.restore();
|
|
13
|
+
|
|
14
|
+
// Set up scoped mocks for this test
|
|
15
|
+
spyOn(entities, 'createUniqueUuid').mockImplementation(
|
|
16
|
+
(_runtime, serverId) => `unique-${serverId}` as UUID
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// Mock logger if it doesn't have the methods
|
|
20
|
+
if (logger_module.logger) {
|
|
21
|
+
const methods = ['error', 'info', 'warn', 'debug'];
|
|
22
|
+
methods.forEach((method) => {
|
|
23
|
+
if (typeof logger_module.logger[method] === 'function') {
|
|
24
|
+
spyOn(logger_module.logger, method).mockImplementation(() => {});
|
|
25
|
+
} else {
|
|
26
|
+
logger_module.logger[method] = mock(() => {});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
mockRuntime = {
|
|
32
|
+
agentId: 'agent-123' as UUID,
|
|
33
|
+
getWorld: mock(),
|
|
34
|
+
getAllWorlds: mock(),
|
|
35
|
+
} as unknown as IAgentRuntime;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
mock.restore();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('getUserServerRole', () => {
|
|
43
|
+
it('should return role from world metadata', async () => {
|
|
44
|
+
const mockWorld: World = {
|
|
45
|
+
id: 'world-123' as UUID,
|
|
46
|
+
name: 'Test World',
|
|
47
|
+
agentId: 'agent-123' as UUID,
|
|
48
|
+
serverId: 'server-123',
|
|
49
|
+
metadata: {
|
|
50
|
+
roles: {
|
|
51
|
+
['user-123-456-789-abc-def012345678' as UUID]: Role.ADMIN,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
(mockRuntime.getWorld as any).mockResolvedValue(mockWorld);
|
|
57
|
+
|
|
58
|
+
const role = await getUserServerRole(
|
|
59
|
+
mockRuntime,
|
|
60
|
+
'user-123-456-789-abc-def012345678',
|
|
61
|
+
'server-123'
|
|
62
|
+
);
|
|
63
|
+
expect(role).toBe(Role.ADMIN);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should return Role.NONE when world is null', async () => {
|
|
67
|
+
(mockRuntime.getWorld as any).mockResolvedValue(null);
|
|
68
|
+
|
|
69
|
+
const role = await getUserServerRole(mockRuntime, 'user-123', 'server-123');
|
|
70
|
+
expect(role).toBe(Role.NONE);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should return Role.NONE when world has no metadata', async () => {
|
|
74
|
+
const mockWorld: World = {
|
|
75
|
+
id: 'world-123' as UUID,
|
|
76
|
+
name: 'Test World',
|
|
77
|
+
agentId: 'agent-123' as UUID,
|
|
78
|
+
serverId: 'server-123',
|
|
79
|
+
metadata: {},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
(mockRuntime.getWorld as any).mockResolvedValue(mockWorld);
|
|
83
|
+
|
|
84
|
+
const role = await getUserServerRole(mockRuntime, 'user-123', 'server-123');
|
|
85
|
+
expect(role).toBe(Role.NONE);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should return Role.NONE when world has no roles in metadata', async () => {
|
|
89
|
+
const mockWorld: World = {
|
|
90
|
+
id: 'world-123' as UUID,
|
|
91
|
+
name: 'Test World',
|
|
92
|
+
agentId: 'agent-123' as UUID,
|
|
93
|
+
serverId: 'server-123',
|
|
94
|
+
metadata: {
|
|
95
|
+
someOtherData: 'value',
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
(mockRuntime.getWorld as any).mockResolvedValue(mockWorld);
|
|
100
|
+
|
|
101
|
+
const role = await getUserServerRole(mockRuntime, 'user-123', 'server-123');
|
|
102
|
+
expect(role).toBe(Role.NONE);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should check original ID format when first check fails', async () => {
|
|
106
|
+
const mockWorld: World = {
|
|
107
|
+
id: 'world-123' as UUID,
|
|
108
|
+
name: 'Test World',
|
|
109
|
+
agentId: 'agent-123' as UUID,
|
|
110
|
+
serverId: 'server-123',
|
|
111
|
+
metadata: {
|
|
112
|
+
roles: {
|
|
113
|
+
['user-456-789-abc-def-012345678901' as UUID]: Role.OWNER,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
(mockRuntime.getWorld as any).mockResolvedValue(mockWorld);
|
|
119
|
+
|
|
120
|
+
// Even though the code has duplicate checks for entityId, it should return NONE
|
|
121
|
+
// since 'user-123' is not in the roles
|
|
122
|
+
const role = await getUserServerRole(mockRuntime, 'user-123', 'server-123');
|
|
123
|
+
expect(role).toBe(Role.NONE);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should return role for different role types', async () => {
|
|
127
|
+
const mockWorld: World = {
|
|
128
|
+
id: 'world-123' as UUID,
|
|
129
|
+
name: 'Test World',
|
|
130
|
+
agentId: 'agent-123' as UUID,
|
|
131
|
+
serverId: 'server-123',
|
|
132
|
+
metadata: {
|
|
133
|
+
roles: {
|
|
134
|
+
['owner-user-123-456-789-abcdef0123' as UUID]: Role.OWNER,
|
|
135
|
+
['admin-user-123-456-789-abcdef0123' as UUID]: Role.ADMIN,
|
|
136
|
+
['none-user-123-456-789-abcdef01234' as UUID]: Role.NONE,
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
(mockRuntime.getWorld as any).mockResolvedValue(mockWorld);
|
|
142
|
+
|
|
143
|
+
const ownerRole = await getUserServerRole(
|
|
144
|
+
mockRuntime,
|
|
145
|
+
'owner-user-123-456-789-abcdef0123',
|
|
146
|
+
'server-123'
|
|
147
|
+
);
|
|
148
|
+
expect(ownerRole).toBe(Role.OWNER);
|
|
149
|
+
|
|
150
|
+
const adminRole = await getUserServerRole(
|
|
151
|
+
mockRuntime,
|
|
152
|
+
'admin-user-123-456-789-abcdef0123',
|
|
153
|
+
'server-123'
|
|
154
|
+
);
|
|
155
|
+
expect(adminRole).toBe(Role.ADMIN);
|
|
156
|
+
|
|
157
|
+
const noneRole = await getUserServerRole(
|
|
158
|
+
mockRuntime,
|
|
159
|
+
'none-user-123-456-789-abcdef01234',
|
|
160
|
+
'server-123'
|
|
161
|
+
);
|
|
162
|
+
expect(noneRole).toBe(Role.NONE);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
describe('findWorldsForOwner', () => {
|
|
167
|
+
it('should find worlds where user is owner', async () => {
|
|
168
|
+
const mockWorlds: World[] = [
|
|
169
|
+
{
|
|
170
|
+
id: 'world-1' as UUID,
|
|
171
|
+
name: 'World 1',
|
|
172
|
+
agentId: 'agent-123' as UUID,
|
|
173
|
+
serverId: 'server-1',
|
|
174
|
+
metadata: {
|
|
175
|
+
ownership: {
|
|
176
|
+
ownerId: 'user-123',
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: 'world-2' as UUID,
|
|
182
|
+
name: 'World 2',
|
|
183
|
+
agentId: 'agent-123' as UUID,
|
|
184
|
+
serverId: 'server-2',
|
|
185
|
+
metadata: {
|
|
186
|
+
ownership: {
|
|
187
|
+
ownerId: 'other-user',
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: 'world-3' as UUID,
|
|
193
|
+
name: 'World 3',
|
|
194
|
+
agentId: 'agent-123' as UUID,
|
|
195
|
+
serverId: 'server-3',
|
|
196
|
+
metadata: {
|
|
197
|
+
ownership: {
|
|
198
|
+
ownerId: 'user-123',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
(mockRuntime.getAllWorlds as any).mockResolvedValue(mockWorlds);
|
|
205
|
+
|
|
206
|
+
const ownerWorlds = await findWorldsForOwner(mockRuntime, 'user-123');
|
|
207
|
+
|
|
208
|
+
expect(ownerWorlds).toBeDefined();
|
|
209
|
+
expect(ownerWorlds?.length).toBe(2);
|
|
210
|
+
expect(ownerWorlds?.[0].id).toBe('world-1' as UUID);
|
|
211
|
+
expect(ownerWorlds?.[1].id).toBe('world-3' as UUID);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('should return null when entityId is empty', async () => {
|
|
215
|
+
const { logger } = await import('../logger');
|
|
216
|
+
|
|
217
|
+
const result = await findWorldsForOwner(mockRuntime, '');
|
|
218
|
+
|
|
219
|
+
expect(result).toBeNull();
|
|
220
|
+
expect(logger.error).toHaveBeenCalledWith('User ID is required to find server');
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('should return null when entityId is null', async () => {
|
|
224
|
+
const { logger } = await import('../logger');
|
|
225
|
+
|
|
226
|
+
const result = await findWorldsForOwner(mockRuntime, null as any);
|
|
227
|
+
|
|
228
|
+
expect(result).toBeNull();
|
|
229
|
+
expect(logger.error).toHaveBeenCalledWith('User ID is required to find server');
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should return null when no worlds exist', async () => {
|
|
233
|
+
const { logger } = await import('../logger');
|
|
234
|
+
|
|
235
|
+
(mockRuntime.getAllWorlds as any).mockResolvedValue([]);
|
|
236
|
+
|
|
237
|
+
const result = await findWorldsForOwner(mockRuntime, 'user-123');
|
|
238
|
+
|
|
239
|
+
expect(result).toBeNull();
|
|
240
|
+
expect(logger.info).toHaveBeenCalledWith('No worlds found for this agent');
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should return null when getAllWorlds returns null', async () => {
|
|
244
|
+
const { logger } = await import('../logger');
|
|
245
|
+
|
|
246
|
+
(mockRuntime.getAllWorlds as any).mockResolvedValue(null);
|
|
247
|
+
|
|
248
|
+
const result = await findWorldsForOwner(mockRuntime, 'user-123');
|
|
249
|
+
|
|
250
|
+
expect(result).toBeNull();
|
|
251
|
+
expect(logger.info).toHaveBeenCalledWith('No worlds found for this agent');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should return null when no worlds match the owner', async () => {
|
|
255
|
+
const mockWorlds: World[] = [
|
|
256
|
+
{
|
|
257
|
+
id: 'world-1' as UUID,
|
|
258
|
+
name: 'World 1',
|
|
259
|
+
agentId: 'agent-123' as UUID,
|
|
260
|
+
serverId: 'server-1',
|
|
261
|
+
metadata: {
|
|
262
|
+
ownership: {
|
|
263
|
+
ownerId: 'other-user-1',
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
id: 'world-2' as UUID,
|
|
269
|
+
name: 'World 2',
|
|
270
|
+
agentId: 'agent-123' as UUID,
|
|
271
|
+
serverId: 'server-2',
|
|
272
|
+
metadata: {
|
|
273
|
+
ownership: {
|
|
274
|
+
ownerId: 'other-user-2',
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
];
|
|
279
|
+
|
|
280
|
+
(mockRuntime.getAllWorlds as any).mockResolvedValue(mockWorlds);
|
|
281
|
+
|
|
282
|
+
const result = await findWorldsForOwner(mockRuntime, 'user-123');
|
|
283
|
+
|
|
284
|
+
expect(result).toBeNull();
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('should handle worlds without metadata', async () => {
|
|
288
|
+
const mockWorlds: World[] = [
|
|
289
|
+
{
|
|
290
|
+
id: 'world-1' as UUID,
|
|
291
|
+
name: 'World 1',
|
|
292
|
+
agentId: 'agent-123' as UUID,
|
|
293
|
+
serverId: 'server-1',
|
|
294
|
+
metadata: {},
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
id: 'world-2' as UUID,
|
|
298
|
+
name: 'World 2',
|
|
299
|
+
agentId: 'agent-123' as UUID,
|
|
300
|
+
serverId: 'server-2',
|
|
301
|
+
} as World,
|
|
302
|
+
];
|
|
303
|
+
|
|
304
|
+
(mockRuntime.getAllWorlds as any).mockResolvedValue(mockWorlds);
|
|
305
|
+
|
|
306
|
+
const result = await findWorldsForOwner(mockRuntime, 'user-123');
|
|
307
|
+
|
|
308
|
+
expect(result).toBeNull();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('should handle worlds without ownership in metadata', async () => {
|
|
312
|
+
const mockWorlds: World[] = [
|
|
313
|
+
{
|
|
314
|
+
id: 'world-1' as UUID,
|
|
315
|
+
name: 'World 1',
|
|
316
|
+
agentId: 'agent-123' as UUID,
|
|
317
|
+
serverId: 'server-1',
|
|
318
|
+
metadata: {
|
|
319
|
+
someOtherData: 'value',
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
];
|
|
323
|
+
|
|
324
|
+
(mockRuntime.getAllWorlds as any).mockResolvedValue(mockWorlds);
|
|
325
|
+
|
|
326
|
+
const result = await findWorldsForOwner(mockRuntime, 'user-123');
|
|
327
|
+
|
|
328
|
+
expect(result).toBeNull();
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
});
|