diff --git a/src/app/(dashboard)/dashboard/usage/page.js b/src/app/(dashboard)/dashboard/usage/page.js index 52a344d6..05daa2c4 100644 --- a/src/app/(dashboard)/dashboard/usage/page.js +++ b/src/app/(dashboard)/dashboard/usage/page.js @@ -6,6 +6,7 @@ import { UsageStats, RequestLogger, CardSkeleton, SegmentedControl } from "@/sha import RequestDetailsTab from "./components/RequestDetailsTab"; const PERIODS = [ + { value: "today", label: "Today" }, { value: "24h", label: "24h" }, { value: "7d", label: "7D" }, { value: "30d", label: "30D" }, diff --git a/src/app/api/usage/chart/route.js b/src/app/api/usage/chart/route.js index 3289ca84..063cedd6 100644 --- a/src/app/api/usage/chart/route.js +++ b/src/app/api/usage/chart/route.js @@ -1,7 +1,7 @@ import { NextResponse } from "next/server"; import { getChartData } from "@/lib/usageDb"; -const VALID_PERIODS = new Set(["24h", "7d", "30d", "60d"]); +const VALID_PERIODS = new Set(["today", "24h", "7d", "30d", "60d"]); export async function GET(request) { try { diff --git a/src/app/api/usage/stats/route.js b/src/app/api/usage/stats/route.js index 2e8c88ad..27e51090 100644 --- a/src/app/api/usage/stats/route.js +++ b/src/app/api/usage/stats/route.js @@ -1,7 +1,7 @@ import { NextResponse } from "next/server"; import { getUsageStats } from "@/lib/usageDb"; -const VALID_PERIODS = new Set(["24h", "7d", "30d", "60d", "all"]); +const VALID_PERIODS = new Set(["today", "24h", "7d", "30d", "60d", "all"]); export const dynamic = "force-dynamic"; diff --git a/src/lib/db/repos/usageRepo.js b/src/lib/db/repos/usageRepo.js index 2d84449e..63d0494e 100644 --- a/src/lib/db/repos/usageRepo.js +++ b/src/lib/db/repos/usageRepo.js @@ -415,7 +415,7 @@ export async function getUsageStats(period = "all") { } } - const useDailySummary = period !== "24h"; + const useDailySummary = period !== "24h" && period !== "today"; if (useDailySummary) { const periodDays = { "7d": 7, "30d": 30, "60d": 60 }; @@ -529,8 +529,15 @@ export async function getUsageStats(period = "all") { if (stats.byEndpoint[endpointKey] && new Date(ts) > new Date(stats.byEndpoint[endpointKey].lastUsed)) stats.byEndpoint[endpointKey].lastUsed = ts; } } else { - // 24h: live history - const cutoff = new Date(Date.now() - PERIOD_MS["24h"]).toISOString(); + // 24h / today: live history + let cutoff; + if (period === "today") { + const startOfDay = new Date(); + startOfDay.setHours(0, 0, 0, 0); + cutoff = startOfDay.toISOString(); + } else { + cutoff = new Date(Date.now() - PERIOD_MS["24h"]).toISOString(); + } const filtered = db.all( `SELECT timestamp, provider, model, connectionId, apiKey, endpoint, promptTokens, completionTokens, cost, tokens FROM usageHistory WHERE timestamp >= ?`, [cutoff] @@ -614,6 +621,32 @@ export async function getChartData(period = "7d") { const db = await getAdapter(); const now = Date.now(); + if (period === "today") { + const bucketCount = 24; + const bucketMs = 3600000; + const startOfDay = new Date(); + startOfDay.setHours(0, 0, 0, 0); + const startTime = startOfDay.getTime(); + const endTime = startTime + bucketCount * bucketMs; + const labelFn = (ts) => new Date(ts).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }); + const buckets = Array.from({ length: bucketCount }, (_, i) => ({ label: labelFn(startTime + i * bucketMs), tokens: 0, cost: 0 })); + + const rows = db.all( + `SELECT timestamp, promptTokens, completionTokens, cost FROM usageHistory WHERE timestamp >= ?`, + [new Date(startTime).toISOString()] + ); + for (const r of rows) { + const t = new Date(r.timestamp).getTime(); + if (t < startTime || t >= endTime) continue; + const idx = Math.floor((t - startTime) / bucketMs); + if (idx >= 0 && idx < bucketCount) { + buckets[idx].tokens += (r.promptTokens || 0) + (r.completionTokens || 0); + buckets[idx].cost += r.cost || 0; + } + } + return buckets; + } + if (period === "24h") { const bucketCount = 24; const bucketMs = 3600000; diff --git a/src/shared/components/UsageStats.js b/src/shared/components/UsageStats.js index 98e7b7fc..29dd7295 100644 --- a/src/shared/components/UsageStats.js +++ b/src/shared/components/UsageStats.js @@ -182,6 +182,7 @@ const TABLE_OPTIONS = [ ]; const PERIODS = [ + { value: "today", label: "Today" }, { value: "24h", label: "24h" }, { value: "7d", label: "7D" }, { value: "30d", label: "30D" }, @@ -412,7 +413,7 @@ export default function UsageStats({ period: periodProp, setPeriod: setPeriodPro {/* Period selector (hidden when controlled by parent) */} {!hidePeriodSelector && (