diff --git a/src/renderer/src/components/Popups/agent/AgentModal.tsx b/src/renderer/src/components/Popups/agent/AgentModal.tsx index 609593493..d49dbb812 100644 --- a/src/renderer/src/components/Popups/agent/AgentModal.tsx +++ b/src/renderer/src/components/Popups/agent/AgentModal.tsx @@ -67,6 +67,7 @@ type Props = { agent?: AgentWithTools isOpen: boolean onClose: () => void + afterSubmit?: (a: AgentEntity) => void } /** @@ -78,7 +79,7 @@ type Props = { * @param onClose - Optional callback when modal closes. From useDisclosure. * @returns Modal component for agent creation/editing */ -export const AgentModal: React.FC = ({ agent, isOpen: _isOpen, onClose: _onClose }) => { +export const AgentModal: React.FC = ({ agent, isOpen: _isOpen, onClose: _onClose, afterSubmit }) => { const { isOpen, onClose } = useDisclosure({ isOpen: _isOpen, onClose: _onClose }) const { t } = useTranslation() const loadingRef = useRef(false) @@ -301,8 +302,13 @@ export const AgentModal: React.FC = ({ agent, isOpen: _isOpen, onClose: _ configuration: form.configuration ? { ...form.configuration } : undefined } satisfies UpdateAgentForm - updateAgent(updatePayload) - logger.debug('Updated agent', updatePayload) + const result = await updateAgent(updatePayload) + if (result) { + logger.debug('Updated agent', result) + afterSubmit?.(result) + } else { + logger.error('Update failed.') + } } else { const newAgent = { type: form.type, @@ -315,12 +321,13 @@ export const AgentModal: React.FC = ({ agent, isOpen: _isOpen, onClose: _ configuration: form.configuration ? { ...form.configuration } : undefined } satisfies AddAgentForm const result = await addAgent(newAgent) + if (!result.success) { loadingRef.current = false throw result.error } + afterSubmit?.(result.data) } - loadingRef.current = false // setTimeoutTimer('onCreateAgent', () => EventEmitter.emit(EVENT_NAMES.SHOW_ASSISTANTS), 0) @@ -329,16 +336,17 @@ export const AgentModal: React.FC = ({ agent, isOpen: _isOpen, onClose: _ [ form.type, form.model, + form.accessible_paths, form.name, form.description, form.instructions, - form.accessible_paths, form.allowed_tools, form.configuration, agent, onClose, t, updateAgent, + afterSubmit, addAgent ] ) diff --git a/src/renderer/src/hooks/agents/types.ts b/src/renderer/src/hooks/agents/types.ts deleted file mode 100644 index 9cf5769f5..000000000 --- a/src/renderer/src/hooks/agents/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type UpdateAgentBaseOptions = { - /** Whether to show success toast after updating. Defaults to true. */ - showSuccessToast?: boolean -} diff --git a/src/renderer/src/hooks/agents/useUpdateAgent.ts b/src/renderer/src/hooks/agents/useUpdateAgent.ts index db3825b9b..76d3fbd9e 100644 --- a/src/renderer/src/hooks/agents/useUpdateAgent.ts +++ b/src/renderer/src/hooks/agents/useUpdateAgent.ts @@ -1,10 +1,10 @@ -import { ListAgentsResponse, UpdateAgentForm } from '@renderer/types' +import { AgentEntity, ListAgentsResponse, UpdateAgentForm } from '@renderer/types' +import { UpdateAgentBaseOptions, UpdateAgentFunction } from '@renderer/types/agent' import { formatErrorMessageWithPrefix } from '@renderer/utils/error' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' import { mutate } from 'swr' -import { UpdateAgentBaseOptions } from './types' import { useAgentClient } from './useAgentClient' export const useUpdateAgent = () => { @@ -12,8 +12,8 @@ export const useUpdateAgent = () => { const client = useAgentClient() const listKey = client.agentPaths.base - const updateAgent = useCallback( - async (form: UpdateAgentForm, options?: UpdateAgentBaseOptions) => { + const updateAgent: UpdateAgentFunction = useCallback( + async (form: UpdateAgentForm, options?: UpdateAgentBaseOptions): Promise => { try { const itemKey = client.agentPaths.withId(form.id) // may change to optimistic update @@ -23,8 +23,10 @@ export const useUpdateAgent = () => { if (options?.showSuccessToast ?? true) { window.toast.success(t('common.update_success')) } + return result } catch (error) { window.toast.error(formatErrorMessageWithPrefix(error, t('agent.update.error.failed'))) + return undefined } }, [client, listKey, t] diff --git a/src/renderer/src/hooks/agents/useUpdateSession.ts b/src/renderer/src/hooks/agents/useUpdateSession.ts index cf52a6463..44a5839d7 100644 --- a/src/renderer/src/hooks/agents/useUpdateSession.ts +++ b/src/renderer/src/hooks/agents/useUpdateSession.ts @@ -1,18 +1,18 @@ -import { ListAgentSessionsResponse, UpdateSessionForm } from '@renderer/types' +import { AgentSessionEntity, ListAgentSessionsResponse, UpdateSessionForm } from '@renderer/types' +import { UpdateAgentBaseOptions, UpdateAgentSessionFunction } from '@renderer/types/agent' import { getErrorMessage } from '@renderer/utils/error' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' import { mutate } from 'swr' -import { UpdateAgentBaseOptions } from './types' import { useAgentClient } from './useAgentClient' export const useUpdateSession = (agentId: string | null) => { const { t } = useTranslation() const client = useAgentClient() - const updateSession = useCallback( - async (form: UpdateSessionForm, options?: UpdateAgentBaseOptions) => { + const updateSession: UpdateAgentSessionFunction = useCallback( + async (form: UpdateSessionForm, options?: UpdateAgentBaseOptions): Promise => { if (!agentId) return const paths = client.getSessionPaths(agentId) const listKey = paths.base @@ -29,8 +29,10 @@ export const useUpdateSession = (agentId: string | null) => { if (options?.showSuccessToast ?? true) { window.toast.success(t('common.update_success')) } + return result } catch (error) { window.toast.error({ title: t('agent.session.update.error.failed'), description: getErrorMessage(error) }) + return undefined } }, [agentId, client, t] diff --git a/src/renderer/src/hooks/useTopic.ts b/src/renderer/src/hooks/useTopic.ts index 990cb12db..b8a3dc977 100644 --- a/src/renderer/src/hooks/useTopic.ts +++ b/src/renderer/src/hooks/useTopic.ts @@ -10,13 +10,13 @@ import { loadTopicMessagesThunk } from '@renderer/store/thunk/messageThunk' import { Assistant, Topic } from '@renderer/types' import { findMainTextBlocks } from '@renderer/utils/messageUtils/find' import { find, isEmpty } from 'lodash' -import { useEffect, useState } from 'react' +import { type Dispatch, type SetStateAction, useEffect, useState } from 'react' import { useAssistant } from './useAssistant' import { getStoreSetting } from './useSettings' let _activeTopic: Topic -let _setActiveTopic: (topic: Topic) => void +let _setActiveTopic: Dispatch> // const logger = loggerService.withContext('useTopic') diff --git a/src/renderer/src/pages/home/HomePage.tsx b/src/renderer/src/pages/home/HomePage.tsx index d387af12b..3825630ba 100644 --- a/src/renderer/src/pages/home/HomePage.tsx +++ b/src/renderer/src/pages/home/HomePage.tsx @@ -4,7 +4,6 @@ import { useAssistants } from '@renderer/hooks/useAssistant' import { useRuntime } from '@renderer/hooks/useRuntime' import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings' import { useActiveTopic } from '@renderer/hooks/useTopic' -import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import NavigationService from '@renderer/services/NavigationService' import { newMessagesActions } from '@renderer/store/newMessage' import { setActiveAgentId, setActiveTopicOrSessionAction } from '@renderer/store/runtime' @@ -33,8 +32,10 @@ const HomePage: FC = () => { const location = useLocation() const state = location.state - const [activeAssistant, _setActiveAssistant] = useState(state?.assistant || _activeAssistant || assistants[0]) - const { activeTopic, setActiveTopic: _setActiveTopic } = useActiveTopic(activeAssistant?.id, state?.topic) + const [activeAssistant, _setActiveAssistant] = useState( + state?.assistant || _activeAssistant || assistants[0] + ) + const { activeTopic, setActiveTopic: _setActiveTopic } = useActiveTopic(activeAssistant?.id ?? '', state?.topic) const { showAssistants, showTopics, topicPosition } = useSettings() const dispatch = useDispatch() const { chat } = useRuntime() @@ -43,16 +44,20 @@ const HomePage: FC = () => { _activeAssistant = activeAssistant const setActiveAssistant = useCallback( + // TODO: allow to set it as null. (newAssistant: Assistant) => { - if (newAssistant.id === activeAssistant.id) return + if (newAssistant.id === activeAssistant?.id) return startTransition(() => { _setActiveAssistant(newAssistant) + if (newAssistant.id !== 'fake') { + dispatch(setActiveAgentId(null)) + } // 同步更新 active topic,避免不必要的重新渲染 const newTopic = newAssistant.topics[0] _setActiveTopic((prev) => (newTopic?.id === prev.id ? prev : newTopic)) }) }, - [_setActiveTopic, activeAssistant] + [_setActiveTopic, activeAssistant?.id, dispatch] ) const setActiveTopic = useCallback( @@ -76,19 +81,6 @@ const HomePage: FC = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [state]) - useEffect(() => { - const unsubscribe = EventEmitter.on(EVENT_NAMES.SWITCH_ASSISTANT, (assistantId: string) => { - const newAssistant = assistants.find((a) => a.id === assistantId) - if (newAssistant) { - setActiveAssistant(newAssistant) - } - }) - - return () => { - unsubscribe() - } - }, [assistants, setActiveAssistant]) - useEffect(() => { const canMinimize = topicPosition == 'left' ? !showAssistants : !showAssistants && !showTopics window.api.window.setMinimumSize(canMinimize ? SECOND_MIN_WINDOW_WIDTH : MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) @@ -98,29 +90,6 @@ const HomePage: FC = () => { } }, [showAssistants, showTopics, topicPosition]) - useEffect(() => { - if (activeTopicOrSession === 'session') { - setActiveAssistant({ - id: 'fake', - name: '', - prompt: '', - topics: [ - { - id: 'fake', - assistantId: 'fake', - name: 'fake', - createdAt: '', - updatedAt: '', - messages: [] - } as unknown as Topic - ], - type: 'chat' - }) - } else if (activeTopicOrSession === 'topic') { - dispatch(setActiveAgentId(null)) - } - }, [activeTopicOrSession, dispatch, setActiveAssistant]) - return ( {isLeftNavbar && ( diff --git a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx index 8fc439b7b..2cb6aabfa 100644 --- a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx @@ -9,7 +9,7 @@ import { useAssistantsTabSortType } from '@renderer/hooks/useStore' import { useTags } from '@renderer/hooks/useTags' import { useAppDispatch } from '@renderer/store' import { addIknowAction } from '@renderer/store/runtime' -import { Assistant, AssistantsSortType } from '@renderer/types' +import { Assistant, AssistantsSortType, Topic } from '@renderer/types' import { getErrorMessage } from '@renderer/utils' import { FC, useCallback, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -99,6 +99,30 @@ const AssistantsTab: FC = (props) => { [setAssistantsTabSortType] ) + const handleAgentPress = useCallback( + (agentId: string) => { + setActiveAgentId(agentId) + // TODO: should allow it to be null + setActiveAssistant({ + id: 'fake', + name: '', + prompt: '', + topics: [ + { + id: 'fake', + assistantId: 'fake', + name: 'fake', + createdAt: '', + updatedAt: '', + messages: [] + } as unknown as Topic + ], + type: 'chat' + }) + }, + [setActiveAgentId, setActiveAssistant] + ) + return ( {!apiServerConfig.enabled && !apiServerRunning && !iknow[ALERT_KEY] && ( @@ -126,7 +150,11 @@ const AssistantsTab: FC = (props) => { /> )} - + {assistantsTabSortType === 'tags' ? ( = (props) => { onAssistantSwitch={setActiveAssistant} onAssistantDelete={onDeleteAssistant} onAgentDelete={deleteAgent} - onAgentPress={setActiveAgentId} + onAgentPress={handleAgentPress} addPreset={addAssistantPreset} copyAssistant={copyAssistant} onCreateDefaultAssistant={onCreateDefaultAssistant} diff --git a/src/renderer/src/pages/home/Tabs/components/UnifiedAddButton.tsx b/src/renderer/src/pages/home/Tabs/components/UnifiedAddButton.tsx index d3e64871a..d50add0bd 100644 --- a/src/renderer/src/pages/home/Tabs/components/UnifiedAddButton.tsx +++ b/src/renderer/src/pages/home/Tabs/components/UnifiedAddButton.tsx @@ -1,19 +1,25 @@ import { Button, Popover, PopoverContent, PopoverTrigger, useDisclosure } from '@heroui/react' import { AgentModal } from '@renderer/components/Popups/agent/AgentModal' +import { useAppDispatch } from '@renderer/store' +import { setActiveTopicOrSessionAction } from '@renderer/store/runtime' +import { AgentEntity, Assistant, Topic } from '@renderer/types' import { Bot, MessageSquare } from 'lucide-react' -import { FC, useState } from 'react' +import { FC, useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import AddButton from './AddButton' interface UnifiedAddButtonProps { onCreateAssistant: () => void + setActiveAssistant: (a: Assistant) => void + setActiveAgentId: (id: string) => void } -const UnifiedAddButton: FC = ({ onCreateAssistant }) => { +const UnifiedAddButton: FC = ({ onCreateAssistant, setActiveAssistant, setActiveAgentId }) => { const { t } = useTranslation() const [isPopoverOpen, setIsPopoverOpen] = useState(false) const { isOpen: isAgentModalOpen, onOpen: onAgentModalOpen, onClose: onAgentModalClose } = useDisclosure() + const dispatch = useAppDispatch() const handleAddAssistant = () => { setIsPopoverOpen(false) @@ -25,6 +31,31 @@ const UnifiedAddButton: FC = ({ onCreateAssistant }) => { onAgentModalOpen() } + const afterCreate = useCallback( + (a: AgentEntity) => { + // TODO: should allow it to be null + setActiveAssistant({ + id: 'fake', + name: '', + prompt: '', + topics: [ + { + id: 'fake', + assistantId: 'fake', + name: 'fake', + createdAt: '', + updatedAt: '', + messages: [] + } as unknown as Topic + ], + type: 'chat' + }) + setActiveAgentId(a.id) + dispatch(setActiveTopicOrSessionAction('session')) + }, + [dispatch, setActiveAgentId, setActiveAssistant] + ) + return (
= ({ onCreateAssistant }) => { - +
) } diff --git a/src/renderer/src/pages/home/Tabs/index.tsx b/src/renderer/src/pages/home/Tabs/index.tsx index 775a045d9..4914ae134 100644 --- a/src/renderer/src/pages/home/Tabs/index.tsx +++ b/src/renderer/src/pages/home/Tabs/index.tsx @@ -7,6 +7,8 @@ import { useRuntime } from '@renderer/hooks/useRuntime' import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings' import { useShowTopics } from '@renderer/hooks/useStore' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' +import { useAppDispatch } from '@renderer/store' +import { setActiveAgentId, setActiveTopicOrSessionAction } from '@renderer/store/runtime' import { Assistant, Topic } from '@renderer/types' import { Tab } from '@renderer/types/chat' import { classNames, getErrorMessage, uuid } from '@renderer/utils' @@ -50,6 +52,7 @@ const HomeTabs: FC = ({ const { activeTopicOrSession, activeAgentId } = chat const { session, isLoading: isSessionLoading, error: sessionError } = useActiveSession() const { updateSession } = useUpdateSession(activeAgentId) + const dispatch = useAppDispatch() const isSessionView = activeTopicOrSession === 'session' const isTopicView = activeTopicOrSession === 'topic' @@ -69,13 +72,19 @@ const HomeTabs: FC = ({ const onCreateAssistant = async () => { const assistant = await AddAssistantPopup.show() - assistant && setActiveAssistant(assistant) + if (assistant) { + setActiveAssistant(assistant) + dispatch(setActiveAgentId(null)) + dispatch(setActiveTopicOrSessionAction('topic')) + } } const onCreateDefaultAssistant = () => { const assistant = { ...defaultAssistant, id: uuid() } addAssistant(assistant) setActiveAssistant(assistant) + dispatch(setActiveAgentId(null)) + dispatch(setActiveTopicOrSessionAction('topic')) } useEffect(() => { diff --git a/src/renderer/src/pages/home/components/ChatNavbarContent.tsx b/src/renderer/src/pages/home/components/ChatNavbarContent.tsx index 00b48cf8f..8f0f2b119 100644 --- a/src/renderer/src/pages/home/components/ChatNavbarContent.tsx +++ b/src/renderer/src/pages/home/components/ChatNavbarContent.tsx @@ -62,7 +62,12 @@ const ChatNavbarContent: FC = ({ assistant }) => { )} {activeSession && ( - + { + await handleUpdateModel(model) + }} + /> )} {activeAgent && activeSession && ( diff --git a/src/renderer/src/pages/settings/AgentSettings/AccessibleDirsSetting.tsx b/src/renderer/src/pages/settings/AgentSettings/AccessibleDirsSetting.tsx index ad228d227..fcdaee231 100644 --- a/src/renderer/src/pages/settings/AgentSettings/AccessibleDirsSetting.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/AccessibleDirsSetting.tsx @@ -1,20 +1,20 @@ import { Button, Tooltip } from '@heroui/react' import { loggerService } from '@logger' -import { AgentBaseWithId, UpdateAgentBaseForm } from '@renderer/types' +import { AgentBaseWithId, UpdateAgentBaseForm, UpdateAgentFunctionUnion } from '@renderer/types' import { Plus } from 'lucide-react' -import React, { useCallback } from 'react' +import { useCallback } from 'react' import { useTranslation } from 'react-i18next' import { SettingsItem, SettingsTitle } from './shared' export interface AccessibleDirsSettingProps { base: AgentBaseWithId | undefined | null - update: (form: UpdateAgentBaseForm) => Promise + update: UpdateAgentFunctionUnion } const logger = loggerService.withContext('AccessibleDirsSetting') -export const AccessibleDirsSetting: React.FC = ({ base, update }) => { +export const AccessibleDirsSetting = ({ base, update }: AccessibleDirsSettingProps) => { const { t } = useTranslation() const updateAccessiblePaths = useCallback( diff --git a/src/renderer/src/pages/settings/AgentSettings/AvatarSetting.tsx b/src/renderer/src/pages/settings/AgentSettings/AvatarSetting.tsx index f067e6e0a..af0c92e72 100644 --- a/src/renderer/src/pages/settings/AgentSettings/AvatarSetting.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/AvatarSetting.tsx @@ -1,5 +1,11 @@ import { EmojiAvatarWithPicker } from '@renderer/components/Avatar/EmojiAvatarWithPicker' -import { AgentConfigurationSchema, AgentEntity, isAgentType, UpdateAgentForm } from '@renderer/types' +import { + AgentConfigurationSchema, + AgentEntity, + isAgentType, + UpdateAgentForm, + UpdateAgentFunction +} from '@renderer/types' import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -7,7 +13,7 @@ import { SettingsItem, SettingsTitle } from './shared' export interface AvatarSettingsProps { agent: AgentEntity - update: (form: UpdateAgentForm) => Promise + update: UpdateAgentFunction } // const logger = loggerService.withContext('AvatarSetting') diff --git a/src/renderer/src/pages/settings/AgentSettings/DescriptionSetting.tsx b/src/renderer/src/pages/settings/AgentSettings/DescriptionSetting.tsx index 5400e8e43..4adeff9d0 100644 --- a/src/renderer/src/pages/settings/AgentSettings/DescriptionSetting.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/DescriptionSetting.tsx @@ -1,16 +1,16 @@ import { Textarea } from '@heroui/react' -import { AgentBaseWithId, UpdateAgentBaseForm } from '@renderer/types' -import React, { useCallback, useState } from 'react' +import { AgentBaseWithId, UpdateAgentBaseForm, UpdateAgentFunctionUnion } from '@renderer/types' +import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import { SettingsItem, SettingsTitle } from './shared' export interface DescriptionSettingProps { base: AgentBaseWithId | undefined | null - update: (form: UpdateAgentBaseForm) => Promise + update: UpdateAgentFunctionUnion } -export const DescriptionSetting: React.FC = ({ base, update }) => { +export const DescriptionSetting = ({ base, update }: DescriptionSettingProps) => { const { t } = useTranslation() const [description, setDescription] = useState(base?.description?.trim()) diff --git a/src/renderer/src/pages/settings/AgentSettings/EssentialSettings.tsx b/src/renderer/src/pages/settings/AgentSettings/EssentialSettings.tsx index c374893fc..c21dca768 100644 --- a/src/renderer/src/pages/settings/AgentSettings/EssentialSettings.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/EssentialSettings.tsx @@ -46,7 +46,9 @@ const EssentialSettings: FC = ({ agentBase, update, show )} - {isAgent && } + {isAgent && ( + ['updateAgent']} /> + )} {showModelSetting && } diff --git a/src/renderer/src/pages/settings/AgentSettings/ModelSetting.tsx b/src/renderer/src/pages/settings/AgentSettings/ModelSetting.tsx index aed615b86..6662b22e7 100644 --- a/src/renderer/src/pages/settings/AgentSettings/ModelSetting.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/ModelSetting.tsx @@ -1,16 +1,16 @@ import SelectAgentBaseModelButton from '@renderer/pages/home/components/SelectAgentBaseModelButton' -import { AgentBaseWithId, ApiModel, UpdateAgentBaseForm } from '@renderer/types' +import { AgentBaseWithId, ApiModel, UpdateAgentFunctionUnion } from '@renderer/types' import { useTranslation } from 'react-i18next' import { SettingsItem, SettingsTitle } from './shared' export interface ModelSettingProps { base: AgentBaseWithId | undefined | null - update: (form: UpdateAgentBaseForm) => Promise + update: UpdateAgentFunctionUnion isDisabled?: boolean } -export const ModelSetting: React.FC = ({ base, update, isDisabled }) => { +export const ModelSetting = ({ base, update, isDisabled }: ModelSettingProps) => { const { t } = useTranslation() const updateModel = async (model: ApiModel) => { @@ -23,7 +23,13 @@ export const ModelSetting: React.FC = ({ base, update, isDisa return ( {t('common.model')} - + { + await updateModel(model) + }} + isDisabled={isDisabled} + /> ) } diff --git a/src/renderer/src/pages/settings/AgentSettings/NameSetting.tsx b/src/renderer/src/pages/settings/AgentSettings/NameSetting.tsx index 26346bc9a..0cdc3e28b 100644 --- a/src/renderer/src/pages/settings/AgentSettings/NameSetting.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/NameSetting.tsx @@ -1,5 +1,5 @@ import { Input } from '@heroui/react' -import { AgentBaseWithId, UpdateAgentBaseForm } from '@renderer/types' +import { AgentBaseWithId, UpdateAgentBaseForm, UpdateAgentFunctionUnion } from '@renderer/types' import { useState } from 'react' import { useTranslation } from 'react-i18next' @@ -7,10 +7,10 @@ import { SettingsItem, SettingsTitle } from './shared' export interface NameSettingsProps { base: AgentBaseWithId | undefined | null - update: (form: UpdateAgentBaseForm) => Promise + update: UpdateAgentFunctionUnion } -export const NameSetting: React.FC = ({ base, update }) => { +export const NameSetting = ({ base, update }: NameSettingsProps) => { const { t } = useTranslation() const [name, setName] = useState(base?.name?.trim()) const updateName = async (name: UpdateAgentBaseForm['name']) => { diff --git a/src/renderer/src/pages/settings/AgentSettings/PluginSettings.tsx b/src/renderer/src/pages/settings/AgentSettings/PluginSettings.tsx index 3b54c15e1..aa7bb93ea 100644 --- a/src/renderer/src/pages/settings/AgentSettings/PluginSettings.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/PluginSettings.tsx @@ -1,6 +1,6 @@ import { Card, CardBody, Tab, Tabs } from '@heroui/react' import { useAvailablePlugins, useInstalledPlugins, usePluginActions } from '@renderer/hooks/usePlugins' -import { GetAgentResponse, GetAgentSessionResponse, UpdateAgentBaseForm } from '@renderer/types/agent' +import { GetAgentResponse, GetAgentSessionResponse, UpdateAgentFunctionUnion } from '@renderer/types/agent' import { FC, useCallback } from 'react' import { useTranslation } from 'react-i18next' @@ -10,7 +10,7 @@ import { SettingsContainer } from './shared' interface PluginSettingsProps { agentBase: GetAgentResponse | GetAgentSessionResponse - update: (partial: UpdateAgentBaseForm) => Promise + update: UpdateAgentFunctionUnion } const PluginSettings: FC = ({ agentBase }) => { diff --git a/src/renderer/src/pages/settings/AgentSettings/ToolingSettings.tsx b/src/renderer/src/pages/settings/AgentSettings/ToolingSettings.tsx index 45782bf43..f58fae7b6 100644 --- a/src/renderer/src/pages/settings/AgentSettings/ToolingSettings.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/ToolingSettings.tsx @@ -10,8 +10,8 @@ import { PermissionMode, Tool, UpdateAgentBaseForm, - UpdateAgentForm, - UpdateSessionForm + UpdateAgentFunction, + UpdateAgentSessionFunction } from '@renderer/types' import { Modal } from 'antd' import { ShieldAlert, ShieldCheck, Wrench } from 'lucide-react' @@ -23,11 +23,11 @@ import { SettingsContainer, SettingsItem, SettingsTitle } from './shared' type AgentToolingSettingsProps = | { agentBase: GetAgentResponse | undefined | null - update: (form: UpdateAgentForm) => Promise | void + update: UpdateAgentFunction } | { agentBase: GetAgentSessionResponse | undefined | null - update: (form: UpdateSessionForm) => Promise | void + update: UpdateAgentSessionFunction } type AgentConfigurationState = AgentConfiguration & Record diff --git a/src/renderer/src/services/EventService.ts b/src/renderer/src/services/EventService.ts index ce5895fc3..badaaccf0 100644 --- a/src/renderer/src/services/EventService.ts +++ b/src/renderer/src/services/EventService.ts @@ -18,7 +18,6 @@ export const EVENT_NAMES = { SHOW_CHAT_SETTINGS: 'SHOW_CHAT_SETTINGS', SHOW_TOPIC_SIDEBAR: 'SHOW_TOPIC_SIDEBAR', SWITCH_TOPIC_SIDEBAR: 'SWITCH_TOPIC_SIDEBAR', - SWITCH_ASSISTANT: 'SWITCH_ASSISTANT', NEW_CONTEXT: 'NEW_CONTEXT', NEW_BRANCH: 'NEW_BRANCH', COPY_TOPIC_IMAGE: 'COPY_TOPIC_IMAGE', diff --git a/src/renderer/src/types/agent.ts b/src/renderer/src/types/agent.ts index 478d8fb7a..cc04dc3f7 100644 --- a/src/renderer/src/types/agent.ts +++ b/src/renderer/src/types/agent.ts @@ -227,6 +227,25 @@ export type SessionForm = CreateSessionForm | UpdateSessionForm export type UpdateAgentBaseForm = Partial & { id: string } +// --------------------- Components & Hooks ---------------------- + +export type UpdateAgentBaseOptions = { + /** Whether to show success toast after updating. Defaults to true. */ + showSuccessToast?: boolean +} + +export type UpdateAgentFunction = ( + form: UpdateAgentForm, + options?: UpdateAgentBaseOptions +) => Promise + +export type UpdateAgentSessionFunction = ( + form: UpdateSessionForm, + options?: UpdateAgentBaseOptions +) => Promise + +export type UpdateAgentFunctionUnion = UpdateAgentFunction | UpdateAgentSessionFunction + // ------------------ API data transfer objects ------------------ export interface CreateAgentRequest extends AgentBase { type: AgentType