Revert back save button thread setting

This commit is contained in:
Faisal Amir 2024-01-03 22:02:06 +07:00
parent 0f333c35f5
commit a653c58384
12 changed files with 219 additions and 634 deletions

View File

@ -1,76 +1,32 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import React from 'react'
import {
Switch,
Tooltip,
TooltipArrow,
TooltipContent,
TooltipPortal,
TooltipTrigger,
} from '@janhq/uikit'
import { Switch } from '@janhq/uikit'
// import { useAtomValue } from 'jotai'
import { useAtomValue } from 'jotai'
import { InfoIcon } from 'lucide-react'
import useUpdateModelParameters from '@/hooks/useUpdateModelParameters'
// import useUpdateModelParameters from '@/hooks/useUpdateModelParameters'
// import { getActiveThreadIdAtom } from '@/helpers/atoms/Thread.atom'
import { getActiveThreadIdAtom } from '@/helpers/atoms/Thread.atom'
type Props = {
name: string
title: string
description: string
value: boolean
checked: boolean
onBlur: () => void
onChange: (e: boolean) => void
}
const Checkbox: React.FC<Props> = ({
name,
value,
title,
checked,
description,
onChange,
onBlur,
}) => {
// const { updateModelParameter } = useUpdateModelParameters()
// const threadId = useAtomValue(getActiveThreadIdAtom)
const Checkbox: React.FC<Props> = ({ name, title, checked }) => {
const { updateModelParameter } = useUpdateModelParameters()
const threadId = useAtomValue(getActiveThreadIdAtom)
// const onCheckedChange = (checked: boolean) => {
// if (!threadId) return
// updateModelParameter(threadId, name, checked)
// }
const onCheckedChange = (checked: boolean) => {
if (!threadId) return
updateModelParameter(threadId, name, checked)
}
return (
<div className="flex justify-between">
<div className="mb-1 flex items-center gap-x-2">
<p className="text-sm font-semibold text-zinc-500 dark:text-gray-300">
{title}
</p>
<Tooltip>
<TooltipTrigger asChild>
<InfoIcon size={16} className="flex-shrink-0 dark:text-gray-500" />
</TooltipTrigger>
<TooltipPortal>
<TooltipContent side="top" className="max-w-[240px]">
<span>{description}</span>
<TooltipArrow />
</TooltipContent>
</TooltipPortal>
</Tooltip>
</div>
<Switch
name={name}
checked={value !== undefined ? value : checked}
onCheckedChange={(e) => onChange(e)}
onBlur={onBlur}
/>
<p className="mb-2 text-sm font-semibold text-gray-600">{title}</p>
<Switch checked={checked} onCheckedChange={onCheckedChange} />
</div>
)
}

View File

@ -16,14 +16,13 @@ import {
} from '@janhq/uikit'
import { motion as m } from 'framer-motion'
import { useAtomValue } from 'jotai'
import {
MessageCircleIcon,
SettingsIcon,
MonitorIcon,
LayoutGridIcon,
Twitter,
Github,
// Twitter,
// Github,
} from 'lucide-react'
import { twMerge } from 'tailwind-merge'
@ -34,13 +33,8 @@ import { MainViewState } from '@/constants/screens'
import { useMainViewState } from '@/hooks/useMainViewState'
import { threadSettingFormUpdateAtom } from '@/helpers/atoms/Thread.atom'
export default function RibbonNav() {
const { mainViewState, setMainViewState } = useMainViewState()
const threadSettingFormUpdate = useAtomValue(threadSettingFormUpdateAtom)
const [showModalUpdateThreadSetting, setshowModalUpdateThreadSetting] =
useState({ show: false, view: mainViewState })
const onMenuClick = (state: MainViewState) => {
if (mainViewState === state) return
@ -70,22 +64,22 @@ export default function RibbonNav() {
},
]
const linksMenu = [
{
name: 'Twitter',
icon: (
<Twitter size={20} className="flex-shrink-0 text-muted-foreground" />
),
link: 'https://twitter.com/janhq_',
},
{
name: 'Github',
icon: (
<Github size={20} className="flex-shrink-0 text-muted-foreground" />
),
link: 'https://github.com/janhq/jan',
},
]
// const linksMenu = [
// {
// name: 'Twitter',
// icon: (
// <Twitter size={20} className="flex-shrink-0 text-muted-foreground" />
// ),
// link: 'https://twitter.com/janhq_',
// },
// {
// name: 'Github',
// icon: (
// <Github size={20} className="flex-shrink-0 text-muted-foreground" />
// ),
// link: 'https://github.com/janhq/jan',
// },
// ]
const secondaryMenus = [
{
@ -132,23 +126,7 @@ export default function RibbonNav() {
'relative flex w-full flex-shrink-0 cursor-pointer items-center justify-center',
isActive && 'z-10'
)}
onClick={() => {
if (
threadSettingFormUpdate &&
mainViewState === MainViewState.Thread
) {
setshowModalUpdateThreadSetting({
show: true,
view: primary.state,
})
} else {
setshowModalUpdateThreadSetting({
show: false,
view: mainViewState,
})
onMenuClick(primary.state)
}
}}
onClick={() => onMenuClick(primary.state)}
>
{primary.icon}
</div>
@ -170,7 +148,8 @@ export default function RibbonNav() {
</div>
<div>
<>
{/* Temporary hidden social media until we finalize design */}
{/* <>
{linksMenu
.filter((link) => !!link)
.map((link, i) => {
@ -195,7 +174,8 @@ export default function RibbonNav() {
</div>
)
})}
</>
</> */}
{secondaryMenus
.filter((secondary) => !!secondary)
.map((secondary, i) => {
@ -210,23 +190,7 @@ export default function RibbonNav() {
'relative flex w-full flex-shrink-0 cursor-pointer items-center justify-center',
isActive && 'z-10'
)}
onClick={() => {
if (
threadSettingFormUpdate &&
mainViewState === MainViewState.Thread
) {
setshowModalUpdateThreadSetting({
show: true,
view: secondary.state,
})
} else {
setshowModalUpdateThreadSetting({
show: false,
view: mainViewState,
})
onMenuClick(secondary.state)
}
}}
onClick={() => onMenuClick(secondary.state)}
>
{secondary.icon}
</div>
@ -248,53 +212,6 @@ export default function RibbonNav() {
</div>
</div>
</div>
<Modal
open={showModalUpdateThreadSetting.show}
onOpenChange={() =>
setshowModalUpdateThreadSetting({
show: false,
view: mainViewState,
})
}
>
<ModalContent>
<ModalHeader>
<ModalTitle>
<div className="text-lg">Unsave changes</div>
</ModalTitle>
<ModalDescription>
<p className="mb-2">
You have unsave changes. Are you sure you want to leave this
page?
</p>
</ModalDescription>
</ModalHeader>
<ModalFooter>
<div className="flex gap-x-2">
<ModalClose asChild>
<Button themes="secondary" block>
Stay
</Button>
</ModalClose>
<Button
themes="danger"
autoFocus
block
onClick={() => {
setshowModalUpdateThreadSetting({
show: false,
view: mainViewState,
})
onMenuClick(showModalUpdateThreadSetting.view)
}}
>
Leave
</Button>
</div>
</ModalFooter>
</ModalContent>
</Modal>
</div>
)
}

View File

@ -181,7 +181,7 @@ const TopBar = () => {
/>
<div className="flex flex-col">
<span className="font-medium text-black dark:text-muted-foreground">
View as JSON
Edit Threads Settings
</span>
<span className="mt-1 text-muted-foreground">
Opens thread.json. Changes affect this thread

View File

@ -1,71 +1,39 @@
import {
Textarea,
Tooltip,
TooltipPortal,
TooltipArrow,
TooltipContent,
TooltipTrigger,
} from '@janhq/uikit'
import { Textarea } from '@janhq/uikit'
// import { useAtomValue } from 'jotai'
import { useAtomValue } from 'jotai'
import { InfoIcon } from 'lucide-react'
import useUpdateModelParameters from '@/hooks/useUpdateModelParameters'
// import useUpdateModelParameters from '@/hooks/useUpdateModelParameters'
// import { getActiveThreadIdAtom } from '@/helpers/atoms/Thread.atom'
import { getActiveThreadIdAtom } from '@/helpers/atoms/Thread.atom'
type Props = {
title: string
name: string
description: string
placeholder: string
value: string
onBlur: () => void
onChange: () => void
}
const ModelConfigInput: React.FC<Props> = ({
title,
name,
value,
description,
placeholder,
onChange,
onBlur,
}) => {
// const { updateModelParameter } = useUpdateModelParameters()
// const threadId = useAtomValue(getActiveThreadIdAtom)
const { updateModelParameter } = useUpdateModelParameters()
const threadId = useAtomValue(getActiveThreadIdAtom)
// const onValueChanged = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
// if (!threadId) return
const onValueChanged = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
if (!threadId) return
// updateModelParameter(threadId, name, e.target.value)
// }
updateModelParameter(threadId, name, e.target.value)
}
return (
<div className="flex flex-col">
<div className="mb-4 flex items-center gap-x-2">
<p className="text-sm font-semibold text-zinc-500 dark:text-gray-300">
{title}
</p>
<Tooltip>
<TooltipTrigger asChild>
<InfoIcon size={16} className="flex-shrink-0 dark:text-gray-500" />
</TooltipTrigger>
<TooltipPortal>
<TooltipContent side="top" className="max-w-[240px]">
<span>{description}</span>
<TooltipArrow />
</TooltipContent>
</TooltipPortal>
</Tooltip>
</div>
<p className="mb-2 text-sm font-semibold text-gray-600">{title}</p>
<Textarea
name={name}
placeholder={placeholder}
onChange={onChange}
onBlur={onBlur}
onChange={onValueChanged}
value={value}
/>
</div>

View File

@ -1,30 +1,19 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import React from 'react'
import { Slider, Input, TooltipPortal } from '@janhq/uikit'
import {
Tooltip,
TooltipContent,
TooltipTrigger,
TooltipArrow,
} from '@janhq/uikit'
// import { useAtomValue } from 'jotai'
import { InfoIcon } from 'lucide-react'
import { Slider, Input } from '@janhq/uikit'
import { useAtomValue } from 'jotai'
// import useUpdateModelParameters from '@/hooks/useUpdateModelParameters'
import useUpdateModelParameters from '@/hooks/useUpdateModelParameters'
// import { getActiveThreadIdAtom } from '@/helpers/atoms/Thread.atom'
import { getActiveThreadIdAtom } from '@/helpers/atoms/Thread.atom'
type Props = {
name: string
description: string
title: string
min: number
max: number
step: number
value: number[]
onChange: (e: any) => void
onBlur: (e: any) => void
value: number
}
const SliderRightPanel: React.FC<Props> = ({
@ -32,50 +21,29 @@ const SliderRightPanel: React.FC<Props> = ({
title,
min,
max,
description,
onChange,
onBlur,
step,
value,
}) => {
// const { updateModelParameter } = useUpdateModelParameters()
// const threadId = useAtomValue(getActiveThreadIdAtom)
const { updateModelParameter } = useUpdateModelParameters()
const threadId = useAtomValue(getActiveThreadIdAtom)
// const onValueChanged = (e: number[]) => {
// if (!threadId) return
// updateModelParameter(threadId, name, e[0])
// }
const onValueChanged = (e: number[]) => {
if (!threadId) return
updateModelParameter(threadId, name, e[0])
}
return (
<div className="flex flex-col">
<div className="mb-4 flex items-center gap-x-2">
<p className="text-sm font-semibold text-zinc-500 dark:text-gray-300">
{title}
</p>
<Tooltip>
<TooltipTrigger asChild>
<InfoIcon size={16} className="flex-shrink-0 dark:text-gray-500" />
</TooltipTrigger>
<TooltipPortal>
<TooltipContent side="top" className="max-w-[240px]">
<span>{description}</span>
<TooltipArrow />
</TooltipContent>
</TooltipPortal>
</Tooltip>
</div>
<p className="mb-2 text-sm font-semibold text-gray-600">{title}</p>
<div className="flex items-center gap-x-4">
<div className="relative w-full">
<Slider
defaultValue={value}
onValueChange={(e) => onChange(e[0])}
onChange={(e) => onChange(e)}
onBlur={onBlur}
name={name}
value={[value]}
onValueChange={onValueChanged}
min={min}
max={max}
step={step}
value={value}
/>
<div className="relative mt-2 flex items-center justify-between text-gray-400">
<p className="text-sm">{min}</p>
@ -89,10 +57,8 @@ const SliderRightPanel: React.FC<Props> = ({
className="-mt-4 h-8 w-16"
min={min}
max={max}
name={name}
value={value[0] || String(value[0])}
onChange={(e) => onChange([e.target.value])}
onBlur={onBlur}
value={String(value)}
onChange={(e) => onValueChanged([Number(e.target.value)])}
/>
</div>
</div>

View File

@ -7,8 +7,6 @@ import {
} from '@janhq/core'
import { atom } from 'jotai'
export const threadSettingFormUpdateAtom = atom<boolean>(false)
/**
* Stores the current active thread id.
*/

View File

@ -25,7 +25,11 @@ export default function useUpdateModelParameters() {
const activeThreadState = useAtomValue(activeThreadStateAtom)
const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom)
const updateModelParameter = async (threadId: string, values: any) => {
const updateModelParameter = async (
threadId: string,
name: string,
value: number | boolean | string
) => {
const thread = threads.find((thread) => thread.id === threadId)
if (!thread) {
console.error(`Thread ${threadId} not found`)
@ -36,10 +40,9 @@ export default function useUpdateModelParameters() {
console.error('No active thread')
return
}
const updatedModelParams: ModelParams = {
...activeModelParams,
...values,
[name]: value,
}
// update the state

View File

@ -10,7 +10,7 @@ import settingComponentBuilder from '../ModelSetting/settingComponentBuilder'
import { getActiveThreadModelParamsAtom } from '@/helpers/atoms/Thread.atom'
const EngineSetting = (props: { form: any }) => {
const EngineSetting = () => {
const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom)
const selectedModel = useAtomValue(selectedModelAtom)
@ -24,7 +24,7 @@ const EngineSetting = (props: { form: any }) => {
return (
<div className="flex flex-col">
{settingComponentBuilder(componentData, props.form)}
{settingComponentBuilder(componentData)}
</div>
)
}

View File

@ -12,7 +12,7 @@ import settingComponentBuilder from './settingComponentBuilder'
import { getActiveThreadModelParamsAtom } from '@/helpers/atoms/Thread.atom'
const ModelSetting = (props: { form: any }) => {
const ModelSetting = () => {
const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom)
const selectedModel = useAtomValue(selectedModelAtom)
@ -26,7 +26,7 @@ const ModelSetting = (props: { form: any }) => {
return (
<div className="flex flex-col">
{settingComponentBuilder(componentData, props.form)}
{settingComponentBuilder(componentData)}
</div>
)
}

View File

@ -1,7 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-case-declarations */
import { FormControl, FormField, FormItem, FormMessage } from '@janhq/uikit'
import Checkbox from '@/containers/Checkbox'
import ModelConfigInput from '@/containers/ModelConfigInput'
import Slider from '@/containers/Slider'
@ -34,7 +31,6 @@ type CheckboxData = {
const settingComponentBuilder = (
componentData: SettingComponentData[],
form?: any,
onlyPrompt?: boolean
) => {
const components = componentData
@ -46,80 +42,36 @@ const settingComponentBuilder = (
case 'slider':
const { min, max, step, value } = data.controllerData as SliderData
return (
<FormField
key={data.title}
control={form.control}
<Slider
key={data.name}
title={data.title}
min={min}
max={max}
step={step}
value={value}
name={data.name}
render={({ field }) => (
<>
<FormItem>
<FormControl>
<Slider
key={data.name}
title={data.title}
description={data.description}
min={min}
max={max}
step={step}
{...field}
value={[field.value || value]}
/>
</FormControl>
<FormMessage />
</FormItem>
</>
)}
/>
)
case 'input':
const { placeholder, value: textValue } =
data.controllerData as InputData
return (
<FormField
key={data.title}
control={form.control}
<ModelConfigInput
title={data.title}
key={data.name}
name={data.name}
render={({ field }) => (
<FormItem>
<FormControl>
<ModelConfigInput
title={data.title}
key={data.name}
description={data.description}
placeholder={placeholder}
{...field}
value={field.value}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
placeholder={placeholder}
value={textValue}
/>
)
case 'checkbox':
const { checked } = data.controllerData as CheckboxData
return (
<FormField
key={data.title}
control={form.control}
<Checkbox
key={data.name}
name={data.name}
render={({ field }) => (
<>
<FormItem>
<FormControl>
<Checkbox
key={data.name}
description={data.description}
title={data.title}
{...field}
checked={field.value || checked}
value={field.value}
/>
</FormControl>
<FormMessage />
</FormItem>
</>
)}
title={data.title}
checked={checked}
/>
)
default:

View File

@ -1,25 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { useEffect } from 'react'
import { FieldValues, useForm } from 'react-hook-form'
import React from 'react'
import { getUserSpace, openFileExplorer, joinPath } from '@janhq/core'
import {
Input,
Textarea,
Form,
Button,
FormField,
FormItem,
Tooltip,
TooltipArrow,
TooltipContent,
TooltipPortal,
TooltipTrigger,
FormControl,
} from '@janhq/uikit'
import { Input, Textarea } from '@janhq/uikit'
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai'
import { atom, useAtomValue } from 'jotai'
import { twMerge } from 'tailwind-merge'
@ -30,14 +16,10 @@ import DropdownListSidebar, {
selectedModelAtom,
} from '@/containers/DropdownListSidebar'
import { currentPromptAtom } from '@/containers/Providers/Jotai'
import { useCreateNewThread } from '@/hooks/useCreateNewThread'
import useUpdateModelParameters from '@/hooks/useUpdateModelParameters'
import { getConfigurationsData } from '@/utils/componentSettings'
import { toRuntimeParams, toSettingParams } from '@/utils/model_param'
import { toSettingParams } from '@/utils/model_param'
import EngineSetting from '../EngineSetting'
import ModelSetting from '../ModelSetting'
@ -46,9 +28,7 @@ import settingComponentBuilder from '../ModelSetting/settingComponentBuilder'
import {
activeThreadAtom,
getActiveThreadIdAtom,
getActiveThreadModelParamsAtom,
threadSettingFormUpdateAtom,
threadStatesAtom,
} from '@/helpers/atoms/Thread.atom'
@ -60,39 +40,11 @@ const Sidebar: React.FC = () => {
const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom)
const selectedModel = useAtomValue(selectedModelAtom)
const { updateThreadMetadata } = useCreateNewThread()
const { updateModelParameter } = useUpdateModelParameters()
const threadStates = useAtomValue(threadStatesAtom)
const threadId = useAtomValue(getActiveThreadIdAtom)
const modelEngineParams = toSettingParams(activeModelParams)
const componentDataEngineSetting = getConfigurationsData(modelEngineParams)
const modelRuntimeParams = toRuntimeParams(activeModelParams)
const componentDataRuntimeSetting = getConfigurationsData(modelRuntimeParams)
const setThreadSettingFormUpdate = useSetAtom(threadSettingFormUpdateAtom)
const [currentPrompt] = useAtom(currentPromptAtom)
const componentData = [
...[
{ name: 'title', controllerData: { value: activeThread?.title } },
{
name: 'instructions',
controllerData: { value: activeThread?.assistants[0].instructions },
},
],
...componentDataRuntimeSetting,
...componentDataEngineSetting,
]
const defaultValues = componentData.reduce(
(obj: any, item: { name: any; controllerData: any }) =>
Object.assign(obj, {
[item.name]: item.controllerData.value
? item.controllerData.value
: item.controllerData.checked,
}),
{}
)
const onReviewInFinderClick = async (type: string) => {
if (!activeThread) return
@ -160,79 +112,6 @@ const Sidebar: React.FC = () => {
openFileExplorer(fullPath)
}
const form = useForm({ defaultValues })
const filterChangedFormFields = <T extends FieldValues>(
allFields: T,
dirtyFields: Partial<Record<keyof T, boolean | boolean[]>>
): Partial<T> => {
const changedFieldValues = Object.keys(dirtyFields).reduce(
(acc, currentField) => {
const isDirty = Array.isArray(dirtyFields[currentField])
? (dirtyFields[currentField] as boolean[]).some((value) => {
value === true
})
: dirtyFields[currentField] === true
if (isDirty) {
return {
...acc,
[currentField]: allFields[currentField],
}
}
return acc
},
{} as Partial<T>
)
return changedFieldValues
}
const isEngineParamsChanges = componentDataEngineSetting.some((x) =>
Object.keys(form.formState.dirtyFields).includes(x.name)
)
const onSubmit = async (values: any) => {
if (!threadId) return
if (!activeThread) return
if (Object.keys(form.formState.dirtyFields).length) {
if (
Object.keys(form.formState.dirtyFields).includes('title') ||
Object.keys(form.formState.dirtyFields).includes('instructions')
) {
updateThreadMetadata({
...activeThread,
title: values.title || activeThread.title,
assistants: [
{
...activeThread.assistants[0],
instructions:
values.instructions || activeThread?.assistants[0].instructions,
},
],
})
}
updateModelParameter(
threadId,
filterChangedFormFields(values, form.formState.dirtyFields)
)
form.reset({}, { keepValues: true })
}
}
const onCancel = () => {
form.reset()
}
// Detect event click after changes value in form to showing tooltip on save button
useEffect(() => {
if (Object.keys(form.formState.dirtyFields).length !== 0) {
setThreadSettingFormUpdate(true)
} else {
setThreadSettingFormUpdate(false)
}
}, [form.formState, setThreadSettingFormUpdate])
return (
<div
className={twMerge(
@ -242,102 +121,84 @@ const Sidebar: React.FC = () => {
: 'w-0 translate-x-full opacity-0'
)}
>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<div
className={twMerge(
'flex flex-col gap-1 delay-200',
showing ? 'animate-enter opacity-100' : 'opacity-0'
)}
>
<div className="flex flex-col space-y-4 p-4">
<div>
<label
id="thread-title"
className="mb-2 inline-block font-bold text-zinc-500 dark:text-gray-300"
>
Title
</label>
<FormField
key={activeThread?.title}
control={form.control}
name="title"
render={({ field }) => (
<>
<FormItem>
<FormControl>
<Input
id="thread-title"
{...field}
defaultValue={activeThread?.title}
name="title"
onChange={(e) => field.onChange(e)}
value={field.value}
/>
</FormControl>
</FormItem>
</>
)}
/>
</div>
<div className="flex flex-col">
<label
id="thread-title"
className="mb-2 inline-block font-bold text-zinc-500 dark:text-gray-300"
>
Threads ID
</label>
<span className="text-xs text-muted-foreground">
{activeThread?.id || '-'}
</span>
</div>
</div>
<CardSidebar
title="Assistant"
onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick}
<div
className={twMerge(
'flex flex-col gap-1 delay-200',
showing ? 'animate-enter opacity-100' : 'opacity-0'
)}
>
<div className="flex flex-col space-y-4 p-4">
<div>
<label
id="thread-title"
className="mb-2 inline-block font-bold text-gray-600 dark:text-gray-300"
>
<div className="flex flex-col space-y-4 p-2">
<div className="flex items-center space-x-2">
<LogoMark width={24} height={24} />
<span className="font-bold capitalize">
{activeThread?.assistants[0].assistant_name ?? '-'}
</span>
</div>
<div>
<label
id="thread-title"
className="mb-2 inline-block font-bold text-zinc-500 dark:text-gray-300"
>
Instructions
</label>
<FormField
key={activeThread?.title}
control={form.control}
name="instructions"
render={({ field }) => (
<>
<FormItem>
<FormControl>
<Textarea
id="assistant-instructions"
placeholder="Eg. You are a helpful assistant."
{...field}
name="instructions"
defaultValue={
activeThread?.assistants[0].instructions
}
value={field.value}
/>
</FormControl>
</FormItem>
</>
)}
/>
</div>
{/* Temporary disabled */}
{/* <div>
Title
</label>
<Input
id="thread-title"
value={activeThread?.title}
onChange={(e) => {
if (activeThread)
updateThreadMetadata({
...activeThread,
title: e.target.value || '',
})
}}
/>
</div>
<div className="flex flex-col">
<label
id="thread-title"
className="mb-2 inline-block font-bold text-zinc-500 dark:text-gray-300"
>
Threads ID
</label>
<span className="text-xs text-muted-foreground">
{activeThread?.id || '-'}
</span>
</div>
</div>
<CardSidebar
title="Assistant"
onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick}
>
<div className="flex flex-col space-y-4 p-2">
<div className="flex items-center space-x-2">
<LogoMark width={24} height={24} />
<span className="font-bold capitalize">
{activeThread?.assistants[0].assistant_name ?? '-'}
</span>
</div>
<div>
<label
id="thread-title"
className="mb-2 inline-block font-bold text-zinc-500 dark:text-gray-300"
>
Instructions
</label>
<Textarea
id="assistant-instructions"
placeholder="Eg. You are a helpful assistant."
value={activeThread?.assistants[0].instructions ?? ''}
onChange={(e) => {
if (activeThread)
updateThreadMetadata({
...activeThread,
assistants: [
{
...activeThread.assistants[0],
instructions: e.target.value || '',
},
],
})
}}
/>
</div>
{/* Temporary disabled */}
{/* <div>
<label
id="tool-title"
className="mb-2 inline-block font-bold text-zinc-500 dark:text-gray-300"
@ -351,78 +212,49 @@ const Sidebar: React.FC = () => {
<Switch name="retrieval" />
</div>
</div> */}
</div>
</CardSidebar>
<CardSidebar
title="Model"
onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick}
>
<div className="px-2">
<div className="mt-4">
<DropdownListSidebar />
</div>
<div className="mt-6">
<CardSidebar title="Inference Parameters" asChild>
<div className="p-2">
<ModelSetting form={form} />
</div>
</CardSidebar>
</div>
<div className="mt-4">
<CardSidebar title="Model Parameters" asChild>
<div className="p-2">
{settingComponentBuilder(
componentDataEngineSetting,
form,
true
)}
</div>
</CardSidebar>
</div>
<div className="my-4">
<CardSidebar
title="Engine Parameters"
onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick}
asChild
>
<div className="p-2">
<EngineSetting form={form} />
</div>
</CardSidebar>
</div>
{Object.keys(form.formState.dirtyFields).length !== 0 && (
<div className="sticky bottom-0 -ml-4 w-[calc(100%+32px)] border-t border-border bg-background px-4 py-3">
<div className="flex gap-3">
<Button themes="secondaryBlue" block onClick={onCancel}>
Cancel
</Button>
<Tooltip open={currentPrompt.length !== 0}>
<TooltipTrigger asChild>
<Button type="submit" block>
{isEngineParamsChanges ? 'Save & Reload' : 'Save'}
</Button>
</TooltipTrigger>
<TooltipPortal>
<TooltipContent side="top" className="max-w-[240px]">
<span>{`It seems changes haven't been saved yet`}</span>
<TooltipArrow />
</TooltipContent>
</TooltipPortal>
</Tooltip>
</div>
</div>
)}
</div>
</CardSidebar>
</div>
</form>
</Form>
</CardSidebar>
<CardSidebar
title="Model"
onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick}
>
<div className="px-2">
<div className="mt-4">
<DropdownListSidebar />
</div>
<div className="mt-6">
<CardSidebar title="Inference Parameters" asChild>
<div className="p-2">
<ModelSetting />
</div>
</CardSidebar>
</div>
<div className="mt-4">
<CardSidebar title="Model Parameters" asChild>
<div className="p-2">
{settingComponentBuilder(componentDataEngineSetting, true)}
</div>
</CardSidebar>
</div>
<div className="my-4">
<CardSidebar
title="Engine Parameters"
onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick}
asChild
>
<div className="p-2">
<EngineSetting />
</div>
</CardSidebar>
</div>
</div>
</CardSidebar>
</div>
</div>
)
}

View File

@ -30,7 +30,7 @@ import ThreadList from '@/screens/Chat/ThreadList'
import Sidebar, { showRightSideBarAtom } from './Sidebar'
import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'
import { threadSettingFormUpdateAtom } from '@/helpers/atoms/Thread.atom'
import {
activeThreadAtom,
getActiveThreadIdAtom,
@ -61,8 +61,6 @@ const ChatScreen = () => {
const textareaRef = useRef<HTMLTextAreaElement>(null)
const modelRef = useRef(activeModel)
const threadSettingFormUpdate = useAtomValue(threadSettingFormUpdateAtom)
useEffect(() => {
modelRef.current = activeModel
}, [activeModel])
@ -174,12 +172,7 @@ const ChatScreen = () => {
{messages[messages.length - 1]?.status !== MessageStatus.Pending ? (
<Button
size="lg"
disabled={
disabled ||
stateModel.loading ||
!activeThread ||
threadSettingFormUpdate
}
disabled={disabled || stateModel.loading || !activeThread}
themes="primary"
className="min-w-[100px]"
onClick={sendChatMessage}