mirror of
https://github.com/coder/coder.git
synced 2026-09-22 13:10:21 +08:00
Stacked on `feat/chat-cache-semantic-ops`. ## Bug Chat search results (`chatSearch` queries) were never invalidated, so the search dialog served stale results after archives, renames, deletions, new chats, message edits, and watch-driven status changes. ## Fix Reintroduces `invalidateChatSearches`, a prefix invalidation over the module-private `chatSearchFamilyKey`, and wires it into: - `chats.ts`: `archiveChat.onSettled`, `unarchiveChat.onSettled`, `updateChatTitle.onSettled`, `editChatMessage.onSettled`, `createChat.onSuccess` - `useChatStore.ts`: `upsertCacheMessages` (unconditional; assistant message bodies are indexed too) and `replaceCacheMessages` - `AgentsPageLayout.tsx`: the `deleted` and root `created` watch branches, the merge watch branch (gated by a new exported `shouldInvalidateChatSearches` helper), the `has_unread` clearing effect, the `onOpen` reconnect convergence, and `archiveAndDeleteMutation.onSuccess` The merge-branch gate only invalidates for search-affecting event kinds (`title_change`, `status_change`, `diff_status_change`, `action_required`). `summary_change`, `chat_summary_change`, and `context_dirty` are excluded: stale `last_turn_summary` subtitles are accepted until reconciliation lands. ## Backend constraint Message bodies only enter full-text search via the dbpurge backfill (`search_tsv` starts NULL and is populated every 10 minutes). Frontend invalidation fixes removals, ordering, and rendered fields immediately, but a chat that newly matches on message body will not appear until the next backfill. This is a server-side eventual-consistency limit we accept. ## Scope decisions (confirmed) - No invalidation in `createChatMessage.onSuccess`: the send path already routes through `useChatStore.upsertCacheMessages`; adding both would double-invalidate every send. - No invalidation for `pinChat`/`unpinChat`/`reorderPinnedChat` (ordering-only, self-heals). - ACL mutations out of scope. - No coalescing/debouncing; that belongs to a later reconciler PR. ## Tests - Prefix invalidation: multiple distinct `q` params invalidated, bystanders (list, by-workspace, entity, messages, cost tree) untouched. - Mutation wiring: settlement of `archiveChat`, `unarchiveChat`, `updateChatTitle`, `editChatMessage`, and `createChat` invalidates a seeded search key; `createChatMessage` asserted NOT to. - `shouldInvalidateChatSearches` unit-tested over all `ChatWatchEventKind` values. PR generated by Coder Agents.