Skip to main content
Glama
orchestrator.js16.5 kB
// Production Orchestrator - Coordinates all agents in the production pipeline import { agentRegistry } from './agent-registry.js'; import { ReviewBoard } from './review-board.js'; import { DocControl } from './doc-control.js'; export class ProductionOrchestrator { constructor() { this.reviewBoard = new ReviewBoard(); this.docControl = new DocControl(); this.activeWorkflows = new Map(); this.taskQueue = []; } async initialize() { await agentRegistry.initialize(); await this.reviewBoard.initialize(); await this.docControl.initialize(); console.log('🎭 Production Orchestrator initialized'); } // Main entry point for automated production async runProductionWorkflow(workflowSpec) { console.log('🚀 Starting automated production workflow:', workflowSpec.name); try { // Create workflow in database const workflow = await this.createWorkflow(workflowSpec); // Plan production steps const productionPlan = await this.planProduction(workflow, workflowSpec); // Execute production pipeline with agent oversight const results = await this.executeProductionPlan(workflow, productionPlan); // Final quality assurance const finalApproval = await this.reviewBoard.finalReview(workflow, results); if (finalApproval.approved) { await this.completeWorkflow(workflow, results); console.log('✅ Production workflow completed successfully'); return { success: true, workflow: workflow, results: results, finalApproval: finalApproval }; } else { console.log('❌ Production workflow failed final review'); return { success: false, workflow: workflow, errors: finalApproval.issues }; } } catch (error) { console.error('❌ Production workflow failed:', error); return { success: false, error: error.message }; } } async createWorkflow(spec) { const { Pool } = await import('pg'); const pool = new Pool({ connectionString: process.env.DATABASE_URL }); try { const orchestratorAgent = agentRegistry.getAgent('orchestrator'); const query = ` INSERT INTO workflows (name, description, storyline_id, created_by, metadata) VALUES ($1, $2, $3, $4, $5) RETURNING * `; const result = await pool.query(query, [ spec.name, spec.description, spec.storylineId || null, orchestratorAgent.id, JSON.stringify(spec) ]); const workflow = result.rows[0]; this.activeWorkflows.set(workflow.id, workflow); console.log(`📋 Created workflow "${spec.name}" with ID ${workflow.id}`); return workflow; } finally { await pool.end(); } } // Use GPT-5 to analyze requirements and plan production steps async planProduction(workflow, spec) { const orchestrator = agentRegistry.getAgent('orchestrator'); const planningPrompt = ` You are the Production Orchestrator for an automated puppet production studio. Plan the complete production pipeline for this project: Project Details: - Name: ${spec.name} - Description: ${spec.description} - Character: ${spec.characterName || 'To be created'} - Type: ${spec.type || 'Full production'} - Duration Target: ${spec.durationTarget || '30-60 seconds'} - Style: ${spec.style || 'Puppet animation'} Available Production Tools: 1. process_character_image - Create puppet character from image 2. generate_production_script - AI-generated script with dialogue 3. breakdown_script_to_scenes - Scene-by-scene breakdown 4. generate_scene_images - Create visual assets for each scene 5. generate_scene_audio - ElevenLabs voice synthesis 6. create_video_production_manifest - Final assembly instructions Create a detailed production plan with: 1. Step-by-step task sequence 2. Dependencies between tasks 3. Quality control checkpoints 4. Resource requirements 5. Timeline estimates Return a JSON production plan. `; const response = await agentRegistry.callAgent('orchestrator', planningPrompt, { systemPrompt: 'You are an expert production planner. Always respond with valid JSON.', jsonMode: true, maxTokens: 4096 }); if (!response.success) { throw new Error(`Production planning failed: ${response.error}`); } const plan = JSON.parse(response.response); // Store plan in workflow metadata await this.updateWorkflowMetadata(workflow.id, { productionPlan: plan }); console.log('📋 Production plan created:', plan.steps?.length || 0, 'steps'); return plan; } // Execute production plan with agent coordination async executeProductionPlan(workflow, plan) { const results = { completedTasks: [], artifacts: [], approvals: [], errors: [] }; for (const step of plan.steps) { console.log(`\n🎬 Executing step: ${step.name}`); try { // Create task in database const task = await this.createTask(workflow.id, step); // Execute with agent coordination const stepResult = await this.executeStepWithAgents(task, step); if (stepResult.success) { results.completedTasks.push(stepResult); if (stepResult.artifacts) { results.artifacts.push(...stepResult.artifacts); } console.log(`✅ Step "${step.name}" completed successfully`); } else { results.errors.push({ step: step.name, error: stepResult.error }); // Handle failure based on step criticality if (step.critical !== false) { throw new Error(`Critical step failed: ${step.name} - ${stepResult.error}`); } else { console.log(`⚠️ Non-critical step failed: ${step.name} - ${stepResult.error}`); } } } catch (error) { console.error(`❌ Step "${step.name}" failed:`, error); results.errors.push({ step: step.name, error: error.message }); if (step.critical !== false) { throw error; // Stop execution for critical steps } } } return results; } // Execute individual step with propose→critique→revise→approve workflow async executeStepWithAgents(task, step) { console.log(`🤖 Starting agent coordination for: ${step.name}`); let iteration = 0; const maxIterations = step.maxIterations || 3; while (iteration < maxIterations) { iteration++; console.log(` 🔄 Iteration ${iteration}/${maxIterations}`); try { // 1. Automation Engineer executes the step const automationResult = await this.executeAutomationStep(task, step); if (!automationResult.success) { return automationResult; } // 2. Creative Director reviews const creativeReview = await this.reviewBoard.creativeReview( task, automationResult.artifact, step.requirements ); // 3. Brand Guardian checks compliance const brandReview = await this.reviewBoard.brandReview( task, automationResult.artifact, creativeReview ); // 4. QA Auditor performs technical checks const qaReview = await this.reviewBoard.qaReview( task, automationResult.artifact, step.qualityChecks ); // 5. Check if all reviews passed if (creativeReview.approved && brandReview.approved && qaReview.approved) { // Success! Document and return await this.docControl.recordApproval(task, { creative: creativeReview, brand: brandReview, qa: qaReview }); console.log(` ✅ Step approved after ${iteration} iterations`); return { success: true, task: task, artifact: automationResult.artifact, approvals: { creative: creativeReview, brand: brandReview, qa: qaReview }, iterations: iteration }; } // Collect feedback for next iteration const combinedFeedback = this.combineFeedback([ creativeReview, brandReview, qaReview ]); console.log(` 🔄 Revision needed:`, combinedFeedback.issues.length, 'issues'); // Update step with feedback for next iteration step.feedback = combinedFeedback; } catch (error) { console.error(` ❌ Iteration ${iteration} failed:`, error); if (iteration >= maxIterations) { return { success: false, error: `Failed after ${maxIterations} iterations: ${error.message}`, task: task }; } } } return { success: false, error: `Exceeded maximum iterations (${maxIterations})`, task: task }; } async executeAutomationStep(task, step) { // This will call the existing MCP production tools const automationAgent = agentRegistry.getAgent('automation_engineer'); console.log(` 🔧 Automation Engineer executing: ${step.tool}`); try { // Map to existing production tools const toolMapping = { 'process_character_image': 'process_character_image', 'generate_script': 'generate_production_script', 'breakdown_scenes': 'breakdown_script_to_scenes', 'generate_images': 'generate_scene_images', 'generate_audio': 'generate_scene_audio', 'create_manifest': 'create_video_production_manifest' }; const mcpTool = toolMapping[step.tool]; if (!mcpTool) { throw new Error(`Unknown tool: ${step.tool}`); } // Execute the MCP tool with the step parameters const result = await this.executeMCPTool(mcpTool, step.parameters); if (result.success) { // Create artifact record const artifact = await this.docControl.createArtifact( task.id, step.outputType || 'mixed', result ); return { success: true, result: result, artifact: artifact }; } else { return { success: false, error: result.message || result.error || 'Tool execution failed' }; } } catch (error) { return { success: false, error: error.message }; } } // This will be the bridge to existing MCP tools async executeMCPTool(toolName, parameters) { // Import the existing tool handlers const { getCharacterToolHandlers } = await import('../tools/character-tools.js'); const handlers = getCharacterToolHandlers(); const handler = handlers[toolName]; if (!handler) { throw new Error(`MCP tool handler not found: ${toolName}`); } try { const result = await handler(parameters); return result; } catch (error) { throw new Error(`MCP tool execution failed: ${error.message}`); } } combineFeedback(reviews) { const allIssues = []; const suggestions = []; for (const review of reviews) { if (!review.approved) { allIssues.push(...(review.issues || [])); suggestions.push(...(review.suggestions || [])); } } return { issues: allIssues, suggestions: suggestions, summary: `${allIssues.length} issues found across ${reviews.length} review stages` }; } async createTask(workflowId, step) { const { Pool } = await import('pg'); const pool = new Pool({ connectionString: process.env.DATABASE_URL }); try { const query = ` INSERT INTO tasks (workflow_id, step, tool, payload, status) VALUES ($1, $2, $3, $4, 'pending') RETURNING * `; const result = await pool.query(query, [ workflowId, step.name, step.tool, JSON.stringify(step.parameters || {}) ]); return result.rows[0]; } finally { await pool.end(); } } async updateWorkflowMetadata(workflowId, metadata) { const { Pool } = await import('pg'); const pool = new Pool({ connectionString: process.env.DATABASE_URL }); try { const query = ` UPDATE workflows SET metadata = metadata || $1::jsonb, updated_at = CURRENT_TIMESTAMP WHERE id = $2 `; await pool.query(query, [JSON.stringify(metadata), workflowId]); } finally { await pool.end(); } } async completeWorkflow(workflow, results) { const { Pool } = await import('pg'); const pool = new Pool({ connectionString: process.env.DATABASE_URL }); try { const query = ` UPDATE workflows SET status = 'completed', completed_at = CURRENT_TIMESTAMP, metadata = metadata || $1::jsonb WHERE id = $2 `; await pool.query(query, [JSON.stringify({ results: results }), workflow.id]); this.activeWorkflows.delete(workflow.id); } finally { await pool.end(); } } } // Singleton instance export const productionOrchestrator = new ProductionOrchestrator();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bermingham85/mcp-puppet-pipeline'

If you have feedback or need assistance with the MCP directory API, please join our Discord server