UNPKG

crewai-ts

Version:

TypeScript port of crewAI for agent-based workflows

208 lines (207 loc) 7.75 kB
/** * Crew Agent Executor Mixin * Handles agent execution with memory management and human feedback capabilities * Optimized for performance and memory efficiency */ // Placeholder for TaskEvaluator until fully implemented class TaskEvaluator { agent; constructor(agent) { this.agent = agent; } async evaluate(task, outputText) { // Simplified implementation for now return { quality: 0.8, suggestions: ['Consider adding more details'], entities: [] }; } } /** * Crew Agent Executor Mixin * * This mixin provides memory management and human feedback functionality * for agent execution with performance optimizations. */ export class CrewAgentExecutorMixin { crew; // Will be properly typed when Crew is implemented agent; task; iterations = 0; maxIterations; memoryEnabled; humanInTheLoop; trainingMode; printer; // Will be properly typed later /** * Constructor for the executor mixin * @param agent Agent being executed * @param task Task being executed * @param crew Crew the agent belongs to (optional) * @param options Execution options */ constructor(agent, task, crew, options = {}) { this.agent = agent; this.task = task; this.crew = crew; this.maxIterations = options.maxIterations ?? 15; this.memoryEnabled = options.memory ?? true; this.humanInTheLoop = options.humanInTheLoop ?? false; this.trainingMode = options.trainingMode ?? false; this.printer = options.printer ?? { print: (content, color) => { console.log(content); } }; } /** * Process the execution result * Updates memory and handles human feedback * @param result Execution result * @returns The processed result */ async processResult(result) { // Track iterations this.iterations++; // Only process if we have a crew with memory if (this.memoryEnabled && this.crew) { // Create short term memory if applicable await this.createShortTermMemory(result); // Create long term memory if applicable await this.createLongTermMemory(result); } // Handle human feedback if enabled if (this.humanInTheLoop) { const feedback = await this.askHumanInput(result.text); if (feedback) { // If feedback was provided, attach it to the result return { ...result, humanFeedback: feedback }; } } return result; } /** * Create and save a short-term memory item if conditions are met * Optimized with error handling and validation * @param output Execution output */ async createShortTermMemory(output) { try { if (this.crew && this.agent && this.task && !output.text.includes('Action: Delegate work to coworker') && this.crew.hasShortTermMemory() // This method would be implemented in the Crew class ) { await this.crew.addToShortTermMemory(output.text, { observation: this.task.description, }, this.agent.role); } } catch (error) { console.error('Failed to add to short term memory:', error); } } /** * Create and save long-term and entity memory items based on evaluation * Optimized for async operations and error handling * @param output Execution output */ async createLongTermMemory(output) { try { if (this.crew && this.crew.hasMemory() && // This method would be implemented in the Crew class this.crew.hasLongTermMemory() && // This method would be implemented in the Crew class this.crew.hasEntityMemory() && // This method would be implemented in the Crew class this.task && this.agent) { // Create task evaluator const evaluator = new TaskEvaluator(this.agent); const evaluation = await evaluator.evaluate(this.task, output.text); if (!evaluation) { return; } // Create and save long term memory const longTermMemory = { task: this.task.description, agent: this.agent.role, quality: evaluation.quality, datetime: Date.now().toString(), expectedOutput: this.task.expectedOutput, metadata: { suggestions: evaluation.suggestions, quality: evaluation.quality, }, }; await this.crew.addToLongTermMemory(longTermMemory); // Create and save entity memories for (const entity of evaluation.entities) { const entityMemory = { name: entity.name, type: entity.type, description: entity.description, relationships: entity.relationships.map((r) => `- ${r}`).join('\n'), }; await this.crew.addToEntityMemory(entityMemory); } } } catch (error) { console.error('Failed to add to long term memory:', error); } } /** * Prompt human input with mode-appropriate messaging * @param finalAnswer Final answer to present to the human * @returns Human feedback or empty string if no feedback */ async askHumanInput(finalAnswer) { this.printer.print(`## Final Result: ${finalAnswer}`, 'green'); let prompt; // Different prompts based on mode if (this.trainingMode) { // Training mode prompt (single iteration) prompt = [ '\n\n=====\n', '## TRAINING MODE: Provide feedback to improve the agent\'s performance.', 'This will be used to train better versions of the agent.', 'Please provide detailed feedback about the result quality and reasoning process.', '=====\n' ].join('\n'); } else { // Regular human-in-the-loop prompt (multiple iterations) prompt = [ '\n\n=====\n', '## HUMAN FEEDBACK: Provide feedback on the Final Result and Agent\'s actions.', 'Please follow these guidelines:', ' - If you are happy with the result, simply hit Enter without typing anything.', ' - Otherwise, provide specific improvement requests.', ' - You can provide multiple rounds of feedback until satisfied.', '=====\n' ].join('\n'); } this.printer.print(prompt, 'yellow'); // In a real implementation, this would get input from the user // For now, we'll just return an empty string return ''; } /** * Get the current iteration count * @returns Number of iterations executed */ getIterations() { return this.iterations; } /** * Check if the execution has reached the maximum number of iterations * @returns True if max iterations reached, false otherwise */ hasReachedMaxIterations() { return this.iterations >= this.maxIterations; } }