Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const NewChatPanel = ({
languageModels={languageModels}
selectedSearchScopes={selectedSearchScopes}
searchContexts={searchContexts}
onContextSelectorOpenChanged={setIsContextSelectorOpen}
/>
<div className="w-full flex flex-row items-center bg-accent rounded-b-md px-2">
<ChatBoxToolbar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -58,6 +59,7 @@ export const AgenticSearch = ({
languageModels={languageModels}
selectedSearchScopes={selectedSearchScopes}
searchContexts={searchContexts}
onContextSelectorOpenChanged={setIsContextSelectorOpen}
/>
<Separator />
<div className="relative">
Expand All @@ -79,6 +81,16 @@ export const AgenticSearch = ({
</div>
</div>

<div className="mt-8">
<RepositorySnapshot
repos={repos}
/>
</div>

<div className="flex flex-col items-center w-fit gap-6">
<Separator className="mt-5 w-[700px]" />
</div>

{demoExamples && (
<AskSourcebotDemoCards
demoExamples={demoExamples}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,110 +66,93 @@ export const AskSourcebotDemoCards = ({
}

return (
<>
{process.env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === "demo" && (
<p className="text-sm text-muted-foreground text-center mt-6">
Interested in using Sourcebot on your code? Check out our{' '}
<a
href="https://docs.sourcebot.dev/docs/overview"
target="_blank"
rel="noopener noreferrer"
className="text-primary hover:underline"
onClick={() => captureEvent('wa_demo_docs_link_pressed', {})}
>
docs
</a>
</p>
)}

<div className="w-full mt-16 space-y-12 px-4 max-w-[1000px]">
{/* Example Searches Row */}
<div className="space-y-4">
<div className="text-center mb-6">
<div className="flex items-center justify-center gap-3 mb-4">
<Search className="h-7 w-7 text-muted-foreground" />
<h3 className="text-2xl font-bold">Community Ask Results</h3>
</div>
<div className="w-full mt-8 space-y-12 px-4 max-w-[1200px]">
{/* Example Searches Row */}
<div className="space-y-4">
<div className="text-center mb-6">
<div className="flex items-center justify-center gap-3 mb-4">
<Search className="h-7 w-7 text-muted-foreground" />
<h3 className="text-2xl font-bold">Community Ask Results</h3>
</div>
</div>

{/* Search Scope Filter */}
<div className="flex flex-wrap items-center justify-center gap-2 mb-6">
<div className="flex items-center gap-2 mr-2">
<div className="relative group">
<Info className="h-4 w-4 text-muted-foreground cursor-help" />
<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">
<SearchScopeInfoCard />
<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>
</div>
{/* Search Scope Filter */}
<div className="flex flex-wrap items-center justify-center gap-2 mb-6">
<div className="flex items-center gap-2 mr-2">
<div className="relative group">
<Info className="h-4 w-4 text-muted-foreground cursor-help" />
<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">
<SearchScopeInfoCard />
<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>
</div>
<span className="text-sm font-medium text-muted-foreground">Search Scope:</span>
</div>
<span className="text-sm font-medium text-muted-foreground">Search Scope:</span>
</div>
<Badge
variant={selectedFilterSearchScope === null ? "default" : "secondary"}
className={`cursor-pointer transition-all duration-200 hover:shadow-sm ${selectedFilterSearchScope === null ? "bg-primary text-primary-foreground" : "hover:bg-secondary/80"
}`}
onClick={() => {
setSelectedFilterSearchScope(null);
}}
>
All
</Badge>
{demoExamples.searchScopes.map((searchScope) => (
<Badge
variant={selectedFilterSearchScope === null ? "default" : "secondary"}
className={`cursor-pointer transition-all duration-200 hover:shadow-sm ${selectedFilterSearchScope === null ? "bg-primary text-primary-foreground" : "hover:bg-secondary/80"
key={searchScope.id}
variant={selectedFilterSearchScope === searchScope.id ? "default" : "secondary"}
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"
}`}
onClick={() => {
setSelectedFilterSearchScope(null);
setSelectedFilterSearchScope(searchScope.id);
}}
>
All
{getSearchScopeIcon(searchScope, 12, selectedFilterSearchScope === searchScope.id)}
{searchScope.displayName}
</Badge>
{demoExamples.searchScopes.map((searchScope) => (
<Badge
key={searchScope.id}
variant={selectedFilterSearchScope === searchScope.id ? "default" : "secondary"}
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"
}`}
onClick={() => {
setSelectedFilterSearchScope(searchScope.id);
}}
>
{getSearchScopeIcon(searchScope, 12, selectedFilterSearchScope === searchScope.id)}
{searchScope.displayName}
</Badge>
))}
</div>
))}
</div>

<div className="flex flex-wrap justify-center gap-3">
{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 (
<Card
key={example.url}
className="cursor-pointer transition-all duration-200 hover:shadow-md hover:scale-105 hover:border-primary/50 group w-full max-w-[350px]"
onClick={() => handleExampleClick(example)}
>
<CardContent className="p-4">
<div className="space-y-3">
<div className="flex items-center justify-between">
{searchScopes.map((searchScope) => (
<Badge key={searchScope.value} variant="secondary" className="text-[10px] px-1.5 py-0.5 h-4 flex items-center gap-1">
{getSearchScopeIcon(searchScope, 12)}
{searchScope.displayName}
</Badge>
))}
</div>
<div className="space-y-1">
<h4 className="font-semibold text-sm group-hover:text-primary transition-colors line-clamp-2">
{example.title}
</h4>
<p className="text-xs text-muted-foreground line-clamp-3 leading-relaxed">
{example.description}
</p>
</div>
<div className="flex flex-wrap justify-center gap-3">
{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 (
<Card
key={example.url}
className="cursor-pointer transition-all duration-200 hover:shadow-md hover:scale-105 hover:border-primary/50 group w-full max-w-[350px]"
onClick={() => handleExampleClick(example)}
>
<CardContent className="p-4">
<div className="space-y-3">
<div className="flex items-center justify-between">
{searchScopes.map((searchScope) => (
<Badge key={searchScope.value} variant="secondary" className="text-[10px] px-1.5 py-0.5 h-4 flex items-center gap-1">
{getSearchScopeIcon(searchScope, 12)}
{searchScope.displayName}
</Badge>
))}
</div>
</CardContent>
</Card>
)
})}
</div>
<div className="space-y-1">
<h4 className="font-semibold text-sm group-hover:text-primary transition-colors line-clamp-2">
{example.title}
</h4>
<p className="text-xs text-muted-foreground line-clamp-3 leading-relaxed">
{example.description}
</p>
</div>
</div>
</CardContent>
</Card>
)
})}
</div>
</div>
</>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand Down Expand Up @@ -68,15 +69,30 @@ export function RepositorySnapshot({
return (
<div className="flex flex-col items-center gap-3">
<span className="text-sm">
{`Search ${indexedRepos.length} `}
{`${indexedRepos.length} `}
<Link
href={`${domain}/repos`}
className="text-link hover:underline"
>
{indexedRepos.length > 1 ? 'repositories' : 'repository'}
</Link>
{` indexed`}
</span>
<RepositoryCarousel repos={indexedRepos} />
{process.env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === "demo" && (
<p className="text-sm text-muted-foreground text-center">
Interested in using Sourcebot on your code? Check out our{' '}
<a
href="https://docs.sourcebot.dev/docs/overview"
target="_blank"
rel="noopener noreferrer"
className="text-primary hover:underline"
onClick={() => captureEvent('wa_demo_docs_link_pressed', {})}
>
docs
</a>
</p>
)}
</div>
)
}
Expand Down
9 changes: 8 additions & 1 deletion packages/web/src/app/onboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -87,6 +87,13 @@ export default async function Onboarding({ searchParams }: OnboardingProps) {
href: "https://docs.sourcebot.dev/docs/connections/overview",
icon: <GitBranchIcon className="w-4 h-4" />,
},
{
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: <Brain className="w-4 h-4" />,
},
{
id: "authentication-system",
title: "Authentication System",
Expand Down
Loading