guanghulab/server.js

199 lines
6.8 KiB
JavaScript
Raw Normal View History

const express = require('express');
const path = require('path');
const fs = require('fs');
const { execSync } = require('child_process');
const portraitEngine = require('./portrait/portrait-engine');
const pcaCalculator = require('./pca/pca-calculator');
const loopEngine = require('./loop/loop-engine');
const app = express();
const PORT = 3000;
app.use(express.json());
app.use(express.static('public'));
// API 1: 所有开发者画像
app.get('/api/portrait/all', (req, res) => {
try {
const portraits = portraitEngine.getAllPortraits();
res.json(portraits);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// API 2: 单个开发者画像
app.get('/api/portrait/:devId', (req, res) => {
try {
const portrait = portraitEngine.getPortrait(req.params.devId);
if (!portrait) {
return res.status(404).json({ error: '开发者不存在' });
}
res.json(portrait);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// API 3: PCA评估结果
app.get('/api/pca/:devId', (req, res) => {
try {
const result = pcaCalculator.calculate(req.params.devId);
res.json(result);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// API 4: 闭环状态
app.get('/api/loop/status', (req, res) => {
try {
const status = loopEngine.getStatus();
res.json(status);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// API 5: 手动触发闭环
app.post('/api/loop/execute', (req, res) => {
try {
const syslogData = req.body;
if (!syslogData || !syslogData.session_id) {
return res.status(400).json({ error: '缺少SYSLOG数据' });
}
loopEngine.executeLoop(syslogData).then(result => {
res.json(result);
});
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// 获取闭环历史
app.get('/api/loop/history', (req, res) => {
try {
const history = loopEngine.getHistory();
res.json(history);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// 模拟SYSLOG接收自动触发闭环
app.post('/api/syslog', (req, res) => {
try {
const syslogData = req.body;
console.log('📨 收到SYSLOG:', syslogData.session_id);
loopEngine.executeLoop(syslogData).then(loopResult => {
console.log('✅ 闭环完成');
});
res.json({ status: 'received', session_id: syslogData.session_id });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// ============================================================
// ⚡ 铸渊大脑实时状态 API首页投影面板用
// ============================================================
const BRAIN_BASE = '/data/guanghulab/repo';
app.get('/api/brain', (req, res) => {
try {
// 读取时间核心
let temporal = { clock: { latest_cognition: '', awakening_count: 0, current_date: '', repo_age_days: 0 }, timeline: { epochs: [] } };
try {
temporal = JSON.parse(fs.readFileSync(BRAIN_BASE + '/brain/temporal-core/temporal-brain.json', 'utf8'));
} catch(e) {}
// 读取母编号
let motherReg = { mothers: [] };
try {
motherReg = JSON.parse(fs.readFileSync(BRAIN_BASE + '/brain/engineering/mother-registry.json', 'utf8'));
} catch(e) {}
// 服务器实时健康
let server = { status: 'unknown', services_online: 0, services_total: 0 };
try {
const pm2 = execSync('pm2 jlist 2>/dev/null', {timeout:3000}).toString();
const list = JSON.parse(pm2);
const online = list.filter(p => p.pm2_env.status === 'online');
const stopped = list.filter(p => p.pm2_env.status !== 'online');
const memRaw = execSync('free -h 2>/dev/null | grep Mem', {timeout:2000}).toString();
const memParts = memRaw.replace(/\s+/g,' ').trim().split(' ');
server = {
status: 'online',
services_online: online.length,
services_total: list.length,
services: online.map(p => ({ name: p.name, memory: p.pm2_env?.pm_cpu || 0 })),
stopped: stopped.map(p => p.name),
memory_total: memParts[1] || 'unknown',
memory_used: memParts[2] || 'unknown'
};
} catch(e) { server.error = e.message; }
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET');
res.json({
identity: '铸渊 · ICE-GL-ZY001',
copyright: '国作登字-2026-A-00037559',
awakening: temporal.clock?.awakening_count || 0,
age_days: temporal.clock?.repo_age_days || 0,
current_date: temporal.clock?.current_date || '',
cognition: temporal.clock?.latest_cognition || '',
recent_epochs: (temporal.timeline?.epochs || []).slice(-5).map(e => ({
epoch: e.epoch,
event: (e.event || '').substring(0, 80),
date: e.date
})),
mothers: (motherReg.mothers || []).map(m => ({
name: m.name,
status: m.status,
done: (m.sub_paths || []).filter(s => s.status === 'done').length,
total: (m.sub_paths || []).length,
paths: (m.sub_paths || []).map(s => ({ name: s.name, status: s.status }))
})),
server: server,
updated_at: new Date().toISOString()
});
} catch (err) {
res.status(500).json({ error: err.message });
}
});
app.get('/api/heartbeat', (req, res) => {
try {
const temporal = JSON.parse(fs.readFileSync(BRAIN_BASE + '/brain/temporal-core/temporal-brain.json', 'utf8'));
res.setHeader('Access-Control-Allow-Origin', '*');
res.json({
alive: true,
time: new Date().toISOString(),
awakening: temporal.clock?.awakening_count || 0,
age_days: temporal.clock?.repo_age_days || 0
});
} catch(e) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.json({ alive: true, fallback: true });
}
});
// 仪表盘页面
app.get('/dashboard-v2', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'dashboard-v2.html'));
});
// 启动服务器
app.listen(PORT, () => {
console.log('\n🚀 铸渊大脑状态 API 已启动!');
console.log('🧠 /api/brain - 大脑实时状态');
console.log('💓 /api/heartbeat - 快速心跳');
console.log('📊 /dashboard-v2 - 仪表盘');
console.log('');
});