Skip to content

perf(search): cap Cmd-K result groups so typing isn't blocked by reshuffle#5597

Merged
waleedlatif1 merged 5 commits into
stagingfrom
perf/cmdk-input-latency
Jul 11, 2026
Merged

perf(search): cap Cmd-K result groups so typing isn't blocked by reshuffle#5597
waleedlatif1 merged 5 commits into
stagingfrom
perf/cmdk-input-latency

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

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. Agent lost to Pi Coding Agent for the query "agent". Now ranked by name first, falling back to searchValue only when the name doesn't match (via a new optional secondary accessor on filterAndSort/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

  • Bug fix (performance + ranking)

Testing

  • Unit tests for 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.ts passes (24 tests).
  • Typecheck + lint clean.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…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.
@vercel

vercel Bot commented Jul 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 11, 2026 6:45pm

Request Review

@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Search-modal filtering and ranking only; no auth, data, or API changes. Main tradeoff is matches ranked below the top 50 per group may be hidden while typing.

Overview
Fixes Cmd-K typing lag and block/tool ranking by changing how search results are filtered and capped.

While the user is searching, each result group now uses filterAndCap (50 rows max, score-sorted) instead of rendering every match on every keystroke; empty or whitespace-only input still returns the full browse list unchanged. filterAndSort trims queries, and blocks/tools rank on name first with searchValue as a secondary field so an exact Agent name beats Pi Coding Agent when the query is agent, while option labels like gpt-4o still surface items. Catalog integrations only show when deferredSearch.trim() is non-empty.

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-apps

greptile-apps Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves Cmd-K search performance and ranking. The main changes are:

  • Caps each result group while an active search is running.
  • Keeps empty and whitespace-only browse states uncapped.
  • Ranks block and tool names before secondary search text.
  • Hides catalog integrations until the user enters a meaningful query.
  • Adds tests for capping, whitespace handling, and name-first ranking.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx Updates command palette groups to use capped search results and applies trimmed query checks for catalog integrations.
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/utils.ts Adds capped filtering, trims search input for browse mode, and supports name-first ranking with secondary fallback text.
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/utils.test.ts Adds tests for capped active search, uncapped browse states, whitespace input, and secondary search ranking.

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.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@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.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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.

@waleedlatif1 waleedlatif1 merged commit 67a2f00 into staging Jul 11, 2026
18 checks passed
@waleedlatif1 waleedlatif1 deleted the perf/cmdk-input-latency branch July 11, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant