mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-06 21:35:52 +08:00
feat(AgentSettings): add model selection to essential settings
- Make model prop optional in ModelAvatar component - Ensure models array always returns an array in useModels hook - Export SelectorProps type for reuse - Add getProviderNameById utility function - Introduce ModelLabel component for displaying model info - Update AgentEssentialSettings to include model selection dropdown
This commit is contained in:
parent
f49d3791b6
commit
f45b744318
@ -5,7 +5,7 @@ import { first } from 'lodash'
|
|||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
model: Model
|
model?: Model
|
||||||
size: number
|
size: number
|
||||||
props?: AvatarProps
|
props?: AvatarProps
|
||||||
className?: string
|
className?: string
|
||||||
|
|||||||
@ -34,7 +34,7 @@ interface MultipleSelectorProps<V> extends BaseSelectorProps<V> {
|
|||||||
onChange: (value: V[]) => void
|
onChange: (value: V[]) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
type SelectorProps<V> = SingleSelectorProps<V> | MultipleSelectorProps<V>
|
export type SelectorProps<V> = SingleSelectorProps<V> | MultipleSelectorProps<V>
|
||||||
|
|
||||||
const Selector = <V extends string | number>({
|
const Selector = <V extends string | number>({
|
||||||
options,
|
options,
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export const useModels = (filter?: ApiModelsFilter) => {
|
|||||||
}, [client, filter])
|
}, [client, filter])
|
||||||
const { data, error, isLoading } = useSWR(path, fetcher)
|
const { data, error, isLoading } = useSWR(path, fetcher)
|
||||||
return {
|
return {
|
||||||
models: data?.data,
|
models: data?.data ?? [],
|
||||||
error,
|
error,
|
||||||
isLoading
|
isLoading
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import { HStack } from '@renderer/components/Layout'
|
import { useModels } from '@renderer/hooks/agents/useModels'
|
||||||
import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent'
|
import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent'
|
||||||
import { AgentEntity, UpdateAgentForm } from '@renderer/types'
|
import { AgentEntity, UpdateAgentForm } from '@renderer/types'
|
||||||
import { Input } from 'antd'
|
import { Input, Select } from 'antd'
|
||||||
import { FC, useState } from 'react'
|
import { DefaultOptionType } from 'antd/es/select'
|
||||||
|
import { FC, useMemo, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { AgentLabel, SettingsContainer, SettingsItem, SettingsTitle } from './shared'
|
import { AgentLabel, ModelLabel, SettingsContainer, SettingsItem, SettingsTitle } from './shared'
|
||||||
|
|
||||||
interface AgentEssentialSettingsProps {
|
interface AgentEssentialSettingsProps {
|
||||||
agent: AgentEntity | undefined | null
|
agent: AgentEntity | undefined | null
|
||||||
@ -15,6 +16,7 @@ interface AgentEssentialSettingsProps {
|
|||||||
const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update }) => {
|
const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [name, setName] = useState<string>((agent?.name ?? '').trim())
|
const [name, setName] = useState<string>((agent?.name ?? '').trim())
|
||||||
|
const { models } = useModels({ providerType: 'anthropic' })
|
||||||
|
|
||||||
const onUpdate = () => {
|
const onUpdate = () => {
|
||||||
if (!agent) return
|
if (!agent) return
|
||||||
@ -22,6 +24,13 @@ const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update
|
|||||||
update(_agent)
|
update(_agent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const modelOptions = useMemo(() => {
|
||||||
|
return models.map((model) => ({
|
||||||
|
value: model.id,
|
||||||
|
label: <ModelLabel model={model} />
|
||||||
|
})) satisfies DefaultOptionType[]
|
||||||
|
}, [models])
|
||||||
|
|
||||||
if (!agent) return null
|
if (!agent) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -30,21 +39,27 @@ const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update
|
|||||||
<SettingsTitle>{t('agent.type.label')}</SettingsTitle>
|
<SettingsTitle>{t('agent.type.label')}</SettingsTitle>
|
||||||
<AgentLabel type={agent.type} />
|
<AgentLabel type={agent.type} />
|
||||||
</SettingsItem>
|
</SettingsItem>
|
||||||
<SettingsItem>
|
<SettingsItem inline>
|
||||||
<SettingsTitle>{t('common.name')}</SettingsTitle>
|
<SettingsTitle>{t('common.name')}</SettingsTitle>
|
||||||
<HStack gap={8} alignItems="center">
|
<Input
|
||||||
<Input
|
placeholder={t('common.agent_one') + t('common.name')}
|
||||||
placeholder={t('common.assistant') + t('common.name')}
|
value={name}
|
||||||
value={name}
|
onChange={(e) => setName(e.target.value)}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onBlur={() => {
|
||||||
onBlur={() => {
|
if (name !== agent.name) {
|
||||||
if (name !== agent.name) {
|
onUpdate()
|
||||||
onUpdate()
|
}
|
||||||
}
|
}}
|
||||||
}}
|
className="max-w-80 flex-1"
|
||||||
style={{ flex: 1 }}
|
/>
|
||||||
/>
|
</SettingsItem>
|
||||||
</HStack>
|
<SettingsItem inline className="gap-8">
|
||||||
|
<SettingsTitle>{t('common.model')}</SettingsTitle>
|
||||||
|
<Select
|
||||||
|
options={modelOptions}
|
||||||
|
className="max-w-80 flex-1"
|
||||||
|
placeholder={t('common.placeholders.select.model')}
|
||||||
|
/>
|
||||||
</SettingsItem>
|
</SettingsItem>
|
||||||
</SettingsContainer>
|
</SettingsContainer>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { Avatar, AvatarProps, cn } from '@heroui/react'
|
import { Avatar, AvatarProps, cn } from '@heroui/react'
|
||||||
import { getAgentAvatar } from '@renderer/config/agent'
|
import { getAgentAvatar } from '@renderer/config/agent'
|
||||||
|
import { getModelLogo } from '@renderer/config/models'
|
||||||
import { getAgentTypeLabel } from '@renderer/i18n/label'
|
import { getAgentTypeLabel } from '@renderer/i18n/label'
|
||||||
import { AgentType } from '@renderer/types'
|
import { AgentType, ApiModel } from '@renderer/types'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { SettingDivider } from '..'
|
import { SettingDivider } from '..'
|
||||||
@ -48,7 +49,7 @@ export const SettingsItem: React.FC<SettingsItemProps> = ({
|
|||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
{...props}
|
{...props}
|
||||||
className={cn('flex flex-col', inline ? 'flex-row items-center justify-between gap-2' : undefined, className)}>
|
className={cn('flex flex-col', inline ? 'flex-row items-center justify-between gap-4' : undefined, className)}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
{divider && <SettingDivider />}
|
{divider && <SettingDivider />}
|
||||||
@ -63,3 +64,18 @@ export const SettingsContainer: React.FC<React.ComponentPropsWithRef<'div'>> = (
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ModelLabelProps extends Omit<React.ComponentPropsWithRef<'div'>, 'children'> {
|
||||||
|
model: ApiModel
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ModelLabel: React.FC<ModelLabelProps> = ({ model, className, ...props }) => {
|
||||||
|
return (
|
||||||
|
<div className={cn('flex items-center gap-1', className)} {...props}>
|
||||||
|
<Avatar src={getModelLogo(model.id)} className="h-4 w-4" />
|
||||||
|
<span>
|
||||||
|
{model.name} | {model.provider_name}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@ -12,6 +12,15 @@ export function getProviderName(model?: Model) {
|
|||||||
return getFancyProviderName(provider)
|
return getFancyProviderName(provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getProviderNameById(pid: string) {
|
||||||
|
const provider = store.getState().llm.providers.find((p) => p.id === pid)
|
||||||
|
if (provider) {
|
||||||
|
return getFancyProviderName(provider)
|
||||||
|
} else {
|
||||||
|
return 'Unknown Provider'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getProviderByModel(model?: Model) {
|
export function getProviderByModel(model?: Model) {
|
||||||
const id = model?.provider
|
const id = model?.provider
|
||||||
const provider = store.getState().llm.providers.find((p) => p.id === id)
|
const provider = store.getState().llm.providers.find((p) => p.id === id)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user