Skip to main content
Glama
debuggingAssistant.ts15.5 kB
import type { EnhancedVideoAnalysis, ErrorOccurrence } from './enhancedVideoAnalyzer' export interface DebuggingPlan { summary: string rootCauseHypotheses: RootCauseHypothesis[] investigationSteps: InvestigationStep[] codeChangeSuggestions: CodeChangeSuggestion[] testingStrategy: TestingStrategy } export interface RootCauseHypothesis { hypothesis: string confidence: number evidence: string[] investigationPriority: number } export interface InvestigationStep { order: number action: string targetFile?: string targetLine?: number expectedOutcome: string tools: ('debugger' | 'console' | 'network' | 'profiler')[] } export interface CodeChangeSuggestion { file: string line?: number type: 'fix' | 'validation' | 'error_handling' | 'logging' | 'refactor' description: string code?: string priority: 'high' | 'medium' | 'low' } export interface TestingStrategy { unitTests: TestSuggestion[] integrationTests: TestSuggestion[] e2eTests: TestSuggestion[] } export interface TestSuggestion { testName: string testType: string coverage: string[] scenario: string } export class DebuggingAssistant { generateDebuggingPlan(analysis: EnhancedVideoAnalysis): DebuggingPlan { const rootCauseHypotheses = this.generateRootCauseHypotheses(analysis) const investigationSteps = this.createInvestigationSteps(analysis, rootCauseHypotheses) const codeChangeSuggestions = this.suggestCodeChanges(analysis) const testingStrategy = this.createTestingStrategy(analysis) const summary = this.generateSummary(analysis, rootCauseHypotheses) return { summary, rootCauseHypotheses, investigationSteps, codeChangeSuggestions, testingStrategy, } } private generateRootCauseHypotheses(analysis: EnhancedVideoAnalysis): RootCauseHypothesis[] { const hypotheses: RootCauseHypothesis[] = [] // Analyze errors for (const error of analysis.errors) { if (error.errorType === 'network') { hypotheses.push({ hypothesis: 'API endpoint is not responding or returning unexpected data', confidence: 0.8, evidence: [`Network error: "${error.errorMessage}"`, ...error.possibleCauses], investigationPriority: 1, }) } else if (error.errorType === 'validation') { hypotheses.push({ hypothesis: 'Form validation logic is incorrectly configured', confidence: 0.7, evidence: [ `Validation error: "${error.errorMessage}"`, `Related form fields: ${analysis.codeContext.components.filter((c) => c.includes('Form')).join(', ')}`, ], investigationPriority: 2, }) } } // Analyze failed actions const failedActions = analysis.userActions.filter((a) => a.result === 'error') if (failedActions.length > 0) { const failedTypes = [...new Set(failedActions.map((a) => a.type))] hypotheses.push({ hypothesis: `User interactions failing due to state management issues`, confidence: 0.6, evidence: [ `${failedActions.length} actions failed`, `Failed action types: ${failedTypes.join(', ')}`, `Components involved: ${failedActions.map((a) => a.target).join(', ')}`, ], investigationPriority: 3, }) } // Analyze data flow issues const dataFlowIssues = this.identifyDataFlowIssues(analysis) if (dataFlowIssues.length > 0) { hypotheses.push({ hypothesis: 'Data is not properly flowing between components', confidence: 0.5, evidence: dataFlowIssues, investigationPriority: 4, }) } // Sort by priority return hypotheses.sort((a, b) => a.investigationPriority - b.investigationPriority) } private createInvestigationSteps( analysis: EnhancedVideoAnalysis, hypotheses: RootCauseHypothesis[] ): InvestigationStep[] { const steps: InvestigationStep[] = [] let stepOrder = 1 // For each hypothesis, create investigation steps for (const hypothesis of hypotheses.slice(0, 3)) { if (hypothesis.hypothesis.includes('API endpoint')) { // Network investigation steps.push({ order: stepOrder++, action: 'Open Network tab and reproduce the issue', expectedOutcome: 'Identify failing API calls and response status', tools: ['network'], }) // Find API-related files const apiFile = analysis.relevantFiles.find( (f) => f.reason.includes('API') || f.path.includes('api') ) if (apiFile) { steps.push({ order: stepOrder++, action: 'Set breakpoint in API call handler', targetFile: apiFile.path, targetLine: apiFile.snippets?.[0]?.line, expectedOutcome: 'Trace request parameters and response', tools: ['debugger'], }) } } else if (hypothesis.hypothesis.includes('validation')) { // Validation investigation const validationFile = analysis.relevantFiles.find( (f) => f.snippets?.some((s) => s.content.includes('validate')) || f.path.includes('validation') ) if (validationFile) { steps.push({ order: stepOrder++, action: 'Inspect validation rules', targetFile: validationFile.path, targetLine: validationFile.snippets?.find((s) => s.content.includes('validate') )?.line, expectedOutcome: 'Verify validation logic matches requirements', tools: ['debugger'], }) } steps.push({ order: stepOrder++, action: 'Log form data before validation', expectedOutcome: 'See actual vs expected data format', tools: ['console'], }) } else if (hypothesis.hypothesis.includes('state management')) { // State investigation steps.push({ order: stepOrder++, action: 'Use React DevTools to inspect component state', expectedOutcome: 'Identify state inconsistencies', tools: ['debugger'], }) const stateFile = analysis.relevantFiles.find( (f) => f.path.includes('state') || f.path.includes('reducer') || f.path.includes('context') ) if (stateFile) { steps.push({ order: stepOrder++, action: 'Add logging to state updates', targetFile: stateFile.path, expectedOutcome: 'Track state changes during user interaction', tools: ['console', 'debugger'], }) } } } // Add general debugging steps based on reproducible steps if (analysis.reproducibleSteps.length > 0) { const errorStep = analysis.reproducibleSteps.find((s) => s.actualResult?.includes('Error') ) if (errorStep) { steps.push({ order: stepOrder++, action: `Reproduce issue by: ${errorStep.action}`, expectedOutcome: 'Observe the exact error in console', tools: ['console', 'network'], }) } } return steps } private suggestCodeChanges(analysis: EnhancedVideoAnalysis): CodeChangeSuggestion[] { const suggestions: CodeChangeSuggestion[] = [] // Error handling suggestions for (const error of analysis.errors) { if (error.relatedCode.length > 0) { const codeRef = error.relatedCode[0] suggestions.push({ file: codeRef.file, line: codeRef.line, type: 'error_handling', description: `Add better error handling for: ${error.errorMessage}`, code: this.generateErrorHandlingCode(error), priority: 'high', }) } } // Validation suggestions const validationErrors = analysis.errors.filter((e) => e.errorType === 'validation') if (validationErrors.length > 0) { const formComponent = analysis.relevantFiles.find( (f) => f.reason.includes('Component') && f.path.includes('form') ) if (formComponent) { suggestions.push({ file: formComponent.path, type: 'validation', description: 'Add input validation before submission', code: this.generateValidationCode(analysis), priority: 'high', }) } } // Logging suggestions for debugging const complexInteractions = analysis.userActions.filter( (a) => a.type === 'submit' || (a.type === 'click' && a.result === 'error') ) if (complexInteractions.length > 0) { suggestions.push({ file: analysis.relevantFiles[0]?.path || 'main component file', type: 'logging', description: 'Add debug logging for user interactions', code: this.generateLoggingCode(), priority: 'medium', }) } return suggestions } private createTestingStrategy(analysis: EnhancedVideoAnalysis): TestingStrategy { const unitTests: TestSuggestion[] = [] const integrationTests: TestSuggestion[] = [] const e2eTests: TestSuggestion[] = [] // Unit tests for validation if (analysis.errors.some((e) => e.errorType === 'validation')) { unitTests.push({ testName: 'Form validation rules', testType: 'unit', coverage: ['validation functions', 'error messages'], scenario: 'Test all validation edge cases', }) } // Integration tests for API calls if (analysis.errors.some((e) => e.errorType === 'network')) { integrationTests.push({ testName: 'API error handling', testType: 'integration', coverage: ['API calls', 'error states', 'retry logic'], scenario: 'Test API failures and recovery', }) } // E2E test based on reproducible steps if (analysis.reproducibleSteps.length > 0) { e2eTests.push({ testName: 'User flow from video', testType: 'e2e', coverage: analysis.reproducibleSteps.map((s) => s.action), scenario: 'Reproduce exact user journey from video', }) } return { unitTests, integrationTests, e2eTests } } private generateSummary( analysis: EnhancedVideoAnalysis, hypotheses: RootCauseHypothesis[] ): string { const errorCount = analysis.errors.length const failedActionCount = analysis.userActions.filter((a) => a.result === 'error').length const topHypothesis = hypotheses[0] let summary = `## Debugging Summary\n\n` summary += `**Issue Overview:**\n` summary += `- ${errorCount} error(s) detected in the video\n` summary += `- ${failedActionCount} user action(s) failed\n` summary += `- ${analysis.relevantFiles.length} relevant code files identified\n\n` if (topHypothesis) { summary += `**Most Likely Cause:** ${topHypothesis.hypothesis} (${(topHypothesis.confidence * 100).toFixed(0)}% confidence)\n\n` } summary += `**Key Findings:**\n` if (analysis.errors.length > 0) { summary += `- Primary error: "${analysis.errors[0].errorMessage}"\n` } if (analysis.screenStates.length > 0) { const routes = [...new Set(analysis.screenStates.map((s) => s.route).filter((r) => r))] summary += `- Pages affected: ${routes.join(', ')}\n` } return summary } private identifyDataFlowIssues(analysis: EnhancedVideoAnalysis): string[] { const issues: string[] = [] // Check for data entered but not appearing const typeActions = analysis.userActions.filter((a) => a.type === 'type') const submitActions = analysis.userActions.filter((a) => a.type === 'submit') if (typeActions.length > 0 && submitActions.some((s) => s.result === 'error')) { issues.push('Data entered in form may not be properly captured') } // Check for missing data in UI if ( analysis.screenStates.some((s) => Object.keys(s.dataPresent).length === 0) && typeActions.length > 0 ) { issues.push('Form data not reflected in component state') } return issues } private generateErrorHandlingCode(error: ErrorOccurrence): string { return ` try { // Existing code here } catch (error) { console.error('${error.errorMessage}:', error); // Add user-friendly error handling if (error.message.includes('${error.errorMessage.split(' ')[0]}')) { // Handle specific error showErrorToUser('${error.possibleCauses[0] || 'An error occurred'}'); } }` } private generateValidationCode(analysis: EnhancedVideoAnalysis): string { const fields = analysis.codeContext.keywords.filter( (k) => k.includes('input') || k.includes('field') ) return ` const validateForm = (data) => { const errors = {}; ${fields .map( (field) => ` if (!data.${field}) { errors.${field} = '${field} is required'; }` ) .join('\n')} return Object.keys(errors).length === 0 ? null : errors; };` } private generateLoggingCode(): string { return ` // Debug logging for user interactions const logUserAction = (action, data) => { console.group(\`User Action: \${action}\`); console.log('Timestamp:', new Date().toISOString()); console.log('Data:', data); console.log('Current State:', getCurrentState()); console.groupEnd(); };` } }

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/currentspace/shortcut_mcp'

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