"use client"; import { useEffect } from "react"; import { createPortal } from "react-dom"; import type { CompactionDetails } from "@/src/core"; /** What one divider carries: the marker's full model-facing content (the * [SESSION HISTORY COMPACTED] header + the summary) and its details — * both dividers open the same dialog from the same payload. */ export interface CompactionDividerData { content: string; details: CompactionDetails; } /** The moment divider (owner round 14): minimal centered small text where * the user currently is — the retrying-message register (SystemLine's * exact classes), NO horizontal rule. The transcript's quiet note that * history was just summarized; the cut divider below carries the seam. */ export function CompactionMomentDivider({ data, onOpen }: { data: CompactionDividerData; onOpen: () => void }) { return (
); } /** The cut divider (owner round 14): the LONGER divider at the actual * compaction cut — the seam where verbatim history ends and the kept * recent tail begins. Phase-divider's geometry (dotted rules + centered * chip) so it reads as a transcript boundary, not a message. */ export function CompactionCutDivider({ data, onOpen }: { data: CompactionDividerData; onOpen: () => void }) { const kTok = data.details.tokensBefore > 0 ? ` · ${Math.round(data.details.tokensBefore / 1000)}k tok` : ""; return ( ); } /** The dialog's pure body — exported for SSR pins (the delete-dialog / * node-dialog body pattern; the wrapper owns the portal + Esc effect). */ export function CompactionSummaryBody({ summary, onClose }: { summary: CompactionDividerData; onClose: () => void }) { return (
Compacted context
					{summary.content}
				
); } /** The full-summary view both dividers open (owner round 14): the * marker's content verbatim — the compaction header + the summary the * model itself reads — in a scrollable document block. Esc and the * Close row both dismiss; the backdrop click does not (the summary is * reference material, not a decision — an accidental dismissal costs a * re-click, and a stray click-through mid-read costs more). */ export function CompactionSummaryDialog({ summary, onClose, }: { summary: CompactionDividerData | null; onClose: () => void; }) { useEffect(() => { if (!summary) return; const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [summary, onClose]); if (!summary) return null; return createPortal(
, document.body, ); }