@elizaos/core 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.browser.js +102 -102
- package/dist/browser/index.browser.js.map +5 -5
- package/dist/browser/index.d.ts +3 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -5
- package/dist/node/index.d.ts +3 -1
- package/dist/node/index.node.js +91 -12
- package/dist/node/index.node.js.map +10 -10
- package/package.json +10 -4
- package/src/__tests__/action-chaining-simple.test.ts +203 -0
- package/src/__tests__/actions.test.ts +218 -0
- package/src/__tests__/buffer.test.ts +337 -0
- package/src/__tests__/character-validation.test.ts +309 -0
- package/src/__tests__/database.test.ts +750 -0
- package/src/__tests__/entities.test.ts +727 -0
- package/src/__tests__/env.test.ts +23 -0
- package/src/__tests__/environment.test.ts +285 -0
- package/src/__tests__/logger-browser-node.test.ts +716 -0
- package/src/__tests__/logger.test.ts +403 -0
- package/src/__tests__/messages.test.ts +196 -0
- package/src/__tests__/mockCharacter.ts +544 -0
- package/src/__tests__/parsing.test.ts +58 -0
- package/src/__tests__/prompts.test.ts +159 -0
- package/src/__tests__/roles.test.ts +331 -0
- package/src/__tests__/runtime-embedding.test.ts +343 -0
- package/src/__tests__/runtime.test.ts +978 -0
- package/src/__tests__/search.test.ts +15 -0
- package/src/__tests__/services-by-type.test.ts +204 -0
- package/src/__tests__/services.test.ts +136 -0
- package/src/__tests__/settings.test.ts +810 -0
- package/src/__tests__/utils.test.ts +1105 -0
- package/src/__tests__/uuid.test.ts +94 -0
- package/src/actions.ts +122 -0
- package/src/database.ts +579 -0
- package/src/entities.ts +406 -0
- package/src/index.browser.ts +48 -0
- package/src/index.node.ts +39 -0
- package/src/index.ts +50 -0
- package/src/logger.ts +527 -0
- package/src/prompts.ts +243 -0
- package/src/roles.ts +85 -0
- package/src/runtime.ts +2514 -0
- package/src/schemas/character.ts +149 -0
- package/src/search.ts +1543 -0
- package/src/sentry/instrument.browser.ts +65 -0
- package/src/sentry/instrument.node.ts +57 -0
- package/src/sentry/instrument.ts +82 -0
- package/src/services.ts +105 -0
- package/src/settings.ts +409 -0
- package/src/test_resources/constants.ts +12 -0
- package/src/test_resources/testSetup.ts +21 -0
- package/src/test_resources/types.ts +22 -0
- package/src/types/agent.ts +112 -0
- package/src/types/browser.ts +145 -0
- package/src/types/components.ts +184 -0
- package/src/types/database.ts +348 -0
- package/src/types/email.ts +162 -0
- package/src/types/environment.ts +129 -0
- package/src/types/events.ts +249 -0
- package/src/types/index.ts +29 -0
- package/src/types/knowledge.ts +65 -0
- package/src/types/lp.ts +124 -0
- package/src/types/memory.ts +228 -0
- package/src/types/message.ts +233 -0
- package/src/types/messaging.ts +57 -0
- package/src/types/model.ts +359 -0
- package/src/types/pdf.ts +77 -0
- package/src/types/plugin.ts +78 -0
- package/src/types/post.ts +271 -0
- package/src/types/primitives.ts +97 -0
- package/src/types/runtime.ts +190 -0
- package/src/types/service.ts +198 -0
- package/src/types/settings.ts +30 -0
- package/src/types/state.ts +60 -0
- package/src/types/task.ts +72 -0
- package/src/types/tee.ts +107 -0
- package/src/types/testing.ts +30 -0
- package/src/types/token.ts +96 -0
- package/src/types/transcription.ts +133 -0
- package/src/types/video.ts +108 -0
- package/src/types/wallet.ts +56 -0
- package/src/types/web-search.ts +146 -0
- package/src/utils/__tests__/buffer.test.ts +80 -0
- package/src/utils/__tests__/environment.test.ts +58 -0
- package/src/utils/__tests__/stringToUuid.test.ts +88 -0
- package/src/utils/buffer.ts +312 -0
- package/src/utils/environment.ts +316 -0
- package/src/utils/server-health.ts +117 -0
- package/src/utils.ts +1076 -0
- package/dist/tsconfig.build.tsbuildinfo +0 -1
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { describe, expect, it, beforeEach, afterEach } from 'bun:test';
|
|
2
|
+
import { mock } from 'bun:test';
|
|
3
|
+
import { createLogger, logger, elizaLogger } from '../logger';
|
|
4
|
+
|
|
5
|
+
// Mock environment variables
|
|
6
|
+
const mockEnv = {
|
|
7
|
+
LOG_LEVEL: '',
|
|
8
|
+
DEFAULT_LOG_LEVEL: '',
|
|
9
|
+
LOG_JSON_FORMAT: '',
|
|
10
|
+
SENTRY_LOGGING: 'false',
|
|
11
|
+
LOG_DIAGNOSTIC: '',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// No external logger transport to mock; Adze is used internally
|
|
15
|
+
|
|
16
|
+
describe('Logger', () => {
|
|
17
|
+
let originalEnv: NodeJS.ProcessEnv;
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
// Save original environment
|
|
21
|
+
originalEnv = { ...process.env };
|
|
22
|
+
// Reset environment variables
|
|
23
|
+
Object.keys(mockEnv).forEach((key) => {
|
|
24
|
+
process.env[key] = mockEnv[key];
|
|
25
|
+
});
|
|
26
|
+
mock.restore();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
// Restore original environment
|
|
31
|
+
process.env = originalEnv;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('Logger Creation', () => {
|
|
35
|
+
it('should export logger instance', () => {
|
|
36
|
+
expect(logger).toBeDefined();
|
|
37
|
+
expect(typeof logger.info).toBe('function');
|
|
38
|
+
expect(typeof logger.error).toBe('function');
|
|
39
|
+
// Note: warn and debug methods exist on the pino logger instance
|
|
40
|
+
// but may not be enumerable. Test their functionality instead.
|
|
41
|
+
expect(logger.warn).toBeDefined();
|
|
42
|
+
expect(logger.debug).toBeDefined();
|
|
43
|
+
expect(typeof logger.warn).toBe('function');
|
|
44
|
+
expect(typeof logger.debug).toBe('function');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should export elizaLogger as alias for backward compatibility', () => {
|
|
48
|
+
expect(elizaLogger).toBeDefined();
|
|
49
|
+
expect(elizaLogger).toBe(logger);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should have custom log levels', () => {
|
|
53
|
+
const testLogger = createLogger({ agentName: 'test' });
|
|
54
|
+
expect(typeof testLogger.fatal).toBe('function');
|
|
55
|
+
expect(typeof testLogger.error).toBe('function');
|
|
56
|
+
expect(typeof testLogger.warn).toBe('function');
|
|
57
|
+
expect(typeof testLogger.info).toBe('function');
|
|
58
|
+
expect(typeof testLogger.debug).toBe('function');
|
|
59
|
+
expect(typeof testLogger.trace).toBe('function');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('createLogger Function', () => {
|
|
64
|
+
it('should create logger with bindings', () => {
|
|
65
|
+
const bindings = { agentName: 'TestAgent', agentId: '123' };
|
|
66
|
+
const customLogger = createLogger(bindings);
|
|
67
|
+
|
|
68
|
+
expect(customLogger).toBeDefined();
|
|
69
|
+
expect(typeof customLogger.info).toBe('function');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should create logger without bindings', () => {
|
|
73
|
+
const customLogger = createLogger();
|
|
74
|
+
|
|
75
|
+
expect(customLogger).toBeDefined();
|
|
76
|
+
expect(typeof customLogger.info).toBe('function');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should handle boolean bindings parameter', () => {
|
|
80
|
+
const customLogger = createLogger(false);
|
|
81
|
+
|
|
82
|
+
expect(customLogger).toBeDefined();
|
|
83
|
+
expect(typeof customLogger.info).toBe('function');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('Log Level Configuration', () => {
|
|
88
|
+
it('should use debug level when LOG_LEVEL is debug', () => {
|
|
89
|
+
process.env.LOG_LEVEL = 'debug';
|
|
90
|
+
const customLogger = createLogger();
|
|
91
|
+
|
|
92
|
+
// Logger should be created with debug level
|
|
93
|
+
expect(customLogger.level).toBeDefined();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should use DEFAULT_LOG_LEVEL when LOG_LEVEL is not debug', () => {
|
|
97
|
+
process.env.LOG_LEVEL = '';
|
|
98
|
+
process.env.DEFAULT_LOG_LEVEL = 'warn';
|
|
99
|
+
const customLogger = createLogger();
|
|
100
|
+
|
|
101
|
+
expect(customLogger.level).toBeDefined();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should default to info level when no log level is specified', () => {
|
|
105
|
+
process.env.LOG_LEVEL = '';
|
|
106
|
+
process.env.DEFAULT_LOG_LEVEL = '';
|
|
107
|
+
const customLogger = createLogger();
|
|
108
|
+
|
|
109
|
+
expect(customLogger.level).toBeDefined();
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('JSON Format Configuration', () => {
|
|
114
|
+
it('should use JSON format when LOG_JSON_FORMAT is true', () => {
|
|
115
|
+
process.env.LOG_JSON_FORMAT = 'true';
|
|
116
|
+
const customLogger = createLogger();
|
|
117
|
+
|
|
118
|
+
expect(customLogger).toBeDefined();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should use pretty format when LOG_JSON_FORMAT is false', () => {
|
|
122
|
+
process.env.LOG_JSON_FORMAT = 'false';
|
|
123
|
+
const customLogger = createLogger();
|
|
124
|
+
|
|
125
|
+
expect(customLogger).toBeDefined();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('Log Filtering', () => {
|
|
130
|
+
it('should filter service registration logs in non-debug mode', () => {
|
|
131
|
+
process.env.LOG_LEVEL = 'info';
|
|
132
|
+
const customLogger = createLogger();
|
|
133
|
+
|
|
134
|
+
// These logs should be filtered in non-debug mode
|
|
135
|
+
const filteredMessages = [
|
|
136
|
+
'registered successfully',
|
|
137
|
+
'Registering',
|
|
138
|
+
'Success:',
|
|
139
|
+
'linked to',
|
|
140
|
+
'Started',
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
// Logger is created and can handle these messages
|
|
144
|
+
filteredMessages.forEach((msg) => {
|
|
145
|
+
expect(() => customLogger.info({ agentName: 'test', agentId: '123' }, msg)).not.toThrow();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should not filter service registration logs in debug mode', () => {
|
|
150
|
+
process.env.LOG_LEVEL = 'debug';
|
|
151
|
+
const customLogger = createLogger();
|
|
152
|
+
|
|
153
|
+
// In debug mode, all logs should pass through
|
|
154
|
+
expect(customLogger.level).toBeDefined();
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe('Error Handling', () => {
|
|
159
|
+
it('should handle Error objects in log messages', () => {
|
|
160
|
+
const customLogger = createLogger();
|
|
161
|
+
const testError = new Error('Test error');
|
|
162
|
+
|
|
163
|
+
expect(() => customLogger.error(testError)).not.toThrow();
|
|
164
|
+
expect(() => customLogger.error('Message', testError)).not.toThrow();
|
|
165
|
+
expect(() =>
|
|
166
|
+
customLogger.error({ context: 'test' }, 'Error occurred', testError)
|
|
167
|
+
).not.toThrow();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should format error messages properly', () => {
|
|
171
|
+
const customLogger = createLogger();
|
|
172
|
+
const testError = new Error('Test error');
|
|
173
|
+
testError.name = 'TestError';
|
|
174
|
+
|
|
175
|
+
// Should handle error formatting without throwing
|
|
176
|
+
expect(() => customLogger.error(testError)).not.toThrow();
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('Clear Method', () => {
|
|
181
|
+
it('should have clear method when not using raw JSON format', () => {
|
|
182
|
+
process.env.LOG_JSON_FORMAT = 'false';
|
|
183
|
+
// Since the logger is created asynchronously with pretty printing,
|
|
184
|
+
// we just verify the logger is created successfully
|
|
185
|
+
expect(logger).toBeDefined();
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('Hook Methods', () => {
|
|
190
|
+
it('should handle various log input formats', () => {
|
|
191
|
+
const customLogger = createLogger();
|
|
192
|
+
|
|
193
|
+
// Test various input formats
|
|
194
|
+
expect(() => customLogger.info('Simple string')).not.toThrow();
|
|
195
|
+
expect(() => customLogger.info({ key: 'value' }, 'With object')).not.toThrow();
|
|
196
|
+
expect(() => customLogger.info('Multiple', 'string', 'parts')).not.toThrow();
|
|
197
|
+
expect(() => customLogger.error(new Error('Test'), 'With error')).not.toThrow();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should handle mixed arguments with errors', () => {
|
|
201
|
+
const customLogger = createLogger();
|
|
202
|
+
const error = new Error('Test error');
|
|
203
|
+
|
|
204
|
+
expect(() => customLogger.error('Message', error, { extra: 'data' })).not.toThrow();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe('Diagnostic Mode', () => {
|
|
209
|
+
it('should add diagnostic flag when LOG_DIAGNOSTIC is enabled', () => {
|
|
210
|
+
process.env.LOG_DIAGNOSTIC = 'true';
|
|
211
|
+
const customLogger = createLogger();
|
|
212
|
+
|
|
213
|
+
// Logger should handle diagnostic mode
|
|
214
|
+
expect(customLogger).toBeDefined();
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe('Custom Prettifiers', () => {
|
|
219
|
+
it('should format log levels correctly', () => {
|
|
220
|
+
const customLogger = createLogger();
|
|
221
|
+
|
|
222
|
+
// Test that various log levels work
|
|
223
|
+
expect(() => customLogger.trace('Trace message')).not.toThrow();
|
|
224
|
+
expect(() => customLogger.debug('Debug message')).not.toThrow();
|
|
225
|
+
expect(() => customLogger.info('Info message')).not.toThrow();
|
|
226
|
+
expect(() => customLogger.warn('Warn message')).not.toThrow();
|
|
227
|
+
expect(() => customLogger.error('Error message')).not.toThrow();
|
|
228
|
+
expect(() => customLogger.fatal('Fatal message')).not.toThrow();
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
describe('Comprehensive Hook Method Coverage', () => {
|
|
233
|
+
it('should handle error as first argument with formatting', () => {
|
|
234
|
+
const customLogger = createLogger();
|
|
235
|
+
const error = new Error('Test error message');
|
|
236
|
+
error.name = 'CustomError';
|
|
237
|
+
error.stack = 'Error: Test error message\n at Object.<anonymous> (test.js:1:1)';
|
|
238
|
+
|
|
239
|
+
// This triggers the formatError path in hooks.logMethod
|
|
240
|
+
expect(() => customLogger.error(error)).not.toThrow();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should handle object with multiple string arguments', () => {
|
|
244
|
+
const customLogger = createLogger();
|
|
245
|
+
|
|
246
|
+
// This triggers the object + rest args path
|
|
247
|
+
expect(() => customLogger.info({ userId: '123' }, 'User', 'logged', 'in')).not.toThrow();
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('should handle string with error in rest arguments', () => {
|
|
251
|
+
const customLogger = createLogger();
|
|
252
|
+
const error1 = new Error('First error');
|
|
253
|
+
const error2 = new Error('Second error');
|
|
254
|
+
|
|
255
|
+
// This triggers error handling in rest args
|
|
256
|
+
expect(() => customLogger.error('Multiple errors:', error1, error2)).not.toThrow();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should handle mixed object and string arguments', () => {
|
|
260
|
+
const customLogger = createLogger();
|
|
261
|
+
|
|
262
|
+
// This triggers the context building path
|
|
263
|
+
expect(() => customLogger.info('Status:', { active: true }, 'for user')).not.toThrow();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('should handle non-string, non-error objects in arguments', () => {
|
|
267
|
+
const customLogger = createLogger();
|
|
268
|
+
|
|
269
|
+
// This triggers JSON.stringify for non-string args
|
|
270
|
+
expect(() =>
|
|
271
|
+
customLogger.info('Data:', { complex: { nested: true } }, ['array', 'data'])
|
|
272
|
+
).not.toThrow();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('should handle Sentry exception capture for errors', () => {
|
|
276
|
+
const originalSentryLogging = process.env.SENTRY_LOGGING;
|
|
277
|
+
process.env.SENTRY_LOGGING = ''; // Not 'false', so Sentry logging is enabled
|
|
278
|
+
|
|
279
|
+
const customLogger = createLogger();
|
|
280
|
+
const error = new Error('Sentry test');
|
|
281
|
+
|
|
282
|
+
// This should trigger Sentry.captureException
|
|
283
|
+
expect(() => customLogger.error(error)).not.toThrow();
|
|
284
|
+
expect(() => customLogger.error('Message with error:', error)).not.toThrow();
|
|
285
|
+
|
|
286
|
+
process.env.SENTRY_LOGGING = originalSentryLogging;
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('should handle all argument being non-string objects', () => {
|
|
290
|
+
const customLogger = createLogger();
|
|
291
|
+
|
|
292
|
+
// Logger expects string message after object, so we need to provide valid signatures
|
|
293
|
+
expect(() => customLogger.info({ a: 1, b: 2, c: 3 }, 'Combined object log')).not.toThrow();
|
|
294
|
+
expect(() => customLogger.info('Objects:', { a: 1 }, { b: 2 })).not.toThrow();
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it('should handle logger clear method when destination exists', () => {
|
|
298
|
+
// Access the clear method if it exists
|
|
299
|
+
if (typeof (logger as any).clear === 'function') {
|
|
300
|
+
expect(() => (logger as any).clear()).not.toThrow();
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Also test on a newly created logger
|
|
304
|
+
const customLogger = createLogger();
|
|
305
|
+
if (typeof (customLogger as any).clear === 'function') {
|
|
306
|
+
expect(() => (customLogger as any).clear()).not.toThrow();
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
describe('InMemoryDestination Coverage', () => {
|
|
312
|
+
it('should handle non-JSON string data in write method', () => {
|
|
313
|
+
const customLogger = createLogger();
|
|
314
|
+
|
|
315
|
+
// This could trigger the non-JSON path in InMemoryDestination.write
|
|
316
|
+
// when the transport receives malformed data
|
|
317
|
+
expect(() => customLogger.info('Simple text that might not be JSON')).not.toThrow();
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it('should handle diagnostic mode with filtered logs', () => {
|
|
321
|
+
process.env.LOG_DIAGNOSTIC = 'true';
|
|
322
|
+
process.env.LOG_LEVEL = 'info'; // Not debug
|
|
323
|
+
|
|
324
|
+
const customLogger = createLogger({ agentName: 'test', agentId: '123' });
|
|
325
|
+
|
|
326
|
+
// These should be filtered but diagnostic mode might log them
|
|
327
|
+
expect(() => customLogger.info('registered successfully')).not.toThrow();
|
|
328
|
+
expect(() => customLogger.info('Registering service')).not.toThrow();
|
|
329
|
+
|
|
330
|
+
process.env.LOG_DIAGNOSTIC = '';
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
describe('Async Stream Creation', () => {
|
|
335
|
+
it('should handle async stream creation when require fails', async () => {
|
|
336
|
+
// This test simulates the async fallback path
|
|
337
|
+
// We can't easily mock require failure in test environments, so we test the async path exists
|
|
338
|
+
const originalEnv = process.env.LOG_JSON_FORMAT;
|
|
339
|
+
process.env.LOG_JSON_FORMAT = 'false';
|
|
340
|
+
|
|
341
|
+
// Force a new logger creation which might use async path
|
|
342
|
+
// Note: bun:test doesn't have resetModules equivalent
|
|
343
|
+
const { createLogger: asyncLogger } = await import('../logger');
|
|
344
|
+
|
|
345
|
+
const logger = asyncLogger();
|
|
346
|
+
expect(logger).toBeDefined();
|
|
347
|
+
|
|
348
|
+
// Wait a bit for async initialization
|
|
349
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
350
|
+
|
|
351
|
+
expect(() => logger.info('Async logger test')).not.toThrow();
|
|
352
|
+
|
|
353
|
+
process.env.LOG_JSON_FORMAT = originalEnv;
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('should handle pino-pretty module not having default export', async () => {
|
|
357
|
+
// Mock pino-pretty without default export
|
|
358
|
+
// Note: bun:test has different module mocking behavior
|
|
359
|
+
const { createLogger: testLogger } = await import('../logger');
|
|
360
|
+
|
|
361
|
+
const logger = testLogger();
|
|
362
|
+
expect(logger).toBeDefined();
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
describe('Additional Custom Level Tests', () => {
|
|
367
|
+
it('should use custom log levels', () => {
|
|
368
|
+
const customLogger = createLogger();
|
|
369
|
+
|
|
370
|
+
// Test custom levels exist and work
|
|
371
|
+
expect(typeof (customLogger as any).log).toBe('function');
|
|
372
|
+
expect(typeof (customLogger as any).progress).toBe('function');
|
|
373
|
+
expect(typeof (customLogger as any).success).toBe('function');
|
|
374
|
+
|
|
375
|
+
expect(() => (customLogger as any).log('Custom log message')).not.toThrow();
|
|
376
|
+
expect(() => (customLogger as any).progress('Progress update')).not.toThrow();
|
|
377
|
+
expect(() => (customLogger as any).success('Operation successful')).not.toThrow();
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
describe('Custom Prettifier Edge Cases', () => {
|
|
382
|
+
it('should handle undefined level in prettifier', () => {
|
|
383
|
+
const customLogger = createLogger();
|
|
384
|
+
|
|
385
|
+
// This might trigger the undefined level path in prettifier
|
|
386
|
+
expect(() => customLogger.info('Test with potential undefined level')).not.toThrow();
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('should handle null level in prettifier', () => {
|
|
390
|
+
const customLogger = createLogger();
|
|
391
|
+
|
|
392
|
+
// Force a log that might have null level
|
|
393
|
+
expect(() => (customLogger as any).child({ level: null }).info('Test')).not.toThrow();
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('should handle object level data in prettifier', () => {
|
|
397
|
+
const customLogger = createLogger();
|
|
398
|
+
|
|
399
|
+
// Test object input to level prettifier
|
|
400
|
+
expect(() => customLogger.child({ level: 30 }).info('Test with numeric level')).not.toThrow();
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
});
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { beforeAll, describe, expect, test, it } from 'bun:test';
|
|
2
|
+
import { formatEntities } from '../entities';
|
|
3
|
+
import { formatMessages, formatTimestamp } from '../utils';
|
|
4
|
+
import type { Content, Entity, Memory, UUID } from '../types';
|
|
5
|
+
|
|
6
|
+
describe('Messages Library', () => {
|
|
7
|
+
let entities: Entity[];
|
|
8
|
+
let entityId: UUID;
|
|
9
|
+
|
|
10
|
+
beforeAll(() => {
|
|
11
|
+
// Mock user data with proper UUID format
|
|
12
|
+
entityId = '123e4567-e89b-12d3-a456-426614174000' as UUID;
|
|
13
|
+
entities = [
|
|
14
|
+
{
|
|
15
|
+
id: entityId,
|
|
16
|
+
names: ['Test User'],
|
|
17
|
+
agentId: '123e4567-e89b-12d3-a456-426614174001' as UUID,
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('formatEntities should format entities into a readable string', () => {
|
|
23
|
+
const formattedEntities = formatEntities({ entities });
|
|
24
|
+
|
|
25
|
+
expect(formattedEntities).toContain('Test User');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('formatMessages should format messages into a readable string', () => {
|
|
29
|
+
const messages: Memory[] = [
|
|
30
|
+
{
|
|
31
|
+
content: { text: 'Hello, world!' } as Content,
|
|
32
|
+
entityId: entityId,
|
|
33
|
+
roomId: '123e4567-e89b-12d3-a456-426614174002' as UUID,
|
|
34
|
+
createdAt: new Date().getTime(),
|
|
35
|
+
agentId: '' as UUID, // assuming agentId is an empty string here
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const formattedMessages = formatMessages({ messages, entities });
|
|
40
|
+
|
|
41
|
+
// Assertions
|
|
42
|
+
expect(formattedMessages).toContain('Hello, world!');
|
|
43
|
+
expect(formattedMessages).toContain('Test User');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('formatTimestamp should return correct time string', () => {
|
|
47
|
+
const timestamp = new Date().getTime() - 60000; // 1 minute ago
|
|
48
|
+
const result = formatTimestamp(timestamp);
|
|
49
|
+
|
|
50
|
+
// Assertions
|
|
51
|
+
expect(result).toBe('1 minute ago');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('formatMessages should include attachments if present', () => {
|
|
55
|
+
const messages: Memory[] = [
|
|
56
|
+
{
|
|
57
|
+
content: {
|
|
58
|
+
text: 'Check this attachment',
|
|
59
|
+
attachments: [
|
|
60
|
+
{
|
|
61
|
+
id: '123e4567-e89b-12d3-a456-426614174003' as UUID,
|
|
62
|
+
title: 'Image',
|
|
63
|
+
url: 'http://example.com/image.jpg',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
} as Content,
|
|
67
|
+
entityId: entityId,
|
|
68
|
+
roomId: '123e4567-e89b-12d3-a456-426614174004' as UUID,
|
|
69
|
+
createdAt: new Date().getTime(),
|
|
70
|
+
agentId: '' as UUID, // assuming agentId is an empty string here
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
const formattedMessages = formatMessages({ messages, entities });
|
|
75
|
+
|
|
76
|
+
// Assertions
|
|
77
|
+
expect(formattedMessages).toContain('Check this attachment');
|
|
78
|
+
expect(formattedMessages).toContain('Attachments: [');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('formatMessages should handle empty attachments gracefully', () => {
|
|
82
|
+
const messages: Memory[] = [
|
|
83
|
+
{
|
|
84
|
+
content: {
|
|
85
|
+
text: 'No attachments here',
|
|
86
|
+
} as Content,
|
|
87
|
+
entityId: entityId,
|
|
88
|
+
roomId: '123e4567-e89b-12d3-a456-426614174005' as UUID,
|
|
89
|
+
createdAt: new Date().getTime(),
|
|
90
|
+
agentId: '' as UUID, // assuming agentId is an empty string here
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
const formattedMessages = formatMessages({ messages, entities });
|
|
95
|
+
|
|
96
|
+
// Assertions
|
|
97
|
+
expect(formattedMessages).toContain('No attachments here');
|
|
98
|
+
expect(formattedMessages).not.toContain('Attachments');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('Messages', () => {
|
|
103
|
+
const mockEntities: Entity[] = [
|
|
104
|
+
{
|
|
105
|
+
id: '123e4567-e89b-12d3-a456-426614174006' as UUID,
|
|
106
|
+
names: ['Alice'],
|
|
107
|
+
agentId: '123e4567-e89b-12d3-a456-426614174001' as UUID,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: '123e4567-e89b-12d3-a456-426614174007' as UUID,
|
|
111
|
+
names: ['Bob'],
|
|
112
|
+
agentId: '123e4567-e89b-12d3-a456-426614174002' as UUID,
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
describe('formatEntities', () => {
|
|
117
|
+
it('should format entities with complete details', () => {
|
|
118
|
+
const formatted = formatEntities({ entities: mockEntities });
|
|
119
|
+
expect(formatted).toContain('"Alice"\nID:');
|
|
120
|
+
expect(formatted).toContain('"Bob"\nID:');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should handle entities without details', () => {
|
|
124
|
+
const actorsWithoutDetails: Entity[] = [
|
|
125
|
+
{
|
|
126
|
+
id: '123e4567-e89b-12d3-a456-426614174013' as UUID,
|
|
127
|
+
names: ['Charlie'],
|
|
128
|
+
agentId: '123e4567-e89b-12d3-a456-426614174003' as UUID,
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
const formatted = formatEntities({ entities: actorsWithoutDetails });
|
|
132
|
+
expect(formatted).toContain('"Charlie"\nID:');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should handle empty entities array', () => {
|
|
136
|
+
const formatted = formatEntities({ entities: [] });
|
|
137
|
+
expect(formatted).toBe('');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('formatMessages', () => {
|
|
142
|
+
it('should handle messages from unknown users', () => {
|
|
143
|
+
const messagesWithUnknownUser: Memory[] = [
|
|
144
|
+
{
|
|
145
|
+
id: '123e4567-e89b-12d3-a456-426614174014' as UUID,
|
|
146
|
+
roomId: '123e4567-e89b-12d3-a456-426614174009' as UUID,
|
|
147
|
+
entityId: '123e4567-e89b-12d3-a456-426614174015' as UUID,
|
|
148
|
+
createdAt: Date.now(),
|
|
149
|
+
content: { text: 'Test message' } as Content,
|
|
150
|
+
agentId: '123e4567-e89b-12d3-a456-426614174001',
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
const formatted = formatMessages({
|
|
155
|
+
messages: messagesWithUnknownUser,
|
|
156
|
+
entities: mockEntities,
|
|
157
|
+
});
|
|
158
|
+
expect(formatted).toContain('Unknown User: Test message');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should handle messages with no action', () => {
|
|
162
|
+
const messagesWithoutAction: Memory[] = [
|
|
163
|
+
{
|
|
164
|
+
id: '123e4567-e89b-12d3-a456-426614174016' as UUID,
|
|
165
|
+
roomId: '123e4567-e89b-12d3-a456-426614174009' as UUID,
|
|
166
|
+
entityId: mockEntities[0].id as UUID,
|
|
167
|
+
createdAt: Date.now(),
|
|
168
|
+
content: { text: 'Simple message' } as Content,
|
|
169
|
+
agentId: '123e4567-e89b-12d3-a456-426614174001',
|
|
170
|
+
},
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
const formatted = formatMessages({
|
|
174
|
+
messages: messagesWithoutAction,
|
|
175
|
+
entities: mockEntities,
|
|
176
|
+
});
|
|
177
|
+
expect(formatted).not.toContain('()');
|
|
178
|
+
expect(formatted).toContain('Simple message');
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should handle empty messages array', () => {
|
|
182
|
+
const formatted = formatMessages({
|
|
183
|
+
messages: [],
|
|
184
|
+
entities: mockEntities,
|
|
185
|
+
});
|
|
186
|
+
expect(formatted).toBe('');
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
describe('formatTimestamp', () => {
|
|
191
|
+
it('should handle exact time boundaries', () => {
|
|
192
|
+
const now = Date.now();
|
|
193
|
+
expect(formatTimestamp(now)).toContain('just now');
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
});
|