agentic-data-stack-community
Version:
AI Agentic Data Stack Framework - Community Edition. Open source data engineering framework with 4 core agents, essential templates, and 3-dimensional quality validation.
909 lines (782 loc) ⢠30.4 kB
JavaScript
/**
* Agent Orchestrator - Multi-Agent Coordination System
*
* Manages agent lifecycle, activation, collaboration, and state management.
* Implements advanced agent patterns for data engineering workflows.
*/
const chalk = require('chalk');
const fs = require('fs-extra');
const path = require('path');
const yaml = require('yaml');
class Agent {
constructor(config, orchestrator) {
this.id = config.id;
this.name = config.name;
this.title = config.title;
this.icon = config.icon;
this.persona = config.persona;
this.commands = config.commands || [];
this.dependencies = config.dependencies || {};
this.orchestrator = orchestrator;
this.state = 'inactive';
this.context = {};
// Advanced coordination capabilities
this.collaborationMode = false;
this.handoffContext = {};
this.workflowState = {};
this.validationRules = config.validation || {};
this.elicitationPreferences = config.elicitation || { method: 'auto', progressive: true };
this.progressiveDisclosure = true;
this.qualityThresholds = config.quality || { completeness: 0.8, accuracy: 0.9, consistency: 0.85 };
this.sessionPersistence = true;
this.knowledgeBase = {};
this.statusTracking = { current: 'ready', history: [], checkpoints: [] };
}
async activate(context = {}) {
this.state = 'active';
this.context = { ...this.context, ...context };
console.log(chalk.green(`${this.icon} ${this.name} activated`));
console.log(chalk.dim(`${this.persona.role}`));
return this;
}
async executeCommand(command, args = [], context = {}) {
const cmd = this.commands.find(c => c.name === command);
if (!cmd) {
throw new Error(`Unknown command: ${command}`);
}
console.log(chalk.blue(`Executing: ${command} ${args.join(' ')}`));
// Route to appropriate handler
switch (command) {
case 'task':
return await this.executeTask(args[0], context);
case 'create-doc':
return await this.createDocument(args[0], context);
case 'help':
return this.showHelp();
default:
return await this.handleCustomCommand(command, args, context);
}
}
async executeTask(taskName, context = {}) {
// If no task name provided, show available tasks
if (!taskName || taskName.trim() === '') {
const tasks = await this.listTasks();
console.log(chalk.yellow('š Available tasks:'));
tasks.forEach(task => {
console.log(chalk.gray(` ⢠${task.name}: ${task.description}`));
});
console.log(chalk.blue('\nš” Usage: *task <task-name> or use specific commands like *analyze-data'));
return;
}
const taskPath = this.resolveTaskPath(taskName);
if (!await fs.pathExists(taskPath)) {
throw new Error(`Task file not found: ${taskName}.md\nPath checked: ${taskPath}`);
}
console.log(chalk.blue(`š Starting task: ${taskName}`));
// Load and execute task
const taskContent = await fs.readFile(taskPath, 'utf8');
return await this.orchestrator.taskOrchestrator.executeTaskContent(taskContent, context);
}
async createDocument(templateName, context = {}) {
// If no template name provided, show available templates
if (!templateName || templateName.trim() === '') {
const templates = await this.getAvailableTemplates();
console.log(chalk.yellow('š Available templates:'));
templates.forEach(template => {
console.log(chalk.gray(` ⢠${template.name}: ${template.description || 'No description'}`));
});
console.log(chalk.blue('\nš” Usage: *create-doc <template-name>'));
return;
}
console.log(chalk.blue(`š Creating document from template: ${templateName}`));
return await this.orchestrator.templateEngine.processTemplate(templateName, {
...context,
agent: this
});
}
async processInput(input, context = {}) {
// Intelligent input processing based on agent capabilities
const normalized = input.toLowerCase().trim();
// Check for direct command matches
for (const cmd of this.commands) {
if (normalized.startsWith(cmd.name)) {
const args = input.split(' ').slice(1);
return await this.executeCommand(cmd.name, args, context);
}
}
// Check for task matches
const tasks = await this.listTasks();
for (const task of tasks) {
if (this.matchesTask(normalized, task)) {
return await this.executeTask(task.name, context);
}
}
// Intelligent interpretation based on agent specialty
return await this.interpretRequest(input, context);
}
async interpretRequest(input, context = {}) {
// Agent-specific request interpretation
const interpretation = this.getRequestInterpretation(input);
if (interpretation.confidence > 0.7) {
console.log(chalk.blue(`š” I think you want to: ${interpretation.suggestion}`));
return await interpretation.action(context);
}
console.log(chalk.yellow(`ā I'm not sure how to help with: "${input}"`));
console.log(chalk.dim('Try one of my available commands or tasks.'));
return { success: false, error: 'Request not understood' };
}
getRequestInterpretation(input) {
const interpretations = this.getAgentSpecificInterpretations();
const inputLower = input.toLowerCase();
for (const interp of interpretations) {
let confidence = 0;
for (const keyword of interp.keywords) {
if (inputLower.includes(keyword)) {
confidence += interp.weight || 0.1;
}
}
if (confidence > 0) {
return {
confidence,
suggestion: interp.suggestion,
action: interp.action
};
}
}
return { confidence: 0 };
}
getAgentSpecificInterpretations() {
// Override in specific agent implementations
return [];
}
async listTasks() {
const tasks = [];
const taskPaths = this.dependencies.tasks || [];
for (const taskFile of taskPaths) {
const taskPath = this.resolveTaskPath(taskFile);
if (await fs.pathExists(taskPath)) {
const content = await fs.readFile(taskPath, 'utf8');
const title = this.extractTaskTitle(content);
const description = this.extractTaskDescription(content);
tasks.push({
name: taskFile.replace('.md', ''),
title,
description,
file: taskFile
});
}
}
return tasks;
}
resolveTaskPath(taskName) {
const baseName = taskName.replace('.md', '');
return path.join(this.orchestrator.dataCore, 'tasks', `${baseName}.md`);
}
extractTaskTitle(content) {
const match = content.match(/^#\s+(.+)/m);
return match ? match[1] : 'Untitled Task';
}
extractTaskDescription(content) {
const lines = content.split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith('## Overview') || lines[i].includes('description')) {
return lines[i + 1]?.trim() || 'No description available';
}
}
return 'No description available';
}
matchesTask(input, task) {
const taskWords = task.name.toLowerCase().split('-');
const inputWords = input.split(' ');
return taskWords.some(taskWord =>
inputWords.some(inputWord =>
inputWord.includes(taskWord) || taskWord.includes(inputWord)
)
);
}
showHelp() {
console.log(chalk.bold(`\n${this.icon} ${this.name} - ${this.title}`));
console.log(chalk.dim(`${this.persona.role}\n`));
if (this.persona.core_principles) {
console.log(chalk.bold('Core Principles:'));
this.persona.core_principles.forEach(principle => {
console.log(` ⢠${principle}`);
});
console.log('');
}
console.log(chalk.bold('Available Commands:'));
this.commands.forEach(cmd => {
console.log(` *${cmd.name}: ${cmd.description}`);
});
console.log(chalk.bold('\nKnowledge Base Commands:'));
console.log(' *kb-mode: Enter interactive knowledge base mode');
console.log(' *search <query>: Search the knowledge base');
console.log(chalk.bold('\nDocument Management Commands:'));
console.log(' *shard-doc <path>: Shard a document into sections');
console.log(' *manage-docs: Interactive document management');
console.log(chalk.bold('\nExpansion Pack Commands:'));
console.log(' *manage-packs: Browse and manage expansion packs');
console.log(' *install-pack <name>: Install an expansion pack');
console.log(' *create-pack: Create a new expansion pack');
console.log('');
return { success: true };
}
async getAvailableTemplates() {
const templatesDir = path.join(this.orchestrator.dataCore, 'templates');
const templates = [];
try {
if (await fs.pathExists(templatesDir)) {
const files = await fs.readdir(templatesDir);
for (const file of files) {
if (file.endsWith('.yaml')) {
const templateName = file.replace('.yaml', '');
templates.push({
name: templateName,
description: `Template for ${templateName.replace(/-/g, ' ')}`
});
}
}
}
} catch (error) {
console.error('Error reading templates:', error.message);
}
return templates;
}
async handleCustomCommand(command, args, context) {
// Handle agent-specific commands like *analyze-data, *build-pipeline, etc.
// Check if this is a task command that maps to an actual task file
const taskPath = this.resolveTaskPath(command);
if (await fs.pathExists(taskPath)) {
return await this.executeTask(command, context);
}
// If it's not a task file, provide a helpful error
throw new Error(`Command '${command}' not implemented for agent '${this.id}'. Available commands: ${this.commands?.map(c => c.name).join(', ') || 'none'}`);
}
deactivate() {
this.state = 'inactive';
this.context = {};
console.log(chalk.dim(`${this.name} deactivated`));
}
}
class DataEngineerAgent extends Agent {
getAgentSpecificInterpretations() {
return [
{
keywords: ['pipeline', 'etl', 'data flow', 'build'],
suggestion: 'build a data pipeline',
action: async (context) => await this.executeTask('build-pipeline', context),
weight: 0.3
},
{
keywords: ['monitor', 'monitoring', 'observe'],
suggestion: 'setup monitoring',
action: async (context) => await this.executeTask('setup-monitoring', context),
weight: 0.3
},
{
keywords: ['quality', 'validation', 'check'],
suggestion: 'implement quality checks',
action: async (context) => await this.executeTask('implement-quality-checks', context),
weight: 0.2
}
];
}
}
class DataAnalystAgent extends Agent {
getAgentSpecificInterpretations() {
return [
{
keywords: ['analyze', 'analysis', 'insight', 'explore'],
suggestion: 'analyze data',
action: async (context) => await this.executeTask('analyze-data', context),
weight: 0.3
},
{
keywords: ['segment', 'customer', 'rfm'],
suggestion: 'perform customer segmentation',
action: async (context) => await this.executeTask('segment-customers', context),
weight: 0.3
},
{
keywords: ['dashboard', 'visualization', 'report'],
suggestion: 'create dashboard',
action: async (context) => await this.executeTask('create-dashboard', context),
weight: 0.2
}
];
}
}
class DataProductManagerAgent extends Agent {
getAgentSpecificInterpretations() {
return [
{
keywords: ['requirements', 'gathering', 'stakeholder'],
suggestion: 'gather requirements',
action: async (context) => await this.executeTask('gather-requirements', context),
weight: 0.3
},
{
keywords: ['contract', 'specification', 'define'],
suggestion: 'create data contract',
action: async (context) => await this.executeTask('create-data-contract', context),
weight: 0.3
},
{
keywords: ['metrics', 'kpi', 'measure'],
suggestion: 'define metrics',
action: async (context) => await this.executeTask('define-metrics', context),
weight: 0.2
}
];
}
}
class DataQualityEngineerAgent extends Agent {
getAgentSpecificInterpretations() {
return [
{
keywords: ['quality', 'validation', 'check', 'test'],
suggestion: 'implement quality checks',
action: async (context) => await this.executeTask('implement-quality-checks', context),
weight: 0.4
},
{
keywords: ['profile', 'profiling', 'understand'],
suggestion: 'profile data',
action: async (context) => await this.executeTask('profile-data', context),
weight: 0.3
},
{
keywords: ['monitor', 'monitoring', 'observe'],
suggestion: 'setup quality monitoring',
action: async (context) => await this.executeTask('setup-monitoring', context),
weight: 0.2
}
];
}
}
class AgentOrchestrator {
constructor(options = {}) {
this.rootDir = options.rootDir || process.cwd();
this.dataCore = path.join(this.rootDir, 'data-core');
this.agents = new Map();
this.activeAgents = new Map();
this.taskOrchestrator = null; // Will be injected
this.templateEngine = null; // Will be injected
}
async initialize() {
await this.loadAgents();
}
async loadAgents() {
const agentDir = path.join(this.dataCore, 'agents');
const agentFiles = await fs.readdir(agentDir);
for (const file of agentFiles) {
if (file.endsWith('.md')) {
await this.loadAgent(path.join(agentDir, file));
}
}
}
async loadAgent(agentPath) {
const content = await fs.readFile(agentPath, 'utf8');
const config = this.parseAgentConfig(content);
if (!config) return;
// Create appropriate agent class
let agent;
switch (config.id) {
case 'data-engineer':
agent = new DataEngineerAgent(config, this);
break;
case 'data-analyst':
agent = new DataAnalystAgent(config, this);
break;
case 'data-product-manager':
agent = new DataProductManagerAgent(config, this);
break;
case 'data-quality-engineer':
agent = new DataQualityEngineerAgent(config, this);
break;
default:
agent = new Agent(config, this);
}
this.agents.set(config.id, agent);
}
parseAgentConfig(content) {
try {
// Extract YAML block from markdown
const yamlMatch = content.match(/```yaml\n([\s\S]*?)\n```/);
if (!yamlMatch) return null;
const config = yaml.parse(yamlMatch[1]);
// Transform config to expected format
return {
id: config.agent?.id,
name: config.agent?.name,
title: config.agent?.title,
icon: config.agent?.icon,
persona: config.persona,
commands: this.parseCommands(config.commands),
dependencies: config.dependencies
};
} catch (error) {
console.error(`Error parsing agent config: ${error.message}`);
return null;
}
}
parseCommands(commandsData) {
if (!commandsData) return [];
const commands = [];
// Handle different command formats
if (Array.isArray(commandsData)) {
// Array format: ['help: Show help', 'task: Execute task']
commandsData.forEach(cmd => {
if (typeof cmd === 'string') {
const match = cmd.match(/^(.+?):\s*(.+)$/);
if (match) {
commands.push({
name: match[1].trim(),
description: match[2].trim()
});
}
} else if (typeof cmd === 'object') {
// Object format: {name: 'help', description: 'Show help'}
commands.push({
name: cmd.name || Object.keys(cmd)[0],
description: cmd.description || cmd[Object.keys(cmd)[0]]
});
}
});
} else if (typeof commandsData === 'object') {
// Object format: {help: 'Show help', task: 'Execute task'}
Object.entries(commandsData).forEach(([name, description]) => {
commands.push({
name: name.trim(),
description: typeof description === 'string' ? description.trim() : 'No description'
});
});
} else if (typeof commandsData === 'string') {
// String format: multiline text
const lines = commandsData.split('\n');
for (const line of lines) {
const match = line.match(/^\s*-?\s*(\w+):\s*(.+)/);
if (match) {
commands.push({
name: match[1],
description: match[2]
});
}
}
}
return commands;
}
async activateAgent(agentId, context = {}) {
const agent = this.agents.get(agentId);
if (!agent) {
// Try fuzzy matching
const matches = this.findAgentMatches(agentId);
if (matches.length === 1) {
return await this.activateAgent(matches[0].id, context);
} else if (matches.length > 1) {
throw new Error(`Multiple agents match '${agentId}': ${matches.map(a => a.name).join(', ')}`);
}
throw new Error(`Agent not found: ${agentId}`);
}
await agent.activate(context);
this.activeAgents.set(agentId, agent);
return agent;
}
findAgentMatches(query) {
const matches = [];
const queryLower = query.toLowerCase();
for (const agent of this.agents.values()) {
if (agent.id.includes(queryLower) ||
agent.name.toLowerCase().includes(queryLower) ||
agent.title.toLowerCase().includes(queryLower)) {
matches.push(agent);
}
}
return matches;
}
async deactivateAgent(agentId) {
const agent = this.activeAgents.get(agentId);
if (agent) {
agent.deactivate();
this.activeAgents.delete(agentId);
}
}
async listAgents() {
return Array.from(this.agents.values()).map(agent => ({
id: agent.id,
name: agent.name,
title: agent.title,
icon: agent.icon,
description: agent.persona?.role || 'No description available'
}));
}
getActiveAgent(agentId) {
return this.activeAgents.get(agentId);
}
// Advanced Elicitation Methods - 12+ Techniques
async performElicitation(content, method = 'auto', context = {}) {
const inquirer = require('inquirer');
// Auto-select best elicitation method based on content type and context
if (method === 'auto') {
method = this.selectElicitationMethod(content, context);
}
console.log(chalk.blue(`š§ Using ${method} elicitation method`));
switch (method) {
case 'tree-of-thoughts':
return await this.treeOfThoughtsElicitation(content, context);
case 'stakeholder-roundtable':
return await this.stakeholderRoundtableElicitation(content, context);
case 'progressive-disclosure':
return await this.progressiveDisclosureElicitation(content, context);
case 'comparative-analysis':
return await this.comparativeAnalysisElicitation(content, context);
case 'scenario-based':
return await this.scenarioBasedElicitation(content, context);
case 'constraint-exploration':
return await this.constraintExplorationElicitation(content, context);
case 'value-based':
return await this.valueBasedElicitation(content, context);
case 'risk-assessment':
return await this.riskAssessmentElicitation(content, context);
case 'user-journey':
return await this.userJourneyElicitation(content, context);
case 'technical-deep-dive':
return await this.technicalDeepDiveElicitation(content, context);
case 'business-model-canvas':
return await this.businessModelCanvasElicitation(content, context);
case 'impact-effort-matrix':
return await this.impactEffortMatrixElicitation(content, context);
default:
return await this.standardElicitation(content, context);
}
}
selectElicitationMethod(content, context) {
// Intelligent method selection based on content analysis
const contentLower = content.toLowerCase();
if (contentLower.includes('requirement') || contentLower.includes('specification')) {
return 'stakeholder-roundtable';
} else if (contentLower.includes('architecture') || contentLower.includes('technical')) {
return 'technical-deep-dive';
} else if (contentLower.includes('risk') || contentLower.includes('concern')) {
return 'risk-assessment';
} else if (contentLower.includes('business') || contentLower.includes('value')) {
return 'business-model-canvas';
} else if (contentLower.includes('user') || contentLower.includes('customer')) {
return 'user-journey';
} else if (context.complexity === 'high') {
return 'tree-of-thoughts';
} else {
return 'progressive-disclosure';
}
}
async treeOfThoughtsElicitation(content, context) {
const inquirer = require('inquirer');
console.log(chalk.yellow('\nš³ Tree of Thoughts Analysis'));
const branches = [
'1. Expand and elaborate on this concept',
'2. Consider alternative approaches',
'3. Identify potential challenges or risks',
'4. Explore implementation details',
'5. Consider stakeholder perspectives',
'6. Analyze dependencies and prerequisites',
'7. Evaluate success criteria and metrics',
'8. Consider long-term implications',
'9. Refine and finalize based on analysis'
];
const { choice } = await inquirer.prompt([{
type: 'list',
name: 'choice',
message: 'Which thought branch would you like to explore?',
choices: branches
}]);
return { method: 'tree-of-thoughts', choice, refinement: choice };
}
async stakeholderRoundtableElicitation(content, context) {
const inquirer = require('inquirer');
console.log(chalk.yellow('\nš„ Stakeholder Roundtable Discussion'));
const perspectives = [
'1. Business Owner: Focus on ROI and strategic value',
'2. End User: Emphasize usability and experience',
'3. Technical Team: Consider implementation feasibility',
'4. Quality Assurance: Focus on reliability and testing',
'5. Security Team: Emphasize compliance and protection',
'6. Operations: Consider maintenance and scalability',
'7. Product Manager: Balance features and timeline',
'8. Legal/Compliance: Address regulatory requirements',
'9. Synthesize all perspectives into final approach'
];
const { perspective } = await inquirer.prompt([{
type: 'list',
name: 'perspective',
message: 'Which stakeholder perspective should we consider?',
choices: perspectives
}]);
return { method: 'stakeholder-roundtable', perspective, refinement: perspective };
}
async progressiveDisclosureElicitation(content, context) {
const inquirer = require('inquirer');
console.log(chalk.yellow('\nš Progressive Disclosure Analysis'));
const levels = [
'1. High-level overview and key concepts',
'2. Main components and their relationships',
'3. Detailed implementation considerations',
'4. Edge cases and error handling',
'5. Performance and optimization aspects',
'6. Integration and dependency details',
'7. Testing and validation approaches',
'8. Documentation and knowledge transfer',
'9. Complete comprehensive refinement'
];
const { level } = await inquirer.prompt([{
type: 'list',
name: 'level',
message: 'What level of detail would you like to explore?',
choices: levels
}]);
return { method: 'progressive-disclosure', level, refinement: level };
}
async comparativeAnalysisElicitation(content, context) {
const inquirer = require('inquirer');
console.log(chalk.yellow('\nāļø Comparative Analysis'));
const comparisons = [
'1. Compare with industry best practices',
'2. Analyze alternative solutions and approaches',
'3. Compare current vs. proposed state',
'4. Evaluate different implementation options',
'5. Compare costs, benefits, and trade-offs',
'6. Analyze competitive landscape',
'7. Compare technical approaches and tools',
'8. Evaluate short-term vs. long-term impacts',
'9. Synthesize comparison results'
];
const { comparison } = await inquirer.prompt([{
type: 'list',
name: 'comparison',
message: 'What comparison would be most valuable?',
choices: comparisons
}]);
return { method: 'comparative-analysis', comparison, refinement: comparison };
}
async scenarioBasedElicitation(content, context) {
const inquirer = require('inquirer');
console.log(chalk.yellow('\nš Scenario-Based Analysis'));
const scenarios = [
'1. Best case scenario - everything goes perfectly',
'2. Worst case scenario - major challenges arise',
'3. Most likely scenario - realistic expectations',
'4. Resource-constrained scenario - limited budget/time',
'5. Rapid growth scenario - scaling challenges',
'6. Technology disruption scenario - major changes',
'7. Competitive pressure scenario - market forces',
'8. Regulatory change scenario - compliance shifts',
'9. Integrate scenario learnings into strategy'
];
const { scenario } = await inquirer.prompt([{
type: 'list',
name: 'scenario',
message: 'Which scenario should we explore?',
choices: scenarios
}]);
return { method: 'scenario-based', scenario, refinement: scenario };
}
async riskAssessmentElicitation(content, context) {
const inquirer = require('inquirer');
console.log(chalk.yellow('\nā ļø Risk Assessment Analysis'));
const riskAreas = [
'1. Technical risks - implementation challenges',
'2. Business risks - market and financial concerns',
'3. Operational risks - process and resource issues',
'4. Security risks - data and system vulnerabilities',
'5. Compliance risks - regulatory and legal concerns',
'6. Timeline risks - schedule and delivery challenges',
'7. Quality risks - performance and reliability issues',
'8. Change management risks - adoption challenges',
'9. Develop comprehensive risk mitigation plan'
];
const { riskArea } = await inquirer.prompt([{
type: 'list',
name: 'riskArea',
message: 'Which risk area needs assessment?',
choices: riskAreas
}]);
return { method: 'risk-assessment', riskArea, refinement: riskArea };
}
async standardElicitation(content, context) {
const inquirer = require('inquirer');
console.log(chalk.yellow('\nš” Interactive Refinement'));
const options = [
'1. Expand with more detail and examples',
'2. Simplify and focus on key points',
'3. Add practical implementation steps',
'4. Include success criteria and metrics',
'5. Consider potential challenges and solutions',
'6. Add stakeholder perspectives and requirements',
'7. Include timeline and resource considerations',
'8. Add quality assurance and validation steps',
'9. Finalize with comprehensive review'
];
const { option } = await inquirer.prompt([{
type: 'list',
name: 'option',
message: 'How would you like to refine this content?',
choices: options
}]);
return { method: 'standard', option, refinement: option };
}
// Enhanced Template Processing with Progressive Disclosure
async processTemplateWithElicitation(templateName, context = {}) {
console.log(chalk.blue(`š Processing template with advanced elicitation: ${templateName}`));
// Load template
const templatePath = path.join(this.orchestrator.dataCore, 'templates', `${templateName}.yaml`);
if (!await fs.pathExists(templatePath)) {
throw new Error(`Template not found: ${templateName}`);
}
const templateContent = await fs.readFile(templatePath, 'utf8');
const template = yaml.parse(templateContent);
// Progressive section processing
const sections = template.structure?.sections || [];
const processedContent = {};
for (const section of sections) {
console.log(chalk.green(`\nš Processing section: ${section.name}`));
// Use elicitation for each section
const elicitationResult = await this.performElicitation(
section.description || section.name,
section.elicitationMethod || 'auto',
{ ...context, section: section.name, complexity: section.complexity || 'medium' }
);
processedContent[section.name] = {
content: section.template || '',
elicitation: elicitationResult,
status: 'processed',
timestamp: new Date().toISOString()
};
// Progressive disclosure - ask if user wants to continue
if (sections.indexOf(section) < sections.length - 1) {
const inquirer = require('inquirer');
const { continue: shouldContinue } = await inquirer.prompt([{
type: 'confirm',
name: 'continue',
message: 'Continue to next section?',
default: true
}]);
if (!shouldContinue) {
console.log(chalk.yellow('Template processing paused. Progress saved.'));
break;
}
}
}
return {
template: templateName,
sections: processedContent,
status: 'completed',
agent: this.name,
timestamp: new Date().toISOString()
};
}
setDependencies(taskOrchestrator, templateEngine, documentManager) {
this.taskOrchestrator = taskOrchestrator;
this.templateEngine = templateEngine;
this.documentManager = documentManager;
}
}
module.exports = AgentOrchestrator;