diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/AgentLLMSelection/AgentLLMItem/index.jsx b/frontend/src/pages/WorkspaceSettings/AgentConfig/AgentLLMSelection/AgentLLMItem/index.jsx index 10bb03473c355a3cfdc2188b1da75384c3ece2c7..02be032dc706058f2687342083c20f151e459b7a 100644 --- a/frontend/src/pages/WorkspaceSettings/AgentConfig/AgentLLMSelection/AgentLLMItem/index.jsx +++ b/frontend/src/pages/WorkspaceSettings/AgentConfig/AgentLLMSelection/AgentLLMItem/index.jsx @@ -4,11 +4,12 @@ import { createPortal } from "react-dom"; import ModalWrapper from "@/components/ModalWrapper"; import { useModal } from "@/hooks/useModal"; -import { X } from "@phosphor-icons/react"; +import { X, Gear } from "@phosphor-icons/react"; import System from "@/models/system"; import showToast from "@/utils/toast"; +import { useEffect, useState } from "react"; -export default function WorkspaceLLM({ +export default function AgentLLMItem({ llm, availableLLMs, settings, @@ -17,18 +18,31 @@ export default function WorkspaceLLM({ }) { const { isOpen, openModal, closeModal } = useModal(); const { name, value, logo, description } = llm; + const [currentSettings, setCurrentSettings] = useState(settings); + + useEffect(() => { + async function getSettings() { + if (isOpen) { + const _settings = await System.keys(); + setCurrentSettings(_settings ?? {}); + } + } + getSettings(); + }, [isOpen]); function handleProviderSelection() { // Determine if provider needs additional setup because its minimum required keys are // not yet set in settings. - const requiresAdditionalSetup = (llm.requiredConfig || []).some( - (key) => !settings[key] - ); - if (requiresAdditionalSetup) { - openModal(); - return; + if (!checked) { + const requiresAdditionalSetup = (llm.requiredConfig || []).some( + (key) => !currentSettings[key] + ); + if (requiresAdditionalSetup) { + openModal(); + return; + } + onClick(value); } - onClick(value); } return ( @@ -47,16 +61,30 @@ export default function WorkspaceLLM({ readOnly={true} formNoValidate={true} /> - <div className="flex gap-x-4 items-center"> - <img - src={logo} - alt={`${name} logo`} - className="w-10 h-10 rounded-md" - /> - <div className="flex flex-col"> - <div className="text-sm font-semibold text-white">{name}</div> - <div className="mt-1 text-xs text-white/60">{description}</div> + <div className="flex gap-x-4 items-center justify-between"> + <div className="flex gap-x-4 items-center"> + <img + src={logo} + alt={`${name} logo`} + className="w-10 h-10 rounded-md" + /> + <div className="flex flex-col"> + <div className="text-sm font-semibold text-white">{name}</div> + <div className="mt-1 text-xs text-white/60">{description}</div> + </div> </div> + {checked && value !== "none" && ( + <button + onClick={(e) => { + e.preventDefault(); + openModal(); + }} + className="p-2 text-white/60 hover:text-white hover:bg-theme-bg-hover rounded-md transition-all duration-300" + title="Edit Settings" + > + <Gear size={20} weight="bold" /> + </button> + )} </div> </div> <SetupProvider @@ -65,6 +93,7 @@ export default function WorkspaceLLM({ provider={value} closeModal={closeModal} postSubmit={onClick} + settings={currentSettings} /> </> ); @@ -76,6 +105,7 @@ function SetupProvider({ provider, closeModal, postSubmit, + settings, }) { if (!isOpen) return null; const LLMOption = availableLLMs.find((llm) => llm.value === provider); @@ -107,7 +137,7 @@ function SetupProvider({ <div className="relative p-6 border-b rounded-t border-theme-modal-border"> <div className="w-full flex gap-x-2 items-center"> <h3 className="text-xl font-semibold text-white overflow-hidden overflow-ellipsis whitespace-nowrap"> - Setup {LLMOption.name} + {LLMOption.name} Settings </h3> </div> <button @@ -120,12 +150,14 @@ function SetupProvider({ </div> <form id="provider-form" onSubmit={handleUpdate}> <div className="px-7 py-6"> - <div className="space-y-6 max-h-[60vh] overflow-y-auto pr-2"> + <div className="space-y-6 max-h-[60vh] overflow-y-auto p-1"> <p className="text-sm text-white/60"> - To use {LLMOption.name} as this workspace's LLM you need to - set it up first. + To use {LLMOption.name} as this workspace's agent LLM you need + to set it up first. </p> - <div>{LLMOption.options({ credentialsOnly: true })}</div> + <div> + {LLMOption.options(settings, { credentialsOnly: true })} + </div> </div> </div> <div className="flex justify-between items-center mt-6 pt-6 border-t border-theme-modal-border px-7 pb-6"> diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/ChatModelSelection/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/ChatModelSelection/index.jsx index 7e139829d22fd49518a094c242e616e5ef253851..9c794a15ea1a25b9ca72eb4b3b0db03f635f3334 100644 --- a/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/ChatModelSelection/index.jsx +++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/ChatModelSelection/index.jsx @@ -16,7 +16,7 @@ export default function ChatModelSelection({ if (loading) { return ( <div> - <div className="flex flex-col"> + <div className="flex flex-col mt-6"> <label htmlFor="name" className="block input-label"> {t("chat.model.title")} </label> @@ -40,7 +40,7 @@ export default function ChatModelSelection({ return ( <div> - <div className="flex flex-col"> + <div className="flex flex-col mt-6"> <label htmlFor="name" className="block input-label"> {t("chat.model.title")} </label> diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/WorkspaceLLMItem/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/WorkspaceLLMItem/index.jsx index a8017b2ec5e94da084f82616093ab7265db8b45e..ee123556c073fdf8237a7ee8e34b91fe3a2dfc1f 100644 --- a/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/WorkspaceLLMItem/index.jsx +++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/WorkspaceLLMItem/index.jsx @@ -4,9 +4,10 @@ import { createPortal } from "react-dom"; import ModalWrapper from "@/components/ModalWrapper"; import { useModal } from "@/hooks/useModal"; -import { X } from "@phosphor-icons/react"; +import { X, Gear } from "@phosphor-icons/react"; import System from "@/models/system"; import showToast from "@/utils/toast"; +import { useEffect, useState } from "react"; export default function WorkspaceLLM({ llm, @@ -17,18 +18,31 @@ export default function WorkspaceLLM({ }) { const { isOpen, openModal, closeModal } = useModal(); const { name, value, logo, description } = llm; + const [currentSettings, setCurrentSettings] = useState(settings); + + useEffect(() => { + async function getSettings() { + if (isOpen) { + const _settings = await System.keys(); + setCurrentSettings(_settings ?? {}); + } + } + getSettings(); + }, [isOpen]); function handleProviderSelection() { // Determine if provider needs additional setup because its minimum required keys are // not yet set in settings. - const requiresAdditionalSetup = (llm.requiredConfig || []).some( - (key) => !settings[key] - ); - if (requiresAdditionalSetup) { - openModal(); - return; + if (!checked) { + const requiresAdditionalSetup = (llm.requiredConfig || []).some( + (key) => !currentSettings[key] + ); + if (requiresAdditionalSetup) { + openModal(); + return; + } + onClick(value); } - onClick(value); } return ( @@ -47,16 +61,30 @@ export default function WorkspaceLLM({ readOnly={true} formNoValidate={true} /> - <div className="flex gap-x-4 items-center"> - <img - src={logo} - alt={`${name} logo`} - className="w-10 h-10 rounded-md" - /> - <div className="flex flex-col"> - <div className="text-sm font-semibold text-white">{name}</div> - <div className="mt-1 text-xs text-white/60">{description}</div> + <div className="flex gap-x-4 items-center justify-between"> + <div className="flex gap-x-4 items-center"> + <img + src={logo} + alt={`${name} logo`} + className="w-10 h-10 rounded-md" + /> + <div className="flex flex-col"> + <div className="text-sm font-semibold text-white">{name}</div> + <div className="mt-1 text-xs text-white/60">{description}</div> + </div> </div> + {checked && ( + <button + onClick={(e) => { + e.preventDefault(); + openModal(); + }} + className="p-2 text-white/60 hover:text-white hover:bg-theme-bg-hover rounded-md transition-all duration-300" + title="Edit Settings" + > + <Gear size={20} weight="bold" /> + </button> + )} </div> </div> <SetupProvider @@ -65,6 +93,7 @@ export default function WorkspaceLLM({ provider={value} closeModal={closeModal} postSubmit={onClick} + settings={currentSettings} /> </> ); @@ -76,6 +105,7 @@ function SetupProvider({ provider, closeModal, postSubmit, + settings, }) { if (!isOpen) return null; const LLMOption = availableLLMs.find((llm) => llm.value === provider); @@ -107,7 +137,7 @@ function SetupProvider({ <div className="relative p-6 border-b rounded-t border-theme-modal-border"> <div className="w-full flex gap-x-2 items-center"> <h3 className="text-xl font-semibold text-white overflow-hidden overflow-ellipsis whitespace-nowrap"> - Setup {LLMOption.name} + {LLMOption.name} Settings </h3> </div> <button @@ -120,12 +150,14 @@ function SetupProvider({ </div> <form id="provider-form" onSubmit={handleUpdate}> <div className="px-7 py-6"> - <div className="space-y-6 max-h-[60vh] overflow-y-auto pr-2"> + <div className="space-y-6 max-h-[60vh] overflow-y-auto p-1"> <p className="text-sm text-white/60"> To use {LLMOption.name} as this workspace's LLM you need to set it up first. </p> - <div>{LLMOption.options({ credentialsOnly: true })}</div> + <div> + {LLMOption.options(settings, { credentialsOnly: true })} + </div> </div> </div> <div className="flex justify-between items-center mt-6 pt-6 border-t border-theme-modal-border px-7 pb-6"> @@ -141,7 +173,7 @@ function SetupProvider({ form="provider-form" className="transition-all duration-300 bg-white text-black hover:opacity-60 px-4 py-2 rounded-lg text-sm" > - Save {LLMOption.name} settings + Save settings </button> </div> </form>