Skip to main content
Glama
problem-decomposer.ts24.2 kB
/** * Problem Decomposer * * Decomposes complex problems into meaningful sub-problems with: * - Domain-specific component extraction * - Descriptive sub-problem names * - Relationship-based dependency descriptions * * Requirements: 2.1, 2.2, 2.3, 2.5 */ export interface SubProblem { id: string; name: string; description: string; depth: number; parent?: string; domain?: string; } export interface Dependency { from: string; to: string; type: string; description: string; } export interface DecompositionResult { subProblems: SubProblem[]; dependencies: Dependency[]; } /** * Parameters for generating sub-problems */ interface GenerateSubProblemsParams { parentProblem: string; components: string[]; parentId: string; currentDepth: number; maxDepth: number; actionIntent: string; domain: string; } /** * Domain patterns for extracting domain-specific components */ const DOMAIN_PATTERNS: Record<string, { keywords: string[]; components: string[] }> = { // Real-time and collaborative systems (HIGH PRIORITY - was missing) realtime: { keywords: [ "real-time", "realtime", "collaborative", "collaboration", "live", "sync", "synchronization", "websocket", "socket", "streaming", ], components: [ "Real-time Communication Protocol", "State Synchronization", "Conflict Resolution (CRDT/OT)", "Presence Detection", "Event Broadcasting", "Connection Management", "Offline Support & Reconciliation", "Latency Optimization", ], }, // Document editing (specific to collaborative docs) document: { keywords: ["document", "editor", "editing", "text", "rich text", "markdown", "wysiwyg"], components: [ "Document Model & Schema", "Operational Transform / CRDT", "Cursor & Selection Sync", "Version History", "Undo/Redo Stack", "Formatting Engine", "Export & Import", ], }, ecommerce: { keywords: ["e-commerce", "ecommerce", "shop", "store", "cart", "checkout", "product", "order"], components: [ "User Authentication", "Product Catalog", "Shopping Cart", "Checkout Process", "Order Management", "Payment Processing", "Inventory Management", "Customer Support", ], }, webapp: { keywords: ["web", "application", "app", "platform", "system", "portal"], components: [ "User Interface", "Backend Services", "Data Storage", "Authentication", "API Design", "Security", "Performance Optimization", "Deployment", ], }, mobile: { keywords: ["mobile", "ios", "android", "app"], components: [ "User Interface", "Navigation", "Data Persistence", "Network Layer", "Push Notifications", "Offline Support", "App Store Deployment", ], }, data: { keywords: ["data", "analytics", "database", "pipeline", "etl", "warehouse"], components: [ "Data Collection", "Data Processing", "Data Storage", "Data Analysis", "Visualization", "Reporting", "Data Quality", ], }, ml: { keywords: ["machine learning", "ml", "ai", "model", "training", "prediction"], components: [ "Data Preparation", "Feature Engineering", "Model Selection", "Training Pipeline", "Model Evaluation", "Deployment", "Monitoring", ], }, api: { keywords: ["api", "rest", "graphql", "endpoint", "service"], components: [ "API Design", "Authentication", "Rate Limiting", "Documentation", "Error Handling", "Versioning", "Testing", ], }, security: { keywords: ["security", "auth", "encryption", "access", "permission"], components: [ "Authentication", "Authorization", "Data Encryption", "Access Control", "Audit Logging", "Vulnerability Assessment", ], }, performance: { keywords: ["performance", "optimization", "speed", "latency", "throughput", "scalable"], components: [ "Performance Analysis", "Bottleneck Identification", "Caching Strategy", "Load Balancing", "Database Optimization", "Code Optimization", ], }, testing: { keywords: ["test", "testing", "qa", "quality", "validation"], components: [ "Test Strategy", "Unit Testing", "Integration Testing", "End-to-End Testing", "Performance Testing", "Test Automation", ], }, devops: { keywords: ["devops", "ci", "cd", "deployment", "infrastructure", "docker", "kubernetes"], components: [ "CI/CD Pipeline", "Infrastructure Setup", "Containerization", "Monitoring", "Logging", "Alerting", "Disaster Recovery", ], }, // Microservices and distributed systems microservices: { keywords: ["microservice", "microservices", "distributed", "service mesh", "saga"], components: [ "Service Decomposition", "Inter-service Communication", "Service Discovery", "API Gateway", "Data Consistency (Saga/Event Sourcing)", "Observability", "Fault Tolerance", ], }, // Migration projects migration: { keywords: ["migrate", "migration", "legacy", "modernize", "modernization", "refactor"], components: [ "Current State Assessment", "Target Architecture Design", "Data Migration Strategy", "Incremental Migration Plan", "Rollback Strategy", "Testing & Validation", "Cutover Planning", ], }, }; /** * Action verbs for generating descriptive names */ const ACTION_VERBS: Record<string, string[]> = { build: ["Design", "Implement", "Create", "Develop"], improve: ["Optimize", "Enhance", "Refactor", "Upgrade"], fix: ["Debug", "Resolve", "Repair", "Correct"], analyze: ["Investigate", "Evaluate", "Assess", "Review"], plan: ["Define", "Outline", "Strategize", "Architect"], integrate: ["Connect", "Combine", "Merge", "Unify"], migrate: ["Transfer", "Move", "Convert", "Transition"], scale: ["Expand", "Grow", "Distribute", "Parallelize"], }; /** * Dependency relationship descriptions */ const DEPENDENCY_DESCRIPTIONS: Record<string, string> = { hierarchical: "is a component of", sequential: "must be completed before", parallel: "can be worked on alongside", data: "provides data for", interface: "defines the interface for", foundation: "provides the foundation for", }; export class ProblemDecomposer { /** * Decompose a problem into meaningful sub-problems */ decompose(problem: string, maxDepth: number): DecompositionResult { const subProblems: SubProblem[] = []; const dependencies: Dependency[] = []; // Detect domain from problem text const domain = this.detectDomain(problem); // Extract action intent from problem const actionIntent = this.extractActionIntent(problem); // Generate root problem const rootId = "root"; const rootName = this.generateRootName(problem, actionIntent); subProblems.push({ id: rootId, name: rootName, description: problem, depth: 1, domain, }); // Generate sub-problems based on domain and problem analysis if (maxDepth > 1) { const components = this.extractComponents(problem, domain); const childProblems = this.generateSubProblems({ parentProblem: problem, components, parentId: rootId, currentDepth: 2, maxDepth, actionIntent, domain, }); subProblems.push(...childProblems.subProblems); dependencies.push(...childProblems.dependencies); } return { subProblems, dependencies }; } /** * Detect the domain of the problem * * Prioritizes more specific domains over generic ones. * For example, "real-time collaborative document editing" should * match "realtime" or "document" before "webapp". */ private detectDomain(problem: string): string { const lowerProblem = problem.toLowerCase(); // Score each domain by keyword matches const domainScores: Array<{ domain: string; score: number; specificity: number }> = []; // Domains ordered by specificity (more specific first) // Business domains (ecommerce) are prioritized over technical aspects (performance) // because they define the problem space more specifically const specificityOrder: Record<string, number> = { realtime: 10, document: 10, microservices: 9, migration: 9, ml: 8, ecommerce: 8, // Business domain - higher priority than technical aspects security: 7, testing: 6, devops: 6, api: 5, data: 4, mobile: 3, performance: 2, // Technical aspect - lower priority, often co-occurs with other domains webapp: 1, // Most generic, lowest priority }; for (const [domain, config] of Object.entries(DOMAIN_PATTERNS)) { const matchCount = config.keywords.filter((kw) => lowerProblem.includes(kw)).length; if (matchCount >= 1) { domainScores.push({ domain, score: matchCount, specificity: specificityOrder[domain] ?? 0, }); } } // Sort by specificity first, then by match count domainScores.sort((a, b) => { if (b.specificity !== a.specificity) { return b.specificity - a.specificity; } return b.score - a.score; }); return domainScores.length > 0 ? domainScores[0].domain : "general"; } /** * Extract action intent from problem text */ private extractActionIntent(problem: string): string { const lowerProblem = problem.toLowerCase(); for (const [intent, verbs] of Object.entries(ACTION_VERBS)) { if (verbs.some((v) => lowerProblem.includes(v.toLowerCase()))) { return intent; } } // Check for common problem patterns if (lowerProblem.includes("how to") || lowerProblem.includes("create")) { return "build"; } if (lowerProblem.includes("why") || lowerProblem.includes("understand")) { return "analyze"; } if (lowerProblem.includes("improve") || lowerProblem.includes("better")) { return "improve"; } if ( lowerProblem.includes("fix") || lowerProblem.includes("bug") || lowerProblem.includes("error") ) { return "fix"; } return "build"; // Default intent } /** * Generate a meaningful root problem name */ private generateRootName(problem: string, actionIntent: string): string { // Extract key nouns from problem const keyTerms = this.extractKeyTerms(problem); if (keyTerms.length > 0) { const verb = this.getActionVerb(actionIntent); return `${verb} ${keyTerms.slice(0, 3).join(" ")}`; } // Fallback: use first meaningful words const words = problem.split(/\s+/).filter((w) => w.length > 3); if (words.length >= 2) { return `${words[0]} ${words[1]}`.substring(0, 50); } return problem.substring(0, 50); } /** * Extract key terms from problem text */ private extractKeyTerms(problem: string): string[] { const stopWords = new Set([ "the", "a", "an", "and", "or", "but", "in", "on", "at", "to", "for", "of", "with", "by", "from", "as", "is", "was", "are", "were", "been", "be", "have", "has", "had", "do", "does", "did", "will", "would", "could", "should", "may", "might", "must", "shall", "can", "need", "that", "this", "these", "those", "it", "its", "how", "what", "when", "where", "why", "which", "who", "whom", "i", "we", "you", "they", "he", "she", "my", "our", "your", "their", ]); const words = problem .toLowerCase() .replace(/[^\w\s-]/g, "") .split(/\s+/) .filter((w) => w.length > 2 && !stopWords.has(w)); // Return unique terms return [...new Set(words)]; } /** * Get an action verb for the intent */ private getActionVerb(intent: string): string { const verbs = ACTION_VERBS[intent] || ACTION_VERBS.build; return verbs[0]; } /** * Extract components from problem text based on domain */ private extractComponents(problem: string, domain: string): string[] { const domainConfig = DOMAIN_PATTERNS[domain]; if (domainConfig) { // Filter components that are relevant to the problem const lowerProblem = problem.toLowerCase(); const relevantComponents = domainConfig.components.filter((comp) => { const compWords = comp.toLowerCase().split(/\s+/); return compWords.some((word) => lowerProblem.includes(word)); }); if (relevantComponents.length >= 2) { return relevantComponents; } // Return default components for the domain return domainConfig.components.slice(0, 4); } // Extract components from problem text directly return this.extractComponentsFromText(problem); } /** * Extract components directly from problem text */ private extractComponentsFromText(problem: string): string[] { const components: string[] = []; // Look for enumerated items const listPatterns = [ /(?:including|such as|like|with)\s+([^.]+)/gi, /(?:need to|want to|should)\s+([^.]+)/gi, /(\w+(?:\s+\w+)?)\s+(?:and|,)\s+(\w+(?:\s+\w+)?)/gi, ]; for (const pattern of listPatterns) { const matches = problem.matchAll(pattern); for (const match of matches) { const items = match[1]?.split(/,\s*|\s+and\s+/) || []; components.push(...items.map((item) => this.capitalizeWords(item.trim()))); } } // If no components found, generate generic ones based on key terms if (components.length < 2) { const keyTerms = this.extractKeyTerms(problem); return keyTerms.slice(0, 4).map((term) => this.capitalizeWords(term)); } return [...new Set(components)].slice(0, 6); } /** * Capitalize words in a string */ private capitalizeWords(str: string): string { return str .split(/\s+/) .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) .join(" "); } /** * Generate sub-problems recursively */ private generateSubProblems(params: GenerateSubProblemsParams): DecompositionResult { const { parentProblem, components, parentId, currentDepth, maxDepth, actionIntent, domain } = params; const subProblems: SubProblem[] = []; const dependencies: Dependency[] = []; const verb = this.getActionVerb(actionIntent); for (let i = 0; i < components.length; i++) { const component = components[i]; const subProblemId = `${parentId}-${i}`; // Generate meaningful name const name = `${verb} ${component}`; // Generate description that explains what needs to be solved const description = this.generateDescription(component, parentProblem, actionIntent); subProblems.push({ id: subProblemId, name, description, depth: currentDepth, parent: parentId, domain, }); // Add dependency with meaningful description const depType = this.determineDependencyType(i, components.length); dependencies.push({ from: parentId, to: subProblemId, type: depType, description: `"${component}" ${DEPENDENCY_DESCRIPTIONS[depType]} "${parentId === "root" ? "the main problem" : "its parent"}"`, }); // Recurse if not at max depth if (currentDepth < maxDepth) { const subComponents = this.generateSubComponents(component, domain); if (subComponents.length > 0) { const childResult = this.generateSubProblems({ parentProblem: `${verb} ${component}`, components: subComponents, parentId: subProblemId, currentDepth: currentDepth + 1, maxDepth, actionIntent, domain, }); subProblems.push(...childResult.subProblems); dependencies.push(...childResult.dependencies); } } } return { subProblems, dependencies }; } /** * Generate a description for a sub-problem */ private generateDescription( component: string, _parentProblem: string, actionIntent: string ): string { const actionDescriptions: Record<string, string> = { build: `Define and implement the ${component.toLowerCase()} component`, improve: `Analyze and optimize the ${component.toLowerCase()} for better performance`, fix: `Identify and resolve issues in the ${component.toLowerCase()}`, analyze: `Investigate and understand the ${component.toLowerCase()} behavior`, plan: `Create a detailed plan for the ${component.toLowerCase()}`, integrate: `Connect and integrate the ${component.toLowerCase()} with other components`, migrate: `Migrate and transition the ${component.toLowerCase()} to the new system`, scale: `Scale and distribute the ${component.toLowerCase()} for higher load`, }; return ( actionDescriptions[actionIntent] || `Address the ${component.toLowerCase()} aspect of the problem` ); } /** * Determine dependency type based on position */ private determineDependencyType(index: number, total: number): string { if (index === 0) { return "foundation"; } if (index === total - 1) { return "sequential"; } return "hierarchical"; } /** * Generate sub-components for a component */ private generateSubComponents(component: string, domain: string): string[] { const componentLower = component.toLowerCase(); // Common sub-component patterns const subComponentPatterns: Record<string, string[]> = { authentication: ["Login Flow", "Registration", "Password Reset", "Session Management"], "user interface": [ "Layout Design", "Component Library", "Responsive Design", "Accessibility", ], "data storage": ["Schema Design", "Query Optimization", "Backup Strategy", "Migration Plan"], "api design": [ "Endpoint Definition", "Request Validation", "Response Format", "Error Handling", ], security: ["Input Validation", "Access Control", "Encryption", "Audit Logging"], testing: ["Test Cases", "Test Data", "Automation", "Coverage Analysis"], deployment: ["Environment Setup", "CI/CD Pipeline", "Monitoring", "Rollback Plan"], performance: ["Profiling", "Caching", "Load Testing", "Optimization"], catalog: ["Product Listing", "Search Functionality", "Category Management"], cart: ["Item Management", "Price Calculation", "Persistence"], checkout: ["Payment Integration", "Order Validation", "Confirmation"], order: ["Order Processing", "Status Tracking", "History Management"], inventory: ["Stock Tracking", "Reorder Logic", "Availability Check"], payment: ["Gateway Integration", "Transaction Processing", "Refund Handling"], user: ["Profile Management", "Preferences", "Account Settings"], notification: ["Email Notifications", "Push Notifications", "In-App Alerts"], search: ["Query Processing", "Result Ranking", "Filtering"], analytics: ["Data Collection", "Metrics Calculation", "Reporting"], backend: ["Business Logic", "Data Access", "Service Layer"], frontend: ["UI Components", "State Management", "Routing"], database: ["Schema Design", "Query Optimization", "Indexing"], api: ["Endpoint Design", "Request Handling", "Response Formatting"], integration: ["External APIs", "Data Mapping", "Error Handling"], validation: ["Input Validation", "Business Rules", "Error Messages"], logging: ["Log Collection", "Log Storage", "Log Analysis"], monitoring: ["Health Checks", "Alerting", "Dashboards"], caching: ["Cache Strategy", "Invalidation", "Storage"], queue: ["Message Processing", "Retry Logic", "Dead Letter Handling"], // NEW: Real-time and collaborative sub-components "real-time": ["WebSocket Setup", "Event Handling", "Connection Pooling"], realtime: ["WebSocket Setup", "Event Handling", "Connection Pooling"], communication: ["Protocol Selection", "Message Format", "Heartbeat"], synchronization: ["State Diffing", "Merge Strategy", "Conflict Detection"], sync: ["State Diffing", "Merge Strategy", "Conflict Detection"], "conflict resolution": ["CRDT Implementation", "OT Algorithm", "Merge Rules"], crdt: ["Data Structure Selection", "Merge Function", "Garbage Collection"], presence: ["User Tracking", "Status Updates", "Cursor Sync"], broadcast: ["Pub/Sub Setup", "Channel Management", "Message Routing"], // NEW: Document editing sub-components document: ["Schema Definition", "Content Model", "Serialization"], editor: ["Input Handling", "Selection Management", "Rendering"], "version history": ["Snapshot Storage", "Diff Generation", "Restore Logic"], formatting: ["Style Application", "Block Types", "Inline Marks"], // NEW: Migration sub-components migration: ["Dependency Analysis", "Risk Assessment", "Rollback Plan"], "data migration": ["Schema Mapping", "ETL Pipeline", "Validation"], modernization: ["Architecture Review", "Technology Selection", "Phased Approach"], // NEW: Microservices sub-components "service decomposition": ["Bounded Context", "API Contract", "Data Ownership"], "service discovery": ["Registry Setup", "Health Checks", "Load Balancing"], "api gateway": ["Routing Rules", "Rate Limiting", "Authentication"], saga: ["Choreography vs Orchestration", "Compensation Logic", "Timeout Handling"], "event sourcing": ["Event Store", "Projection", "Replay"], }; for (const [pattern, subComponents] of Object.entries(subComponentPatterns)) { if (componentLower.includes(pattern)) { return subComponents.slice(0, 3); } } // Fallback: generate generic sub-components based on domain return this.generateGenericSubComponents(component, domain); } /** * Generate generic sub-components when no specific pattern matches * This ensures decomposition can reach the requested maxDepth */ private generateGenericSubComponents(component: string, domain: string): string[] { // Domain-specific generic sub-components const domainSubComponents: Record<string, string[]> = { ecommerce: ["Requirements Analysis", "Implementation", "Integration"], webapp: ["Design Phase", "Development Phase", "Testing Phase"], mobile: ["UI Design", "Core Logic", "Platform Integration"], data: ["Data Modeling", "Processing Logic", "Output Generation"], ml: ["Data Preparation", "Model Development", "Evaluation"], api: ["Specification", "Implementation", "Documentation"], security: ["Threat Analysis", "Implementation", "Verification"], performance: ["Analysis", "Optimization", "Validation"], testing: ["Test Design", "Test Implementation", "Test Execution"], devops: ["Configuration", "Automation", "Monitoring"], general: ["Analysis", "Implementation", "Verification"], }; const subComponents = domainSubComponents[domain] || domainSubComponents.general; // Customize sub-component names with the component context const componentWords = component.split(/\s+/).filter((w) => w.length > 3); const contextWord = componentWords.length > 0 ? componentWords[componentWords.length - 1] : ""; if (contextWord) { return subComponents.map((sub) => `${sub} for ${contextWord}`); } return subComponents; } }

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/keyurgolani/ThoughtMcp'

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