diff --git a/src/interface/web/app/common/modelSelector.tsx b/src/interface/web/app/common/modelSelector.tsx index ae0e6d4f..d5716c1d 100644 --- a/src/interface/web/app/common/modelSelector.tsx +++ b/src/interface/web/app/common/modelSelector.tsx @@ -28,22 +28,29 @@ import { ModelOptions, useChatModelOptions } from "./auth"; import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card"; import { Skeleton } from "@/components/ui/skeleton"; -export function ModelSelector({ ...props }: PopoverProps) { +interface ModelSelectorProps extends PopoverProps { + onSelect: (model: ModelOptions) => void; + selectedModel?: string; + disabled?: boolean; +} + +export function ModelSelector({ ...props }: ModelSelectorProps) { const [open, setOpen] = React.useState(false) const { models, isLoading, error } = useChatModelOptions(); const [peekedModel, setPeekedModel] = useState(undefined); const [selectedModel, setSelectedModel] = useState(undefined); useEffect(() => { - if (models && models.length > 0) { - setSelectedModel(models[0]) + if (!models?.length) return; + + if (props.selectedModel) { + const model = models.find(model => model.name === props.selectedModel); + setSelectedModel(model || models[0]); + return; } - if (models && models.length > 0 && !selectedModel) { - setSelectedModel(models[0]) - } - - }, [models]); + setSelectedModel(models[0]); + }, [models, props.selectedModel]); if (isLoading) { return ( @@ -67,9 +74,10 @@ export function ModelSelector({ ...props }: PopoverProps) { aria-expanded={open} aria-label="Select a model" className="w-full justify-between text-left" + disabled={props.disabled ?? false} >

- {selectedModel ? selectedModel.name.substring(0,20) : "Select a model..."} + {selectedModel ? selectedModel.name.substring(0, 20) : "Select a model..."}

@@ -157,7 +165,7 @@ function ModelItem({ model, isSelected, onSelect, onPeek }: ModelItemProps) { key={model.id} onSelect={onSelect} ref={ref} - className="data-[selected=true]:bg-primary data-[selected=true]:text-primary-foreground" + className="data-[selected=true]:bg-muted data-[selected=true]:text-secondary-foreground" > {model.name} -
+

{usingConversationContext ? "Manage Context" : "Files"} @@ -424,7 +424,7 @@ function SessionsAndFiles(props: SessionsAndFilesProps) {
{props.subsetOrganizedData != null && diff --git a/src/interface/web/app/components/chatSidebar/chatSidebar.tsx b/src/interface/web/app/components/chatSidebar/chatSidebar.tsx index 8ebd3243..8047a97b 100644 --- a/src/interface/web/app/components/chatSidebar/chatSidebar.tsx +++ b/src/interface/web/app/components/chatSidebar/chatSidebar.tsx @@ -1,21 +1,28 @@ "use client" -import * as React from "react" - -import { Bell } from "@phosphor-icons/react"; +import { ArrowsDownUp, Bell, CaretCircleDown, Sparkle } from "@phosphor-icons/react"; import { Button } from "@/components/ui/button"; -import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "@/components/ui/sidebar"; -import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; +import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "@/components/ui/sidebar"; +import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { Textarea } from "@/components/ui/textarea"; import { ModelSelector } from "@/app/common/modelSelector"; import { FilesMenu } from "../allConversations/allConversations"; import { AgentConfigurationOptions } from "@/app/agents/page"; import useSWR from "swr"; import { Sheet, SheetContent } from "@/components/ui/sheet"; +import { AgentData } from "../agentCard/agentCard"; +import { useState } from "react"; +import { getIconForSlashCommand, getIconFromIconName } from "@/app/common/iconUtils"; +import { Label } from "@/components/ui/label"; +import { Checkbox } from "@/components/ui/checkbox"; +import { Tooltip, TooltipTrigger } from "@/components/ui/tooltip"; +import { TooltipContent } from "@radix-ui/react-tooltip"; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; interface ChatSideBarProps { + preexistingAgent?: AgentData | null; conversationId: string; isOpen: boolean; isMobileWidth?: boolean; @@ -47,13 +54,28 @@ export function ChatSidebar({ ...props }: ChatSideBarProps) { function ChatSidebarInternal({ ...props }: ChatSideBarProps) { + const isEditable = props.preexistingAgent?.name.toLowerCase() === "khoj" || props.preexistingAgent?.is_hidden === true; + const isDefaultAgent = props.preexistingAgent?.name.toLowerCase() === "khoj"; const { data: agentConfigurationOptions, error: agentConfigurationOptionsError } = useSWR("/api/agents/options", fetcher); + const [customPrompt, setCustomPrompt] = useState(!isDefaultAgent && props.preexistingAgent ? props.preexistingAgent.persona : "always respond in spanish"); + const [selectedModel, setSelectedModel] = useState(props.preexistingAgent?.chat_model); + const [inputTools, setInputTools] = useState(props.preexistingAgent?.input_tools); + + + function isValueChecked(value: string, existingSelections: string[] | undefined): boolean { + if (existingSelections === undefined || existingSelections === null || existingSelections.length === 0) { + return true; + } + + return existingSelections.includes(value); + } + return ( - Chat Options + { + props.preexistingAgent && !isEditable ? ( + + ) : ( +
+ {getIconFromIconName("lightbulb", "orange")} + Chat Options +
+ ) + }
- + - - Custom Instructions -