claude-collab
Version:
Claude Collab - The AI collaboration framework that prevents echo chambers
158 lines (131 loc) • 3.87 kB
JavaScript
/**
* Metrics Panel Component for Terminal Dashboard
* Shows diversity metrics and collaboration health
*/
const blessed = require('blessed');
const contrib = require('blessed-contrib');
class MetricsPanel {
constructor(grid, options) {
this.options = options;
// Create container for metrics
this.container = grid.set(
options.row,
options.col,
options.rowSpan,
options.colSpan,
blessed.box,
{
label: options.label || ' Diversity Metrics ',
border: { type: 'line' },
style: {
border: { fg: 'cyan' }
}
}
);
this.setupComponents();
this.metrics = {};
}
setupComponents() {
// Diversity gauge
this.diversityGauge = contrib.gauge({
parent: this.container,
label: 'Overall Diversity',
width: '25%',
height: '80%',
top: 1,
left: 1,
stroke: 'green',
fill: 'white',
gaugeSpacing: 1,
gaugeHeight: 1
});
// Agreement rate
this.agreementGauge = contrib.gauge({
parent: this.container,
label: 'Agreement Rate',
width: '25%',
height: '80%',
top: 1,
left: '25%',
stroke: 'yellow',
fill: 'white'
});
// Evidence rate
this.evidenceGauge = contrib.gauge({
parent: this.container,
label: 'Evidence Rate',
width: '25%',
height: '80%',
top: 1,
left: '50%',
stroke: 'cyan',
fill: 'white'
});
// Stats text
this.statsBox = blessed.box({
parent: this.container,
width: '25%',
height: '80%',
top: 1,
left: '75%',
tags: true,
style: {
fg: 'white'
}
});
}
update(metrics) {
this.metrics = metrics;
// Update gauges with percentages
const diversityPercent = Math.round((metrics.overallDiversity || 0) * 100);
const agreementPercent = Math.round((metrics.agreementRate || 0) * 100);
const evidencePercent = Math.round((metrics.evidenceRate || 0) * 100);
this.diversityGauge.setPercent(diversityPercent);
this.agreementGauge.setPercent(agreementPercent);
this.evidenceGauge.setPercent(evidencePercent);
// Set gauge colors based on thresholds
this.setGaugeColor(this.diversityGauge, diversityPercent, 60, 40); // Want high diversity
this.setGaugeColor(this.agreementGauge, 100 - agreementPercent, 70, 50); // Want low agreement
this.setGaugeColor(this.evidenceGauge, evidencePercent, 70, 50); // Want high evidence
// Update stats
this.updateStats(metrics);
this.container.screen.render();
}
setGaugeColor(gauge, value, goodThreshold, warningThreshold) {
if (value >= goodThreshold) {
gauge.setOptions({ stroke: 'green' });
} else if (value >= warningThreshold) {
gauge.setOptions({ stroke: 'yellow' });
} else {
gauge.setOptions({ stroke: 'red' });
}
}
updateStats(metrics) {
const content = `{bold}Live Stats{/}
Agents: {cyan-fg}${metrics.activeAgents || 0}{/}
Msg/min: {yellow-fg}${metrics.messagesPerMinute || 0}{/}
{bold}Warnings:{/}
${this.getWarnings(metrics)}`;
this.statsBox.setContent(content);
}
getWarnings(metrics) {
const warnings = [];
if (metrics.overallDiversity < 0.5) {
warnings.push('{red-fg}⚠ Low diversity!{/}');
}
if (metrics.agreementRate > 0.8) {
warnings.push('{red-fg}⚠ Echo chamber risk!{/}');
}
if (metrics.evidenceRate < 0.3) {
warnings.push('{yellow-fg}⚠ Low evidence rate{/}');
}
if (metrics.activeAgents < 2) {
warnings.push('{gray-fg}ℹ Need more agents{/}');
}
return warnings.length > 0 ? warnings.join('\n') : '{green-fg}✓ All good!{/}';
}
focus() {
this.container.focus();
}
}
module.exports = MetricsPanel;