UNPKG

@neuroequalityorg/knightcode

Version:

Knightcode CLI - Your local AI coding assistant using Ollama, LM Studio, and more

253 lines (220 loc) 5.55 kB
/** * Logger * * Provides a consistent logging interface across the application. * Supports multiple log levels, formatting, and output destinations. */ import { ErrorLevel } from '../errors/types.js'; /** * Log levels */ export enum LogLevel { DEBUG = 0, INFO = 1, WARN = 2, ERROR = 3, SILENT = 4 } /** * Logger configuration */ export interface LoggerConfig { /** * Minimum log level to display */ level: LogLevel; /** * Whether to include timestamps in logs */ timestamps: boolean; /** * Whether to colorize output */ colors: boolean; /** * Whether to include additional context in logs */ verbose: boolean; /** * Custom output destination (defaults to console) */ destination?: (message: string, level: LogLevel) => void; } /** * Default logger configuration */ const DEFAULT_CONFIG: LoggerConfig = { level: LogLevel.INFO, timestamps: true, colors: true, verbose: false }; /** * Logger class */ class Logger { private config: LoggerConfig; constructor(config: Partial<LoggerConfig> = {}) { this.config = { ...DEFAULT_CONFIG, ...config }; } /** * Set logger configuration */ configure(config: Partial<LoggerConfig>): void { this.config = { ...this.config, ...config }; } /** * Set log level */ setLevel(level: LogLevel): void { this.config.level = level; } /** * Log a debug message */ debug(message: string, context?: any): void { this.log(message, LogLevel.DEBUG, context); } /** * Log an info message */ info(message: string, context?: any): void { this.log(message, LogLevel.INFO, context); } /** * Log a warning message */ warn(message: string, context?: any): void { this.log(message, LogLevel.WARN, context); } /** * Log an error message */ error(message: string, context?: any): void { this.log(message, LogLevel.ERROR, context); } /** * Log a message with level */ private log(message: string, level: LogLevel, context?: any): void { // Check if this log level should be displayed if (level < this.config.level) { return; } // Format the message const formattedMessage = this.formatMessage(message, level, context); // Send to destination if (this.config.destination) { this.config.destination(formattedMessage, level); } else { this.logToConsole(formattedMessage, level); } } /** * Format a log message */ private formatMessage(message: string, level: LogLevel, context?: any): string { let result = ''; // Add timestamp if enabled if (this.config.timestamps) { const timestamp = new Date().toISOString(); result += `[${timestamp}] `; } // Add log level result += `${this.getLevelName(level)}: `; // Add message result += message; // Add context if verbose and context is provided if (this.config.verbose && context) { try { if (typeof context === 'object') { const contextStr = JSON.stringify(context); result += ` ${contextStr}`; } else { result += ` ${context}`; } } catch (error) { result += ' [Context serialization failed]'; } } return result; } /** * Get the name of a log level */ private getLevelName(level: LogLevel): string { switch (level) { case LogLevel.DEBUG: return this.colorize('DEBUG', '\x1b[36m'); // Cyan case LogLevel.INFO: return this.colorize('INFO', '\x1b[32m'); // Green case LogLevel.WARN: return this.colorize('WARN', '\x1b[33m'); // Yellow case LogLevel.ERROR: return this.colorize('ERROR', '\x1b[31m'); // Red default: return 'UNKNOWN'; } } /** * Colorize a string if colors are enabled */ private colorize(text: string, colorCode: string): string { if (!this.config.colors) { return text; } return `${colorCode}${text}\x1b[0m`; } /** * Log to console */ private logToConsole(message: string, level: LogLevel): void { switch (level) { case LogLevel.DEBUG: console.debug(message); break; case LogLevel.INFO: console.info(message); break; case LogLevel.WARN: console.warn(message); break; case LogLevel.ERROR: console.error(message); break; } } /** * Convert ErrorLevel to LogLevel */ errorLevelToLogLevel(level: ErrorLevel): LogLevel { switch (level) { case ErrorLevel.DEBUG: return LogLevel.DEBUG; case ErrorLevel.INFO: return LogLevel.INFO; case ErrorLevel.WARNING: return LogLevel.WARN; case ErrorLevel.ERROR: case ErrorLevel.CRITICAL: case ErrorLevel.FATAL: return LogLevel.ERROR; default: return LogLevel.INFO; } } } // Create singleton logger instance export const logger = new Logger(); // Configure logger based on environment if (process.env.NODE_ENV === 'development' || process.env.DEBUG === 'true') { logger.setLevel(LogLevel.DEBUG); } else if (process.env.VERBOSE === 'true') { logger.configure({ verbose: true }); } else if (process.env.LOG_LEVEL) { const level = parseInt(process.env.LOG_LEVEL, 10); if (!isNaN(level) && level >= LogLevel.DEBUG && level <= LogLevel.SILENT) { logger.setLevel(level as LogLevel); } } export default logger;