feat(tui,dashboard,docs): add context command parity and context health panel
This commit is contained in:
@@ -75,6 +75,11 @@ function renderSkeleton(el) {
|
||||
<div class="text-muted text-sm">Loading...</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">Context Health</h2>
|
||||
<div id="ops-context-health">
|
||||
<div class="text-muted text-sm">Loading...</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">Event Stream</h2>
|
||||
<div class="event-stream" id="ops-events">
|
||||
<div class="event-row event-level-info">Loading events...</div>
|
||||
@@ -346,6 +351,66 @@ function updateSessionAnalytics(analyticsData) {
|
||||
`;
|
||||
}
|
||||
|
||||
function updateContextHealth(contextData) {
|
||||
const el = document.getElementById('ops-context-health');
|
||||
if (!el) {return;}
|
||||
|
||||
const sessions = contextData?.sessions ?? [];
|
||||
if (sessions.length === 0) {
|
||||
el.innerHTML = '<div class="text-muted text-sm">No active context usage snapshots</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const sorted = [...sessions].sort((a, b) => (b.budget?.usagePct ?? 0) - (a.budget?.usagePct ?? 0));
|
||||
const top = sorted.slice(0, 8);
|
||||
const highest = top[0]?.budget?.usagePct ?? 0;
|
||||
const overThreshold = sessions.filter(s => (s.budget?.shouldCompact ?? false)).length;
|
||||
|
||||
const summary = `
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Highest Usage</div>
|
||||
<div class="stat-value ${highest >= 90 ? 'error' : ''}">${highest.toFixed(1)}%</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Sessions Near Limit</div>
|
||||
<div class="stat-value ${overThreshold > 0 ? 'error' : ''}">${overThreshold}</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Active Snapshots</div>
|
||||
<div class="stat-value">${sessions.length}</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const rows = top.map((entry) => {
|
||||
const budget = entry.budget ?? {};
|
||||
const usage = budget.usagePct ?? 0;
|
||||
const cls = usage >= 95 ? 'text-error' : usage >= 85 ? 'status-warning' : '';
|
||||
return `<tr>
|
||||
<td>${escapeHtml(entry.sessionId)}</td>
|
||||
<td class="${cls}">${usage.toFixed(1)}%</td>
|
||||
<td>${formatNumber(budget.estimatedTokens ?? 0)} / ${formatNumber(budget.contextWindow ?? 0)}</td>
|
||||
<td>${budget.shouldCompact ? 'yes' : 'no'}</td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
|
||||
el.innerHTML = `
|
||||
${summary}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Session</th>
|
||||
<th>Usage</th>
|
||||
<th>Estimated Tokens</th>
|
||||
<th>Should Compact</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>${rows}</tbody>
|
||||
</table>
|
||||
`;
|
||||
}
|
||||
|
||||
function _updateChannels(channelsData) {
|
||||
const el = document.getElementById('ops-channels');
|
||||
if (!el) {return;}
|
||||
@@ -414,12 +479,13 @@ async function fetchFast(client) {
|
||||
|
||||
async function fetchSlow(client) {
|
||||
try {
|
||||
const [health, services, sessionAnalytics] = await Promise.all([
|
||||
const [health, services, sessionAnalytics, contextUsage] = await Promise.all([
|
||||
client.call('system.health'),
|
||||
client.call('system.services'),
|
||||
client.call('system.sessionAnalytics', { days: 14, topLimit: 5 }),
|
||||
client.call('system.contextUsage'),
|
||||
]);
|
||||
return { health, services, sessionAnalytics };
|
||||
return { health, services, sessionAnalytics, contextUsage };
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
@@ -451,6 +517,7 @@ async function loadDashboard(el, client) {
|
||||
if (slow) {
|
||||
updateServices(slow.services);
|
||||
updateSessionAnalytics(slow.sessionAnalytics);
|
||||
updateContextHealth(slow.contextUsage);
|
||||
}
|
||||
|
||||
// Fast refresh: 3 seconds for metrics, events, requests
|
||||
@@ -473,6 +540,7 @@ async function loadDashboard(el, client) {
|
||||
updateCounters(_lastMetrics, data.health);
|
||||
updateServices(data.services);
|
||||
updateSessionAnalytics(data.sessionAnalytics);
|
||||
updateContextHealth(data.contextUsage);
|
||||
}
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user