import { Conversation, Message } from './conversation'; export interface ConversationTurns { /** * Every turn, both surfaces. Readonly, so it cannot be handed to a component * that renders a message list — that is the point of it being readonly. * * Use it for questions about the CONVERSATION ("is it used at all?"), never * for questions about a SURFACE ("what should I draw?"). */ all: readonly Message[]; /** Typed turns — what the chat thread draws. */ chat: Message[]; /** Spoken turns — what the voice panel and the transcript draw. */ voice: Message[]; } /** * One place that decides which turns belong to which surface. * * Voice and chat share a single message array; separation is a per-message * marker plus a filter applied by every reader. That makes correctness scale * with the NUMBER OF READERS, which is how the last round of leaks happened — * the message list filtered correctly while four other readers did not, and * nothing failed. * * ★ Deliberately a hook returning memoised arrays rather than a zustand * selector. A selector like `useAssistantStore(s => chatTurns(...))` builds a * fresh array on every call, so `Object.is` never matches and the component * re-renders on every unrelated store change. Subscribing to the array and * filtering in `useMemo` is the version that does not. * * The two filters are separate memos on purpose: a typed turn arriving must not * hand the voice panel a new array identity, or the voice session re-renders * mid-utterance. */ export declare function useConversationTurns(conversation: Conversation | undefined): ConversationTurns; //# sourceMappingURL=useConversationTurns.d.ts.map