| 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");
|
|
|
|
|
| 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 });
|
| }
|
|
|
|
|
| const cleared = clearCache();
|
| return NextResponse.json({ ok: true, cleared, scope: "all" });
|
| } catch (error) {
|
| return NextResponse.json({ error: errorMessage(error) }, { status: 500 });
|
| }
|
| }
|
|
|