@elizaos/core 1.5.4 → 1.5.5
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 +0 -15
- package/dist/index.d.ts +4886 -3
- package/dist/index.js +5287 -4
- package/package.json +21 -39
- package/dist/browser/index.browser.js +0 -1109
- package/dist/browser/index.browser.js.map +0 -707
- package/dist/browser/index.d.ts +0 -3
- package/dist/node/index.d.ts +0 -3
- package/dist/node/index.node.js +0 -74530
- package/dist/node/index.node.js.map +0 -1027
- package/src/__tests__/action-chaining-simple.test.ts +0 -203
- package/src/__tests__/actions.test.ts +0 -218
- package/src/__tests__/buffer.test.ts +0 -337
- package/src/__tests__/character-validation.test.ts +0 -309
- package/src/__tests__/database.test.ts +0 -750
- package/src/__tests__/entities.test.ts +0 -727
- package/src/__tests__/env.test.ts +0 -23
- package/src/__tests__/environment.test.ts +0 -285
- package/src/__tests__/logger-browser-node.test.ts +0 -716
- package/src/__tests__/logger.test.ts +0 -403
- package/src/__tests__/messages.test.ts +0 -196
- package/src/__tests__/mockCharacter.ts +0 -544
- package/src/__tests__/parsing.test.ts +0 -58
- package/src/__tests__/prompts.test.ts +0 -159
- package/src/__tests__/roles.test.ts +0 -331
- package/src/__tests__/runtime-embedding.test.ts +0 -343
- package/src/__tests__/runtime.test.ts +0 -978
- package/src/__tests__/search.test.ts +0 -15
- package/src/__tests__/services-by-type.test.ts +0 -204
- package/src/__tests__/services.test.ts +0 -136
- package/src/__tests__/settings.test.ts +0 -810
- package/src/__tests__/utils.test.ts +0 -1105
- package/src/__tests__/uuid.test.ts +0 -94
- package/src/actions.ts +0 -122
- package/src/database.ts +0 -579
- package/src/entities.ts +0 -406
- package/src/index.browser.ts +0 -48
- package/src/index.node.ts +0 -39
- package/src/index.ts +0 -50
- package/src/logger.ts +0 -527
- package/src/prompts.ts +0 -243
- package/src/roles.ts +0 -85
- package/src/runtime.ts +0 -2514
- package/src/schemas/character.ts +0 -149
- package/src/search.ts +0 -1543
- package/src/sentry/instrument.browser.ts +0 -65
- package/src/sentry/instrument.node.ts +0 -57
- package/src/sentry/instrument.ts +0 -82
- package/src/services.ts +0 -105
- package/src/settings.ts +0 -409
- package/src/test_resources/constants.ts +0 -12
- package/src/test_resources/testSetup.ts +0 -21
- package/src/test_resources/types.ts +0 -22
- package/src/types/agent.ts +0 -112
- package/src/types/browser.ts +0 -145
- package/src/types/components.ts +0 -184
- package/src/types/database.ts +0 -348
- package/src/types/email.ts +0 -162
- package/src/types/environment.ts +0 -129
- package/src/types/events.ts +0 -249
- package/src/types/index.ts +0 -29
- package/src/types/knowledge.ts +0 -65
- package/src/types/lp.ts +0 -124
- package/src/types/memory.ts +0 -228
- package/src/types/message.ts +0 -233
- package/src/types/messaging.ts +0 -57
- package/src/types/model.ts +0 -359
- package/src/types/pdf.ts +0 -77
- package/src/types/plugin.ts +0 -78
- package/src/types/post.ts +0 -271
- package/src/types/primitives.ts +0 -97
- package/src/types/runtime.ts +0 -190
- package/src/types/service.ts +0 -198
- package/src/types/settings.ts +0 -30
- package/src/types/state.ts +0 -60
- package/src/types/task.ts +0 -72
- package/src/types/tee.ts +0 -107
- package/src/types/testing.ts +0 -30
- package/src/types/token.ts +0 -96
- package/src/types/transcription.ts +0 -133
- package/src/types/video.ts +0 -108
- package/src/types/wallet.ts +0 -56
- package/src/types/web-search.ts +0 -146
- package/src/utils/__tests__/buffer.test.ts +0 -80
- package/src/utils/__tests__/environment.test.ts +0 -58
- package/src/utils/__tests__/stringToUuid.test.ts +0 -88
- package/src/utils/buffer.ts +0 -312
- package/src/utils/environment.ts +0 -316
- package/src/utils/server-health.ts +0 -117
- package/src/utils.ts +0 -1076
|
@@ -1,727 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'bun:test';
|
|
2
|
-
import { mock, spyOn } from 'bun:test';
|
|
3
|
-
import { findEntityByName, createUniqueUuid, getEntityDetails, formatEntities } from '../entities';
|
|
4
|
-
import type { IAgentRuntime } from '../types/runtime';
|
|
5
|
-
import type { Entity, UUID, Memory, State } from '../types';
|
|
6
|
-
import * as utils from '../utils';
|
|
7
|
-
import * as index from '../index';
|
|
8
|
-
import * as logger_module from '../logger';
|
|
9
|
-
|
|
10
|
-
describe('entities', () => {
|
|
11
|
-
let mockRuntime: IAgentRuntime;
|
|
12
|
-
let mockMemory: Memory;
|
|
13
|
-
let mockState: State;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
mock.restore();
|
|
17
|
-
|
|
18
|
-
// Mock logger methods to prevent undefined function errors
|
|
19
|
-
// Mock both the index-exported logger and direct logger module
|
|
20
|
-
const loggerInstances = [index.logger, logger_module.logger].filter(Boolean);
|
|
21
|
-
|
|
22
|
-
loggerInstances.forEach((loggerInstance) => {
|
|
23
|
-
if (loggerInstance) {
|
|
24
|
-
// Always ensure these methods exist and are mocked
|
|
25
|
-
const methods = ['warn', 'error', 'info', 'debug'];
|
|
26
|
-
methods.forEach((method) => {
|
|
27
|
-
if (typeof loggerInstance[method] === 'function') {
|
|
28
|
-
spyOn(loggerInstance, method).mockImplementation(() => {});
|
|
29
|
-
} else {
|
|
30
|
-
loggerInstance[method] = mock(() => {});
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// Create a comprehensive mock runtime
|
|
37
|
-
mockRuntime = {
|
|
38
|
-
agentId: 'agent-id-123' as UUID,
|
|
39
|
-
character: {
|
|
40
|
-
id: 'agent-id-123' as UUID,
|
|
41
|
-
name: 'TestAgent',
|
|
42
|
-
},
|
|
43
|
-
getRoom: mock(),
|
|
44
|
-
getWorld: mock(),
|
|
45
|
-
getEntitiesForRoom: mock(),
|
|
46
|
-
getRelationships: mock(),
|
|
47
|
-
getEntityById: mock(),
|
|
48
|
-
useModel: mock(),
|
|
49
|
-
getMemories: mock(),
|
|
50
|
-
} as unknown as IAgentRuntime;
|
|
51
|
-
|
|
52
|
-
// Create mock memory
|
|
53
|
-
mockMemory = {
|
|
54
|
-
id: 'memory-123' as UUID,
|
|
55
|
-
entityId: 'entity-456' as UUID,
|
|
56
|
-
roomId: 'room-789' as UUID,
|
|
57
|
-
content: {},
|
|
58
|
-
} as Memory;
|
|
59
|
-
|
|
60
|
-
// Create mock state
|
|
61
|
-
mockState = {
|
|
62
|
-
data: {
|
|
63
|
-
room: null,
|
|
64
|
-
},
|
|
65
|
-
values: {},
|
|
66
|
-
text: '',
|
|
67
|
-
};
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('findEntityByName', () => {
|
|
71
|
-
it('should find entity by exact name match', async () => {
|
|
72
|
-
const mockRoom = {
|
|
73
|
-
id: 'room-789' as UUID,
|
|
74
|
-
name: 'Test Room',
|
|
75
|
-
worldId: 'world-123' as UUID,
|
|
76
|
-
createdAt: Date.now(),
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const mockWorld = {
|
|
80
|
-
id: 'world-123' as UUID,
|
|
81
|
-
name: 'Test World',
|
|
82
|
-
agentId: 'agent-id-123' as UUID,
|
|
83
|
-
serverId: 'server-123' as UUID,
|
|
84
|
-
metadata: {
|
|
85
|
-
roles: {},
|
|
86
|
-
},
|
|
87
|
-
createdAt: Date.now(),
|
|
88
|
-
entities: [],
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const mockEntity: Entity = {
|
|
92
|
-
id: 'entity-123' as UUID,
|
|
93
|
-
names: ['Alice', 'Alice Smith'],
|
|
94
|
-
agentId: 'agent-id-123' as UUID,
|
|
95
|
-
metadata: {},
|
|
96
|
-
components: [],
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
mockRuntime.getRoom = mock().mockResolvedValue(mockRoom);
|
|
100
|
-
mockRuntime.getWorld = mock().mockResolvedValue(mockWorld);
|
|
101
|
-
mockRuntime.getEntitiesForRoom = mock().mockResolvedValue([mockEntity]);
|
|
102
|
-
mockRuntime.getRelationships = mock().mockResolvedValue([]);
|
|
103
|
-
mockRuntime.getMemories = mock().mockResolvedValue([]);
|
|
104
|
-
mockRuntime.useModel = mock().mockResolvedValue('mocked model response');
|
|
105
|
-
mockRuntime.getEntityById = mock().mockResolvedValue(mockEntity);
|
|
106
|
-
|
|
107
|
-
// Mock the parseKeyValueXml to return the expected resolution
|
|
108
|
-
const parseXmlSpy = spyOn(utils, 'parseKeyValueXml');
|
|
109
|
-
parseXmlSpy.mockReturnValue({
|
|
110
|
-
type: 'EXACT_MATCH',
|
|
111
|
-
entityId: 'entity-123',
|
|
112
|
-
matches: {
|
|
113
|
-
match: [{ name: 'Alice', reason: 'Exact match found' }],
|
|
114
|
-
},
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
const result = await findEntityByName(mockRuntime, mockMemory, mockState);
|
|
118
|
-
|
|
119
|
-
expect(result).toEqual(mockEntity);
|
|
120
|
-
expect(mockRuntime.getRoom).toHaveBeenCalledWith('room-789');
|
|
121
|
-
expect(mockRuntime.getEntitiesForRoom).toHaveBeenCalledWith('room-789', true);
|
|
122
|
-
parseXmlSpy.mockRestore();
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should return null when room not found', async () => {
|
|
126
|
-
mockRuntime.getRoom = mock().mockResolvedValue(null);
|
|
127
|
-
|
|
128
|
-
const result = await findEntityByName(mockRuntime, mockMemory, mockState);
|
|
129
|
-
|
|
130
|
-
expect(result).toBeNull();
|
|
131
|
-
expect(mockRuntime.getEntitiesForRoom).not.toHaveBeenCalled();
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it('should filter components based on permissions', async () => {
|
|
135
|
-
const mockRoom = {
|
|
136
|
-
id: 'room-789' as UUID,
|
|
137
|
-
worldId: 'world-123' as UUID,
|
|
138
|
-
createdAt: Date.now(),
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const mockWorld = {
|
|
142
|
-
id: 'world-123' as UUID,
|
|
143
|
-
name: 'Test World',
|
|
144
|
-
agentId: 'agent-id-123' as UUID,
|
|
145
|
-
serverId: 'server-123' as UUID,
|
|
146
|
-
metadata: {
|
|
147
|
-
roles: {
|
|
148
|
-
'admin-entity': 'ADMIN',
|
|
149
|
-
'owner-entity': 'OWNER',
|
|
150
|
-
},
|
|
151
|
-
},
|
|
152
|
-
createdAt: Date.now(),
|
|
153
|
-
entities: [],
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const mockEntity: Entity = {
|
|
157
|
-
id: 'entity-123' as UUID,
|
|
158
|
-
names: ['Alice'],
|
|
159
|
-
agentId: 'agent-id-123' as UUID,
|
|
160
|
-
components: [
|
|
161
|
-
{
|
|
162
|
-
id: 'comp-1' as UUID,
|
|
163
|
-
entityId: 'entity-123' as UUID,
|
|
164
|
-
agentId: 'agent-id-123' as UUID,
|
|
165
|
-
roomId: 'room-789' as UUID,
|
|
166
|
-
worldId: 'world-123' as UUID,
|
|
167
|
-
sourceEntityId: 'entity-456' as UUID, // Should pass - message sender
|
|
168
|
-
type: 'PROFILE',
|
|
169
|
-
createdAt: Date.now(),
|
|
170
|
-
data: {},
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
id: 'comp-2' as UUID,
|
|
174
|
-
entityId: 'entity-123' as UUID,
|
|
175
|
-
agentId: 'agent-id-123' as UUID,
|
|
176
|
-
roomId: 'room-789' as UUID,
|
|
177
|
-
worldId: 'world-123' as UUID,
|
|
178
|
-
sourceEntityId: 'admin-entity' as UUID, // Should pass - admin
|
|
179
|
-
type: 'PROFILE',
|
|
180
|
-
createdAt: Date.now(),
|
|
181
|
-
data: {},
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
id: 'comp-3' as UUID,
|
|
185
|
-
entityId: 'entity-123' as UUID,
|
|
186
|
-
agentId: 'agent-id-123' as UUID,
|
|
187
|
-
roomId: 'room-789' as UUID,
|
|
188
|
-
worldId: 'world-123' as UUID,
|
|
189
|
-
sourceEntityId: 'random-entity' as UUID, // Should be filtered out
|
|
190
|
-
type: 'PROFILE',
|
|
191
|
-
createdAt: Date.now(),
|
|
192
|
-
data: {},
|
|
193
|
-
},
|
|
194
|
-
],
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
mockRuntime.getRoom = mock().mockResolvedValue(mockRoom);
|
|
198
|
-
mockRuntime.getWorld = mock().mockResolvedValue(mockWorld);
|
|
199
|
-
mockRuntime.getEntitiesForRoom = mock().mockResolvedValue([mockEntity]);
|
|
200
|
-
mockRuntime.getRelationships = mock().mockResolvedValue([]);
|
|
201
|
-
mockRuntime.getMemories = mock().mockResolvedValue([]);
|
|
202
|
-
mockRuntime.useModel = mock().mockResolvedValue(
|
|
203
|
-
JSON.stringify({
|
|
204
|
-
type: 'EXACT_MATCH',
|
|
205
|
-
entityId: 'entity-123',
|
|
206
|
-
})
|
|
207
|
-
);
|
|
208
|
-
mockRuntime.getEntityById = mock().mockResolvedValue(mockEntity);
|
|
209
|
-
|
|
210
|
-
await findEntityByName(mockRuntime, mockMemory, mockState);
|
|
211
|
-
|
|
212
|
-
// The mock setup should have filtered components, but since we're mocking
|
|
213
|
-
// the entire flow, we need to verify the logic would work correctly
|
|
214
|
-
expect(mockRuntime.getWorld).toHaveBeenCalledWith('world-123');
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it('should handle LLM parse failure gracefully', async () => {
|
|
218
|
-
const mockRoom = {
|
|
219
|
-
id: 'room-789' as UUID,
|
|
220
|
-
createdAt: Date.now(),
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
mockRuntime.getRoom = mock().mockResolvedValue(mockRoom);
|
|
224
|
-
mockRuntime.getWorld = mock().mockResolvedValue(null);
|
|
225
|
-
mockRuntime.getEntitiesForRoom = mock().mockResolvedValue([]);
|
|
226
|
-
mockRuntime.getRelationships = mock().mockResolvedValue([]);
|
|
227
|
-
mockRuntime.getMemories = mock().mockResolvedValue([]);
|
|
228
|
-
mockRuntime.useModel = mock().mockResolvedValue('invalid json');
|
|
229
|
-
|
|
230
|
-
const result = await findEntityByName(mockRuntime, mockMemory, mockState);
|
|
231
|
-
|
|
232
|
-
expect(result).toBeNull();
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it('should handle EXACT_MATCH with entity components filtering', async () => {
|
|
236
|
-
const mockRoom = {
|
|
237
|
-
id: 'room-789' as UUID,
|
|
238
|
-
worldId: 'world-123' as UUID,
|
|
239
|
-
createdAt: Date.now(),
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const mockWorld = {
|
|
243
|
-
id: 'world-123' as UUID,
|
|
244
|
-
name: 'Test World',
|
|
245
|
-
agentId: 'agent-id-123' as UUID,
|
|
246
|
-
serverId: 'server-123' as UUID,
|
|
247
|
-
metadata: {
|
|
248
|
-
roles: {
|
|
249
|
-
'admin-entity': 'ADMIN',
|
|
250
|
-
'owner-entity': 'OWNER',
|
|
251
|
-
'regular-entity': 'MEMBER',
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
createdAt: Date.now(),
|
|
255
|
-
entities: [],
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
const mockEntityWithComponents: Entity = {
|
|
259
|
-
id: 'entity-exact' as UUID,
|
|
260
|
-
names: ['ExactMatch'],
|
|
261
|
-
agentId: 'agent-id-123' as UUID,
|
|
262
|
-
metadata: {},
|
|
263
|
-
components: [
|
|
264
|
-
{
|
|
265
|
-
id: 'comp-1' as UUID,
|
|
266
|
-
entityId: 'entity-exact' as UUID,
|
|
267
|
-
agentId: 'agent-id-123' as UUID,
|
|
268
|
-
roomId: 'room-789' as UUID,
|
|
269
|
-
worldId: 'world-123' as UUID,
|
|
270
|
-
sourceEntityId: 'entity-456' as UUID, // Same as message sender
|
|
271
|
-
type: 'PROFILE',
|
|
272
|
-
createdAt: Date.now(),
|
|
273
|
-
data: { bio: 'User profile' },
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
id: 'comp-2' as UUID,
|
|
277
|
-
entityId: 'entity-exact' as UUID,
|
|
278
|
-
agentId: 'agent-id-123' as UUID,
|
|
279
|
-
roomId: 'room-789' as UUID,
|
|
280
|
-
worldId: 'world-123' as UUID,
|
|
281
|
-
sourceEntityId: 'admin-entity' as UUID, // Admin role
|
|
282
|
-
type: 'SETTINGS',
|
|
283
|
-
createdAt: Date.now(),
|
|
284
|
-
data: { settings: 'admin settings' },
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
id: 'comp-3' as UUID,
|
|
288
|
-
entityId: 'entity-exact' as UUID,
|
|
289
|
-
agentId: 'agent-id-123' as UUID,
|
|
290
|
-
roomId: 'room-789' as UUID,
|
|
291
|
-
worldId: 'world-123' as UUID,
|
|
292
|
-
sourceEntityId: 'random-entity' as UUID, // Should be filtered out
|
|
293
|
-
type: 'PRIVATE',
|
|
294
|
-
createdAt: Date.now(),
|
|
295
|
-
data: { private: 'data' },
|
|
296
|
-
},
|
|
297
|
-
],
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
mockRuntime.getRoom = mock().mockResolvedValue(mockRoom);
|
|
301
|
-
mockRuntime.getWorld = mock().mockResolvedValue(mockWorld);
|
|
302
|
-
mockRuntime.getEntitiesForRoom = mock().mockResolvedValue([mockEntityWithComponents]);
|
|
303
|
-
mockRuntime.getRelationships = mock().mockResolvedValue([]);
|
|
304
|
-
mockRuntime.getMemories = mock().mockResolvedValue([]);
|
|
305
|
-
mockRuntime.useModel = mock().mockResolvedValue(
|
|
306
|
-
JSON.stringify({
|
|
307
|
-
entityId: 'entity-exact',
|
|
308
|
-
type: 'EXACT_MATCH',
|
|
309
|
-
matches: [{ name: 'ExactMatch', reason: 'Exact ID match' }],
|
|
310
|
-
})
|
|
311
|
-
);
|
|
312
|
-
mockRuntime.getEntityById = mock().mockResolvedValue(mockEntityWithComponents);
|
|
313
|
-
|
|
314
|
-
// Mock parseKeyValueXml to return proper resolution
|
|
315
|
-
const parseXmlSpy = spyOn(utils, 'parseKeyValueXml');
|
|
316
|
-
parseXmlSpy.mockReturnValue({
|
|
317
|
-
entityId: 'entity-exact',
|
|
318
|
-
type: 'EXACT_MATCH',
|
|
319
|
-
matches: {
|
|
320
|
-
match: [{ name: 'ExactMatch', reason: 'Exact ID match' }],
|
|
321
|
-
},
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
const result = await findEntityByName(mockRuntime, mockMemory, mockState);
|
|
325
|
-
|
|
326
|
-
expect(result).toBeDefined();
|
|
327
|
-
expect(result?.id).toBe('entity-exact' as UUID);
|
|
328
|
-
// Verify getEntityById was called (covers lines 274-282)
|
|
329
|
-
expect(mockRuntime.getEntityById).toHaveBeenCalledWith('entity-exact');
|
|
330
|
-
parseXmlSpy.mockRestore();
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
it('should find entity by username in components', async () => {
|
|
334
|
-
const mockRoom = {
|
|
335
|
-
id: 'room-789' as UUID,
|
|
336
|
-
worldId: null,
|
|
337
|
-
createdAt: Date.now(),
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
const mockEntity: Entity = {
|
|
341
|
-
id: 'entity-user' as UUID,
|
|
342
|
-
names: ['John Doe'],
|
|
343
|
-
agentId: 'agent-id-123' as UUID,
|
|
344
|
-
metadata: {},
|
|
345
|
-
components: [
|
|
346
|
-
{
|
|
347
|
-
id: 'comp-1' as UUID,
|
|
348
|
-
entityId: 'entity-user' as UUID,
|
|
349
|
-
agentId: 'agent-id-123' as UUID,
|
|
350
|
-
roomId: 'room-789' as UUID,
|
|
351
|
-
worldId: null as any,
|
|
352
|
-
sourceEntityId: 'entity-456' as UUID,
|
|
353
|
-
type: 'PROFILE',
|
|
354
|
-
createdAt: Date.now(),
|
|
355
|
-
data: { username: 'johndoe123' },
|
|
356
|
-
},
|
|
357
|
-
],
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
mockRuntime.getRoom = mock().mockResolvedValue(mockRoom);
|
|
361
|
-
mockRuntime.getWorld = mock().mockResolvedValue(null);
|
|
362
|
-
mockRuntime.getEntitiesForRoom = mock().mockResolvedValue([mockEntity]);
|
|
363
|
-
mockRuntime.getRelationships = mock().mockResolvedValue([]);
|
|
364
|
-
mockRuntime.getMemories = mock().mockResolvedValue([]);
|
|
365
|
-
mockRuntime.useModel = mock().mockResolvedValue(
|
|
366
|
-
JSON.stringify({
|
|
367
|
-
type: 'USERNAME_MATCH',
|
|
368
|
-
matches: [{ name: 'johndoe123', reason: 'Username match' }],
|
|
369
|
-
})
|
|
370
|
-
);
|
|
371
|
-
|
|
372
|
-
// Mock parseKeyValueXml
|
|
373
|
-
const parseXmlSpy = spyOn(utils, 'parseKeyValueXml');
|
|
374
|
-
parseXmlSpy.mockReturnValue({
|
|
375
|
-
type: 'USERNAME_MATCH',
|
|
376
|
-
matches: {
|
|
377
|
-
match: [{ name: 'johndoe123', reason: 'Username match' }],
|
|
378
|
-
},
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
const result = await findEntityByName(mockRuntime, mockMemory, mockState);
|
|
382
|
-
|
|
383
|
-
expect(result).toBeDefined();
|
|
384
|
-
expect(result?.id).toBe('entity-user' as UUID);
|
|
385
|
-
parseXmlSpy.mockRestore();
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
it('should find entity by handle in components', async () => {
|
|
389
|
-
const mockRoom = {
|
|
390
|
-
id: 'room-789' as UUID,
|
|
391
|
-
worldId: null,
|
|
392
|
-
createdAt: Date.now(),
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
const mockEntity: Entity = {
|
|
396
|
-
id: 'entity-handle' as UUID,
|
|
397
|
-
names: ['Jane Smith'],
|
|
398
|
-
agentId: 'agent-id-123' as UUID,
|
|
399
|
-
metadata: {},
|
|
400
|
-
components: [
|
|
401
|
-
{
|
|
402
|
-
id: 'comp-1' as UUID,
|
|
403
|
-
entityId: 'entity-handle' as UUID,
|
|
404
|
-
agentId: 'agent-id-123' as UUID,
|
|
405
|
-
roomId: 'room-789' as UUID,
|
|
406
|
-
worldId: null as any,
|
|
407
|
-
sourceEntityId: 'entity-456' as UUID,
|
|
408
|
-
type: 'PROFILE',
|
|
409
|
-
createdAt: Date.now(),
|
|
410
|
-
data: { handle: '@janesmith' },
|
|
411
|
-
},
|
|
412
|
-
],
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
mockRuntime.getRoom = mock().mockResolvedValue(mockRoom);
|
|
416
|
-
mockRuntime.getWorld = mock().mockResolvedValue(null);
|
|
417
|
-
mockRuntime.getEntitiesForRoom = mock().mockResolvedValue([mockEntity]);
|
|
418
|
-
mockRuntime.getRelationships = mock().mockResolvedValue([]);
|
|
419
|
-
mockRuntime.getMemories = mock().mockResolvedValue([]);
|
|
420
|
-
mockRuntime.useModel = mock().mockResolvedValue(
|
|
421
|
-
JSON.stringify({
|
|
422
|
-
type: 'USERNAME_MATCH',
|
|
423
|
-
matches: [{ name: '@janesmith', reason: 'Handle match' }],
|
|
424
|
-
})
|
|
425
|
-
);
|
|
426
|
-
|
|
427
|
-
// Mock parseKeyValueXml
|
|
428
|
-
const parseXmlSpy = spyOn(utils, 'parseKeyValueXml');
|
|
429
|
-
parseXmlSpy.mockReturnValue({
|
|
430
|
-
type: 'USERNAME_MATCH',
|
|
431
|
-
matches: {
|
|
432
|
-
match: [{ name: '@janesmith', reason: 'Handle match' }],
|
|
433
|
-
},
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
const result = await findEntityByName(mockRuntime, mockMemory, mockState);
|
|
437
|
-
|
|
438
|
-
expect(result).toBeDefined();
|
|
439
|
-
expect(result?.id).toBe('entity-handle' as UUID);
|
|
440
|
-
parseXmlSpy.mockRestore();
|
|
441
|
-
});
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
describe('createUniqueUuid', () => {
|
|
445
|
-
it('should return agent ID when base user ID matches agent ID', () => {
|
|
446
|
-
const result = createUniqueUuid(mockRuntime, 'agent-id-123');
|
|
447
|
-
expect(result).toBe('agent-id-123' as UUID);
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
it('should create UUID from combined string for different IDs', () => {
|
|
451
|
-
const stringToUuidSpy = spyOn(index, 'stringToUuid');
|
|
452
|
-
stringToUuidSpy.mockReturnValue('unique-uuid-123' as UUID);
|
|
453
|
-
|
|
454
|
-
const result = createUniqueUuid(mockRuntime, 'user-456');
|
|
455
|
-
|
|
456
|
-
expect(result).toBe('unique-uuid-123' as UUID);
|
|
457
|
-
expect(stringToUuidSpy).toHaveBeenCalledWith('user-456:agent-id-123');
|
|
458
|
-
stringToUuidSpy.mockRestore();
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
it('should handle UUID type as base user ID', () => {
|
|
462
|
-
const stringToUuidSpy = spyOn(index, 'stringToUuid');
|
|
463
|
-
stringToUuidSpy.mockReturnValue('unique-uuid-456' as UUID);
|
|
464
|
-
|
|
465
|
-
const result = createUniqueUuid(mockRuntime, 'user-789' as UUID);
|
|
466
|
-
|
|
467
|
-
expect(result).toBe('unique-uuid-456' as UUID);
|
|
468
|
-
expect(stringToUuidSpy).toHaveBeenCalledWith('user-789:agent-id-123');
|
|
469
|
-
stringToUuidSpy.mockRestore();
|
|
470
|
-
});
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
describe('getEntityDetails', () => {
|
|
474
|
-
it('should retrieve and format entity details for a room', async () => {
|
|
475
|
-
const mockRoom = {
|
|
476
|
-
id: 'room-123' as UUID,
|
|
477
|
-
source: 'discord',
|
|
478
|
-
createdAt: Date.now(),
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
const mockEntities: Entity[] = [
|
|
482
|
-
{
|
|
483
|
-
id: 'entity-1' as UUID,
|
|
484
|
-
names: ['Alice', 'Alice Smith'],
|
|
485
|
-
agentId: 'agent-id-123' as UUID,
|
|
486
|
-
metadata: {
|
|
487
|
-
bio: 'Test bio',
|
|
488
|
-
discord: { name: 'Alice#1234' },
|
|
489
|
-
},
|
|
490
|
-
components: [
|
|
491
|
-
{
|
|
492
|
-
id: 'comp-1' as UUID,
|
|
493
|
-
entityId: 'entity-1' as UUID,
|
|
494
|
-
agentId: 'agent-id-123' as UUID,
|
|
495
|
-
roomId: 'room-123' as UUID,
|
|
496
|
-
worldId: 'world-123' as UUID,
|
|
497
|
-
sourceEntityId: 'source-123' as UUID,
|
|
498
|
-
type: 'PROFILE',
|
|
499
|
-
createdAt: Date.now(),
|
|
500
|
-
data: { avatar: 'avatar.jpg' },
|
|
501
|
-
},
|
|
502
|
-
{
|
|
503
|
-
id: 'comp-2' as UUID,
|
|
504
|
-
entityId: 'entity-1' as UUID,
|
|
505
|
-
agentId: 'agent-id-123' as UUID,
|
|
506
|
-
roomId: 'room-123' as UUID,
|
|
507
|
-
worldId: 'world-123' as UUID,
|
|
508
|
-
sourceEntityId: 'source-123' as UUID,
|
|
509
|
-
type: 'SETTINGS',
|
|
510
|
-
createdAt: Date.now(),
|
|
511
|
-
data: { theme: 'dark' },
|
|
512
|
-
},
|
|
513
|
-
],
|
|
514
|
-
},
|
|
515
|
-
{
|
|
516
|
-
id: 'entity-2' as UUID,
|
|
517
|
-
names: ['Bob'],
|
|
518
|
-
agentId: 'agent-id-123' as UUID,
|
|
519
|
-
metadata: {},
|
|
520
|
-
components: [],
|
|
521
|
-
},
|
|
522
|
-
];
|
|
523
|
-
|
|
524
|
-
mockRuntime.getRoom = mock().mockResolvedValue(mockRoom);
|
|
525
|
-
mockRuntime.getEntitiesForRoom = mock().mockResolvedValue(mockEntities);
|
|
526
|
-
|
|
527
|
-
const result = await getEntityDetails({
|
|
528
|
-
runtime: mockRuntime,
|
|
529
|
-
roomId: 'room-123' as UUID,
|
|
530
|
-
});
|
|
531
|
-
|
|
532
|
-
expect(result).toHaveLength(2);
|
|
533
|
-
expect(result[0]).toEqual({
|
|
534
|
-
id: 'entity-1',
|
|
535
|
-
name: 'Alice#1234', // Uses discord name from metadata
|
|
536
|
-
names: ['Alice', 'Alice Smith'],
|
|
537
|
-
data: expect.stringContaining('avatar'),
|
|
538
|
-
});
|
|
539
|
-
expect(result[1]).toEqual({
|
|
540
|
-
id: 'entity-2',
|
|
541
|
-
name: 'Bob',
|
|
542
|
-
names: ['Bob'],
|
|
543
|
-
data: '{}',
|
|
544
|
-
});
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
it('should handle deduplication of entities', async () => {
|
|
548
|
-
const mockRoom = {
|
|
549
|
-
id: 'room-123' as UUID,
|
|
550
|
-
createdAt: Date.now(),
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
const duplicateEntity = {
|
|
554
|
-
id: 'entity-1' as UUID,
|
|
555
|
-
names: ['Alice'],
|
|
556
|
-
agentId: 'agent-id-123' as UUID,
|
|
557
|
-
metadata: {},
|
|
558
|
-
components: [],
|
|
559
|
-
};
|
|
560
|
-
|
|
561
|
-
mockRuntime.getRoom = mock().mockResolvedValue(mockRoom);
|
|
562
|
-
mockRuntime.getEntitiesForRoom = mock().mockResolvedValue([
|
|
563
|
-
duplicateEntity,
|
|
564
|
-
duplicateEntity, // Duplicate
|
|
565
|
-
]);
|
|
566
|
-
|
|
567
|
-
const result = await getEntityDetails({
|
|
568
|
-
runtime: mockRuntime,
|
|
569
|
-
roomId: 'room-123' as UUID,
|
|
570
|
-
});
|
|
571
|
-
|
|
572
|
-
expect(result).toHaveLength(1);
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
it('should merge array data in components', async () => {
|
|
576
|
-
const mockRoom = {
|
|
577
|
-
id: 'room-123' as UUID,
|
|
578
|
-
createdAt: Date.now(),
|
|
579
|
-
};
|
|
580
|
-
|
|
581
|
-
const mockEntity: Entity = {
|
|
582
|
-
id: 'entity-1' as UUID,
|
|
583
|
-
names: ['Charlie'],
|
|
584
|
-
agentId: 'agent-id-123' as UUID,
|
|
585
|
-
metadata: {},
|
|
586
|
-
components: [
|
|
587
|
-
{
|
|
588
|
-
id: 'comp-1' as UUID,
|
|
589
|
-
entityId: 'entity-1' as UUID,
|
|
590
|
-
agentId: 'agent-id-123' as UUID,
|
|
591
|
-
roomId: 'room-123' as UUID,
|
|
592
|
-
worldId: 'world-123' as UUID,
|
|
593
|
-
sourceEntityId: 'source-123' as UUID,
|
|
594
|
-
type: 'PROFILE',
|
|
595
|
-
createdAt: Date.now(),
|
|
596
|
-
data: { hobbies: ['reading', 'gaming'] },
|
|
597
|
-
},
|
|
598
|
-
{
|
|
599
|
-
id: 'comp-2' as UUID,
|
|
600
|
-
entityId: 'entity-1' as UUID,
|
|
601
|
-
agentId: 'agent-id-123' as UUID,
|
|
602
|
-
roomId: 'room-123' as UUID,
|
|
603
|
-
worldId: 'world-123' as UUID,
|
|
604
|
-
sourceEntityId: 'source-123' as UUID,
|
|
605
|
-
type: 'PROFILE',
|
|
606
|
-
createdAt: Date.now(),
|
|
607
|
-
data: { hobbies: ['gaming', 'music'] }, // Duplicate "gaming"
|
|
608
|
-
},
|
|
609
|
-
],
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
mockRuntime.getRoom = mock().mockResolvedValue(mockRoom);
|
|
613
|
-
mockRuntime.getEntitiesForRoom = mock().mockResolvedValue([mockEntity]);
|
|
614
|
-
|
|
615
|
-
const result = await getEntityDetails({
|
|
616
|
-
runtime: mockRuntime,
|
|
617
|
-
roomId: 'room-123' as UUID,
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
const parsedData = JSON.parse(result[0].data);
|
|
621
|
-
// Note: Due to how Object.assign works in the implementation,
|
|
622
|
-
// the second component's hobbies array overwrites the first one
|
|
623
|
-
expect(parsedData.hobbies).toEqual(['gaming', 'music']);
|
|
624
|
-
});
|
|
625
|
-
});
|
|
626
|
-
|
|
627
|
-
describe('formatEntities', () => {
|
|
628
|
-
it('should format single entity with basic info', () => {
|
|
629
|
-
const entities: Entity[] = [
|
|
630
|
-
{
|
|
631
|
-
id: 'entity-1' as UUID,
|
|
632
|
-
names: ['Alice'],
|
|
633
|
-
agentId: 'agent-id-123' as UUID,
|
|
634
|
-
metadata: { bio: 'Test bio' },
|
|
635
|
-
},
|
|
636
|
-
];
|
|
637
|
-
|
|
638
|
-
const result = formatEntities({ entities });
|
|
639
|
-
|
|
640
|
-
expect(result).toContain('"Alice"');
|
|
641
|
-
expect(result).toContain('ID: entity-1');
|
|
642
|
-
expect(result).toContain('Data: {"bio":"Test bio"}');
|
|
643
|
-
});
|
|
644
|
-
|
|
645
|
-
it('should format multiple entities', () => {
|
|
646
|
-
const entities: Entity[] = [
|
|
647
|
-
{
|
|
648
|
-
id: 'entity-1' as UUID,
|
|
649
|
-
names: ['Alice', 'Alice Smith'],
|
|
650
|
-
agentId: 'agent-id-123' as UUID,
|
|
651
|
-
metadata: { role: 'Developer' },
|
|
652
|
-
},
|
|
653
|
-
{
|
|
654
|
-
id: 'entity-2' as UUID,
|
|
655
|
-
names: ['Bob'],
|
|
656
|
-
agentId: 'agent-id-123' as UUID,
|
|
657
|
-
metadata: { role: 'Manager' },
|
|
658
|
-
},
|
|
659
|
-
];
|
|
660
|
-
|
|
661
|
-
const result = formatEntities({ entities });
|
|
662
|
-
|
|
663
|
-
expect(result).toContain('"Alice" aka "Alice Smith"');
|
|
664
|
-
expect(result).toContain('"Bob"');
|
|
665
|
-
expect(result).toContain('ID: entity-1');
|
|
666
|
-
expect(result).toContain('ID: entity-2');
|
|
667
|
-
expect(result).toContain('{"role":"Developer"}');
|
|
668
|
-
expect(result).toContain('{"role":"Manager"}');
|
|
669
|
-
});
|
|
670
|
-
|
|
671
|
-
it('should handle entities without metadata', () => {
|
|
672
|
-
const entities: Entity[] = [
|
|
673
|
-
{
|
|
674
|
-
id: 'entity-1' as UUID,
|
|
675
|
-
names: ['Charlie'],
|
|
676
|
-
agentId: 'agent-id-123' as UUID,
|
|
677
|
-
},
|
|
678
|
-
];
|
|
679
|
-
|
|
680
|
-
const result = formatEntities({ entities });
|
|
681
|
-
|
|
682
|
-
expect(result).toContain('"Charlie"');
|
|
683
|
-
expect(result).toContain('ID: entity-1');
|
|
684
|
-
expect(result).not.toContain('Data:');
|
|
685
|
-
});
|
|
686
|
-
|
|
687
|
-
it('should handle empty entities array', () => {
|
|
688
|
-
const result = formatEntities({ entities: [] });
|
|
689
|
-
expect(result).toBe('');
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
it('should handle entities with empty metadata', () => {
|
|
693
|
-
const entities: Entity[] = [
|
|
694
|
-
{
|
|
695
|
-
id: 'entity-1' as UUID,
|
|
696
|
-
names: ['David'],
|
|
697
|
-
agentId: 'agent-id-123' as UUID,
|
|
698
|
-
metadata: {},
|
|
699
|
-
},
|
|
700
|
-
];
|
|
701
|
-
|
|
702
|
-
const result = formatEntities({ entities });
|
|
703
|
-
|
|
704
|
-
expect(result).toContain('"David"');
|
|
705
|
-
expect(result).toContain('ID: entity-1');
|
|
706
|
-
expect(result).not.toContain('Data:');
|
|
707
|
-
});
|
|
708
|
-
});
|
|
709
|
-
|
|
710
|
-
it('createUniqueUuid combines user and agent ids', () => {
|
|
711
|
-
const runtime = { agentId: 'agent' } as any;
|
|
712
|
-
const id = createUniqueUuid(runtime, 'user');
|
|
713
|
-
const expected = index.stringToUuid('user:agent');
|
|
714
|
-
expect(id).toBe(expected);
|
|
715
|
-
});
|
|
716
|
-
|
|
717
|
-
it('formatEntities outputs joined string', () => {
|
|
718
|
-
const entities = [
|
|
719
|
-
{ id: '1', names: ['A'], metadata: {} },
|
|
720
|
-
{ id: '2', names: ['B'], metadata: { extra: true } },
|
|
721
|
-
] as any;
|
|
722
|
-
const text = formatEntities({ entities });
|
|
723
|
-
expect(text).toContain('"A"');
|
|
724
|
-
expect(text).toContain('ID: 1');
|
|
725
|
-
expect(text).toContain('ID: 2');
|
|
726
|
-
});
|
|
727
|
-
});
|