converse-mcp-server 2.3.1 → 2.4.1

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 (42) hide show
  1. package/README.md +771 -738
  2. package/docs/API.md +10 -1
  3. package/docs/PROVIDERS.md +8 -4
  4. package/package.json +12 -12
  5. package/src/async/asyncJobStore.js +82 -52
  6. package/src/async/eventBus.js +25 -20
  7. package/src/async/fileCache.js +121 -40
  8. package/src/async/jobRunner.js +65 -39
  9. package/src/async/providerStreamNormalizer.js +203 -117
  10. package/src/config.js +374 -102
  11. package/src/continuationStore.js +32 -24
  12. package/src/index.js +45 -25
  13. package/src/prompts/helpPrompt.js +328 -305
  14. package/src/providers/anthropic.js +303 -119
  15. package/src/providers/codex.js +103 -45
  16. package/src/providers/deepseek.js +24 -8
  17. package/src/providers/google.js +337 -93
  18. package/src/providers/index.js +1 -1
  19. package/src/providers/interface.js +16 -11
  20. package/src/providers/mistral.js +179 -69
  21. package/src/providers/openai-compatible.js +231 -94
  22. package/src/providers/openai.js +1094 -914
  23. package/src/providers/openrouter-endpoints-client.js +220 -216
  24. package/src/providers/openrouter.js +426 -381
  25. package/src/providers/xai.js +153 -56
  26. package/src/resources/helpResource.js +70 -67
  27. package/src/router.js +95 -67
  28. package/src/services/summarizationService.js +51 -24
  29. package/src/systemPrompts.js +89 -89
  30. package/src/tools/cancelJob.js +31 -19
  31. package/src/tools/chat.js +997 -883
  32. package/src/tools/checkStatus.js +86 -65
  33. package/src/tools/consensus.js +400 -234
  34. package/src/tools/index.js +39 -16
  35. package/src/transport/httpTransport.js +82 -55
  36. package/src/utils/contextProcessor.js +54 -37
  37. package/src/utils/errorHandler.js +95 -45
  38. package/src/utils/fileValidator.js +107 -98
  39. package/src/utils/formatStatus.js +122 -64
  40. package/src/utils/logger.js +459 -449
  41. package/src/utils/pathUtils.js +2 -2
  42. package/src/utils/tokenLimiter.js +216 -216
@@ -1,450 +1,460 @@
1
- /**
2
- * Logger Utility
3
- *
4
- * Structured logging system with different log levels and development/production modes.
5
- * Provides consistent logging interface across all modules with proper error handling.
6
- */
7
-
8
- import { inspect } from 'util';
9
-
10
- /**
11
- * Check if console output should be suppressed
12
- * @returns {boolean} True if console output should be suppressed
13
- */
14
- function shouldSuppressConsole() {
15
- return process.env.LOG_LEVEL === 'silent' ||
16
- process.env.NODE_ENV === 'test' ||
17
- process.env.MCP_TRANSPORT === 'stdio';
18
- }
19
-
20
- /**
21
- * Log levels in order of severity (lower number = higher severity)
22
- */
23
- const LOG_LEVELS = {
24
- silent: -1,
25
- error: 0,
26
- warn: 1,
27
- info: 2,
28
- debug: 3,
29
- trace: 4
30
- };
31
-
32
- /**
33
- * Logger configuration
34
- */
35
- let loggerConfig = {
36
- level: process.env.LOG_LEVEL || 'info',
37
- isDevelopment: process.env.NODE_ENV === 'development',
38
- enableColors: process.env.NODE_ENV !== 'production',
39
- enableTimestamps: true,
40
- enableStackTrace: process.env.NODE_ENV === 'development'
41
- };
42
-
43
- /**
44
- * ANSI color codes for console output
45
- */
46
- const COLORS = {
47
- reset: '\x1b[0m',
48
- bright: '\x1b[1m',
49
- dim: '\x1b[2m',
50
- red: '\x1b[31m',
51
- green: '\x1b[32m',
52
- yellow: '\x1b[33m',
53
- blue: '\x1b[34m',
54
- magenta: '\x1b[35m',
55
- cyan: '\x1b[36m',
56
- white: '\x1b[37m',
57
- gray: '\x1b[90m'
58
- };
59
-
60
- /**
61
- * Log level color mapping
62
- */
63
- const LEVEL_COLORS = {
64
- error: COLORS.red,
65
- warn: COLORS.yellow,
66
- info: COLORS.green,
67
- debug: COLORS.blue,
68
- trace: COLORS.gray
69
- };
70
-
71
- /**
72
- * Format timestamp for log entries
73
- * @returns {string} Formatted timestamp
74
- */
75
- function formatTimestamp() {
76
- return new Date().toISOString();
77
- }
78
-
79
- /**
80
- * Format log level for display
81
- * @param {string} level - Log level
82
- * @returns {string} Formatted log level
83
- */
84
- function formatLevel(level) {
85
- const upperLevel = level.toUpperCase().padEnd(5);
86
- if (loggerConfig.enableColors) {
87
- const color = LEVEL_COLORS[level] || COLORS.white;
88
- return `${color}${upperLevel}${COLORS.reset}`;
89
- }
90
- return upperLevel;
91
- }
92
-
93
- /**
94
- * Format context information
95
- * @param {string} module - Module name
96
- * @param {string} operation - Operation name
97
- * @returns {string} Formatted context
98
- */
99
- function formatContext(module, operation) {
100
- if (!module && !operation) return '';
101
-
102
- const context = [module, operation].filter(Boolean).join(':');
103
- if (loggerConfig.enableColors) {
104
- return `${COLORS.dim}[${context}]${COLORS.reset}`;
105
- }
106
- return `[${context}]`;
107
- }
108
-
109
- /**
110
- * Format error objects for logging
111
- * @param {Error} error - Error object
112
- * @returns {object} Formatted error information
113
- */
114
- function formatError(error) {
115
- if (!(error instanceof Error)) {
116
- return { error };
117
- }
118
-
119
- const errorInfo = {
120
- name: error.name,
121
- message: error.message,
122
- code: error.code,
123
- details: error.details
124
- };
125
-
126
- if (loggerConfig.enableStackTrace && error.stack) {
127
- errorInfo.stack = error.stack;
128
- }
129
-
130
- return errorInfo;
131
- }
132
-
133
- /**
134
- * Format log data for output
135
- * @param {any} data - Data to format
136
- * @returns {string} Formatted data
137
- */
138
- function formatData(data) {
139
- if (data === null || data === undefined) {
140
- return '';
141
- }
142
-
143
- if (typeof data === 'string') {
144
- return data;
145
- }
146
-
147
- if (data instanceof Error) {
148
- const errorInfo = formatError(data);
149
- if (loggerConfig.isDevelopment) {
150
- return inspect(errorInfo, { depth: 3, colors: loggerConfig.enableColors });
151
- }
152
- return JSON.stringify(errorInfo);
153
- }
154
-
155
- if (typeof data === 'object') {
156
- if (loggerConfig.isDevelopment) {
157
- return inspect(data, { depth: 2, colors: loggerConfig.enableColors });
158
- }
159
- return JSON.stringify(data);
160
- }
161
-
162
- return String(data);
163
- }
164
-
165
- /**
166
- * Check if log level should be output
167
- * @param {string} level - Log level to check
168
- * @returns {boolean} True if should log
169
- */
170
- function shouldLog(level) {
171
- const currentLevel = LOG_LEVELS[loggerConfig.level] || LOG_LEVELS.info;
172
- const messageLevel = LOG_LEVELS[level] || LOG_LEVELS.info;
173
- return messageLevel <= currentLevel;
174
- }
175
-
176
- /**
177
- * Core logging function
178
- * @param {string} level - Log level
179
- * @param {string} message - Log message
180
- * @param {object} metadata - Additional metadata
181
- */
182
- function log(level, message, metadata = {}) {
183
- if (!shouldLog(level)) {
184
- return;
185
- }
186
-
187
- const timestamp = loggerConfig.enableTimestamps ? formatTimestamp() : null;
188
- const formattedLevel = formatLevel(level);
189
- const context = formatContext(metadata.module, metadata.operation);
190
-
191
- // Build log parts
192
- const parts = [
193
- timestamp,
194
- formattedLevel,
195
- context,
196
- message
197
- ].filter(Boolean);
198
-
199
- // Output main log line
200
- const logLine = parts.join(' ');
201
-
202
- if (!shouldSuppressConsole()) {
203
- if (level === 'error') {
204
- console.error(logLine);
205
- } else {
206
- console.log(logLine);
207
- }
208
- }
209
-
210
- // Output additional data if provided
211
- if (metadata.data !== undefined) {
212
- const formattedData = formatData(metadata.data);
213
- if (formattedData) {
214
- if (!shouldSuppressConsole()) {
215
- if (level === 'error') {
216
- console.error(formattedData);
217
- } else {
218
- console.log(formattedData);
219
- }
220
- }
221
- }
222
- }
223
-
224
- // Output error details if provided
225
- if (metadata.error && metadata.error instanceof Error) {
226
- const errorInfo = formatError(metadata.error);
227
- const formattedError = formatData(errorInfo);
228
- if (level === 'error') {
229
- if (!shouldSuppressConsole()) {
230
- console.error(formattedError);
231
- }
232
- } else {
233
- if (!shouldSuppressConsole()) {
234
- console.log(formattedError);
235
- }
236
- }
237
- }
238
- }
239
-
240
- /**
241
- * Create logger instance for a specific module
242
- * @param {string} moduleName - Name of the module
243
- * @returns {object} Logger instance
244
- */
245
- export function createLogger(moduleName) {
246
- return {
247
- /**
248
- * Log error message
249
- * @param {string} message - Error message
250
- * @param {object} metadata - Additional metadata
251
- */
252
- error(message, metadata = {}) {
253
- log('error', message, { ...metadata, module: moduleName });
254
- },
255
-
256
- /**
257
- * Log warning message
258
- * @param {string} message - Warning message
259
- * @param {object} metadata - Additional metadata
260
- */
261
- warn(message, metadata = {}) {
262
- log('warn', message, { ...metadata, module: moduleName });
263
- },
264
-
265
- /**
266
- * Log info message
267
- * @param {string} message - Info message
268
- * @param {object} metadata - Additional metadata
269
- */
270
- info(message, metadata = {}) {
271
- log('info', message, { ...metadata, module: moduleName });
272
- },
273
-
274
- /**
275
- * Log debug message
276
- * @param {string} message - Debug message
277
- * @param {object} metadata - Additional metadata
278
- */
279
- debug(message, metadata = {}) {
280
- log('debug', message, { ...metadata, module: moduleName });
281
- },
282
-
283
- /**
284
- * Log trace message
285
- * @param {string} message - Trace message
286
- * @param {object} metadata - Additional metadata
287
- */
288
- trace(message, metadata = {}) {
289
- log('trace', message, { ...metadata, module: moduleName });
290
- },
291
-
292
- /**
293
- * Log with custom operation context
294
- * @param {string} operation - Operation name
295
- * @returns {object} Logger with operation context
296
- */
297
- operation(operation) {
298
- return {
299
- error: (message, metadata = {}) => log('error', message, { ...metadata, module: moduleName, operation }),
300
- warn: (message, metadata = {}) => log('warn', message, { ...metadata, module: moduleName, operation }),
301
- info: (message, metadata = {}) => log('info', message, { ...metadata, module: moduleName, operation }),
302
- debug: (message, metadata = {}) => log('debug', message, { ...metadata, module: moduleName, operation }),
303
- trace: (message, metadata = {}) => log('trace', message, { ...metadata, module: moduleName, operation })
304
- };
305
- }
306
- };
307
- }
308
-
309
- /**
310
- * Configure logger settings
311
- * @param {object} config - Logger configuration
312
- */
313
- export function configureLogger(config) {
314
- loggerConfig = { ...loggerConfig, ...config };
315
- }
316
-
317
- /**
318
- * Get current logger configuration
319
- * @returns {object} Current configuration
320
- */
321
- export function getLoggerConfig() {
322
- return { ...loggerConfig };
323
- }
324
-
325
- /**
326
- * Global logger instance
327
- */
328
- export const logger = createLogger('global');
329
-
330
- /**
331
- * Create structured error for logging
332
- * @param {string} message - Error message
333
- * @param {string} code - Error code
334
- * @param {object} details - Error details
335
- * @param {Error} originalError - Original error
336
- * @returns {Error} Structured error
337
- */
338
- export function createStructuredError(message, code = 'UNKNOWN_ERROR', details = {}, originalError = null) {
339
- const error = new Error(message);
340
- error.code = code;
341
- error.details = details;
342
-
343
- if (originalError) {
344
- error.originalError = originalError;
345
- error.cause = originalError;
346
- }
347
-
348
- return error;
349
- }
350
-
351
- /**
352
- * Log performance timing
353
- * @param {string} operation - Operation name
354
- * @param {number} startTime - Start time in milliseconds
355
- * @param {object} metadata - Additional metadata
356
- */
357
- export function logTiming(operation, startTime, metadata = {}) {
358
- const duration = Date.now() - startTime;
359
-
360
- if (duration > 1000) {
361
- logger.warn(`Slow operation: ${operation}`, {
362
- ...metadata,
363
- data: { duration: `${duration}ms` }
364
- });
365
- } else if (duration > 100) {
366
- logger.info(`Operation completed: ${operation}`, {
367
- ...metadata,
368
- data: { duration: `${duration}ms` }
369
- });
370
- } else {
371
- logger.debug(`Operation completed: ${operation}`, {
372
- ...metadata,
373
- data: { duration: `${duration}ms` }
374
- });
375
- }
376
- }
377
-
378
- /**
379
- * Performance timer utility
380
- * @param {string} operation - Operation name
381
- * @param {string} module - Module name
382
- * @returns {function} Function to end timing
383
- */
384
- export function startTimer(operation, module = 'timer') {
385
- const startTime = Date.now();
386
- const moduleLogger = createLogger(module);
387
-
388
- moduleLogger.debug(`Starting: ${operation}`);
389
-
390
- return (result = 'completed', metadata = {}) => {
391
- const duration = Date.now() - startTime;
392
- moduleLogger.debug(`${result}: ${operation}`, {
393
- ...metadata,
394
- data: { duration: `${duration}ms` }
395
- });
396
- return duration;
397
- };
398
- }
399
-
400
- /**
401
- * Log function entry and exit (for debugging)
402
- * @param {string} functionName - Function name
403
- * @param {string} module - Module name
404
- * @returns {function} Function to end logging
405
- */
406
- export function logFunction(functionName, module = 'function') {
407
- const moduleLogger = createLogger(module);
408
- const startTime = Date.now();
409
-
410
- moduleLogger.trace(`Entering: ${functionName}`);
411
-
412
- return (result = 'completed', error = null) => {
413
- const duration = Date.now() - startTime;
414
-
415
- if (error) {
416
- moduleLogger.trace(`Exiting with error: ${functionName}`, {
417
- data: { duration: `${duration}ms` },
418
- error
419
- });
420
- } else {
421
- moduleLogger.trace(`Exiting: ${functionName}`, {
422
- data: { duration: `${duration}ms`, result }
423
- });
424
- }
425
- };
426
- }
427
-
428
- /**
429
- * Express error for consistent error logging across modules
430
- */
431
- export class LoggedError extends Error {
432
- constructor(message, code = 'LOGGED_ERROR', details = {}, logger = null) {
433
- super(message);
434
- this.name = 'LoggedError';
435
- this.code = code;
436
- this.details = details;
437
- this.timestamp = new Date().toISOString();
438
-
439
- // Log the error immediately
440
- if (logger) {
441
- logger.error(`${this.name}: ${message}`, {
442
- data: { code, details }
443
- });
444
- } else {
445
- global.logger?.error(`${this.name}: ${message}`, {
446
- data: { code, details }
447
- });
448
- }
449
- }
1
+ /**
2
+ * Logger Utility
3
+ *
4
+ * Structured logging system with different log levels and development/production modes.
5
+ * Provides consistent logging interface across all modules with proper error handling.
6
+ */
7
+
8
+ import { inspect } from 'util';
9
+
10
+ /**
11
+ * Check if console output should be suppressed
12
+ * @returns {boolean} True if console output should be suppressed
13
+ */
14
+ function shouldSuppressConsole() {
15
+ return (
16
+ process.env.LOG_LEVEL === 'silent' ||
17
+ process.env.NODE_ENV === 'test' ||
18
+ process.env.MCP_TRANSPORT === 'stdio'
19
+ );
20
+ }
21
+
22
+ /**
23
+ * Log levels in order of severity (lower number = higher severity)
24
+ */
25
+ const LOG_LEVELS = {
26
+ silent: -1,
27
+ error: 0,
28
+ warn: 1,
29
+ info: 2,
30
+ debug: 3,
31
+ trace: 4,
32
+ };
33
+
34
+ /**
35
+ * Logger configuration
36
+ */
37
+ let loggerConfig = {
38
+ level: process.env.LOG_LEVEL || 'info',
39
+ isDevelopment: process.env.NODE_ENV === 'development',
40
+ enableColors: process.env.NODE_ENV !== 'production',
41
+ enableTimestamps: true,
42
+ enableStackTrace: process.env.NODE_ENV === 'development',
43
+ };
44
+
45
+ /**
46
+ * ANSI color codes for console output
47
+ */
48
+ const COLORS = {
49
+ reset: '\x1b[0m',
50
+ bright: '\x1b[1m',
51
+ dim: '\x1b[2m',
52
+ red: '\x1b[31m',
53
+ green: '\x1b[32m',
54
+ yellow: '\x1b[33m',
55
+ blue: '\x1b[34m',
56
+ magenta: '\x1b[35m',
57
+ cyan: '\x1b[36m',
58
+ white: '\x1b[37m',
59
+ gray: '\x1b[90m',
60
+ };
61
+
62
+ /**
63
+ * Log level color mapping
64
+ */
65
+ const LEVEL_COLORS = {
66
+ error: COLORS.red,
67
+ warn: COLORS.yellow,
68
+ info: COLORS.green,
69
+ debug: COLORS.blue,
70
+ trace: COLORS.gray,
71
+ };
72
+
73
+ /**
74
+ * Format timestamp for log entries
75
+ * @returns {string} Formatted timestamp
76
+ */
77
+ function formatTimestamp() {
78
+ return new Date().toISOString();
79
+ }
80
+
81
+ /**
82
+ * Format log level for display
83
+ * @param {string} level - Log level
84
+ * @returns {string} Formatted log level
85
+ */
86
+ function formatLevel(level) {
87
+ const upperLevel = level.toUpperCase().padEnd(5);
88
+ if (loggerConfig.enableColors) {
89
+ const color = LEVEL_COLORS[level] || COLORS.white;
90
+ return `${color}${upperLevel}${COLORS.reset}`;
91
+ }
92
+ return upperLevel;
93
+ }
94
+
95
+ /**
96
+ * Format context information
97
+ * @param {string} module - Module name
98
+ * @param {string} operation - Operation name
99
+ * @returns {string} Formatted context
100
+ */
101
+ function formatContext(module, operation) {
102
+ if (!module && !operation) return '';
103
+
104
+ const context = [module, operation].filter(Boolean).join(':');
105
+ if (loggerConfig.enableColors) {
106
+ return `${COLORS.dim}[${context}]${COLORS.reset}`;
107
+ }
108
+ return `[${context}]`;
109
+ }
110
+
111
+ /**
112
+ * Format error objects for logging
113
+ * @param {Error} error - Error object
114
+ * @returns {object} Formatted error information
115
+ */
116
+ function formatError(error) {
117
+ if (!(error instanceof Error)) {
118
+ return { error };
119
+ }
120
+
121
+ const errorInfo = {
122
+ name: error.name,
123
+ message: error.message,
124
+ code: error.code,
125
+ details: error.details,
126
+ };
127
+
128
+ if (loggerConfig.enableStackTrace && error.stack) {
129
+ errorInfo.stack = error.stack;
130
+ }
131
+
132
+ return errorInfo;
133
+ }
134
+
135
+ /**
136
+ * Format log data for output
137
+ * @param {any} data - Data to format
138
+ * @returns {string} Formatted data
139
+ */
140
+ function formatData(data) {
141
+ if (data === null || data === undefined) {
142
+ return '';
143
+ }
144
+
145
+ if (typeof data === 'string') {
146
+ return data;
147
+ }
148
+
149
+ if (data instanceof Error) {
150
+ const errorInfo = formatError(data);
151
+ if (loggerConfig.isDevelopment) {
152
+ return inspect(errorInfo, {
153
+ depth: 3,
154
+ colors: loggerConfig.enableColors,
155
+ });
156
+ }
157
+ return JSON.stringify(errorInfo);
158
+ }
159
+
160
+ if (typeof data === 'object') {
161
+ if (loggerConfig.isDevelopment) {
162
+ return inspect(data, { depth: 2, colors: loggerConfig.enableColors });
163
+ }
164
+ return JSON.stringify(data);
165
+ }
166
+
167
+ return String(data);
168
+ }
169
+
170
+ /**
171
+ * Check if log level should be output
172
+ * @param {string} level - Log level to check
173
+ * @returns {boolean} True if should log
174
+ */
175
+ function shouldLog(level) {
176
+ const currentLevel = LOG_LEVELS[loggerConfig.level] || LOG_LEVELS.info;
177
+ const messageLevel = LOG_LEVELS[level] || LOG_LEVELS.info;
178
+ return messageLevel <= currentLevel;
179
+ }
180
+
181
+ /**
182
+ * Core logging function
183
+ * @param {string} level - Log level
184
+ * @param {string} message - Log message
185
+ * @param {object} metadata - Additional metadata
186
+ */
187
+ function log(level, message, metadata = {}) {
188
+ if (!shouldLog(level)) {
189
+ return;
190
+ }
191
+
192
+ const timestamp = loggerConfig.enableTimestamps ? formatTimestamp() : null;
193
+ const formattedLevel = formatLevel(level);
194
+ const context = formatContext(metadata.module, metadata.operation);
195
+
196
+ // Build log parts
197
+ const parts = [timestamp, formattedLevel, context, message].filter(Boolean);
198
+
199
+ // Output main log line
200
+ const logLine = parts.join(' ');
201
+
202
+ if (!shouldSuppressConsole()) {
203
+ if (level === 'error') {
204
+ console.error(logLine);
205
+ } else {
206
+ console.log(logLine);
207
+ }
208
+ }
209
+
210
+ // Output additional data if provided
211
+ if (metadata.data !== undefined) {
212
+ const formattedData = formatData(metadata.data);
213
+ if (formattedData) {
214
+ if (!shouldSuppressConsole()) {
215
+ if (level === 'error') {
216
+ console.error(formattedData);
217
+ } else {
218
+ console.log(formattedData);
219
+ }
220
+ }
221
+ }
222
+ }
223
+
224
+ // Output error details if provided
225
+ if (metadata.error && metadata.error instanceof Error) {
226
+ const errorInfo = formatError(metadata.error);
227
+ const formattedError = formatData(errorInfo);
228
+ if (level === 'error') {
229
+ if (!shouldSuppressConsole()) {
230
+ console.error(formattedError);
231
+ }
232
+ } else {
233
+ if (!shouldSuppressConsole()) {
234
+ console.log(formattedError);
235
+ }
236
+ }
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Create logger instance for a specific module
242
+ * @param {string} moduleName - Name of the module
243
+ * @returns {object} Logger instance
244
+ */
245
+ export function createLogger(moduleName) {
246
+ return {
247
+ /**
248
+ * Log error message
249
+ * @param {string} message - Error message
250
+ * @param {object} metadata - Additional metadata
251
+ */
252
+ error(message, metadata = {}) {
253
+ log('error', message, { ...metadata, module: moduleName });
254
+ },
255
+
256
+ /**
257
+ * Log warning message
258
+ * @param {string} message - Warning message
259
+ * @param {object} metadata - Additional metadata
260
+ */
261
+ warn(message, metadata = {}) {
262
+ log('warn', message, { ...metadata, module: moduleName });
263
+ },
264
+
265
+ /**
266
+ * Log info message
267
+ * @param {string} message - Info message
268
+ * @param {object} metadata - Additional metadata
269
+ */
270
+ info(message, metadata = {}) {
271
+ log('info', message, { ...metadata, module: moduleName });
272
+ },
273
+
274
+ /**
275
+ * Log debug message
276
+ * @param {string} message - Debug message
277
+ * @param {object} metadata - Additional metadata
278
+ */
279
+ debug(message, metadata = {}) {
280
+ log('debug', message, { ...metadata, module: moduleName });
281
+ },
282
+
283
+ /**
284
+ * Log trace message
285
+ * @param {string} message - Trace message
286
+ * @param {object} metadata - Additional metadata
287
+ */
288
+ trace(message, metadata = {}) {
289
+ log('trace', message, { ...metadata, module: moduleName });
290
+ },
291
+
292
+ /**
293
+ * Log with custom operation context
294
+ * @param {string} operation - Operation name
295
+ * @returns {object} Logger with operation context
296
+ */
297
+ operation(operation) {
298
+ return {
299
+ error: (message, metadata = {}) =>
300
+ log('error', message, { ...metadata, module: moduleName, operation }),
301
+ warn: (message, metadata = {}) =>
302
+ log('warn', message, { ...metadata, module: moduleName, operation }),
303
+ info: (message, metadata = {}) =>
304
+ log('info', message, { ...metadata, module: moduleName, operation }),
305
+ debug: (message, metadata = {}) =>
306
+ log('debug', message, { ...metadata, module: moduleName, operation }),
307
+ trace: (message, metadata = {}) =>
308
+ log('trace', message, { ...metadata, module: moduleName, operation }),
309
+ };
310
+ },
311
+ };
312
+ }
313
+
314
+ /**
315
+ * Configure logger settings
316
+ * @param {object} config - Logger configuration
317
+ */
318
+ export function configureLogger(config) {
319
+ loggerConfig = { ...loggerConfig, ...config };
320
+ }
321
+
322
+ /**
323
+ * Get current logger configuration
324
+ * @returns {object} Current configuration
325
+ */
326
+ export function getLoggerConfig() {
327
+ return { ...loggerConfig };
328
+ }
329
+
330
+ /**
331
+ * Global logger instance
332
+ */
333
+ export const logger = createLogger('global');
334
+
335
+ /**
336
+ * Create structured error for logging
337
+ * @param {string} message - Error message
338
+ * @param {string} code - Error code
339
+ * @param {object} details - Error details
340
+ * @param {Error} originalError - Original error
341
+ * @returns {Error} Structured error
342
+ */
343
+ export function createStructuredError(
344
+ message,
345
+ code = 'UNKNOWN_ERROR',
346
+ details = {},
347
+ originalError = null,
348
+ ) {
349
+ const error = new Error(message);
350
+ error.code = code;
351
+ error.details = details;
352
+
353
+ if (originalError) {
354
+ error.originalError = originalError;
355
+ error.cause = originalError;
356
+ }
357
+
358
+ return error;
359
+ }
360
+
361
+ /**
362
+ * Log performance timing
363
+ * @param {string} operation - Operation name
364
+ * @param {number} startTime - Start time in milliseconds
365
+ * @param {object} metadata - Additional metadata
366
+ */
367
+ export function logTiming(operation, startTime, metadata = {}) {
368
+ const duration = Date.now() - startTime;
369
+
370
+ if (duration > 1000) {
371
+ logger.warn(`Slow operation: ${operation}`, {
372
+ ...metadata,
373
+ data: { duration: `${duration}ms` },
374
+ });
375
+ } else if (duration > 100) {
376
+ logger.info(`Operation completed: ${operation}`, {
377
+ ...metadata,
378
+ data: { duration: `${duration}ms` },
379
+ });
380
+ } else {
381
+ logger.debug(`Operation completed: ${operation}`, {
382
+ ...metadata,
383
+ data: { duration: `${duration}ms` },
384
+ });
385
+ }
386
+ }
387
+
388
+ /**
389
+ * Performance timer utility
390
+ * @param {string} operation - Operation name
391
+ * @param {string} module - Module name
392
+ * @returns {function} Function to end timing
393
+ */
394
+ export function startTimer(operation, module = 'timer') {
395
+ const startTime = Date.now();
396
+ const moduleLogger = createLogger(module);
397
+
398
+ moduleLogger.debug(`Starting: ${operation}`);
399
+
400
+ return (result = 'completed', metadata = {}) => {
401
+ const duration = Date.now() - startTime;
402
+ moduleLogger.debug(`${result}: ${operation}`, {
403
+ ...metadata,
404
+ data: { duration: `${duration}ms` },
405
+ });
406
+ return duration;
407
+ };
408
+ }
409
+
410
+ /**
411
+ * Log function entry and exit (for debugging)
412
+ * @param {string} functionName - Function name
413
+ * @param {string} module - Module name
414
+ * @returns {function} Function to end logging
415
+ */
416
+ export function logFunction(functionName, module = 'function') {
417
+ const moduleLogger = createLogger(module);
418
+ const startTime = Date.now();
419
+
420
+ moduleLogger.trace(`Entering: ${functionName}`);
421
+
422
+ return (result = 'completed', error = null) => {
423
+ const duration = Date.now() - startTime;
424
+
425
+ if (error) {
426
+ moduleLogger.trace(`Exiting with error: ${functionName}`, {
427
+ data: { duration: `${duration}ms` },
428
+ error,
429
+ });
430
+ } else {
431
+ moduleLogger.trace(`Exiting: ${functionName}`, {
432
+ data: { duration: `${duration}ms`, result },
433
+ });
434
+ }
435
+ };
436
+ }
437
+
438
+ /**
439
+ * Express error for consistent error logging across modules
440
+ */
441
+ export class LoggedError extends Error {
442
+ constructor(message, code = 'LOGGED_ERROR', details = {}, logger = null) {
443
+ super(message);
444
+ this.name = 'LoggedError';
445
+ this.code = code;
446
+ this.details = details;
447
+ this.timestamp = new Date().toISOString();
448
+
449
+ // Log the error immediately
450
+ if (logger) {
451
+ logger.error(`${this.name}: ${message}`, {
452
+ data: { code, details },
453
+ });
454
+ } else {
455
+ global.logger?.error(`${this.name}: ${message}`, {
456
+ data: { code, details },
457
+ });
458
+ }
459
+ }
450
460
  }