"use client"; import React, { useEffect, useRef, useState } from "react"; import { audioBlobURLFromBase64, BACKEND_URL, Citation, ChatMessage, CompareResponse, CoverageResponse, getCompare, getCoverage, getHealth, getInsurerReviews, getMarketplace, getPredictedPremiumBand, getProfileCompleteness, getScorecard, InsurerReviews, MarketplacePolicy, MarketplaceResponse, postChat, postPremiumEstimate, postProfileUpdate, postSessionClear, postTranscribe, PremiumEstimateResponse, PredictedPremiumBandResponse, ProfileCompletenessResponse, ScorecardResponse, uploadPolicy, UserProfile, } from "@/lib/api"; import { translate, UILang, StringKey, GLOSSARY } from "@/lib/i18n"; import PolicyCompareModal, { parseScorecardFacts, SnapshotView, GlossaryTip, fmtSumInsured } from "@/components/PolicyCompareModal"; import PolicyPremiumWidget from "@/components/PolicyPremiumWidget"; import PolicyScorecardWidget from "@/components/PolicyScorecardWidget"; import type { PremiumBulkProfile, BulkScorecardProfile } from "@/lib/api"; // KI-168 (2026-05-15) — voice path migrated from custom-VAD `useLiveConversation` // to native browser SpeechRecognition via `useStreamingVoice`. The old hook // remains on disk as a graveyard reference until KI-168 is field-verified. import { useStreamingVoice } from "@/lib/useStreamingVoice"; import { useIsTouch } from "@/lib/useIsTouch"; import HelpTip from "@/components/HelpTip"; type DisplayMessage = ChatMessage & { id: string; citations?: Citation[]; audioUrl?: string; brain?: string; latencyMs?: number; blocked?: boolean; // KI-278 (2026-05-16) — when the backend couldn't synthesize voice for // this reply (e.g. Sarvam 429 / out of credits), it ships a friendly // explanation here. Rendered as a small inline notice under the bubble // so a voice-less reply never looks broken/unexplained. ttsNotice?: string; }; export default function Page() { const [messages, setMessages] = useState([]); const [input, setInput] = useState(""); const [busy, setBusy] = useState(false); // Voice-display fix — the composer