// const express = require('express'); // const http = require('http'); // const socketIo = require('socket.io'); // const { Pool } = require('pg'); // const Redis = require('redis'); // const cors = require('cors'); // const axios = require('axios'); // const app = express(); // const server = http.createServer(app); // const io = socketIo(server, { // cors: { origin: "*", methods: ["GET", "POST", "PUT", "DELETE"] } // }); // // Database connections // const pgPool = new Pool({ // host: process.env.POSTGRES_HOST || 'pipeline_postgres', // port: process.env.POSTGRES_PORT || 5432, // database: process.env.POSTGRES_DB || 'dev_pipeline', // user: process.env.POSTGRES_USER || 'pipeline_admin', // password: process.env.POSTGRES_PASSWORD || 'secure_pipeline_2024', // max: 20, // idleTimeoutMillis: 30000, // connectionTimeoutMillis: 2000, // }); // const redisClient = Redis.createClient({ // socket: { // host: process.env.REDIS_HOST || 'pipeline_redis', // port: process.env.REDIS_PORT || 6379 // }, // password: process.env.REDIS_PASSWORD || 'redis_secure_2024' // }); // redisClient.on('error', (err) => console.log('Redis Client Error', err)); // // Services configuration // const SERVICES = { // 'api-gateway': { // port: 8000, // name: 'API Gateway', // container: 'pipeline_api_gateway', // url: 'http://pipeline_api_gateway:8000' // }, // 'requirement-processor': { // port: 8001, // name: 'Requirement Processor', // container: 'pipeline_requirement_processor', // url: 'http://pipeline_requirement_processor:8001' // }, // 'tech-stack-selector': { // port: 8002, // name: 'Tech Stack Selector', // container: 'pipeline_tech_stack_selector', // url: 'http://pipeline_tech_stack_selector:8002' // }, // 'architecture-designer': { // port: 8003, // name: 'Architecture Designer', // container: 'pipeline_architecture_designer', // url: 'http://pipeline_architecture_designer:8003' // }, // 'code-generator': { // port: 8004, // name: 'Code Generator', // container: 'pipeline_code_generator', // url: 'http://pipeline_code_generator:8004' // }, // 'test-generator': { // port: 8005, // name: 'Test Generator', // container: 'pipeline_test_generator', // url: 'http://pipeline_test_generator:8005' // }, // 'deployment-manager': { // port: 8006, // name: 'Deployment Manager', // container: 'pipeline_deployment_manager', // url: 'http://pipeline_deployment_manager:8006' // }, // 'self-improving-generator': { // port: 8007, // name: 'Self-Improving Generator', // container: 'pipeline_self_improving_generator', // url: 'http://pipeline_self_improving_generator:8007' // } // }; // // Middleware // app.use(cors()); // app.use(express.json({ limit: '50mb' })); // app.use(express.urlencoded({ extended: true, limit: '50mb' })); // // Database service - FIXED to work with your actual database structure // class DatabaseService { // static async getProjects(filters = {}) { // try { // console.log('🔍 Querying projects from database...'); // // Simple query for project_contexts table - NO JOINS // let query = ` // SELECT // id, // project_name, // technology_stack, // all_features, // completed_features, // pending_features, // project_path, // created_at, // updated_at // FROM project_contexts // `; // const conditions = []; // const values = []; // let paramCount = 0; // if (filters.project_name) { // conditions.push(`project_name ILIKE $${++paramCount}`); // values.push(`%${filters.project_name}%`); // } // if (conditions.length > 0) { // query += ` WHERE ${conditions.join(' AND ')}`; // } // query += ` ORDER BY created_at DESC LIMIT 20`; // console.log('🔍 Executing query:', query); // const result = await pgPool.query(query, values); // console.log('✅ Query result:', result.rows.length, 'projects found'); // // Get file counts for each project separately - SAFE QUERIES // for (let project of result.rows) { // try { // const fileCountResult = await pgPool.query( // 'SELECT COUNT(*) FROM code_files WHERE project_id = $1', // [project.id] // ); // project.file_count = parseInt(fileCountResult.rows[0].count); // } catch (fileError) { // console.log('⚠️ Could not get file count for project', project.id); // project.file_count = 0; // } // } // return result.rows; // } catch (error) { // console.error('❌ Database query error:', error.message); // throw error; // } // } // static async getSystemStats() { // try { // console.log('🔍 Getting system stats from database...'); // // Get counts from each table - SIMPLE QUERIES // const projectCountResult = await pgPool.query('SELECT COUNT(*) FROM project_contexts'); // const fileCountResult = await pgPool.query('SELECT COUNT(*) FROM code_files'); // const improvementCountResult = await pgPool.query('SELECT COUNT(*) FROM improvement_history'); // // Get recent projects (last 24 hours) // const recentResult = await pgPool.query(` // SELECT COUNT(*) FROM project_contexts // WHERE created_at > NOW() - INTERVAL '24 hours' // `); // const stats = { // project_contexts: parseInt(projectCountResult.rows[0].count), // code_files: parseInt(fileCountResult.rows[0].count), // improvement_history: parseInt(improvementCountResult.rows[0].count), // recent_projects: parseInt(recentResult.rows[0].count) // }; // console.log('📊 System stats:', stats); // return stats; // } catch (error) { // console.error('❌ System stats error:', error); // return { // project_contexts: 0, // code_files: 0, // improvement_history: 0, // recent_projects: 0 // }; // } // } // } // // WebSocket connection handling // io.on('connection', (socket) => { // console.log(`Dashboard client connected: ${socket.id}`); // socket.emit('connected', { // message: 'Connected to AI Pipeline Dashboard', // timestamp: new Date().toISOString() // }); // socket.on('disconnect', () => { // console.log(`Dashboard client disconnected: ${socket.id}`); // }); // }); // // API Routes // app.get('/api/health', (req, res) => { // res.json({ // status: 'healthy', // timestamp: new Date().toISOString(), // service: 'AI Pipeline Dashboard', // version: '2.0.0' // }); // }); // // Debug endpoint // app.get('/api/debug/database', async (req, res) => { // try { // console.log('🔍 Database debug endpoint called'); // const connectionTest = await pgPool.query('SELECT NOW()'); // console.log('✅ Database connection successful'); // const projectCount = await pgPool.query('SELECT COUNT(*) FROM project_contexts'); // const fileCount = await pgPool.query('SELECT COUNT(*) FROM code_files'); // const improvementCount = await pgPool.query('SELECT COUNT(*) FROM improvement_history'); // // Get sample project names // let sampleProjects = []; // const sampleResult = await pgPool.query('SELECT id, project_name, created_at FROM project_contexts ORDER BY created_at DESC LIMIT 3'); // sampleProjects = sampleResult.rows; // res.json({ // connection: 'OK', // timestamp: connectionTest.rows[0].now, // tables: { // project_contexts: parseInt(projectCount.rows[0].count), // code_files: parseInt(fileCount.rows[0].count), // improvement_history: parseInt(improvementCount.rows[0].count) // }, // sampleProjects: sampleProjects // }); // } catch (error) { // console.error('❌ Database debug error:', error); // res.status(500).json({ // error: error.message, // connection: 'FAILED' // }); // } // }); // // System status with real data // app.get('/api/system/status', async (req, res) => { // try { // console.log('🔍 System status endpoint called'); // let healthyServices = 0; // const serviceChecks = []; // // Check services // for (const [key, service] of Object.entries(SERVICES)) { // try { // await axios.get(`${service.url}/health`, { timeout: 5000 }); // healthyServices++; // serviceChecks.push({ service: key, status: 'healthy' }); // } catch (error) { // serviceChecks.push({ service: key, status: 'unhealthy', error: error.message }); // } // } // // Get database stats // const dbStats = await DatabaseService.getSystemStats(); // res.json({ // healthyServices, // totalServices: Object.keys(SERVICES).length, // totalProjects: dbStats.project_contexts, // totalFiles: dbStats.code_files, // activeProjects: dbStats.recent_projects, // improvements: dbStats.improvement_history, // serviceChecks, // timestamp: new Date().toISOString() // }); // } catch (error) { // console.error('❌ System status error:', error); // res.status(500).json({ error: error.message }); // } // }); // // Projects endpoint // app.get('/api/projects', async (req, res) => { // try { // console.log('🔍 Projects endpoint called'); // const projects = await DatabaseService.getProjects(req.query); // console.log('✅ Projects returned:', projects.length); // res.json({ projects }); // } catch (error) { // console.error('❌ Projects endpoint error:', error); // res.status(500).json({ // error: error.message, // details: 'Check server logs for database connection issues' // }); // } // }); // // Services health endpoint // app.get('/api/services/health', async (req, res) => { // console.log('🔍 Services health check called'); // const healthChecks = await Promise.allSettled( // Object.entries(SERVICES).map(async ([key, service]) => { // const startTime = Date.now(); // try { // await axios.get(`${service.url}/health`, { timeout: 5000 }); // return { // name: service.name, // status: 'healthy', // port: service.port, // container: service.container, // responseTime: Date.now() - startTime, // lastCheck: new Date().toISOString() // }; // } catch (error) { // return { // name: service.name, // status: 'unhealthy', // port: service.port, // container: service.container, // responseTime: Date.now() - startTime, // error: error.message, // lastCheck: new Date().toISOString() // }; // } // }) // ); // const services = healthChecks.map(result => // result.status === 'fulfilled' ? result.value : result.reason // ); // res.json({ services }); // }); // // Code Editor API endpoints // app.get('/api/projects/:projectId/files', async (req, res) => { // try { // const projectId = req.params.projectId; // console.log('🔍 Getting files for project:', projectId); // const result = await pgPool.query( // 'SELECT id, file_name, file_path, file_type, created_at FROM code_files WHERE project_id = $1 ORDER BY file_path', // [projectId] // ); // res.json({ files: result.rows }); // } catch (error) { // console.error('❌ Error getting project files:', error); // res.status(500).json({ error: error.message }); // } // }); // app.get('/api/files/:fileId/content', async (req, res) => { // try { // const fileId = req.params.fileId; // console.log('🔍 Getting content for file:', fileId); // const result = await pgPool.query( // 'SELECT file_content, file_name, file_type FROM code_files WHERE id = $1', // [fileId] // ); // if (result.rows.length === 0) { // return res.status(404).json({ error: 'File not found' }); // } // res.json({ // content: result.rows[0].file_content, // fileName: result.rows[0].file_name, // fileType: result.rows[0].file_type // }); // } catch (error) { // console.error('❌ Error getting file content:', error); // res.status(500).json({ error: error.message }); // } // }); // app.put('/api/files/:fileId/content', async (req, res) => { // try { // const fileId = req.params.fileId; // const { content } = req.body; // console.log('🔍 Updating content for file:', fileId); // await pgPool.query( // 'UPDATE code_files SET file_content = $1, updated_at = NOW() WHERE id = $2', // [content, fileId] // ); // res.json({ success: true }); // } catch (error) { // console.error('❌ Error updating file content:', error); // res.status(500).json({ error: error.message }); // } // }); // // Main dashboard page // app.get('/', (req, res) => { // res.send(` // // // // AI Pipeline Dashboard // // // // // //
// //
//
//
//
// // // // `); // }); // // Initialize connections and start server // async function startServer() { // try { // await pgPool.query('SELECT NOW()'); // console.log('✅ Connected to PostgreSQL database (dev_pipeline)'); // await redisClient.connect(); // await redisClient.ping(); // console.log('✅ Connected to Redis cache'); // const PORT = process.env.PORT || 8008; // server.listen(PORT, '0.0.0.0', () => { // console.log(`🚀 AI Pipeline Dashboard running on port ${PORT}`); // console.log(`📊 Dashboard URL: http://localhost:${PORT}`); // console.log(`🔗 Integrated with existing database: dev_pipeline`); // console.log(`📁 Monitoring projects: ${Object.keys(SERVICES).length} services`); // }); // } catch (error) { // console.error('❌ Failed to start dashboard:', error); // process.exit(1); // } // } // startServer(); const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const { Pool } = require('pg'); const Redis = require('redis'); const cors = require('cors'); const axios = require('axios'); const { exec } = require('child_process'); const util = require('util'); const execPromise = util.promisify(exec); const app = express(); const server = http.createServer(app); const io = socketIo(server, { cors: { origin: "*", methods: ["GET", "POST", "PUT", "DELETE"] } }); // Database connections const pgPool = new Pool({ host: process.env.POSTGRES_HOST || 'pipeline_postgres', port: process.env.POSTGRES_PORT || 5432, database: process.env.POSTGRES_DB || 'dev_pipeline', user: process.env.POSTGRES_USER || 'pipeline_admin', password: process.env.POSTGRES_PASSWORD || 'secure_pipeline_2024', max: 20, idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000, }); const redisClient = Redis.createClient({ socket: { host: process.env.REDIS_HOST || 'pipeline_redis', port: process.env.REDIS_PORT || 6379 }, password: process.env.REDIS_PASSWORD || 'redis_secure_2024' }); redisClient.on('error', (err) => console.log('Redis Client Error', err)); // Services configuration const SERVICES = { 'api-gateway': { port: 8000, name: 'API Gateway', container: 'pipeline_api_gateway', url: 'http://pipeline_api_gateway:8000' }, 'requirement-processor': { port: 8001, name: 'Requirement Processor', container: 'pipeline_requirement_processor', url: 'http://pipeline_requirement_processor:8001' }, 'tech-stack-selector': { port: 8002, name: 'Tech Stack Selector', container: 'pipeline_tech_stack_selector', url: 'http://pipeline_tech_stack_selector:8002' }, 'architecture-designer': { port: 8003, name: 'Architecture Designer', container: 'pipeline_architecture_designer', url: 'http://pipeline_architecture_designer:8003' }, 'code-generator': { port: 8004, name: 'Code Generator', container: 'pipeline_code_generator', url: 'http://pipeline_code_generator:8004' }, 'test-generator': { port: 8005, name: 'Test Generator', container: 'pipeline_test_generator', url: 'http://pipeline_test_generator:8005' }, 'deployment-manager': { port: 8006, name: 'Deployment Manager', container: 'pipeline_deployment_manager', url: 'http://pipeline_deployment_manager:8006' }, 'self-improving-generator': { port: 8007, name: 'Self-Improving Generator', container: 'pipeline_self_improving_generator', url: 'http://pipeline_self_improving_generator:8007' } }; // Middleware app.use(cors()); app.use(express.json({ limit: '50mb' })); app.use(express.urlencoded({ extended: true, limit: '50mb' })); // Database service - FIXED to work with your actual database structure class DatabaseService { static async getProjects(filters = {}) { try { console.log('🔍 Querying projects from database...'); // Simple query for project_contexts table - NO JOINS let query = ` SELECT id, project_name, technology_stack, all_features, completed_features, pending_features, project_path, created_at, updated_at FROM project_contexts `; const conditions = []; const values = []; let paramCount = 0; if (filters.project_name) { conditions.push(`project_name ILIKE $${++paramCount}`); values.push(`%${filters.project_name}%`); } if (conditions.length > 0) { query += ` WHERE ${conditions.join(' AND ')}`; } query += ` ORDER BY created_at DESC LIMIT 20`; console.log('🔍 Executing query:', query); const result = await pgPool.query(query, values); console.log('✅ Query result:', result.rows.length, 'projects found'); // Get file counts for each project separately - SAFE QUERIES for (let project of result.rows) { try { const fileCountResult = await pgPool.query( 'SELECT COUNT(*) FROM code_files WHERE project_id = $1', [project.id] ); project.file_count = parseInt(fileCountResult.rows[0].count); } catch (fileError) { console.log('⚠️ Could not get file count for project', project.id); project.file_count = 0; } } return result.rows; } catch (error) { console.error('❌ Database query error:', error.message); throw error; } } static async getSystemStats() { try { console.log('🔍 Getting system stats from database...'); // Get counts from each table - SIMPLE QUERIES const projectCountResult = await pgPool.query('SELECT COUNT(*) FROM project_contexts'); const fileCountResult = await pgPool.query('SELECT COUNT(*) FROM code_files'); const improvementCountResult = await pgPool.query('SELECT COUNT(*) FROM improvement_history'); // Get recent projects (last 24 hours) const recentResult = await pgPool.query(` SELECT COUNT(*) FROM project_contexts WHERE created_at > NOW() - INTERVAL '24 hours' `); const stats = { project_contexts: parseInt(projectCountResult.rows[0].count), code_files: parseInt(fileCountResult.rows[0].count), improvement_history: parseInt(improvementCountResult.rows[0].count), recent_projects: parseInt(recentResult.rows[0].count) }; console.log('📊 System stats:', stats); return stats; } catch (error) { console.error('❌ System stats error:', error); return { project_contexts: 0, code_files: 0, improvement_history: 0, recent_projects: 0 }; } } } // WebSocket connection handling io.on('connection', (socket) => { console.log(`Dashboard client connected: ${socket.id}`); socket.emit('connected', { message: 'Connected to AI Pipeline Dashboard', timestamp: new Date().toISOString() }); socket.on('disconnect', () => { console.log(`Dashboard client disconnected: ${socket.id}`); }); }); // API Routes app.get('/api/health', (req, res) => { res.json({ status: 'healthy', timestamp: new Date().toISOString(), service: 'AI Pipeline Dashboard', version: '2.0.0' }); }); // Debug endpoint app.get('/api/debug/database', async (req, res) => { try { console.log('🔍 Database debug endpoint called'); const connectionTest = await pgPool.query('SELECT NOW()'); console.log('✅ Database connection successful'); const projectCount = await pgPool.query('SELECT COUNT(*) FROM project_contexts'); const fileCount = await pgPool.query('SELECT COUNT(*) FROM code_files'); const improvementCount = await pgPool.query('SELECT COUNT(*) FROM improvement_history'); // Get sample project names let sampleProjects = []; const sampleResult = await pgPool.query('SELECT id, project_name, created_at FROM project_contexts ORDER BY created_at DESC LIMIT 3'); sampleProjects = sampleResult.rows; res.json({ connection: 'OK', timestamp: connectionTest.rows[0].now, tables: { project_contexts: parseInt(projectCount.rows[0].count), code_files: parseInt(fileCount.rows[0].count), improvement_history: parseInt(improvementCount.rows[0].count) }, sampleProjects: sampleProjects }); } catch (error) { console.error('❌ Database debug error:', error); res.status(500).json({ error: error.message, connection: 'FAILED' }); } }); // System status with real data app.get('/api/system/status', async (req, res) => { try { console.log('🔍 System status endpoint called'); let healthyServices = 0; const serviceChecks = []; // Check services for (const [key, service] of Object.entries(SERVICES)) { try { await axios.get(`${service.url}/health`, { timeout: 5000 }); healthyServices++; serviceChecks.push({ service: key, status: 'healthy' }); } catch (error) { serviceChecks.push({ service: key, status: 'unhealthy', error: error.message }); } } // Get database stats const dbStats = await DatabaseService.getSystemStats(); res.json({ healthyServices, totalServices: Object.keys(SERVICES).length, totalProjects: dbStats.project_contexts, totalFiles: dbStats.code_files, activeProjects: dbStats.recent_projects, improvements: dbStats.improvement_history, serviceChecks, timestamp: new Date().toISOString() }); } catch (error) { console.error('❌ System status error:', error); res.status(500).json({ error: error.message }); } }); // Projects endpoint app.get('/api/projects', async (req, res) => { try { console.log('🔍 Projects endpoint called'); const projects = await DatabaseService.getProjects(req.query); console.log('✅ Projects returned:', projects.length); res.json({ projects }); } catch (error) { console.error('❌ Projects endpoint error:', error); res.status(500).json({ error: error.message, details: 'Check server logs for database connection issues' }); } }); // Services health endpoint app.get('/api/services/health', async (req, res) => { console.log('🔍 Services health check called'); const healthChecks = await Promise.allSettled( Object.entries(SERVICES).map(async ([key, service]) => { const startTime = Date.now(); try { await axios.get(`${service.url}/health`, { timeout: 5000 }); return { name: service.name, status: 'healthy', port: service.port, container: service.container, responseTime: Date.now() - startTime, lastCheck: new Date().toISOString() }; } catch (error) { return { name: service.name, status: 'unhealthy', port: service.port, container: service.container, responseTime: Date.now() - startTime, error: error.message, lastCheck: new Date().toISOString() }; } }) ); const services = healthChecks.map(result => result.status === 'fulfilled' ? result.value : result.reason ); res.json({ services }); }); // Code Editor API endpoints - FIXED to handle missing files gracefully app.get('/api/projects/:projectId/files', async (req, res) => { try { const projectId = req.params.projectId; console.log('🔍 Getting files for project:', projectId); const result = await pgPool.query( 'SELECT id, file_path, file_type, created_at FROM code_files WHERE project_id = $1 ORDER BY file_path', [projectId] ); res.json({ files: result.rows }); } catch (error) { console.error('❌ Error getting project files:', error); res.status(500).json({ error: error.message }); } }); // Helper function to try reading file from different containers async function tryReadFileFromContainers(filePath, projectId) { const containers = ['pipeline_code_generator', 'pipeline_self_improving_generator']; const possiblePaths = [ `/tmp/generated-projects/${projectId}/${filePath}`, `/tmp/projects/${projectId}/${filePath}`, `/app/projects/${projectId}/${filePath}`, `/tmp/${filePath}`, `/app/${filePath}` ]; for (const container of containers) { for (const path of possiblePaths) { try { const { stdout } = await execPromise(`docker exec ${container} cat "${path}" 2>/dev/null`); if (stdout) { console.log(`✅ Found file in ${container} at ${path}`); return stdout; } } catch (error) { // Continue trying other paths } } } return null; } app.get('/api/files/:fileId/content', async (req, res) => { try { const fileId = req.params.fileId; console.log('🔍 Getting content for file:', fileId); // Get file info from database const result = await pgPool.query( 'SELECT file_path, file_type, project_id FROM code_files WHERE id = $1', [fileId] ); if (result.rows.length === 0) { return res.status(404).json({ error: 'File not found' }); } const file = result.rows[0]; const fileName = file.file_path.split('/').pop() || file.file_path; // Try to read file from containers let content = await tryReadFileFromContainers(file.file_path, file.project_id); if (!content) { // Generate sample content based on file type content = generateSampleContent(file.file_path, file.file_type); } res.json({ content: content, fileName: fileName, fileType: file.file_type }); } catch (error) { console.error('❌ Error getting file content:', error); res.status(500).json({ error: error.message }); } }); // Generate sample content when files are not found function generateSampleContent(filePath, fileType) { const fileName = filePath.split('/').pop(); const ext = fileName.split('.').pop(); switch (ext) { case 'tsx': case 'jsx': return `// ${fileName} // This file was generated but the content is no longer available on disk // The file structure and metadata are preserved in the database import React from 'react'; const ${fileName.split('.')[0]} = () => { return (

Generated Component: ${fileName}

Original file path: ${filePath}

File type: ${fileType}

Note: This is placeholder content. The original generated code is not available.

); }; export default ${fileName.split('.')[0]};`; case 'ts': case 'js': return `// ${fileName} // This file was generated but the content is no longer available on disk // The file structure and metadata are preserved in the database /** * Original file path: ${filePath} * File type: ${fileType} * Note: This is placeholder content. The original generated code is not available. */ export default function ${fileName.split('.')[0]}() { console.log('Generated file: ${fileName}'); // Original implementation would be here return { message: 'This file was generated but content is not available', path: '${filePath}', type: '${fileType}' }; }`; case 'py': return `# ${fileName} # This file was generated but the content is no longer available on disk # The file structure and metadata are preserved in the database """ Original file path: ${filePath} File type: ${fileType} Note: This is placeholder content. The original generated code is not available. """ def main(): print("Generated file: ${fileName}") print("Original path: ${filePath}") print("File type: ${fileType}") # Original implementation would be here pass if __name__ == "__main__": main()`; case 'html': return ` ${fileName}

Generated File: ${fileName}

Original file path: ${filePath}

File type: ${fileType}

Note: This is placeholder content. The original generated code is not available.

`; case 'css': return `/* ${fileName} */ /* This file was generated but the content is no longer available on disk */ /* The file structure and metadata are preserved in the database */ /* Original file path: ${filePath} File type: ${fileType} Note: This is placeholder content. The original generated code is not available. */ body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; } .container { max-width: 800px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } /* Original styles would be here */`; default: return `// ${fileName} // This file was generated but the content is no longer available on disk // The file structure and metadata are preserved in the database /* Original file path: ${filePath} File type: ${fileType} Note: This is placeholder content. The original generated code is not available. To fix this issue, you need to: 1. Ensure generated files are stored in a persistent volume 2. Mount the volume between the code generator and dashboard containers 3. Or implement a file storage service to persist generated code */`; } } app.put('/api/files/:fileId/content', async (req, res) => { try { const fileId = req.params.fileId; const { content } = req.body; console.log('🔍 Updating content for file:', fileId); // For now, just return success since files aren't persisted // In a real implementation, you'd save the content to a persistent storage console.log('⚠️ File content updated in memory only (not persisted)'); res.json({ success: true, message: 'Content updated (note: changes are not persisted to disk)' }); } catch (error) { console.error('❌ Error updating file content:', error); res.status(500).json({ error: error.message }); } }); // Main dashboard page app.get('/', (req, res) => { res.send(` AI Pipeline Dashboard
`); }); // Initialize connections and start server async function startServer() { try { await pgPool.query('SELECT NOW()'); console.log('✅ Connected to PostgreSQL database (dev_pipeline)'); await redisClient.connect(); await redisClient.ping(); console.log('✅ Connected to Redis cache'); const PORT = process.env.PORT || 8008; server.listen(PORT, '0.0.0.0', () => { console.log(`🚀 AI Pipeline Dashboard running on port ${PORT}`); console.log(`📊 Dashboard URL: http://localhost:${PORT}`); console.log(`🔗 Integrated with existing database: dev_pipeline`); console.log(`📁 Monitoring projects: ${Object.keys(SERVICES).length} services`); }); } catch (error) { console.error('❌ Failed to start dashboard:', error); process.exit(1); } } startServer();