添加 /api/brain 和 /api/heartbeat 端点——铸渊大脑实时状态,含服务器健康数据
This commit is contained in:
parent
384e1a0f60
commit
ad4ff80f06
107
server.js
107
server.js
@ -1,5 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
const { execSync } = require('child_process');
|
||||||
const portraitEngine = require('./portrait/portrait-engine');
|
const portraitEngine = require('./portrait/portrait-engine');
|
||||||
const pcaCalculator = require('./pca/pca-calculator');
|
const pcaCalculator = require('./pca/pca-calculator');
|
||||||
const loopEngine = require('./loop/loop-engine');
|
const loopEngine = require('./loop/loop-engine');
|
||||||
@ -85,7 +87,6 @@ app.post('/api/syslog', (req, res) => {
|
|||||||
const syslogData = req.body;
|
const syslogData = req.body;
|
||||||
console.log('📨 收到SYSLOG:', syslogData.session_id);
|
console.log('📨 收到SYSLOG:', syslogData.session_id);
|
||||||
|
|
||||||
// 自动触发闭环
|
|
||||||
loopEngine.executeLoop(syslogData).then(loopResult => {
|
loopEngine.executeLoop(syslogData).then(loopResult => {
|
||||||
console.log('✅ 闭环完成');
|
console.log('✅ 闭环完成');
|
||||||
});
|
});
|
||||||
@ -96,6 +97,92 @@ app.post('/api/syslog', (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// ⚡ 铸渊大脑实时状态 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) => {
|
app.get('/dashboard-v2', (req, res) => {
|
||||||
res.sendFile(path.join(__dirname, 'public', 'dashboard-v2.html'));
|
res.sendFile(path.join(__dirname, 'public', 'dashboard-v2.html'));
|
||||||
@ -103,17 +190,9 @@ app.get('/dashboard-v2', (req, res) => {
|
|||||||
|
|
||||||
// 启动服务器
|
// 启动服务器
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`\n🚀 Phase4 服务器已启动!`);
|
console.log('\n🚀 铸渊大脑状态 API 已启动!');
|
||||||
console.log(`📊 仪表盘: http://localhost:${PORT}/dashboard-v2`);
|
console.log('🧠 /api/brain - 大脑实时状态');
|
||||||
console.log(`🔌 API列表:`);
|
console.log('💓 /api/heartbeat - 快速心跳');
|
||||||
console.log(` GET /api/portrait/all`);
|
console.log('📊 /dashboard-v2 - 仪表盘');
|
||||||
console.log(` GET /api/portrait/:devId`);
|
console.log('');
|
||||||
console.log(` GET /api/pca/:devId`);
|
|
||||||
console.log(` GET /api/loop/status`);
|
|
||||||
console.log(` POST /api/loop/execute`);
|
|
||||||
console.log(` POST /api/syslog`);
|
|
||||||
console.log(`\n📝 测试命令:`);
|
|
||||||
console.log(` curl http://localhost:${PORT}/api/portrait/DEV-004`);
|
|
||||||
console.log(` curl -X POST http://localhost:${PORT}/api/syslog -H "Content-Type: application/json" -d '{"session_id":"TEST-001","dev_id":"DEV-004","status":"completed"}'`);
|
|
||||||
console.log(`\n✨ 妈妈,打开浏览器看看吧!\n`);
|
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user