@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.
Files changed (90) hide show
  1. package/dist/browser/index.browser.js +102 -102
  2. package/dist/browser/index.browser.js.map +5 -5
  3. package/dist/browser/index.d.ts +3 -1
  4. package/dist/index.d.ts +2 -3
  5. package/dist/index.js +1 -5
  6. package/dist/node/index.d.ts +3 -1
  7. package/dist/node/index.node.js +91 -12
  8. package/dist/node/index.node.js.map +10 -10
  9. package/package.json +10 -4
  10. package/src/__tests__/action-chaining-simple.test.ts +203 -0
  11. package/src/__tests__/actions.test.ts +218 -0
  12. package/src/__tests__/buffer.test.ts +337 -0
  13. package/src/__tests__/character-validation.test.ts +309 -0
  14. package/src/__tests__/database.test.ts +750 -0
  15. package/src/__tests__/entities.test.ts +727 -0
  16. package/src/__tests__/env.test.ts +23 -0
  17. package/src/__tests__/environment.test.ts +285 -0
  18. package/src/__tests__/logger-browser-node.test.ts +716 -0
  19. package/src/__tests__/logger.test.ts +403 -0
  20. package/src/__tests__/messages.test.ts +196 -0
  21. package/src/__tests__/mockCharacter.ts +544 -0
  22. package/src/__tests__/parsing.test.ts +58 -0
  23. package/src/__tests__/prompts.test.ts +159 -0
  24. package/src/__tests__/roles.test.ts +331 -0
  25. package/src/__tests__/runtime-embedding.test.ts +343 -0
  26. package/src/__tests__/runtime.test.ts +978 -0
  27. package/src/__tests__/search.test.ts +15 -0
  28. package/src/__tests__/services-by-type.test.ts +204 -0
  29. package/src/__tests__/services.test.ts +136 -0
  30. package/src/__tests__/settings.test.ts +810 -0
  31. package/src/__tests__/utils.test.ts +1105 -0
  32. package/src/__tests__/uuid.test.ts +94 -0
  33. package/src/actions.ts +122 -0
  34. package/src/database.ts +579 -0
  35. package/src/entities.ts +406 -0
  36. package/src/index.browser.ts +48 -0
  37. package/src/index.node.ts +39 -0
  38. package/src/index.ts +50 -0
  39. package/src/logger.ts +527 -0
  40. package/src/prompts.ts +243 -0
  41. package/src/roles.ts +85 -0
  42. package/src/runtime.ts +2514 -0
  43. package/src/schemas/character.ts +149 -0
  44. package/src/search.ts +1543 -0
  45. package/src/sentry/instrument.browser.ts +65 -0
  46. package/src/sentry/instrument.node.ts +57 -0
  47. package/src/sentry/instrument.ts +82 -0
  48. package/src/services.ts +105 -0
  49. package/src/settings.ts +409 -0
  50. package/src/test_resources/constants.ts +12 -0
  51. package/src/test_resources/testSetup.ts +21 -0
  52. package/src/test_resources/types.ts +22 -0
  53. package/src/types/agent.ts +112 -0
  54. package/src/types/browser.ts +145 -0
  55. package/src/types/components.ts +184 -0
  56. package/src/types/database.ts +348 -0
  57. package/src/types/email.ts +162 -0
  58. package/src/types/environment.ts +129 -0
  59. package/src/types/events.ts +249 -0
  60. package/src/types/index.ts +29 -0
  61. package/src/types/knowledge.ts +65 -0
  62. package/src/types/lp.ts +124 -0
  63. package/src/types/memory.ts +228 -0
  64. package/src/types/message.ts +233 -0
  65. package/src/types/messaging.ts +57 -0
  66. package/src/types/model.ts +359 -0
  67. package/src/types/pdf.ts +77 -0
  68. package/src/types/plugin.ts +78 -0
  69. package/src/types/post.ts +271 -0
  70. package/src/types/primitives.ts +97 -0
  71. package/src/types/runtime.ts +190 -0
  72. package/src/types/service.ts +198 -0
  73. package/src/types/settings.ts +30 -0
  74. package/src/types/state.ts +60 -0
  75. package/src/types/task.ts +72 -0
  76. package/src/types/tee.ts +107 -0
  77. package/src/types/testing.ts +30 -0
  78. package/src/types/token.ts +96 -0
  79. package/src/types/transcription.ts +133 -0
  80. package/src/types/video.ts +108 -0
  81. package/src/types/wallet.ts +56 -0
  82. package/src/types/web-search.ts +146 -0
  83. package/src/utils/__tests__/buffer.test.ts +80 -0
  84. package/src/utils/__tests__/environment.test.ts +58 -0
  85. package/src/utils/__tests__/stringToUuid.test.ts +88 -0
  86. package/src/utils/buffer.ts +312 -0
  87. package/src/utils/environment.ts +316 -0
  88. package/src/utils/server-health.ts +117 -0
  89. package/src/utils.ts +1076 -0
  90. package/dist/tsconfig.build.tsbuildinfo +0 -1
package/src/logger.ts ADDED
@@ -0,0 +1,527 @@
1
+ import { Sentry } from './sentry/instrument';
2
+ // Expose a tiny test hook to clear env cache in logger tests (kept internal)
3
+ // Note: we re-export a function that clears the environment cache indirectly via getEnv
4
+ export const __loggerTestHooks = {
5
+ __noop: () => {},
6
+ };
7
+ import { getEnv as getEnvironmentVar } from './utils/environment';
8
+ import adze, { setup } from 'adze';
9
+
10
+ // ============================================================================
11
+ // Type Definitions
12
+ // ============================================================================
13
+
14
+ /**
15
+ * Log function signature matching Pino's API for compatibility
16
+ */
17
+ type LogFn = (
18
+ obj: Record<string, unknown> | string | Error,
19
+ msg?: string,
20
+ ...args: unknown[]
21
+ ) => void;
22
+
23
+ /**
24
+ * Logger interface - ElizaOS standard logger API
25
+ */
26
+ export interface Logger {
27
+ level: string;
28
+ trace: LogFn;
29
+ debug: LogFn;
30
+ info: LogFn;
31
+ warn: LogFn;
32
+ error: LogFn;
33
+ fatal: LogFn;
34
+ success: LogFn;
35
+ progress: LogFn;
36
+ log: LogFn;
37
+ clear: () => void;
38
+ child: (bindings: Record<string, unknown>) => Logger;
39
+ }
40
+
41
+ /**
42
+ * Configuration for logger creation
43
+ */
44
+ export interface LoggerBindings extends Record<string, unknown> {
45
+ level?: string;
46
+ namespace?: string;
47
+ namespaces?: string[];
48
+ maxMemoryLogs?: number;
49
+ __forceType?: 'browser' | 'node'; // For testing - forces specific environment behavior
50
+ }
51
+
52
+ /**
53
+ * Log entry structure for in-memory storage
54
+ */
55
+ interface LogEntry {
56
+ time: number;
57
+ level?: number;
58
+ msg: string;
59
+ }
60
+
61
+ /**
62
+ * In-memory destination for recent logs
63
+ */
64
+ interface InMemoryDestination {
65
+ write: (entry: LogEntry) => void;
66
+ clear: () => void;
67
+ recentLogs: () => string;
68
+ }
69
+
70
+ // ============================================================================
71
+ // Utility Functions
72
+ // ============================================================================
73
+
74
+ /**
75
+ * Log level priorities for filtering
76
+ */
77
+ const LOG_LEVEL_PRIORITY: Record<string, number> = {
78
+ trace: 10,
79
+ verbose: 10,
80
+ debug: 20,
81
+ info: 30,
82
+ log: 30,
83
+ warn: 40,
84
+ error: 50,
85
+ fatal: 60,
86
+ alert: 60,
87
+ success: 30,
88
+ progress: 30,
89
+ };
90
+
91
+ /**
92
+ * Check if a message should be logged based on current level
93
+ */
94
+ function shouldLog(messageLevel: string, currentLevel: string): boolean {
95
+ const messagePriority = LOG_LEVEL_PRIORITY[messageLevel.toLowerCase()] || 30;
96
+ const currentPriority = LOG_LEVEL_PRIORITY[currentLevel.toLowerCase()] || 30;
97
+ return messagePriority >= currentPriority;
98
+ }
99
+
100
+ /**
101
+ * Safe JSON stringify that handles circular references
102
+ */
103
+ function safeStringify(obj: unknown): string {
104
+ try {
105
+ const seen = new WeakSet();
106
+ return JSON.stringify(obj, (_, value) => {
107
+ if (typeof value === 'object' && value !== null) {
108
+ if (seen.has(value)) return '[Circular]';
109
+ seen.add(value);
110
+ }
111
+ return value;
112
+ });
113
+ } catch {
114
+ return String(obj);
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Parse boolean from text string
120
+ */
121
+ function parseBooleanFromText(value: string | undefined | null): boolean {
122
+ if (!value) return false;
123
+ const normalized = value.toLowerCase().trim();
124
+ return normalized === 'true' || normalized === '1' || normalized === 'yes' || normalized === 'on';
125
+ }
126
+
127
+ // ============================================================================
128
+ // Configuration
129
+ // ============================================================================
130
+
131
+ // Log level configuration
132
+ const DEFAULT_LOG_LEVEL = 'info';
133
+ const effectiveLogLevel = getEnvironmentVar('LOG_LEVEL') || DEFAULT_LOG_LEVEL;
134
+
135
+ // Custom log levels mapping (ElizaOS to Adze)
136
+ export const customLevels: Record<string, number> = {
137
+ fatal: 60,
138
+ error: 50,
139
+ warn: 40,
140
+ info: 30,
141
+ log: 29,
142
+ progress: 28,
143
+ success: 27,
144
+ debug: 20,
145
+ trace: 10,
146
+ };
147
+
148
+ // Configuration flags
149
+ const raw = parseBooleanFromText(getEnvironmentVar('LOG_JSON_FORMAT'));
150
+ const showTimestamps = parseBooleanFromText(getEnvironmentVar('LOG_TIMESTAMPS') ?? 'true');
151
+
152
+ // ============================================================================
153
+ // In-Memory Log Storage
154
+ // ============================================================================
155
+
156
+ /**
157
+ * Creates an in-memory destination for storing recent logs
158
+ */
159
+ function createInMemoryDestination(maxLogs = 100): InMemoryDestination {
160
+ const logs: LogEntry[] = [];
161
+
162
+ return {
163
+ write(entry: LogEntry): void {
164
+ logs.push(entry);
165
+ if (logs.length > maxLogs) {
166
+ logs.shift();
167
+ }
168
+ },
169
+ clear(): void {
170
+ logs.length = 0;
171
+ },
172
+ recentLogs(): string {
173
+ return logs
174
+ .map((entry) => {
175
+ const timestamp = showTimestamps ? new Date(entry.time).toISOString() : '';
176
+ return `${timestamp} ${entry.msg}`.trim();
177
+ })
178
+ .join('\n');
179
+ },
180
+ };
181
+ }
182
+
183
+ // Global in-memory destination
184
+ const globalInMemoryDestination = createInMemoryDestination();
185
+
186
+ // ============================================================================
187
+ // Adze Configuration
188
+ // ============================================================================
189
+
190
+ /**
191
+ * Maps ElizaOS log levels to Adze log levels
192
+ */
193
+ function mapToAdzeActiveLevel(level: string | number): string {
194
+ const levelStr = typeof level === 'number' ? 'info' : level;
195
+ const normalized = levelStr.toLowerCase();
196
+ if (normalized === 'trace') return 'verbose';
197
+ if (normalized === 'fatal') return 'alert';
198
+ return normalized;
199
+ }
200
+
201
+ // Configure Adze globally
202
+ const adzeStore = setup({
203
+ activeLevel: mapToAdzeActiveLevel(effectiveLogLevel) as any,
204
+ format: raw ? 'json' : 'pretty',
205
+ timestampFormatter: showTimestamps ? undefined : () => '',
206
+ withEmoji: false,
207
+ });
208
+
209
+ // Mirror Adze output to in-memory storage
210
+ adzeStore.addListener('*', (log: any) => {
211
+ try {
212
+ const d = log.data;
213
+ const msg = Array.isArray(d?.message)
214
+ ? d.message.map((m: unknown) => (typeof m === 'string' ? m : safeStringify(m))).join(' ')
215
+ : typeof d?.message === 'string'
216
+ ? d.message
217
+ : '';
218
+ const entry: LogEntry = {
219
+ time: Date.now(),
220
+ level: typeof d?.level === 'number' ? d.level : undefined,
221
+ msg,
222
+ };
223
+ globalInMemoryDestination.write(entry);
224
+ } catch {
225
+ // Silent fail - don't break logging
226
+ }
227
+ });
228
+
229
+ // ============================================================================
230
+ // Logger Factory
231
+ // ============================================================================
232
+
233
+ /**
234
+ * Creates a sealed Adze logger instance with namespaces and metadata
235
+ */
236
+ function sealAdze(base: Record<string, unknown>): ReturnType<typeof adze.seal> {
237
+ let chain = adze as any;
238
+
239
+ // Add namespaces if provided
240
+ const namespaces: string[] = [];
241
+ if (typeof base.namespace === 'string') namespaces.push(base.namespace);
242
+ if (Array.isArray(base.namespaces)) namespaces.push(...(base.namespaces as string[]));
243
+ if (namespaces.length > 0) {
244
+ chain = chain.ns(...namespaces);
245
+ }
246
+
247
+ // Add metadata (excluding namespace properties)
248
+ const metaBase = { ...base };
249
+ delete (metaBase as any).namespace;
250
+ delete (metaBase as any).namespaces;
251
+
252
+ return chain.meta(metaBase).seal();
253
+ }
254
+
255
+ /**
256
+ * Extract configuration from bindings
257
+ */
258
+ function extractBindingsConfig(bindings: LoggerBindings | boolean): {
259
+ level: string;
260
+ base: Record<string, unknown>;
261
+ maxMemoryLogs?: number;
262
+ } {
263
+ let level = effectiveLogLevel;
264
+ let base: Record<string, unknown> = {};
265
+ let maxMemoryLogs: number | undefined;
266
+
267
+ if (typeof bindings === 'object' && bindings !== null) {
268
+ if ('level' in bindings) {
269
+ level = bindings.level as string;
270
+ }
271
+ if ('maxMemoryLogs' in bindings && typeof bindings.maxMemoryLogs === 'number') {
272
+ maxMemoryLogs = bindings.maxMemoryLogs;
273
+ }
274
+
275
+ // Extract base bindings (excluding special properties)
276
+ const { level: _, maxMemoryLogs: __, ...rest } = bindings;
277
+ base = rest;
278
+ }
279
+
280
+ return { level, base, maxMemoryLogs };
281
+ }
282
+
283
+ /**
284
+ * Creates a logger instance using Adze
285
+ * @param bindings - Logger configuration or boolean flag
286
+ * @returns Logger instance with ElizaOS API
287
+ */
288
+ function createLogger(bindings: LoggerBindings | boolean = false): Logger {
289
+ const { level, base, maxMemoryLogs } = extractBindingsConfig(bindings);
290
+
291
+ // Reset memory buffer if custom limit requested
292
+ if (typeof maxMemoryLogs === 'number' && maxMemoryLogs > 0) {
293
+ globalInMemoryDestination.clear();
294
+ }
295
+
296
+ // Check if we should force browser behavior (for testing)
297
+ const forceBrowser =
298
+ typeof bindings === 'object' &&
299
+ bindings &&
300
+ '__forceType' in bindings &&
301
+ bindings.__forceType === 'browser';
302
+
303
+ // If forcing browser mode, create a simple console-based logger
304
+ if (forceBrowser) {
305
+ const levelStr = typeof level === 'number' ? 'info' : level || effectiveLogLevel;
306
+ const currentLevel = levelStr.toLowerCase();
307
+
308
+ const formatArgs = (...args: unknown[]): string => {
309
+ return args
310
+ .map((arg) => {
311
+ if (typeof arg === 'string') return arg;
312
+ if (arg instanceof Error) return arg.message;
313
+ return safeStringify(arg);
314
+ })
315
+ .join(' ');
316
+ };
317
+
318
+ const logToConsole = (method: string, ...args: unknown[]): void => {
319
+ if (!shouldLog(method, currentLevel)) {
320
+ return;
321
+ }
322
+
323
+ const message = formatArgs(...args);
324
+ const consoleMethod =
325
+ method === 'fatal'
326
+ ? 'error'
327
+ : method === 'trace' || method === 'verbose'
328
+ ? 'debug'
329
+ : method === 'success' || method === 'progress'
330
+ ? 'info'
331
+ : method === 'log'
332
+ ? 'log'
333
+ : (console as any)[method]
334
+ ? method
335
+ : 'log';
336
+
337
+ if (typeof (console as any)[consoleMethod] === 'function') {
338
+ (console as any)[consoleMethod](message);
339
+ }
340
+ };
341
+
342
+ const adaptArgs = (
343
+ obj: Record<string, unknown> | string | Error,
344
+ msg?: string,
345
+ ...args: unknown[]
346
+ ): unknown[] => {
347
+ if (typeof obj === 'string') {
348
+ return msg !== undefined ? [obj, msg, ...args] : [obj, ...args];
349
+ }
350
+ if (obj instanceof Error) {
351
+ return msg !== undefined ? [obj.message, msg, ...args] : [obj.message, ...args];
352
+ }
353
+ if (msg !== undefined) {
354
+ return [msg, obj, ...args];
355
+ }
356
+ return [obj, ...args];
357
+ };
358
+
359
+ return {
360
+ level: currentLevel,
361
+ trace: (obj, msg, ...args) => logToConsole('trace', ...adaptArgs(obj, msg, ...args)),
362
+ debug: (obj, msg, ...args) => logToConsole('debug', ...adaptArgs(obj, msg, ...args)),
363
+ info: (obj, msg, ...args) => logToConsole('info', ...adaptArgs(obj, msg, ...args)),
364
+ warn: (obj, msg, ...args) => logToConsole('warn', ...adaptArgs(obj, msg, ...args)),
365
+ error: (obj, msg, ...args) => logToConsole('error', ...adaptArgs(obj, msg, ...args)),
366
+ fatal: (obj, msg, ...args) => logToConsole('fatal', ...adaptArgs(obj, msg, ...args)),
367
+ success: (obj, msg, ...args) => logToConsole('success', ...adaptArgs(obj, msg, ...args)),
368
+ progress: (obj, msg, ...args) => logToConsole('progress', ...adaptArgs(obj, msg, ...args)),
369
+ log: (obj, msg, ...args) => logToConsole('log', ...adaptArgs(obj, msg, ...args)),
370
+ clear: () => {
371
+ if (typeof console.clear === 'function') console.clear();
372
+ },
373
+ child: (childBindings: Record<string, unknown>) =>
374
+ createLogger({ level: currentLevel, ...base, ...childBindings, __forceType: 'browser' }),
375
+ };
376
+ }
377
+
378
+ // Create sealed Adze instance with configuration
379
+ const sealed = sealAdze(base);
380
+ const levelStr = typeof level === 'number' ? 'info' : level || effectiveLogLevel;
381
+ const currentLevel = levelStr.toLowerCase();
382
+
383
+ /**
384
+ * Capture errors to Sentry if configured
385
+ */
386
+ const captureIfError = (method: string, args: unknown[]): void => {
387
+ if (getEnvironmentVar('SENTRY_LOGGING') !== 'false') {
388
+ if (method === 'error' || method === 'fatal' || method === 'alert') {
389
+ for (const arg of args) {
390
+ if (arg instanceof Error) {
391
+ Sentry.captureException(arg);
392
+ return;
393
+ }
394
+ }
395
+ // Create error from message if no Error object found
396
+ const message = args.map((a) => (typeof a === 'string' ? a : safeStringify(a))).join(' ');
397
+ if (message) {
398
+ Sentry.captureException(new Error(message));
399
+ }
400
+ }
401
+ }
402
+ };
403
+
404
+ /**
405
+ * Invoke Adze method with error capture
406
+ */
407
+ const invoke = (method: string, ...args: unknown[]): void => {
408
+ // Check if this log level should be output
409
+ if (!shouldLog(method, currentLevel)) {
410
+ return;
411
+ }
412
+
413
+ // Ensure Sentry sees the semantic level name (e.g., 'fatal')
414
+ captureIfError(method, args);
415
+
416
+ // Map Eliza methods to correct Adze invocations
417
+ let adzeMethod = method;
418
+ let adzeArgs = args;
419
+
420
+ // Normalize special cases
421
+ if (method === 'fatal') {
422
+ // Adze uses 'alert' for fatal-level logging
423
+ adzeMethod = 'alert';
424
+ } else if (method === 'progress') {
425
+ // Use Adze custom level for progress
426
+ adzeMethod = 'custom';
427
+ adzeArgs = ['progress', ...args];
428
+ }
429
+
430
+ try {
431
+ (sealed as any)[adzeMethod](...adzeArgs);
432
+ } catch (error) {
433
+ // Fallback to console if Adze fails
434
+ console.log(`[${method.toUpperCase()}]`, ...args);
435
+ }
436
+ };
437
+
438
+ /**
439
+ * Adapt ElizaOS logger API arguments to Adze format
440
+ */
441
+ const adaptArgs = (
442
+ obj: Record<string, unknown> | string | Error,
443
+ msg?: string,
444
+ ...args: unknown[]
445
+ ): unknown[] => {
446
+ // String first argument
447
+ if (typeof obj === 'string') {
448
+ return msg !== undefined ? [obj, msg, ...args] : [obj, ...args];
449
+ }
450
+ // Error object
451
+ if (obj instanceof Error) {
452
+ return msg !== undefined
453
+ ? [obj.message, { error: obj }, msg, ...args]
454
+ : [obj.message, { error: obj }, ...args];
455
+ }
456
+ // Object (context) - put message first if provided
457
+ if (msg !== undefined) {
458
+ return [msg, obj, ...args];
459
+ }
460
+ return [obj, ...args];
461
+ };
462
+
463
+ // Create log methods
464
+ const trace: LogFn = (obj, msg, ...args) => invoke('verbose', ...adaptArgs(obj, msg, ...args));
465
+ const debug: LogFn = (obj, msg, ...args) => invoke('debug', ...adaptArgs(obj, msg, ...args));
466
+ const info: LogFn = (obj, msg, ...args) => invoke('info', ...adaptArgs(obj, msg, ...args));
467
+ const warn: LogFn = (obj, msg, ...args) => invoke('warn', ...adaptArgs(obj, msg, ...args));
468
+ const error: LogFn = (obj, msg, ...args) => invoke('error', ...adaptArgs(obj, msg, ...args));
469
+ const fatal: LogFn = (obj, msg, ...args) => invoke('fatal', ...adaptArgs(obj, msg, ...args));
470
+ const success: LogFn = (obj, msg, ...args) => invoke('success', ...adaptArgs(obj, msg, ...args));
471
+ const progress: LogFn = (obj, msg, ...args) =>
472
+ invoke('progress', ...adaptArgs(obj, msg, ...args));
473
+ const logFn: LogFn = (obj, msg, ...args) => invoke('log', ...adaptArgs(obj, msg, ...args));
474
+
475
+ /**
476
+ * Clear console and memory buffer
477
+ */
478
+ const clear = (): void => {
479
+ try {
480
+ if (typeof console?.clear === 'function') {
481
+ console.clear();
482
+ }
483
+ } catch {
484
+ // Silent fail
485
+ }
486
+ globalInMemoryDestination.clear();
487
+ };
488
+
489
+ /**
490
+ * Create child logger with additional bindings
491
+ */
492
+ const child = (childBindings: Record<string, unknown>): Logger => {
493
+ return createLogger({ level: currentLevel, ...base, ...childBindings });
494
+ };
495
+
496
+ return {
497
+ level: currentLevel,
498
+ trace,
499
+ debug,
500
+ info,
501
+ warn,
502
+ error,
503
+ fatal,
504
+ success,
505
+ progress,
506
+ log: logFn,
507
+ clear,
508
+ child,
509
+ };
510
+ }
511
+
512
+ // ============================================================================
513
+ // Exports
514
+ // ============================================================================
515
+
516
+ // Create default logger instance
517
+ const logger = createLogger();
518
+
519
+ // Backward compatibility alias
520
+ export const elizaLogger = logger;
521
+
522
+ // Export recent logs function
523
+ export const recentLogs = (): string => globalInMemoryDestination.recentLogs();
524
+
525
+ // Export everything
526
+ export { logger, createLogger };
527
+ export default logger;