utilities.js•6.49 kB
import { existsSync } from 'fs';
import { join, resolve } from 'path';
export function createToolResponse(content, isError = false) {
  return {
    content: [{ type: "text", text: content }],
    isError
  };
}
export function createErrorResponse(message, details = null) {
  let response = `❌ Error: ${message}`;
  if (details) {
    response += `\n\n${details}`;
  }
  return createToolResponse(response, true);
}
export function validateRequiredParams(params, requiredParams) {
  const missing = requiredParams.filter(param => !params[param]);
  if (missing.length > 0) {
    return {
      isValid: false,
      error: `Missing required parameters: ${missing.join(', ')}`
    };
  }
  return { isValid: true };
}
export function validateWorkingDirectory(workingDir) {
  if (!workingDir) {
    return {
      isValid: false,
      error: 'Working directory is required'
    };
  }
  const resolvedDir = resolve(workingDir);
  if (!existsSync(resolvedDir)) {
    return {
      isValid: false,
      error: `Working directory does not exist: ${resolvedDir}`
    };
  }
  return { isValid: true, resolvedDir };
}
export function truncateContent(content, maxLength = 10000) {
  if (content.length <= maxLength) {
    return content;
  }
  const truncated = content.substring(0, maxLength);
  const lastNewline = truncated.lastIndexOf('\n');
  if (lastNewline > maxLength * 0.8) {
    return truncated.substring(0, lastNewline) + '\n...[truncated]';
  }
  return truncated + '\n...[truncated]';
}
export function formatToolResponse(content) {
  return typeof content === 'string' ? content : JSON.stringify(content, null, 2);
}
export function createTimeoutPromise(timeoutMs, operation = 'Operation') {
  return new Promise((_, reject) => {
    setTimeout(() => {
      reject(new Error(`${operation} timed out after ${timeoutMs}ms`));
    }, timeoutMs);
  });
}
export function handleAsyncError(error, context = 'Operation') {
  console.error(`❌ ${context} error:`, error);
  if (error.code === 'ENOENT') {
    return createErrorResponse('File not found', error.message);
  }
  if (error.code === 'EACCES') {
    return createErrorResponse('Permission denied', error.message);
  }
  if (error.name === 'TimeoutError') {
    return createErrorResponse('Operation timed out', 'The operation took too long to complete');
  }
  return createErrorResponse(`${context} failed`, error.message);
}
export function getDefaultIgnorePatterns() {
  return [
    'node_modules/**',
    '.git/**',
    'dist/**',
    'build/**',
    'out/**',
    '.next/**',
    '.nuxt/**',
    '.cache/**',
    '.vscode/**',
    '.idea/**',
    '*.log',
    '*.tmp',
    '.env*',
    'coverage/**',
    '.pytest_cache/**',
    '__pycache__/**',
    '*.pyc',
    '.DS_Store',
    'Thumbs.db',
    '*.min.js',
    '*.min.css',
    'package-lock.json',
    'yarn.lock',
    'pnpm-lock.yaml'
  ];
}
export function shouldIgnoreFile(filePath, ignorePatterns = null) {
  if (!ignorePatterns) {
    ignorePatterns = getDefaultIgnorePatterns();
  }
  const normalizedPath = filePath.replace(/\\/g, '/');
  return ignorePatterns.some(pattern => {
    const regexPattern = pattern
      .replace(/\*\*/g, '.*')
      .replace(/\*/g, '[^/]*')
      .replace(/\?/g, '.');
    try {
      const regex = new RegExp(`^${regexPattern}$`);
      return regex.test(normalizedPath);
    } catch (e) {
      return normalizedPath.includes(pattern.replace(/\*\*/g, '').replace(/\*/g, ''));
    }
  });
}
export function createToolConfig(name, description, inputSchema, handler) {
  return {
    name,
    description,
    inputSchema,
    handler: createToolHandler(handler, name)
  };
}
function createToolHandler(handler, toolName) {
  return async (args) => {
    try {
      console.log(`🔧 Executing ${toolName} with args:`, JSON.stringify(args, null, 2));
      const result = await handler(args);
      console.log(`✅ ${toolName} completed successfully`);
      return result;
    } catch (error) {
      console.error(`❌ ${toolName} failed:`, error);
      return handleAsyncError(error, toolName);
    }
  };
}
export function ensureAbsolutePaths(paths, basePath) {
  return paths.map(path => {
    if (path.startsWith('/')) {
      return path;
    }
    return join(basePath, path);
  });
}
export function getRelativePath(filePath, basePath) {
  const absolutePath = resolve(filePath);
  const absoluteBase = resolve(basePath);
  if (absolutePath.startsWith(absoluteBase)) {
    return absolutePath.substring(absoluteBase.length).replace(/^\/+/, '');
  }
  return absolutePath;
}
export function createPaginationResponse(items, page, pageSize, total) {
  const totalPages = Math.ceil(total / pageSize);
  const hasNext = page < totalPages;
  const hasPrev = page > 1;
  return {
    items,
    pagination: {
      currentPage: page,
      pageSize,
      totalItems: total,
      totalPages,
      hasNext,
      hasPrev
    }
  };
}
export function createSearchQuery(term, options = {}) {
  const { exactMatch = false, caseSensitive = false } = options;
  if (exactMatch) {
    return caseSensitive ? `"${term}"` : `"${term}"`;
  }
  return caseSensitive ? term : term.toLowerCase();
}
export function highlightMatches(text, query, caseSensitive = false) {
  if (!query) return text;
  const flags = caseSensitive ? 'g' : 'gi';
  const regex = new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), flags);
  return text.replace(regex, match => `**${match}**`);
}
export function logDebug(message, data = null) {
  if (process.env.DEBUG || process.env.NODE_ENV === 'development') {
    console.log(`🔍 [DEBUG] ${message}`, data ? JSON.stringify(data, null, 2) : '');
  }
}
export function logPerformance(operation, startTime) {
  const duration = Date.now() - startTime;
  console.log(`⏱️ ${operation} completed in ${duration}ms`);
  if (duration > 5000) {
    console.warn(`⚠️ ${operation} took ${duration}ms - consider optimization`);
  }
}
export function generateId() {
  return Math.random().toString(36).substr(2, 9);
}
export default {
  createToolResponse,
  createErrorResponse,
  validateRequiredParams,
  validateWorkingDirectory,
  truncateContent,
  formatToolResponse,
  createTimeoutPromise,
  handleAsyncError,
  getDefaultIgnorePatterns,
  shouldIgnoreFile,
  createToolConfig,
  ensureAbsolutePaths,
  getRelativePath,
  createPaginationResponse,
  createSearchQuery,
  highlightMatches,
  logDebug,
  logPerformance,
  generateId
};