From e61167b29068ee6c496a2f254d931f370391e011 Mon Sep 17 00:00:00 2001 From: Ashwin Upadhyay Date: Wed, 3 Jun 2026 17:34:00 +0530 Subject: [PATCH] Hide non-matching threads in chat search (#5651) Fixes #5572. Replaces cmdk's default fuzzy filter with a strict substring-token filter so threads that do not match the query are hidden and the empty state shows. Each item uses its unique thread id as the cmdk value, with the searchable title and preview supplied via keywords. --- .../chat/components/chat-search-dialog.tsx | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/studio/frontend/src/features/chat/components/chat-search-dialog.tsx b/studio/frontend/src/features/chat/components/chat-search-dialog.tsx index 85480359b4..676dcc23d5 100644 --- a/studio/frontend/src/features/chat/components/chat-search-dialog.tsx +++ b/studio/frontend/src/features/chat/components/chat-search-dialog.tsx @@ -16,6 +16,21 @@ import { useEffect } from "react"; import { useChatSearchIndex } from "../hooks/use-chat-search-index"; import { useChatSearchStore } from "../stores/chat-search-store"; +// cmdk's default fuzzy scorer keeps non-matching rows visible (issue #5572), so +// require every whitespace token to be a substring of the item's keywords. +// `value` is the unique thread id (cmdk selection); title/preview come via keywords. +export function chatSearchFilter( + _value: string, + search: string, + keywords?: string[], +): number { + const query = search.trim().toLowerCase(); + if (query === "") return 1; + const haystack = (keywords ?? []).join(" ").toLowerCase(); + const tokens = query.split(/\s+/); + return tokens.every((token) => haystack.includes(token)) ? 1 : 0; +} + function formatRelative(createdAt: number): string { const diff = Date.now() - createdAt; const day = 86_400_000; @@ -52,7 +67,7 @@ export function ChatSearchDialog() { className="corner-squircle top-[25%] w-[635px] max-w-[calc(100%-2rem)] gap-0 p-0 sm:max-w-[635px] border-0 ring-0 shadow-[0_10px_34px_rgba(0,0,0,0.12)] dark:border dark:border-border dark:ring-0 dark:shadow-none" overlayClassName="bg-transparent" > - +
( { navigate({ to: "/chat",