let costChart = null;
async function renderCostAnalytics() {
const content = document.getElementById('pageContent');
content.innerHTML = `
`;
try {
const cost = await api.getCost();
const entries = cost.entries || [];
// Aggregate
const totalTokens = entries.reduce((sum, e) => sum + (e.tokens || 0), 0);
const today = new Date().toISOString().slice(0, 10);
const todayTokens = entries.filter(e => e.timestamp && e.timestamp.startsWith(today)).reduce((sum, e) => sum + (e.tokens || 0), 0);
document.getElementById('totalTokens').textContent = totalTokens.toLocaleString();
document.getElementById('todayTokens').textContent = todayTokens.toLocaleString();
document.getElementById('estimatedMonthly').textContent = `$${(totalTokens * 0.000002).toFixed(2)}`;
// Agent breakdown
const byAgent = {};
entries.forEach(e => {
const agent = e.agent || 'unknown';
byAgent[agent] = (byAgent[agent] || 0) + (e.tokens || 0);
});
const breakdown = document.getElementById('costAgentBreakdown');
Object.entries(byAgent).forEach(([agent, tokens]) => {
const pct = totalTokens > 0 ? (tokens / totalTokens * 100).toFixed(1) : 0;
breakdown.innerHTML += `
${agent}
${tokens.toLocaleString()} (${pct}%)
`;
});
// Free tier alerts
const alerts = cost.free_tier_alerts || [];
const alertsContainer = document.getElementById('freeTierAlerts');
if (alerts.length === 0) {
alertsContainer.innerHTML = 'No active alerts. All within free tier limits.
';
} else {
alertsContainer.innerHTML = alerts.map(a => `
ALERT
${a}
`).join('');
}
// Chart
const ctx = document.getElementById('costChart');
if (ctx && Chart) {
if (costChart) costChart.destroy();
const dailyTotals = {};
entries.forEach(e => {
if (e.timestamp) {
const day = e.timestamp.slice(0, 10);
dailyTotals[day] = (dailyTotals[day] || 0) + (e.tokens || 0);
}
});
const days = Object.keys(dailyTotals).slice(-14);
const values = days.map(d => dailyTotals[d]);
costChart = new Chart(ctx, {
type: 'line',
data: {
labels: days,
datasets: [{
label: 'Daily Tokens',
data: values,
borderColor: '#6c5ce7',
backgroundColor: 'rgba(108,92,231,0.1)',
fill: true,
tension: 0.4,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: { legend: { display: false } },
scales: {
x: { ticks: { color: '#8b8fa3', maxTicksLimit: 7 } },
y: { ticks: { color: '#8b8fa3' } }
}
}
});
}
} catch (err) {
document.getElementById('costCards').innerHTML = `Error: ${escapeHtml(err.message)}
`;
}
}