Files
multica/server/migrations/145_chat_read_cursor.down.sql
Lambda 68cd730fec feat(chat): Chat V2 — first-class IM-style Chat tab (MUL-4171)
Replace the floating chat FAB/window with a first-class Chat tab under
Inbox, laid out as an IM-style two-pane surface (thread list + conversation).

Highlights:
- New Chat page (packages/views/chat/chat-page.tsx) with URL-addressable
  session selection; web + desktop routing wired up. Removes the old
  chat-fab / chat-window / resize-handles / context-items paths.
- IM thread list: agent avatar + last-message preview + IM timestamp, red
  unread *count* badge (read-cursor model), presence-gated typing vs waiting.
  Rename lives only in the conversation header ⋯ menu (not the list hover).
- Per-session conversation header (rename / view agent / delete), agent-aware
  empty state (avatar + name + description + starter prompts), and a
  deterministic clean-title derivation from the first message.
- Server: read-cursor unread model (migration 145) and per-user pinned agents
  (migration 146, dedicated chat_pinned_agent table + handler/queries).
  New-agent welcome chat auto-enqueues a real agent run (LLM intro, no
  static template).
- Design: fade the global --border token; borderless list headers on
  Chat/Inbox, kept (faded) on the conversation header.

Verified: pnpm typecheck (all packages), go build ./..., go vet, gofmt.
Co-authored-by: multica-agent <github@multica.ai>
2026-07-08 15:12:57 +08:00

17 lines
627 B
SQL

ALTER TABLE chat_session ADD COLUMN unread_since TIMESTAMPTZ;
-- Best-effort restore of the boolean flag: any session with an assistant
-- message after its read cursor is stamped unread at the earliest such message.
UPDATE chat_session cs
SET unread_since = sub.first_unread
FROM (
SELECT m.chat_session_id, min(m.created_at) AS first_unread
FROM chat_message m
JOIN chat_session s ON s.id = m.chat_session_id
WHERE m.role = 'assistant' AND m.created_at > s.last_read_at
GROUP BY m.chat_session_id
) sub
WHERE cs.id = sub.chat_session_id;
ALTER TABLE chat_session DROP COLUMN last_read_at;