toknmtr-selfhost/src/routes/+page.server.ts
megaproxy 71a60ab054 toknmtr — self-hostable Claude Code usage & analytics dashboard
Server (SvelteKit + SQLite Docker container) + per-machine agent that parses
Claude Code JSONL transcripts. docker-compose one-command deploy; raw transcript
view + search gated behind SHOW_TRANSCRIPTS (hidden by default).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 19:33:55 +01:00

57 lines
2 KiB
TypeScript

import {
overviewStats,
usageSeries,
usageByModel,
topTools,
recentSessions,
hourOfDayActivity,
cacheEfficiency,
usageGauges,
type Bucket,
type TimeWindow
} from '$lib/server/queries';
import { resolveRange } from '$lib/server/range';
import { getCostByProject } from '$lib/server/stats/byProject';
import { getGaugeHistory } from '$lib/server/stats/gaugeHistory';
import { getWebUsage } from '$lib/server/stats/webUsage';
import { getToolErrors } from '$lib/server/stats/toolErrors';
import { getTopActivity } from '$lib/server/stats/topActivity';
import { getLatencyTrends } from '$lib/server/stats/latency';
import { getActivityCalendar } from '$lib/server/stats/calendar';
import { getPunchcard } from '$lib/server/stats/punchcard';
import type { PageServerLoad } from './$types';
const TOP_TOOLS_LIMIT = 10;
const RECENT_SESSIONS_LIMIT = 7; // dashboard shows a short preview; full list lives at /sessions
const DAY_MS = 86_400_000;
export const load: PageServerLoad = async ({ url }) => {
const range = resolveRange(url);
const window: TimeWindow = { since: range.since, until: range.until };
// usageSeries needs concrete bounds; fall back to a 30-day span if the DB is empty.
const seriesSince = range.since ?? new Date(Date.now() - 30 * DAY_MS).toISOString();
const bucket: Bucket = range.bucket;
const byModel = usageByModel(window);
return {
range,
overview: overviewStats(window),
series: usageSeries(seriesSince, range.until, bucket),
modelSet: byModel.map((m) => m.model), // stacking order (cost desc)
byModel,
hourly: hourOfDayActivity(window),
cache: cacheEfficiency(window),
topTools: topTools(TOP_TOOLS_LIMIT, window),
recentSessions: recentSessions(RECENT_SESSIONS_LIMIT, window),
gauges: usageGauges(),
projects: getCostByProject(window),
gaugeHistory: getGaugeHistory(window),
webUsage: getWebUsage(window),
toolErrors: getToolErrors(window),
topActivity: getTopActivity(window),
speed: getLatencyTrends(window),
activityCalendar: getActivityCalendar(),
punchcard: getPunchcard(window)
};
};