mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-09 05:39:12 +00:00
Move the create agent button to the bottom of the sidebar and fix experience when resetting settings
This commit is contained in:
@@ -67,6 +67,15 @@ export function ModelSelector({ ...props }: ModelSelectorProps) {
|
|||||||
const model = models.find(model => model.name === props.selectedModel);
|
const model = models.find(model => model.name === props.selectedModel);
|
||||||
setSelectedModel(model);
|
setSelectedModel(model);
|
||||||
}
|
}
|
||||||
|
else if (props.selectedModel === null && userConfig) {
|
||||||
|
const selectedChatModelOption = userConfig.chat_model_options.find(model => model.id === userConfig.selected_chat_model_config);
|
||||||
|
if (!selectedChatModelOption) {
|
||||||
|
props.onSelect(userConfig.chat_model_options[0], false);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
props.onSelect(selectedChatModelOption, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}, [props.selectedModel, models]);
|
}, [props.selectedModel, models]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -145,8 +145,8 @@ function AgentCreationForm(props: IAgentCreationProps) {
|
|||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
className="p-1"
|
className="w-full"
|
||||||
variant="ghost"
|
variant="secondary"
|
||||||
>
|
>
|
||||||
Create Agent
|
Create Agent
|
||||||
</Button>
|
</Button>
|
||||||
@@ -166,131 +166,131 @@ function AgentCreationForm(props: IAgentCreationProps) {
|
|||||||
}
|
}
|
||||||
<DialogClose />
|
<DialogClose />
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
{
|
{
|
||||||
doneCreating && createdSlug ? (
|
doneCreating && createdSlug ? (
|
||||||
<div className="flex flex-col items-center justify-center gap-4 py-8">
|
<div className="flex flex-col items-center justify-center gap-4 py-8">
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ scale: 0 }}
|
initial={{ scale: 0 }}
|
||||||
animate={{ scale: 1 }}
|
animate={{ scale: 1 }}
|
||||||
transition={{
|
transition={{
|
||||||
type: "spring",
|
type: "spring",
|
||||||
stiffness: 260,
|
stiffness: 260,
|
||||||
damping: 20
|
damping: 20
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CheckCircle
|
<CheckCircle
|
||||||
className="w-16 h-16 text-green-500"
|
className="w-16 h-16 text-green-500"
|
||||||
weight="fill"
|
weight="fill"
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
<motion.p
|
<motion.p
|
||||||
initial={{ opacity: 0, y: 10 }}
|
initial={{ opacity: 0, y: 10 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ delay: 0.2 }}
|
transition={{ delay: 0.2 }}
|
||||||
className="text-center text-lg font-medium text-accent-foreground"
|
className="text-center text-lg font-medium text-accent-foreground"
|
||||||
>
|
>
|
||||||
Created successfully!
|
Created successfully!
|
||||||
</motion.p>
|
</motion.p>
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 10 }}
|
initial={{ opacity: 0, y: 10 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ delay: 0.4 }}
|
transition={{ delay: 0.4 }}
|
||||||
>
|
>
|
||||||
<Link href={`/agents?agent=${createdSlug}`}>
|
<Link href={`/agents?agent=${createdSlug}`}>
|
||||||
<Button variant="secondary" className="mt-2">
|
<Button variant="secondary" className="mt-2">
|
||||||
Manage Agent
|
Manage Agent
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
|
||||||
) :
|
|
||||||
<div className="flex flex-col gap-4">
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="agent_name">Name</Label>
|
|
||||||
<Input
|
|
||||||
id="agent_name"
|
|
||||||
className="w-full p-2 border mt-4 border-slate-500 rounded-lg"
|
|
||||||
disabled={isCreating}
|
|
||||||
value={customAgentName}
|
|
||||||
onChange={(e) => setCustomAgentName(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-4">
|
) :
|
||||||
<div className="flex-1">
|
<div className="flex flex-col gap-4">
|
||||||
<Select onValueChange={setCustomAgentColor} defaultValue={customAgentColor}>
|
<div>
|
||||||
<SelectTrigger className="w-full dark:bg-muted" disabled={isCreating}>
|
<Label htmlFor="agent_name">Name</Label>
|
||||||
<SelectValue placeholder="Color" />
|
<Input
|
||||||
</SelectTrigger>
|
id="agent_name"
|
||||||
<SelectContent className="items-center space-y-1 inline-flex flex-col">
|
className="w-full p-2 border mt-4 border-slate-500 rounded-lg"
|
||||||
{colorOptions.map((colorOption) => (
|
disabled={isCreating}
|
||||||
<SelectItem key={colorOption} value={colorOption}>
|
value={customAgentName}
|
||||||
<div className="flex items-center space-x-2">
|
onChange={(e) => setCustomAgentName(e.target.value)}
|
||||||
<Circle
|
/>
|
||||||
className={`w-6 h-6 mr-2 ${convertColorToTextClass(colorOption)}`}
|
|
||||||
weight="fill"
|
|
||||||
/>
|
|
||||||
{colorOption}
|
|
||||||
</div>
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex gap-4">
|
||||||
<Select onValueChange={setCustomAgentIcon} defaultValue={customAgentIcon}>
|
<div className="flex-1">
|
||||||
<SelectTrigger className="w-full dark:bg-muted" disabled={isCreating}>
|
<Select onValueChange={setCustomAgentColor} defaultValue={customAgentColor}>
|
||||||
<SelectValue placeholder="Icon" />
|
<SelectTrigger className="w-full dark:bg-muted" disabled={isCreating}>
|
||||||
</SelectTrigger>
|
<SelectValue placeholder="Color" />
|
||||||
<SelectContent className="items-center space-y-1 inline-flex flex-col">
|
</SelectTrigger>
|
||||||
{iconOptions.map((iconOption) => (
|
<SelectContent className="items-center space-y-1 inline-flex flex-col">
|
||||||
<SelectItem key={iconOption} value={iconOption}>
|
{colorOptions.map((colorOption) => (
|
||||||
<div className="flex items-center space-x-2">
|
<SelectItem key={colorOption} value={colorOption}>
|
||||||
{getIconFromIconName(
|
<div className="flex items-center space-x-2">
|
||||||
iconOption,
|
<Circle
|
||||||
customAgentColor ?? "gray",
|
className={`w-6 h-6 mr-2 ${convertColorToTextClass(colorOption)}`}
|
||||||
"w-6",
|
weight="fill"
|
||||||
"h-6",
|
/>
|
||||||
)}
|
{colorOption}
|
||||||
{iconOption}
|
</div>
|
||||||
</div>
|
</SelectItem>
|
||||||
</SelectItem>
|
))}
|
||||||
))}
|
</SelectContent>
|
||||||
</SelectContent>
|
</Select>
|
||||||
</Select>
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<Select onValueChange={setCustomAgentIcon} defaultValue={customAgentIcon}>
|
||||||
|
<SelectTrigger className="w-full dark:bg-muted" disabled={isCreating}>
|
||||||
|
<SelectValue placeholder="Icon" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent className="items-center space-y-1 inline-flex flex-col">
|
||||||
|
{iconOptions.map((iconOption) => (
|
||||||
|
<SelectItem key={iconOption} value={iconOption}>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
{getIconFromIconName(
|
||||||
|
iconOption,
|
||||||
|
customAgentColor ?? "gray",
|
||||||
|
"w-6",
|
||||||
|
"h-6",
|
||||||
|
)}
|
||||||
|
{iconOption}
|
||||||
|
</div>
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
}
|
</div>
|
||||||
</div>
|
<DialogFooter>
|
||||||
<DialogFooter>
|
{
|
||||||
{
|
error && (
|
||||||
error && (
|
<div className="text-red-500 text-sm">
|
||||||
<div className="text-red-500 text-sm">
|
{error}
|
||||||
{error}
|
</div>
|
||||||
</div>
|
)
|
||||||
)
|
}
|
||||||
}
|
{
|
||||||
{
|
!doneCreating && (
|
||||||
!doneCreating && (
|
<Button
|
||||||
<Button
|
type="submit"
|
||||||
type="submit"
|
onClick={() => createAgent()}
|
||||||
onClick={() => createAgent()}
|
disabled={isCreating || !isValid}
|
||||||
disabled={isCreating || !isValid}
|
>
|
||||||
>
|
{
|
||||||
{
|
isCreating ?
|
||||||
isCreating ?
|
<CircleNotch className="animate-spin" />
|
||||||
<CircleNotch className="animate-spin" />
|
:
|
||||||
:
|
<PersonSimpleTaiChi />
|
||||||
<PersonSimpleTaiChi />
|
}
|
||||||
}
|
Create
|
||||||
Create
|
</Button>
|
||||||
</Button>
|
)
|
||||||
)
|
}
|
||||||
}
|
<DialogClose />
|
||||||
<DialogClose />
|
</DialogFooter>
|
||||||
</DialogFooter>
|
</DialogContent>
|
||||||
</DialogContent>
|
|
||||||
</Dialog >
|
</Dialog >
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -317,6 +317,8 @@ function ChatSidebarInternal({ ...props }: ChatSideBarProps) {
|
|||||||
|
|
||||||
const [isSaving, setIsSaving] = useState<boolean>(false);
|
const [isSaving, setIsSaving] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const isSubscribed = authenticatedData?.is_active ?? false;
|
||||||
|
|
||||||
function setupAgentData() {
|
function setupAgentData() {
|
||||||
if (agentData) {
|
if (agentData) {
|
||||||
setInputTools(agentData.input_tools);
|
setInputTools(agentData.input_tools);
|
||||||
@@ -456,16 +458,6 @@ function ChatSidebarInternal({ ...props }: ChatSideBarProps) {
|
|||||||
<p>
|
<p>
|
||||||
Chat Options
|
Chat Options
|
||||||
</p>
|
</p>
|
||||||
{
|
|
||||||
isEditable && customPrompt && !isDefaultAgent && selectedModel && (
|
|
||||||
<AgentCreationForm
|
|
||||||
customPrompt={customPrompt}
|
|
||||||
selectedModel={selectedModel}
|
|
||||||
inputTools={inputTools ?? []}
|
|
||||||
outputModes={outputModes ?? []}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -508,7 +500,7 @@ function ChatSidebarInternal({ ...props }: ChatSideBarProps) {
|
|||||||
<SidebarGroupLabel>
|
<SidebarGroupLabel>
|
||||||
Model
|
Model
|
||||||
{
|
{
|
||||||
!authenticatedData?.is_active && (
|
!isSubscribed && (
|
||||||
<a href="/settings" className="hover:font-bold text-accent-foreground m-2 bg-accent bg-opacity-10 p-1 rounded-lg">
|
<a href="/settings" className="hover:font-bold text-accent-foreground m-2 bg-accent bg-opacity-10 p-1 rounded-lg">
|
||||||
Upgrade
|
Upgrade
|
||||||
</a>
|
</a>
|
||||||
@@ -518,7 +510,7 @@ function ChatSidebarInternal({ ...props }: ChatSideBarProps) {
|
|||||||
<SidebarMenu className="p-0 m-0">
|
<SidebarMenu className="p-0 m-0">
|
||||||
<SidebarMenuItem key={"model"} className="list-none">
|
<SidebarMenuItem key={"model"} className="list-none">
|
||||||
<ModelSelector
|
<ModelSelector
|
||||||
disabled={!isEditable || !authenticatedData?.is_active}
|
disabled={!isEditable || !isSubscribed}
|
||||||
onSelect={(model, userModification) => handleModelSelect(model.name, userModification)}
|
onSelect={(model, userModification) => handleModelSelect(model.name, userModification)}
|
||||||
initialModel={isDefaultAgent ? undefined : agentData?.chat_model}
|
initialModel={isDefaultAgent ? undefined : agentData?.chat_model}
|
||||||
selectedModel={selectedModel}
|
selectedModel={selectedModel}
|
||||||
@@ -647,6 +639,20 @@ function ChatSidebarInternal({ ...props }: ChatSideBarProps) {
|
|||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
) :
|
) :
|
||||||
<>
|
<>
|
||||||
|
{
|
||||||
|
!hasModified && isEditable && customPrompt && !isDefaultAgent && selectedModel && (
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton asChild>
|
||||||
|
<AgentCreationForm
|
||||||
|
customPrompt={customPrompt}
|
||||||
|
selectedModel={selectedModel}
|
||||||
|
inputTools={inputTools ?? []}
|
||||||
|
outputModes={outputModes ?? []}
|
||||||
|
/>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<SidebarMenuButton asChild>
|
<SidebarMenuButton asChild>
|
||||||
<Button
|
<Button
|
||||||
@@ -679,6 +685,7 @@ function ChatSidebarInternal({ ...props }: ChatSideBarProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
|
|||||||
Reference in New Issue
Block a user