/** * 光湖Agent引擎 · 知识库对话服务 * BS-SG-001 · 铸渊 ICE-GL-ZY001 · D135b * * 连接: 代码仓库 ↔ Outline知识库 ↔ 冰朔对话 * * 功能: * /api/chat → 对话查询(读代码仓库·Outline·数据库) * /api/health → 健康检查 * /api/agent-status → 查看五分身流水线状态 */ const express = require('express'); const cors = require('cors'); const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const app = express(); const PORT = process.env.PORT || 3095; app.use(express.json()); app.use(cors()); const REPO_ROOT = '/opt/zhuyuan/guanghulab'; const OUTLINE_URL = process.env.OUTLINE_URL || 'http://127.0.0.1:3090'; // ============ 知识库导航 ============ function scanRepo() { const dataDir = path.join(REPO_ROOT, 'video-ai-system/data'); const brainDir = path.join(REPO_ROOT, 'brain/fifth-domain/zero-point/zhuyuan/causal-chains'); const result = { projects: [], chains: [], agents: [] }; // Scan video AI data try { const files = fs.readdirSync(dataDir); for (const f of files) { if (f.endsWith('.json') && f.startsWith('ep')) { result.projects.push({ file: f, type: 'output' }); } } } catch(e) {} // Scan causal chains try { const chains = fs.readdirSync(brainDir); for (const c of chains) { if (c.endsWith('.hdlp')) { result.chains.push({ file: c }); } } } catch(e) {} // Scan agent configs try { const agentDir = path.join(REPO_ROOT, 'video-ai-system/config/agents'); const agents = fs.readdirSync(agentDir); for (const a of agents) { result.agents.push({ file: a }); } } catch(e) {} return result; } function getPipelineStatus() { const dataDir = path.join(REPO_ROOT, 'video-ai-system/data'); const status = { episode1: { agents: {} }, }; const fileStatus = { 'ep01-scenes.json': 'Agent_01 · 拆文', 'ep01-storyboard.json': 'Agent_03 · 分镜', 'ep01-prompts.json': 'Agent_04 · 提示词', 'ep01-audit.json': 'Agent_05 · 审核', }; for (const [file, agent] of Object.entries(fileStatus)) { const filePath = path.join(dataDir, file); status.episode1.agents[agent] = fs.existsSync(filePath) ? '✅ 完成' : '⏳ 待执行'; } // Check characters.hdlp for Agent_02 const charPath = path.join(REPO_ROOT, 'video-ai-system/data/characters.hdlp'); status.episode1.agents['Agent_02 · 编号'] = fs.existsSync(charPath) ? '✅ 完成' : '⏳'; return status; } // ============ 简单意图路由 ============ function routeIntent(message) { const lower = message.toLowerCase(); // Pipeline status if (/进度|状态|流水线|第几集|做到哪/.test(message)) { return getPipelineStatus(); } // Character query if (/人物|角色|CHAR|苏白|诸葛风|萧灵汐/.test(message)) { try { const chars = fs.readFileSync( path.join(REPO_ROOT, 'video-ai-system/data/characters.hdlp'), 'utf8'); return { type: 'characters', content: chars.substring(0, 3000) }; } catch(e) { return { error: '读取人物库失败' }; } } // Framework query if (/框架|规则|agent|分身|硬骨架/.test(message)) { try { const framework = fs.readFileSync( path.join(REPO_ROOT, 'video-ai-system/config/PROJECT-FRAMEWORK.hdlp'), 'utf8'); return { type: 'framework', content: framework.substring(0, 3000) }; } catch(e) { return { error: '读取框架失败' }; } } // Navigation if (/有什么|导航|目录|结构/.test(message)) { return { type: 'navigation', content: scanRepo() }; } // Fallback return { type: 'help', content: '铸渊Agent引擎在线。你可以问我:\n• 流水线进度\n• 人物档案\n• 框架规则\n• 项目导航', navigation: scanRepo() }; } // ============ API ============ app.post('/api/chat', (req, res) => { const { message } = req.body; if (!message) return res.status(400).json({ error: '需要消息' }); const response = routeIntent(message); res.json({ reply: typeof response.content === 'string' ? response.content : JSON.stringify(response, null, 2), structured: response }); }); app.get('/api/health', (req, res) => { res.json({ ok: true, service: 'zhuyuan-agent-engine', version: 'v1.0', repo: fs.existsSync(REPO_ROOT) ? 'connected' : 'missing', outline: OUTLINE_URL }); }); app.get('/api/agent-status', (req, res) => { res.json(getPipelineStatus()); }); // ============ 注册系统 ============ const bcrypt = require('bcryptjs'); const { execSync: dexExecSync } = require('child_process'); const DEX_DB_HOST = '/opt/outline/dex-data/dex.db'; app.post('/api/register', (req, res) => { const { username, email, password } = req.body; if (!username || username.length < 2) return res.status(400).json({ ok: false, error: '用户名至少2个字符' }); if (!email || !email.includes('@')) return res.status(400).json({ ok: false, error: '无效邮箱' }); if (!password || password.length < 8) return res.status(400).json({ ok: false, error: '密码至少8位' }); try { // Hash password const hash = bcrypt.hashSync(password, 10); const userId = 'user-' + Date.now().toString(36) + '-' + Math.random().toString(36).substring(2, 8); // Use Python3 + sqlite3 to write to Dex database // Steps: 1) docker cp db out, 2) python modify, 3) docker cp back, 4) restart dex const safeEmail = email.replace(/'/g, "''"); const safeHash = hash.replace(/'/g, "''"); const safeUser = username.replace(/'/g, "''"); const script = ` import sqlite3, sys db = sqlite3.connect('${DEX_DB_HOST}') try: db.execute("CREATE TABLE IF NOT EXISTS password (email TEXT PRIMARY KEY, hash TEXT, username TEXT, user_id TEXT)") existing = db.execute("SELECT email FROM password WHERE email=?", ('${safeEmail}',)).fetchone() if existing: print('EXISTS') sys.exit(1) db.execute("INSERT INTO password (email, hash, username, user_id) VALUES (?,?,?,?)", ('${safeEmail}', '${safeHash}', '${safeUser}', '${userId}')) db.commit() print('OK') finally: db.close() `; dexExecSync(`docker cp outline-dex:/tmp/dex.db ${DEX_DB_HOST} 2>/dev/null || true`); const result = dexExecSync(`python3 -c "${script.replace(/"/g, '\\"').replace(/\n/g, '\\n')}"`, { timeout: 5000, encoding: 'utf8' }).trim(); if (result === 'EXISTS') { return res.status(400).json({ ok: false, error: '该邮箱已注册' }); } if (result !== 'OK') { throw new Error('Python script failed: ' + result); } dexExecSync(`docker cp ${DEX_DB_HOST} outline-dex:/tmp/dex.db`); dexExecSync('docker restart outline-dex 2>/dev/null'); console.log(`[注册] 新用户: ${username} <${email}>`); res.json({ ok: true, message: '注册成功', userId }); } catch(e) { console.error('[注册失败]', e.message); res.status(500).json({ ok: false, error: '服务器错误:' + e.message }); } }); app.listen(PORT, '127.0.0.1', () => { console.log(`[Agent引擎] 启动 · 端口${PORT} · 仓库${REPO_ROOT}`); });