@elizaos/test-utils 1.2.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/index.js ADDED
@@ -0,0 +1,3013 @@
1
+ // src/realRuntime.ts
2
+ import { AgentRuntime, logger as logger3, stringToUuid } from "@elizaos/core";
3
+
4
+ // ../../node_modules/uuid/dist/esm/stringify.js
5
+ var byteToHex = [];
6
+ for (let i = 0; i < 256; ++i) {
7
+ byteToHex.push((i + 256).toString(16).slice(1));
8
+ }
9
+ function unsafeStringify(arr, offset = 0) {
10
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
11
+ }
12
+
13
+ // ../../node_modules/uuid/dist/esm/rng.js
14
+ import { randomFillSync } from "crypto";
15
+ var rnds8Pool = new Uint8Array(256);
16
+ var poolPtr = rnds8Pool.length;
17
+ function rng() {
18
+ if (poolPtr > rnds8Pool.length - 16) {
19
+ randomFillSync(rnds8Pool);
20
+ poolPtr = 0;
21
+ }
22
+ return rnds8Pool.slice(poolPtr, poolPtr += 16);
23
+ }
24
+
25
+ // ../../node_modules/uuid/dist/esm/native.js
26
+ import { randomUUID } from "crypto";
27
+ var native_default = { randomUUID };
28
+
29
+ // ../../node_modules/uuid/dist/esm/v4.js
30
+ function v4(options, buf, offset) {
31
+ if (native_default.randomUUID && !buf && !options) {
32
+ return native_default.randomUUID();
33
+ }
34
+ options = options || {};
35
+ const rnds = options.random ?? options.rng?.() ?? rng();
36
+ if (rnds.length < 16) {
37
+ throw new Error("Random bytes length must be >= 16");
38
+ }
39
+ rnds[6] = rnds[6] & 15 | 64;
40
+ rnds[8] = rnds[8] & 63 | 128;
41
+ if (buf) {
42
+ offset = offset || 0;
43
+ if (offset < 0 || offset + 16 > buf.length) {
44
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
45
+ }
46
+ for (let i = 0; i < 16; ++i) {
47
+ buf[offset + i] = rnds[i];
48
+ }
49
+ return buf;
50
+ }
51
+ return unsafeStringify(rnds);
52
+ }
53
+ var v4_default = v4;
54
+
55
+ // src/testDatabase.ts
56
+ import { logger } from "@elizaos/core";
57
+ var TestDatabaseManager = class {
58
+ testDatabases = /* @__PURE__ */ new Map();
59
+ tempPaths = /* @__PURE__ */ new Set();
60
+ /**
61
+ * Creates an isolated database for testing
62
+ * Uses PostgreSQL for testing when available, falls back to mock database
63
+ */
64
+ async createIsolatedDatabase(testId) {
65
+ try {
66
+ logger.debug(`Creating isolated test database for ${testId}`);
67
+ let adapter;
68
+ try {
69
+ logger.debug(`Attempting to load PostgreSQL adapter for ${testId}`);
70
+ if (process.env.FORCE_MOCK_DB === "true") {
71
+ logger.warn("FORCE_MOCK_DB is set - using mock database");
72
+ adapter = this.createMockDatabase(testId);
73
+ } else {
74
+ try {
75
+ const sqlPlugin = globalThis.__elizaOS_sqlPlugin;
76
+ if (!sqlPlugin?.createDatabaseAdapter) {
77
+ throw new Error("SQL plugin not available - falling back to mock database");
78
+ }
79
+ const postgresUrl = process.env.TEST_POSTGRES_URL || process.env.POSTGRES_URL;
80
+ if (!postgresUrl) {
81
+ throw new Error("PostgreSQL URL not available - falling back to mock database");
82
+ }
83
+ adapter = await sqlPlugin.createDatabaseAdapter(
84
+ {
85
+ postgresUrl
86
+ },
87
+ "11111111-2222-3333-4444-555555555555"
88
+ );
89
+ logger.debug(`Successfully created PostgreSQL adapter for ${testId}`);
90
+ } catch (importError) {
91
+ logger.warn(
92
+ `SQL plugin not available: ${importError instanceof Error ? importError.message : String(importError)} - falling back to mock database`
93
+ );
94
+ adapter = this.createMockDatabase(testId);
95
+ }
96
+ }
97
+ } catch (postgresError) {
98
+ logger.warn(
99
+ `Failed to create PostgreSQL database: ${postgresError instanceof Error ? postgresError.message : String(postgresError)} - falling back to mock database`
100
+ );
101
+ adapter = this.createMockDatabase(testId);
102
+ }
103
+ await adapter.init();
104
+ this.testDatabases.set(testId, adapter);
105
+ logger.debug(`Successfully created isolated database for ${testId}`);
106
+ return adapter;
107
+ } catch (error) {
108
+ logger.error(
109
+ `Failed to create test database for ${testId}: ${error instanceof Error ? error.message : String(error)}`
110
+ );
111
+ throw new Error(
112
+ `Test database creation failed: ${error instanceof Error ? error.message : String(error)}`
113
+ );
114
+ }
115
+ }
116
+ /**
117
+ * Creates a minimal mock database adapter for testing when real database unavailable
118
+ * This is a FUNCTIONAL mock that actually stores data in memory
119
+ */
120
+ createMockDatabase(testId) {
121
+ const storage = {
122
+ agents: /* @__PURE__ */ new Map(),
123
+ entities: /* @__PURE__ */ new Map(),
124
+ memories: /* @__PURE__ */ new Map(),
125
+ relationships: /* @__PURE__ */ new Map(),
126
+ rooms: /* @__PURE__ */ new Map(),
127
+ participants: /* @__PURE__ */ new Map(),
128
+ cache: /* @__PURE__ */ new Map(),
129
+ worlds: /* @__PURE__ */ new Map(),
130
+ tasks: /* @__PURE__ */ new Map(),
131
+ logs: /* @__PURE__ */ new Map()
132
+ };
133
+ const adapter = {
134
+ db: null,
135
+ // Mock database instance
136
+ async initialize() {
137
+ logger.debug(`Initialized mock database for ${testId}`);
138
+ },
139
+ async init() {
140
+ logger.debug(`Initialized mock database for ${testId}`);
141
+ },
142
+ async runMigrations() {
143
+ },
144
+ async isReady() {
145
+ return true;
146
+ },
147
+ async close() {
148
+ storage.agents.clear();
149
+ storage.entities.clear();
150
+ storage.memories.clear();
151
+ storage.relationships.clear();
152
+ storage.rooms.clear();
153
+ storage.participants.clear();
154
+ storage.cache.clear();
155
+ storage.worlds.clear();
156
+ storage.tasks.clear();
157
+ },
158
+ async getConnection() {
159
+ return null;
160
+ },
161
+ async ensureEmbeddingDimension() {
162
+ },
163
+ async getAgent(agentId) {
164
+ return storage.agents.get(agentId) || null;
165
+ },
166
+ async getAgents() {
167
+ return Array.from(storage.agents.values());
168
+ },
169
+ async createAgent(agent) {
170
+ const id = agent.id || v4_default();
171
+ const fullAgent = { ...agent, id };
172
+ storage.agents.set(id, fullAgent);
173
+ return true;
174
+ },
175
+ async updateAgent(agentId, agent) {
176
+ if (storage.agents.has(agentId)) {
177
+ storage.agents.set(agentId, { ...agent, id: agentId });
178
+ return true;
179
+ }
180
+ return false;
181
+ },
182
+ async deleteAgent(agentId) {
183
+ return storage.agents.delete(agentId);
184
+ },
185
+ // Entity operations
186
+ async createEntity(entity) {
187
+ const id = entity.id || v4_default();
188
+ const fullEntity = { ...entity, id };
189
+ storage.entities.set(id, fullEntity);
190
+ return fullEntity;
191
+ },
192
+ async createEntities(entities) {
193
+ for (const entity of entities) {
194
+ const id = entity.id || v4_default();
195
+ const fullEntity = { ...entity, id };
196
+ storage.entities.set(id, fullEntity);
197
+ }
198
+ return true;
199
+ },
200
+ async getEntityById(id) {
201
+ return storage.entities.get(id) || null;
202
+ },
203
+ async updateEntity(entity) {
204
+ if (!entity.id || !storage.entities.has(entity.id)) {
205
+ throw new Error("Entity not found");
206
+ }
207
+ storage.entities.set(entity.id, entity);
208
+ },
209
+ async getEntitiesForRoom(roomId) {
210
+ const participants = Array.from(storage.participants.values()).filter(
211
+ (p) => p.roomId === roomId
212
+ );
213
+ const entities = [];
214
+ for (const participant of participants) {
215
+ const entity = storage.entities.get(participant.entityId);
216
+ if (entity) {
217
+ entities.push(entity);
218
+ }
219
+ }
220
+ return entities;
221
+ },
222
+ // Memory operations
223
+ async createMemory(memory, tableName = "messages", _unique = false) {
224
+ const id = memory.id || v4_default();
225
+ const fullMemory = {
226
+ ...memory,
227
+ id,
228
+ createdAt: memory.createdAt || Date.now()
229
+ };
230
+ if (!storage.memories.has(tableName)) {
231
+ storage.memories.set(tableName, /* @__PURE__ */ new Map());
232
+ }
233
+ storage.memories.get(tableName).set(id, fullMemory);
234
+ return id;
235
+ },
236
+ async getMemories(params) {
237
+ const tableName = params.tableName || "messages";
238
+ const tableData = storage.memories.get(tableName);
239
+ if (!tableData) {
240
+ return [];
241
+ }
242
+ let memories = Array.from(tableData.values());
243
+ if (params.roomId) {
244
+ memories = memories.filter((m) => m.roomId === params.roomId);
245
+ }
246
+ if (params.entityId) {
247
+ memories = memories.filter((m) => m.entityId === params.entityId);
248
+ }
249
+ memories.sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0));
250
+ if (params.count) {
251
+ memories = memories.slice(0, params.count);
252
+ }
253
+ return memories;
254
+ },
255
+ async searchMemories(params) {
256
+ const tableName = params.tableName || "messages";
257
+ const tableData = storage.memories.get(tableName);
258
+ if (!tableData) {
259
+ return [];
260
+ }
261
+ let memories = Array.from(tableData.values());
262
+ if (params.roomId) {
263
+ memories = memories.filter((m) => m.roomId === params.roomId);
264
+ }
265
+ if (params.query) {
266
+ memories = memories.filter(
267
+ (m) => m.content?.text?.toLowerCase().includes(params.query.toLowerCase())
268
+ );
269
+ }
270
+ return memories.slice(0, params.count || 10);
271
+ },
272
+ async getMemoryById(id) {
273
+ for (const [_tableName, tableData] of storage.memories) {
274
+ const memory = tableData.get(id);
275
+ if (memory) {
276
+ return memory;
277
+ }
278
+ }
279
+ return null;
280
+ },
281
+ async getMemoriesByIds(ids, tableName = "messages") {
282
+ const tableData = storage.memories.get(tableName);
283
+ if (!tableData) {
284
+ return [];
285
+ }
286
+ const memories = [];
287
+ for (const id of ids) {
288
+ const memory = tableData.get(id);
289
+ if (memory) {
290
+ memories.push(memory);
291
+ }
292
+ }
293
+ return memories;
294
+ },
295
+ async getMemoriesByRoomIds(params) {
296
+ const tableData = storage.memories.get(params.tableName);
297
+ if (!tableData) {
298
+ return [];
299
+ }
300
+ let memories = Array.from(tableData.values()).filter(
301
+ (m) => params.roomIds.includes(m.roomId)
302
+ );
303
+ if (params.limit) {
304
+ memories = memories.slice(0, params.limit);
305
+ }
306
+ return memories;
307
+ },
308
+ async getCachedEmbeddings() {
309
+ return [];
310
+ },
311
+ async log(params) {
312
+ if (!storage.logs) {
313
+ storage.logs = /* @__PURE__ */ new Map();
314
+ }
315
+ const logId = v4_default();
316
+ storage.logs.set(logId, {
317
+ id: logId,
318
+ ...params,
319
+ createdAt: /* @__PURE__ */ new Date()
320
+ });
321
+ },
322
+ async getLogs() {
323
+ if (!storage.logs) {
324
+ return [];
325
+ }
326
+ return Array.from(storage.logs.values());
327
+ },
328
+ async deleteMemory(memoryId, tableName = "messages") {
329
+ const tableData = storage.memories.get(tableName);
330
+ if (tableData) {
331
+ return tableData.delete(memoryId);
332
+ }
333
+ return false;
334
+ },
335
+ // Room operations
336
+ async createRoom(room) {
337
+ const id = room.id || v4_default();
338
+ const fullRoom = { ...room, id };
339
+ storage.rooms.set(id, fullRoom);
340
+ },
341
+ async getRoom(roomId) {
342
+ return storage.rooms.get(roomId) || null;
343
+ },
344
+ async getRooms(worldId) {
345
+ return Array.from(storage.rooms.values()).filter(
346
+ (room) => !worldId || room.worldId === worldId
347
+ );
348
+ },
349
+ // Participant operations
350
+ async addParticipant(entityId, roomId) {
351
+ const participantId = `${entityId}-${roomId}`;
352
+ storage.participants.set(participantId, { entityId, roomId });
353
+ return true;
354
+ },
355
+ async removeParticipant(entityId, roomId) {
356
+ const participantId = `${entityId}-${roomId}`;
357
+ return storage.participants.delete(participantId);
358
+ },
359
+ async getParticipantsForRoom(roomId) {
360
+ return Array.from(storage.participants.values()).filter((p) => p.roomId === roomId).map((p) => p.entityId);
361
+ },
362
+ // Cache operations
363
+ async setCache(key, value) {
364
+ storage.cache.set(key, {
365
+ value,
366
+ createdAt: Date.now()
367
+ });
368
+ return true;
369
+ },
370
+ async getCache(key) {
371
+ const cached = storage.cache.get(key);
372
+ return cached ? cached.value : null;
373
+ },
374
+ async deleteCache(key) {
375
+ return storage.cache.delete(key);
376
+ },
377
+ // World operations
378
+ async createWorld(world) {
379
+ const id = world.id || v4_default();
380
+ const fullWorld = { ...world, id };
381
+ storage.worlds.set(id, fullWorld);
382
+ return id;
383
+ },
384
+ async getWorld(worldId) {
385
+ return storage.worlds.get(worldId) || null;
386
+ },
387
+ async getAllWorlds() {
388
+ return Array.from(storage.worlds.values());
389
+ },
390
+ // Task operations
391
+ async createTask(task) {
392
+ const id = task.id || v4_default();
393
+ const fullTask = {
394
+ ...task,
395
+ id,
396
+ updatedAt: task.updatedAt || Date.now()
397
+ };
398
+ storage.tasks.set(id, fullTask);
399
+ return id;
400
+ },
401
+ async getTasks(params) {
402
+ let tasks = Array.from(storage.tasks.values());
403
+ if (params.roomId) {
404
+ tasks = tasks.filter((task) => task.roomId === params.roomId);
405
+ }
406
+ if (params.tags) {
407
+ tasks = tasks.filter(
408
+ (task) => params.tags.some((tag) => task.tags.includes(tag))
409
+ );
410
+ }
411
+ return tasks;
412
+ },
413
+ async deleteTask(taskId) {
414
+ storage.tasks.delete(taskId);
415
+ },
416
+ // Relationship operations
417
+ async createRelationship(relationship) {
418
+ const id = v4_default();
419
+ const fullRelationship = { ...relationship, id };
420
+ storage.relationships.set(id, fullRelationship);
421
+ return true;
422
+ },
423
+ async getRelationships(params) {
424
+ let relationships = Array.from(storage.relationships.values());
425
+ if (params.entityId) {
426
+ relationships = relationships.filter(
427
+ (rel) => rel.sourceEntityId === params.entityId || rel.targetEntityId === params.entityId
428
+ );
429
+ }
430
+ return relationships;
431
+ },
432
+ async getEntitiesByIds(ids) {
433
+ const entities = [];
434
+ for (const id of ids) {
435
+ const entity = storage.entities.get(id);
436
+ if (entity) {
437
+ entities.push(entity);
438
+ }
439
+ }
440
+ return entities;
441
+ },
442
+ async updateMemory(memory) {
443
+ const tableName = "messages";
444
+ const tableData = storage.memories.get(tableName);
445
+ if (tableData && tableData.has(memory.id)) {
446
+ const existing = tableData.get(memory.id);
447
+ const updated = { ...existing, ...memory };
448
+ tableData.set(memory.id, updated);
449
+ return updated;
450
+ }
451
+ return null;
452
+ },
453
+ async countMemories(roomId, tableName = "messages") {
454
+ const tableData = storage.memories.get(tableName);
455
+ if (!tableData) {
456
+ return 0;
457
+ }
458
+ if (!roomId) {
459
+ return tableData.size;
460
+ }
461
+ return Array.from(tableData.values()).filter((m) => m.roomId === roomId).length;
462
+ },
463
+ async getMemoriesByEntityIds(entityIds, tableName = "messages") {
464
+ const tableData = storage.memories.get(tableName);
465
+ if (!tableData) {
466
+ return [];
467
+ }
468
+ return Array.from(tableData.values()).filter((m) => entityIds.includes(m.entityId));
469
+ },
470
+ async removeAllMemories(roomId, tableName = "messages") {
471
+ const tableData = storage.memories.get(tableName);
472
+ if (!tableData) {
473
+ return;
474
+ }
475
+ const toDelete = [];
476
+ for (const [id, memory] of tableData) {
477
+ if (memory.roomId === roomId) {
478
+ toDelete.push(id);
479
+ }
480
+ }
481
+ for (const id of toDelete) {
482
+ tableData.delete(id);
483
+ }
484
+ },
485
+ async updateRoom(room) {
486
+ if (!room.id || !storage.rooms.has(room.id)) {
487
+ throw new Error("Room not found");
488
+ }
489
+ storage.rooms.set(room.id, room);
490
+ },
491
+ async deleteRoom(roomId) {
492
+ storage.rooms.delete(roomId);
493
+ },
494
+ async getRoomsByIds(roomIds) {
495
+ const rooms = [];
496
+ for (const id of roomIds) {
497
+ const room = storage.rooms.get(id);
498
+ if (room) {
499
+ rooms.push(room);
500
+ }
501
+ }
502
+ return rooms;
503
+ },
504
+ async createRooms(rooms) {
505
+ const ids = [];
506
+ for (const room of rooms) {
507
+ const id = room.id || v4_default();
508
+ const fullRoom = { ...room, id };
509
+ storage.rooms.set(id, fullRoom);
510
+ ids.push(id);
511
+ }
512
+ return ids;
513
+ },
514
+ async getRoomsByWorld(worldId) {
515
+ return Array.from(storage.rooms.values()).filter((room) => room.worldId === worldId);
516
+ },
517
+ async deleteRoomsByWorldId(worldId) {
518
+ const toDelete = [];
519
+ for (const [id, room] of storage.rooms) {
520
+ if (room.worldId === worldId) {
521
+ toDelete.push(id);
522
+ }
523
+ }
524
+ for (const id of toDelete) {
525
+ storage.rooms.delete(id);
526
+ }
527
+ },
528
+ async getWorlds(params) {
529
+ let worlds = Array.from(storage.worlds.values());
530
+ if (params?.agentId) {
531
+ worlds = worlds.filter((w) => w.agentId === params.agentId);
532
+ }
533
+ return worlds;
534
+ },
535
+ async removeWorld(worldId) {
536
+ storage.worlds.delete(worldId);
537
+ },
538
+ async updateWorld(world) {
539
+ if (!world.id || !storage.worlds.has(world.id)) {
540
+ throw new Error("World not found");
541
+ }
542
+ storage.worlds.set(world.id, world);
543
+ },
544
+ async createComponent(component) {
545
+ const entityComponents = storage.entities.get(component.entityId)?.components || [];
546
+ entityComponents.push(component);
547
+ const entity = storage.entities.get(component.entityId);
548
+ if (entity) {
549
+ entity.components = entityComponents;
550
+ storage.entities.set(component.entityId, entity);
551
+ }
552
+ return true;
553
+ },
554
+ async getComponents(entityId) {
555
+ const entity = storage.entities.get(entityId);
556
+ return entity?.components || [];
557
+ },
558
+ async updateComponent(component) {
559
+ const entity = storage.entities.get(component.entityId);
560
+ if (entity && entity.components) {
561
+ const index = entity.components.findIndex((c) => c.id === component.id);
562
+ if (index >= 0) {
563
+ entity.components[index] = component;
564
+ storage.entities.set(component.entityId, entity);
565
+ return;
566
+ }
567
+ }
568
+ throw new Error("Component not found");
569
+ },
570
+ async deleteComponent(componentId) {
571
+ for (const entity of storage.entities.values()) {
572
+ if (entity.components) {
573
+ const index = entity.components.findIndex((c) => c.id === componentId);
574
+ if (index >= 0) {
575
+ entity.components.splice(index, 1);
576
+ storage.entities.set(entity.id, entity);
577
+ return;
578
+ }
579
+ }
580
+ }
581
+ },
582
+ async getComponent(entityId, type, worldId, sourceEntityId) {
583
+ const entity = storage.entities.get(entityId);
584
+ if (!entity?.components) {
585
+ return null;
586
+ }
587
+ return entity.components.find(
588
+ (c) => c.type === type && (!worldId || c.worldId === worldId) && (!sourceEntityId || c.sourceEntityId === sourceEntityId)
589
+ ) || null;
590
+ },
591
+ async getParticipantsForEntity(entityId) {
592
+ return Array.from(storage.participants.values()).filter(
593
+ (p) => p.entityId === entityId
594
+ );
595
+ },
596
+ async getRoomsForParticipant(entityId) {
597
+ return Array.from(storage.participants.values()).filter((p) => p.entityId === entityId).map((p) => p.roomId);
598
+ },
599
+ async getRoomsForParticipants(userIds) {
600
+ const roomIds = /* @__PURE__ */ new Set();
601
+ for (const participant of storage.participants.values()) {
602
+ if (userIds.includes(participant.entityId)) {
603
+ roomIds.add(participant.roomId);
604
+ }
605
+ }
606
+ return Array.from(roomIds);
607
+ },
608
+ async getParticipantUserState(_roomId, _entityId) {
609
+ return null;
610
+ },
611
+ async setParticipantUserState(_roomId, _entityId, _state) {
612
+ },
613
+ async getRelationship(params) {
614
+ const relationships = Array.from(storage.relationships.values());
615
+ return relationships.find(
616
+ (r) => r.sourceEntityId === params.sourceEntityId && r.targetEntityId === params.targetEntityId
617
+ ) || null;
618
+ },
619
+ async updateRelationship(relationship) {
620
+ if (!relationship.id || !storage.relationships.has(relationship.id)) {
621
+ throw new Error("Relationship not found");
622
+ }
623
+ storage.relationships.set(relationship.id, relationship);
624
+ },
625
+ async getTask(id) {
626
+ return storage.tasks.get(id) || null;
627
+ },
628
+ async getTasksByName(name) {
629
+ return Array.from(storage.tasks.values()).filter((task) => task.name === name);
630
+ },
631
+ async updateTask(id, updates) {
632
+ const task = storage.tasks.get(id);
633
+ if (!task) {
634
+ throw new Error("Task not found");
635
+ }
636
+ const updated = { ...task, ...updates, updatedAt: Date.now() };
637
+ storage.tasks.set(id, updated);
638
+ },
639
+ async deleteLog(logId) {
640
+ if (storage.logs) {
641
+ storage.logs.delete(logId);
642
+ }
643
+ },
644
+ async getMemoriesByWorldId(params) {
645
+ const tableName = params.tableName || "messages";
646
+ const tableData = storage.memories.get(tableName);
647
+ if (!tableData) {
648
+ return [];
649
+ }
650
+ let memories = Array.from(tableData.values()).filter(
651
+ (m) => m.worldId === params.worldId
652
+ );
653
+ if (params.count) {
654
+ memories = memories.slice(0, params.count);
655
+ }
656
+ return memories;
657
+ },
658
+ async deleteManyMemories(memoryIds) {
659
+ for (const [_tableName, tableData] of storage.memories) {
660
+ for (const id of memoryIds) {
661
+ tableData.delete(id);
662
+ }
663
+ }
664
+ },
665
+ async deleteAllMemories(roomId, _tableName) {
666
+ const tableData = storage.memories.get(_tableName);
667
+ if (!tableData) {
668
+ return;
669
+ }
670
+ const toDelete = [];
671
+ for (const [id, memory] of tableData) {
672
+ if (memory.roomId === roomId) {
673
+ toDelete.push(id);
674
+ }
675
+ }
676
+ for (const id of toDelete) {
677
+ tableData.delete(id);
678
+ }
679
+ },
680
+ async addParticipantsRoom(entityIds, roomId) {
681
+ for (const entityId of entityIds) {
682
+ const participantId = `${entityId}-${roomId}`;
683
+ storage.participants.set(participantId, { entityId, roomId });
684
+ }
685
+ return true;
686
+ }
687
+ };
688
+ return adapter;
689
+ }
690
+ /**
691
+ * Cleanup a specific test database
692
+ */
693
+ async cleanupDatabase(testId) {
694
+ try {
695
+ const adapter = this.testDatabases.get(testId);
696
+ if (adapter) {
697
+ await adapter.close();
698
+ this.testDatabases.delete(testId);
699
+ logger.debug(`Cleaned up database for ${testId}`);
700
+ }
701
+ } catch (error) {
702
+ logger.warn(
703
+ `Error cleaning up database ${testId}: ${error instanceof Error ? error.message : String(error)}`
704
+ );
705
+ }
706
+ }
707
+ /**
708
+ * Cleanup all test databases
709
+ */
710
+ async cleanup() {
711
+ logger.debug("Cleaning up all test databases");
712
+ const cleanupPromises = Array.from(this.testDatabases.keys()).map(
713
+ (testId) => this.cleanupDatabase(testId)
714
+ );
715
+ await Promise.all(cleanupPromises);
716
+ this.tempPaths.clear();
717
+ this.testDatabases.clear();
718
+ logger.debug("Successfully cleaned up all test databases");
719
+ }
720
+ /**
721
+ * Get statistics about test databases
722
+ */
723
+ getStats() {
724
+ return {
725
+ activeDatabases: this.testDatabases.size,
726
+ tempPaths: Array.from(this.tempPaths),
727
+ memoryUsage: `${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB`
728
+ };
729
+ }
730
+ };
731
+ async function createTestDatabase(testId) {
732
+ const actualTestId = testId || `test-${v4_default().slice(0, 8)}`;
733
+ const manager = new TestDatabaseManager();
734
+ const adapter = await manager.createIsolatedDatabase(actualTestId);
735
+ return { adapter, manager, testId: actualTestId };
736
+ }
737
+
738
+ // src/testModels.ts
739
+ import { logger as logger2 } from "@elizaos/core";
740
+ var TestModelProvider = class {
741
+ responses = /* @__PURE__ */ new Map();
742
+ patterns = [];
743
+ defaultResponse;
744
+ contextHistory = [];
745
+ constructor(defaultResponse = "I understand and will help with that.", _options = {}) {
746
+ this.defaultResponse = defaultResponse;
747
+ this.addDefaultPatterns();
748
+ }
749
+ /**
750
+ * Add realistic default response patterns
751
+ */
752
+ addDefaultPatterns() {
753
+ const defaultPatterns = [
754
+ // Greeting patterns
755
+ {
756
+ pattern: /^(hello|hi|hey|greetings)/i,
757
+ response: "Hello! How can I help you today?"
758
+ },
759
+ {
760
+ pattern: /(good morning|good afternoon|good evening)/i,
761
+ response: "Good day! What can I assist you with?"
762
+ },
763
+ // Task creation patterns
764
+ {
765
+ pattern: /(create|add|make).*?(todo|task|reminder)/i,
766
+ response: "I'll create that task for you right away. Let me add it to your todo list."
767
+ },
768
+ {
769
+ pattern: /(schedule|plan|organize)/i,
770
+ response: "I'll help you schedule that. Let me organize this for you."
771
+ },
772
+ // Information requests
773
+ {
774
+ pattern: /(search|find|look|query).*?(for|about)/i,
775
+ response: "Let me search for that information. I'll look into it right away."
776
+ },
777
+ {
778
+ pattern: /(what|how|when|where|why)/i,
779
+ response: "Let me find that information for you. I'll provide a detailed answer."
780
+ },
781
+ // Analysis and review
782
+ {
783
+ pattern: /(analyze|review|examine|check)/i,
784
+ response: "I'll analyze this carefully and provide my assessment with detailed insights."
785
+ },
786
+ {
787
+ pattern: /(explain|describe|tell me about)/i,
788
+ response: "I'll explain that in detail for you. Here's what you need to know."
789
+ },
790
+ // Action requests
791
+ {
792
+ pattern: /(send|email|message|notify)/i,
793
+ response: "I'll send that message for you. Let me take care of the communication."
794
+ },
795
+ {
796
+ pattern: /(delete|remove|cancel)/i,
797
+ response: "I'll remove that for you. Let me handle the deletion safely."
798
+ },
799
+ // File and data operations
800
+ {
801
+ pattern: /(save|store|backup)/i,
802
+ response: "I'll save that information securely. Your data will be stored properly."
803
+ },
804
+ {
805
+ pattern: /(load|open|access)/i,
806
+ response: "I'll access that resource for you. Let me retrieve the information."
807
+ },
808
+ // Problem solving
809
+ {
810
+ pattern: /(fix|repair|solve|troubleshoot)/i,
811
+ response: "I'll help troubleshoot this issue. Let me analyze the problem and find a solution."
812
+ },
813
+ {
814
+ pattern: /(help|assist|support)/i,
815
+ response: "I'm here to help! Let me assist you with whatever you need."
816
+ },
817
+ // Decision making
818
+ {
819
+ pattern: /(should|recommend|suggest|advise)/i,
820
+ response: "Based on the information provided, I'd recommend the following approach."
821
+ },
822
+ {
823
+ pattern: /(choose|select|decide)/i,
824
+ response: "Let me help you make that decision. Here are the key factors to consider."
825
+ },
826
+ // Confirmation and acknowledgment
827
+ {
828
+ pattern: /(yes|ok|okay|sure|agreed)/i,
829
+ response: "Understood! I'll proceed with that as requested."
830
+ },
831
+ {
832
+ pattern: /(no|stop|cancel|abort)/i,
833
+ response: "Alright, I'll stop that process. Is there anything else I can help with?"
834
+ },
835
+ // Complex reasoning patterns
836
+ {
837
+ pattern: /(if.*then|because|therefore|since)/i,
838
+ response: "I understand the logic. Let me work through this step by step."
839
+ },
840
+ {
841
+ pattern: /(compare|contrast|difference|similar)/i,
842
+ response: "I'll compare these options and highlight the key differences and similarities."
843
+ },
844
+ // Error handling
845
+ {
846
+ pattern: /(error|problem|issue|broken|failed)/i,
847
+ response: "I see there's an issue. Let me investigate the problem and find a solution."
848
+ }
849
+ ];
850
+ this.patterns.push(...defaultPatterns);
851
+ }
852
+ /**
853
+ * Generate text response based on prompt
854
+ */
855
+ async generateText(params) {
856
+ const prompt = params.prompt;
857
+ try {
858
+ const exactMatch = this.responses.get(prompt);
859
+ if (exactMatch) {
860
+ this.addToHistory(prompt, exactMatch);
861
+ return exactMatch;
862
+ }
863
+ for (const { pattern, response } of this.patterns) {
864
+ if (pattern.test(prompt)) {
865
+ const contextualResponse = this.makeContextual(response, prompt);
866
+ this.addToHistory(prompt, contextualResponse);
867
+ return contextualResponse;
868
+ }
869
+ }
870
+ const intelligentResponse = this.generateIntelligentDefault(prompt);
871
+ this.addToHistory(prompt, intelligentResponse);
872
+ return intelligentResponse;
873
+ } catch (error) {
874
+ logger2.warn(
875
+ `Error in test model provider: ${error instanceof Error ? error.message : String(error)}`
876
+ );
877
+ return this.defaultResponse;
878
+ }
879
+ }
880
+ /**
881
+ * Generate embeddings for text (mock implementation with consistent vectors)
882
+ */
883
+ async generateEmbedding(params) {
884
+ const text = params.text;
885
+ const hash = this.simpleHash(text);
886
+ const embedding = [];
887
+ for (let i = 0; i < 1536; i++) {
888
+ const value = Math.sin(hash + i) * 0.5;
889
+ embedding.push(value);
890
+ }
891
+ return embedding;
892
+ }
893
+ /**
894
+ * Generate object-structured responses
895
+ */
896
+ async generateObject(params) {
897
+ const prompt = params.prompt;
898
+ if (prompt.includes("thought") || prompt.includes("reasoning")) {
899
+ return {
900
+ thought: "I need to think about this carefully and provide a helpful response.",
901
+ reasoning: "Based on the context provided, here's my analysis.",
902
+ confidence: 0.85
903
+ };
904
+ }
905
+ if (prompt.includes("action") || prompt.includes("execute")) {
906
+ return {
907
+ action: "RESPOND",
908
+ parameters: {},
909
+ confidence: 0.9
910
+ };
911
+ }
912
+ if (prompt.includes("memory") || prompt.includes("remember")) {
913
+ return {
914
+ shouldStore: true,
915
+ importance: 0.7,
916
+ category: "conversation"
917
+ };
918
+ }
919
+ return {
920
+ response: await this.generateText({ prompt, ...params }),
921
+ confidence: 0.8,
922
+ metadata: {
923
+ timestamp: Date.now(),
924
+ model: "test-model"
925
+ }
926
+ };
927
+ }
928
+ /**
929
+ * Make response more contextual based on prompt content
930
+ */
931
+ makeContextual(response, prompt) {
932
+ const keyTerms = this.extractKeyTerms(prompt);
933
+ if (keyTerms.length > 0) {
934
+ const term = keyTerms[0];
935
+ return response.replace(
936
+ /that|this|it/g,
937
+ term.length > 20 ? `that ${term.substring(0, 20)}...` : `that ${term}`
938
+ );
939
+ }
940
+ return response;
941
+ }
942
+ /**
943
+ * Generate intelligent default response based on prompt analysis
944
+ */
945
+ generateIntelligentDefault(prompt) {
946
+ const lowerPrompt = prompt.toLowerCase();
947
+ if (lowerPrompt.includes("?")) {
948
+ return "That's a great question. Let me provide you with a comprehensive answer based on the available information.";
949
+ }
950
+ if (lowerPrompt.match(/^(please|can you|could you|would you)/)) {
951
+ return "Of course! I'll take care of that for you right away.";
952
+ }
953
+ if (lowerPrompt.length > 200) {
954
+ return "I understand this is a complex request. Let me work through this systematically and provide you with a detailed response.";
955
+ }
956
+ if (lowerPrompt.match(/(angry|sad|frustrated|excited|happy|worried)/)) {
957
+ return "I understand how you're feeling. Let me help you work through this thoughtfully.";
958
+ }
959
+ return this.defaultResponse;
960
+ }
961
+ /**
962
+ * Extract key terms from prompt for contextualization
963
+ */
964
+ extractKeyTerms(prompt) {
965
+ const commonWords = /* @__PURE__ */ new Set([
966
+ "the",
967
+ "a",
968
+ "an",
969
+ "and",
970
+ "or",
971
+ "but",
972
+ "in",
973
+ "on",
974
+ "at",
975
+ "to",
976
+ "for",
977
+ "of",
978
+ "with",
979
+ "by",
980
+ "i",
981
+ "you",
982
+ "he",
983
+ "she",
984
+ "it",
985
+ "we",
986
+ "they",
987
+ "this",
988
+ "that",
989
+ "these",
990
+ "those",
991
+ "is",
992
+ "are",
993
+ "was",
994
+ "were",
995
+ "be",
996
+ "been",
997
+ "being",
998
+ "have",
999
+ "has",
1000
+ "had",
1001
+ "do",
1002
+ "does",
1003
+ "did",
1004
+ "will",
1005
+ "would",
1006
+ "could",
1007
+ "should",
1008
+ "can",
1009
+ "may",
1010
+ "might",
1011
+ "must"
1012
+ ]);
1013
+ const words = prompt.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((word) => word.length > 2 && !commonWords.has(word));
1014
+ return [...new Set(words)].slice(0, 3);
1015
+ }
1016
+ /**
1017
+ * Simple hash function for deterministic embeddings
1018
+ */
1019
+ simpleHash(str) {
1020
+ let hash = 0;
1021
+ for (let i = 0; i < str.length; i++) {
1022
+ const char = str.charCodeAt(i);
1023
+ hash = (hash << 5) - hash + char;
1024
+ hash = hash & hash;
1025
+ }
1026
+ return Math.abs(hash);
1027
+ }
1028
+ /**
1029
+ * Add interaction to context history
1030
+ */
1031
+ addToHistory(prompt, response) {
1032
+ this.contextHistory.push({ prompt, response });
1033
+ if (this.contextHistory.length > 10) {
1034
+ this.contextHistory.shift();
1035
+ }
1036
+ }
1037
+ /**
1038
+ * Set a specific response for a prompt
1039
+ */
1040
+ setResponse(prompt, response) {
1041
+ this.responses.set(prompt, response);
1042
+ }
1043
+ /**
1044
+ * Add a pattern-based response
1045
+ */
1046
+ addPattern(pattern, response) {
1047
+ this.patterns.unshift({ pattern, response });
1048
+ }
1049
+ /**
1050
+ * Set the default response
1051
+ */
1052
+ setDefaultResponse(response) {
1053
+ this.defaultResponse = response;
1054
+ }
1055
+ /**
1056
+ * Clear all custom responses and patterns
1057
+ */
1058
+ clear() {
1059
+ this.responses.clear();
1060
+ this.patterns.length = 0;
1061
+ this.contextHistory.length = 0;
1062
+ this.addDefaultPatterns();
1063
+ }
1064
+ /**
1065
+ * Get conversation history
1066
+ */
1067
+ getHistory() {
1068
+ return [...this.contextHistory];
1069
+ }
1070
+ };
1071
+ function createTestModelProvider(scenarios2 = [], defaultResponse) {
1072
+ const provider = new TestModelProvider(defaultResponse);
1073
+ for (const scenario of scenarios2) {
1074
+ if (scenario.prompt instanceof RegExp) {
1075
+ provider.addPattern(scenario.prompt, scenario.response);
1076
+ } else {
1077
+ provider.setResponse(scenario.prompt, scenario.response);
1078
+ }
1079
+ }
1080
+ return provider;
1081
+ }
1082
+ function createSpecializedModelProvider(type) {
1083
+ const provider = new TestModelProvider();
1084
+ switch (type) {
1085
+ case "conversational":
1086
+ provider.addPattern(
1087
+ /.*/,
1088
+ "That's interesting! Let me respond thoughtfully to what you've shared."
1089
+ );
1090
+ break;
1091
+ case "analytical":
1092
+ provider.addPattern(
1093
+ /.*/,
1094
+ "Let me analyze this systematically. Based on the data and context provided, here's my assessment."
1095
+ );
1096
+ break;
1097
+ case "creative":
1098
+ provider.addPattern(
1099
+ /.*/,
1100
+ "What a creative challenge! Let me think outside the box and explore innovative possibilities."
1101
+ );
1102
+ break;
1103
+ case "factual":
1104
+ provider.addPattern(
1105
+ /.*/,
1106
+ "Based on factual information and established knowledge, here's an accurate response."
1107
+ );
1108
+ break;
1109
+ }
1110
+ return provider;
1111
+ }
1112
+ function createModelHandler(provider) {
1113
+ return async (runtime, params) => {
1114
+ const modelType = params.modelType || "TEXT_LARGE";
1115
+ switch (modelType) {
1116
+ case "TEXT_SMALL":
1117
+ case "TEXT_LARGE":
1118
+ return await provider.generateText(params);
1119
+ case "TEXT_EMBEDDING":
1120
+ return await provider.generateEmbedding(params);
1121
+ case "OBJECT_SMALL":
1122
+ case "OBJECT_LARGE":
1123
+ return await provider.generateObject(params);
1124
+ default:
1125
+ return await provider.generateText(params);
1126
+ }
1127
+ };
1128
+ }
1129
+ var TestScenarioBuilder = class {
1130
+ scenarios = [];
1131
+ addGreeting(response = "Hello! How can I help you?") {
1132
+ this.scenarios.push({
1133
+ prompt: /^(hello|hi|hey)/i,
1134
+ response
1135
+ });
1136
+ return this;
1137
+ }
1138
+ addTaskCreation(response = "I'll create that task for you.") {
1139
+ this.scenarios.push({
1140
+ prompt: /(create|add|make).*?(todo|task)/i,
1141
+ response
1142
+ });
1143
+ return this;
1144
+ }
1145
+ addSearch(response = "Let me search for that information.") {
1146
+ this.scenarios.push({
1147
+ prompt: /(search|find|look)/i,
1148
+ response
1149
+ });
1150
+ return this;
1151
+ }
1152
+ addCustom(prompt, response) {
1153
+ this.scenarios.push({ prompt, response });
1154
+ return this;
1155
+ }
1156
+ build(defaultResponse) {
1157
+ return createTestModelProvider(this.scenarios, defaultResponse);
1158
+ }
1159
+ };
1160
+ function scenarios() {
1161
+ return new TestScenarioBuilder();
1162
+ }
1163
+
1164
+ // src/realRuntime.ts
1165
+ var RuntimeTestHarness = class {
1166
+ runtimes = /* @__PURE__ */ new Map();
1167
+ databaseManager;
1168
+ testId;
1169
+ constructor(testId) {
1170
+ this.testId = testId || `test-${v4_default().slice(0, 8)}`;
1171
+ this.databaseManager = new TestDatabaseManager();
1172
+ }
1173
+ /**
1174
+ * Creates an AgentRuntime instance for testing
1175
+ * This uses the standard AgentRuntime - it will actually execute all functionality
1176
+ */
1177
+ async createTestRuntime(config) {
1178
+ try {
1179
+ logger3.info(`Creating real test runtime for ${this.testId}`);
1180
+ const databaseAdapter = await this.databaseManager.createIsolatedDatabase(
1181
+ `${this.testId}-${Date.now()}`
1182
+ );
1183
+ const runtime = new AgentRuntime({
1184
+ character: config.character,
1185
+ adapter: databaseAdapter
1186
+ });
1187
+ for (const plugin of config.plugins) {
1188
+ if (typeof plugin === "string") {
1189
+ const loadedPlugin = await this.loadPlugin(plugin);
1190
+ await runtime.registerPlugin(loadedPlugin);
1191
+ } else {
1192
+ await runtime.registerPlugin(plugin);
1193
+ }
1194
+ }
1195
+ await runtime.initialize();
1196
+ this.runtimes.set(runtime.agentId, runtime);
1197
+ logger3.info(`Successfully created real runtime ${runtime.agentId}`);
1198
+ return runtime;
1199
+ } catch (error) {
1200
+ logger3.error(
1201
+ `Failed to create test runtime: ${error instanceof Error ? error.message : String(error)}`
1202
+ );
1203
+ throw new Error(
1204
+ `Test runtime creation failed: ${error instanceof Error ? error.message : String(error)}`
1205
+ );
1206
+ }
1207
+ }
1208
+ /**
1209
+ * Loads a plugin by name from the ElizaOS ecosystem
1210
+ * Uses dynamic imports to avoid circular dependencies during build
1211
+ */
1212
+ async loadPlugin(pluginName) {
1213
+ try {
1214
+ logger3.info(`Attempting to load plugin: ${pluginName}`);
1215
+ let pluginModule;
1216
+ try {
1217
+ pluginModule = await import(pluginName);
1218
+ } catch (importError) {
1219
+ logger3.warn(
1220
+ `Could not import ${pluginName}: ${importError instanceof Error ? importError.message : String(importError)}`
1221
+ );
1222
+ throw importError;
1223
+ }
1224
+ const plugin = pluginModule.default || pluginModule[Object.keys(pluginModule)[0]];
1225
+ if (!plugin || typeof plugin !== "object") {
1226
+ throw new Error(`Invalid plugin export from ${pluginName}`);
1227
+ }
1228
+ logger3.info(`Successfully loaded plugin: ${pluginName}`);
1229
+ return plugin;
1230
+ } catch (error) {
1231
+ logger3.error(
1232
+ `Failed to load plugin ${pluginName}: ${error instanceof Error ? error.message : String(error)}`
1233
+ );
1234
+ throw new Error(
1235
+ `Plugin ${pluginName} must be available for testing. Install it before running tests. Error: ${error instanceof Error ? error.message : String(error)}`
1236
+ );
1237
+ }
1238
+ }
1239
+ /**
1240
+ * Creates a test model provider that gives realistic responses
1241
+ */
1242
+ createRealisticModelProvider(scenarios2) {
1243
+ const defaultScenarios = [
1244
+ {
1245
+ prompt: /hello|hi|hey/i,
1246
+ response: "Hello! How can I help you today?"
1247
+ },
1248
+ {
1249
+ prompt: /create.*todo|add.*task/i,
1250
+ response: "I'll create that todo item for you right away."
1251
+ },
1252
+ {
1253
+ prompt: /search|find|look/i,
1254
+ response: "Let me search for that information."
1255
+ },
1256
+ {
1257
+ prompt: /analyze|review/i,
1258
+ response: "I'll analyze this carefully and provide my assessment."
1259
+ }
1260
+ ];
1261
+ return createTestModelProvider(scenarios2 || defaultScenarios);
1262
+ }
1263
+ /**
1264
+ * Executes a real message processing test
1265
+ */
1266
+ async processTestMessage(runtime, messageText, options = {}) {
1267
+ const startTime = Date.now();
1268
+ const roomId = options.roomId || stringToUuid(`test-room-${v4_default()}`);
1269
+ const entityId = options.entityId || stringToUuid(`test-user-${v4_default()}`);
1270
+ try {
1271
+ const memory = {
1272
+ id: stringToUuid(`message-${v4_default()}`),
1273
+ entityId,
1274
+ roomId,
1275
+ content: {
1276
+ text: messageText,
1277
+ source: "test"
1278
+ },
1279
+ createdAt: Date.now()
1280
+ };
1281
+ const _messageId = await runtime.createMemory(memory, "messages");
1282
+ const responses = await runtime.processActions(memory, [], void 0, void 0);
1283
+ const responseTime = Date.now() - startTime;
1284
+ const result = {
1285
+ scenarioName: `Process: "${messageText}"`,
1286
+ passed: true,
1287
+ errors: [],
1288
+ executedActions: [],
1289
+ createdMemories: Array.isArray(responses) ? responses.length : 0,
1290
+ responseTime
1291
+ };
1292
+ if (options.expectedActions && options.expectedActions.length > 0) {
1293
+ const executedActions = await this.getExecutedActions(runtime, roomId);
1294
+ const missingActions = options.expectedActions.filter(
1295
+ (action) => !executedActions.includes(action)
1296
+ );
1297
+ if (missingActions.length > 0) {
1298
+ result.passed = false;
1299
+ result.errors.push(`Missing expected actions: ${missingActions.join(", ")}`);
1300
+ }
1301
+ result.executedActions = executedActions;
1302
+ }
1303
+ if (options.timeoutMs && responseTime > options.timeoutMs) {
1304
+ result.passed = false;
1305
+ result.errors.push(
1306
+ `Response time ${responseTime}ms exceeded timeout ${options.timeoutMs}ms`
1307
+ );
1308
+ }
1309
+ return result;
1310
+ } catch (error) {
1311
+ return {
1312
+ scenarioName: `Process: "${messageText}"`,
1313
+ passed: false,
1314
+ errors: [`Runtime error: ${error instanceof Error ? error.message : String(error)}`],
1315
+ executedActions: [],
1316
+ createdMemories: 0,
1317
+ responseTime: Date.now() - startTime
1318
+ };
1319
+ }
1320
+ }
1321
+ /**
1322
+ * Gets actions that were actually executed (not mocked)
1323
+ */
1324
+ async getExecutedActions(runtime, roomId) {
1325
+ try {
1326
+ const memories = await runtime.getMemories({
1327
+ roomId,
1328
+ count: 10,
1329
+ tableName: "messages"
1330
+ });
1331
+ const actions = [];
1332
+ for (const memory of memories) {
1333
+ if (memory.content.actions && Array.isArray(memory.content.actions)) {
1334
+ actions.push(...memory.content.actions);
1335
+ }
1336
+ }
1337
+ return [...new Set(actions)];
1338
+ } catch (error) {
1339
+ logger3.warn(
1340
+ `Could not retrieve executed actions: ${error instanceof Error ? error.message : String(error)}`
1341
+ );
1342
+ return [];
1343
+ }
1344
+ }
1345
+ /**
1346
+ * Validates that a runtime is actually functional
1347
+ */
1348
+ async validateRuntimeHealth(runtime) {
1349
+ const issues = [];
1350
+ const services = [];
1351
+ const plugins = [];
1352
+ try {
1353
+ if (!runtime.agentId) {
1354
+ issues.push("Runtime missing agentId");
1355
+ }
1356
+ if (!runtime.character) {
1357
+ issues.push("Runtime missing character");
1358
+ }
1359
+ try {
1360
+ const healthMemory = {
1361
+ id: stringToUuid("health-check-message"),
1362
+ entityId: stringToUuid("health-check-entity"),
1363
+ roomId: stringToUuid("health-check-room"),
1364
+ content: { text: "Health check", source: "test" },
1365
+ createdAt: Date.now()
1366
+ };
1367
+ await runtime.createMemory(healthMemory, "test");
1368
+ } catch (error) {
1369
+ issues.push(
1370
+ `Database not functional: ${error instanceof Error ? error.message : String(error)}`
1371
+ );
1372
+ }
1373
+ try {
1374
+ const serviceMap = runtime.services || /* @__PURE__ */ new Map();
1375
+ for (const [name, service] of serviceMap) {
1376
+ services.push(name);
1377
+ if (!service) {
1378
+ issues.push(`Service ${name} is null/undefined`);
1379
+ }
1380
+ }
1381
+ } catch (error) {
1382
+ issues.push(
1383
+ `Services not accessible: ${error instanceof Error ? error.message : String(error)}`
1384
+ );
1385
+ }
1386
+ try {
1387
+ plugins.push(...runtime.plugins?.map((p) => p.name) || []);
1388
+ } catch (error) {
1389
+ issues.push(
1390
+ `Plugins not accessible: ${error instanceof Error ? error.message : String(error)}`
1391
+ );
1392
+ }
1393
+ return {
1394
+ healthy: issues.length === 0,
1395
+ issues,
1396
+ services,
1397
+ plugins
1398
+ };
1399
+ } catch (error) {
1400
+ return {
1401
+ healthy: false,
1402
+ issues: [
1403
+ `Runtime health check failed: ${error instanceof Error ? error.message : String(error)}`
1404
+ ],
1405
+ services,
1406
+ plugins
1407
+ };
1408
+ }
1409
+ }
1410
+ /**
1411
+ * Cleanup all test resources
1412
+ */
1413
+ async cleanup() {
1414
+ try {
1415
+ logger3.info(`Cleaning up test harness ${this.testId}`);
1416
+ for (const [runtimeId, runtime] of this.runtimes) {
1417
+ try {
1418
+ await runtime.stop();
1419
+ logger3.debug(`Stopped runtime ${runtimeId}`);
1420
+ } catch (error) {
1421
+ logger3.warn(
1422
+ `Error stopping runtime ${runtimeId}: ${error instanceof Error ? error.message : String(error)}`
1423
+ );
1424
+ }
1425
+ }
1426
+ this.runtimes.clear();
1427
+ await this.databaseManager.cleanup();
1428
+ logger3.info(`Successfully cleaned up test harness ${this.testId}`);
1429
+ } catch (error) {
1430
+ logger3.error(
1431
+ `Error during cleanup: ${error instanceof Error ? error.message : String(error)}`
1432
+ );
1433
+ throw error;
1434
+ }
1435
+ }
1436
+ };
1437
+ async function createTestRuntime(config = {}) {
1438
+ const harness = new RuntimeTestHarness();
1439
+ const defaultCharacter = {
1440
+ name: "TestAgent",
1441
+ system: "You are a helpful test agent.",
1442
+ bio: ["I am a test agent used for integration testing."],
1443
+ messageExamples: [],
1444
+ postExamples: [],
1445
+ topics: ["testing"],
1446
+ knowledge: [],
1447
+ plugins: []
1448
+ };
1449
+ const runtime = await harness.createTestRuntime({
1450
+ character: defaultCharacter,
1451
+ plugins: [],
1452
+ apiKeys: { OPENAI_API_KEY: "test-key" },
1453
+ ...config
1454
+ });
1455
+ return { runtime, harness };
1456
+ }
1457
+ async function runIntegrationTest(testName, testFn, config) {
1458
+ const startTime = Date.now();
1459
+ let harness;
1460
+ try {
1461
+ const { runtime, harness: testHarness } = await createTestRuntime(config);
1462
+ harness = testHarness;
1463
+ await testFn(runtime);
1464
+ return {
1465
+ scenarioName: testName,
1466
+ passed: true,
1467
+ errors: [],
1468
+ executedActions: [],
1469
+ createdMemories: 0,
1470
+ responseTime: Date.now() - startTime
1471
+ };
1472
+ } catch (error) {
1473
+ return {
1474
+ scenarioName: testName,
1475
+ passed: false,
1476
+ errors: [error instanceof Error ? error.message : String(error)],
1477
+ executedActions: [],
1478
+ createdMemories: 0,
1479
+ responseTime: Date.now() - startTime
1480
+ };
1481
+ } finally {
1482
+ if (harness) {
1483
+ await harness.cleanup();
1484
+ }
1485
+ }
1486
+ }
1487
+
1488
+ // src/templates.ts
1489
+ import { logger as logger4 } from "@elizaos/core";
1490
+ var TestTemplate = class {
1491
+ config;
1492
+ runtime;
1493
+ constructor(config) {
1494
+ this.config = config;
1495
+ }
1496
+ async setup() {
1497
+ if (this.config.setup) {
1498
+ await this.config.setup();
1499
+ }
1500
+ }
1501
+ async teardown() {
1502
+ if (this.config.teardown) {
1503
+ await this.config.teardown();
1504
+ }
1505
+ }
1506
+ shouldSkip() {
1507
+ return this.config.skipCondition?.() ?? false;
1508
+ }
1509
+ getConfig() {
1510
+ return this.config;
1511
+ }
1512
+ };
1513
+ var UnitTestTemplate = class extends TestTemplate {
1514
+ testFunction;
1515
+ constructor(config, testFunction) {
1516
+ super(config);
1517
+ this.testFunction = testFunction;
1518
+ }
1519
+ async execute() {
1520
+ const startTime = Date.now();
1521
+ if (this.shouldSkip()) {
1522
+ return {
1523
+ name: this.config.name,
1524
+ passed: true,
1525
+ duration: 0,
1526
+ warnings: ["Test skipped due to skip condition"]
1527
+ };
1528
+ }
1529
+ try {
1530
+ await this.setup();
1531
+ await this.testFunction();
1532
+ return {
1533
+ name: this.config.name,
1534
+ passed: true,
1535
+ duration: Date.now() - startTime
1536
+ };
1537
+ } catch (error) {
1538
+ return {
1539
+ name: this.config.name,
1540
+ passed: false,
1541
+ duration: Date.now() - startTime,
1542
+ error: error instanceof Error ? error : new Error(String(error))
1543
+ };
1544
+ } finally {
1545
+ await this.teardown();
1546
+ }
1547
+ }
1548
+ };
1549
+ var IntegrationTestTemplate = class extends TestTemplate {
1550
+ testFunction;
1551
+ character;
1552
+ constructor(config, testFunction, character) {
1553
+ super(config);
1554
+ this.testFunction = testFunction;
1555
+ this.character = character;
1556
+ }
1557
+ async execute() {
1558
+ const startTime = Date.now();
1559
+ if (this.shouldSkip()) {
1560
+ return {
1561
+ name: this.config.name,
1562
+ passed: true,
1563
+ duration: 0,
1564
+ warnings: ["Test skipped due to skip condition"]
1565
+ };
1566
+ }
1567
+ try {
1568
+ await this.setup();
1569
+ const { runtime } = await createTestRuntime({
1570
+ character: this.character
1571
+ });
1572
+ this.runtime = runtime;
1573
+ await this.testFunction(runtime);
1574
+ return {
1575
+ name: this.config.name,
1576
+ passed: true,
1577
+ duration: Date.now() - startTime
1578
+ };
1579
+ } catch (error) {
1580
+ return {
1581
+ name: this.config.name,
1582
+ passed: false,
1583
+ duration: Date.now() - startTime,
1584
+ error: error instanceof Error ? error : new Error(String(error))
1585
+ };
1586
+ } finally {
1587
+ await this.teardown();
1588
+ }
1589
+ }
1590
+ };
1591
+ var PluginTestTemplate = class extends TestTemplate {
1592
+ plugin;
1593
+ testFunction;
1594
+ constructor(config, plugin, testFunction) {
1595
+ super(config);
1596
+ this.plugin = plugin;
1597
+ this.testFunction = testFunction;
1598
+ }
1599
+ async execute() {
1600
+ const startTime = Date.now();
1601
+ if (this.shouldSkip()) {
1602
+ return {
1603
+ name: this.config.name,
1604
+ passed: true,
1605
+ duration: 0,
1606
+ warnings: ["Test skipped due to skip condition"]
1607
+ };
1608
+ }
1609
+ try {
1610
+ await this.setup();
1611
+ const { runtime } = await createTestRuntime({
1612
+ character: {
1613
+ name: "Test Agent",
1614
+ bio: "Test agent for plugin testing",
1615
+ plugins: [this.plugin.name]
1616
+ },
1617
+ plugins: [this.plugin]
1618
+ });
1619
+ await this.testFunction(runtime, this.plugin);
1620
+ return {
1621
+ name: this.config.name,
1622
+ passed: true,
1623
+ duration: Date.now() - startTime
1624
+ };
1625
+ } catch (error) {
1626
+ return {
1627
+ name: this.config.name,
1628
+ passed: false,
1629
+ duration: Date.now() - startTime,
1630
+ error: error instanceof Error ? error : new Error(String(error))
1631
+ };
1632
+ } finally {
1633
+ await this.teardown();
1634
+ }
1635
+ }
1636
+ };
1637
+ var ErrorTestTemplate = class extends TestTemplate {
1638
+ testFunction;
1639
+ expectedError;
1640
+ constructor(config, testFunction, expectedError) {
1641
+ super(config);
1642
+ this.testFunction = testFunction;
1643
+ this.expectedError = expectedError;
1644
+ }
1645
+ async execute() {
1646
+ const startTime = Date.now();
1647
+ if (this.shouldSkip()) {
1648
+ return {
1649
+ name: this.config.name,
1650
+ passed: true,
1651
+ duration: 0,
1652
+ warnings: ["Test skipped due to skip condition"]
1653
+ };
1654
+ }
1655
+ try {
1656
+ await this.setup();
1657
+ await this.testFunction();
1658
+ return {
1659
+ name: this.config.name,
1660
+ passed: false,
1661
+ duration: Date.now() - startTime,
1662
+ error: new Error(`Expected ${this.expectedError} error but test completed successfully`)
1663
+ };
1664
+ } catch (error) {
1665
+ const passed = error.category === this.expectedError;
1666
+ return {
1667
+ name: this.config.name,
1668
+ passed,
1669
+ duration: Date.now() - startTime,
1670
+ error: passed ? void 0 : error instanceof Error ? error : new Error(String(error))
1671
+ };
1672
+ } finally {
1673
+ await this.teardown();
1674
+ }
1675
+ }
1676
+ };
1677
+ var PerformanceTestTemplate = class extends TestTemplate {
1678
+ testFunction;
1679
+ maxDuration;
1680
+ maxMemoryMB;
1681
+ constructor(config, testFunction, maxDuration, maxMemoryMB) {
1682
+ super(config);
1683
+ this.testFunction = testFunction;
1684
+ this.maxDuration = maxDuration;
1685
+ this.maxMemoryMB = maxMemoryMB;
1686
+ }
1687
+ async execute() {
1688
+ const startTime = Date.now();
1689
+ const startMemory = process.memoryUsage().heapUsed;
1690
+ if (this.shouldSkip()) {
1691
+ return {
1692
+ name: this.config.name,
1693
+ passed: true,
1694
+ duration: 0,
1695
+ warnings: ["Test skipped due to skip condition"]
1696
+ };
1697
+ }
1698
+ try {
1699
+ await this.setup();
1700
+ await this.testFunction();
1701
+ const duration = Date.now() - startTime;
1702
+ const memoryUsed = (process.memoryUsage().heapUsed - startMemory) / (1024 * 1024);
1703
+ const warnings = [];
1704
+ let passed = true;
1705
+ if (duration > this.maxDuration) {
1706
+ warnings.push(`Test exceeded max duration: ${duration}ms > ${this.maxDuration}ms`);
1707
+ passed = false;
1708
+ }
1709
+ if (memoryUsed > this.maxMemoryMB) {
1710
+ warnings.push(
1711
+ `Test exceeded max memory: ${memoryUsed.toFixed(2)}MB > ${this.maxMemoryMB}MB`
1712
+ );
1713
+ passed = false;
1714
+ }
1715
+ return {
1716
+ name: this.config.name,
1717
+ passed,
1718
+ duration,
1719
+ warnings,
1720
+ metadata: {
1721
+ memoryUsedMB: memoryUsed,
1722
+ maxDurationMs: this.maxDuration,
1723
+ maxMemoryMB: this.maxMemoryMB
1724
+ }
1725
+ };
1726
+ } catch (error) {
1727
+ return {
1728
+ name: this.config.name,
1729
+ passed: false,
1730
+ duration: Date.now() - startTime,
1731
+ error: error instanceof Error ? error : new Error(String(error))
1732
+ };
1733
+ } finally {
1734
+ await this.teardown();
1735
+ }
1736
+ }
1737
+ };
1738
+ var TestSuite = class {
1739
+ tests = [];
1740
+ name;
1741
+ constructor(name) {
1742
+ this.name = name;
1743
+ }
1744
+ addTest(test) {
1745
+ this.tests.push(test);
1746
+ }
1747
+ async run() {
1748
+ const startTime = Date.now();
1749
+ const results = [];
1750
+ logger4.info(`Running test suite: ${this.name}`);
1751
+ for (const test of this.tests) {
1752
+ try {
1753
+ const result = await test.execute();
1754
+ results.push(result);
1755
+ if (result.passed) {
1756
+ logger4.info(`\u2713 ${result.name} (${result.duration}ms)`);
1757
+ } else {
1758
+ logger4.error(`\u2717 ${result.name} (${result.duration}ms): ${result.error?.message}`);
1759
+ }
1760
+ } catch (error) {
1761
+ const errorResult = {
1762
+ name: `${test.getConfig().name} (execution error)`,
1763
+ passed: false,
1764
+ duration: 0,
1765
+ error: error instanceof Error ? error : new Error(String(error))
1766
+ };
1767
+ results.push(errorResult);
1768
+ logger4.error(`\u2717 ${errorResult.name}: ${errorResult.error?.message}`);
1769
+ }
1770
+ }
1771
+ const passed = results.filter((r) => r.passed).length;
1772
+ const failed = results.length - passed;
1773
+ const duration = Date.now() - startTime;
1774
+ logger4.info(
1775
+ `Test suite ${this.name} completed: ${passed}/${results.length} passed (${duration}ms)`
1776
+ );
1777
+ return {
1778
+ suiteName: this.name,
1779
+ totalTests: results.length,
1780
+ passed,
1781
+ failed,
1782
+ duration,
1783
+ results
1784
+ };
1785
+ }
1786
+ };
1787
+ function createUnitTest(name, testFunction, options = {}) {
1788
+ return new UnitTestTemplate({ name, timeout: 5e3, ...options }, testFunction);
1789
+ }
1790
+ function createIntegrationTest(name, testFunction, character, options = {}) {
1791
+ return new IntegrationTestTemplate({ name, timeout: 3e4, ...options }, testFunction, character);
1792
+ }
1793
+ function createPluginTest(name, plugin, testFunction, options = {}) {
1794
+ return new PluginTestTemplate({ name, timeout: 3e4, ...options }, plugin, testFunction);
1795
+ }
1796
+ function createErrorTest(name, testFunction, expectedError, options = {}) {
1797
+ return new ErrorTestTemplate({ name, timeout: 5e3, ...options }, testFunction, expectedError);
1798
+ }
1799
+ function createPerformanceTest(name, testFunction, maxDurationMs, maxMemoryMB, options = {}) {
1800
+ return new PerformanceTestTemplate(
1801
+ { name, timeout: maxDurationMs * 2, ...options },
1802
+ testFunction,
1803
+ maxDurationMs,
1804
+ maxMemoryMB
1805
+ );
1806
+ }
1807
+ var TestDataGenerator = class {
1808
+ static generateUUID() {
1809
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
1810
+ const r = Math.random() * 16 | 0;
1811
+ const v = c === "x" ? r : r & 3 | 8;
1812
+ return v.toString(16);
1813
+ });
1814
+ }
1815
+ static generateMemory(overrides = {}) {
1816
+ return {
1817
+ id: this.generateUUID(),
1818
+ entityId: this.generateUUID(),
1819
+ agentId: this.generateUUID(),
1820
+ roomId: this.generateUUID(),
1821
+ content: {
1822
+ text: "Test message content",
1823
+ source: "test"
1824
+ },
1825
+ ...overrides
1826
+ };
1827
+ }
1828
+ static generateCharacter(overrides = {}) {
1829
+ return {
1830
+ name: "Test Agent",
1831
+ bio: "A test agent for automated testing",
1832
+ ...overrides
1833
+ };
1834
+ }
1835
+ static generateContent(overrides = {}) {
1836
+ return {
1837
+ text: "Test content",
1838
+ source: "test",
1839
+ ...overrides
1840
+ };
1841
+ }
1842
+ };
1843
+
1844
+ // src/mocks/mockUtils.ts
1845
+ function mock(implementation) {
1846
+ const calls = [];
1847
+ let mockImplementationFn = implementation;
1848
+ let mockReturnValueValue;
1849
+ let mockResolvedValueValue;
1850
+ let mockRejectedValueValue;
1851
+ let shouldResolve = false;
1852
+ let shouldReject = false;
1853
+ const fn = function(...args) {
1854
+ calls.push(args);
1855
+ if (mockImplementationFn) {
1856
+ return mockImplementationFn(...args);
1857
+ }
1858
+ if (shouldReject) {
1859
+ return Promise.reject(mockRejectedValueValue);
1860
+ }
1861
+ if (shouldResolve) {
1862
+ return Promise.resolve(mockResolvedValueValue);
1863
+ }
1864
+ return mockReturnValueValue;
1865
+ };
1866
+ fn.calls = calls;
1867
+ fn.mock = {
1868
+ calls,
1869
+ results: []
1870
+ };
1871
+ fn.mockReturnValue = (value) => {
1872
+ mockReturnValueValue = value;
1873
+ shouldResolve = false;
1874
+ shouldReject = false;
1875
+ return fn;
1876
+ };
1877
+ fn.mockResolvedValue = (value) => {
1878
+ mockResolvedValueValue = value;
1879
+ shouldResolve = true;
1880
+ shouldReject = false;
1881
+ return fn;
1882
+ };
1883
+ fn.mockRejectedValue = (error) => {
1884
+ mockRejectedValueValue = error;
1885
+ shouldReject = true;
1886
+ shouldResolve = false;
1887
+ return fn;
1888
+ };
1889
+ fn.mockImplementation = (implementation2) => {
1890
+ mockImplementationFn = implementation2;
1891
+ return fn;
1892
+ };
1893
+ return fn;
1894
+ }
1895
+
1896
+ // src/mocks/runtime.ts
1897
+ function createMockRuntime(overrides = {}) {
1898
+ const defaultCharacter = {
1899
+ id: "test-character-id",
1900
+ name: "Test Character",
1901
+ username: "test_character",
1902
+ system: "You are a helpful test assistant.",
1903
+ bio: ["A character designed for testing purposes"],
1904
+ messageExamples: [],
1905
+ postExamples: [],
1906
+ topics: ["testing", "development"],
1907
+ knowledge: [],
1908
+ plugins: [],
1909
+ settings: {
1910
+ model: "gpt-4",
1911
+ secrets: {}
1912
+ },
1913
+ style: {
1914
+ all: ["be helpful", "be concise"],
1915
+ chat: ["respond quickly"],
1916
+ post: ["be engaging"]
1917
+ }
1918
+ };
1919
+ const mockDb = {
1920
+ execute: mock().mockResolvedValue([]),
1921
+ query: mock().mockResolvedValue([]),
1922
+ run: mock().mockResolvedValue({ changes: 1 }),
1923
+ all: mock().mockResolvedValue([]),
1924
+ get: mock().mockResolvedValue(null)
1925
+ };
1926
+ const baseRuntime = {
1927
+ // Core Properties
1928
+ agentId: "test-agent-id",
1929
+ character: overrides.character || defaultCharacter,
1930
+ providers: overrides.providers || [],
1931
+ actions: overrides.actions || [],
1932
+ evaluators: overrides.evaluators || [],
1933
+ plugins: overrides.plugins || [],
1934
+ services: overrides.services || /* @__PURE__ */ new Map(),
1935
+ events: overrides.events || /* @__PURE__ */ new Map(),
1936
+ fetch: overrides.fetch || null,
1937
+ routes: overrides.routes || [],
1938
+ // Database Properties
1939
+ db: overrides.db || mockDb,
1940
+ // Core Runtime Methods
1941
+ registerPlugin: mock().mockResolvedValue(void 0),
1942
+ initialize: mock().mockResolvedValue(void 0),
1943
+ getConnection: mock().mockResolvedValue(mockDb),
1944
+ getService: mock().mockReturnValue(null),
1945
+ getAllServices: mock().mockReturnValue(/* @__PURE__ */ new Map()),
1946
+ registerService: mock().mockResolvedValue(void 0),
1947
+ registerDatabaseAdapter: mock(),
1948
+ setSetting: mock(),
1949
+ getSetting: mock((key) => {
1950
+ const defaultSettings = {
1951
+ TEST_API_KEY: "test-api-key",
1952
+ ...overrides.character?.settings
1953
+ };
1954
+ return defaultSettings[key];
1955
+ }),
1956
+ getConversationLength: mock().mockReturnValue(10),
1957
+ processActions: mock().mockResolvedValue(void 0),
1958
+ evaluate: mock().mockResolvedValue([]),
1959
+ registerProvider: mock(),
1960
+ registerAction: mock(),
1961
+ registerEvaluator: mock(),
1962
+ ensureConnection: mock().mockResolvedValue(void 0),
1963
+ ensureConnections: mock().mockResolvedValue(void 0),
1964
+ ensureParticipantInRoom: mock().mockResolvedValue(void 0),
1965
+ ensureWorldExists: mock().mockResolvedValue(void 0),
1966
+ ensureRoomExists: mock().mockResolvedValue(void 0),
1967
+ composeState: mock().mockResolvedValue({
1968
+ values: {},
1969
+ data: {},
1970
+ text: ""
1971
+ }),
1972
+ useModel: mock().mockResolvedValue("Mock response"),
1973
+ registerModel: mock(),
1974
+ getModel: mock().mockReturnValue(void 0),
1975
+ registerEvent: mock(),
1976
+ getEvent: mock().mockReturnValue(void 0),
1977
+ emitEvent: mock().mockResolvedValue(void 0),
1978
+ registerTaskWorker: mock(),
1979
+ getTaskWorker: mock().mockReturnValue(void 0),
1980
+ stop: mock().mockResolvedValue(void 0),
1981
+ addEmbeddingToMemory: mock().mockImplementation((memory) => Promise.resolve(memory)),
1982
+ createRunId: mock().mockReturnValue("test-run-id"),
1983
+ startRun: mock().mockReturnValue("test-run-id"),
1984
+ endRun: mock(),
1985
+ getCurrentRunId: mock().mockReturnValue("test-run-id"),
1986
+ registerSendHandler: mock(),
1987
+ sendMessageToTarget: mock().mockResolvedValue(void 0),
1988
+ // Database Adapter Methods - Agent Management
1989
+ init: mock().mockResolvedValue(void 0),
1990
+ isReady: mock().mockResolvedValue(true),
1991
+ runMigrations: mock().mockResolvedValue(void 0),
1992
+ close: mock().mockResolvedValue(void 0),
1993
+ getAgent: mock().mockResolvedValue(null),
1994
+ getAgents: mock().mockResolvedValue([]),
1995
+ createAgent: mock().mockResolvedValue(true),
1996
+ updateAgent: mock().mockResolvedValue(true),
1997
+ deleteAgent: mock().mockResolvedValue(true),
1998
+ // Entity Management
1999
+ getEntityById: mock().mockResolvedValue(null),
2000
+ getEntitiesByIds: mock().mockResolvedValue([]),
2001
+ getEntitiesForRoom: mock().mockResolvedValue([]),
2002
+ createEntity: mock().mockResolvedValue("test-entity-id"),
2003
+ createEntities: mock().mockResolvedValue(true),
2004
+ updateEntity: mock().mockResolvedValue(void 0),
2005
+ // Component Management
2006
+ getComponent: mock().mockResolvedValue(null),
2007
+ getComponents: mock().mockResolvedValue([]),
2008
+ createComponent: mock().mockResolvedValue("test-component-id"),
2009
+ updateComponent: mock().mockResolvedValue(void 0),
2010
+ deleteComponent: mock().mockResolvedValue(void 0),
2011
+ // Memory Management
2012
+ getMemories: mock().mockResolvedValue([]),
2013
+ getAllMemories: overrides.getAllMemories || mock().mockResolvedValue([]),
2014
+ clearAllAgentMemories: mock().mockResolvedValue(void 0),
2015
+ getMemoryById: mock().mockResolvedValue(null),
2016
+ getMemoriesByIds: mock().mockResolvedValue([]),
2017
+ getMemoriesByRoomIds: mock().mockResolvedValue([]),
2018
+ getMemoriesByWorldId: mock().mockResolvedValue([]),
2019
+ getCachedEmbeddings: mock().mockResolvedValue([]),
2020
+ log: mock().mockResolvedValue(void 0),
2021
+ getLogs: mock().mockResolvedValue([]),
2022
+ deleteLog: mock().mockResolvedValue(void 0),
2023
+ searchMemories: mock().mockResolvedValue([]),
2024
+ createMemory: mock().mockResolvedValue("test-memory-id"),
2025
+ updateMemory: mock().mockResolvedValue(true),
2026
+ deleteMemory: mock().mockResolvedValue(void 0),
2027
+ deleteManyMemories: mock().mockResolvedValue(void 0),
2028
+ deleteAllMemories: mock().mockResolvedValue(void 0),
2029
+ countMemories: mock().mockResolvedValue(0),
2030
+ ensureEmbeddingDimension: mock().mockResolvedValue(void 0),
2031
+ // World Management
2032
+ createWorld: mock().mockResolvedValue("test-world-id"),
2033
+ getWorld: mock().mockResolvedValue(null),
2034
+ removeWorld: mock().mockResolvedValue(void 0),
2035
+ getAllWorlds: mock().mockResolvedValue([]),
2036
+ updateWorld: mock().mockResolvedValue(void 0),
2037
+ // Room Management
2038
+ getRoom: mock().mockResolvedValue(null),
2039
+ getRooms: mock().mockResolvedValue([]),
2040
+ getRoomsByIds: mock().mockResolvedValue([]),
2041
+ createRoom: mock().mockResolvedValue("test-room-id"),
2042
+ createRooms: mock().mockResolvedValue([]),
2043
+ deleteRoom: mock().mockResolvedValue(void 0),
2044
+ deleteRoomsByWorldId: mock().mockResolvedValue(void 0),
2045
+ updateRoom: mock().mockResolvedValue(void 0),
2046
+ getRoomsForParticipant: mock().mockResolvedValue([]),
2047
+ getRoomsForParticipants: mock().mockResolvedValue([]),
2048
+ getRoomsByWorld: mock().mockResolvedValue([]),
2049
+ // Participant Management
2050
+ addParticipant: mock().mockResolvedValue(true),
2051
+ removeParticipant: mock().mockResolvedValue(true),
2052
+ addParticipantsRoom: mock().mockResolvedValue(true),
2053
+ getParticipantsForEntity: mock().mockResolvedValue([]),
2054
+ getParticipantsForRoom: mock().mockResolvedValue([]),
2055
+ getParticipantUserState: mock().mockResolvedValue(null),
2056
+ setParticipantUserState: mock().mockResolvedValue(void 0),
2057
+ // Relationship Management
2058
+ createRelationship: mock().mockResolvedValue(true),
2059
+ updateRelationship: mock().mockResolvedValue(void 0),
2060
+ getRelationship: mock().mockResolvedValue(null),
2061
+ getRelationships: mock().mockResolvedValue([]),
2062
+ // Cache Management
2063
+ getCache: mock().mockResolvedValue(void 0),
2064
+ setCache: mock().mockResolvedValue(true),
2065
+ deleteCache: mock().mockResolvedValue(true),
2066
+ // Task Management
2067
+ createTask: mock().mockResolvedValue("test-task-id"),
2068
+ getTasks: mock().mockResolvedValue([]),
2069
+ getTask: mock().mockResolvedValue(null),
2070
+ getTasksByName: mock().mockResolvedValue([]),
2071
+ updateTask: mock().mockResolvedValue(void 0),
2072
+ deleteTask: mock().mockResolvedValue(void 0),
2073
+ // Apply overrides
2074
+ ...overrides
2075
+ };
2076
+ return baseRuntime;
2077
+ }
2078
+
2079
+ // src/mocks/memory.ts
2080
+ import { ContentType } from "@elizaos/core";
2081
+ function createMockMemory(overrides = {}) {
2082
+ const defaultContent = {
2083
+ text: "Test message content",
2084
+ source: "test",
2085
+ ...overrides.content
2086
+ };
2087
+ const defaultMetadata = {
2088
+ type: "message",
2089
+ source: "test",
2090
+ timestamp: Date.now(),
2091
+ ...overrides.metadata
2092
+ };
2093
+ const baseMemory = {
2094
+ id: "test-memory-id",
2095
+ entityId: "test-entity-id",
2096
+ agentId: "test-agent-id",
2097
+ roomId: "test-room-id",
2098
+ worldId: "test-world-id",
2099
+ content: defaultContent,
2100
+ embedding: void 0,
2101
+ createdAt: Date.now(),
2102
+ unique: true,
2103
+ similarity: 1,
2104
+ metadata: defaultMetadata,
2105
+ ...overrides
2106
+ };
2107
+ return baseMemory;
2108
+ }
2109
+ function createMockContent(overrides = {}) {
2110
+ const baseContent = {
2111
+ text: "Mock content text",
2112
+ thought: "Mock internal thought",
2113
+ actions: [],
2114
+ providers: [],
2115
+ source: "test",
2116
+ target: void 0,
2117
+ url: void 0,
2118
+ inReplyTo: void 0,
2119
+ attachments: [],
2120
+ channelType: "DM",
2121
+ ...overrides
2122
+ };
2123
+ return baseContent;
2124
+ }
2125
+ function createMockUserMessage(text, overrides = {}) {
2126
+ return createMockMemory({
2127
+ content: {
2128
+ text,
2129
+ source: "user"
2130
+ },
2131
+ metadata: {
2132
+ type: "message",
2133
+ source: "user"
2134
+ },
2135
+ ...overrides
2136
+ });
2137
+ }
2138
+ function createMockAgentResponse(text, thought, actions = [], overrides = {}) {
2139
+ return createMockMemory({
2140
+ entityId: "test-agent-id",
2141
+ content: {
2142
+ text,
2143
+ thought,
2144
+ actions,
2145
+ source: "agent"
2146
+ },
2147
+ metadata: {
2148
+ type: "message",
2149
+ source: "agent"
2150
+ },
2151
+ ...overrides
2152
+ });
2153
+ }
2154
+ function createMockFact(fact, confidence = 0.9, overrides = {}) {
2155
+ return createMockMemory({
2156
+ content: {
2157
+ text: fact,
2158
+ source: "fact_extraction"
2159
+ },
2160
+ metadata: {
2161
+ type: "fact",
2162
+ confidence,
2163
+ source: "evaluator"
2164
+ },
2165
+ ...overrides
2166
+ });
2167
+ }
2168
+ function createMockMemoryWithEmbedding(text, dimension = 1536, overrides = {}) {
2169
+ const embedding = new Array(dimension).fill(0).map(() => Math.random());
2170
+ return createMockMemory({
2171
+ content: { text },
2172
+ embedding,
2173
+ ...overrides
2174
+ });
2175
+ }
2176
+ function createMockConversation(count = 5, roomId) {
2177
+ const memories = [];
2178
+ const actualRoomId = roomId || "test-room-id";
2179
+ for (let i = 0; i < count; i++) {
2180
+ const isUserMessage = i % 2 === 0;
2181
+ const memory = isUserMessage ? createMockUserMessage(`User message ${i + 1}`, { roomId: actualRoomId }) : createMockAgentResponse(`Agent response ${i + 1}`, `Thinking about response ${i + 1}`, [], {
2182
+ roomId: actualRoomId
2183
+ });
2184
+ memory.createdAt = Date.now() - (count - i) * 1e3;
2185
+ memories.push(memory);
2186
+ }
2187
+ return memories;
2188
+ }
2189
+ function createMockMedia(type = "image", url = "https://example.com/test.jpg", overrides = {}) {
2190
+ const baseContentTypes = {
2191
+ image: ContentType.IMAGE,
2192
+ video: ContentType.VIDEO,
2193
+ audio: ContentType.AUDIO,
2194
+ document: ContentType.DOCUMENT
2195
+ };
2196
+ return {
2197
+ id: "test-media-id",
2198
+ url,
2199
+ title: `Test ${type}`,
2200
+ source: "test",
2201
+ description: `Mock ${type} for testing`,
2202
+ text: `Alt text for ${type}`,
2203
+ contentType: baseContentTypes[type],
2204
+ ...overrides
2205
+ };
2206
+ }
2207
+
2208
+ // src/mocks/state.ts
2209
+ function createMockState(overrides = {}) {
2210
+ const baseState = {
2211
+ // Core state properties
2212
+ values: {
2213
+ currentTime: (/* @__PURE__ */ new Date()).toISOString(),
2214
+ agentName: "Test Agent",
2215
+ roomId: "test-room-id",
2216
+ entityId: "test-entity-id",
2217
+ userName: "TestUser",
2218
+ conversationLength: 10,
2219
+ lastMessage: "Hello, how can I help you?",
2220
+ ...overrides.values
2221
+ },
2222
+ data: {
2223
+ providers: {
2224
+ TIME: { currentTime: (/* @__PURE__ */ new Date()).toISOString() },
2225
+ CHARACTER: { agentName: "Test Agent", bio: "A helpful test assistant" },
2226
+ RECENT_MESSAGES: { messageCount: 5, lastSpeaker: "user" }
2227
+ },
2228
+ actionResults: [],
2229
+ context: "test conversation",
2230
+ ...overrides.data
2231
+ },
2232
+ text: `[CONTEXT]
2233
+ Current Time: ${(/* @__PURE__ */ new Date()).toISOString()}
2234
+ Agent: Test Agent
2235
+ User: TestUser
2236
+ Room: test-room-id
2237
+ Recent conversation context available.
2238
+ [/CONTEXT]`,
2239
+ // Additional properties that might be added dynamically
2240
+ ...overrides
2241
+ };
2242
+ if (overrides.text) {
2243
+ baseState.text = overrides.text;
2244
+ }
2245
+ return baseState;
2246
+ }
2247
+ function createMockProviderResult(overrides = {}) {
2248
+ const baseResult = {
2249
+ values: {
2250
+ mockValue: "test-value",
2251
+ timestamp: Date.now(),
2252
+ ...overrides.values
2253
+ },
2254
+ data: {
2255
+ source: "mock-provider",
2256
+ processed: true,
2257
+ ...overrides.data
2258
+ },
2259
+ text: "[MOCK PROVIDER]\nMock provider context information\n[/MOCK PROVIDER]",
2260
+ ...overrides
2261
+ };
2262
+ return baseResult;
2263
+ }
2264
+ function createMockActionResult(overrides = {}) {
2265
+ const baseResult = {
2266
+ success: true,
2267
+ values: {
2268
+ success: true,
2269
+ actionId: "test-action-id",
2270
+ timestamp: Date.now(),
2271
+ ...overrides.values
2272
+ },
2273
+ data: {
2274
+ executionTime: 150,
2275
+ metadata: { source: "mock-action" },
2276
+ ...overrides.data
2277
+ },
2278
+ text: "Mock action executed successfully",
2279
+ ...overrides
2280
+ };
2281
+ return baseResult;
2282
+ }
2283
+ function createMockStateWithProvider(providerName, providerData, overrides = {}) {
2284
+ return createMockState({
2285
+ data: {
2286
+ providers: {
2287
+ [providerName]: providerData,
2288
+ ...overrides.data?.providers
2289
+ },
2290
+ ...overrides.data
2291
+ },
2292
+ text: `[${providerName}]
2293
+ ${JSON.stringify(providerData, null, 2)}
2294
+ [/${providerName}]`,
2295
+ ...overrides
2296
+ });
2297
+ }
2298
+ function createMockStateWithActions(actionResults, overrides = {}) {
2299
+ return createMockState({
2300
+ data: {
2301
+ actionResults,
2302
+ ...overrides.data
2303
+ },
2304
+ values: {
2305
+ lastActionSuccess: actionResults.length > 0 ? actionResults[actionResults.length - 1].values?.success : void 0,
2306
+ actionCount: actionResults.length,
2307
+ ...overrides.values
2308
+ },
2309
+ ...overrides
2310
+ });
2311
+ }
2312
+ function createMockConversationState(conversationHistory = ["Hello", "Hi there!", "How are you?"], currentUser = "TestUser", overrides = {}) {
2313
+ const recentContext = conversationHistory.slice(-3).join(" | ");
2314
+ return createMockState({
2315
+ values: {
2316
+ userName: currentUser,
2317
+ conversationLength: conversationHistory.length,
2318
+ lastMessage: conversationHistory[conversationHistory.length - 1],
2319
+ recentContext,
2320
+ ...overrides.values
2321
+ },
2322
+ data: {
2323
+ providers: {
2324
+ RECENT_MESSAGES: {
2325
+ messages: conversationHistory,
2326
+ count: conversationHistory.length,
2327
+ lastSpeaker: conversationHistory.length % 2 === 0 ? "agent" : "user"
2328
+ },
2329
+ ...overrides.data?.providers
2330
+ },
2331
+ ...overrides.data
2332
+ },
2333
+ text: `[CONVERSATION CONTEXT]
2334
+ User: ${currentUser}
2335
+ Recent messages: ${recentContext}
2336
+ Message count: ${conversationHistory.length}
2337
+ [/CONVERSATION CONTEXT]`,
2338
+ ...overrides
2339
+ });
2340
+ }
2341
+
2342
+ // src/mocks/character.ts
2343
+ function createMockCharacter(overrides = {}) {
2344
+ const baseCharacter = {
2345
+ id: "test-character-id",
2346
+ name: "TestAgent",
2347
+ username: "test_agent",
2348
+ system: "You are a helpful test assistant designed for automated testing scenarios. Respond concisely and clearly.",
2349
+ bio: [
2350
+ "A test agent designed for comprehensive testing scenarios",
2351
+ "Provides consistent, predictable responses for test validation",
2352
+ "Supports all core ElizaOS features and plugin interactions",
2353
+ "Maintains conversation context and handles complex workflows",
2354
+ "Optimized for both unit and integration testing environments"
2355
+ ],
2356
+ messageExamples: [
2357
+ [
2358
+ {
2359
+ name: "{{user}}",
2360
+ content: {
2361
+ text: "Hello, how are you?"
2362
+ }
2363
+ },
2364
+ {
2365
+ name: "TestAgent",
2366
+ content: {
2367
+ text: "Hello! I'm doing well, thank you for asking. How can I help you today?"
2368
+ }
2369
+ }
2370
+ ],
2371
+ [
2372
+ {
2373
+ name: "{{user}}",
2374
+ content: {
2375
+ text: "Can you help me test this feature?"
2376
+ }
2377
+ },
2378
+ {
2379
+ name: "TestAgent",
2380
+ content: {
2381
+ text: "Absolutely! I'm designed specifically to help with testing. What feature would you like to test?"
2382
+ }
2383
+ }
2384
+ ],
2385
+ [
2386
+ {
2387
+ name: "{{user}}",
2388
+ content: {
2389
+ text: "What capabilities do you have?"
2390
+ }
2391
+ },
2392
+ {
2393
+ name: "TestAgent",
2394
+ content: {
2395
+ text: "I can assist with testing various ElizaOS features including actions, providers, services, and plugin functionality."
2396
+ }
2397
+ }
2398
+ ]
2399
+ ],
2400
+ postExamples: [
2401
+ "Testing new ElizaOS features today - everything looking good!",
2402
+ "Just validated another plugin integration - the ecosystem keeps growing",
2403
+ "Reminder: always test your agents thoroughly before deployment",
2404
+ "Quality assurance is key to reliable AI agent systems"
2405
+ ],
2406
+ topics: [
2407
+ "software testing",
2408
+ "quality assurance",
2409
+ "test automation",
2410
+ "agent behavior validation",
2411
+ "plugin integration",
2412
+ "system reliability",
2413
+ "debugging",
2414
+ "performance testing"
2415
+ ],
2416
+ knowledge: [
2417
+ "ElizaOS architecture and patterns",
2418
+ "Test-driven development practices",
2419
+ "Quality assurance methodologies",
2420
+ "Plugin system integration",
2421
+ "Agent behavior patterns",
2422
+ "Debugging and troubleshooting"
2423
+ ],
2424
+ plugins: ["@elizaos/plugin-sql", "@elizaos/plugin-bootstrap"],
2425
+ settings: {
2426
+ model: "gpt-4",
2427
+ temperature: 0.1,
2428
+ // Low temperature for consistent test responses
2429
+ maxTokens: 1e3,
2430
+ secrets: {},
2431
+ voice: {
2432
+ model: "en_US-hfc_female-medium"
2433
+ },
2434
+ embeddingModel: "text-embedding-ada-002",
2435
+ ...overrides.settings
2436
+ },
2437
+ secrets: {
2438
+ TEST_API_KEY: "test-api-key-value",
2439
+ MOCK_SECRET: "mock-secret-value",
2440
+ ...overrides.secrets
2441
+ },
2442
+ style: {
2443
+ all: [
2444
+ "be helpful and supportive",
2445
+ "provide clear and concise responses",
2446
+ "maintain professional tone",
2447
+ "focus on testing and quality assurance",
2448
+ "be thorough in explanations"
2449
+ ],
2450
+ chat: [
2451
+ "respond promptly",
2452
+ "ask clarifying questions when needed",
2453
+ "provide actionable guidance",
2454
+ "maintain conversational flow"
2455
+ ],
2456
+ post: [
2457
+ "share testing insights",
2458
+ "promote quality practices",
2459
+ "be informative and educational",
2460
+ "encourage best practices"
2461
+ ]
2462
+ },
2463
+ // Apply all overrides
2464
+ ...overrides
2465
+ };
2466
+ return baseCharacter;
2467
+ }
2468
+ function createMinimalMockCharacter(name = "MinimalTestAgent", overrides = {}) {
2469
+ return createMockCharacter({
2470
+ name,
2471
+ bio: [`${name} - A minimal test agent`],
2472
+ messageExamples: [
2473
+ [
2474
+ { name: "{{user}}", content: { text: "Hello" } },
2475
+ { name, content: { text: "Hi there!" } }
2476
+ ]
2477
+ ],
2478
+ topics: ["testing"],
2479
+ plugins: [],
2480
+ ...overrides
2481
+ });
2482
+ }
2483
+ function createPluginTestCharacter(pluginName, overrides = {}) {
2484
+ return createMockCharacter({
2485
+ name: `${pluginName}TestAgent`,
2486
+ bio: [`Agent designed to test ${pluginName} plugin functionality`],
2487
+ plugins: [pluginName],
2488
+ topics: [`${pluginName} testing`, "plugin integration"],
2489
+ knowledge: [`${pluginName} plugin documentation and usage`],
2490
+ ...overrides
2491
+ });
2492
+ }
2493
+ function createRichConversationCharacter(overrides = {}) {
2494
+ const additionalExamples = [
2495
+ [
2496
+ { name: "{{user}}", content: { text: "Can you perform an action?" } },
2497
+ {
2498
+ name: "TestAgent",
2499
+ content: {
2500
+ text: "I can perform various actions based on available plugins.",
2501
+ actions: ["TEST_ACTION"]
2502
+ }
2503
+ }
2504
+ ],
2505
+ [
2506
+ { name: "{{user}}", content: { text: "What do you think about that?" } },
2507
+ {
2508
+ name: "TestAgent",
2509
+ content: {
2510
+ text: "Based on our conversation, I think this is a good approach.",
2511
+ thought: "The user is asking for my analysis of the previous topic."
2512
+ }
2513
+ }
2514
+ ],
2515
+ [
2516
+ { name: "{{user}}", content: { text: "Remember this important fact: X equals Y" } },
2517
+ {
2518
+ name: "TestAgent",
2519
+ content: {
2520
+ text: "I'll remember that X equals Y. This has been noted for future reference."
2521
+ }
2522
+ }
2523
+ ]
2524
+ ];
2525
+ return createMockCharacter({
2526
+ messageExamples: [...createMockCharacter().messageExamples || [], ...additionalExamples],
2527
+ postExamples: [
2528
+ "Just had an interesting conversation about X and Y relationships",
2529
+ "Learning new facts every day through conversations",
2530
+ "Testing advanced conversation patterns",
2531
+ "Exploring the depths of agent-user interactions"
2532
+ ],
2533
+ ...overrides
2534
+ });
2535
+ }
2536
+ function createMultipleCharacters(count = 3, baseName = "TestAgent", overrides = {}) {
2537
+ const characters = [];
2538
+ for (let i = 1; i <= count; i++) {
2539
+ const character = createMockCharacter({
2540
+ name: `${baseName}${i}`,
2541
+ username: `${baseName.toLowerCase()}${i}`,
2542
+ id: `test-character-${i}-id`,
2543
+ bio: [`${baseName}${i} - Agent ${i} in a multi-agent test scenario`],
2544
+ ...overrides
2545
+ });
2546
+ characters.push(character);
2547
+ }
2548
+ return characters;
2549
+ }
2550
+
2551
+ // src/factories.ts
2552
+ function createTestEnvironment(options = {}) {
2553
+ const {
2554
+ characterName = "TestAgent",
2555
+ conversationLength = 5,
2556
+ roomId = "test-room-id",
2557
+ plugins = [],
2558
+ runtimeOverrides = {},
2559
+ characterOverrides = {}
2560
+ } = options;
2561
+ const character = createMockCharacter({
2562
+ name: characterName,
2563
+ plugins,
2564
+ ...characterOverrides
2565
+ });
2566
+ const runtime = createMockRuntime({
2567
+ character,
2568
+ ...runtimeOverrides
2569
+ });
2570
+ const conversation = createMockConversation(conversationLength, roomId);
2571
+ const state = createMockConversationState(
2572
+ conversation.map((m) => m.content.text || ""),
2573
+ "TestUser"
2574
+ );
2575
+ return {
2576
+ runtime,
2577
+ character,
2578
+ conversation,
2579
+ state,
2580
+ roomId
2581
+ };
2582
+ }
2583
+ function createTestAction(name, options = {}) {
2584
+ const {
2585
+ description = `Test action: ${name}`,
2586
+ validateResult = true,
2587
+ handlerResult = { text: `${name} executed successfully`, success: true },
2588
+ examples = []
2589
+ } = options;
2590
+ return {
2591
+ name,
2592
+ similes: [`${name.toLowerCase()}`, `${name.replace("_", " ").toLowerCase()}`],
2593
+ description,
2594
+ examples,
2595
+ validate: mock().mockResolvedValue(validateResult),
2596
+ handler: mock(
2597
+ async (runtime, message, state, options2, callback) => {
2598
+ if (callback) {
2599
+ await callback({
2600
+ text: handlerResult.text || `${name} action executed`,
2601
+ thought: `Executing ${name} action`,
2602
+ actions: [name]
2603
+ });
2604
+ }
2605
+ return handlerResult;
2606
+ }
2607
+ )
2608
+ };
2609
+ }
2610
+ function createTestProvider(name, options = {}) {
2611
+ const {
2612
+ description = `Test provider: ${name}`,
2613
+ text = `[${name}]
2614
+ Provider context information
2615
+ [/${name}]`,
2616
+ values = { [`${name.toLowerCase()}Data`]: "test-value" },
2617
+ data = { source: name, timestamp: Date.now() },
2618
+ dynamic = false,
2619
+ isPrivate = false
2620
+ } = options;
2621
+ return {
2622
+ name,
2623
+ description,
2624
+ dynamic,
2625
+ private: isPrivate,
2626
+ get: mock().mockResolvedValue({
2627
+ text,
2628
+ values,
2629
+ data
2630
+ })
2631
+ };
2632
+ }
2633
+ function createTestEvaluator(name, options = {}) {
2634
+ const {
2635
+ description = `Test evaluator: ${name}`,
2636
+ alwaysRun = false,
2637
+ validateResult = true,
2638
+ handlerResult = { success: true }
2639
+ } = options;
2640
+ return {
2641
+ name,
2642
+ description,
2643
+ alwaysRun,
2644
+ examples: [],
2645
+ validate: mock().mockResolvedValue(validateResult),
2646
+ handler: mock(async (_runtime, _message, _state) => {
2647
+ return handlerResult;
2648
+ })
2649
+ };
2650
+ }
2651
+ function createPluginTestScenario(pluginName, options = {}) {
2652
+ const {
2653
+ actions = ["TEST_ACTION"],
2654
+ providers = ["TEST_PROVIDER"],
2655
+ evaluators = ["TEST_EVALUATOR"],
2656
+ conversationSteps = ["Hello", "How can I test this plugin?"]
2657
+ } = options;
2658
+ const { runtime, character, state, roomId } = createTestEnvironment({
2659
+ characterName: `${pluginName}TestAgent`,
2660
+ plugins: [pluginName]
2661
+ });
2662
+ const testActions = actions.map((name) => createTestAction(name));
2663
+ const testProviders = providers.map((name) => createTestProvider(name));
2664
+ const testEvaluators = evaluators.map((name) => createTestEvaluator(name));
2665
+ const conversation = conversationSteps.map(
2666
+ (text, index) => createMockMemory({
2667
+ content: { text },
2668
+ entityId: index % 2 === 0 ? "user-id" : runtime.agentId,
2669
+ roomId
2670
+ })
2671
+ );
2672
+ return {
2673
+ runtime,
2674
+ character,
2675
+ state,
2676
+ roomId,
2677
+ conversation,
2678
+ components: {
2679
+ actions: testActions,
2680
+ providers: testProviders,
2681
+ evaluators: testEvaluators
2682
+ },
2683
+ // Helper methods for common test operations
2684
+ helpers: {
2685
+ executeAction: async (actionName, message) => {
2686
+ const action = testActions.find((a) => a.name === actionName);
2687
+ const testMessage = message || conversation[0];
2688
+ return action?.handler(runtime, testMessage, state);
2689
+ },
2690
+ getProviderData: async (providerName, message) => {
2691
+ const provider = testProviders.find((p) => p.name === providerName);
2692
+ const testMessage = message || conversation[0];
2693
+ return provider?.get(runtime, testMessage, state);
2694
+ },
2695
+ runEvaluator: async (evaluatorName, message) => {
2696
+ const evaluator = testEvaluators.find((e) => e.name === evaluatorName);
2697
+ const testMessage = message || conversation[0];
2698
+ return evaluator?.handler(runtime, testMessage, state);
2699
+ }
2700
+ }
2701
+ };
2702
+ }
2703
+ function createMultiAgentScenario(agentCount = 2, options = {}) {
2704
+ const {
2705
+ sharedRoomId = "shared-room-id",
2706
+ agentNames = Array.from({ length: agentCount }, (_, i) => `Agent${i + 1}`),
2707
+ conversationSteps = [
2708
+ { agentIndex: 0, message: "Hello from Agent 1" },
2709
+ { agentIndex: 1, message: "Hello from Agent 2" }
2710
+ ]
2711
+ } = options;
2712
+ const agents = agentNames.map((name, index) => {
2713
+ const { runtime, character } = createTestEnvironment({
2714
+ characterName: name,
2715
+ roomId: sharedRoomId
2716
+ });
2717
+ return { runtime, character, index };
2718
+ });
2719
+ const conversation = conversationSteps.map(
2720
+ (step) => createMockMemory({
2721
+ content: { text: step.message },
2722
+ entityId: agents[step.agentIndex].runtime.agentId,
2723
+ roomId: sharedRoomId
2724
+ })
2725
+ );
2726
+ return {
2727
+ agents,
2728
+ sharedRoomId,
2729
+ conversation,
2730
+ helpers: {
2731
+ sendMessage: (agentIndex, text) => {
2732
+ const message = createMockMemory({
2733
+ content: { text },
2734
+ entityId: agents[agentIndex].runtime.agentId,
2735
+ roomId: sharedRoomId
2736
+ });
2737
+ conversation.push(message);
2738
+ return message;
2739
+ },
2740
+ getAgentByName: (name) => {
2741
+ return agents.find((agent) => agent.character.name === name);
2742
+ }
2743
+ }
2744
+ };
2745
+ }
2746
+
2747
+ // src/mocks/database.ts
2748
+ function createMockDatabase(overrides = {}) {
2749
+ const mockConnection = {
2750
+ execute: mock().mockResolvedValue([]),
2751
+ query: mock().mockResolvedValue([]),
2752
+ run: mock().mockResolvedValue({ changes: 1 }),
2753
+ all: mock().mockResolvedValue([]),
2754
+ get: mock().mockResolvedValue(null)
2755
+ };
2756
+ const baseDatabaseAdapter = {
2757
+ // Core Database Properties
2758
+ db: overrides.db || mockConnection,
2759
+ // Core Lifecycle Methods
2760
+ init: mock().mockResolvedValue(void 0),
2761
+ initialize: mock().mockResolvedValue(void 0),
2762
+ isReady: mock().mockResolvedValue(true),
2763
+ runMigrations: mock().mockResolvedValue(void 0),
2764
+ close: mock().mockResolvedValue(void 0),
2765
+ getConnection: mock().mockResolvedValue(mockConnection),
2766
+ // Agent Management
2767
+ getAgent: mock().mockResolvedValue(null),
2768
+ getAgents: mock().mockResolvedValue([]),
2769
+ createAgent: mock().mockResolvedValue(true),
2770
+ updateAgent: mock().mockResolvedValue(true),
2771
+ deleteAgent: mock().mockResolvedValue(true),
2772
+ // Entity Management
2773
+ getEntitiesByIds: mock().mockResolvedValue([]),
2774
+ getEntitiesForRoom: mock().mockResolvedValue([]),
2775
+ createEntities: mock().mockResolvedValue(true),
2776
+ updateEntity: mock().mockResolvedValue(void 0),
2777
+ // Component Management
2778
+ getComponent: mock().mockResolvedValue(null),
2779
+ getComponents: mock().mockResolvedValue([]),
2780
+ createComponent: mock().mockResolvedValue(true),
2781
+ updateComponent: mock().mockResolvedValue(void 0),
2782
+ deleteComponent: mock().mockResolvedValue(void 0),
2783
+ // Memory Management
2784
+ getMemories: mock().mockResolvedValue([]),
2785
+ getMemoryById: mock().mockResolvedValue(null),
2786
+ getMemoriesByIds: mock().mockResolvedValue([]),
2787
+ getMemoriesByRoomIds: mock().mockResolvedValue([]),
2788
+ getMemoriesByWorldId: mock().mockResolvedValue([]),
2789
+ getCachedEmbeddings: mock().mockResolvedValue([]),
2790
+ searchMemories: mock().mockResolvedValue([]),
2791
+ createMemory: mock().mockResolvedValue("test-memory-id"),
2792
+ updateMemory: mock().mockResolvedValue(true),
2793
+ deleteMemory: mock().mockResolvedValue(void 0),
2794
+ deleteManyMemories: mock().mockResolvedValue(void 0),
2795
+ deleteAllMemories: mock().mockResolvedValue(void 0),
2796
+ countMemories: mock().mockResolvedValue(0),
2797
+ ensureEmbeddingDimension: mock().mockResolvedValue(void 0),
2798
+ // Logging
2799
+ log: mock().mockResolvedValue(void 0),
2800
+ getLogs: mock().mockResolvedValue([]),
2801
+ deleteLog: mock().mockResolvedValue(void 0),
2802
+ // World Management
2803
+ createWorld: mock().mockResolvedValue("test-world-id"),
2804
+ getWorld: mock().mockResolvedValue(null),
2805
+ removeWorld: mock().mockResolvedValue(void 0),
2806
+ getAllWorlds: mock().mockResolvedValue([]),
2807
+ updateWorld: mock().mockResolvedValue(void 0),
2808
+ // Room Management
2809
+ getRoomsByIds: mock().mockResolvedValue([]),
2810
+ createRooms: mock().mockResolvedValue([]),
2811
+ deleteRoom: mock().mockResolvedValue(void 0),
2812
+ deleteRoomsByWorldId: mock().mockResolvedValue(void 0),
2813
+ updateRoom: mock().mockResolvedValue(void 0),
2814
+ getRoomsForParticipant: mock().mockResolvedValue([]),
2815
+ getRoomsForParticipants: mock().mockResolvedValue([]),
2816
+ getRoomsByWorld: mock().mockResolvedValue([]),
2817
+ // Participant Management
2818
+ removeParticipant: mock().mockResolvedValue(true),
2819
+ addParticipantsRoom: mock().mockResolvedValue(true),
2820
+ getParticipantsForEntity: mock().mockResolvedValue([]),
2821
+ getParticipantsForRoom: mock().mockResolvedValue([]),
2822
+ getParticipantUserState: mock().mockResolvedValue(null),
2823
+ setParticipantUserState: mock().mockResolvedValue(void 0),
2824
+ // Relationship Management
2825
+ createRelationship: mock().mockResolvedValue(true),
2826
+ updateRelationship: mock().mockResolvedValue(void 0),
2827
+ getRelationship: mock().mockResolvedValue(null),
2828
+ getRelationships: mock().mockResolvedValue([]),
2829
+ // Cache Management
2830
+ getCache: mock().mockResolvedValue(void 0),
2831
+ setCache: mock().mockResolvedValue(true),
2832
+ deleteCache: mock().mockResolvedValue(true),
2833
+ // Task Management
2834
+ createTask: mock().mockResolvedValue("test-task-id"),
2835
+ getTasks: mock().mockResolvedValue([]),
2836
+ getTask: mock().mockResolvedValue(null),
2837
+ getTasksByName: mock().mockResolvedValue([]),
2838
+ updateTask: mock().mockResolvedValue(void 0),
2839
+ deleteTask: mock().mockResolvedValue(void 0),
2840
+ // Apply overrides
2841
+ ...overrides
2842
+ };
2843
+ return baseDatabaseAdapter;
2844
+ }
2845
+ function createMockDbConnection(overrides = {}) {
2846
+ return {
2847
+ execute: mock().mockResolvedValue([]),
2848
+ query: mock().mockResolvedValue([]),
2849
+ run: mock().mockResolvedValue({ changes: 1 }),
2850
+ all: mock().mockResolvedValue([]),
2851
+ get: mock().mockResolvedValue(null),
2852
+ prepare: mock().mockReturnValue({
2853
+ get: mock().mockReturnValue(null),
2854
+ all: mock().mockReturnValue([]),
2855
+ run: mock().mockReturnValue({ changes: 1 })
2856
+ }),
2857
+ ...overrides
2858
+ };
2859
+ }
2860
+
2861
+ // src/mocks/services.ts
2862
+ import { ServiceType } from "@elizaos/core";
2863
+ function createMockService(serviceType = ServiceType.UNKNOWN, overrides = {}) {
2864
+ const baseService = {
2865
+ // Static properties (would be on the class)
2866
+ serviceType,
2867
+ // Instance properties
2868
+ capabilityDescription: `Mock service for testing`,
2869
+ config: {
2870
+ enabled: true,
2871
+ mockData: true,
2872
+ ...overrides.config
2873
+ },
2874
+ // Core lifecycle methods
2875
+ stop: mock().mockResolvedValue(void 0),
2876
+ // Common service methods that might be implemented
2877
+ start: mock().mockResolvedValue(void 0),
2878
+ initialize: mock().mockResolvedValue(void 0),
2879
+ isReady: mock().mockReturnValue(true),
2880
+ getStatus: mock().mockReturnValue("active"),
2881
+ restart: mock().mockResolvedValue(void 0),
2882
+ // Runtime property (protected in Service class, but needed for mocks)
2883
+ runtime: null,
2884
+ // Apply overrides
2885
+ ...overrides
2886
+ };
2887
+ return baseService;
2888
+ }
2889
+ function createMockDatabaseService(overrides = {}) {
2890
+ return createMockService(ServiceType.UNKNOWN, {
2891
+ capabilityDescription: "Provides database connectivity and operations",
2892
+ ...overrides
2893
+ });
2894
+ }
2895
+ function createMockCacheService(overrides = {}) {
2896
+ const cache = /* @__PURE__ */ new Map();
2897
+ return createMockService(ServiceType.UNKNOWN, {
2898
+ capabilityDescription: "Provides in-memory caching capabilities",
2899
+ ...overrides
2900
+ });
2901
+ }
2902
+ function createMockHttpService(overrides = {}) {
2903
+ return createMockService(ServiceType.UNKNOWN, {
2904
+ capabilityDescription: "Provides HTTP client capabilities",
2905
+ ...overrides
2906
+ });
2907
+ }
2908
+ function createMockBlockchainService(overrides = {}) {
2909
+ return createMockService("WALLET", {
2910
+ capabilityDescription: "Provides blockchain wallet and transaction capabilities",
2911
+ ...overrides
2912
+ });
2913
+ }
2914
+ function createMockModelService(overrides = {}) {
2915
+ return createMockService(ServiceType.UNKNOWN, {
2916
+ capabilityDescription: "Provides AI model inference capabilities",
2917
+ ...overrides
2918
+ });
2919
+ }
2920
+ function createMockMessagingService(overrides = {}) {
2921
+ return createMockService(ServiceType.UNKNOWN, {
2922
+ capabilityDescription: "Provides messaging platform integration",
2923
+ ...overrides
2924
+ });
2925
+ }
2926
+ function createMockServiceMap(services = []) {
2927
+ const serviceMap = /* @__PURE__ */ new Map();
2928
+ if (services.length === 0) {
2929
+ services = [
2930
+ { name: "database", type: ServiceType.UNKNOWN },
2931
+ { name: "cache", type: ServiceType.UNKNOWN },
2932
+ { name: "http", type: ServiceType.UNKNOWN }
2933
+ ];
2934
+ }
2935
+ services.forEach(({ name, type = ServiceType.UNKNOWN, overrides = {} }) => {
2936
+ const service = createMockService(type, overrides);
2937
+ serviceMap.set(name, service);
2938
+ });
2939
+ return serviceMap;
2940
+ }
2941
+ function registerMockServices(runtime, services = []) {
2942
+ const serviceMap = createMockServiceMap(services);
2943
+ runtime.getService = mock().mockImplementation((serviceName) => {
2944
+ return serviceMap.get(serviceName) || null;
2945
+ });
2946
+ runtime.services = serviceMap;
2947
+ return runtime;
2948
+ }
2949
+ export {
2950
+ ErrorTestTemplate,
2951
+ IntegrationTestTemplate,
2952
+ PerformanceTestTemplate,
2953
+ PluginTestTemplate,
2954
+ RuntimeTestHarness,
2955
+ TestDataGenerator,
2956
+ TestDatabaseManager,
2957
+ TestModelProvider,
2958
+ TestScenarioBuilder,
2959
+ TestSuite,
2960
+ TestTemplate,
2961
+ UnitTestTemplate,
2962
+ createErrorTest,
2963
+ createIntegrationTest,
2964
+ createMinimalMockCharacter,
2965
+ createMockActionResult,
2966
+ createMockAgentResponse,
2967
+ createMockBlockchainService,
2968
+ createMockCacheService,
2969
+ createMockCharacter,
2970
+ createMockContent,
2971
+ createMockConversation,
2972
+ createMockConversationState,
2973
+ createMockDatabase,
2974
+ createMockDatabaseService,
2975
+ createMockDbConnection,
2976
+ createMockFact,
2977
+ createMockHttpService,
2978
+ createMockMedia,
2979
+ createMockMemory,
2980
+ createMockMemoryWithEmbedding,
2981
+ createMockMessagingService,
2982
+ createMockModelService,
2983
+ createMockProviderResult,
2984
+ createMockRuntime,
2985
+ createMockService,
2986
+ createMockServiceMap,
2987
+ createMockState,
2988
+ createMockStateWithActions,
2989
+ createMockStateWithProvider,
2990
+ createMockUserMessage,
2991
+ createModelHandler,
2992
+ createMultiAgentScenario,
2993
+ createMultipleCharacters,
2994
+ createPerformanceTest,
2995
+ createPluginTest,
2996
+ createPluginTestCharacter,
2997
+ createPluginTestScenario,
2998
+ createRichConversationCharacter,
2999
+ createSpecializedModelProvider,
3000
+ createTestAction,
3001
+ createTestDatabase,
3002
+ createTestEnvironment,
3003
+ createTestEvaluator,
3004
+ createTestModelProvider,
3005
+ createTestProvider,
3006
+ createTestRuntime,
3007
+ createUnitTest,
3008
+ mock,
3009
+ registerMockServices,
3010
+ runIntegrationTest,
3011
+ scenarios
3012
+ };
3013
+ //# sourceMappingURL=index.js.map