import { NextResponse } from "next/server"; import { z } from "zod"; import { requireManagementAuth } from "@/lib/api/requireManagementAuth"; import { compressionPreviewConfigSchema } from "@/shared/validation/compressionConfigSchemas"; import { applyCompression } from "@omniroute/open-sse/services/compression/strategySelector"; import type { CompressionConfig, CompressionMode, } from "@omniroute/open-sse/services/compression/types"; import { buildCompressionPreviewDiff } from "@omniroute/open-sse/services/compression/diffHelper"; export const PreviewCompressionConfigSchema = compressionPreviewConfigSchema; export const PreviewRequestSchema = z.object({ messages: z .array( z.object({ role: z.string(), content: z.union([z.string(), z.array(z.unknown())]), }) ) .min(1), mode: z.enum(["off", "lite", "standard", "aggressive", "ultra", "rtk", "stacked"]), config: PreviewCompressionConfigSchema.optional(), }); function countTokens(text: string): number { return Math.ceil(text.split(/\s+/).filter(Boolean).length * 1.33); } function messagesToText(messages: Array<{ role: string; content: unknown }>): string { return messages .map((m) => { const content = typeof m.content === "string" ? m.content : JSON.stringify(m.content); return `${m.role}: ${content}`; }) .join("\n"); } export async function POST(req: Request) { const authError = await requireManagementAuth(req); if (authError) return authError; let body: unknown; try { body = await req.json(); } catch { return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 }); } const parsed = PreviewRequestSchema.safeParse(body); if (!parsed.success) { return NextResponse.json( { error: "Invalid request", details: parsed.error.issues }, { status: 400 } ); } const { messages, mode, config } = parsed.data; const originalText = messagesToText(messages); const originalTokens = countTokens(originalText); try { const start = Date.now(); const requestBody = { messages }; const result = await applyCompression(requestBody as Record, mode, { config: config as CompressionConfig | undefined, }); const durationMs = Date.now() - start; const compressedMessages = (result.body.messages ?? messages) as Array<{ role: string; content: unknown; }>; const compressedText = messagesToText(compressedMessages); const compressedTokens = countTokens(compressedText); const tokensSaved = Math.max(0, originalTokens - compressedTokens); const savingsPct = originalTokens > 0 ? Math.round((tokensSaved / originalTokens) * 100) : 0; const techniquesUsed: string[] = result.stats?.techniquesUsed ?? []; const diff = buildCompressionPreviewDiff(originalText, compressedText, result.stats); return NextResponse.json({ original: originalText, compressed: compressedText, originalTokens, compressedTokens, tokensSaved, savingsPct, techniquesUsed, durationMs, mode, intensity: null, outputMode: null, skippedReasons: [], diff: diff.segments, preservedBlocks: diff.preservedBlocks, ruleRemovals: diff.ruleRemovals, rulesApplied: diff.ruleRemovals, validation: { valid: diff.validationErrors.length === 0, errors: diff.validationErrors, warnings: diff.validationWarnings, fallbackApplied: diff.fallbackApplied, }, validationWarnings: diff.validationWarnings, validationErrors: diff.validationErrors, fallbackApplied: diff.fallbackApplied, }); } catch (err: unknown) { const msg = err instanceof Error ? err.message : String(err); console.error("[/api/compression/preview]", msg); return NextResponse.json({ error: "Compression failed", details: msg }, { status: 500 }); } }