ConsoleBackend.js 3.62 KB
/**
 * ConsoleBackend - 控制台输出后端
 *
 * 用于开发和调试,将日志输出到控制台
 */

const { BaseBackend } = require('./BaseBackend');

class ConsoleBackend extends BaseBackend {
  constructor(options = {}) {
    super({ name: 'console', ...options });
    this.colorize = options.colorize !== false;
    this.pretty = options.pretty !== false;
  }

  async init() {
    // 无需初始化
  }

  async write(entry) {
    if (!this._shouldLog(entry)) return;

    const formatted = this._formatEntry(entry);
    const output = this._formatForConsole(formatted);

    if (entry.level === 'error' || entry.level === 'fatal') {
      console.error(output);
    } else if (entry.level === 'warn') {
      console.warn(output);
    } else {
      console.log(output);
    }
  }

  async query(filters = {}) {
    // 控制台不支持查询
    return [];
  }

  /**
   * 格式化为控制台输出
   * @private
   */
  _formatForConsole(entry) {
    const { timestamp, level, category, agentName, eventType, payload, sequence } = entry;

    const time = new Date(timestamp).toLocaleTimeString();
    const agent = agentName ? `[${agentName}]` : '';
    const seq = sequence !== undefined ? `#${sequence}` : '';

    let output = '';

    if (this.pretty) {
      // 彩色格式化
      const colors = {
        reset: '\x1b[0m',
        dim: '\x1b[2m',
        bright: '\x1b[1m',
        red: '\x1b[31m',
        green: '\x1b[32m',
        yellow: '\x1b[33m',
        blue: '\x1b[34m',
        magenta: '\x1b[35m',
        cyan: '\x1b[36m',
      };

      const levelColors = {
        debug: colors.dim,
        info: colors.blue,
        warn: colors.yellow,
        error: colors.red,
        fatal: colors.red + colors.bright,
      };

      const categoryColors = {
        agent: colors.cyan,
        protocol: colors.magenta,
        tool: colors.green,
        file: colors.yellow,
        system: colors.dim,
      };

      const lc = this.colorize ? levelColors[level] || colors.reset : '';
      const cc = this.colorize ? categoryColors[category] || colors.reset : '';
      const rc = this.colorize ? colors.reset : '';

      output = `${colors.dim}${time}${rc} ${lc}[${level.toUpperCase()}]${rc} ${cc}[${category}]${rc}${agent} ${eventType} ${seq}`;

      // 添加 payload 摘要
      if (payload) {
        const payloadStr = this._summarizePayload(payload);
        if (payloadStr) {
          output += ` ${colors.dim}|${rc} ${payloadStr}`;
        }
      }
    } else {
      // 简单格式
      output = `[${time}] [${level}] [${category}]${agent} ${eventType} ${seq}`;

      if (payload) {
        const payloadStr = this._summarizePayload(payload);
        if (payloadStr) {
          output += ` | ${payloadStr}`;
        }
      }
    }

    return output;
  }

  /**
   * 摘要化 payload
   * @private
   */
  _summarizePayload(payload) {
    if (!payload) return '';

    // 流式输出摘要
    if (payload.chunk) {
      const text = payload.chunk.substring(0, 50).replace(/\n/g, '\\n');
      return `chunk: "${text}${payload.chunk.length > 50 ? '...' : ''}"`;
    }

    // 状态变更
    if (payload.status) {
      return `status: ${payload.status}`;
    }

    // 工具调用
    if (payload.toolName) {
      return `tool: ${payload.toolName}`;
    }

    // 文件操作
    if (payload.operation && payload.filePath) {
      return `${payload.operation}: ${payload.filePath}`;
    }

    // 默认:返回 JSON 摘要
    try {
      const str = JSON.stringify(payload);
      return str.length > 100 ? str.substring(0, 100) + '...' : str;
    } catch {
      return '[Object]';
    }
  }
}

module.exports = { ConsoleBackend };