Spaces:
Runtime error
Runtime error
| import { NextRequest, NextResponse } from "next/server"; | |
| import { | |
| getCacheStats, | |
| clearCache, | |
| invalidateByModel, | |
| invalidateBySignature, | |
| invalidateStale, | |
| } from "@/lib/semanticCache"; | |
| import { getIdempotencyStats } from "@/lib/idempotencyLayer"; | |
| import { getCacheMetrics, getCacheTrend } from "@/lib/db/settings"; | |
| import { getCachedSettings } from "@/lib/localDb"; | |
| import { isAuthenticated } from "@/shared/utils/apiAuth"; | |
| import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error"; | |
| function errorMessage(error: unknown): string { | |
| return sanitizeErrorMessage(error); | |
| } | |
| export async function GET(req: NextRequest) { | |
| if (!(await isAuthenticated(req))) { | |
| return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); | |
| } | |
| try { | |
| const { searchParams } = new URL(req.url); | |
| const rawHours = parseInt(searchParams.get("trendHours") || "24", 10); | |
| const trendHours = Math.min(720, Math.max(1, Number.isNaN(rawHours) ? 24 : rawHours)); | |
| const cacheStats = getCacheStats(); | |
| const idempotencyStats = await getIdempotencyStats(); | |
| const promptCacheMetrics = await getCacheMetrics(); | |
| const trend = await getCacheTrend(trendHours); | |
| const settings = await getCachedSettings().catch(() => ({})); | |
| return NextResponse.json({ | |
| semanticCache: cacheStats, | |
| promptCache: promptCacheMetrics, | |
| trend, | |
| idempotency: idempotencyStats, | |
| config: { | |
| semanticCacheEnabled: settings.semanticCacheEnabled !== false, | |
| }, | |
| }); | |
| } catch (error) { | |
| return NextResponse.json({ error: errorMessage(error) }, { status: 500 }); | |
| } | |
| } | |
| export async function DELETE(req: NextRequest) { | |
| if (!(await isAuthenticated(req))) { | |
| return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); | |
| } | |
| try { | |
| const { searchParams } = new URL(req.url); | |
| const model = searchParams.get("model"); | |
| const signature = searchParams.get("signature"); | |
| const staleMsParam = searchParams.get("staleMs"); | |
| // Enforce mutual exclusivity — only one invalidation mode per request | |
| const paramCount = [model, signature, staleMsParam].filter(Boolean).length; | |
| if (paramCount > 1) { | |
| return NextResponse.json( | |
| { | |
| error: | |
| "Only one invalidation parameter (model, signature, or staleMs) may be provided per request.", | |
| }, | |
| { status: 400 } | |
| ); | |
| } | |
| if (model) { | |
| const removed = invalidateByModel(model); | |
| return NextResponse.json({ ok: true, invalidated: removed, scope: "model", model }); | |
| } | |
| if (signature) { | |
| const removed = invalidateBySignature(signature); | |
| return NextResponse.json({ ok: true, invalidated: removed ? 1 : 0, scope: "signature" }); | |
| } | |
| if (staleMsParam) { | |
| const maxAgeMs = parseInt(staleMsParam, 10); | |
| if (Number.isNaN(maxAgeMs) || maxAgeMs <= 0) { | |
| return NextResponse.json( | |
| { error: "staleMs must be a positive integer (milliseconds)." }, | |
| { status: 400 } | |
| ); | |
| } | |
| const removed = invalidateStale(maxAgeMs); | |
| return NextResponse.json({ ok: true, invalidated: removed, scope: "stale", maxAgeMs }); | |
| } | |
| // Full clear | |
| const cleared = clearCache(); | |
| return NextResponse.json({ ok: true, cleared, scope: "all" }); | |
| } catch (error) { | |
| return NextResponse.json({ error: errorMessage(error) }, { status: 500 }); | |
| } | |
| } | |