UNPKG

il2cpp-dump-analyzer-mcp

Version:

Agentic RAG system for analyzing IL2CPP dump.cs files from Unity games

277 lines 11.1 kB
"use strict"; /** * Base Tool Handler for MCP Tools * Eliminates code duplication by providing a common foundation for all MCP tool implementations */ Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseGenerationToolHandler = exports.BaseAnalysisToolHandler = exports.BaseSearchToolHandler = exports.BaseMCPToolHandler = void 0; const parameter_validator_1 = require("../utils/parameter-validator"); const mcp_response_formatter_1 = require("../utils/mcp-response-formatter"); const error_types_1 = require("./error-types"); /** * Abstract base class for all MCP tool handlers */ class BaseMCPToolHandler { constructor(config, context) { this.startTime = 0; this.config = config; this.context = context; } /** * Main execution method - handles the complete tool lifecycle */ async execute(params) { this.startTime = Date.now(); try { // Step 1: Ensure system is initialized this.ensureInitialized(); // Step 2: Log tool execution start this.logToolStart(params); // Step 3: Validate parameters const validation = await this.validateParameters(params); if (!validation.isValid) { throw new parameter_validator_1.ParameterValidationError(validation.errors, validation.warnings); } // Step 4: Apply parameter adjustments const adjustedParams = this.applyParameterAdjustments(params, validation.adjustedValues); // Step 5: Execute core tool logic const result = await this.executeCore(adjustedParams); // Step 6: Format and return response const response = this.formatResponse(result, validation.warnings); // Step 7: Log successful completion this.logToolCompletion(result); return response; } catch (error) { // Handle and format errors consistently return this.handleError(error, params); } } /** * Validate tool parameters - can be overridden by subclasses */ async validateParameters(params) { if (!this.config.enableParameterValidation) { return { isValid: true, errors: [], warnings: [] }; } // Default validation using common parameters return parameter_validator_1.ParameterValidator.validateCommonParams(params); } /** * Apply parameter adjustments from validation */ applyParameterAdjustments(originalParams, adjustedValues) { if (!adjustedValues) { return originalParams; } return { ...originalParams, ...adjustedValues }; } /** * Format the tool response - can be overridden by subclasses */ formatResponse(result, warnings = []) { if (!this.config.enableResponseFormatting) { return mcp_response_formatter_1.MCPResponseFormatter.formatTextResponse(result); } const executionTime = Date.now() - this.startTime; let response = mcp_response_formatter_1.MCPResponseFormatter.formatAnalysisResults(result, this.config.name, {}, executionTime); if (warnings.length > 0) { response = mcp_response_formatter_1.MCPResponseFormatter.addWarnings(response, warnings); } return mcp_response_formatter_1.MCPResponseFormatter.addExecutionTiming(response, this.startTime, this.config.name); } /** * Handle errors consistently across all tools */ handleError(error, params) { const executionTime = Date.now() - this.startTime; this.context.logger.error(`Error in ${this.config.name} tool:`, error); // Handle parameter validation errors if (error instanceof parameter_validator_1.ParameterValidationError) { return mcp_response_formatter_1.MCPResponseFormatter.formatValidationResults(false, error.errors, error.warnings); } // Handle MCP server errors if (error instanceof error_types_1.MCPServerError) { throw error; // Re-throw MCP errors to be handled by the framework } // Handle generic errors const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new error_types_1.MCPServerError(`Tool execution error: ${errorMessage}`, error_types_1.ErrorType.TOOL_EXECUTION_ERROR); } /** * Ensure the system is properly initialized */ ensureInitialized() { if (!this.context.isInitialized()) { throw new error_types_1.MCPServerError('MCP server not initialized. Please wait for initialization to complete.', error_types_1.ErrorType.INITIALIZATION_ERROR); } } /** * Log tool execution start */ logToolStart(params) { this.context.logger.debug(`Tool call: ${this.config.name}`, { parameters: this.sanitizeParamsForLogging(params) }); } /** * Log tool execution completion */ logToolCompletion(result) { const executionTime = Date.now() - this.startTime; this.context.logger.debug(`${this.config.name} completed successfully in ${executionTime}ms`); } /** * Sanitize parameters for logging (remove sensitive data) */ sanitizeParamsForLogging(params) { // Override in subclasses if needed to remove sensitive parameters return params; } /** * Helper method for vector store searches with consistent error handling */ async performVectorSearch(query, filter = {}, limit = 5) { try { if (Object.keys(filter).length > 0) { return await this.context.vectorStore.searchWithFilter(query, filter, limit); } else { return await this.context.vectorStore.similaritySearch(query, limit); } } catch (error) { this.context.logger.error('Vector search failed:', error); throw new error_types_1.MCPServerError(`Search operation failed: ${error instanceof Error ? error.message : 'Unknown error'}`, error_types_1.ErrorType.TOOL_EXECUTION_ERROR); } } /** * Helper method to create search filters from parameters */ createSearchFilter(params) { const filter = {}; if (params.filter_type) filter.type = params.filter_type; if (params.filter_namespace) filter.namespace = params.filter_namespace; if (params.filter_monobehaviour) filter.isMonoBehaviour = true; return filter; } /** * Helper method to extract and validate query from parameters */ extractQuery(params) { return parameter_validator_1.ParameterValidator.validateQuery(params.query || params.class_name || ''); } } exports.BaseMCPToolHandler = BaseMCPToolHandler; /** * Specialized base class for search-based tools */ class BaseSearchToolHandler extends BaseMCPToolHandler { /** * Execute search and format results */ async executeCore(params) { const query = this.extractQuery(params); const filter = this.createSearchFilter(params); const limit = params.top_k || 5; return await this.performVectorSearch(query, filter, limit); } /** * Format search results with metadata */ formatResponse(results, warnings = []) { const query = this.extractQuery({}); const filter = this.createSearchFilter({}); let response = mcp_response_formatter_1.MCPResponseFormatter.formatSearchResults(results, query, filter, { totalTime: Date.now() - this.startTime, warnings }); return mcp_response_formatter_1.MCPResponseFormatter.addExecutionTiming(response, this.startTime, this.config.name); } } exports.BaseSearchToolHandler = BaseSearchToolHandler; /** * Specialized base class for analysis tools */ class BaseAnalysisToolHandler extends BaseMCPToolHandler { /** * Perform analysis with consistent error handling and logging */ async performAnalysis(analysisFunction) { try { this.context.logger.debug(`Starting ${this.config.name} analysis`); const result = await analysisFunction(); this.context.logger.debug(`${this.config.name} analysis completed`); return result; } catch (error) { this.context.logger.error(`${this.config.name} analysis failed:`, error); throw error; } } } exports.BaseAnalysisToolHandler = BaseAnalysisToolHandler; /** * Specialized base class for code generation tools */ class BaseGenerationToolHandler extends BaseMCPToolHandler { /** * Perform code generation with consistent error handling and logging */ async performGeneration(generationFunction) { try { this.context.logger.debug(`Starting ${this.config.name} code generation`); const result = await generationFunction(); this.context.logger.debug(`${this.config.name} code generation completed`); return result; } catch (error) { this.context.logger.error(`${this.config.name} code generation failed:`, error); throw error; } } /** * Validate class name for generation */ validateClassNameForGeneration(className) { const errors = []; const warnings = []; if (!className || typeof className !== 'string') { errors.push('class_name is required and must be a string'); } else { const trimmed = className.trim(); if (trimmed.length === 0) { errors.push('class_name cannot be empty'); } else if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(trimmed)) { errors.push('class_name must be a valid identifier (letters, numbers, underscore, starting with letter)'); } else if (!/^[A-Z]/.test(trimmed)) { warnings.push('class_name should follow PascalCase convention'); } } return { isValid: errors.length === 0, errors, warnings }; } /** * Format generation results with metadata */ formatGenerationResponse(generatedCode, metadata, warnings = []) { const allWarnings = [...warnings, ...(metadata.warnings || [])]; let response = mcp_response_formatter_1.MCPResponseFormatter.formatGenerationResults(generatedCode, { ...metadata, warnings: allWarnings }); if (allWarnings.length > 0) { response = mcp_response_formatter_1.MCPResponseFormatter.addWarnings(response, allWarnings); } return mcp_response_formatter_1.MCPResponseFormatter.addExecutionTiming(response, this.startTime, this.config.name); } } exports.BaseGenerationToolHandler = BaseGenerationToolHandler; //# sourceMappingURL=base-tool-handler.js.map