feat(ui): AI Usage Sacred Valley card + /api/ai-usage proxy (Claude tokens + local model perf)
Summarises the Homelab Monitor (CT300 :8080) into a blackflame card: Claude Code token usage today/week + top model, and OpenClaw/Ollama p50/p95 latency + error rate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
36
tests/api/ai_usage.test.js
Normal file
36
tests/api/ai_usage.test.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { summarizeUsage } from '../../lib/api/routes/ai_usage.js';
|
||||
|
||||
describe('summarizeUsage', () => {
|
||||
it('sums today + week tokens, picks top model, condenses local perf', () => {
|
||||
const data = {
|
||||
generated_at: '2026-06-04T23:00:00Z',
|
||||
daily_by_model: [
|
||||
{ day: '2026-06-04', model: 'claude-opus-4-8', input: 100, output: 200, cache_read: 1000, cache_creation: 50, turns: 5 },
|
||||
{ day: '2026-06-04', model: 'claude-sonnet-4-6', input: 10, output: 20, cache_read: 0, cache_creation: 0, turns: 2 },
|
||||
{ day: '2026-06-03', model: 'claude-opus-4-8', input: 1, output: 1, cache_read: 0, cache_creation: 0, turns: 1 }
|
||||
]
|
||||
};
|
||||
const openclaw = { summary: { by_model: [
|
||||
{ model: 'ollama/qwen2.5-coder:7b', count: 165, errors: 0, error_rate: 0, p50_ms: 3540, p95_ms: 88749 },
|
||||
{ model: 'ollama/llama3.1:8b', count: 50, errors: 2, error_rate: 0.04, p50_ms: 17443, p95_ms: 17991 }
|
||||
] } };
|
||||
|
||||
const s = summarizeUsage(data, openclaw);
|
||||
expect(s.ok).toBe(true);
|
||||
expect(s.today).toBe('2026-06-04');
|
||||
expect(s.claude.today).toEqual({ input: 110, output: 220, cache: 1050, turns: 7 });
|
||||
expect(s.claude.week.turns).toBe(8); // includes 06-03
|
||||
expect(s.claude.top_model).toBe('claude-opus-4-8'); // most tokens this week
|
||||
expect(s.local.runs).toBe(215);
|
||||
expect(s.local.top.model).toBe('qwen2.5-coder:7b'); // ollama/ stripped, highest count
|
||||
expect(s.local.top.p95_ms).toBe(88749);
|
||||
});
|
||||
|
||||
it('handles a missing openclaw payload', () => {
|
||||
const s = summarizeUsage({ daily_by_model: [] }, null);
|
||||
expect(s.ok).toBe(true);
|
||||
expect(s.local.runs).toBe(0);
|
||||
expect(s.local.top).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user