mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 04:15:30 +00:00
feat(ask_sb): Add back search scope requirement and other UI changes (#411)
* Revert "Remove search scope constraint"
This reverts commit e69ac0d806.
* 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
This commit is contained in:
parent
211ad8fb12
commit
53edd44462
10 changed files with 210 additions and 122 deletions
|
|
@ -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)
|
- 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] 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] 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
|
## [4.6.0] - 2025-07-25
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ export const NewChatPanel = ({
|
||||||
languageModels={languageModels}
|
languageModels={languageModels}
|
||||||
selectedSearchScopes={selectedSearchScopes}
|
selectedSearchScopes={selectedSearchScopes}
|
||||||
searchContexts={searchContexts}
|
searchContexts={searchContexts}
|
||||||
|
onContextSelectorOpenChanged={setIsContextSelectorOpen}
|
||||||
/>
|
/>
|
||||||
<div className="w-full flex flex-row items-center bg-accent rounded-b-md px-2">
|
<div className="w-full flex flex-row items-center bg-accent rounded-b-md px-2">
|
||||||
<ChatBoxToolbar
|
<ChatBoxToolbar
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import { DemoExamples } from "@/types";
|
||||||
import { AskSourcebotDemoCards } from "./askSourcebotDemoCards";
|
import { AskSourcebotDemoCards } from "./askSourcebotDemoCards";
|
||||||
import { AgenticSearchTutorialDialog } from "./agenticSearchTutorialDialog";
|
import { AgenticSearchTutorialDialog } from "./agenticSearchTutorialDialog";
|
||||||
import { setAgenticSearchTutorialDismissedCookie } from "@/actions";
|
import { setAgenticSearchTutorialDismissedCookie } from "@/actions";
|
||||||
|
import { RepositorySnapshot } from "./repositorySnapshot";
|
||||||
|
|
||||||
interface AgenticSearchProps {
|
interface AgenticSearchProps {
|
||||||
searchModeSelectorProps: SearchModeSelectorProps;
|
searchModeSelectorProps: SearchModeSelectorProps;
|
||||||
|
|
@ -58,6 +59,7 @@ export const AgenticSearch = ({
|
||||||
languageModels={languageModels}
|
languageModels={languageModels}
|
||||||
selectedSearchScopes={selectedSearchScopes}
|
selectedSearchScopes={selectedSearchScopes}
|
||||||
searchContexts={searchContexts}
|
searchContexts={searchContexts}
|
||||||
|
onContextSelectorOpenChanged={setIsContextSelectorOpen}
|
||||||
/>
|
/>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
@ -79,6 +81,16 @@ export const AgenticSearch = ({
|
||||||
</div>
|
</div>
|
||||||
</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 && (
|
{demoExamples && (
|
||||||
<AskSourcebotDemoCards
|
<AskSourcebotDemoCards
|
||||||
demoExamples={demoExamples}
|
demoExamples={demoExamples}
|
||||||
|
|
|
||||||
|
|
@ -66,23 +66,7 @@ export const AskSourcebotDemoCards = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="w-full mt-8 space-y-12 px-4 max-w-[1200px]">
|
||||||
{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 */}
|
{/* Example Searches Row */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="text-center mb-6">
|
<div className="text-center mb-6">
|
||||||
|
|
@ -170,6 +154,5 @@ export const AskSourcebotDemoCards = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
import { RepoIndexingStatus } from "@sourcebot/db";
|
import { RepoIndexingStatus } from "@sourcebot/db";
|
||||||
import { SymbolIcon } from "@radix-ui/react-icons";
|
import { SymbolIcon } from "@radix-ui/react-icons";
|
||||||
import { RepositoryQuery } from "@/lib/types";
|
import { RepositoryQuery } from "@/lib/types";
|
||||||
|
import { captureEvent } from "@/hooks/useCaptureEvent";
|
||||||
|
|
||||||
interface RepositorySnapshotProps {
|
interface RepositorySnapshotProps {
|
||||||
repos: RepositoryQuery[];
|
repos: RepositoryQuery[];
|
||||||
|
|
@ -68,15 +69,30 @@ export function RepositorySnapshot({
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center gap-3">
|
<div className="flex flex-col items-center gap-3">
|
||||||
<span className="text-sm">
|
<span className="text-sm">
|
||||||
{`Search ${indexedRepos.length} `}
|
{`${indexedRepos.length} `}
|
||||||
<Link
|
<Link
|
||||||
href={`${domain}/repos`}
|
href={`${domain}/repos`}
|
||||||
className="text-link hover:underline"
|
className="text-link hover:underline"
|
||||||
>
|
>
|
||||||
{indexedRepos.length > 1 ? 'repositories' : 'repository'}
|
{indexedRepos.length > 1 ? 'repositories' : 'repository'}
|
||||||
</Link>
|
</Link>
|
||||||
|
{` indexed`}
|
||||||
</span>
|
</span>
|
||||||
<RepositoryCarousel repos={indexedRepos} />
|
<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>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import { prisma } from "@/prisma";
|
||||||
import { OrgRole } from "@sourcebot/db";
|
import { OrgRole } from "@sourcebot/db";
|
||||||
import { LogoutEscapeHatch } from "@/app/components/logoutEscapeHatch";
|
import { LogoutEscapeHatch } from "@/app/components/logoutEscapeHatch";
|
||||||
import { redirect } from "next/navigation";
|
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 { hasEntitlement } from "@sourcebot/shared";
|
||||||
import { env } from "@/env.mjs";
|
import { env } from "@/env.mjs";
|
||||||
import { GcpIapAuth } from "@/app/[domain]/components/gcpIapAuth";
|
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",
|
href: "https://docs.sourcebot.dev/docs/connections/overview",
|
||||||
icon: <GitBranchIcon className="w-4 h-4" />,
|
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",
|
id: "authentication-system",
|
||||||
title: "Authentication System",
|
title: "Authentication System",
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,9 @@ import { Button } from "@/components/ui/button";
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
import { CustomEditor, LanguageModelInfo, MentionElement, RenderElementPropsFor, SearchScope } from "@/features/chat/types";
|
import { CustomEditor, LanguageModelInfo, MentionElement, RenderElementPropsFor, SearchScope } from "@/features/chat/types";
|
||||||
import { insertMention, slateContentToString } from "@/features/chat/utils";
|
import { insertMention, slateContentToString } from "@/features/chat/utils";
|
||||||
import { SearchContextQuery } from "@/lib/types";
|
|
||||||
import { cn, IS_MAC } from "@/lib/utils";
|
import { cn, IS_MAC } from "@/lib/utils";
|
||||||
import { computePosition, flip, offset, shift, VirtualElement } from "@floating-ui/react";
|
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 { Fragment, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useHotkeys } from "react-hotkeys-hook";
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
import { Descendant, insertText } from "slate";
|
import { Descendant, insertText } from "slate";
|
||||||
|
|
@ -18,6 +17,8 @@ import { SuggestionBox } from "./suggestionsBox";
|
||||||
import { Suggestion } from "./types";
|
import { Suggestion } from "./types";
|
||||||
import { useSuggestionModeAndQuery } from "./useSuggestionModeAndQuery";
|
import { useSuggestionModeAndQuery } from "./useSuggestionModeAndQuery";
|
||||||
import { useSuggestionsData } from "./useSuggestionsData";
|
import { useSuggestionsData } from "./useSuggestionsData";
|
||||||
|
import { useToast } from "@/components/hooks/use-toast";
|
||||||
|
import { SearchContextQuery } from "@/lib/types";
|
||||||
|
|
||||||
interface ChatBoxProps {
|
interface ChatBoxProps {
|
||||||
onSubmit: (children: Descendant[], editor: CustomEditor) => void;
|
onSubmit: (children: Descendant[], editor: CustomEditor) => void;
|
||||||
|
|
@ -29,6 +30,7 @@ interface ChatBoxProps {
|
||||||
languageModels: LanguageModelInfo[];
|
languageModels: LanguageModelInfo[];
|
||||||
selectedSearchScopes: SearchScope[];
|
selectedSearchScopes: SearchScope[];
|
||||||
searchContexts: SearchContextQuery[];
|
searchContexts: SearchContextQuery[];
|
||||||
|
onContextSelectorOpenChanged: (isOpen: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChatBox = ({
|
export const ChatBox = ({
|
||||||
|
|
@ -41,6 +43,7 @@ export const ChatBox = ({
|
||||||
languageModels,
|
languageModels,
|
||||||
selectedSearchScopes,
|
selectedSearchScopes,
|
||||||
searchContexts,
|
searchContexts,
|
||||||
|
onContextSelectorOpenChanged,
|
||||||
}: ChatBoxProps) => {
|
}: ChatBoxProps) => {
|
||||||
const suggestionsBoxRef = useRef<HTMLDivElement>(null);
|
const suggestionsBoxRef = useRef<HTMLDivElement>(null);
|
||||||
const [index, setIndex] = useState(0);
|
const [index, setIndex] = useState(0);
|
||||||
|
|
@ -67,6 +70,7 @@ export const ChatBox = ({
|
||||||
const { selectedLanguageModel } = useSelectedLanguageModel({
|
const { selectedLanguageModel } = useSelectedLanguageModel({
|
||||||
initialLanguageModel: languageModels.length > 0 ? languageModels[0] : undefined,
|
initialLanguageModel: languageModels.length > 0 ? languageModels[0] : undefined,
|
||||||
});
|
});
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
// Reset the index when the suggestion mode changes.
|
// Reset the index when the suggestion mode changes.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -97,9 +101,9 @@ export const ChatBox = ({
|
||||||
return <Leaf {...props} />
|
return <Leaf {...props} />
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { isSubmitDisabled } = useMemo((): {
|
const { isSubmitDisabled, isSubmitDisabledReason } = useMemo((): {
|
||||||
isSubmitDisabled: true,
|
isSubmitDisabled: true,
|
||||||
isSubmitDisabledReason: "empty" | "redirecting" | "generating" | "no-language-model-selected"
|
isSubmitDisabledReason: "empty" | "redirecting" | "generating" | "no-repos-selected" | "no-language-model-selected"
|
||||||
} | {
|
} | {
|
||||||
isSubmitDisabled: false,
|
isSubmitDisabled: false,
|
||||||
isSubmitDisabledReason: undefined,
|
isSubmitDisabledReason: undefined,
|
||||||
|
|
@ -125,6 +129,13 @@ export const ChatBox = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selectedSearchScopes.length === 0) {
|
||||||
|
return {
|
||||||
|
isSubmitDisabled: true,
|
||||||
|
isSubmitDisabledReason: "no-repos-selected",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedLanguageModel === undefined) {
|
if (selectedLanguageModel === undefined) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -138,11 +149,29 @@ export const ChatBox = ({
|
||||||
isSubmitDisabledReason: undefined,
|
isSubmitDisabledReason: undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [editor.children, isRedirecting, isGenerating, selectedLanguageModel])
|
}, [
|
||||||
|
editor.children,
|
||||||
|
isRedirecting,
|
||||||
|
isGenerating,
|
||||||
|
selectedSearchScopes.length,
|
||||||
|
selectedLanguageModel,
|
||||||
|
])
|
||||||
|
|
||||||
const onSubmit = useCallback(() => {
|
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.children, editor);
|
||||||
}, [_onSubmit, editor]);
|
}, [_onSubmit, editor, isSubmitDisabled, isSubmitDisabledReason, toast, onContextSelectorOpenChanged]);
|
||||||
|
|
||||||
const onInsertSuggestion = useCallback((suggestion: Suggestion) => {
|
const onInsertSuggestion = useCallback((suggestion: Suggestion) => {
|
||||||
switch (suggestion.type) {
|
switch (suggestion.type) {
|
||||||
|
|
@ -281,6 +310,19 @@ export const ChatBox = ({
|
||||||
Stop
|
Stop
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
// @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();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
variant={isSubmitDisabled ? "outline" : "default"}
|
variant={isSubmitDisabled ? "outline" : "default"}
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -290,6 +332,17 @@ export const ChatBox = ({
|
||||||
>
|
>
|
||||||
<ArrowUp className="w-4 h-4" />
|
<ArrowUp className="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
{(isSubmitDisabled && isSubmitDisabledReason === "no-repos-selected") && (
|
||||||
|
<TooltipContent>
|
||||||
|
<div className="flex flex-row items-center">
|
||||||
|
<TriangleAlertIcon className="h-4 w-4 text-warning mr-1" />
|
||||||
|
<span className="text-destructive">You must select at least one search scope</span>
|
||||||
|
</div>
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{suggestionMode !== "none" && (
|
{suggestionMode !== "none" && (
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ export const SearchScopeSelector = React.forwardRef<
|
||||||
) => {
|
) => {
|
||||||
const scrollContainerRef = React.useRef<HTMLDivElement>(null);
|
const scrollContainerRef = React.useRef<HTMLDivElement>(null);
|
||||||
const scrollPosition = React.useRef<number>(0);
|
const scrollPosition = React.useRef<number>(0);
|
||||||
|
const [hasSearchInput, setHasSearchInput] = React.useState(false);
|
||||||
|
|
||||||
const handleInputKeyDown = (
|
const handleInputKeyDown = (
|
||||||
event: React.KeyboardEvent<HTMLInputElement>
|
event: React.KeyboardEvent<HTMLInputElement>
|
||||||
|
|
@ -93,6 +94,10 @@ export const SearchScopeSelector = React.forwardRef<
|
||||||
onSelectedSearchScopesChange([]);
|
onSelectedSearchScopesChange([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSelectAll = () => {
|
||||||
|
onSelectedSearchScopesChange(allSearchScopeItems);
|
||||||
|
};
|
||||||
|
|
||||||
const handleTogglePopover = () => {
|
const handleTogglePopover = () => {
|
||||||
onOpenChanged(!isOpen);
|
onOpenChanged(!isOpen);
|
||||||
};
|
};
|
||||||
|
|
@ -180,10 +185,19 @@ export const SearchScopeSelector = React.forwardRef<
|
||||||
<CommandInput
|
<CommandInput
|
||||||
placeholder="Search scopes..."
|
placeholder="Search scopes..."
|
||||||
onKeyDown={handleInputKeyDown}
|
onKeyDown={handleInputKeyDown}
|
||||||
|
onValueChange={(value) => setHasSearchInput(!!value)}
|
||||||
/>
|
/>
|
||||||
<CommandList ref={scrollContainerRef}>
|
<CommandList ref={scrollContainerRef}>
|
||||||
<CommandEmpty>No results found.</CommandEmpty>
|
<CommandEmpty>No results found.</CommandEmpty>
|
||||||
<CommandGroup>
|
<CommandGroup>
|
||||||
|
{!hasSearchInput && (
|
||||||
|
<div
|
||||||
|
onClick={handleSelectAll}
|
||||||
|
className="flex items-center px-2 py-1.5 text-sm text-muted-foreground hover:text-foreground cursor-pointer transition-colors"
|
||||||
|
>
|
||||||
|
<span className="text-xs">Select all</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{sortedSearchScopeItems.map(({ item, isSelected }) => {
|
{sortedSearchScopeItems.map(({ item, isSelected }) => {
|
||||||
return (
|
return (
|
||||||
<CommandItem
|
<CommandItem
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,7 @@ export const ChatThread = ({
|
||||||
languageModels={languageModels}
|
languageModels={languageModels}
|
||||||
selectedSearchScopes={selectedSearchScopes}
|
selectedSearchScopes={selectedSearchScopes}
|
||||||
searchContexts={searchContexts}
|
searchContexts={searchContexts}
|
||||||
|
onContextSelectorOpenChanged={setIsContextSelectorOpen}
|
||||||
/>
|
/>
|
||||||
<div className="w-full flex flex-row items-center bg-accent rounded-b-md px-2">
|
<div className="w-full flex flex-row items-center bg-accent rounded-b-md px-2">
|
||||||
<ChatBoxToolbar
|
<ChatBoxToolbar
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { Separator } from '@/components/ui/separator';
|
||||||
import { Skeleton } from '@/components/ui/skeleton';
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { cn } from '@/lib/utils';
|
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 { MarkdownRenderer } from './markdownRenderer';
|
||||||
import { FindSymbolDefinitionsToolComponent } from './tools/findSymbolDefinitionsToolComponent';
|
import { FindSymbolDefinitionsToolComponent } from './tools/findSymbolDefinitionsToolComponent';
|
||||||
import { FindSymbolReferencesToolComponent } from './tools/findSymbolReferencesToolComponent';
|
import { FindSymbolReferencesToolComponent } from './tools/findSymbolReferencesToolComponent';
|
||||||
|
|
@ -89,7 +89,7 @@ export const DetailsCard = ({
|
||||||
)}
|
)}
|
||||||
{metadata?.modelName && (
|
{metadata?.modelName && (
|
||||||
<div className="flex items-center text-xs">
|
<div className="flex items-center text-xs">
|
||||||
<Cpu className="w-3 h-3 mr-1 flex-shrink-0" />
|
<Brain className="w-3 h-3 mr-1 flex-shrink-0" />
|
||||||
{metadata?.modelName}
|
{metadata?.modelName}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -106,7 +106,7 @@ export const DetailsCard = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex items-center text-xs">
|
<div className="flex items-center text-xs">
|
||||||
<Brain className="w-3 h-3 mr-1 flex-shrink-0" />
|
<List className="w-3 h-3 mr-1 flex-shrink-0" />
|
||||||
{`${thinkingSteps.length} step${thinkingSteps.length === 1 ? '' : 's'}`}
|
{`${thinkingSteps.length} step${thinkingSteps.length === 1 ? '' : 's'}`}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue