diff --git a/packages/twenty-front/src/pages/settings/ai/SettingsAI.tsx b/packages/twenty-front/src/pages/settings/ai/SettingsAI.tsx index 3403ff0003..fd025d016b 100644 --- a/packages/twenty-front/src/pages/settings/ai/SettingsAI.tsx +++ b/packages/twenty-front/src/pages/settings/ai/SettingsAI.tsx @@ -13,15 +13,16 @@ import { getSettingsPath } from 'twenty-shared/utils'; import { t } from '@lingui/core/macro'; import { H2Title, + IconCpu, IconFileText, - IconSettings, + IconSettingsBolt, IconSparkles, IconTool, } from 'twenty-ui/display'; import { Button } from 'twenty-ui/input'; import { Card, Section } from 'twenty-ui/layout'; import { SettingsAIMCP } from './components/SettingsAIMCP'; -import { SettingsAIRouterSettings } from './components/SettingsAIRouterSettings'; +import { SettingsAIModelsTab } from './components/SettingsAIModelsTab'; import { SettingsSkillsTable } from './components/SettingsSkillsTable'; import { SettingsToolsTable } from './components/SettingsToolsTable'; import { SETTINGS_AI_TABS } from './constants/SettingsAiTabs'; @@ -37,6 +38,11 @@ export const SettingsAI = () => { ); const tabs = [ + { + id: SETTINGS_AI_TABS.TABS_IDS.MODELS, + title: t`Models`, + Icon: IconCpu, + }, { id: SETTINGS_AI_TABS.TABS_IDS.SKILLS, title: t`Skills`, @@ -48,15 +54,16 @@ export const SettingsAI = () => { Icon: IconTool, }, { - id: SETTINGS_AI_TABS.TABS_IDS.SETTINGS, - title: t`Settings`, - Icon: IconSettings, + id: SETTINGS_AI_TABS.TABS_IDS.MORE, + title: t`More`, + Icon: IconSettingsBolt, }, ]; + const isModelsTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.MODELS; const isSkillsTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.SKILLS; const isToolsTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.TOOLS; - const isSettingsTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.SETTINGS; + const isMoreTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.MORE; return ( { tabs={tabs} componentInstanceId={SETTINGS_AI_TABS.COMPONENT_INSTANCE_ID} /> + {isModelsTab && } {isSkillsTab && } {isToolsTab && } - {isSettingsTab && ( + {isMoreTab && ( <> -
= new Set([ + DEFAULT_SMART_MODEL, + DEFAULT_FAST_MODEL, +]); + +export const SettingsAIModelsTab = () => { + const { enqueueSuccessSnackBar, enqueueErrorSnackBar } = useSnackBar(); + const [currentWorkspace, setCurrentWorkspace] = useRecoilState( + currentWorkspaceState, + ); + const [updateWorkspace] = useUpdateWorkspaceMutation(); + + const aiModels = useRecoilValueV2(aiModelsState); + + const realModels = aiModels.filter( + (model) => !VIRTUAL_MODEL_IDS.has(model.modelId), + ); + + const currentSmartModel = currentWorkspace?.smartModel; + + const defaultModelOptions = realModels + .filter((model) => !model.deprecated || model.modelId === currentSmartModel) + .map((model) => ({ + value: model.modelId, + label: model.label, + Icon: PROVIDER_CONFIG[model.provider.toUpperCase()]?.Icon, + })); + + const handleDefaultModelChange = async (value: string) => { + if (!currentWorkspace?.id) { + return; + } + + const previousSmartModel = currentWorkspace.smartModel; + + try { + setCurrentWorkspace({ + ...currentWorkspace, + smartModel: value, + }); + + await updateWorkspace({ + variables: { + input: { + smartModel: value, + }, + }, + }); + + enqueueSuccessSnackBar({ + message: t`Default model updated successfully`, + }); + } catch { + setCurrentWorkspace({ + ...currentWorkspace, + smartModel: previousSmartModel, + }); + + enqueueErrorSnackBar({ + message: t`Failed to update default model`, + }); + } + }; + + return ( +
+ + + + + - - - - - - - -
- - {t`Smart Model`} - - - {t`Advanced model for complex planning`} - -
- -