From ddd5c240800cf114109c6772c122580cd3f7ff9d Mon Sep 17 00:00:00 2001 From: msukkari Date: Tue, 29 Jul 2025 14:14:23 -0700 Subject: [PATCH 1/6] Revert "Remove search scope constraint" This reverts commit e69ac0d806960271c3184af00022683eb59b5533. --- .../[domain]/chat/components/newChatPanel.tsx | 1 + .../components/homepage/agenticSearch.tsx | 1 + .../chat/components/chatBox/chatBox.tsx | 83 +++++++++++++++---- .../chat/components/chatThread/chatThread.tsx | 1 + 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/packages/web/src/app/[domain]/chat/components/newChatPanel.tsx b/packages/web/src/app/[domain]/chat/components/newChatPanel.tsx index 699e63bd1..91ae3f960 100644 --- a/packages/web/src/app/[domain]/chat/components/newChatPanel.tsx +++ b/packages/web/src/app/[domain]/chat/components/newChatPanel.tsx @@ -51,6 +51,7 @@ export const NewChatPanel = ({ languageModels={languageModels} selectedSearchScopes={selectedSearchScopes} searchContexts={searchContexts} + onContextSelectorOpenChanged={setIsContextSelectorOpen} />
diff --git a/packages/web/src/features/chat/components/chatBox/chatBox.tsx b/packages/web/src/features/chat/components/chatBox/chatBox.tsx index 5d539bcf7..934199f2e 100644 --- a/packages/web/src/features/chat/components/chatBox/chatBox.tsx +++ b/packages/web/src/features/chat/components/chatBox/chatBox.tsx @@ -5,10 +5,9 @@ import { Button } from "@/components/ui/button"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { CustomEditor, LanguageModelInfo, MentionElement, RenderElementPropsFor, SearchScope } from "@/features/chat/types"; import { insertMention, slateContentToString } from "@/features/chat/utils"; -import { SearchContextQuery } from "@/lib/types"; import { cn, IS_MAC } from "@/lib/utils"; import { computePosition, flip, offset, shift, VirtualElement } from "@floating-ui/react"; -import { ArrowUp, Loader2, StopCircleIcon } from "lucide-react"; +import { ArrowUp, Loader2, StopCircleIcon, TriangleAlertIcon } from "lucide-react"; import { Fragment, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useHotkeys } from "react-hotkeys-hook"; import { Descendant, insertText } from "slate"; @@ -18,6 +17,8 @@ import { SuggestionBox } from "./suggestionsBox"; import { Suggestion } from "./types"; import { useSuggestionModeAndQuery } from "./useSuggestionModeAndQuery"; import { useSuggestionsData } from "./useSuggestionsData"; +import { useToast } from "@/components/hooks/use-toast"; +import { SearchContextQuery } from "@/lib/types"; interface ChatBoxProps { onSubmit: (children: Descendant[], editor: CustomEditor) => void; @@ -29,6 +30,7 @@ interface ChatBoxProps { languageModels: LanguageModelInfo[]; selectedSearchScopes: SearchScope[]; searchContexts: SearchContextQuery[]; + onContextSelectorOpenChanged: (isOpen: boolean) => void; } export const ChatBox = ({ @@ -41,6 +43,7 @@ export const ChatBox = ({ languageModels, selectedSearchScopes, searchContexts, + onContextSelectorOpenChanged, }: ChatBoxProps) => { const suggestionsBoxRef = useRef(null); const [index, setIndex] = useState(0); @@ -67,6 +70,7 @@ export const ChatBox = ({ const { selectedLanguageModel } = useSelectedLanguageModel({ initialLanguageModel: languageModels.length > 0 ? languageModels[0] : undefined, }); + const { toast } = useToast(); // Reset the index when the suggestion mode changes. useEffect(() => { @@ -97,9 +101,9 @@ export const ChatBox = ({ return }, []); - const { isSubmitDisabled } = useMemo((): { + const { isSubmitDisabled, isSubmitDisabledReason } = useMemo((): { isSubmitDisabled: true, - isSubmitDisabledReason: "empty" | "redirecting" | "generating" | "no-language-model-selected" + isSubmitDisabledReason: "empty" | "redirecting" | "generating" | "no-repos-selected" | "no-language-model-selected" } | { isSubmitDisabled: false, isSubmitDisabledReason: undefined, @@ -125,6 +129,13 @@ export const ChatBox = ({ } } + if (selectedSearchScopes.length === 0) { + return { + isSubmitDisabled: true, + isSubmitDisabledReason: "no-repos-selected", + } + } + if (selectedLanguageModel === undefined) { return { @@ -138,11 +149,29 @@ export const ChatBox = ({ isSubmitDisabledReason: undefined, } - }, [editor.children, isRedirecting, isGenerating, selectedLanguageModel]) + }, [ + editor.children, + isRedirecting, + isGenerating, + selectedSearchScopes.length, + selectedLanguageModel, + ]) const onSubmit = useCallback(() => { + if (isSubmitDisabled) { + if (isSubmitDisabledReason === "no-repos-selected") { + toast({ + description: "⚠️ You must select at least one search scope", + variant: "destructive", + }); + onContextSelectorOpenChanged(true); + } + + return; + } + _onSubmit(editor.children, editor); - }, [_onSubmit, editor]); + }, [_onSubmit, editor, isSubmitDisabled, isSubmitDisabledReason, toast, onContextSelectorOpenChanged]); const onInsertSuggestion = useCallback((suggestion: Suggestion) => { switch (suggestion.type) { @@ -281,15 +310,39 @@ export const ChatBox = ({ Stop ) : ( - + + +
{ + // @hack: When submission is disabled, we still want to issue + // a warning to the user as to why the submission is disabled. + // onSubmit on the Button will not be called because of the + // disabled prop, hence the call here. + if (isSubmitDisabled) { + onSubmit(); + } + }} + > + +
+
+ {(isSubmitDisabled && isSubmitDisabledReason === "no-repos-selected") && ( + +
+ + You must select at least one search scope +
+
+ )} +
)}
{suggestionMode !== "none" && ( diff --git a/packages/web/src/features/chat/components/chatThread/chatThread.tsx b/packages/web/src/features/chat/components/chatThread/chatThread.tsx index 943183a74..62e066ac5 100644 --- a/packages/web/src/features/chat/components/chatThread/chatThread.tsx +++ b/packages/web/src/features/chat/components/chatThread/chatThread.tsx @@ -321,6 +321,7 @@ export const ChatThread = ({ languageModels={languageModels} selectedSearchScopes={selectedSearchScopes} searchContexts={searchContexts} + onContextSelectorOpenChanged={setIsContextSelectorOpen} />
Date: Tue, 29 Jul 2025 14:28:06 -0700 Subject: [PATCH 2/6] add llm section to onboard final page --- packages/web/src/app/onboard/page.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/web/src/app/onboard/page.tsx b/packages/web/src/app/onboard/page.tsx index fbc746d92..5fd4a49b2 100644 --- a/packages/web/src/app/onboard/page.tsx +++ b/packages/web/src/app/onboard/page.tsx @@ -14,7 +14,7 @@ import { prisma } from "@/prisma"; import { OrgRole } from "@sourcebot/db"; import { LogoutEscapeHatch } from "@/app/components/logoutEscapeHatch"; import { redirect } from "next/navigation"; -import { BetweenHorizontalStart, GitBranchIcon, LockIcon } from "lucide-react"; +import { BetweenHorizontalStart, Brain, GitBranchIcon, LockIcon } from "lucide-react"; import { hasEntitlement } from "@sourcebot/shared"; import { env } from "@/env.mjs"; import { GcpIapAuth } from "@/app/[domain]/components/gcpIapAuth"; @@ -87,6 +87,13 @@ export default async function Onboarding({ searchParams }: OnboardingProps) { href: "https://docs.sourcebot.dev/docs/connections/overview", icon: , }, + { + id: "language-models", + title: "Language Models", + description: "Learn how to configure your language model providers to start using Ask Sourcebot", + href: "https://docs.sourcebot.dev/docs/configuration/language-model-providers", + icon: , + }, { id: "authentication-system", title: "Authentication System", From 7fa0832927ce0caf4ad26d262dcb6115b3d0ddbf Mon Sep 17 00:00:00 2001 From: msukkari Date: Tue, 29 Jul 2025 14:39:43 -0700 Subject: [PATCH 3/6] add select all button --- .../components/chatBox/searchScopeSelector.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/web/src/features/chat/components/chatBox/searchScopeSelector.tsx b/packages/web/src/features/chat/components/chatBox/searchScopeSelector.tsx index a1c8f5955..63a44cef4 100644 --- a/packages/web/src/features/chat/components/chatBox/searchScopeSelector.tsx +++ b/packages/web/src/features/chat/components/chatBox/searchScopeSelector.tsx @@ -57,6 +57,7 @@ export const SearchScopeSelector = React.forwardRef< ) => { const scrollContainerRef = React.useRef(null); const scrollPosition = React.useRef(0); + const [hasSearchInput, setHasSearchInput] = React.useState(false); const handleInputKeyDown = ( event: React.KeyboardEvent @@ -93,6 +94,10 @@ export const SearchScopeSelector = React.forwardRef< onSelectedSearchScopesChange([]); }; + const handleSelectAll = () => { + onSelectedSearchScopesChange(allSearchScopeItems); + }; + const handleTogglePopover = () => { onOpenChanged(!isOpen); }; @@ -180,10 +185,19 @@ export const SearchScopeSelector = React.forwardRef< setHasSearchInput(!!value)} /> No results found. + {!hasSearchInput && ( +
+ Select all +
+ )} {sortedSearchScopeItems.map(({ item, isSelected }) => { return ( Date: Tue, 29 Jul 2025 15:01:18 -0700 Subject: [PATCH 4/6] add repo snapshot to agentic search and other ui nits --- .../[domain]/components/homepage/agenticSearch.tsx | 11 +++++++++++ .../components/homepage/askSourcebotDemoCards.tsx | 2 +- .../components/homepage/repositorySnapshot.tsx | 3 ++- .../chat/components/chatThread/detailsCard.tsx | 6 +++--- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/web/src/app/[domain]/components/homepage/agenticSearch.tsx b/packages/web/src/app/[domain]/components/homepage/agenticSearch.tsx index 76b2907d0..327cd2977 100644 --- a/packages/web/src/app/[domain]/components/homepage/agenticSearch.tsx +++ b/packages/web/src/app/[domain]/components/homepage/agenticSearch.tsx @@ -13,6 +13,7 @@ import { DemoExamples } from "@/types"; import { AskSourcebotDemoCards } from "./askSourcebotDemoCards"; import { AgenticSearchTutorialDialog } from "./agenticSearchTutorialDialog"; import { setAgenticSearchTutorialDismissedCookie } from "@/actions"; +import { RepositorySnapshot } from "./repositorySnapshot"; interface AgenticSearchProps { searchModeSelectorProps: SearchModeSelectorProps; @@ -80,6 +81,16 @@ export const AgenticSearch = ({
+
+ +
+ +
+ +
+ {demoExamples && ( )} -
+
{/* Example Searches Row */}
diff --git a/packages/web/src/app/[domain]/components/homepage/repositorySnapshot.tsx b/packages/web/src/app/[domain]/components/homepage/repositorySnapshot.tsx index c867fdd0e..5395403d8 100644 --- a/packages/web/src/app/[domain]/components/homepage/repositorySnapshot.tsx +++ b/packages/web/src/app/[domain]/components/homepage/repositorySnapshot.tsx @@ -68,13 +68,14 @@ export function RepositorySnapshot({ return (
- {`Search ${indexedRepos.length} `} + {`${indexedRepos.length} `} {indexedRepos.length > 1 ? 'repositories' : 'repository'} + {` indexed`}
diff --git a/packages/web/src/features/chat/components/chatThread/detailsCard.tsx b/packages/web/src/features/chat/components/chatThread/detailsCard.tsx index bf81a3117..d7b9966a7 100644 --- a/packages/web/src/features/chat/components/chatThread/detailsCard.tsx +++ b/packages/web/src/features/chat/components/chatThread/detailsCard.tsx @@ -6,7 +6,7 @@ import { Separator } from '@/components/ui/separator'; import { Skeleton } from '@/components/ui/skeleton'; import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'; import { cn } from '@/lib/utils'; -import { Brain, ChevronDown, ChevronRight, Clock, Cpu, InfoIcon, Loader2, ScanSearchIcon, Zap } from 'lucide-react'; +import { Brain, ChevronDown, ChevronRight, Clock, Cpu, InfoIcon, Loader2, List, ScanSearchIcon, Zap } from 'lucide-react'; import { MarkdownRenderer } from './markdownRenderer'; import { FindSymbolDefinitionsToolComponent } from './tools/findSymbolDefinitionsToolComponent'; import { FindSymbolReferencesToolComponent } from './tools/findSymbolReferencesToolComponent'; @@ -89,7 +89,7 @@ export const DetailsCard = ({ )} {metadata?.modelName && (
- + {metadata?.modelName}
)} @@ -106,7 +106,7 @@ export const DetailsCard = ({
)}
- + {`${thinkingSteps.length} step${thinkingSteps.length === 1 ? '' : 's'}`}
From 16d6e3edf30d923105d5c4b898cbb20ba8fa08f6 Mon Sep 17 00:00:00 2001 From: msukkari Date: Tue, 29 Jul 2025 15:04:32 -0700 Subject: [PATCH 5/6] refactor demo repo index cta into repo snapshop --- .../homepage/askSourcebotDemoCards.tsx | 165 ++++++++---------- .../homepage/repositorySnapshot.tsx | 15 ++ 2 files changed, 89 insertions(+), 91 deletions(-) diff --git a/packages/web/src/app/[domain]/components/homepage/askSourcebotDemoCards.tsx b/packages/web/src/app/[domain]/components/homepage/askSourcebotDemoCards.tsx index 3208b2b7a..057dcf1b6 100644 --- a/packages/web/src/app/[domain]/components/homepage/askSourcebotDemoCards.tsx +++ b/packages/web/src/app/[domain]/components/homepage/askSourcebotDemoCards.tsx @@ -66,110 +66,93 @@ export const AskSourcebotDemoCards = ({ } return ( - <> - {process.env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === "demo" && ( -

- Interested in using Sourcebot on your code? Check out our{' '} - captureEvent('wa_demo_docs_link_pressed', {})} - > - docs - -

- )} - -
- {/* Example Searches Row */} -
-
-
- -

Community Ask Results

-
+
+ {/* Example Searches Row */} +
+
+
+ +

Community Ask Results

+
- {/* Search Scope Filter */} -
-
-
- -
- -
-
+ {/* Search Scope Filter */} +
+
+
+ +
+ +
- Search Scope:
+ Search Scope: +
+ { + setSelectedFilterSearchScope(null); + }} + > + All + + {demoExamples.searchScopes.map((searchScope) => ( { - setSelectedFilterSearchScope(null); + setSelectedFilterSearchScope(searchScope.id); }} > - All + {getSearchScopeIcon(searchScope, 12, selectedFilterSearchScope === searchScope.id)} + {searchScope.displayName} - {demoExamples.searchScopes.map((searchScope) => ( - { - setSelectedFilterSearchScope(searchScope.id); - }} - > - {getSearchScopeIcon(searchScope, 12, selectedFilterSearchScope === searchScope.id)} - {searchScope.displayName} - - ))} -
+ ))} +
-
- {demoExamples.searchExamples - .filter((example) => { - if (selectedFilterSearchScope === null) return true; - return example.searchScopes.includes(selectedFilterSearchScope); - }) - .map((example) => { - const searchScopes = demoExamples.searchScopes.filter((searchScope) => example.searchScopes.includes(searchScope.id)) - return ( - handleExampleClick(example)} - > - -
-
- {searchScopes.map((searchScope) => ( - - {getSearchScopeIcon(searchScope, 12)} - {searchScope.displayName} - - ))} -
-
-

- {example.title} -

-

- {example.description} -

-
+
+ {demoExamples.searchExamples + .filter((example) => { + if (selectedFilterSearchScope === null) return true; + return example.searchScopes.includes(selectedFilterSearchScope); + }) + .map((example) => { + const searchScopes = demoExamples.searchScopes.filter((searchScope) => example.searchScopes.includes(searchScope.id)) + return ( + handleExampleClick(example)} + > + +
+
+ {searchScopes.map((searchScope) => ( + + {getSearchScopeIcon(searchScope, 12)} + {searchScope.displayName} + + ))}
- - - ) - })} -
+
+

+ {example.title} +

+

+ {example.description} +

+
+
+ + + ) + })}
- +
); }; \ No newline at end of file diff --git a/packages/web/src/app/[domain]/components/homepage/repositorySnapshot.tsx b/packages/web/src/app/[domain]/components/homepage/repositorySnapshot.tsx index 5395403d8..6248a659f 100644 --- a/packages/web/src/app/[domain]/components/homepage/repositorySnapshot.tsx +++ b/packages/web/src/app/[domain]/components/homepage/repositorySnapshot.tsx @@ -16,6 +16,7 @@ import { import { RepoIndexingStatus } from "@sourcebot/db"; import { SymbolIcon } from "@radix-ui/react-icons"; import { RepositoryQuery } from "@/lib/types"; +import { captureEvent } from "@/hooks/useCaptureEvent"; interface RepositorySnapshotProps { repos: RepositoryQuery[]; @@ -78,6 +79,20 @@ export function RepositorySnapshot({ {` indexed`} + {process.env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === "demo" && ( +

+ Interested in using Sourcebot on your code? Check out our{' '} + captureEvent('wa_demo_docs_link_pressed', {})} + > + docs + +

+ )}
) } From 259ca41b6a47bbbfe42a43ec112a44d37a662fd5 Mon Sep 17 00:00:00 2001 From: msukkari Date: Tue, 29 Jul 2025 15:07:24 -0700 Subject: [PATCH 6/6] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea7e39ebe..f80f4a225 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bumped next version. [#406](https://github.com/sourcebot-dev/sourcebot/pull/406) - [ask sb] Improved search code tool with filter options. [#400](https://github.com/sourcebot-dev/sourcebot/pull/400) - [ask sb] Removed search scope constraint. [#400](https://github.com/sourcebot-dev/sourcebot/pull/400) +- [ask sb] Add back search scope requirement and other UI changes. [#411](https://github.com/sourcebot-dev/sourcebot/pull/411) ## [4.6.0] - 2025-07-25