Skip to content

Commit 53edd44

Browse files
authored
feat(ask_sb): Add back search scope requirement and other UI changes (#411)
* Revert "Remove search scope constraint" This reverts commit e69ac0d. * add llm section to onboard final page * add select all button * add repo snapshot to agentic search and other ui nits * refactor demo repo index cta into repo snapshop * changelog
1 parent 211ad8f commit 53edd44

File tree

10 files changed

+199
-111
lines changed

10 files changed

+199
-111
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
- Bumped next version. [#406](https://github.com/sourcebot-dev/sourcebot/pull/406)
2525
- [ask sb] Improved search code tool with filter options. [#400](https://github.com/sourcebot-dev/sourcebot/pull/400)
2626
- [ask sb] Removed search scope constraint. [#400](https://github.com/sourcebot-dev/sourcebot/pull/400)
27+
- [ask sb] Add back search scope requirement and other UI changes. [#411](https://github.com/sourcebot-dev/sourcebot/pull/411)
2728

2829
## [4.6.0] - 2025-07-25
2930

packages/web/src/app/[domain]/chat/components/newChatPanel.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const NewChatPanel = ({
5151
languageModels={languageModels}
5252
selectedSearchScopes={selectedSearchScopes}
5353
searchContexts={searchContexts}
54+
onContextSelectorOpenChanged={setIsContextSelectorOpen}
5455
/>
5556
<div className="w-full flex flex-row items-center bg-accent rounded-b-md px-2">
5657
<ChatBoxToolbar

packages/web/src/app/[domain]/components/homepage/agenticSearch.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { DemoExamples } from "@/types";
1313
import { AskSourcebotDemoCards } from "./askSourcebotDemoCards";
1414
import { AgenticSearchTutorialDialog } from "./agenticSearchTutorialDialog";
1515
import { setAgenticSearchTutorialDismissedCookie } from "@/actions";
16+
import { RepositorySnapshot } from "./repositorySnapshot";
1617

1718
interface AgenticSearchProps {
1819
searchModeSelectorProps: SearchModeSelectorProps;
@@ -58,6 +59,7 @@ export const AgenticSearch = ({
5859
languageModels={languageModels}
5960
selectedSearchScopes={selectedSearchScopes}
6061
searchContexts={searchContexts}
62+
onContextSelectorOpenChanged={setIsContextSelectorOpen}
6163
/>
6264
<Separator />
6365
<div className="relative">
@@ -79,6 +81,16 @@ export const AgenticSearch = ({
7981
</div>
8082
</div>
8183

84+
<div className="mt-8">
85+
<RepositorySnapshot
86+
repos={repos}
87+
/>
88+
</div>
89+
90+
<div className="flex flex-col items-center w-fit gap-6">
91+
<Separator className="mt-5 w-[700px]" />
92+
</div>
93+
8294
{demoExamples && (
8395
<AskSourcebotDemoCards
8496
demoExamples={demoExamples}

packages/web/src/app/[domain]/components/homepage/askSourcebotDemoCards.tsx

Lines changed: 74 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -66,110 +66,93 @@ export const AskSourcebotDemoCards = ({
6666
}
6767

6868
return (
69-
<>
70-
{process.env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === "demo" && (
71-
<p className="text-sm text-muted-foreground text-center mt-6">
72-
Interested in using Sourcebot on your code? Check out our{' '}
73-
<a
74-
href="https://docs.sourcebot.dev/docs/overview"
75-
target="_blank"
76-
rel="noopener noreferrer"
77-
className="text-primary hover:underline"
78-
onClick={() => captureEvent('wa_demo_docs_link_pressed', {})}
79-
>
80-
docs
81-
</a>
82-
</p>
83-
)}
84-
85-
<div className="w-full mt-16 space-y-12 px-4 max-w-[1000px]">
86-
{/* Example Searches Row */}
87-
<div className="space-y-4">
88-
<div className="text-center mb-6">
89-
<div className="flex items-center justify-center gap-3 mb-4">
90-
<Search className="h-7 w-7 text-muted-foreground" />
91-
<h3 className="text-2xl font-bold">Community Ask Results</h3>
92-
</div>
69+
<div className="w-full mt-8 space-y-12 px-4 max-w-[1200px]">
70+
{/* Example Searches Row */}
71+
<div className="space-y-4">
72+
<div className="text-center mb-6">
73+
<div className="flex items-center justify-center gap-3 mb-4">
74+
<Search className="h-7 w-7 text-muted-foreground" />
75+
<h3 className="text-2xl font-bold">Community Ask Results</h3>
9376
</div>
77+
</div>
9478

95-
{/* Search Scope Filter */}
96-
<div className="flex flex-wrap items-center justify-center gap-2 mb-6">
97-
<div className="flex items-center gap-2 mr-2">
98-
<div className="relative group">
99-
<Info className="h-4 w-4 text-muted-foreground cursor-help" />
100-
<div className="absolute bottom-6 left-1/2 transform -translate-x-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 z-10 pointer-events-none">
101-
<SearchScopeInfoCard />
102-
<div className="absolute top-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-border"></div>
103-
</div>
79+
{/* Search Scope Filter */}
80+
<div className="flex flex-wrap items-center justify-center gap-2 mb-6">
81+
<div className="flex items-center gap-2 mr-2">
82+
<div className="relative group">
83+
<Info className="h-4 w-4 text-muted-foreground cursor-help" />
84+
<div className="absolute bottom-6 left-1/2 transform -translate-x-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 z-10 pointer-events-none">
85+
<SearchScopeInfoCard />
86+
<div className="absolute top-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-border"></div>
10487
</div>
105-
<span className="text-sm font-medium text-muted-foreground">Search Scope:</span>
10688
</div>
89+
<span className="text-sm font-medium text-muted-foreground">Search Scope:</span>
90+
</div>
91+
<Badge
92+
variant={selectedFilterSearchScope === null ? "default" : "secondary"}
93+
className={`cursor-pointer transition-all duration-200 hover:shadow-sm ${selectedFilterSearchScope === null ? "bg-primary text-primary-foreground" : "hover:bg-secondary/80"
94+
}`}
95+
onClick={() => {
96+
setSelectedFilterSearchScope(null);
97+
}}
98+
>
99+
All
100+
</Badge>
101+
{demoExamples.searchScopes.map((searchScope) => (
107102
<Badge
108-
variant={selectedFilterSearchScope === null ? "default" : "secondary"}
109-
className={`cursor-pointer transition-all duration-200 hover:shadow-sm ${selectedFilterSearchScope === null ? "bg-primary text-primary-foreground" : "hover:bg-secondary/80"
103+
key={searchScope.id}
104+
variant={selectedFilterSearchScope === searchScope.id ? "default" : "secondary"}
105+
className={`cursor-pointer transition-all duration-200 hover:shadow-sm flex items-center gap-1 ${selectedFilterSearchScope === searchScope.id ? "bg-primary text-primary-foreground" : "hover:bg-secondary/80"
110106
}`}
111107
onClick={() => {
112-
setSelectedFilterSearchScope(null);
108+
setSelectedFilterSearchScope(searchScope.id);
113109
}}
114110
>
115-
All
111+
{getSearchScopeIcon(searchScope, 12, selectedFilterSearchScope === searchScope.id)}
112+
{searchScope.displayName}
116113
</Badge>
117-
{demoExamples.searchScopes.map((searchScope) => (
118-
<Badge
119-
key={searchScope.id}
120-
variant={selectedFilterSearchScope === searchScope.id ? "default" : "secondary"}
121-
className={`cursor-pointer transition-all duration-200 hover:shadow-sm flex items-center gap-1 ${selectedFilterSearchScope === searchScope.id ? "bg-primary text-primary-foreground" : "hover:bg-secondary/80"
122-
}`}
123-
onClick={() => {
124-
setSelectedFilterSearchScope(searchScope.id);
125-
}}
126-
>
127-
{getSearchScopeIcon(searchScope, 12, selectedFilterSearchScope === searchScope.id)}
128-
{searchScope.displayName}
129-
</Badge>
130-
))}
131-
</div>
114+
))}
115+
</div>
132116

133-
<div className="flex flex-wrap justify-center gap-3">
134-
{demoExamples.searchExamples
135-
.filter((example) => {
136-
if (selectedFilterSearchScope === null) return true;
137-
return example.searchScopes.includes(selectedFilterSearchScope);
138-
})
139-
.map((example) => {
140-
const searchScopes = demoExamples.searchScopes.filter((searchScope) => example.searchScopes.includes(searchScope.id))
141-
return (
142-
<Card
143-
key={example.url}
144-
className="cursor-pointer transition-all duration-200 hover:shadow-md hover:scale-105 hover:border-primary/50 group w-full max-w-[350px]"
145-
onClick={() => handleExampleClick(example)}
146-
>
147-
<CardContent className="p-4">
148-
<div className="space-y-3">
149-
<div className="flex items-center justify-between">
150-
{searchScopes.map((searchScope) => (
151-
<Badge key={searchScope.value} variant="secondary" className="text-[10px] px-1.5 py-0.5 h-4 flex items-center gap-1">
152-
{getSearchScopeIcon(searchScope, 12)}
153-
{searchScope.displayName}
154-
</Badge>
155-
))}
156-
</div>
157-
<div className="space-y-1">
158-
<h4 className="font-semibold text-sm group-hover:text-primary transition-colors line-clamp-2">
159-
{example.title}
160-
</h4>
161-
<p className="text-xs text-muted-foreground line-clamp-3 leading-relaxed">
162-
{example.description}
163-
</p>
164-
</div>
117+
<div className="flex flex-wrap justify-center gap-3">
118+
{demoExamples.searchExamples
119+
.filter((example) => {
120+
if (selectedFilterSearchScope === null) return true;
121+
return example.searchScopes.includes(selectedFilterSearchScope);
122+
})
123+
.map((example) => {
124+
const searchScopes = demoExamples.searchScopes.filter((searchScope) => example.searchScopes.includes(searchScope.id))
125+
return (
126+
<Card
127+
key={example.url}
128+
className="cursor-pointer transition-all duration-200 hover:shadow-md hover:scale-105 hover:border-primary/50 group w-full max-w-[350px]"
129+
onClick={() => handleExampleClick(example)}
130+
>
131+
<CardContent className="p-4">
132+
<div className="space-y-3">
133+
<div className="flex items-center justify-between">
134+
{searchScopes.map((searchScope) => (
135+
<Badge key={searchScope.value} variant="secondary" className="text-[10px] px-1.5 py-0.5 h-4 flex items-center gap-1">
136+
{getSearchScopeIcon(searchScope, 12)}
137+
{searchScope.displayName}
138+
</Badge>
139+
))}
165140
</div>
166-
</CardContent>
167-
</Card>
168-
)
169-
})}
170-
</div>
141+
<div className="space-y-1">
142+
<h4 className="font-semibold text-sm group-hover:text-primary transition-colors line-clamp-2">
143+
{example.title}
144+
</h4>
145+
<p className="text-xs text-muted-foreground line-clamp-3 leading-relaxed">
146+
{example.description}
147+
</p>
148+
</div>
149+
</div>
150+
</CardContent>
151+
</Card>
152+
)
153+
})}
171154
</div>
172155
</div>
173-
</>
156+
</div>
174157
);
175158
};

packages/web/src/app/[domain]/components/homepage/repositorySnapshot.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
import { RepoIndexingStatus } from "@sourcebot/db";
1717
import { SymbolIcon } from "@radix-ui/react-icons";
1818
import { RepositoryQuery } from "@/lib/types";
19+
import { captureEvent } from "@/hooks/useCaptureEvent";
1920

2021
interface RepositorySnapshotProps {
2122
repos: RepositoryQuery[];
@@ -68,15 +69,30 @@ export function RepositorySnapshot({
6869
return (
6970
<div className="flex flex-col items-center gap-3">
7071
<span className="text-sm">
71-
{`Search ${indexedRepos.length} `}
72+
{`${indexedRepos.length} `}
7273
<Link
7374
href={`${domain}/repos`}
7475
className="text-link hover:underline"
7576
>
7677
{indexedRepos.length > 1 ? 'repositories' : 'repository'}
7778
</Link>
79+
{` indexed`}
7880
</span>
7981
<RepositoryCarousel repos={indexedRepos} />
82+
{process.env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === "demo" && (
83+
<p className="text-sm text-muted-foreground text-center">
84+
Interested in using Sourcebot on your code? Check out our{' '}
85+
<a
86+
href="https://docs.sourcebot.dev/docs/overview"
87+
target="_blank"
88+
rel="noopener noreferrer"
89+
className="text-primary hover:underline"
90+
onClick={() => captureEvent('wa_demo_docs_link_pressed', {})}
91+
>
92+
docs
93+
</a>
94+
</p>
95+
)}
8096
</div>
8197
)
8298
}

packages/web/src/app/onboard/page.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { prisma } from "@/prisma";
1414
import { OrgRole } from "@sourcebot/db";
1515
import { LogoutEscapeHatch } from "@/app/components/logoutEscapeHatch";
1616
import { redirect } from "next/navigation";
17-
import { BetweenHorizontalStart, GitBranchIcon, LockIcon } from "lucide-react";
17+
import { BetweenHorizontalStart, Brain, GitBranchIcon, LockIcon } from "lucide-react";
1818
import { hasEntitlement } from "@sourcebot/shared";
1919
import { env } from "@/env.mjs";
2020
import { GcpIapAuth } from "@/app/[domain]/components/gcpIapAuth";
@@ -87,6 +87,13 @@ export default async function Onboarding({ searchParams }: OnboardingProps) {
8787
href: "https://docs.sourcebot.dev/docs/connections/overview",
8888
icon: <GitBranchIcon className="w-4 h-4" />,
8989
},
90+
{
91+
id: "language-models",
92+
title: "Language Models",
93+
description: "Learn how to configure your language model providers to start using Ask Sourcebot",
94+
href: "https://docs.sourcebot.dev/docs/configuration/language-model-providers",
95+
icon: <Brain className="w-4 h-4" />,
96+
},
9097
{
9198
id: "authentication-system",
9299
title: "Authentication System",

0 commit comments

Comments
 (0)