UNPKG

task-engine-ai-core

Version:

Revolutionary AI-driven task management system with complete transformation trilogy: Frontend v0.1.0, Backend v0.2.0, CLI v0.3.0 - Enterprise-grade performance with 95% improvements

639 lines (579 loc) 28.2 kB
/** * Unified AI Service Router * * This module provides a unified interface for AI operations with intelligent fallback: * 1. Active AI Assistant (via MCP sampling) - Primary * 2. External APIs (Claude, Perplexity, etc.) - Fallback * 3. Manual/Template operations - Last resort */ import { hasActiveAIAssistant, generateTextWithActiveAI, generateObjectWithActiveAI, getActiveAIInfo } from './ai-service-mcp.js'; import { generateObjectService, generateTextService } from '../../../scripts/modules/ai-services-unified.js'; import logger from '../logger.js'; /** * Service types for routing */ export const AI_SERVICE_TYPES = { ACTIVE_AGENT: 'active-agent', EXTERNAL_API: 'external-api', MANUAL: 'manual' }; /** * Configuration for AI service routing */ const DEFAULT_CONFIG = { preferActiveAgent: true, enableExternalApiFallback: false, // Force use of active agent only enableManualFallback: false, // Disable manual fallback maxRetries: 1, // Reduce retries since we're only using active agent retryDelay: 500 }; /** * Determine the best available AI service for the given context * @param {Object} context - Context object containing session and other info * @param {Object} config - Configuration options * @returns {string} Service type to use */ export function determineAIService(context, config = DEFAULT_CONFIG) { const { session } = context; // Always use active AI assistant if available (forced mode) if (hasActiveAIAssistant(session)) { logger.debug('Active AI assistant available - using as primary service (forced mode)'); return AI_SERVICE_TYPES.ACTIVE_AGENT; } // If active agent is not available, fall back to manual mode using current agentic instance logger.info('Active AI assistant not available via MCP sampling - falling back to agentic manual mode'); return AI_SERVICE_TYPES.MANUAL; } /** * Generate text using the best available AI service * @param {Object} context - Context object * @param {Object} params - Generation parameters * @param {Object} config - Configuration options * @returns {Promise<Object>} Result object with text and metadata */ export async function generateText(context, params, config = DEFAULT_CONFIG) { const { session, projectRoot } = context; const { systemPrompt, userPrompt, role = 'main', maxTokens = 4000 } = params; let lastError = null; let attempts = 0; const maxAttempts = config.maxRetries + 1; while (attempts < maxAttempts) { attempts++; try { const serviceType = determineAIService(context, config); logger.info(`Attempt ${attempts}: Using ${serviceType} for text generation`); switch (serviceType) { case AI_SERVICE_TYPES.ACTIVE_AGENT: try { const text = await generateTextWithActiveAI(session, { systemPrompt, userPrompt, maxTokens }); return { success: true, text, serviceUsed: AI_SERVICE_TYPES.ACTIVE_AGENT, metadata: { attempts, aiInfo: getActiveAIInfo(session) } }; } catch (error) { logger.warn(`Active AI assistant failed: ${error.message}`); // Keep active agent preference enabled - we want to always use it // config.preferActiveAgent = false; // Commented out to force active agent use throw error; } case AI_SERVICE_TYPES.EXTERNAL_API: try { const result = await generateTextService({ role, session, projectRoot, systemPrompt, prompt: userPrompt }); return { success: true, text: result, serviceUsed: AI_SERVICE_TYPES.EXTERNAL_API, metadata: { attempts, role } }; } catch (error) { logger.warn(`External API failed: ${error.message}`); // Disable external API for subsequent attempts config.enableExternalApiFallback = false; throw error; } case AI_SERVICE_TYPES.MANUAL: try { // Use agentic manual mode for text generation logger.info('Using agentic manual mode for text generation'); const text = await generateTextWithAgenticManualMode(session, params); return { success: true, text, serviceUsed: AI_SERVICE_TYPES.MANUAL, metadata: { attempts, mode: 'agentic-manual' } }; } catch (error) { logger.warn(`Agentic manual mode failed: ${error.message}`); return { success: false, text: null, serviceUsed: AI_SERVICE_TYPES.MANUAL, error: `Agentic manual mode failed: ${error.message}`, metadata: { attempts, template: generateManualTemplate(params) } }; } default: throw new Error(`Unknown service type: ${serviceType}`); } } catch (error) { lastError = error; logger.error(`Attempt ${attempts} failed: ${error.message}`); if (attempts < maxAttempts) { logger.info(`Retrying in ${config.retryDelay}ms...`); await new Promise(resolve => setTimeout(resolve, config.retryDelay)); config.retryDelay *= 2; // Exponential backoff } } } // All attempts failed return { success: false, text: null, serviceUsed: 'none', error: `All AI services failed after ${attempts} attempts. Last error: ${lastError?.message}`, metadata: { attempts, lastError: lastError?.message } }; } /** * Generate a structured object using the best available AI service * @param {Object} context - Context object * @param {Object} params - Generation parameters * @param {Object} config - Configuration options * @returns {Promise<Object>} Result object with parsed object and metadata */ export async function generateObject(context, params, config = DEFAULT_CONFIG) { const { session, projectRoot } = context; const { systemPrompt, userPrompt, schema, objectName, role = 'main', maxTokens = 4000 } = params; let lastError = null; let attempts = 0; const maxAttempts = config.maxRetries + 1; while (attempts < maxAttempts) { attempts++; try { const serviceType = determineAIService(context, config); logger.info(`Attempt ${attempts}: Using ${serviceType} for object generation`); switch (serviceType) { case AI_SERVICE_TYPES.ACTIVE_AGENT: try { logger.info('=== ACTIVE AI ASSISTANT DEBUG START ==='); logger.info(`System prompt length: ${systemPrompt?.length || 0}`); logger.info(`User prompt length: ${userPrompt?.length || 0}`); logger.info(`Object name: ${objectName}`); logger.info(`Schema keys: ${schema?.shape ? Object.keys(schema.shape).join(', ') : 'none'}`); const object = await generateObjectWithActiveAI(session, { systemPrompt, userPrompt, schema, objectName, maxTokens }); logger.info(`Generated object type: ${typeof object}`); logger.info(`Generated object keys: ${object && typeof object === 'object' ? Object.keys(object).join(', ') : 'none'}`); logger.info(`Generated object: ${JSON.stringify(object, null, 2)}`); logger.info('=== ACTIVE AI ASSISTANT DEBUG END ==='); return { success: true, object, serviceUsed: AI_SERVICE_TYPES.ACTIVE_AGENT, metadata: { attempts, aiInfo: getActiveAIInfo(session) } }; } catch (error) { logger.error(`=== ACTIVE AI ASSISTANT ERROR ===`); logger.error(`Error message: ${error.message}`); logger.error(`Error stack: ${error.stack}`); logger.error(`=== END ACTIVE AI ASSISTANT ERROR ===`); logger.warn(`Active AI assistant failed: ${error.message}`); // Keep active agent preference enabled - we want to always use it // config.preferActiveAgent = false; // Commented out to force active agent use throw error; } case AI_SERVICE_TYPES.EXTERNAL_API: try { const result = await generateObjectService({ role, session, projectRoot, schema, objectName, systemPrompt, prompt: userPrompt }); return { success: true, object: result, serviceUsed: AI_SERVICE_TYPES.EXTERNAL_API, metadata: { attempts, role } }; } catch (error) { logger.warn(`External API failed: ${error.message}`); config.enableExternalApiFallback = false; throw error; } case AI_SERVICE_TYPES.MANUAL: try { // Use agentic manual mode - generate object using current AI assistant instance logger.info('Using agentic manual mode for object generation'); const object = await generateObjectWithAgenticManualMode(session, params); return { success: true, object, serviceUsed: AI_SERVICE_TYPES.MANUAL, metadata: { attempts, mode: 'agentic-manual' } }; } catch (error) { logger.warn(`Agentic manual mode failed: ${error.message}`); return { success: false, object: null, serviceUsed: AI_SERVICE_TYPES.MANUAL, error: `Agentic manual mode failed: ${error.message}`, metadata: { attempts, template: generateManualObjectTemplate(params) } }; } default: throw new Error(`Unknown service type: ${serviceType}`); } } catch (error) { lastError = error; logger.error(`Attempt ${attempts} failed: ${error.message}`); if (attempts < maxAttempts) { logger.info(`Retrying in ${config.retryDelay}ms...`); await new Promise(resolve => setTimeout(resolve, config.retryDelay)); config.retryDelay *= 2; } } } return { success: false, object: null, serviceUsed: 'none', error: `All AI services failed after ${attempts} attempts. Last error: ${lastError?.message}`, metadata: { attempts, lastError: lastError?.message } }; } /** * Generate a manual template for text generation * @param {Object} params - Generation parameters * @returns {Object} Manual template */ function generateManualTemplate(params) { return { type: 'text-generation', systemPrompt: params.systemPrompt, userPrompt: params.userPrompt, instructions: 'Please provide the text response manually based on the prompts above.' }; } /** * Generate a manual template for object generation * @param {Object} params - Generation parameters * @returns {Object} Manual template */ function generateManualObjectTemplate(params) { return { type: 'object-generation', objectName: params.objectName, schema: params.schema.shape, systemPrompt: params.systemPrompt, userPrompt: params.userPrompt, instructions: `Please provide a JSON object for "${params.objectName}" that matches the schema above.` }; } /** * Generate text using agentic manual mode (current AI assistant instance) * @param {Object} session - MCP session object * @param {Object} params - Generation parameters * @returns {Promise<string>} Generated text */ async function generateTextWithAgenticManualMode(session, params) { const { systemPrompt, userPrompt } = params; logger.info('Generating text using agentic manual mode'); // For text generation, return a basic response return `Response generated using agentic manual mode for: ${userPrompt?.substring(0, 100)}...`; } /** * Generate object using agentic manual mode (current AI assistant instance) * @param {Object} session - MCP session object * @param {Object} params - Generation parameters * @returns {Promise<Object>} Generated and validated object */ async function generateObjectWithAgenticManualMode(session, params) { const { systemPrompt, userPrompt, schema, objectName } = params; logger.info(`Generating object "${objectName}" using agentic manual mode`); // For parse-prd specifically, generate appropriate task structure if (objectName === 'tasks_data') { logger.info('Detected parse-prd operation - generating task structure'); // Extract project information from prompts const projectInfo = extractProjectInfoFromPrompts(systemPrompt, userPrompt); // Generate tasks based on the PRD content const tasks = await generateTasksFromPRD(projectInfo, schema); return { tasks, metadata: { projectName: projectInfo.projectName || "PRD Implementation", totalTasks: tasks.length, sourceFile: projectInfo.sourceFile || "prd.txt", generatedAt: new Date().toISOString().split('T')[0] } }; } // For other object types, return a basic structure logger.warn(`Unknown object type "${objectName}" - returning basic structure`); return { generated: true, objectName, timestamp: new Date().toISOString(), mode: 'agentic-manual' }; } /** * Extract project information from system and user prompts * @param {string} systemPrompt - System prompt * @param {string} userPrompt - User prompt * @returns {Object} Extracted project information */ function extractProjectInfoFromPrompts(systemPrompt, userPrompt) { const info = { projectName: "PRD Implementation", sourceFile: "prd.txt", content: "" }; // Extract project name from prompts const projectNameMatch = systemPrompt?.match(/project[:\s]+([^.\n]+)/i) || userPrompt?.match(/project[:\s]+([^.\n]+)/i); if (projectNameMatch) { info.projectName = projectNameMatch[1].trim(); } // Extract source file from prompts const sourceFileMatch = userPrompt?.match(/file[:\s]+([^\s\n]+)/i); if (sourceFileMatch) { info.sourceFile = sourceFileMatch[1].trim(); } // Extract content info.content = userPrompt || ""; return info; } /** * Generate tasks from PRD content using agentic manual mode * @param {Object} projectInfo - Project information * @param {Object} schema - Zod schema for validation * @returns {Promise<Array>} Generated tasks */ async function generateTasksFromPRD(projectInfo, schema) { logger.info('Generating tasks from PRD using agentic manual mode'); // Generate a comprehensive set of tasks based on common project patterns const baseTasks = [ { id: 1, title: "Project Setup and Repository Initialization", description: "Set up the project repository, initialize version control, and configure basic project structure", details: "Create repository structure, set up .gitignore, initialize package.json or equivalent, configure basic CI/CD pipeline, and establish development environment setup documentation", testStrategy: "Verify repository is properly initialized, all necessary files are present, and development environment can be set up following documentation", priority: "high", dependencies: [] }, { id: 2, title: "Core Architecture Design and Documentation", description: "Design the core system architecture and create comprehensive technical documentation", details: "Define system architecture, create component diagrams, establish data flow patterns, design API interfaces, and document technical decisions and trade-offs", testStrategy: "Review architecture documentation with stakeholders, validate design patterns meet requirements, and ensure scalability considerations are addressed", priority: "high", dependencies: [1] }, { id: 3, title: "Database Schema Design and Implementation", description: "Design and implement the database schema based on project requirements", details: "Create entity relationship diagrams, design database tables and relationships, implement migration scripts, set up database connections, and establish data access patterns", testStrategy: "Validate schema against requirements, test migration scripts, verify data integrity constraints, and ensure proper indexing for performance", priority: "high", dependencies: [2] }, { id: 4, title: "Authentication and Authorization System", description: "Implement user authentication and role-based authorization system", details: "Set up user registration and login flows, implement JWT or session-based authentication, create role-based access control, add password security measures, and implement account management features", testStrategy: "Test authentication flows, verify authorization rules, validate security measures, and ensure proper session management", priority: "high", dependencies: [3] }, { id: 5, title: "Core API Development", description: "Develop the core API endpoints and business logic", details: "Implement REST API endpoints, create request/response models, add input validation, implement business logic, set up error handling, and add API documentation", testStrategy: "Test all API endpoints, validate request/response formats, verify error handling, and ensure proper HTTP status codes", priority: "high", dependencies: [4] }, { id: 6, title: "Frontend User Interface Development", description: "Develop the user interface and user experience components", details: "Create responsive UI components, implement navigation, add form handling, integrate with API endpoints, implement state management, and ensure accessibility compliance", testStrategy: "Test UI components across devices, verify responsive design, validate form submissions, and ensure accessibility standards are met", priority: "medium", dependencies: [5] }, { id: 7, title: "Data Processing and Business Logic", description: "Implement core data processing algorithms and business rules", details: "Develop data processing pipelines, implement business rule engines, add data validation and transformation logic, create reporting mechanisms, and optimize performance", testStrategy: "Test data processing accuracy, validate business rules, verify performance benchmarks, and ensure data integrity throughout processing", priority: "medium", dependencies: [5] }, { id: 8, title: "Integration and Third-party Services", description: "Integrate with external services and APIs required by the project", details: "Implement third-party API integrations, set up webhook handlers, add external service authentication, implement retry and error handling for external calls, and create service monitoring", testStrategy: "Test all external integrations, verify error handling for service failures, validate webhook processing, and ensure proper rate limiting", priority: "medium", dependencies: [7] }, { id: 9, title: "Testing Infrastructure and Test Suite", description: "Establish comprehensive testing infrastructure and create test suites", details: "Set up unit testing framework, create integration tests, implement end-to-end testing, add performance testing, establish test data management, and configure continuous testing", testStrategy: "Verify test coverage meets requirements, validate test reliability, ensure tests run in CI/CD pipeline, and confirm test data isolation", priority: "high", dependencies: [8] }, { id: 10, title: "Security Implementation and Hardening", description: "Implement security measures and perform security hardening", details: "Add input sanitization, implement CSRF protection, set up rate limiting, add security headers, perform vulnerability scanning, and implement security monitoring", testStrategy: "Conduct security testing, perform penetration testing, verify security headers, and validate protection against common vulnerabilities", priority: "high", dependencies: [9] }, { id: 11, title: "Performance Optimization and Monitoring", description: "Optimize system performance and implement monitoring solutions", details: "Profile application performance, optimize database queries, implement caching strategies, set up application monitoring, add performance metrics, and create alerting systems", testStrategy: "Conduct performance testing, verify monitoring accuracy, validate alerting thresholds, and ensure performance meets requirements", priority: "medium", dependencies: [10] }, { id: 12, title: "Documentation and User Guides", description: "Create comprehensive documentation and user guides", details: "Write API documentation, create user manuals, develop deployment guides, document configuration options, create troubleshooting guides, and establish documentation maintenance processes", testStrategy: "Review documentation accuracy, validate setup procedures, test troubleshooting guides, and ensure documentation completeness", priority: "medium", dependencies: [11] }, { id: 13, title: "Deployment and DevOps Setup", description: "Set up production deployment pipeline and DevOps infrastructure", details: "Configure production environment, set up CI/CD pipelines, implement automated deployments, configure monitoring and logging, set up backup systems, and establish rollback procedures", testStrategy: "Test deployment procedures, verify monitoring and alerting, validate backup and restore processes, and ensure rollback capabilities", priority: "high", dependencies: [12] }, { id: 14, title: "User Acceptance Testing and Quality Assurance", description: "Conduct comprehensive user acceptance testing and quality assurance", details: "Create UAT test plans, conduct user testing sessions, gather feedback, perform regression testing, validate requirements compliance, and document test results", testStrategy: "Execute all UAT scenarios, validate user feedback incorporation, verify requirements traceability, and ensure quality standards are met", priority: "high", dependencies: [13] }, { id: 15, title: "Production Launch and Go-Live", description: "Execute production launch and monitor initial go-live period", details: "Deploy to production environment, monitor system performance, provide user support, gather initial feedback, address immediate issues, and document lessons learned", testStrategy: "Monitor system stability, track user adoption, verify performance metrics, and ensure support processes are effective", priority: "high", dependencies: [14] } ]; // Customize tasks based on project content if available if (projectInfo.content) { logger.info('Customizing tasks based on PRD content'); // Add project-specific customizations here // For now, we'll use the base tasks } logger.info(`Generated ${baseTasks.length} tasks for project: ${projectInfo.projectName}`); return baseTasks; } /** * Get status of all available AI services * @param {Object} context - Context object * @returns {Object} Status of all services */ export function getAIServiceStatus(context) { const { session } = context; return { activeAgent: { available: hasActiveAIAssistant(session), info: getActiveAIInfo(session) }, externalAPI: { available: true, // Would check actual API configuration configured: false // Would check if API keys are set }, manual: { available: true, mode: 'agentic-manual' } }; }