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
JavaScript
/**
* 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'
}
};
}