"use client"; import { use, useState, useRef } from "react"; import { ArrowLeft, Send, Loader2 } from "lucide-react"; import Link from "next/link"; import { useSession, useMessages } from "@/lib/hooks"; import { timeAgo, formatTokens, platformBadgeClass } from "@/lib/utils"; import { MessageBubble } from "@/components/MessageBubble"; import { useQueryClient } from "@tanstack/react-query"; export default function SessionReplayPage({ params }: { params: Promise<{ id: string }> }) { const { id } = use(params); const qc = useQueryClient(); const { data: sessionData } = useSession(id); const { data: messagesData, isLoading } = useMessages(id); const [input, setInput] = useState(""); const [sending, setSending] = useState(false); const [pendingMsg, setPendingMsg] = useState(null); const inputRef = useRef(null); const session = sessionData?.session; const messages = messagesData?.items || []; const visibleMessages = messages .filter((m) => m.role === "user" || m.role === "assistant") .reverse(); const toolResults = new Map(); for (const m of messages) { if (m.role === "tool" && m.tool_call_id) { toolResults.set(m.tool_call_id, { name: m.tool_name || "tool", content: m.content || "", }); } } const sendMessage = async () => { if (!input.trim() || sending) return; const msg = input.trim(); setInput(""); setSending(true); setPendingMsg(msg); try { await fetch("/api/sessions/" + id + "/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: msg }), }); } catch {} setPendingMsg(null); setSending(false); qc.invalidateQueries({ queryKey: ["messages", id] }); qc.invalidateQueries({ queryKey: ["session", id] }); }; return (
{/* Header */}
{session?.title || "Session " + id.slice(0, 8)}
{session && (
{session.source} {session.message_count} msgs · {formatTokens(session.input_tokens + session.output_tokens)} · {timeAgo(session.started_at)}
)}
{/* Message input */}
setInput(e.target.value)} onKeyDown={(e) => e.key === "Enter" && sendMessage()} placeholder={sending ? "Hermes is thinking..." : "Send a message..."} className="flex-1 px-4 py-2.5 rounded-xl text-sm outline-none transition-colors" style={{ background: "var(--bg-raised)", border: "1px solid var(--border)", color: "var(--text-1)", }} disabled={sending} />
{/* Messages - newest first */} {isLoading ? (
{[...Array(4)].map((_, i) => (
))}
) : (
{/* Pending thinking indicator */} {sending && (
Thinking...
)} {/* Pending user message */} {pendingMsg && (

{pendingMsg}

)} {visibleMessages.map((m) => ( ))} {visibleMessages.length === 0 && !sending && (

Empty session

)}
)}
); }