Skip to main content
Glama

diff_method_signatures

Compare method signatures between caller and callee to identify parameter mismatches and provide actionable fixes for code analysis.

Instructions

Compare method signatures between caller and callee to identify parameter mismatches and provide actionable fixes

WORKFLOW: Perfect for understanding complex code, identifying issues, and technical debt assessment TIP: Use Desktop Commander to read files, then pass content here for analysis SAVES: Claude context for strategic decisions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
analysisDepthNoLevel of analysis detaildetailed
analysisTypeNoType of analysis to performcomprehensive
calledClassNoClass name containing the called method
callingFileNoAbsolute path to file containing the method call
codeNoThe code to analyze (for single-file analysis)
filePathNoPath to single file to analyze
filesNoArray of specific file paths (for multi-file analysis)
languageNoProgramming languagejavascript
maxDepthNoMaximum directory depth for multi-file discovery (1-5)
methodNameNoName of the method to check
projectPathNoPath to project root (for multi-file analysis)

Implementation Reference

  • The main handler implementation is the MethodSignatureDiffer class which extends BasePlugin and implements IPromptPlugin. It defines the tool name, parameters, description, and the core execute() method that orchestrates single-file, multi-file, and specific method signature comparison using LLM prompts with intelligent chunking and caching.
    export class MethodSignatureDiffer extends BasePlugin implements IPromptPlugin { name = 'diff_method_signatures'; category = 'analyze' as const; description = 'Compare method signatures between caller and callee to identify parameter mismatches and provide actionable fixes'; // Universal parameter set - supports both single and multi-file scenarios parameters = { // Single-file parameters code: { type: 'string' as const, description: 'The code to analyze (for single-file analysis)', required: false }, filePath: { type: 'string' as const, description: 'Path to single file to analyze', required: false }, // Multi-file parameters projectPath: { type: 'string' as const, description: 'Path to project root (for multi-file analysis)', required: false }, files: { type: 'array' as const, description: 'Array of specific file paths (for multi-file analysis)', required: false, items: { type: 'string' as const } }, maxDepth: { type: 'number' as const, description: 'Maximum directory depth for multi-file discovery (1-5)', required: false, default: 3 }, // Specific parameters for method signature comparison callingFile: { type: 'string' as const, description: 'Absolute path to file containing the method call', required: false }, calledClass: { type: 'string' as const, description: 'Class name containing the called method', required: false }, methodName: { type: 'string' as const, description: 'Name of the method to check', required: false }, // Universal parameters language: { type: 'string' as const, description: 'Programming language', required: false, default: 'javascript' }, analysisDepth: { type: 'string' as const, description: 'Level of analysis detail', enum: ['basic', 'detailed', 'comprehensive'], default: 'detailed', required: false }, analysisType: { type: 'string' as const, description: 'Type of analysis to perform', enum: ['signature', 'compatibility', 'comprehensive'], default: 'comprehensive', required: false } }; private analysisCache = getAnalysisCache(); private multiFileAnalysis = new MultiFileAnalysis(); constructor() { super(); // Cache and analysis utilities are initialized above } async execute(params: any, llmClient: any) { return await withSecurity(this, params, llmClient, async (secureParams) => { try { // 1. Auto-detect analysis mode based on parameters const analysisMode = this.detectAnalysisMode(secureParams); // 2. Validate parameters based on detected mode this.validateParameters(secureParams, analysisMode); // 3. Setup model const { model, contextLength } = await ModelSetup.getReadyModel(llmClient); // 4. Route to appropriate analysis method if (analysisMode === 'single-file') { return await this.executeSingleFileAnalysis(secureParams, model, contextLength); } else { return await this.executeMultiFileAnalysis(secureParams, model, contextLength); } } catch (error: any) { return ErrorHandler.createExecutionError('diff_method_signatures', error); } }); } /** * Auto-detect whether this is single-file or multi-file analysis */ private detectAnalysisMode(params: any): 'single-file' | 'multi-file' { // Single-file indicators take priority (avoids default parameter issues) if (params.code || params.filePath) { return 'single-file'; } // Multi-file indicators - method signature comparison typically requires multiple files if (params.projectPath || params.files || (params.callingFile && params.calledClass)) { return 'multi-file'; } // Default to multi-file for method signature comparison return 'multi-file'; } /** * Validate parameters based on detected analysis mode */ private validateParameters(params: any, mode: 'single-file' | 'multi-file'): void { if (mode === 'single-file') { ParameterValidator.validateCodeOrFile(params); } else { // For multi-file method signature comparison, we need either: // 1. Specific method signature params (callingFile + calledClass + methodName) // 2. General project analysis params (projectPath) if (params.callingFile && params.calledClass && params.methodName) { // Specific method signature comparison if (!params.callingFile || typeof params.callingFile !== 'string') { throw new Error('callingFile is required and must be a string for method signature comparison'); } if (!params.calledClass || typeof params.calledClass !== 'string') { throw new Error('calledClass is required and must be a string for method signature comparison'); } if (!params.methodName || typeof params.methodName !== 'string') { throw new Error('methodName is required and must be a string for method signature comparison'); } } else { // General project analysis ParameterValidator.validateProjectPath(params); ParameterValidator.validateDepth(params); } } // Universal validations ParameterValidator.validateEnum(params, 'analysisType', ['signature', 'compatibility', 'comprehensive']); ParameterValidator.validateEnum(params, 'analysisDepth', ['basic', 'detailed', 'comprehensive']); } /** * Execute single-file analysis */ private async executeSingleFileAnalysis(params: any, model: any, contextLength: number) { // Process single file input let codeToAnalyze = params.code; if (params.filePath) { codeToAnalyze = await readFileContent(params.filePath); } // Generate prompt stages for single file const promptStages = this.getSingleFilePromptStages({ ...params, code: codeToAnalyze }); // Execute with appropriate method const promptManager = new ThreeStagePromptManager(); const needsChunking = TokenCalculator.needsChunking(promptStages, contextLength); if (needsChunking) { const chunkSize = TokenCalculator.calculateOptimalChunkSize(promptStages, contextLength); const dataChunks = promptManager.chunkDataPayload(promptStages.dataPayload, chunkSize); const conversation = promptManager.createChunkedConversation(promptStages, dataChunks); const messages = [ conversation.systemMessage, ...conversation.dataMessages, conversation.analysisMessage ]; return await ResponseProcessor.executeChunked( messages, model, contextLength, 'diff_method_signatures', 'single' ); } else { return await ResponseProcessor.executeDirect( promptStages, model, contextLength, 'diff_method_signatures' ); } } /** * Execute multi-file analysis */ private async executeMultiFileAnalysis(params: any, model: any, contextLength: number) { // For specific method signature comparison if (params.callingFile && params.calledClass && params.methodName) { return await this.executeSpecificMethodComparison(params, model, contextLength); } // For general project analysis let filesToAnalyze: string[] = params.files || await this.discoverRelevantFiles( params.projectPath, params.maxDepth, params.analysisType ); // Perform multi-file analysis with caching const analysisResult = await this.performMultiFileAnalysis( filesToAnalyze, params, model, contextLength ); // Generate prompt stages for multi-file const promptStages = this.getMultiFilePromptStages({ ...params, analysisResult, fileCount: filesToAnalyze.length }); // Always use chunking for multi-file const promptManager = new ThreeStagePromptManager(); const chunkSize = TokenCalculator.calculateOptimalChunkSize(promptStages, contextLength); const dataChunks = promptManager.chunkDataPayload(promptStages.dataPayload, chunkSize); const conversation = promptManager.createChunkedConversation(promptStages, dataChunks); const messages = [ conversation.systemMessage, ...conversation.dataMessages, conversation.analysisMessage ]; return await ResponseProcessor.executeChunked( messages, model, contextLength, 'diff_method_signatures', 'multifile' ); } /** * Execute specific method signature comparison */ private async executeSpecificMethodComparison(params: any, model: any, contextLength: number) { try { // Read calling file const callingFileContent = await readFileContent(params.callingFile); // Find files that might contain the called class const { dirname } = await import('path'); const projectDir = dirname(params.callingFile); const classFiles = await this.findClassFiles(params.calledClass, projectDir); if (classFiles.length === 0) { throw new Error(`Could not find any files containing class: ${params.calledClass}`); } // Read class file contents const classFileContents: Record<string, string> = {}; for (const file of classFiles) { try { classFileContents[file] = await readFileContent(file); } catch (error) { // Skip files we can't read } } // Generate prompt stages for specific comparison const promptStages = this.getSpecificComparisonPromptStages({ ...params, callingFileContent, classFileContents }); // Execute with appropriate method const promptManager = new ThreeStagePromptManager(); const needsChunking = TokenCalculator.needsChunking(promptStages, contextLength); if (needsChunking) { const chunkSize = TokenCalculator.calculateOptimalChunkSize(promptStages, contextLength); const dataChunks = promptManager.chunkDataPayload(promptStages.dataPayload, chunkSize); const conversation = promptManager.createChunkedConversation(promptStages, dataChunks); const messages = [ conversation.systemMessage, ...conversation.dataMessages, conversation.analysisMessage ]; return await ResponseProcessor.executeChunked( messages, model, contextLength, 'diff_method_signatures', 'multifile' ); } else { return await ResponseProcessor.executeDirect( promptStages, model, contextLength, 'diff_method_signatures' ); } } catch (error: any) { return ErrorHandler.createExecutionError('diff_method_signatures', error); } } /** * Single-file prompt stages for method signature analysis within one file */ private getSingleFilePromptStages(params: any): PromptStages { const { code, language, analysisDepth, analysisType } = params; const systemAndContext = `You are a senior software engineer and code review expert specializing in ${analysisDepth} method signature analysis and compatibility assessment. **Your Expertise:** - 15+ years of experience in ${language} development - Deep understanding of method signatures, parameter passing, and type systems - Expert in identifying compatibility issues that cause runtime errors - Skilled at providing actionable, specific fix recommendations **Analysis Context:** - Language: ${language} - Analysis Depth: ${analysisDepth} - Analysis Type: ${analysisType} - Mode: Single File Analysis **Your Mission:** Analyze method signatures within this file to identify potential compatibility issues, parameter mismatches, and provide concrete solutions that prevent runtime errors.`; const dataPayload = `File content to analyze for method signature issues: \`\`\`${language} ${code} \`\`\``; const outputInstructions = `**COMPREHENSIVE METHOD SIGNATURE ANALYSIS** Provide your analysis in this structured format: ## Method Signature Issues Found ### Issue 1: [Type of Issue] - **Method**: \`methodName()\` - **Location**: Line X - **Problem**: Clear description of the signature issue - **Severity**: Critical/High/Medium/Low - **Impact**: What happens at runtime - **Fix**: Specific code change needed ### Issue 2: [Type of Issue] [Continue for all issues found...] ## Method Compatibility Assessment ### Well-Defined Methods ✅ - List methods with clear, compatible signatures ### Problematic Methods ⚠️ - List methods with potential issues ## Recommendations ### Immediate Actions Required 1. [Most critical fixes needed] 2. [Second priority fixes] ### Long-term Improvements 1. [Architectural suggestions] 2. [Best practice recommendations] ## Code Examples ### Before (Problematic): \`\`\`${language} // Show problematic signature \`\`\` ### After (Fixed): \`\`\`${language} // Show corrected signature \`\`\` **Analysis Confidence**: X%`; return { systemAndContext, dataPayload, outputInstructions }; } /** * Multi-file prompt stages for cross-file method signature analysis */ private getMultiFilePromptStages(params: any): PromptStages { const { analysisResult, analysisType, analysisDepth, fileCount } = params; const systemAndContext = `You are a senior software architect and integration specialist with ${analysisDepth} expertise in cross-file method signature compatibility. **Your Expertise:** - 20+ years of experience in large-scale software architecture - Expert in identifying integration issues between modules and classes - Deep knowledge of method signature compatibility across file boundaries - Proven track record of preventing runtime integration failures **Analysis Context:** - Analysis Type: ${analysisType} - Analysis Depth: ${analysisDepth} - Files Analyzed: ${fileCount} - Mode: Cross-File Integration Analysis **Your Mission:** Analyze method signatures across multiple files to identify integration risks, compatibility issues, and provide architectural recommendations for bulletproof inter-module communication.`; const dataPayload = `Cross-file method signature analysis results: ${JSON.stringify(analysisResult, null, 2)}`; const outputInstructions = `**CROSS-FILE METHOD SIGNATURE COMPATIBILITY REPORT** ## Executive Summary - **Total Integration Points**: [number] - **Critical Issues**: [number] - **Files at Risk**: [list] - **Overall Compatibility**: [percentage] ## Critical Integration Issues ### Issue 1: Method Signature Mismatch - **Caller**: \`File A, Line X\` - **Callee**: \`File B, Line Y\` - **Method**: \`className.methodName()\` - **Problem**: Detailed description of signature incompatibility - **Runtime Impact**: What breaks when this is called - **Severity**: Critical/High/Medium/Low - **Fix Strategy**: Step-by-step resolution approach [Continue for all critical issues...] ## Architecture Assessment ### Stable Integration Points ✅ - List well-designed, compatible method signatures ### Fragile Integration Points ⚠️ - List risky method calls requiring attention ### Missing Integration Points ❌ - Methods called but not found ## Compatibility Matrix | Caller File | Called Class | Method | Status | Risk Level | |-------------|--------------|---------|---------|------------| | FileA.js | ClassB | methodX | ⚠️ Mismatch | High | | FileC.ts | ClassD | methodY | ✅ Compatible | Low | ## Actionable Remediation Plan ### Phase 1: Critical Fixes (Do Now) 1. **Fix signature mismatch in ClassB.methodX** - Change: \`methodX(param1)\` → \`methodX(param1, param2)\` - Files to update: [specific files and lines] - Test strategy: [how to verify fix] ### Phase 2: Preventive Measures (Next Sprint) 1. [Improvements to prevent future issues] 2. [Tooling or process changes] ### Phase 3: Architecture Improvements (Future) 1. [Systematic improvements to method design] 2. [Interface standardization recommendations] ## Code Fixes ### Critical Fix Example: **Before (Broken):** \`\`\`javascript // Caller expects: user.updateProfile(name, email) // Method provides: updateProfile(profileData) \`\`\` **After (Fixed):** \`\`\`javascript // Updated method signature for compatibility \`\`\` **Risk Assessment**: [Low/Medium/High] risk of regression`; return { systemAndContext, dataPayload, outputInstructions }; } /** * Specific comparison prompt stages for targeted method signature analysis */ private getSpecificComparisonPromptStages(params: any): PromptStages { const { callingFile, calledClass, methodName, callingFileContent, classFileContents } = params; const getBasename = (filePath: string) => { const parts = filePath.replace(/\\/g, '/').split('/'); return parts[parts.length - 1]; }; const systemAndContext = `You are a world-class debugging specialist and method signature expert with forensic-level attention to detail. **Your Expertise:** - 25+ years of experience hunting down method signature bugs - Expert in parameter compatibility, type coercion, and runtime behavior - Legendary ability to spot subtle signature mismatches that cause production failures - Known for providing surgical-precision fixes that solve problems permanently **Debugging Mission:** - **Target Method**: \`${calledClass}.${methodName}()\` - **Calling File**: ${getBasename(callingFile)} - **Called Class**: ${calledClass} **Your Task:** Perform forensic analysis of this specific method signature issue. Find the exact incompatibility, understand the runtime impact, and provide a bulletproof fix.`; const dataPayload = `**=== CALLING FILE CONTENT ===** File: ${callingFile} ${callingFileContent} **=== CLASS DEFINITION FILES ===** ${Object.entries(classFileContents).map(([file, content]) => `File: ${file}\n${content}\n${'='.repeat(80)}` ).join('\n\n')}`; const outputInstructions = `**FORENSIC METHOD SIGNATURE ANALYSIS** ## Method Call Investigation ### 1. Call Site Analysis - **File**: ${require('path').basename(callingFile)} - **Line Number**: [exact line] - **Call Pattern**: \`${calledClass}.${methodName}(parameters here)\` - **Parameters Passed**: 1. \`param1\` - Type: [type], Value: [value/expression] 2. \`param2\` - Type: [type], Value: [value/expression] [Continue for all parameters...] ### 2. Method Definition Analysis - **File**: [which file contains the class] - **Line Number**: [exact line] - **Method Signature**: \`${methodName}(expected parameters)\` - **Expected Parameters**: 1. \`param1\` - Type: [expected type], Required: [yes/no], Default: [if any] 2. \`param2\` - Type: [expected type], Required: [yes/no], Default: [if any] [Continue for all parameters...] ### 3. Compatibility Assessment #### ✅ Compatible Aspects - [List what's working correctly] #### ❌ Incompatibilities Found 1. **Parameter Count Mismatch** - Passed: X parameters - Expected: Y parameters - Impact: [specific runtime behavior] 2. **Type Mismatches** - Parameter 1: Passing [actualType] but expecting [expectedType] - Parameter 2: [continue analysis...] 3. **Parameter Order Issues** - [If parameters are in wrong order] ## Runtime Impact Analysis ### What Happens When This Runs: - **Best Case**: [if it somehow works] - **Most Likely**: [typical failure mode] - **Worst Case**: [catastrophic failure scenario] ### Error Messages You'll See: \`\`\` [Likely error messages or unexpected behavior] \`\`\` ## Surgical Fix ### Option 1: Update Method Call (Recommended) **File**: ${require('path').basename(callingFile)} **Change this:** \`\`\`javascript ${calledClass}.${methodName}(current_call_here) \`\`\` **To this:** \`\`\`javascript ${calledClass}.${methodName}(corrected_call_here) \`\`\` ### Option 2: Update Method Definition (If Needed) **File**: [class definition file] **Change the method signature if the call is correct but definition is wrong** ### Option 3: Adapter Pattern (For Complex Cases) \`\`\`javascript // If both sides have valid reasons to stay as-is const adapter = { ${methodName}: (callerParams) => { return ${calledClass}.${methodName}(convertedParams); } }; \`\`\` ## Testing Strategy 1. **Unit Test**: [specific test to verify fix] 2. **Integration Test**: [test the full call path] 3. **Regression Prevention**: [ensure fix doesn't break other callers] **Confidence Level**: [High/Medium/Low] - with reasoning **Fix Complexity**: [Simple/Moderate/Complex] - estimated effort required`; return { systemAndContext, dataPayload, outputInstructions }; } /** * Implement for backwards compatibility * The system still expects this method, so we intelligently route to the appropriate stages */ getPromptStages(params: any): PromptStages { const mode = this.detectAnalysisMode(params); // If we have specific method comparison parameters if (params.callingFile && params.calledClass && params.methodName) { return this.getSpecificComparisonPromptStages(params); } if (mode === 'single-file') { return this.getSingleFilePromptStages(params); } else { return this.getMultiFilePromptStages(params); } } // Multi-file helper methods private async discoverRelevantFiles( projectPath: string, maxDepth: number, analysisType: string ): Promise<string[]> { const extensions = this.getFileExtensions(analysisType); return await this.multiFileAnalysis.discoverFiles(projectPath, extensions, maxDepth); } private async performMultiFileAnalysis( files: string[], params: any, model: any, contextLength: number ): Promise<any> { const cacheKey = this.analysisCache.generateKey( 'diff_method_signatures', params, files ); const cached = await this.analysisCache.get(cacheKey); if (cached) return cached; const fileAnalysisResults = await this.multiFileAnalysis.analyzeBatch( files, (file: string) => this.analyzeIndividualFile(file, params, model), contextLength ); // Aggregate results into proper analysis result format const aggregatedResult = { summary: `Method signature analysis of ${files.length} files`, findings: fileAnalysisResults, data: { fileCount: files.length, totalSize: fileAnalysisResults.reduce((sum: number, result: any) => sum + (result.size || 0), 0), methodCalls: this.extractMethodCalls(fileAnalysisResults), classDefinitions: this.extractClassDefinitions(fileAnalysisResults) } }; await this.analysisCache.cacheAnalysis(cacheKey, aggregatedResult, { modelUsed: model.identifier || 'unknown', executionTime: Date.now() - Date.now(), // TODO: Track actual execution time timestamp: new Date().toISOString() }); return aggregatedResult; } private async analyzeIndividualFile(file: string, params: any, model: any): Promise<any> { const content = await import('fs/promises').then(fs => fs.readFile(file, 'utf-8')); return { filePath: file, size: content.length, lines: content.split('\n').length, extension: await import('path').then(p => p.extname(file)), // Extract method calls and class definitions for signature analysis methodCalls: this.findMethodCallsInContent(content), classDefinitions: this.findClassDefinitionsInContent(content) }; } private getFileExtensions(analysisType: string): string[] { const extensionMap: Record<string, string[]> = { 'signature': ['.js', '.ts', '.jsx', '.tsx', '.php', '.py', '.java'], 'compatibility': ['.js', '.ts', '.jsx', '.tsx', '.php', '.py', '.java'], 'comprehensive': ['.js', '.ts', '.jsx', '.tsx', '.php', '.py', '.java', '.cs', '.cpp'] }; return extensionMap[analysisType] || extensionMap.comprehensive; } private extractMethodCalls(results: any[]): any[] { return results.flatMap(result => result.methodCalls || []); } private extractClassDefinitions(results: any[]): any[] { return results.flatMap(result => result.classDefinitions || []); } private findMethodCallsInContent(content: string): any[] { // Simple heuristic to find method calls - can be enhanced const methodCallPattern = /(\w+)\.(\w+)\s*\(/g; const calls = []; let match; while ((match = methodCallPattern.exec(content)) !== null) { calls.push({ object: match[1], method: match[2], line: content.substring(0, match.index).split('\n').length }); } return calls; } private findClassDefinitionsInContent(content: string): any[] { // Simple heuristic to find class definitions const classPattern = /class\s+(\w+)/g; const classes = []; let match; while ((match = classPattern.exec(content)) !== null) { classes.push({ name: match[1], line: content.substring(0, match.index).split('\n').length }); } return classes; } /** * Find files that might contain the specified class */ private async findClassFiles(className: string, searchDir: string): Promise<string[]> { const files = await this.multiFileAnalysis.discoverFiles( searchDir, ['.js', '.ts', '.jsx', '.tsx', '.php', '.py', '.java'], 3 ); const classFiles: string[] = []; for (const file of files) { try { const content = await readFileContent(file); if (this.fileContainsClass(content, className)) { classFiles.push(file); } } catch (error) { // Skip files we can't read } } return classFiles; } private fileContainsClass(content: string, className: string): boolean { const classPatterns = [ new RegExp(`class\\s+${className}\\s*{`, 'i'), new RegExp(`class\\s+${className}\\s+extends`, 'i'), new RegExp(`class\\s+${className}\\s+implements`, 'i'), new RegExp(`export\\s+class\\s+${className}`, 'i'), new RegExp(`function\\s+${className}\\s*\\(`, 'i'), // Constructor function ]; return classPatterns.some(pattern => pattern.test(content)); } private generateCacheKey(files: string[], params: any): string { const fileHash = files.join('|'); const paramHash = JSON.stringify(params); return `${fileHash}_${paramHash}`.substring(0, 64); } } export default MethodSignatureDiffer;
  • The response schema DiffMethodSignaturesResponse defines the structure of the tool's output, including comparison details, mismatches, compatibility status, and suggestions.
    export interface DiffMethodSignaturesResponse extends BaseResponse { data: { comparison: { caller: { file: string; line: number; signature: string; parameters: Array<{ name: string; type?: string; default?: string; }>; }; callee: { file: string; line: number; signature: string; parameters: Array<{ name: string; type?: string; required: boolean; default?: string; }>; }; }; mismatches: Array<{ type: "missing" | "extra" | "type-mismatch" | "order"; parameter: string; description: string; }>; compatible: boolean; suggestions: string[]; }; }
  • Input parameter schema defined in the plugin class, supporting single-file, multi-file, and specific method comparison modes with validation.
    parameters = { // Single-file parameters code: { type: 'string' as const, description: 'The code to analyze (for single-file analysis)', required: false }, filePath: { type: 'string' as const, description: 'Path to single file to analyze', required: false }, // Multi-file parameters projectPath: { type: 'string' as const, description: 'Path to project root (for multi-file analysis)', required: false }, files: { type: 'array' as const, description: 'Array of specific file paths (for multi-file analysis)', required: false, items: { type: 'string' as const } }, maxDepth: { type: 'number' as const, description: 'Maximum directory depth for multi-file discovery (1-5)', required: false, default: 3 }, // Specific parameters for method signature comparison callingFile: { type: 'string' as const, description: 'Absolute path to file containing the method call', required: false }, calledClass: { type: 'string' as const, description: 'Class name containing the called method', required: false }, methodName: { type: 'string' as const, description: 'Name of the method to check', required: false }, // Universal parameters language: { type: 'string' as const, description: 'Programming language', required: false, default: 'javascript' }, analysisDepth: { type: 'string' as const, description: 'Level of analysis detail', enum: ['basic', 'detailed', 'comprehensive'], default: 'detailed', required: false }, analysisType: { type: 'string' as const, description: 'Type of analysis to perform', enum: ['signature', 'compatibility', 'comprehensive'], default: 'comprehensive', required: false } };
  • Dynamic registration: The PluginLoader scans the src/prompts/analyze directory, dynamically imports diff-signatures.ts (as default export), instantiates MethodSignatureDiffer, and registers it by name 'diff_method_signatures'.
    private async loadPlugin(filePath: string, category: 'analyze' | 'generate' | 'custom' | 'system'): Promise<void> { try { // Skip .d.ts files (TypeScript declaration files) if (filePath.endsWith('.d.ts')) { return; } // Use pathToFileURL for proper ES module loading on Windows const fileUrl = pathToFileURL(filePath).href; const module = await import(fileUrl); const PluginClass = module.default; if (PluginClass && typeof PluginClass === 'function') { const plugin = new PluginClass(); if (plugin instanceof BasePlugin) { this.registerPlugin(plugin); // Removed console.log to avoid JSON-RPC interference } } } catch (error) { // Silent error handling to avoid JSON-RPC interference // console.error(`Error loading plugin from ${filePath}:`, error); } }
  • The loadPlugins method iterates over 'analyze' category (containing diff-signatures.ts) and triggers loading of all plugins.
    async loadPlugins(promptsDir: string): Promise<void> { const categories = ['analyze', 'generate', 'custom', 'system', 'fun']; for (const category of categories) { const categoryPath = path.join(promptsDir, category); try { const files = await fs.readdir(categoryPath); for (const file of files) { if (file.endsWith('.js') && !file.includes('.test.')) { // Only load .js files, skip .d.ts and tests await this.loadPlugin(path.join(categoryPath, file), category as any); } } } catch (error) { // Silent error handling to avoid JSON-RPC interference // console.error(`Error loading plugins from ${category}:`, error); } } // Load system plugins from shared (cache management) await this.loadSystemPlugins(path.join(promptsDir, 'shared')); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/houtini-ai/lm'

If you have feedback or need assistance with the MCP directory API, please join our Discord server