diff --git a/apps/client/src/features/search/components/ai-search-result.tsx b/apps/client/src/features/search/components/ai-search-result.tsx index cf67fb0b..b1a3db00 100644 --- a/apps/client/src/features/search/components/ai-search-result.tsx +++ b/apps/client/src/features/search/components/ai-search-result.tsx @@ -4,6 +4,8 @@ import { IconSparkles, IconFileText } from "@tabler/icons-react"; import { Link } from "react-router-dom"; import { IAiSearchResponse } from "../services/ai-search-service"; import { buildPageUrl } from "@/features/page/page.utils"; +import { markdownToHtml } from "@docmost/editor-ext"; +import DOMPurify from "dompurify"; interface AiSearchResultProps { result: IAiSearchResponse; @@ -14,7 +16,7 @@ export function AiSearchResult({ result, isLoading }: AiSearchResultProps) { // Deduplicate sources by pageId, keeping the one with highest similarity const deduplicatedSources = useMemo(() => { if (!result?.sources) return []; - + const pageMap = new Map(); result.sources.forEach((source) => { const existing = pageMap.get(source.pageId); @@ -22,7 +24,7 @@ export function AiSearchResult({ result, isLoading }: AiSearchResultProps) { pageMap.set(source.pageId, source); } }); - + return Array.from(pageMap.values()); }, [result?.sources]); @@ -46,11 +48,17 @@ export function AiSearchResult({ result, isLoading }: AiSearchResultProps) { - AI Answer + + AI Answer + - - {result.answer} - + {deduplicatedSources.length > 0 && ( @@ -63,10 +71,10 @@ export function AiSearchResult({ result, isLoading }: AiSearchResultProps) { key={source.pageId} component={Link} to={buildPageUrl(source.spaceSlug, source.slugId, source.title)} - style={{ + style={{ textDecoration: "none", color: "inherit", - display: "block" + display: "block", }} > ); -} \ No newline at end of file +} diff --git a/apps/client/src/features/search/components/search-spotlight.tsx b/apps/client/src/features/search/components/search-spotlight.tsx index 077952d9..b1869af5 100644 --- a/apps/client/src/features/search/components/search-spotlight.tsx +++ b/apps/client/src/features/search/components/search-spotlight.tsx @@ -28,7 +28,6 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) { contentType: "page", }); const [isAiMode, setIsAiMode] = useState(false); - const [triggerAiSearch, setTriggerAiSearch] = useState(false); // Build unified search params const searchParams = useMemo(() => { @@ -49,10 +48,7 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) { searchParams, !isAiMode // Disable regular search when in AI mode ); - const { data: aiSearchResult, isLoading: isAiLoading, refetch: refetchAiSearch } = useAiSearch( - searchParams, - isAiMode && triggerAiSearch - ); + const { data: aiSearchResult, isPending: isAiLoading, mutate: triggerAiSearchMutation } = useAiSearch(); // Determine result type for rendering const isAttachmentSearch = @@ -72,16 +68,12 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) { }; const handleAskClick = () => { - const newMode = !isAiMode; - setIsAiMode(newMode); - // Reset AI search state when toggling modes - setTriggerAiSearch(false); + setIsAiMode(!isAiMode); }; const handleAiSearchTrigger = () => { if (query.trim() && isAiMode) { - setTriggerAiSearch(true); - refetchAiSearch(); + triggerAiSearchMutation(searchParams); } }; diff --git a/apps/client/src/features/search/hooks/use-ai-search.ts b/apps/client/src/features/search/hooks/use-ai-search.ts index 6c70b428..872e77cf 100644 --- a/apps/client/src/features/search/hooks/use-ai-search.ts +++ b/apps/client/src/features/search/hooks/use-ai-search.ts @@ -1,21 +1,11 @@ -import { useQuery, UseQueryResult } from "@tanstack/react-query"; +import { useMutation, UseMutationResult } from "@tanstack/react-query"; import { askAi, IAiSearchResponse } from "@/features/search/services/ai-search-service"; import { IPageSearchParams } from "@/features/search/types/search.types"; -import { useLicense } from "@/ee/hooks/use-license"; -export function useAiSearch( - params: IPageSearchParams, - enabled: boolean = false, -): UseQueryResult { - const { hasLicenseKey } = useLicense(); - - return useQuery({ - queryKey: ["ai-search", params], - queryFn: async () => { +export function useAiSearch(): UseMutationResult { + return useMutation({ + mutationFn: async (params: IPageSearchParams) => { return await askAi(params); }, - enabled: !!params.query && hasLicenseKey && enabled, - staleTime: Infinity, // Don't refetch automatically - gcTime: 0, // Don't cache results when component unmounts }); } \ No newline at end of file diff --git a/apps/server/src/core/search/search.service.ts b/apps/server/src/core/search/search.service.ts index 0f8dbb90..29508797 100644 --- a/apps/server/src/core/search/search.service.ts +++ b/apps/server/src/core/search/search.service.ts @@ -62,7 +62,7 @@ export class SearchService { ) .where('deletedAt', 'is', null) .orderBy('rank', 'desc') - .limit(searchParams.limit | 20) + .limit(searchParams.limit | 25) .offset(searchParams.offset || 0); if (!searchParams.shareId) {