const express = require('express'); const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const app = express(); const PORT = 3000; // 中间件 app.use(express.json()); app.use(express.static('public')); // 数据库连接 const db = new sqlite3.Database('./tasks.db', (err) => { if (err) { console.error('❌ 数据库连接失败:', err.message); process.exit(1); } console.log('✅ 已连接到 SQLite 数据库'); }); // 初始化数据库表 db.serialize(() => { // 项目表 db.run(`CREATE TABLE IF NOT EXISTS projects ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, description TEXT, status TEXT DEFAULT 'active', created_by TEXT DEFAULT 'human', created_at DATETIME DEFAULT CURRENT_TIMESTAMP )`); // 任务表 db.run(`CREATE TABLE IF NOT EXISTS tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, project_id INTEGER NOT NULL, parent_id INTEGER, title TEXT NOT NULL, description TEXT, type TEXT DEFAULT 'development', priority TEXT DEFAULT 'normal', status TEXT DEFAULT 'initial', assigned_to TEXT, created_by TEXT DEFAULT 'human', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (project_id) REFERENCES projects(id), FOREIGN KEY (parent_id) REFERENCES tasks(id) )`); // 智能体表 db.run(`CREATE TABLE IF NOT EXISTS agents ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, type TEXT, capabilities TEXT, status TEXT DEFAULT 'idle', current_task TEXT, completed_tasks INTEGER DEFAULT 0, last_heartbeat DATETIME DEFAULT CURRENT_TIMESTAMP )`); // 附件表 db.run(`CREATE TABLE IF NOT EXISTS attachments ( id INTEGER PRIMARY KEY AUTOINCREMENT, task_id INTEGER NOT NULL, filename TEXT NOT NULL, filepath TEXT NOT NULL, size INTEGER, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (task_id) REFERENCES tasks(id) )`); // 规约表 (支持全局和项目级别) db.run(`CREATE TABLE IF NOT EXISTS rules ( id INTEGER PRIMARY KEY AUTOINCREMENT, project_id INTEGER, rule_no TEXT NOT NULL, rule_type TEXT NOT NULL, description TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (project_id) REFERENCES projects(id) )`); console.log('✅ 数据库表已初始化'); }); // ==================== API 路由 ==================== // 健康检查 app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString(), uptime: process.uptime(), memory: process.memoryUsage(), version: require('./package.json').version }); }); // 统计信息 app.get('/api/stats', (req, res) => { const stats = {}; db.get('SELECT COUNT(*) as count FROM projects', (err, row) => { stats.projects = row ? row.count : 0; db.get('SELECT COUNT(*) as count FROM tasks', (err, row) => { stats.tasks = row ? row.count : 0; db.get('SELECT COUNT(*) as count FROM tasks WHERE status = "in_progress"', (err, row) => { stats.in_progress_tasks = row ? row.count : 0; db.get('SELECT COUNT(*) as count FROM tasks WHERE status = "completed"', (err, row) => { stats.completed_tasks = row ? row.count : 0; db.get('SELECT COUNT(*) as count FROM agents', (err, row) => { stats.total_agents = row ? row.count : 0; db.get('SELECT COUNT(*) as count FROM agents WHERE status = "busy"', (err, row) => { stats.active_agents = row ? row.count : 0; res.json(stats); }); }); }); }); }); }); }); // 项目管理 app.get('/api/projects', (req, res) => { db.all('SELECT * FROM projects ORDER BY created_at DESC', (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows || []); }); }); app.post('/api/projects', (req, res) => { const { name, description, created_by = 'human' } = req.body; db.run( 'INSERT INTO projects (name, description, created_by) VALUES (?, ?, ?)', [name, description, created_by], function(err) { if (err) return res.status(500).json({ error: err.message }); res.json({ id: this.lastID, name, description, created_by }); } ); }); app.get('/api/projects/:id', (req, res) => { db.get('SELECT * FROM projects WHERE id = ?', [req.params.id], (err, row) => { if (err) return res.status(500).json({ error: err.message }); if (!row) return res.status(404).json({ error: 'Project not found' }); res.json(row); }); }); app.delete('/api/projects/:id', (req, res) => { // 先删除项目下的所有任务 db.run('DELETE FROM tasks WHERE project_id = ?', [req.params.id], (err) => { if (err) return res.status(500).json({ error: err.message }); // 然后删除项目 db.run('DELETE FROM projects WHERE id = ?', [req.params.id], function(err) { if (err) return res.status(500).json({ error: err.message }); if (this.changes === 0) return res.status(404).json({ error: 'Project not found' }); res.json({ success: true }); }); }); }); // 任务管理 app.get('/api/tasks', (req, res) => { const { project_id } = req.query; let query = 'SELECT t.*, (SELECT COUNT(*) FROM tasks WHERE parent_id = t.id) as subtask_count, (SELECT COUNT(*) FROM attachments WHERE task_id = t.id) as attachment_count FROM tasks t'; let params = []; if (project_id) { query += ' WHERE t.project_id = ?'; params.push(project_id); } query += ' ORDER BY t.created_at DESC'; db.all(query, params, (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows || []); }); }); app.post('/api/tasks', (req, res) => { const { project_id, parent_id, title, description, type = 'development', priority = 'normal', status = 'initial', assigned_to, created_by = 'human' } = req.body; db.run( 'INSERT INTO tasks (project_id, parent_id, title, description, type, priority, status, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', [project_id, parent_id || null, title, description, type, priority, status, assigned_to || null, created_by], function(err) { if (err) return res.status(500).json({ error: err.message }); res.json({ id: this.lastID, project_id, title, type, priority, status }); } ); }); app.get('/api/tasks/:id', (req, res) => { db.get('SELECT * FROM tasks WHERE id = ?', [req.params.id], (err, task) => { if (err) return res.status(500).json({ error: err.message }); if (!task) return res.status(404).json({ error: 'Task not found' }); // 获取附件 db.all('SELECT * FROM attachments WHERE task_id = ?', [req.params.id], (err, attachments) => { task.attachments = attachments || []; // 获取子任务 db.all('SELECT * FROM tasks WHERE parent_id = ?', [req.params.id], (err, subtasks) => { task.subtasks = subtasks || []; res.json(task); }); }); }); }); app.put('/api/tasks/:id', (req, res) => { const updates = []; const values = []; ['status', 'type', 'priority', 'assigned_to', 'title', 'description'].forEach(field => { if (req.body[field] !== undefined) { updates.push(`${field} = ?`); values.push(req.body[field]); } }); if (updates.length === 0) { return res.status(400).json({ error: 'No fields to update' }); } values.push(req.params.id); db.run( `UPDATE tasks SET ${updates.join(', ')} WHERE id = ?`, values, function(err) { if (err) return res.status(500).json({ error: err.message }); if (this.changes === 0) return res.status(404).json({ error: 'Task not found' }); res.json({ success: true }); } ); }); app.delete('/api/tasks/:id', (req, res) => { db.run('DELETE FROM tasks WHERE id = ?', [req.params.id], function(err) { if (err) return res.status(500).json({ error: err.message }); res.json({ success: true }); }); }); // 智能体管理 app.get('/api/agents', (req, res) => { db.all('SELECT * FROM agents ORDER BY name', (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows || []); }); }); app.post('/api/agents', (req, res) => { const { name, type, capabilities } = req.body; db.run( 'INSERT INTO agents (name, type, capabilities) VALUES (?, ?, ?)', [name, type, JSON.stringify(capabilities)], function(err) { if (err) return res.status(500).json({ error: err.message }); res.json({ id: this.lastID, name, type, capabilities }); } ); }); // 规约管理 (支持多条目) // 获取全局规约列表 app.get('/api/rules/global', (req, res) => { db.all('SELECT * FROM rules WHERE project_id IS NULL ORDER BY rule_no', (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows || []); }); }); // 获取项目规约列表 app.get('/api/rules/project/:projectId', (req, res) => { db.all('SELECT * FROM rules WHERE project_id = ? ORDER BY rule_no', [req.params.projectId], (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows || []); }); }); // 获取单个规约 app.get('/api/rules/:id', (req, res) => { db.get('SELECT * FROM rules WHERE id = ?', [req.params.id], (err, row) => { if (err) return res.status(500).json({ error: err.message }); if (!row) return res.status(404).json({ error: 'Rule not found' }); res.json(row); }); }); // 创建规约 app.post('/api/rules', (req, res) => { const { project_id, rule_no, rule_type, description } = req.body; db.run( 'INSERT INTO rules (project_id, rule_no, rule_type, description) VALUES (?, ?, ?, ?)', [project_id || null, rule_no, rule_type, description], function(err) { if (err) return res.status(500).json({ error: err.message }); res.json({ id: this.lastID, project_id, rule_no, rule_type, description }); } ); }); // 更新规约 app.put('/api/rules/:id', (req, res) => { const { rule_no, rule_type, description } = req.body; const updates = []; const values = []; if (rule_no !== undefined) { updates.push('rule_no = ?'); values.push(rule_no); } if (rule_type !== undefined) { updates.push('rule_type = ?'); values.push(rule_type); } if (description !== undefined) { updates.push('description = ?'); values.push(description); } updates.push('updated_at = CURRENT_TIMESTAMP'); if (values.length === 0) { return res.status(400).json({ error: 'No fields to update' }); } values.push(req.params.id); db.run( `UPDATE rules SET ${updates.join(', ')} WHERE id = ?`, values, function(err) { if (err) return res.status(500).json({ error: err.message }); res.json({ success: true }); } ); }); // 删除规约 app.delete('/api/rules/:id', (req, res) => { db.run('DELETE FROM rules WHERE id = ?', [req.params.id], function(err) { if (err) return res.status(500).json({ error: err.message }); res.json({ success: true }); }); }); // 错误处理中间件(必须在所有路由之后) app.use((err, req, res, next) => { console.error('❌ API错误:', err.stack); res.status(500).json({ error: err.message || '服务器内部错误', timestamp: new Date().toISOString() }); }); // 启动服务器 const server = app.listen(PORT, () => { console.log(`🚀 多智能体任务管理系统已启动`); console.log(` 本地访问: http://localhost:${PORT}`); console.log(` 远程访问: http://10.0.6.5:${PORT}`); }); // 监听端口错误 server.on('error', (err) => { if (err.code === 'EADDRINUSE') { console.error(`❌ 端口 ${PORT} 已被占用`); console.error(` 请先停止占用端口的进程: lsof -ti:${PORT} | xargs kill -9`); process.exit(1); } else { console.error('❌ 服务器启动失败:', err); process.exit(1); } }); // 全局异常捕获 process.on('uncaughtException', (err) => { console.error('❌ 未捕获异常:', err); console.error(' 堆栈:', err.stack); // 不退出进程,继续运行 }); process.on('unhandledRejection', (reason, promise) => { console.error('❌ 未处理的Promise拒绝:', reason); console.error(' Promise:', promise); // 不退出进程,继续运行 }); // 优雅关闭 process.on('SIGINT', () => { console.log('\n⏸️ 收到关闭信号,准备关闭服务器...'); server.close(() => { console.log('📡 HTTP服务器已关闭'); db.close((err) => { if (err) { console.error('❌ 数据库关闭失败:', err); process.exit(1); } console.log('💾 数据库连接已关闭'); console.log('👋 服务器已完全关闭'); process.exit(0); }); }); // 强制超时退出(10秒) setTimeout(() => { console.error('⚠️ 强制退出(超时)'); process.exit(1); }, 10000); });