mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 12:25:22 +00:00
wip demo example path
This commit is contained in:
parent
aebd8df193
commit
1114ee57f5
5 changed files with 226 additions and 216 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { ChatBox } from "@/features/chat/components/chatBox";
|
import { ChatBox } from "@/features/chat/components/chatBox";
|
||||||
import { ChatBoxToolbar } from "@/features/chat/components/chatBox/chatBoxToolbar";
|
import { ChatBoxToolbar } from "@/features/chat/components/chatBox/chatBoxToolbar";
|
||||||
|
|
@ -10,40 +9,15 @@ import { resetEditor } from "@/features/chat/utils";
|
||||||
import { useDomain } from "@/hooks/useDomain";
|
import { useDomain } from "@/hooks/useDomain";
|
||||||
import { RepositoryQuery, SearchContextQuery } from "@/lib/types";
|
import { RepositoryQuery, SearchContextQuery } from "@/lib/types";
|
||||||
import { getDisplayTime } from "@/lib/utils";
|
import { getDisplayTime } from "@/lib/utils";
|
||||||
import { BrainIcon, FileIcon, LucideIcon, SearchIcon } from "lucide-react";
|
import { Code, Database, FileIcon, FileText, Gamepad2, Globe, Layers, LucideIcon, Search, SearchIcon, Smartphone, Zap } from "lucide-react";
|
||||||
import Link from "next/link";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
|
import { useState } from "react";
|
||||||
import { ReactEditor, useSlate } from "slate-react";
|
|
||||||
import { SearchModeSelector, SearchModeSelectorProps } from "./toolbar";
|
import { SearchModeSelector, SearchModeSelectorProps } from "./toolbar";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
import { CardContent } from "@/components/ui/card";
|
||||||
import { useLocalStorage } from "usehooks-ts";
|
import { useLocalStorage } from "usehooks-ts";
|
||||||
import { ContextItem } from "@/features/chat/components/chatBox/contextSelector";
|
import { ContextItem } from "@/features/chat/components/chatBox/contextSelector";
|
||||||
|
import { DemoExamples, DemoSearchExample, DemoSearchContextExample } from "@/types";
|
||||||
// @todo: we should probably rename this to a different type since it sort-of clashes
|
|
||||||
// with the Suggestion system we have built into the chat box.
|
|
||||||
type SuggestionType = "understand" | "find" | "summarize";
|
|
||||||
|
|
||||||
const suggestionTypes: Record<SuggestionType, {
|
|
||||||
icon: LucideIcon;
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
}> = {
|
|
||||||
understand: {
|
|
||||||
icon: BrainIcon,
|
|
||||||
title: "Understand",
|
|
||||||
description: "Understand the codebase",
|
|
||||||
},
|
|
||||||
find: {
|
|
||||||
icon: SearchIcon,
|
|
||||||
title: "Find",
|
|
||||||
description: "Find the codebase",
|
|
||||||
},
|
|
||||||
summarize: {
|
|
||||||
icon: FileIcon,
|
|
||||||
title: "Summarize",
|
|
||||||
description: "Summarize the codebase",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const Highlight = ({ children }: { children: React.ReactNode }) => {
|
const Highlight = ({ children }: { children: React.ReactNode }) => {
|
||||||
return (
|
return (
|
||||||
|
|
@ -53,59 +27,6 @@ const Highlight = ({ children }: { children: React.ReactNode }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const suggestions: Record<SuggestionType, {
|
|
||||||
queryText: string;
|
|
||||||
queryNode?: ReactNode;
|
|
||||||
openRepoSelector?: boolean;
|
|
||||||
}[]> = {
|
|
||||||
understand: [
|
|
||||||
{
|
|
||||||
queryText: "How does authentication work in this codebase?",
|
|
||||||
openRepoSelector: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
queryText: "How are API endpoints structured and organized?",
|
|
||||||
openRepoSelector: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
queryText: "How does the build and deployment process work?",
|
|
||||||
openRepoSelector: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
queryText: "How is error handling implemented across the application?",
|
|
||||||
openRepoSelector: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
find: [
|
|
||||||
{
|
|
||||||
queryText: "Find examples of different logging libraries used throughout the codebase.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
queryText: "Find examples of potential security vulnerabilities or authentication issues.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
queryText: "Find examples of API endpoints and route handlers.",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
summarize: [
|
|
||||||
{
|
|
||||||
queryText: "Summarize the purpose of this file @file:",
|
|
||||||
queryNode: <span>Summarize the purpose of this file <Highlight>@file:</Highlight></span>
|
|
||||||
},
|
|
||||||
{
|
|
||||||
queryText: "Summarize the project structure and architecture.",
|
|
||||||
openRepoSelector: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
queryText: "Provide a quick start guide for ramping up on this codebase.",
|
|
||||||
openRepoSelector: true,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
const MAX_RECENT_CHAT_HISTORY_COUNT = 10;
|
|
||||||
|
|
||||||
|
|
||||||
interface AgenticSearchProps {
|
interface AgenticSearchProps {
|
||||||
searchModeSelectorProps: SearchModeSelectorProps;
|
searchModeSelectorProps: SearchModeSelectorProps;
|
||||||
languageModels: LanguageModelInfo[];
|
languageModels: LanguageModelInfo[];
|
||||||
|
|
@ -116,49 +37,121 @@ interface AgenticSearchProps {
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
}[];
|
}[];
|
||||||
|
demoExamples: DemoExamples | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const exampleSearches = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
title: "Show me examples of how useMemo is used",
|
||||||
|
description: "Find React performance optimization patterns",
|
||||||
|
icon: <Zap className="h-4 w-4" />,
|
||||||
|
category: "React",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
title: "How do I implement authentication?",
|
||||||
|
description: "Explore auth patterns and best practices",
|
||||||
|
icon: <Database className="h-4 w-4" />,
|
||||||
|
category: "Security",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
title: "Find API route handlers",
|
||||||
|
description: "Locate and analyze API endpoint implementations",
|
||||||
|
icon: <Globe className="h-4 w-4" />,
|
||||||
|
category: "Backend",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
title: "Show me error handling patterns",
|
||||||
|
description: "Discover error boundary and exception handling",
|
||||||
|
icon: <FileText className="h-4 w-4" />,
|
||||||
|
category: "Best Practices",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5",
|
||||||
|
title: "How are components structured?",
|
||||||
|
description: "Analyze component architecture and patterns",
|
||||||
|
icon: <Layers className="h-4 w-4" />,
|
||||||
|
category: "Architecture",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const searchContextsExample = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
displayName: "Next.js",
|
||||||
|
name: "nextjs",
|
||||||
|
description: "React framework for production",
|
||||||
|
icon: <Code className="h-5 w-5" />,
|
||||||
|
color: "bg-black text-white",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
displayName: "React",
|
||||||
|
name: "react",
|
||||||
|
description: "JavaScript library for building UIs",
|
||||||
|
icon: <Code className="h-5 w-5" />,
|
||||||
|
color: "bg-blue-500 text-white",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
displayName: "TypeScript",
|
||||||
|
name: "typescript",
|
||||||
|
description: "Typed JavaScript at scale",
|
||||||
|
icon: <FileText className="h-5 w-5" />,
|
||||||
|
color: "bg-blue-600 text-white",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
displayName: "Tailwind CSS",
|
||||||
|
name: "tailwindcss",
|
||||||
|
description: "Utility-first CSS framework",
|
||||||
|
icon: <Layers className="h-5 w-5" />,
|
||||||
|
color: "bg-cyan-500 text-white",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5",
|
||||||
|
displayName: "Godot Engine",
|
||||||
|
name: "godot",
|
||||||
|
description: "Open source game engine",
|
||||||
|
icon: <Gamepad2 className="h-5 w-5" />,
|
||||||
|
color: "bg-blue-400 text-white",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "6",
|
||||||
|
displayName: "React Native",
|
||||||
|
name: "react-native",
|
||||||
|
description: "Build mobile apps with React",
|
||||||
|
icon: <Smartphone className="h-5 w-5" />,
|
||||||
|
color: "bg-purple-500 text-white",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
export const AgenticSearch = ({
|
export const AgenticSearch = ({
|
||||||
searchModeSelectorProps,
|
searchModeSelectorProps,
|
||||||
languageModels,
|
languageModels,
|
||||||
repos,
|
repos,
|
||||||
searchContexts,
|
searchContexts,
|
||||||
chatHistory,
|
chatHistory,
|
||||||
|
demoExamples,
|
||||||
}: AgenticSearchProps) => {
|
}: AgenticSearchProps) => {
|
||||||
const [selectedSuggestionType, _setSelectedSuggestionType] = useState<SuggestionType | undefined>(undefined);
|
|
||||||
const { createNewChatThread, isLoading } = useCreateNewChatThread();
|
const { createNewChatThread, isLoading } = useCreateNewChatThread();
|
||||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
||||||
const editor = useSlate();
|
|
||||||
const [selectedItems, setSelectedItems] = useLocalStorage<ContextItem[]>("selectedContextItems", [], { initializeWithValue: false });
|
const [selectedItems, setSelectedItems] = useLocalStorage<ContextItem[]>("selectedContextItems", [], { initializeWithValue: false });
|
||||||
const domain = useDomain();
|
|
||||||
const [isContextSelectorOpen, setIsContextSelectorOpen] = useState(false);
|
const [isContextSelectorOpen, setIsContextSelectorOpen] = useState(false);
|
||||||
|
|
||||||
const setSelectedSuggestionType = useCallback((type: SuggestionType | undefined) => {
|
const handleExampleClick = (example: DemoSearchExample) => {
|
||||||
_setSelectedSuggestionType(type);
|
console.log(example);
|
||||||
if (type) {
|
}
|
||||||
ReactEditor.focus(editor);
|
|
||||||
}
|
|
||||||
}, [editor, _setSelectedSuggestionType]);
|
|
||||||
|
|
||||||
// Close dropdown when clicking outside
|
const handleContextClick = (context: DemoSearchContextExample) => {
|
||||||
useEffect(() => {
|
console.log(context);
|
||||||
function handleClickOutside(event: MouseEvent) {
|
}
|
||||||
if (
|
|
||||||
!dropdownRef.current?.contains(event.target as Node)
|
|
||||||
) {
|
|
||||||
setSelectedSuggestionType(undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("mousedown", handleClickOutside)
|
|
||||||
return () => document.removeEventListener("mousedown", handleClickOutside)
|
|
||||||
}, [setSelectedSuggestionType]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center w-full max-w-[800px]">
|
<div className="flex flex-col items-center w-full">
|
||||||
<div
|
<div className="mt-4 w-full border rounded-md shadow-sm max-w-[800px]">
|
||||||
className="mt-4 w-full border rounded-md shadow-sm"
|
|
||||||
>
|
|
||||||
<ChatBox
|
<ChatBox
|
||||||
onSubmit={(children) => {
|
onSubmit={(children) => {
|
||||||
createNewChatThread(children, selectedItems);
|
createNewChatThread(children, selectedItems);
|
||||||
|
|
@ -187,111 +180,93 @@ export const AgenticSearch = ({
|
||||||
className="ml-auto"
|
className="ml-auto"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{selectedSuggestionType && (
|
|
||||||
<div
|
|
||||||
ref={dropdownRef}
|
|
||||||
className="w-full absolute top-10 z-10 drop-shadow-2xl bg-background border rounded-md p-2"
|
|
||||||
>
|
|
||||||
<p className="text-muted-foreground text-sm mb-2">
|
|
||||||
{suggestionTypes[selectedSuggestionType].title}
|
|
||||||
</p>
|
|
||||||
{suggestions[selectedSuggestionType].map(({ queryText, queryNode, openRepoSelector }, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="flex flex-row items-center gap-2 cursor-pointer hover:bg-muted rounded-md px-1 py-0.5"
|
|
||||||
onClick={() => {
|
|
||||||
resetEditor(editor);
|
|
||||||
editor.insertText(queryText);
|
|
||||||
setSelectedSuggestionType(undefined);
|
|
||||||
|
|
||||||
if (openRepoSelector) {
|
|
||||||
setIsContextSelectorOpen(true);
|
|
||||||
} else {
|
|
||||||
ReactEditor.focus(editor);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SearchIcon className="w-4 h-4" />
|
|
||||||
{queryNode ?? queryText}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center w-fit gap-6 mt-8 relative">
|
|
||||||
<div className="flex flex-row items-center gap-4">
|
{demoExamples && (
|
||||||
{Object.entries(suggestionTypes).map(([type, suggestion], index) => (
|
<div className="w-full mt-8 grid grid-cols-1 lg:grid-cols-2 gap-8 px-4 max-w-[1200px]">
|
||||||
<ExampleButton
|
{/* Example Searches Column */}
|
||||||
key={index}
|
<div className="space-y-4">
|
||||||
Icon={suggestion.icon}
|
<div className="flex items-center gap-2 mb-6">
|
||||||
title={suggestion.title}
|
<Search className="h-5 w-5 text-muted-foreground" />
|
||||||
onClick={() => {
|
<h3 className="text-lg font-semibold">Example Searches</h3>
|
||||||
setSelectedSuggestionType(type as SuggestionType);
|
</div>
|
||||||
}}
|
<div className="space-y-3">
|
||||||
/>
|
{demoExamples.searchExamples.map((example) => (
|
||||||
))}
|
<Card
|
||||||
</div>
|
key={example.id}
|
||||||
</div>
|
className="cursor-pointer transition-all duration-200 hover:shadow-md hover:border-primary/50 group"
|
||||||
{chatHistory.length > 0 && (
|
onClick={() => handleExampleClick(example)}
|
||||||
<div className="flex flex-col items-center w-[80%]">
|
>
|
||||||
<Separator className="my-6" />
|
<CardContent className="p-4">
|
||||||
<span className="font-semibold mb-2">Recent conversations</span>
|
<div className="flex items-start gap-3">
|
||||||
<div
|
<div className="flex-shrink-0 p-2 rounded-lg bg-primary/10 text-primary group-hover:bg-primary group-hover:text-primary-foreground transition-colors">
|
||||||
className="flex flex-col gap-1 w-full"
|
{example.icon}
|
||||||
>
|
</div>
|
||||||
{chatHistory
|
<div className="flex-1 min-w-0">
|
||||||
.slice(0, MAX_RECENT_CHAT_HISTORY_COUNT)
|
<h4 className="font-medium text-sm mb-1 group-hover:text-primary transition-colors">
|
||||||
.map((chat) => (
|
{example.title}
|
||||||
<Link
|
</h4>
|
||||||
key={chat.id}
|
<p className="text-xs text-muted-foreground mb-2">{example.description}</p>
|
||||||
className="flex flex-row items-center justify-between gap-1 w-full rounded-md hover:bg-muted px-2 py-0.5 cursor-pointer group"
|
<Badge className="text-xs">
|
||||||
href={`/${domain}/chat/${chat.id}`}
|
{example.category}
|
||||||
>
|
</Badge>
|
||||||
<span className="text-sm text-muted-foreground group-hover:text-foreground">
|
</div>
|
||||||
{chat.name ?? "Untitled Chat"}
|
</div>
|
||||||
</span>
|
</CardContent>
|
||||||
<span className="text-sm text-muted-foreground group-hover:text-foreground">
|
</Card>
|
||||||
{getDisplayTime(chat.createdAt)}
|
))}
|
||||||
</span>
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
{chatHistory.length > MAX_RECENT_CHAT_HISTORY_COUNT && (
|
|
||||||
<Link
|
|
||||||
href={`/${domain}/chat`}
|
|
||||||
className="text-sm text-link hover:underline mt-6"
|
|
||||||
>
|
|
||||||
View all
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Search Contexts Column */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center gap-2 mb-6">
|
||||||
|
<Layers className="h-5 w-5 text-muted-foreground" />
|
||||||
|
<h3 className="text-lg font-semibold">Search Contexts</h3>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-1 xl:grid-cols-2 gap-3">
|
||||||
|
{demoExamples.searchContexts?.map((context) => {
|
||||||
|
const searchContext = searchContexts.find((item) => item.name === context.name);
|
||||||
|
if (!searchContext) return null;
|
||||||
|
const isSelected = false; //selectedItems.some((item) => item.id === context.id)
|
||||||
|
|
||||||
|
const numRepos = searchContext.repoNames.length;
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
key={context.id}
|
||||||
|
className={`cursor-pointer transition-all duration-200 hover:shadow-md group ${isSelected ? "border-primary bg-primary/5 shadow-sm" : "hover:border-primary/50"
|
||||||
|
}`}
|
||||||
|
onClick={() => handleContextClick(context)}
|
||||||
|
>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<div
|
||||||
|
className={`flex-shrink-0 p-2 rounded-lg ${context.color} transition-transform group-hover:scale-105`}
|
||||||
|
>
|
||||||
|
{context.icon}
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<h4
|
||||||
|
className={`font-medium text-sm mb-1 transition-colors ${isSelected ? "text-primary" : "group-hover:text-primary"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{context.displayName}
|
||||||
|
</h4>
|
||||||
|
<p className="text-xs text-muted-foreground mb-2">{context.description}</p>
|
||||||
|
<Badge className="text-xs">
|
||||||
|
{numRepos} repos
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div >
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
interface ExampleButtonProps {
|
|
||||||
Icon: LucideIcon;
|
|
||||||
title: string;
|
|
||||||
onClick: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ExampleButton = ({
|
|
||||||
Icon,
|
|
||||||
title,
|
|
||||||
onClick,
|
|
||||||
}: ExampleButtonProps) => {
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
onClick={onClick}
|
|
||||||
className="h-9"
|
|
||||||
>
|
|
||||||
<Icon className="w-4 h-4" />
|
|
||||||
{title}
|
|
||||||
</Button>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ import { SearchMode } from "./toolbar";
|
||||||
import { CustomSlateEditor } from "@/features/chat/customSlateEditor";
|
import { CustomSlateEditor } from "@/features/chat/customSlateEditor";
|
||||||
import { setSearchModeCookie } from "@/actions";
|
import { setSearchModeCookie } from "@/actions";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
import { DemoExamples } from "@/types";
|
||||||
|
|
||||||
interface HomepageProps {
|
interface HomepageProps {
|
||||||
initialRepos: RepositoryQuery[];
|
initialRepos: RepositoryQuery[];
|
||||||
|
|
@ -21,6 +22,7 @@ interface HomepageProps {
|
||||||
name: string | null;
|
name: string | null;
|
||||||
}[];
|
}[];
|
||||||
initialSearchMode: SearchMode;
|
initialSearchMode: SearchMode;
|
||||||
|
demoExamples: DemoExamples | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -30,6 +32,7 @@ export const Homepage = ({
|
||||||
languageModels,
|
languageModels,
|
||||||
chatHistory,
|
chatHistory,
|
||||||
initialSearchMode,
|
initialSearchMode,
|
||||||
|
demoExamples,
|
||||||
}: HomepageProps) => {
|
}: HomepageProps) => {
|
||||||
const [searchMode, setSearchMode] = useState<SearchMode>(initialSearchMode);
|
const [searchMode, setSearchMode] = useState<SearchMode>(initialSearchMode);
|
||||||
const isAgenticSearchEnabled = languageModels.length > 0;
|
const isAgenticSearchEnabled = languageModels.length > 0;
|
||||||
|
|
@ -86,6 +89,7 @@ export const Homepage = ({
|
||||||
repos={initialRepos}
|
repos={initialRepos}
|
||||||
searchContexts={searchContexts}
|
searchContexts={searchContexts}
|
||||||
chatHistory={chatHistory}
|
chatHistory={chatHistory}
|
||||||
|
demoExamples={demoExamples}
|
||||||
/>
|
/>
|
||||||
</CustomSlateEditor>
|
</CustomSlateEditor>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { getRepos, getSearchContexts } from "@/actions";
|
||||||
import { Footer } from "@/app/components/footer";
|
import { Footer } from "@/app/components/footer";
|
||||||
import { getOrgFromDomain } from "@/data/org";
|
import { getOrgFromDomain } from "@/data/org";
|
||||||
import { getConfiguredLanguageModelsInfo, getUserChatHistory } from "@/features/chat/actions";
|
import { getConfiguredLanguageModelsInfo, getUserChatHistory } from "@/features/chat/actions";
|
||||||
import { isServiceError } from "@/lib/utils";
|
import { isServiceError, loadDemoExamples } from "@/lib/utils";
|
||||||
import { Homepage } from "./components/homepage";
|
import { Homepage } from "./components/homepage";
|
||||||
import { NavigationMenu } from "./components/navigationMenu";
|
import { NavigationMenu } from "./components/navigationMenu";
|
||||||
import { PageNotFound } from "./components/pageNotFound";
|
import { PageNotFound } from "./components/pageNotFound";
|
||||||
|
|
@ -11,6 +11,7 @@ import { ServiceErrorException } from "@/lib/serviceError";
|
||||||
import { auth } from "@/auth";
|
import { auth } from "@/auth";
|
||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
import { SEARCH_MODE_COOKIE_NAME } from "@/lib/constants";
|
import { SEARCH_MODE_COOKIE_NAME } from "@/lib/constants";
|
||||||
|
import { env } from "@/env.mjs";
|
||||||
|
|
||||||
export default async function Home({ params: { domain } }: { params: { domain: string } }) {
|
export default async function Home({ params: { domain } }: { params: { domain: string } }) {
|
||||||
const org = await getOrgFromDomain(domain);
|
const org = await getOrgFromDomain(domain);
|
||||||
|
|
@ -48,6 +49,8 @@ export default async function Home({ params: { domain } }: { params: { domain: s
|
||||||
searchModeCookie?.value === "precise"
|
searchModeCookie?.value === "precise"
|
||||||
) ? searchModeCookie.value : models.length > 0 ? "agentic" : "precise";
|
) ? searchModeCookie.value : models.length > 0 ? "agentic" : "precise";
|
||||||
|
|
||||||
|
const demoExamples = undefined; //await loadDemoExamples(env.SOURCEBOT_DEMO_EXAMPLES_PATH);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center overflow-hidden min-h-screen">
|
<div className="flex flex-col items-center overflow-hidden min-h-screen">
|
||||||
<NavigationMenu
|
<NavigationMenu
|
||||||
|
|
@ -61,6 +64,7 @@ export default async function Home({ params: { domain } }: { params: { domain: s
|
||||||
languageModels={models}
|
languageModels={models}
|
||||||
chatHistory={chatHistory}
|
chatHistory={chatHistory}
|
||||||
initialSearchMode={initialSearchMode}
|
initialSearchMode={initialSearchMode}
|
||||||
|
demoExamples={demoExamples}
|
||||||
/>
|
/>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,8 @@ export const env = createEnv({
|
||||||
DEBUG_WRITE_CHAT_MESSAGES_TO_FILE: booleanSchema.default('false'),
|
DEBUG_WRITE_CHAT_MESSAGES_TO_FILE: booleanSchema.default('false'),
|
||||||
|
|
||||||
LANGFUSE_SECRET_KEY: z.string().optional(),
|
LANGFUSE_SECRET_KEY: z.string().optional(),
|
||||||
|
|
||||||
|
SOURCEBOT_DEMO_EXAMPLES_PATH: z.string().optional(),
|
||||||
},
|
},
|
||||||
// @NOTE: Please make sure of the following:
|
// @NOTE: Please make sure of the following:
|
||||||
// - Make sure you destructure all client variables in
|
// - Make sure you destructure all client variables in
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,29 @@ export const orgMetadataSchema = z.object({
|
||||||
anonymousAccessEnabled: z.boolean().optional(),
|
anonymousAccessEnabled: z.boolean().optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const demoSearchExampleSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
title: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
icon: z.string(),
|
||||||
|
category: z.string(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const demoSearchContextExampleSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
displayName: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
icon: z.string(),
|
||||||
|
color: z.string(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const demoExamplesSchema = z.object({
|
||||||
|
searchExamples: demoSearchExampleSchema.array(),
|
||||||
|
searchContexts: demoSearchContextExampleSchema.array(),
|
||||||
|
})
|
||||||
|
|
||||||
export type OrgMetadata = z.infer<typeof orgMetadataSchema>;
|
export type OrgMetadata = z.infer<typeof orgMetadataSchema>;
|
||||||
|
export type DemoExamples = z.infer<typeof demoExamplesSchema>;
|
||||||
|
export type DemoSearchExample = z.infer<typeof demoSearchExampleSchema>;
|
||||||
|
export type DemoSearchContextExample = z.infer<typeof demoSearchContextExampleSchema>;
|
||||||
Loading…
Reference in a new issue