UNPKG

task-master-neo-sdlc

Version:

Enhanced task management system with Neo SDLC agents and MCP tools for comprehensive, AI-driven software development lifecycle management.

163 lines (143 loc) 7.55 kB
import { KnowledgeGraph } from '../knowledge-graph'; import { AgentWorkflowSystem } from '../agent-workflow'; // Assume workflow definitions might be stored in KG or loaded from files // import workflowLoader from '../../utils/workflowLoader'; export class ProcessManagerAgent { constructor(knowledgeGraph, workflowSystem) { this.knowledgeGraph = knowledgeGraph; this.workflowSystem = workflowSystem; // Use the existing workflow system this.runningProcesses = new Map(); // Track ongoing processes } /** * Starts a defined process or workflow. * @param {string} workflowDefinitionId - ID of the workflow definition (in KG or file). * @param {object} initialContext - Initial data for the workflow instance. * @returns {Promise<string>} The ID of the started process instance. */ async startProcess(workflowDefinitionId, initialContext = {}) { console.log(`Starting process based on workflow definition: ${workflowDefinitionId}`); // Placeholder: Load workflow definition // const definition = await workflowLoader.load(workflowDefinitionId); const definition = { id: workflowDefinitionId, name: `Workflow ${workflowDefinitionId}`, steps: [ { id: 'step1', action: 'agentA.doSomething', next: 'step2' }, { id: 'step2', action: 'agentB.doAnotherThing', params: { input: '${step1.output}' } , next: null }, // Example: Using output from step1 ] }; if (!definition || !definition.steps || definition.steps.length === 0) { throw new Error(`Workflow definition ${workflowDefinitionId} is invalid or empty.`); } const processInstanceId = `process_${Date.now()}`; const processState = { id: processInstanceId, definitionId: workflowDefinitionId, status: 'running', // running, completed, failed, suspended currentStepId: definition.steps[0].id, context: { ...initialContext }, history: [{ stepId: null, status: 'started', timestamp: Date.now() }] }; this.runningProcesses.set(processInstanceId, processState); // Add process instance to knowledge graph await this.knowledgeGraph.addNode({ id: `processInstance:${processInstanceId}`, type: 'process_instance', data: { ...processState, history: processState.history.slice(-5) } // Store recent history }); console.log(`Process instance ${processInstanceId} started at step ${processState.currentStepId}.`); // Trigger the first step execution asynchronously this.executeStep(processInstanceId); return processInstanceId; } /** * Executes the current step of a running process instance. * (Typically called internally or triggered by events) * @param {string} processInstanceId - The ID of the process instance. */ async executeStep(processInstanceId) { const processState = this.runningProcesses.get(processInstanceId); if (!processState || processState.status !== 'running') { console.log(`Process ${processInstanceId} is not in a runnable state (${processState?.status}).`); return; } // Placeholder: Load definition again if needed const definition = { steps: [{ id: 'step1', action: 'agentA.doSomething', next: 'step2' }, { id: 'step2', action: 'agentB.doAnotherThing', params: { input: '${step1.output}' }, next: null }] }; const currentStep = definition.steps.find(s => s.id === processState.currentStepId); if (!currentStep) { console.error(`Current step ${processState.currentStepId} not found in definition for process ${processInstanceId}. Failing process.`); processState.status = 'failed'; processState.history.push({ stepId: processState.currentStepId, status: 'error', details: 'Step definition not found', timestamp: Date.now() }); this.runningProcesses.delete(processInstanceId); // Or mark as failed await this._updateProcessStateInKG(processInstanceId, processState); return; } console.log(`Executing step ${currentStep.id} for process ${processInstanceId}: ${currentStep.action}`); processState.history.push({ stepId: currentStep.id, status: 'executing', timestamp: Date.now() }); await this._updateProcessStateInKG(processInstanceId, processState); try { // Placeholder: Execute the action defined in the step. // This would involve resolving the action string (e.g., 'agentA.doSomething') // to an actual function call, potentially via the AgentWorkflowSystem. // It would also handle parameter substitution from context. // const result = await this.workflowSystem.executeAction(currentStep.action, currentStep.params, processState.context); const result = { output: `Result from ${currentStep.action}` }; // Simulate result // Update context with step result processState.context[currentStep.id] = result; processState.history.push({ stepId: currentStep.id, status: 'completed', timestamp: Date.now() }); // Move to next step or complete if (currentStep.next) { processState.currentStepId = currentStep.next; await this._updateProcessStateInKG(processInstanceId, processState); // Trigger next step asynchronously setImmediate(() => this.executeStep(processInstanceId)); } else { processState.status = 'completed'; this.runningProcesses.delete(processInstanceId); // Remove completed process console.log(`Process instance ${processInstanceId} completed successfully.`); await this._updateProcessStateInKG(processInstanceId, processState); } } catch (error) { console.error(`Error executing step ${currentStep.id} for process ${processInstanceId}:`, error); processState.status = 'failed'; processState.history.push({ stepId: currentStep.id, status: 'failed', details: error.message, timestamp: Date.now() }); this.runningProcesses.delete(processInstanceId); // Remove failed process await this._updateProcessStateInKG(processInstanceId, processState); } } /** * Gets the status and context of a running process instance. * @param {string} processInstanceId - The ID of the process instance. * @returns {Promise<object|null>} The process state or null if not found. */ async getProcessStatus(processInstanceId) { const state = this.runningProcesses.get(processInstanceId); if (state) { return { ...state }; // Return a copy } // Maybe check KG for historical/completed processes const node = await this.knowledgeGraph.findNodes({ id: `processInstance:${processInstanceId}` }).then(n => n[0]); return node ? node.data : null; } /** * Helper to update process state in Knowledge Graph. * @param {string} instanceId - The process instance ID. * @param {object} state - The current process state. */ async _updateProcessStateInKG(instanceId, state) { try { await this.knowledgeGraph.updateContext({ id: `processInstance:${instanceId}`, // type: 'process_instance', // Type might not be needed for updateContext data: { ...state, history: state.history.slice(-10) } // Update with recent history }); } catch (kgError) { console.error(`Failed to update process state in KG for ${instanceId}:`, kgError); // Decide how to handle KG update failure (retry, log, etc.) } } // Other potential methods: // - suspendProcess(processInstanceId) // - resumeProcess(processInstanceId) // - cancelProcess(processInstanceId) }