/** * /d/ — Document view (Sonnet 4.6 agentic chunks v0.2.0, the only view). * * Server component loads chunks from disk; client component * provides language + flow/paged toggles, image crops on-demand, table CSVs. */ import Link from "next/link"; import { notFound } from "next/navigation"; import { readChunksByPage, readIndex, hasChunks, readReadingVersion } from "@/lib/chunks"; import { readDocument } from "@/lib/wiki"; import { pickPitch } from "@/lib/doc-summary"; import { getLocale } from "@/components/locale-toggle"; import { AuthBar } from "@/components/auth-bar"; import { ChatBubble } from "@/components/chat-bubble"; import { DocReadingView } from "@/components/doc-reading-view"; import { AnomalyHighlights, type AnomalyFlag } from "@/components/anomaly-highlights"; import { DocBureauPanel } from "@/components/doc-bureau-panel"; import { MarkdownBody } from "@/components/markdown-body"; export const dynamic = "force-dynamic"; export default async function DocPage({ params, }: { params: Promise<{ docId: string }>; }) { const { docId } = await params; const locale = await getLocale(); if (!(await hasChunks(docId))) { return (
← home

▍ Documento ainda não processado

Este documento ainda não foi indexado.

doc_id: {docId}

); } const [idx, byPage, doc, reading] = await Promise.all([ readIndex(docId), readChunksByPage(docId), readDocument(docId), readReadingVersion(docId), ]); if (!idx) notFound(); const ordered: Array<[number, typeof byPage extends Map ? V : never]> = Array.from(byPage.entries()).sort((a, b) => a[0] - b[0]); const pitch = pickPitch( doc?.fm as Record | undefined, locale === "en" ? "en" : "pt", ); // Histogram chunk types const typeCounts = new Map(); for (const entry of idx.chunks ?? []) { typeCounts.set(entry.type, (typeCounts.get(entry.type) || 0) + 1); } const topTypes = Array.from(typeCounts.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, 6); // Count UFO/cryptid anomalies across chunks + collect flags for the highlight panel let imageCount = 0; const ufoFlags: AnomalyFlag[] = []; const cryptidFlags: AnomalyFlag[] = []; for (const [page, chunks] of byPage) { for (const c of chunks) { if (c.fm.ufo_anomaly_detected) ufoFlags.push({ chunk_id: c.fm.chunk_id, page, type: c.fm.ufo_anomaly_type ?? null, rationale: c.fm.ufo_anomaly_rationale ?? null, }); if (c.fm.cryptid_anomaly_detected) cryptidFlags.push({ chunk_id: c.fm.chunk_id, page, type: c.fm.cryptid_anomaly_type ?? null, rationale: c.fm.cryptid_anomaly_rationale ?? null, }); if (c.fm.type === "image") imageCount++; } } const ufoCount = ufoFlags.length; const cryptidCount = cryptidFlags.length; const classification = (doc?.fm.highest_classification as string) ?? "—"; const collection = (doc?.fm.collection as string) ?? "—"; return (
← home
{classification} · {collection} · doc_id: {docId}

▍ {(doc?.fm.canonical_title as string) ?? docId}

{pitch && (
{pitch}
)}
{idx.total_pages} páginas {idx.total_chunks} trechos {imageCount > 0 && {imageCount} imagens} {ufoCount > 0 && 🛸 {ufoCount} UAP flags} {cryptidCount > 0 && {cryptidCount} cryptid}
{topTypes.length > 0 && (
{topTypes.map(([t, n]) => ( {t} {n} ))}
)}
); }