From 710592b0536560be06234f7abb5e20598312c4f5 Mon Sep 17 00:00:00 2001 From: icarus Date: Mon, 22 Sep 2025 00:04:15 +0800 Subject: [PATCH] refactor(agents): rename useModels to useApiModels and extract model label component Extract ModelLabel component into standalone ApiModelLabel and rename useModels hook to useApiModels for better clarity. Update all references to use the new names. This improves code organization and maintainability. --- src/renderer/src/components/ApiModelLabel.tsx | 19 +++++++++++++++++++ .../components/Popups/agent/AgentModal.tsx | 4 ++-- .../components/Popups/agent/SessionModal.tsx | 4 ++-- src/renderer/src/hooks/agents/useModel.ts | 10 ++++++++++ src/renderer/src/hooks/agents/useModels.ts | 2 +- src/renderer/src/pages/home/ChatNavbar.tsx | 14 ++++++++++++-- .../AgentSettings/AgentEssentialSettings.tsx | 9 +++++---- .../pages/settings/AgentSettings/shared.tsx | 18 +----------------- 8 files changed, 52 insertions(+), 28 deletions(-) create mode 100644 src/renderer/src/components/ApiModelLabel.tsx create mode 100644 src/renderer/src/hooks/agents/useModel.ts diff --git a/src/renderer/src/components/ApiModelLabel.tsx b/src/renderer/src/components/ApiModelLabel.tsx new file mode 100644 index 0000000000..e9c78deb48 --- /dev/null +++ b/src/renderer/src/components/ApiModelLabel.tsx @@ -0,0 +1,19 @@ +import { Avatar, cn } from '@heroui/react' +import { getModelLogo } from '@renderer/config/models' +import { ApiModel } from '@renderer/types' +import React from 'react' + +export interface ModelLabelProps extends Omit, 'children'> { + model?: ApiModel +} + +export const ApiModelLabel: React.FC = ({ model, className, ...props }) => { + return ( +
+ + + {model?.name} | {model?.provider_name} + +
+ ) +} diff --git a/src/renderer/src/components/Popups/agent/AgentModal.tsx b/src/renderer/src/components/Popups/agent/AgentModal.tsx index ef5ac31785..72945681da 100644 --- a/src/renderer/src/components/Popups/agent/AgentModal.tsx +++ b/src/renderer/src/components/Popups/agent/AgentModal.tsx @@ -18,7 +18,7 @@ import { loggerService } from '@logger' import ClaudeIcon from '@renderer/assets/images/models/claude.png' import { getModelLogo } from '@renderer/config/models' import { useAgents } from '@renderer/hooks/agents/useAgents' -import { useModels } from '@renderer/hooks/agents/useModels' +import { useApiModels } from '@renderer/hooks/agents/useModels' import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent' import { AddAgentForm, AgentEntity, AgentType, BaseAgentForm, isAgentType, UpdateAgentForm } from '@renderer/types' import { ChangeEvent, FormEvent, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react' @@ -82,7 +82,7 @@ export const AgentModal: React.FC = ({ agent, trigger, isOpen: _isOpen, o const { addAgent } = useAgents() const updateAgent = useUpdateAgent() // hard-coded. We only support anthropic for now. - const { models } = useModels({ providerType: 'anthropic' }) + const { models } = useApiModels({ providerType: 'anthropic' }) const isEditing = (agent?: AgentEntity) => agent !== undefined const [form, setForm] = useState(() => buildAgentForm(agent)) diff --git a/src/renderer/src/components/Popups/agent/SessionModal.tsx b/src/renderer/src/components/Popups/agent/SessionModal.tsx index 1735c73d55..6e64e4a1aa 100644 --- a/src/renderer/src/components/Popups/agent/SessionModal.tsx +++ b/src/renderer/src/components/Popups/agent/SessionModal.tsx @@ -18,7 +18,7 @@ import { import { loggerService } from '@logger' import { getModelLogo } from '@renderer/config/models' import { useAgent } from '@renderer/hooks/agents/useAgent' -import { useModels } from '@renderer/hooks/agents/useModels' +import { useApiModels } from '@renderer/hooks/agents/useModels' import { useSessions } from '@renderer/hooks/agents/useSessions' import { AgentEntity, AgentSessionEntity, BaseSessionForm, CreateSessionForm, UpdateSessionForm } from '@renderer/types' import { ChangeEvent, FormEvent, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react' @@ -80,7 +80,7 @@ export const SessionModal: React.FC = ({ agentId, session, trigger, isOpe // const { setTimeoutTimer } = useTimer() const { createSession, updateSession } = useSessions(agentId) // Only support claude code for now - const { models } = useModels({ providerType: 'anthropic' }) + const { models } = useApiModels({ providerType: 'anthropic' }) const { agent } = useAgent(agentId) const isEditing = (session?: AgentSessionEntity) => session !== undefined diff --git a/src/renderer/src/hooks/agents/useModel.ts b/src/renderer/src/hooks/agents/useModel.ts new file mode 100644 index 0000000000..dd7f9cc1d6 --- /dev/null +++ b/src/renderer/src/hooks/agents/useModel.ts @@ -0,0 +1,10 @@ +import { useApiModels } from './useModels' + +export type UseModelProps = { + id: string +} + +export const useApiModel = (id?: string) => { + const { models } = useApiModels() + return models.find((model) => model.id === id) +} diff --git a/src/renderer/src/hooks/agents/useModels.ts b/src/renderer/src/hooks/agents/useModels.ts index 442f42d4c4..f05cb777b9 100644 --- a/src/renderer/src/hooks/agents/useModels.ts +++ b/src/renderer/src/hooks/agents/useModels.ts @@ -4,7 +4,7 @@ import useSWR from 'swr' import { useAgentClient } from './useAgentClient' -export const useModels = (filter?: ApiModelsFilter) => { +export const useApiModels = (filter?: ApiModelsFilter) => { const client = useAgentClient() const path = client.getModelsPath(filter) const fetcher = useCallback(() => { diff --git a/src/renderer/src/pages/home/ChatNavbar.tsx b/src/renderer/src/pages/home/ChatNavbar.tsx index 63ed16f989..f437f0bb49 100644 --- a/src/renderer/src/pages/home/ChatNavbar.tsx +++ b/src/renderer/src/pages/home/ChatNavbar.tsx @@ -1,8 +1,11 @@ +import { ApiModelLabel } from '@renderer/components/ApiModelLabel' import { NavbarHeader } from '@renderer/components/app/Navbar' import { HStack } from '@renderer/components/Layout' import SearchPopup from '@renderer/components/Popups/SearchPopup' +import { useAgent } from '@renderer/hooks/agents/useAgent' +import { useApiModel } from '@renderer/hooks/agents/useModel' import { useAssistant } from '@renderer/hooks/useAssistant' -import { modelGenerating } from '@renderer/hooks/useRuntime' +import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime' import { useSettings } from '@renderer/hooks/useSettings' import { useShortcut } from '@renderer/hooks/useShortcuts' import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore' @@ -35,6 +38,10 @@ const HeaderNavbar: FC = ({ activeAssistant, setActiveAssistant, activeTo const { topicPosition, narrowMode } = useSettings() const { showTopics, toggleShowTopics } = useShowTopics() const dispatch = useAppDispatch() + const { chat } = useRuntime() + const { activeTopicOrSession, activeAgentId } = chat + const { agent } = useAgent(activeAgentId) + const agentModel = useApiModel(agent?.model) useShortcut('toggle_show_assistants', toggleShowAssistants) @@ -94,7 +101,10 @@ const HeaderNavbar: FC = ({ activeAssistant, setActiveAssistant, activeTo )} - + {activeTopicOrSession === 'topic' && } + {/* TODO: Show a select model button for agent. */} + {/* FIXME: models endpoint doesn't return all models, so cannot found. */} + {activeTopicOrSession === 'session' && } diff --git a/src/renderer/src/pages/settings/AgentSettings/AgentEssentialSettings.tsx b/src/renderer/src/pages/settings/AgentSettings/AgentEssentialSettings.tsx index c3ea9f8b24..b278da6dca 100644 --- a/src/renderer/src/pages/settings/AgentSettings/AgentEssentialSettings.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/AgentEssentialSettings.tsx @@ -1,4 +1,5 @@ -import { useModels } from '@renderer/hooks/agents/useModels' +import { ApiModelLabel } from '@renderer/components/ApiModelLabel' +import { useApiModels } from '@renderer/hooks/agents/useModels' import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent' import { AgentEntity, UpdateAgentForm } from '@renderer/types' import { Input, Select } from 'antd' @@ -6,7 +7,7 @@ import { DefaultOptionType } from 'antd/es/select' import { FC, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' -import { AgentLabel, ModelLabel, SettingsContainer, SettingsItem, SettingsTitle } from './shared' +import { AgentLabel, SettingsContainer, SettingsItem, SettingsTitle } from './shared' interface AgentEssentialSettingsProps { agent: AgentEntity | undefined | null @@ -16,7 +17,7 @@ interface AgentEssentialSettingsProps { const AgentEssentialSettings: FC = ({ agent, update }) => { const { t } = useTranslation() const [name, setName] = useState((agent?.name ?? '').trim()) - const { models } = useModels({ providerType: 'anthropic' }) + const { models } = useApiModels({ providerType: 'anthropic' }) const agentModel = models.find((model) => model.id === agent?.model) const [model, setModel] = useState(agentModel?.id) @@ -29,7 +30,7 @@ const AgentEssentialSettings: FC = ({ agent, update const modelOptions = useMemo(() => { return models.map((model) => ({ value: model.id, - label: + label: })) satisfies DefaultOptionType[] }, [models]) diff --git a/src/renderer/src/pages/settings/AgentSettings/shared.tsx b/src/renderer/src/pages/settings/AgentSettings/shared.tsx index 4e6d36b3af..1d2c9c5811 100644 --- a/src/renderer/src/pages/settings/AgentSettings/shared.tsx +++ b/src/renderer/src/pages/settings/AgentSettings/shared.tsx @@ -1,8 +1,7 @@ import { Avatar, AvatarProps, cn } from '@heroui/react' import { getAgentAvatar } from '@renderer/config/agent' -import { getModelLogo } from '@renderer/config/models' import { getAgentTypeLabel } from '@renderer/i18n/label' -import { AgentType, ApiModel } from '@renderer/types' +import { AgentType } from '@renderer/types' import React from 'react' import { SettingDivider } from '..' @@ -64,18 +63,3 @@ export const SettingsContainer: React.FC> = ( ) } - -export interface ModelLabelProps extends Omit, 'children'> { - model: ApiModel -} - -export const ModelLabel: React.FC = ({ model, className, ...props }) => { - return ( -
- - - {model.name} | {model.provider_name} - -
- ) -}