UNPKG

shipdeck

Version:

Ship MVPs in 48 hours. Fix bugs in 30 seconds. The command deck for developers who ship.

456 lines (386 loc) • 13.6 kB
/** * DAG Workflow Engine Integration for Shipdeck Ultimate * Integrates the workflow engine with the existing Shipdeck infrastructure */ const { ShipdeckWorkflowEngine } = require('./workflow'); const path = require('path'); /** * Workflow Engine Factory * Creates and configures workflow engine instances for Shipdeck Ultimate */ class WorkflowEngineFactory { /** * Create a production-ready workflow engine */ static createProductionEngine(config = {}) { const defaultConfig = { // State management stateDir: path.join(process.cwd(), '.shipdeck', 'workflows'), autoSave: true, saveInterval: 30000, // 30 seconds // Execution limits maxConcurrentWorkflows: 5, defaultTimeout: 14400000, // 4 hours for complex workflows // Performance settings progressTracking: true, maxConcurrency: 8, // Allow high parallelization // Integration with existing Anthropic setup anthropic: { apiKey: process.env.ANTHROPIC_API_KEY, model: 'claude-3-sonnet-20240229', // Use existing token manager if available tokenManager: config.tokenManager, // Use existing config manager if available configManager: config.configManager } }; const finalConfig = { ...defaultConfig, ...config }; return new ShipdeckWorkflowEngine(finalConfig); } /** * Create a development/testing engine */ static createDevelopmentEngine(config = {}) { return this.createProductionEngine({ ...config, stateDir: path.join(process.cwd(), '.shipdeck', 'dev-workflows'), maxConcurrentWorkflows: 2, saveInterval: 10000, // More frequent saves for development anthropic: { ...config.anthropic, // Allow mock mode for development skipInit: config.mockMode || false } }); } /** * Create engine with Shipdeck integration */ static createIntegratedEngine(shipdeckInstance) { return this.createProductionEngine({ // Integrate with existing Shipdeck components anthropic: { apiKey: shipdeckInstance.anthropicClient?.apiKey, tokenManager: shipdeckInstance.tokenManager, configManager: shipdeckInstance.configManager }, // Use Shipdeck's state directory stateDir: path.join(shipdeckInstance.configDir || '.shipdeck', 'workflows'), // Match Shipdeck's performance settings maxConcurrentWorkflows: shipdeckInstance.maxConcurrency || 5 }); } } /** * Shipdeck Workflow Extension * Extends the main Shipdeck class with workflow capabilities */ class ShipdeckWorkflowExtension { constructor(shipdeckInstance) { this.shipdeck = shipdeckInstance; this.workflowEngine = WorkflowEngineFactory.createIntegratedEngine(shipdeckInstance); // Setup event forwarding this.setupIntegration(); } /** * Setup integration between Shipdeck and workflow engine */ setupIntegration() { // Forward workflow events to main Shipdeck instance this.workflowEngine.progressManager.on('workflow:started', (data) => { this.shipdeck.emit?.('workflow:started', data); }); this.workflowEngine.progressManager.on('workflow:completed', (data) => { this.shipdeck.emit?.('workflow:completed', data); }); this.workflowEngine.progressManager.on('progress:update', (data) => { this.shipdeck.emit?.('workflow:progress', data); }); // Add workflow methods to main Shipdeck instance this.extendShipdeckInstance(); } /** * Extend Shipdeck instance with workflow methods */ extendShipdeckInstance() { // Add workflow generation methods this.shipdeck.generateMVP = this.generateMVP.bind(this); this.shipdeck.createWorkflow = this.createWorkflow.bind(this); this.shipdeck.executeWorkflow = this.executeWorkflow.bind(this); this.shipdeck.getWorkflowStatus = this.getWorkflowStatus.bind(this); this.shipdeck.listWorkflows = this.listWorkflows.bind(this); this.shipdeck.getWorkflowMetrics = this.getWorkflowMetrics.bind(this); } /** * Generate complete MVP using workflow engine */ async generateMVP(projectConfig = {}) { console.log(`šŸš€ Starting 48-hour MVP generation: ${projectConfig.name || 'Unnamed Project'}`); const mvpConfig = { name: projectConfig.name || 'MVP Project', context: { projectName: projectConfig.name || 'MVP', techStack: projectConfig.stack || 'Next.js 14, TypeScript, Supabase', features: projectConfig.features || ['auth', 'dashboard'], ...projectConfig.context }, maxConcurrency: projectConfig.maxConcurrency || 5, ...projectConfig }; try { const result = await this.workflowEngine.generateMVP(mvpConfig); // Integrate with Shipdeck's result tracking if (this.shipdeck.trackResult) { this.shipdeck.trackResult('mvp-generation', result); } return result; } catch (error) { console.error('āŒ MVP Generation failed:', error.message); // Integrate with Shipdeck's error tracking if (this.shipdeck.trackError) { this.shipdeck.trackError('mvp-generation', error); } throw error; } } /** * Create workflow from template or custom config */ async createWorkflow(config) { if (typeof config === 'string') { // Template ID provided return await this.workflowEngine.createFromTemplate(config); } else if (config.template) { // Template with customization return await this.workflowEngine.createFromTemplate(config.template, config); } else { // Custom workflow return await this.workflowEngine.createCustomWorkflow(config); } } /** * Execute workflow with Shipdeck integration */ async executeWorkflow(workflowId, options = {}) { console.log(`⚔ Executing workflow: ${workflowId}`); try { const result = await this.workflowEngine.executeWorkflow(workflowId, options); // Track successful execution if (this.shipdeck.trackResult) { this.shipdeck.trackResult('workflow-execution', { workflowId, ...result }); } return result; } catch (error) { // Track failed execution if (this.shipdeck.trackError) { this.shipdeck.trackError('workflow-execution', error, { workflowId }); } throw error; } } /** * Get workflow status with enhanced information */ async getWorkflowStatus(workflowId) { const status = await this.workflowEngine.getWorkflowStatus(workflowId); // Enhance with Shipdeck-specific information if (status && this.shipdeck.enhanceStatus) { return this.shipdeck.enhanceStatus(status); } return status; } /** * List workflows with Shipdeck integration */ async listWorkflows() { const workflows = await this.workflowEngine.listWorkflows(); // Add Shipdeck-specific metadata if available if (this.shipdeck.enhanceWorkflowList) { return this.shipdeck.enhanceWorkflowList(workflows); } return workflows; } /** * Get comprehensive workflow metrics */ async getWorkflowMetrics() { const metrics = await this.workflowEngine.getMetrics(); // Add Shipdeck-specific metrics const enhancedMetrics = { ...metrics, integration: { shipdeckVersion: this.shipdeck.version || 'unknown', totalUsage: this.shipdeck.usage || {}, uptime: this.shipdeck.uptime || 0 } }; return enhancedMetrics; } /** * Cleanup workflows and shutdown */ async shutdown() { console.log('šŸ›‘ Shutting down workflow integration...'); try { // Cleanup old workflows await this.workflowEngine.cleanup(); // Shutdown workflow engine await this.workflowEngine.shutdown(); console.log('āœ… Workflow integration shutdown complete'); } catch (error) { console.error('āŒ Workflow shutdown error:', error.message); } } } /** * Workflow CLI Commands * Command-line interface for workflow operations */ class WorkflowCLI { constructor(workflowEngine) { this.engine = workflowEngine; } /** * Register CLI commands */ registerCommands(program) { // MVP generation command program .command('generate-mvp') .description('Generate a complete MVP in 48 hours') .option('-n, --name <name>', 'Project name') .option('-s, --stack <stack>', 'Technology stack') .option('-f, --features <features>', 'Comma-separated features') .option('-c, --concurrency <num>', 'Max concurrency', parseInt, 5) .action(async (options) => { try { const result = await this.engine.generateMVP({ name: options.name, stack: options.stack, features: options.features?.split(','), maxConcurrency: options.concurrency }); console.log('āœ… MVP Generation Complete!'); console.log(`Duration: ${result.mvpStats.hoursUsed} hours`); console.log(`Efficiency: ${result.mvpStats.efficiency}%`); } catch (error) { console.error('āŒ MVP Generation failed:', error.message); process.exit(1); } }); // Workflow execution command program .command('execute-workflow <workflow-id>') .description('Execute a specific workflow') .option('-c, --concurrency <num>', 'Max concurrency', parseInt) .option('-t, --timeout <ms>', 'Timeout in milliseconds', parseInt) .action(async (workflowId, options) => { try { const result = await this.engine.executeWorkflow(workflowId, { maxConcurrency: options.concurrency, timeout: options.timeout }); console.log(`āœ… Workflow ${workflowId} completed successfully`); console.log(`Nodes: ${result.nodes.completed}/${result.nodes.total}`); } catch (error) { console.error(`āŒ Workflow ${workflowId} failed:`, error.message); process.exit(1); } }); // List workflows command program .command('list-workflows') .description('List all workflows') .option('-s, --status <status>', 'Filter by status') .action(async (options) => { try { let workflows = await this.engine.listWorkflows(); if (options.status) { workflows = workflows.filter(w => w.status === options.status); } console.log(`\nšŸ“‹ Found ${workflows.length} workflows:\n`); workflows.forEach(workflow => { console.log(`${workflow.isActive ? '🟢' : '⚪'} ${workflow.id}`); console.log(` Name: ${workflow.name}`); console.log(` Status: ${workflow.status}`); console.log(` Nodes: ${workflow.completedCount}/${workflow.nodeCount}`); console.log(` Started: ${new Date(workflow.startedAt).toLocaleString()}`); console.log(''); }); } catch (error) { console.error('āŒ Failed to list workflows:', error.message); process.exit(1); } }); // Metrics command program .command('workflow-metrics') .description('Show workflow metrics and analytics') .action(async () => { try { const metrics = await this.engine.getMetrics(); console.log('\nšŸ“Š Workflow Metrics:\n'); console.log(`Total Workflows: ${metrics.executor.total}`); console.log(`Active: ${metrics.executor.active}`); console.log(`Completed: ${metrics.executor.completed}`); console.log(`Success Rate: ${metrics.executor.successRate.toFixed(1)}%`); console.log(`Avg Completion Time: ${(metrics.executor.averageCompletionTime / 1000 / 60).toFixed(1)} minutes`); console.log(`Available Templates: ${metrics.templates.available}`); } catch (error) { console.error('āŒ Failed to get metrics:', error.message); process.exit(1); } }); } } /** * Integration helper functions */ const WorkflowIntegrationHelpers = { /** * Initialize workflow engine for Shipdeck */ initializeForShipdeck(shipdeckInstance) { return new ShipdeckWorkflowExtension(shipdeckInstance); }, /** * Create standalone workflow engine */ createStandaloneEngine(config) { return WorkflowEngineFactory.createProductionEngine(config); }, /** * Setup CLI for workflow operations */ setupCLI(workflowEngine, program) { const cli = new WorkflowCLI(workflowEngine); cli.registerCommands(program); return cli; }, /** * Quick MVP generation function */ async quickMVP(projectName, features = ['auth', 'dashboard']) { const engine = WorkflowEngineFactory.createProductionEngine(); try { const result = await engine.generateMVP({ name: projectName, features }); await engine.shutdown(); return result; } catch (error) { await engine.shutdown(); throw error; } } }; module.exports = { WorkflowEngineFactory, ShipdeckWorkflowExtension, WorkflowCLI, WorkflowIntegrationHelpers };