- Add 21-06-SUMMARY.md documenting search filtering and keyboard shortcut - Advance STATE.md to ready_for_verification, 100% progress - ROADMAP.md phase 21 marked Complete (7/7 summaries)
68 lines
3.3 KiB
Markdown
68 lines
3.3 KiB
Markdown
---
|
|
phase: 21-chat-foundation
|
|
plan: "06"
|
|
subsystem: chat
|
|
tags: [chat, search, keyboard-shortcuts, filtering]
|
|
dependency_graph:
|
|
requires: []
|
|
provides: [HIST-02, INPUT-07]
|
|
affects: [ChatConversationList, useChatConversations, chatApi, chatService, chatRoutes, useKeyboardShortcuts, Layout]
|
|
tech_stack:
|
|
added: []
|
|
patterns: [custom-event-bus, debounced-input, ilike-filter, global-keyboard-shortcut]
|
|
key_files:
|
|
created: []
|
|
modified:
|
|
- server/src/services/chat.ts
|
|
- server/src/routes/chat.ts
|
|
- ui/src/api/chat.ts
|
|
- ui/src/hooks/useChatConversations.ts
|
|
- ui/src/components/ChatConversationList.tsx
|
|
- ui/src/hooks/useKeyboardShortcuts.ts
|
|
- ui/src/components/Layout.tsx
|
|
decisions:
|
|
- "Used custom window event (nexus:focus-chat-search) instead of forwardRef drilling to focus search input from Cmd+K — avoids threading refs through ChatPanel"
|
|
- "Debounce search at 300ms via useEffect+setTimeout pattern to avoid flooding the server with requests on every keystroke"
|
|
- "Cmd+K handler placed before the input-guard early return in useKeyboardShortcuts so it fires even when typing in inputs/textareas"
|
|
metrics:
|
|
duration: "~10 min"
|
|
completed: "2026-04-01"
|
|
tasks: 2
|
|
files: 7
|
|
---
|
|
|
|
# Phase 21 Plan 06: Chat Search and Cmd+K Shortcut Summary
|
|
|
|
Gap closure for HIST-02 (conversation search) and INPUT-07 (Cmd+K keyboard shortcut): server-side ilike filtering on conversation titles with a debounced search input, plus Cmd+K to open chat panel and focus search.
|
|
|
|
## What Was Built
|
|
|
|
### Task 1: Server-side search and agentId filtering
|
|
- `chatService.listConversations` extended with `search?: string` and `agentId?: string` opts; adds `ilike(chatConversations.title, '%term%')` and `eq(chatConversations.agentId, id)` conditions when provided
|
|
- `GET /companies/:companyId/conversations` route extracts `search` and `agentId` from `req.query`
|
|
- `chatApi.listConversations` serializes `search` and `agentId` as URL query params
|
|
- `useChatConversations` accepts `opts?: { search?: string }`, includes search in queryKey (triggers refetch on change), passes to API
|
|
|
|
### Task 2: Search input UI and Cmd+K shortcut
|
|
- `ChatConversationList` renders a search input with Search icon (left) and clear X button (right); 300ms debounce; passes debouncedSearch to `useChatConversations`
|
|
- `ChatConversationList` listens for `nexus:focus-chat-search` custom window event to focus the input
|
|
- `useKeyboardShortcuts` adds `onSearch?: () => void` to `ShortcutHandlers`; Cmd+K/Ctrl+K handler is placed BEFORE the input-guard early return (fires globally)
|
|
- `Layout` wires `onSearch` to open chat panel if closed, then dispatches `nexus:focus-chat-search` via `requestAnimationFrame`
|
|
|
|
## Verification Results
|
|
|
|
- TypeScript: no new chat-related errors in server or UI (pre-existing plugin-sdk errors in plugins.ts are out of scope)
|
|
- All tests pass: chat-service (21), chat-routes (11), ChatMarkdownMessage (4), ChatInput (6) — 42 total
|
|
- Search input present with placeholder "Search conversations..."
|
|
- Cmd+K handler on `metaKey || ctrlKey` + `k` in useKeyboardShortcuts
|
|
- Route passes search/agentId params
|
|
|
|
## Deviations from Plan
|
|
|
|
None — plan executed exactly as written. Used the simpler custom-event approach (suggested as ALTERNATIVE in plan) rather than forwardRef/useImperativeHandle, as plan explicitly recommended this path.
|
|
|
|
## Known Stubs
|
|
|
|
None.
|
|
|
|
## Self-Check: PASSED
|