* fix(#584): follow stream without freezing (persistent snapshotFlow)
The auto-scroll LaunchedEffect was keyed on (messages.size,
streamingMessage?.content?.length, isThinking) — those change on EVERY
streamed token, so the effect restarted per token and cancelled the
in-flight animateScrollToItem, leaving the view stuck/frozen mid-stream.
Replace it with a single persistent LaunchedEffect(Unit) + snapshotFlow +
collectLatest. The streaming follow now uses an instant scrollToBottom
(animated=false) which is idempotent per token and has no animation to
cancel; a discrete new message arriving while at the bottom still animates.
Because the effect runs once, mirror the params through rememberUpdatedState
and read them live inside snapshotFlow/collectLatest so the flow actually
fires per token and session-switch detection uses the current session id
(rather than stale first-composition closure captures).
* fix(#584): leave scroll free during streaming (no auto-follow)
m57 follow-up: the previous fix stopped the freeze but still force-pinned
to the bottom while streaming. Now, while a message is streaming, the
scroll is left completely free — no auto-follow of the streaming message —
so the user can scroll up/down to read while it generates.
Auto-scroll only on explicit actions (send / FAB / session switch) and when
a discrete non-streaming message lands while already pinned to the bottom.
streamingMessage is dropped from the snapshotFlow keys so the flow no
longer churns per token.
---------
Co-authored-by: M57 <m57@hermes-control.app>