#!/usr/bin/env node const { Pool } = require('pg'); const pool = new Pool({ host: process.env.DB_HOST || 'localhost', port: process.env.DB_PORT || 5432, database: process.env.DB_NAME || 'agent_tasks_v2', user: process.env.DB_USER || 'postgres', password: process.env.DB_PASSWORD || 'postgres', }); async function migrate() { const client = await pool.connect(); try { console.log('🔧 开始数据库迁移...'); // 创建智能体表 console.log('创建 agents 表...'); await client.query(` CREATE TABLE IF NOT EXISTS agents ( id VARCHAR(255) PRIMARY KEY, name VARCHAR(255) NOT NULL, type VARCHAR(100), capabilities JSONB, status VARCHAR(50) DEFAULT 'idle', registered_at BIGINT, last_heartbeat BIGINT ) `); // 创建项目表 console.log('创建 projects 表...'); await client.query(` CREATE TABLE IF NOT EXISTS projects ( id VARCHAR(255) PRIMARY KEY, name VARCHAR(500) NOT NULL, description TEXT, created_by VARCHAR(255), created_at BIGINT, updated_at BIGINT, status VARCHAR(50) DEFAULT 'active' ) `); // 创建全局协作规约表 console.log('创建 global_collaboration_rules 表...'); await client.query(` CREATE TABLE IF NOT EXISTS global_collaboration_rules ( id VARCHAR(255) PRIMARY KEY, content TEXT NOT NULL, created_by VARCHAR(255), created_at BIGINT, updated_at BIGINT ) `); // 创建项目协作规约表 console.log('创建 collaboration_rules 表...'); await client.query(` CREATE TABLE IF NOT EXISTS collaboration_rules ( id VARCHAR(255) PRIMARY KEY, project_id VARCHAR(255), content TEXT NOT NULL, created_by VARCHAR(255), created_at BIGINT, updated_at BIGINT ) `); // 创建项目信息共享清单表 console.log('创建 project_notes 表...'); await client.query(` CREATE TABLE IF NOT EXISTS project_notes ( id VARCHAR(255) PRIMARY KEY, project_id VARCHAR(255), content TEXT NOT NULL, created_by VARCHAR(255), created_at BIGINT, updated_at BIGINT ) `); // 创建任务表 console.log('创建 tasks 表...'); await client.query(` CREATE TABLE IF NOT EXISTS tasks ( id VARCHAR(255) PRIMARY KEY, project_id VARCHAR(255), parent_task_id VARCHAR(255), title VARCHAR(500) NOT NULL, description TEXT, task_type VARCHAR(50) DEFAULT 'development', priority VARCHAR(50) DEFAULT 'normal', status VARCHAR(50) DEFAULT 'initial', created_by VARCHAR(255), assigned_to VARCHAR(255), created_at BIGINT, updated_at BIGINT, completed_at BIGINT, result TEXT ) `); // 创建附件表 console.log('创建 attachments 表...'); await client.query(` CREATE TABLE IF NOT EXISTS attachments ( id VARCHAR(255) PRIMARY KEY, task_id VARCHAR(255), filename VARCHAR(500) NOT NULL, original_name VARCHAR(500) NOT NULL, file_path VARCHAR(1000) NOT NULL, file_size BIGINT, mime_type VARCHAR(100), uploaded_by VARCHAR(255), uploaded_at BIGINT ) `); // 现在添加外键约束 console.log('添加外键约束...'); await client.query(` DO $$ BEGIN -- collaboration_rules 外键 IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'collaboration_rules_project_id_fkey' ) THEN ALTER TABLE collaboration_rules ADD CONSTRAINT collaboration_rules_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; END IF; -- project_notes 外键 IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'project_notes_project_id_fkey' ) THEN ALTER TABLE project_notes ADD CONSTRAINT project_notes_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; END IF; -- tasks 外键 IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'tasks_project_id_fkey' ) THEN ALTER TABLE tasks ADD CONSTRAINT tasks_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; END IF; IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'tasks_parent_task_id_fkey' ) THEN ALTER TABLE tasks ADD CONSTRAINT tasks_parent_task_id_fkey FOREIGN KEY (parent_task_id) REFERENCES tasks(id) ON DELETE SET NULL; END IF; -- attachments 外键 IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'attachments_task_id_fkey' ) THEN ALTER TABLE attachments ADD CONSTRAINT attachments_task_id_fkey FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE; END IF; END $$; `); // 创建索引 console.log('创建索引...'); await client.query(`CREATE INDEX IF NOT EXISTS idx_agents_status ON agents(status)`); await client.query(`CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)`); await client.query(`CREATE INDEX IF NOT EXISTS idx_tasks_project ON tasks(project_id)`); await client.query(`CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_task_id)`); await client.query(`CREATE INDEX IF NOT EXISTS idx_tasks_assigned ON tasks(assigned_to)`); await client.query(`CREATE INDEX IF NOT EXISTS idx_attachments_task ON attachments(task_id)`); await client.query(`CREATE INDEX IF NOT EXISTS idx_project_notes_project ON project_notes(project_id)`); console.log('✅ 数据库迁移完成!'); } catch (err) { console.error('❌ 迁移失败:', err); process.exit(1); } finally { client.release(); await pool.end(); } } migrate();