UNPKG

vibe-coder-mcp

Version:

Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.

210 lines (209 loc) 7.91 kB
import { JobStatus } from './index.js'; import logger from '../../logger.js'; export class JobExecutionAdapter { executionCoordinator; jobToExecutionMap = new Map(); executionToJobMap = new Map(); constructor(executionCoordinator) { this.executionCoordinator = executionCoordinator; } convertJobToScheduledTask(job) { const { toolName, params } = job; const atomicTask = { id: job.id, title: `${toolName} execution`, description: params.description || `Executing ${toolName} tool`, status: 'pending', priority: params.priority || 'medium', type: 'development', functionalArea: 'backend', estimatedHours: params.estimatedHours || 1, actualHours: undefined, epicId: params.epicId || 'default-epic', projectId: params.projectId || 'default-project', dependencies: [], dependents: [], filePaths: [], acceptanceCriteria: params.acceptanceCriteria || [`${toolName} execution completed successfully`], testingRequirements: { unitTests: [], integrationTests: [], performanceTests: [], coverageTarget: 0 }, performanceCriteria: {}, qualityCriteria: { codeQuality: [], documentation: [], typeScript: false, eslint: false }, integrationCriteria: { compatibility: [], patterns: [] }, validationMethods: { automated: [], manual: [] }, createdAt: new Date(job.createdAt), updatedAt: new Date(job.updatedAt), createdBy: 'job-manager', tags: params.tags || [toolName], metadata: { createdAt: new Date(job.createdAt), updatedAt: new Date(job.updatedAt), createdBy: 'job-manager', tags: params.tags || [toolName] } }; const scheduledTask = { task: atomicTask, scheduledStart: new Date(), scheduledEnd: new Date(Date.now() + (params.estimatedHours || 1) * 60 * 60 * 1000), assignedResources: { memoryMB: params.estimatedMemoryMB || 256, cpuWeight: params.estimatedCPUWeight || 1.0, agentId: params.agentId }, batchId: 0, prerequisiteTasks: [], dependentTasks: [], metadata: { algorithm: 'priority_first', priorityScore: 0, resourceScore: 0, deadlineScore: 0, dependencyScore: 0, durationScore: 0, systemLoadScore: 0, complexityScore: 0, businessImpactScore: 0, agentAvailabilityScore: 0, totalScore: 0, scheduledAt: new Date(), lastOptimized: new Date() } }; return scheduledTask; } async executeJob(job) { try { const scheduledTask = this.convertJobToScheduledTask(job); const execution = await this.executionCoordinator.executeTask(scheduledTask); this.jobToExecutionMap.set(job.id, execution.metadata.executionId); this.executionToJobMap.set(execution.metadata.executionId, job.id); logger.info({ jobId: job.id, executionId: execution.metadata.executionId, toolName: job.toolName }, 'Job execution started via ExecutionCoordinator'); return execution.metadata.executionId; } catch (error) { logger.error({ jobId: job.id, toolName: job.toolName, error: error instanceof Error ? error.message : String(error) }, 'Failed to execute job via ExecutionCoordinator'); throw error; } } async cancelJobExecution(jobId) { const executionId = this.jobToExecutionMap.get(jobId); if (!executionId) { logger.warn({ jobId }, 'No execution found for job'); return false; } try { const cancelled = await this.executionCoordinator.cancelExecution(executionId); if (cancelled) { logger.info({ jobId, executionId }, 'Job execution cancelled'); this.jobToExecutionMap.delete(jobId); this.executionToJobMap.delete(executionId); } return cancelled; } catch (error) { logger.error({ jobId, executionId, error: error instanceof Error ? error.message : String(error) }, 'Failed to cancel job execution'); return false; } } async getJobExecutionStatus(jobId) { const executionId = this.jobToExecutionMap.get(jobId); if (!executionId) { return null; } const statusInfo = await this.executionCoordinator.getTaskExecutionStatus(jobId); return statusInfo ? statusInfo.status : null; } convertExecutionStatusToJobStatus(executionStatus) { switch (executionStatus) { case 'queued': return JobStatus.PENDING; case 'running': return JobStatus.RUNNING; case 'completed': return JobStatus.COMPLETED; case 'failed': case 'cancelled': case 'timeout': return JobStatus.FAILED; default: return JobStatus.PENDING; } } async getJobExecutionResult(jobId) { const executionId = this.jobToExecutionMap.get(jobId); if (!executionId) { return null; } const metrics = this.executionCoordinator.getExecutionMetrics(); logger.debug({ jobId, executionId, totalExecuted: metrics.totalTasksExecuted, running: metrics.runningTasks }, 'Retrieved execution metrics for job'); return null; } registerJobLifecycleHooks(jobStatusUpdater) { this.executionCoordinator.onExecutionStateChange((event) => { const jobId = this.executionToJobMap.get(event.executionId); if (jobId) { const jobStatus = this.convertExecutionStatusToJobStatus(event.newStatus); const message = `Execution ${event.newStatus}: ${event.metadata?.reason || ''}`; jobStatusUpdater(jobId, jobStatus, message.trim()); if (event.newStatus === 'completed' || event.newStatus === 'failed' || event.newStatus === 'cancelled' || event.newStatus === 'timeout') { this.jobToExecutionMap.delete(jobId); this.executionToJobMap.delete(event.executionId); } } }); } getJobIdFromExecutionId(executionId) { return this.executionToJobMap.get(executionId); } getExecutionIdFromJobId(jobId) { return this.jobToExecutionMap.get(jobId); } cleanup() { this.jobToExecutionMap.clear(); this.executionToJobMap.clear(); } } let adapterInstance = null; export function getJobExecutionAdapter(executionCoordinator) { if (!adapterInstance && executionCoordinator) { adapterInstance = new JobExecutionAdapter(executionCoordinator); } if (!adapterInstance) { throw new Error('JobExecutionAdapter not initialized. Provide ExecutionCoordinator on first call.'); } return adapterInstance; }