@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/.npmignore +5 -0
- package/LICENSE +21 -0
- package/README.md +255 -0
- package/dist/index.d.ts +950 -0
- package/dist/index.js +3013 -0
- package/dist/index.js.map +1 -0
- package/package.json +75 -0
- package/tsup.config.ts +20 -0
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
|