Initial commit with translated description
This commit is contained in:
127
utils/dashboard-generator.js
Normal file
127
utils/dashboard-generator.js
Normal file
@@ -0,0 +1,127 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function generateDashboardCard(stats, systemInfo, cycleInfo) {
|
||||
const { total, successRate, intents, recent, avgFiles, avgLines, avgRigor } = stats;
|
||||
const { proc, mem, uptime, load, disk, loopStatus } = systemInfo;
|
||||
const { id, duration } = cycleInfo;
|
||||
|
||||
// --- ALERTS ---
|
||||
const alerts = [];
|
||||
if (systemInfo.errorAlert) alerts.push(systemInfo.errorAlert);
|
||||
if (systemInfo.healthAlert) alerts.push(systemInfo.healthAlert);
|
||||
|
||||
// Header color based on success rate and loop status
|
||||
let headerColor = 'blue';
|
||||
if (loopStatus.includes('STOPPED') || loopStatus.includes('OFF')) headerColor = 'grey';
|
||||
else if (parseFloat(successRate) < 80) headerColor = 'orange';
|
||||
else if (parseFloat(successRate) < 50) headerColor = 'red';
|
||||
else headerColor = 'green'; // Healthy and running
|
||||
|
||||
const elements = [];
|
||||
|
||||
if (alerts.length > 0) {
|
||||
elements.push({
|
||||
tag: 'div',
|
||||
text: {
|
||||
tag: 'lark_md',
|
||||
content: alerts.join('\n\n')
|
||||
}
|
||||
});
|
||||
elements.push({ tag: 'hr' });
|
||||
headerColor = 'red'; // Override color
|
||||
}
|
||||
|
||||
// 1. System Vital Signs (Fields)
|
||||
elements.push({
|
||||
tag: 'div',
|
||||
fields: [
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Status**: ${loopStatus}` }
|
||||
},
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Uptime**: ${Math.floor(uptime / 3600)}h` }
|
||||
},
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Memory**: ${mem}MB` }
|
||||
},
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Load**: ${load}` }
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
elements.push({ tag: 'hr' });
|
||||
|
||||
// 2. Evolution Stats (Fields) - ENHANCED
|
||||
elements.push({
|
||||
tag: 'div',
|
||||
fields: [
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Total Cycles**: ${total}` }
|
||||
},
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Success Rate**: ${successRate}%` }
|
||||
},
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Intents**: ✨${intents.innovate} 🔧${intents.repair} ⚡${intents.optimize}` }
|
||||
},
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Last Cycle**: #${id} (${duration})` }
|
||||
},
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Avg Blast**: ${avgFiles}f / ${avgLines}L` }
|
||||
},
|
||||
{
|
||||
is_short: true,
|
||||
text: { tag: 'lark_md', content: `**Avg Rigor**: ${avgRigor || 'N/A'}` }
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
elements.push({ tag: 'hr' });
|
||||
|
||||
// 3. Recent Activity Timeline
|
||||
let timelineMd = recent.map(e => {
|
||||
const icon = e.intent === 'innovate' ? '✨' : (e.intent === 'repair' ? '🔧' : '⚡');
|
||||
const statusIcon = e.status === 'success' ? '✅' : '❌';
|
||||
return `${statusIcon} **#${e.id}** ${icon} ${e.summary || 'No summary'}`;
|
||||
}).join('\n');
|
||||
|
||||
if (!timelineMd) timelineMd = '_No recent activity_';
|
||||
|
||||
elements.push({
|
||||
tag: 'div',
|
||||
text: {
|
||||
tag: 'lark_md',
|
||||
content: `**Recent Activity**:\n${timelineMd}`
|
||||
}
|
||||
});
|
||||
|
||||
// 4. Action hint (if needed)
|
||||
if (loopStatus.includes('STOPPED')) {
|
||||
elements.push({
|
||||
tag: 'note',
|
||||
elements: [{ tag: 'plain_text', content: '⚠️ Evolver loop is stopped. Run "lifecycle.js start" to resume.' }]
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
header: {
|
||||
template: headerColor,
|
||||
title: { tag: 'plain_text', content: '🧬 Evolver Capability Dashboard' }
|
||||
},
|
||||
elements: elements
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { generateDashboardCard };
|
||||
33
utils/logger.js
Normal file
33
utils/logger.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const LOG_FILE = path.join(__dirname, '../../../logs/evolver.log');
|
||||
|
||||
function log(level, message, data = {}) {
|
||||
const timestamp = new Date().toISOString();
|
||||
const logEntry = {
|
||||
timestamp,
|
||||
level,
|
||||
message,
|
||||
...data
|
||||
};
|
||||
|
||||
// Ensure logs directory exists
|
||||
const logDir = path.dirname(LOG_FILE);
|
||||
if (!fs.existsSync(logDir)) {
|
||||
fs.mkdirSync(logDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Append to log file
|
||||
fs.appendFileSync(LOG_FILE, JSON.stringify(logEntry) + '\n');
|
||||
|
||||
// Also log to console for immediate visibility
|
||||
console.log(`[${level}] ${message}`, JSON.stringify(data));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
info: (msg, data) => log('INFO', msg, data),
|
||||
error: (msg, data) => log('ERROR', msg, data),
|
||||
warn: (msg, data) => log('WARN', msg, data),
|
||||
debug: (msg, data) => log('DEBUG', msg, data)
|
||||
};
|
||||
15
utils/sleep.js
Normal file
15
utils/sleep.js
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
function sleepSync(ms) {
|
||||
if (ms <= 0) return;
|
||||
try {
|
||||
const sab = new SharedArrayBuffer(4);
|
||||
const int32 = new Int32Array(sab);
|
||||
Atomics.wait(int32, 0, 0, ms);
|
||||
} catch (e) {
|
||||
// Fallback for environments without SharedArrayBuffer (rare in Node 22)
|
||||
const end = Date.now() + ms;
|
||||
while (Date.now() < end) {}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { sleepSync };
|
||||
Reference in New Issue
Block a user