- Backend emits session id in SSE; frontend sets activeChat so follow-ups
reuse the same session (fixes fragmented history).
- sessions.summary column; messages past RECENT_LIMIT (10) are folded into
a persisted summary via a non-streaming model call.
- buildMessages sends system(+summary) + last 10 messages, bounding context
while preserving long-range memory.
- Tests: aiMessages (capping + summary injection).
Persist the user message before streaming so the model receives the
current question (previously only the system prompt was sent on new
chats, causing canned greetings). Also fixes user message being lost
when the AI call errors.