perf(search): cap Cmd-K result groups so typing isn't blocked by reshuffle#5597
Conversation
…uffle Every result group re-rendered its full match set on each keystroke — the catalog alone is 1,000+ tool operations, plus all workflows/files in large workspaces — so the deferred re-render that reshuffles results stalls the input and drops the next character. Add a per-group cap (filterAndCap, MAX_RESULTS_PER_GROUP=50) applied to every variable-size group. Results are already score-sorted, so the cap only trims the low-relevance tail while keeping the DOM and per-keystroke reconciliation bounded. No UX changes.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryLow Risk Overview While the user is searching, each result group now uses Unit tests cover name-first ordering and cap behavior (active search capped, browse uncapped, whitespace treated as browse). Reviewed by Cursor Bugbot for commit 54a0129. Configure here. |
Greptile SummaryThis PR improves Cmd-K search performance and ranking. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (5): Last reviewed commit: "fix(search): keep integrations catalog h..." | Re-trigger Greptile |
…e list Keep the empty state byte-for-byte identical to before — capping applies only to the top-ranked matches of an active query (the reshuffling per-keystroke render that stalls input), never to the full browsable list. No browsable result a user could otherwise see is hidden.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 3107b1b. Configure here.
Blocks and tools were ranked against their full searchValue (name + type + every command-searchable option label), so an exact name match couldn't earn the exact-match bonus and paid a length penalty inflated by option text — e.g. "Agent" lost to "Pi Coding Agent" for the query "agent". Rank by name first via a new optional secondary accessor on filterAndSort/filterAndCap, falling back to searchValue only when the name doesn't match, so an exact name match always wins while a block stays findable by an option label.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit ee6df29. Configure here.
A whitespace-only query (e.g. a single space) was truthy, so it both filtered (a space matches the spaces in multi-word labels) and capped large groups to 50 while the palette looked empty. Trim the query at the source in filterAndSort so every caller treats whitespace-only as browse, and decide the cap on the trimmed query — whitespace-only input now returns the full, unfiltered browse state.
|
@cursor review |
The filteredIntegrations guard used the raw deferredSearch, so a whitespace-only value passed it while filterAndCap trimmed the same value to browse and returned the full catalog. Guard on deferredSearch.trim() to match the trimmed-emptiness semantics — the catalog stays hidden until the user types something meaningful.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 54a0129. Configure here.
Summary
Two closely-related fixes to the Cmd-K command palette search:
1. Input latency (perf). Typing stalled and dropped the next character while results reshuffle, because every result group re-rendered its full match set each keystroke — the catalog alone is 1,000+ tool operations, plus every workflow/file in large workspaces. Added a per-group cap (
filterAndCap,MAX_RESULTS_PER_GROUP = 50) applied only while searching. Results are score-sorted, so the cap trims just the low-relevance tail; the empty/browse state is returned in full (no browsable item is hidden).2. Exact name matches now win (ranking). Blocks/tools were ranked against their full
searchValue(name + type + every command-searchable option label), so an exact name match couldn't earn the exact-match bonus and paid a length penalty inflated by option text — e.g.Agentlost toPi Coding Agentfor the query "agent". Now ranked by name first, falling back tosearchValueonly when the name doesn't match (via a new optional secondary accessor onfilterAndSort/filterAndCap), so an exact name match always wins while a block stays findable by an option label.Minimal and self-contained: no UX/layout changes, no new components; single-field ranking (workflows, files, etc.) is byte-identical.
Type of Change
Testing
filterAndCap(caps active search, never caps the browse state, preserves ranking) and name-first ranking (exact name beats a substring buried in another item's option text; still findable by option label).utils.test.tspasses (24 tests).Checklist