6b3eb247a358361e31b4821ba151cef2d3bbf977
Completes the turn/session decoupling so nothing is lost across disconnects. Phase 2 (durability): - New chat_session_events table (global monotonic id = cursor) + queries appendChatEvent / getChatEventsSince / pruneChatEventsOlderThan. - Every durable outbound ServerMessage now goes through emitToSession: appended to the queue (even while the client is disconnected) and delivered live with its seq. Streaming deltas stay ephemeral (live-only, never persisted). Phase 3 (resilient transport): - New 'resume-cursor' client message → handleResumeCursor re-binds the socket to the (still-live) session (cancels idle-GC via attachWs) and replays every event since the client's cursor. - useChatWebSocket already auto-reconnects; added an onOpen hook. useChat tracks the max seq and, on every (re)connect with an established session, sends resume-cursor — so a dropped connection self-heals with no manual navigate away/back, and background task notifications that landed while offline replay. Verified end-to-end: disconnect after a turn's result but before a background task finishes, reconnect with the cursor → the missed task:notification is replayed from Postgres, no duplicates. Note: the DB is managed via drizzle push/direct DDL (no __drizzle_migrations table), so 0001 was applied directly; the generated migration is committed for the record. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Description
No description provided
42 MiB
Languages
TypeScript
90.9%
Shell
4.7%
JavaScript
4.1%
CSS
0.2%
HTML
0.1%